PageRenderTime 19ms CodeModel.GetById 2ms app.highlight 11ms RepoModel.GetById 2ms app.codeStats 0ms

/IronPython_2_0/Src/Microsoft.Scripting/SymbolTable.cs

#
C# | 154 lines | 98 code | 29 blank | 27 comment | 22 complexity | 9990a97fa466e63fc26ae91279145efc MD5 | raw file
  1/* ****************************************************************************
  2 *
  3 * Copyright (c) Microsoft Corporation. 
  4 *
  5 * This source code is subject to terms and conditions of the Microsoft Public License. A 
  6 * copy of the license can be found in the License.html file at the root of this distribution. If 
  7 * you cannot locate the  Microsoft Public License, please send an email to 
  8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
  9 * by the terms of the Microsoft Public License.
 10 *
 11 * You must not remove this notice, or any other, from this software.
 12 *
 13 *
 14 * ***************************************************************************/
 15using System; using Microsoft;
 16
 17
 18using System.Collections.Generic;
 19using System.Diagnostics;
 20using Microsoft.Scripting.Utils;
 21
 22namespace Microsoft.Scripting {
 23    public static class SymbolTable {
 24        private static readonly object _lockObj = new object();
 25
 26        private static readonly Dictionary<string, int> _idDict = new Dictionary<string, int>(InitialTableSize);
 27
 28        private const int InitialTableSize = 256;
 29        private static readonly Dictionary<int, string> _fieldDict = CreateFieldDictionary();
 30        [MultiRuntimeAware]
 31        private static int _nextCaseInsensitiveId = 1;
 32
 33        private static Dictionary<int, string>  CreateFieldDictionary() {
 34            Dictionary<int, string> result = new Dictionary<int, string>(InitialTableSize);
 35            result[0] = null;   // initialize the null string
 36            return result;
 37        }
 38
 39        public static SymbolId StringToId(string field) {
 40            ContractUtils.RequiresNotNull(field, "field");
 41
 42            int res;
 43            lock (_lockObj) {
 44                // First, look up the identifier case-sensitively.
 45                if (!_idDict.TryGetValue(field, out res)) {
 46                    string invariantField = field.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
 47
 48                    // OK, didn't find it, so let's look up the case-insensitive
 49                    // identifier.
 50                    if (_idDict.TryGetValue(invariantField, out res)) {
 51                        // OK, this is a new casing of an existing identifier.
 52                        Debug.Assert(res < 0, "Must have invariant bit set!");
 53
 54                        // Throw if we've exhausted the number of casings.
 55                        if (unchecked(((uint)res & 0x00FFFFFF) == 0x00FFFFFF)) {
 56                            throw Error.CantAddCasing(field);
 57                        }
 58
 59                        int invariantRes = res + 0x01000000;
 60
 61                        // Mask off the high bit.
 62                        res = unchecked((int)((uint)res & 0x7FFFFFFF));
 63
 64                        _idDict[field] = res;
 65                        _idDict[invariantField] = invariantRes;
 66                        _fieldDict[res] = field;
 67                    } else {
 68                        // This is a whole new identifier.
 69
 70                        if (_nextCaseInsensitiveId == int.MaxValue) {
 71                            throw Error.CantAddIdentifier(field);
 72                        }
 73
 74                        // register new id...
 75                        res = _nextCaseInsensitiveId++;
 76                        // Console.WriteLine("Registering {0} as {1}", field, res);
 77
 78                        _fieldDict[res] = invariantField;
 79
 80                        if (field != invariantField) {
 81                            res |= 0x01000000;
 82                            _idDict[field] = res;
 83                            _fieldDict[res] = field;
 84                        }
 85
 86                        _idDict[invariantField] = unchecked((int)(((uint)res | 0x80000000) + 0x01000000));
 87                    }
 88                } else {
 89                    // If this happens to be the invariant field, then we need to
 90                    // mask off the top byte, since that's just used to pick the next
 91                    // id for this identifier.
 92                    if (res < 0) {
 93                        res &= 0x00FFFFFF;
 94                    }
 95                }
 96            }
 97            return new SymbolId(res);
 98        }
 99
100        public static SymbolId StringToCaseInsensitiveId(string field) {
101            return StringToId(field.ToUpper(System.Globalization.CultureInfo.InvariantCulture));
102        }
103
104        public static SymbolId[] QualifiedStringToIds(string fields) {
105            if (fields != null) {
106                string[] strings = fields.Split('.');
107                SymbolId[] identifiers = new SymbolId[strings.Length];
108
109                for (int i = 0; i < strings.Length; i++) {
110                    identifiers[i] = StringToId(strings[i]);
111                }
112
113                return identifiers;
114            }
115
116            return null;
117        }
118
119        public static string IdToString(SymbolId id) {
120            return _fieldDict[id.Id];
121        }
122
123        // Tries to lookup the SymbolId to see if it is valid
124        public static bool ContainsId(SymbolId id) {
125            return _fieldDict.ContainsKey(id.Id);
126        }
127
128        public static string[] IdsToStrings(IList<SymbolId> ids) {
129            string[] ret = new string[ids.Count];
130            for (int i = 0; i < ids.Count; i++) {
131                if (ids[i] == SymbolId.Empty) ret[i] = null;
132                else ret[i] = IdToString(ids[i]);
133            }
134            return ret;
135        }
136
137        public static SymbolId[] StringsToIds(IList<string> strings) {
138            SymbolId[] ret = new SymbolId[strings.Count];
139            for (int i = 0; i < strings.Count; i++) {
140                if (strings[i] == null) ret[i] = SymbolId.Empty;
141                else ret[i] = StringToId(strings[i]);
142            }
143            return ret;
144        }
145
146        public static bool StringHasId(string symbol) {
147            ContractUtils.RequiresNotNull(symbol, "symbol");
148
149            lock (_lockObj) {
150                return _idDict.ContainsKey(symbol);
151            }
152        }
153    }
154}