} // end _PrepareAdd()

        private SortedList <TItem> _PrepareRemove(DbgTemplateNode template)
        {
            Util.Assert(!String.IsNullOrEmpty(m_matchedTemplateName));
            if (0 != Util.Strcmp_OI(m_matchedTemplateName, template.TemplateName))
            {
                Util.Fail("should not happen");
                throw new ArgumentException(Util.Sprintf("The supplied item is for template {0}, but this list is for template {1}.",
                                                         template.TemplateName,
                                                         m_matchedTemplateName),
                                            "item");
            }

            SortedList <int, SortedList <TItem> > targetCategoryList;

            if (template.HasMultiTypeWildcard)
            {
                targetCategoryList = m_itemLists[NoMultiMatchIdx];
            }
            else
            {
                targetCategoryList = m_itemLists[HasMultiMatchIdx];
            }

            SortedList <TItem> itemList;

            if (!targetCategoryList.TryGetValue(template.SingleTypeWildcardCount, out itemList))
            {
                return(null);
            }
            return(itemList);
        } // end _PrepareRemove()
Esempio n. 2
0
        } // end constructor

        private static string _VerifyParamsAndBuildFullTypeName(string templateName,
                                                                IReadOnlyList <DbgTemplateNode> parameters,
                                                                DbgTemplateNode nestedType)
        {
            if (String.IsNullOrEmpty(templateName))
            {
                throw new ArgumentException("You must supply a template name.", "templateName");
            }

            if (null == parameters)
            {
                throw new ArgumentNullException("parameters");
            }

            for (int i = 0; i < parameters.Count; i++)
            {
                if (null == parameters[i])
                {
                    throw new ArgumentException("Null parameters not allowed.",
                                                Util.Sprintf("parameters[ {0} ]", i));
                }

                if ((parameters[i].FullName == c_MultiTypeWildcard) &&
                    (i != (parameters.Count - 1)))
                {
                    throw new ArgumentException(Util.Sprintf("The '{0}' wildcard must be the last parameter of a template.",
                                                             c_MultiTypeWildcard),
                                                "parameters");
                }
            } // end for( each param )

            StringBuilder sb = new StringBuilder(templateName.Length +
                                                 (parameters.Count * (templateName.Length * 3)));

            sb.Append(templateName);
            if (parameters.Count > 0)
            {
                sb.Append('<');
                bool first = true;
                foreach (var pn in parameters)
                {
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        sb.Append(',');
                    }
                    sb.Append(pn);
                }
                sb.Append('>');
            }
            if (null != nestedType)
            {
                sb.Append("::");
                sb.Append(nestedType.FullName);
            }
            return(sb.ToString());
        } // end _VerifyParamsAndBuildFullTypeName()
        } // end TryFindMatchingItem()

        /// <summary>
        ///    Finds all items with a matching template.
        /// </summary>
        public IEnumerable <TItem> FindMatchingItems(DbgTemplateNode typeTemplate)
        {
            if (null == typeTemplate)
            {
                throw new ArgumentNullException("typeTemplate");
            }

            if (0 != Util.Strcmp_OI(m_matchedTemplateName, typeTemplate.TemplateName))
            {
                Util.Fail("should not happen");
                throw new ArgumentException(Util.Sprintf("The supplied item is for template {0}, but this list is for template {1}.",
                                                         typeTemplate.TemplateName,
                                                         m_matchedTemplateName),
                                            "item");
            }

            foreach (var categoryList in m_itemLists)
            {
                foreach (var kvp in categoryList)
                {
                    foreach (var item in kvp.Value)
                    {
                        if (item.TypeName.Matches(typeTemplate))
                        {
                            yield return(item);
                        }
                    }
                }
            }
        } // end FindMatchingItems()
