public bool PathExists(string path) { string ns = path; int lastIndex = 0; CliNamespaceKeyedTree topLevel = this.info; nextPart: int next = ns.IndexOf('.', lastIndex); if (next != -1) { string current = ns.Substring(lastIndex, next - lastIndex); uint currentHash = (uint)current.GetHashCode(); if (topLevel.ContainsKey(currentHash)) { topLevel = topLevel[currentHash]; } else { return(false); } lastIndex = next + 1; goto nextPart; } else { string current = ns.Substring(lastIndex); uint currentHash = (uint)current.GetHashCode(); return(topLevel.ContainsKey(currentHash)); } }
internal CliNamespaceDictionary(CliAssembly owner, INamespaceParent parent, CliNamespaceKeyedTree info) : base(info.Keys) { this.owner = owner; this.info = info; this.parent = parent; }
public INamespaceDeclaration this[string path] { get { string ns = path; int lastIndex = 0; CliNamespaceKeyedTree topLevel = this.info; INamespaceDictionary topNamespaceDict = this; StringBuilder pathBuilder = new StringBuilder(); bool first = true; nextPart: int next = ns.IndexOf('.', lastIndex); if (first) { first = false; } else { pathBuilder.Append('.'); } if (next != -1) { string current = ns.Substring(lastIndex, next - lastIndex); pathBuilder.Append(current); uint currentHash = (uint)current.GetHashCode(); if (topLevel.ContainsKey(currentHash)) { topLevel = topLevel[currentHash]; topNamespaceDict = topNamespaceDict[TypeSystemIdentifiers.GetDeclarationIdentifier(pathBuilder.ToString())].Namespaces; } else { return(null); } lastIndex = next + 1; goto nextPart; } else { string current = ns.Substring(lastIndex); pathBuilder.Append(current); uint currentHash = (uint)current.GetHashCode(); if (topLevel.ContainsKey(currentHash)) { topLevel = topLevel[currentHash]; return(topNamespaceDict[TypeSystemIdentifiers.GetDeclarationIdentifier(pathBuilder.ToString())]); } else { return(null); } } } }
protected override void Dispose(bool disposing) { this.metadataRoot.Dispose(); this.metadataRoot = null; this.namespaceInformation = null; }
internal void InitializeCommon() { ICliMetadataModuleTableRow[] modules = this.Modules.GetMetadata(); var typeTables = (from moduleRow in modules let ts = moduleRow.MetadataRoot.TableStream where ts.TypeDefinitionTable != null select ts.TypeDefinitionTable).ToArray(); if (typeTables.Length == 0) { return; } HashSet <Tuple <int, uint> > namespaceIndices = new HashSet <Tuple <int, uint> >(); Dictionary <uint, CliMetadataTypeDefinitionLockedTableRow[]> nonNestedTypes = new Dictionary <uint, CliMetadataTypeDefinitionLockedTableRow[]>(); Dictionary <uint, int> nonNestedCounts = new Dictionary <uint, int>(); /* * * Breakdown the types by their namespace index, and * create a unique list of namespaceIndices via a HashSet<T>. * * * Copy the table to a local set to avoid redundant load * checks, and to instruct it to read the full table sequentially. * */ int totalTypeCount = 0; for (int typeTable = 0; typeTable < typeTables.Length; typeTable++) { totalTypeCount += typeTables[typeTable].Count; } ICliMetadataTypeDefinitionTableRow[] types = new ICliMetadataTypeDefinitionTableRow[totalTypeCount]; for (int moduleIndex = 0, cOff = 0; moduleIndex < typeTables.Length; cOff += typeTables[moduleIndex++].Count) { typeTables[moduleIndex].CopyTo(types, cOff); } ICliMetadataTypeDefinitionTable moduleTypes = typeTables[0]; for (int typeIndex = 0, moduleIndex = 0, moduleOffset = 0; typeIndex < types.Length; typeIndex++, moduleOffset++) { moduleCheck: if (moduleOffset >= moduleTypes.Count) { moduleIndex++; if (moduleIndex < typeTables.Length) { moduleTypes = typeTables[moduleIndex]; } moduleOffset = 0; goto moduleCheck; } var typeRow = types[typeIndex]; if ((typeRow.TypeAttributes & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic || (typeRow.TypeAttributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) { uint nsIndex = typeRow.NamespaceIndex; namespaceIndices.Add(Tuple.Create(moduleIndex, nsIndex)); CliMetadataTypeDefinitionLockedTableRow[] currentRows; if (!nonNestedTypes.TryGetValue(nsIndex, out currentRows)) { nonNestedTypes.Add(nsIndex, currentRows = new CliMetadataTypeDefinitionLockedTableRow[4]); nonNestedCounts.Add(nsIndex, 0); } CliMetadataTypeDefinitionLockedTableRow[] spaceAvailableRows = currentRows.EnsureSpaceExists(nonNestedCounts[nsIndex], 1); if (spaceAvailableRows != currentRows) { nonNestedTypes[nsIndex] = currentRows = spaceAvailableRows; } currentRows[nonNestedCounts[nsIndex]++] = typeRow as CliMetadataTypeDefinitionLockedTableRow; } } var namespaceIndicesArray = namespaceIndices.ToArray(); CliMetadataTypeDefinitionLockedTableRow[] topLevelRows; if (nonNestedTypes.TryGetValue(0, out topLevelRows)) { int topLevelCount = nonNestedCounts[0]; int noModuleCount = 0; for (int typeIndex = 0; typeIndex < topLevelCount; typeIndex++) { if (topLevelRows[typeIndex].Index != CliMetadataTypeDefinitionTableReader.__COR_TYPEDEFINITION_MODULE_INDEX__) { noModuleCount++; } } if (topLevelRows.Length != noModuleCount) { CliMetadataTypeDefinitionLockedTableRow[] topLevelRowsActual = new CliMetadataTypeDefinitionLockedTableRow[noModuleCount]; /* * * Filter the entries based off of their index. The special <Module> type * is the global fields and methods. There's no need to include them and * have to inject checks elsewhere to filter it out. * */ for (int typeIndex = 0, cOffset = 0; typeIndex < topLevelCount; typeIndex++) { if (topLevelRows[typeIndex].Index != CliMetadataTypeDefinitionTableReader.__COR_TYPEDEFINITION_MODULE_INDEX__) { topLevelRowsActual[cOffset++] = topLevelRows[typeIndex]; } } Array.Sort(topLevelRowsActual, _CompareTo_); topLevelRows = topLevelRowsActual; } else { Array.Sort(topLevelRows, _CompareTo_); } } else { topLevelRows = new CliMetadataTypeDefinitionLockedTableRow[0]; } CliNamespaceKeyedTree partialOrFullNamespaces = new CliNamespaceKeyedTree(topLevelRows); Dictionary <string, uint> partIndex = new Dictionary <string, uint>(); for (int namespaceIndex = 0; namespaceIndex < namespaceIndicesArray.Length; namespaceIndex++) { uint currentIndex = namespaceIndicesArray[namespaceIndex].Item2; if (currentIndex == 0) { continue; } var currentRows = nonNestedTypes[currentIndex]; var currentCount = nonNestedCounts[currentIndex]; var module = modules[namespaceIndicesArray[namespaceIndex].Item1]; string currentString = module.MetadataRoot.StringsHeap[currentIndex]; /* * * Eliminate the null row entries by reducing the sizes * of the arrays. * */ if (currentRows.Length != currentCount) { var currentRowsCopy = new CliMetadataTypeDefinitionLockedTableRow[currentCount]; Array.ConstrainedCopy(currentRows, 0, currentRowsCopy, 0, currentCount); Array.Sort(currentRowsCopy, _CompareTo_); currentRows = currentRowsCopy; } else { Array.Sort(currentRows, _CompareTo_); } CliNamespaceKeyedTree current = partialOrFullNamespaces; string[] breakdown = currentString.Split(new[] { "." }, StringSplitOptions.None); int currentLength = 0; bool first = true; foreach (var part in breakdown) { /* * * Position tracking, there is no period preceeding * the first namespace identifier. * */ if (first) { first = false; } else { currentLength++; } uint partId; /* * * Don't use the namespace index as a key for the * partial or full dictionary. * * * Use the substring of the current namespace as a guide, * since the 'System' of 'System'.Collections.Generic would * be a different string heap index than 'System' alone, * create our own reference lookup for the individual * segments of the namespace's name. * * * Use the segment's hash code to determine the part index; * while there's a chance for collision, the chances are slim. * Main reason is: while the space of possible character combinations * is small, the chance of a user-written name overlapping, in the * realm of its sibling namespaces, is unlikely. * */ if (!partIndex.TryGetValue(part, out partId)) { partIndex.Add(part, partId = (uint)part.GetHashCode()); } int startIndex = currentLength; currentLength += part.Length; bool fullName = currentLength == currentString.Length; CliNamespaceKeyedTreeNode next; if (!current.TryGetValue(partId, out next)) { if (fullName) { current = current.Add(partId, currentIndex, startIndex, currentLength - startIndex, currentRows, module.MetadataRoot.StringsHeap); } else { current = current.Add(partId, currentIndex, startIndex, currentLength - startIndex, module.MetadataRoot.StringsHeap); } } else { current = next; if (fullName) { current.PushModuleTypes(currentRows); } } } } this.namespaceInformation = partialOrFullNamespaces; }