SymbolTable.cs :  » Script » IronRuby » Microsoft » Scripting » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Script » IronRuby 
IronRuby » Microsoft » Scripting » SymbolTable.cs
/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 *
 * ***************************************************************************/

using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Scripting.Utils;
using System;

namespace Microsoft.Scripting{
    /// <summary>
    /// Provides a common table of all SymbolId's in the system.
    /// 
    /// Implementation details:
    /// 
    /// The case insensitive lookups are implemented by using the top 8 bits for
    /// storing information about multiple casings.  These bits are zero for a case insensitive
    /// identifier or specify the casing version for case sensitive lookups.  Because of this
    /// there can be at most 255 variations of casing for each identifier.
    /// 
    /// Two dictionaries are used to track both the case sensitive and case insensitive versions.
    /// 
    /// For the case insensitive versions this is just a normal dictionary keyed from string to
    /// the ID for that specific version.  For the case sensitive version a case insensitive
    /// dictionary is used.  The value in this case is the last case insensitive version that
    /// we handed out.
    /// 
    /// When we hand out an ID we first do a lookup in the normal dictionary.  If this succeeds
    /// then we have the ID and we're done.  If this fails we then need to consult the case
    /// insensitive dictionary.  If the entry exists there then we just need to bump the invariant
    /// version, store that back into the invariant dictionary, and then update the normal dictionary
    /// with the newly produced version.  If teh entry wasn't in the case insensitive dictionary
    /// then we need to create a new entry in both tables.
    /// </summary>
    public static class SymbolTable {
        private static readonly object _lockObj = new object();

        private static readonly Dictionary<string, int> _idDict = new Dictionary<string, int>(InitialTableSize);
        private static readonly Dictionary<string, int> _invariantDict = new Dictionary<string, int>(InitialTableSize, StringComparer.OrdinalIgnoreCase);

        private const int InitialTableSize = 256;
        private static readonly Dictionary<int, string> _fieldDict = CreateFieldDictionary();

        private static int _nextCaseInsensitiveId = 1;

        internal const int CaseVersionMask = unchecked((int)0xFF000000);
        internal const int CaseVersionIncrement = 0x01000000;

        private static Dictionary<int, string>  CreateFieldDictionary() {
            Dictionary<int, string> result = new Dictionary<int, string>(InitialTableSize);
            result[0] = null;   // initialize the null string
            return result;
        }

        public static SymbolId StringToId(string value) {
            ContractUtils.RequiresNotNull(value, "value");

            int res;
            lock (_lockObj) {
                // First, look up the identifier case-sensitively.
                if (!_idDict.TryGetValue(value, out res)) {
                    // OK, didn't find it, so let's look up the case-insensitive
                    // identifier.
                    if (!_invariantDict.TryGetValue(value, out res)) {
                        // This is a whole new identifier.
                        if (_nextCaseInsensitiveId == ~CaseVersionMask) {
                            throw Error.CantAddIdentifier(value);
                        }

                        // allocate new ID at case version 1.
                        res = _nextCaseInsensitiveId++ | CaseVersionIncrement;
                    } else {
                        // OK, this is a new casing of an existing identifier.
                        // Throw if we've exhausted the number of casings.
                        if (unchecked(((uint)res & CaseVersionMask) == CaseVersionMask)) {
                            throw Error.CantAddCasing(value);
                        }

                        // bump the case version
                        res += CaseVersionIncrement;
                    }

                    // update the tables with the IDs
                    _invariantDict[value] = res;
                    _idDict[value] = res;
                    _fieldDict[res] = value;
                }
            }
            return new SymbolId(res);
        }

        public static SymbolId StringToCaseInsensitiveId(string value) {
            return StringToId(value).CaseInsensitiveIdentifier;
        }

        public static SymbolId[] QualifiedStringToIds(string values) {
            if (values != null) {
                string[] strings = values.Split('.');
                SymbolId[] identifiers = new SymbolId[strings.Length];

                for (int i = 0; i < strings.Length; i++) {
                    identifiers[i] = StringToId(strings[i]);
                }

                return identifiers;
            }

            return null;
        }

        public static string IdToString(SymbolId id) {
            lock (_fieldDict) {
                if (id.IsCaseInsensitive) {
                    return _fieldDict[id.Id | CaseVersionIncrement];
                }
                return _fieldDict[id.Id];
            }
        }

        // Tries to lookup the SymbolId to see if it is valid
        public static bool ContainsId(SymbolId id) {
            lock (_fieldDict) {
                if (id.IsCaseInsensitive) {
                    return _fieldDict.ContainsKey(id.Id | CaseVersionIncrement);
                }
                return _fieldDict.ContainsKey(id.Id);
            }
        }

        public static string[] IdsToStrings(IList<SymbolId> ids) {
            string[] ret = new string[ids.Count];
            for (int i = 0; i < ids.Count; i++) {
                if (ids[i] == SymbolId.Empty) ret[i] = null;
                else ret[i] = IdToString(ids[i]);
            }
            return ret;
        }

        public static SymbolId[] StringsToIds(IList<string> values) {
            SymbolId[] ret = new SymbolId[values.Count];
            for (int i = 0; i < values.Count; i++) {
                if (values[i] == null) ret[i] = SymbolId.Empty;
                else ret[i] = StringToId(values[i]);
            }
            return ret;
        }

        public static bool StringHasId(string symbol) {
            ContractUtils.RequiresNotNull(symbol, "symbol");

            lock (_lockObj) {
                return _idDict.ContainsKey(symbol);
            }
        }

        public static SymbolId StringToIdOrEmpty(string value) {
            if (value == null) {
                return SymbolId.Empty;
            }
            return StringToId(value);
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.