Esempio n. 4
0
        /// <summary>
        ///    Creates a new DbgValueConverterInfo object.
        /// </summary>
        /// <param name="typeName">
        ///    This can be module-qualified (like "dfsrs!_FILETIME"), or not (like
        ///    "!_FILETIME").
        /// </param>
        public DbgValueConverterInfo(string typeName, IDbgValueConverter converter, string sourceScript)
        {
            if (String.IsNullOrEmpty(typeName))
            {
                throw new ArgumentException("You must supply a type name.", "typeName");
            }

            if (null == converter)
            {
                throw new ArgumentNullException("converter");
            }

            int bangIdx = typeName.IndexOf('!');

            if (bangIdx < 0)
            {
                m_typeName = DbgTemplateNode.CrackTemplate(typeName);
            }
            else
            {
                ScopingModule = typeName.Substring(0, bangIdx);
                if (bangIdx == (typeName.Length - 1))
                {
                    throw new ArgumentException("No type name after the '!'.", typeName);
                }

                var tn = typeName.Substring(bangIdx + 1);
                m_typeName = DbgTemplateNode.CrackTemplate(tn);
            }

            Converter    = converter;
            SourceScript = sourceScript;
        } // end constructor
            _GetMatchingEntriesForModule(Dictionary <string, TypeNameMatchList <DbgValueConverterInfo> > entryDict,
                                         string templateFilter,
                                         bool exactMatchOnly,
                                         bool throwIfNoResult)
            {
                if (String.IsNullOrEmpty(templateFilter))
                {
                    if (exactMatchOnly)
                    {
                        throw new ArgumentException("You asked for exact matches only, but gave no templateFilter.");
                    }

                    foreach (var tml in entryDict.Values)
                    {
                        foreach (var converter in tml)
                        {
                            yield return(converter);
                        }
                    }
                }
                else
                {
                    TypeNameMatchList <DbgValueConverterInfo> tml;
                    DbgTemplateNode crackedName = DbgTemplate.CrackTemplate(templateFilter);
                    if (!entryDict.TryGetValue(crackedName.TemplateName, out tml))
                    {
                        if (throwIfNoResult)
                        {
                            throw new DbgProviderException(Util.Sprintf("Could not find converter info matching '{0}'.",
                                                                        templateFilter),
                                                           "NoConverterForTemplateFilter",
                                                           ErrorCategory.ObjectNotFound,
                                                           templateFilter);
                        }
                    }
                    else
                    {
                        if (exactMatchOnly)
                        {
                            int count = 0;
                            foreach (var converter in tml.FindMatchingItemsExact(crackedName))
                            {
                                count++;
                                yield return(converter);
                            }
                            Util.Assert(count <= 1);   // shouldn't be able to have more than one exact match
                        }
                        else
                        {
                            foreach (var converter in tml.FindMatchingItems(crackedName))
                            {
                                yield return(converter);
                            }
                        }
                    }
                }
            } // end _GetMatchingEntriesForModule()
Esempio n. 6
0
        /// <summary>
        ///    Indicates if two templates "match" exactly (if they are identical). The
        ///    comparison is case-insensitive.
        /// </summary>
        /// <remarks>
        /// <para>
        ///    For an exact match, the templates must be identical, including wildcards.
        ///    In other words, the FullName of each template must be the same (except for
        ///    case).
        /// </para>
        /// <para>
        ///    Normally when using template names, you should use the <see cref="Match"/>
        ///    method, so that wildcards are taken into account. This method is useful,
        ///    for instance, when you need to find something stored by template name in
        ///    order to update it.
        /// </para>
        /// <para>
        ///    N.B. The "const-ness" (HasConst) of a type name does not affect matching.
        /// </para>
        /// </remarks>
        public bool MatchesExact(DbgTemplateNode other)
        {
            if (null == other)
            {
                throw new ArgumentNullException("other");
            }

            return(0 == Util.Strcmp_OI(FullName, other.FullName));
        } // end MatchesExact()
        } // end FindMatchingItems()

        /// <summary>
        ///    Enumerates all items that have the exact same template.
        /// </summary>
        /// <remarks>
        ///    Items with templates that match but are not exact matches will not be
        ///    returned.
        /// </remarks>
        public IEnumerable <TItem> FindMatchingItemsExact(string typeName)
        {
            if (String.IsNullOrEmpty(typeName))
            {
                throw new ArgumentException("You must supply a type name.", "typeName");
            }

            DbgTemplateNode matchMe = DbgTemplateNode.CrackTemplate(typeName);

            return(FindMatchingItemsExact(matchMe));
        } // end FindMatchingItemsExact()
        } // end class ExactMatchEqualityComparer


        /// <summary>
        ///    Attempts to find an item with a matching template.
        /// </summary>
        /// <remarks>
        ///    There may be multiple matches in the list; this just returns the first
        ///    match, where matches are made according to priority order.
        /// </remarks>
        public TItem TryFindMatchingItem(string typeName)
        {
            if (String.IsNullOrEmpty(typeName))
            {
                throw new ArgumentException("You must supply a type name.", "typeName");
            }

            DbgTemplateNode matchMe = DbgTemplateNode.CrackTemplate(typeName);

            return(TryFindMatchingItem(matchMe));
        } // end TryFindMatchingItem()
Esempio n. 9
0
        } // end constructor

        public override bool Matches(DbgTemplateNode other)
        {
            // Special typename wildcard:
            if (IsEitherNameSingleTypeWildcard(FullName, other.FullName))
            {
                return(true);
            }

            if (other.IsTemplate)
            {
                return(false);
            }

            // TODO: PS Wildcard? Regex?
            return(0 == Util.Strcmp_OI(other.FullName, FullName));
        } // end Matches()
        } // end Remove()

        // public void AddRange( IEnumerable< TItem > items )
        // {
        //     if( null == items )
        //         throw new ArgumentNullException( "items" );

        //     DbgTemplateNode template = null;
        //     int count = 0;
        //     foreach( var item in items )
        //     {
        //         count++;

        //         if( null == template )
        //             template = item.TypeName;

        //         // Technically they only need to have wildcard type and count match, but
        //         // this should be fine.
        //         if( !item.TypeName.MatchesExact( template ) )
        //             throw new InvalidOperationException( "All items used with AddRange must have exactly-matching templates." );
        //     }

        //     if( 0 == count )
        //     {
        //         Util.Fail( "Why AddRange with nothing?" ); // Not a program invariant; just weird.
        //         return;
        //     }

        //     List< TItem > itemList = _PrepareAdd( template, count );
        //     itemList.AddRange( items );
        // } // end AddRange()


        private SortedList <TItem> _PrepareAdd(DbgTemplateNode template, int sizeHint)
        {
            m_version++;
            if (0 >= sizeHint)
            {
                sizeHint = 4;
            }

            if (null == m_matchedTemplateName)
            {
                m_matchedTemplateName = template.TemplateName;
                Util.Assert(!String.IsNullOrEmpty(m_matchedTemplateName));
            }
            else
            {
                if (0 != Util.Strcmp_OI(m_matchedTemplateName, template.TemplateName))
                {
                    Util.Fail("should not happen");
                    throw new ArgumentException(Util.Sprintf("The supplied item is for template {0}, but this list is for template {1}.",
                                                             template.TemplateName,
                                                             m_matchedTemplateName),
                                                "item");
                }
            }

            SortedList <int, SortedList <TItem> > targetCategoryList;

            if (template.HasMultiTypeWildcard)
            {
                targetCategoryList = m_itemLists[NoMultiMatchIdx];
            }
            else
            {
                targetCategoryList = m_itemLists[HasMultiMatchIdx];
            }

            SortedList <TItem> itemList;

            if (!targetCategoryList.TryGetValue(template.SingleTypeWildcardCount, out itemList))
            {
                itemList = new SortedList <TItem>(sizeHint,
                                                  NonWildcardParamComparer.Instance,
                                                  ExactMatchEqualityComparer.Instance);
                targetCategoryList.Add(template.SingleTypeWildcardCount, itemList);
            }
            return(itemList);
        } // end _PrepareAdd()
Esempio n. 11
0
        // TODO: perhaps this should be private as well, to prevent ill-formed templateName.
        internal DbgTemplate(string templateName,
                             IReadOnlyList <DbgTemplateNode> parameters,
                             DbgTemplateNode nestedType,
                             bool hasConst)
            : base(_VerifyParamsAndBuildFullTypeName(templateName,
                                                     parameters,
                                                     nestedType),
                   hasConst)
        {
            if (null == parameters)
            {
                throw new ArgumentNullException("parameters");
            }

            m_templateName = templateName;
            Parameters     = parameters;
            NestedNode     = nestedType;
        } // end constructor
        } // end FindMatchingItemsExact()

        /// <summary>
        ///    Enumerates all items that have the exact same template.
        /// </summary>
        /// <remarks>
        ///    Items with templates that match but are not exact matches will not be
        ///    returned.
        /// </remarks>
        public IEnumerable <TItem> FindMatchingItemsExact(DbgTemplateNode typeTemplate)
        {
            if (null == typeTemplate)
            {
                throw new ArgumentNullException("typeTemplate");
            }

            if (0 != Util.Strcmp_OI(m_matchedTemplateName, typeTemplate.TemplateName))
            {
                Util.Fail("should not happen");
                throw new ArgumentException(Util.Sprintf("The supplied item is for template {0}, but this list is for template {1}.",
                                                         typeTemplate.TemplateName,
                                                         m_matchedTemplateName),
                                            "item");
            }

            SortedList <int, SortedList <TItem> > targetCategoryList;

            if (typeTemplate.HasMultiTypeWildcard)
            {
                targetCategoryList = m_itemLists[NoMultiMatchIdx];
            }
            else
            {
                targetCategoryList = m_itemLists[HasMultiMatchIdx];
            }

            SortedList <TItem> itemList;

            if (!targetCategoryList.TryGetValue(typeTemplate.SingleTypeWildcardCount, out itemList))
            {
                yield break;
            }

            foreach (var item in itemList)
            {
                // TODO: But couldn't I go faster by using NonWildcardParameterCount?
                if (item.TypeName.MatchesExact(typeTemplate))
                {
                    yield return(item);
                }
            }
        } // end FindMatchingItemsExact()
Esempio n. 13
0
        } // end _AddBaseClassNodesToList()

        private void _AddBaseClassPointerNodesToList(List <DbgTemplateNode> list, DbgPointerTypeInfo pti)
        {
            DbgNamedTypeInfo dnti = pti;
            int numStars          = 0;

            while (dnti is DbgPointerTypeInfo)
            {
                dnti = ((DbgPointerTypeInfo)dnti).PointeeType;
                numStars++;
            }

            if (!typeof(DbgUdtTypeInfo).IsAssignableFrom(dnti.GetType()))
            {
                return; // It doesn't point to a UDT.
            }
            string stars = new String('*', numStars);
            var    q     = new Queue <DbgUdtTypeInfo>();
            var    uti   = (DbgUdtTypeInfo)dnti;

            uti.VisitAllBaseClasses((bc) => list.Add(DbgTemplateNode.CrackTemplate(bc.TemplateNode.FullName + stars)));
        } // end _AddBaseClassPointerNodesToList()
Esempio n. 14
0
        public IReadOnlyList <DbgTemplateNode> GetTemplateNodes()
        {
            if (null == m_templateNodes)
            {
                var templateTypeNames = new List <DbgTemplateNode>();
                DbgArrayTypeInfo ati  = this as DbgArrayTypeInfo;
                if (null != ati)
                {
                    templateTypeNames.Add(DbgTemplateNode.CrackTemplate(ati.ArrayElementType.Name + "[]"));     // we don't want the dimensions
                    // TODO: And maybe for array types, we'd like to include the array type /with/ dimensions,
                    // so that, for instance, all Foo[8] could be treated specially or something. But maybe that's
                    // stretching it.

                    // TODO: How about co-(or is it contra-)variance? (should we get base types of the element type, like we do for pointers?)
                }
                else if (typeof(DbgUdtTypeInfo).IsAssignableFrom(GetType()))
                {
                    DbgUdtTypeInfo uti = (DbgUdtTypeInfo)this;
                    templateTypeNames.Add(uti.TemplateNode);
                    _AddBaseClassNodesToList(templateTypeNames, uti);
                }
                else if (typeof(DbgPointerTypeInfo).IsAssignableFrom(GetType()))
                {
                    DbgPointerTypeInfo pti = (DbgPointerTypeInfo)this;
                    templateTypeNames.Add(pti.TemplateNode);
                    _AddBaseClassPointerNodesToList(templateTypeNames, pti);
                }
                else
                {
                    templateTypeNames.Add(DbgTemplateNode.CrackTemplate(Name));
                }

                m_templateNodes = templateTypeNames.AsReadOnly();
            }
            return(m_templateNodes);
        } // end GetTemplateNodes()
Esempio n. 15
0
        } // end constructor

        /// <summary>
        ///    Indicates if two templates "match", taking special template-matching
        ///    wildcards into account.
        /// </summary>
        /// <remarks>
        /// <para>
        ///    Two special wildcards can be used to match template parameters:
        ///      <list type="unordered">
        ///         <item>?
        ///           <description>Matches any single template parameter.</description>
        ///         </item>
        ///         <item>?*
        ///           <description>Matches one or more template parameters. Must be the last
        ///           parameter in a list.</description>
        ///         </item>
        ///      </list>
        ///    For example "std::foo&lt;WCHAR,?&gt;" matches "std::foo&lt;WCHAR,unsigned char&gt;".
        /// </para>
        /// <para>
        ///    Note that for DbgTemplate objects, these wildcards are only applicable in
        ///    the template parameter list; and DbgTemplateLeaf objects can consist of the
        ///    single-type wildcard (?), but not the multi-type wildcard
        ///    (?*).
        /// </para>
        /// <para>
        ///    The SingleTypeWildcardCount and HasMultiTypeWildcard properties can be
        ///    used to establish precedence between multiple matching templates.
        /// </para>
        /// <para>
        ///    N.B. The "const-ness" (HasConst) of a type name does not affect matching.
        /// </para>
        /// </remarks>
        public abstract bool Matches(DbgTemplateNode other);
Esempio n. 16
0
        } // end _HasTwoColonsPreceding()

        private static bool _TryCrackTemplate(string name,
                                              int startIdx,
                                              out DbgTemplateNode templatePart,
                                              out string problem)
        {
            templatePart = null;
            problem      = null;
            name         = name.Trim();

            bool hasConst = false;

            if (name.StartsWith("const ", StringComparison.OrdinalIgnoreCase))
            {
                // I haven't actually observed any type names with "const" at the
                // beginning, but it seems like it could be possible.
                hasConst = true;
                name     = name.Substring(6).Trim();
            }
            else if (name.EndsWith(" const", StringComparison.OrdinalIgnoreCase))
            {
                hasConst = true;
                name     = name.Substring(0, name.Length - 6).Trim();
            }

            int idx;

            if (!_LooksLikeATemplateName(name, startIdx, /* angleBracketIdx */ out idx))
            {
                templatePart = new DbgTemplateLeaf(name.Substring(startIdx), hasConst);
                return(true);
            }

            var             templateName   = name.Substring(startIdx, idx - startIdx);
            StringBuilder   sb             = new StringBuilder();
            DbgTemplateNode nestedType     = null;
            int             depth          = 1;
            var             templateParams = new List <DbgTemplateNode>();

            for (idx = idx + 1; idx < name.Length; idx++)  // start after the first '<'
            {
                char c = name[idx];
                if ('<' == c)
                {
                    depth++;
                }
                else if ('>' == c)
                {
                    depth--;
                    if (depth < 0)
                    {
                        problem = Util.Sprintf("Unbalanced closing angle bracket at position {0}.", idx);
                        return(false);
                    }

                    if (0 == depth)
                    {
                        if (sb.Length > 0)
                        {
                            templateParams.Add(CrackTemplate(sb.ToString().Trim()));
                        }

                        if (idx != (name.Length - 1))
                        {
                            // TODO: '+' for nested types in managed generic types?

                            if ((name.Length < (idx + 4)) || // there has to be at least "::X"
                                (name[idx + 1] != ':') ||
                                (name[idx + 2] != ':'))
                            {
                                problem = Util.Sprintf("Unexpected characters at position {0}.", idx);
                                return(false);
                            }
                            idx += 3; // skip the "::"

                            if (!_TryCrackTemplate(name, idx, out nestedType, out problem))
                            {
                                Util.Assert(!String.IsNullOrEmpty(problem));
                                return(false);
                            }
                        }
                        break;
                    }
                }

                if (depth > 1)
                {
                    sb.Append(c);
                }
                else
                {
                    Util.Assert(1 == depth);
                    if (',' == c)
                    {
                        // TODO: Hmm... I wonder if it's possible to get a symbol with ",," (which
                        // would lead to an empty part name, which will throw).
                        templateParams.Add(CrackTemplate(sb.ToString().Trim()));
                        sb.Clear();
                    }
                    else
                    {
                        sb.Append(c);
                    }
                }
            } // end for( each character )

            templatePart = new DbgTemplate(templateName,
                                           templateParams.AsReadOnly(),
                                           nestedType,
                                           hasConst);
            return(true);
        } // end _TryCrackTemplate()
Esempio n. 17
0
 protected static bool IsMultiMatchWildcard(DbgTemplateNode dtp)
 {
     return(dtp.FullName == c_MultiTypeWildcard);
 }
Esempio n. 18
0
        } // end _VerifyParamsAndBuildFullTypeName()

        public override bool Matches(DbgTemplateNode other)
        {
            // Special typename wildcard:
            if (IsEitherNameSingleTypeWildcard(other.FullName, FullName))
            {
                return(true);
            }

            if (!other.IsTemplate)
            {
                return(false);
            }

            DbgTemplate dtOther = (DbgTemplate)other;

            // TODO: PS Wildcard? Regex?
            if (0 != Util.Strcmp_OI(dtOther.TemplateName, TemplateName))
            {
                return(false);
            }

            for (int i = 0; i < dtOther.Parameters.Count; i++)
            {
                if (i >= Parameters.Count)
                {
                    return(false);
                }

                // Special typename wildcard:
                if (IsMultiMatchWildcard(dtOther.Parameters[i]))
                {
                    if (i != (dtOther.Parameters.Count - 1))
                    {
                        Util.Fail("Not reachable.");   // construction of such now disallowed.
                        throw new ArgumentException(Util.Sprintf("The '{0}' placeholder can only come last in a template parameter list.",
                                                                 c_MultiTypeWildcard),
                                                    "other");
                    }
                    break;
                }

                // Special typename wildcard:
                if (IsMultiMatchWildcard(Parameters[i]))
                {
                    if (i != (Parameters.Count - 1))
                    {
                        throw new ArgumentException(Util.Sprintf("The '{0}' placeholder can only come last in a template parameter list.",
                                                                 c_MultiTypeWildcard),
                                                    "this");
                    }

                    break;
                }

                if (!Parameters[i].Matches(dtOther.Parameters[i]))
                {
                    return(false);
                }
            }

            if ((null == NestedNode) != (null == dtOther.NestedNode))
            {
                // One has a nested node, and the other doesn't.
                return(false);
            }

            if (null != NestedNode)
            {
                return(NestedNode.Matches(dtOther.NestedNode));
            }
            else
            {
                return(true);
            }
        } // end Matches()