summaryrefslogtreecommitdiff
path: root/src/vm/typestring.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/typestring.h')
-rw-r--r--src/vm/typestring.h266
1 files changed, 266 insertions, 0 deletions
diff --git a/src/vm/typestring.h b/src/vm/typestring.h
new file mode 100644
index 0000000000..84a8e40447
--- /dev/null
+++ b/src/vm/typestring.h
@@ -0,0 +1,266 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// ---------------------------------------------------------------------------
+// typestring.cpp
+// ---------------------------------------------------------------------------
+//
+
+//
+// This module contains all helper functions required to produce
+// string representations of types, with options to control the
+// appearance of namespace and assembly information. Its primary use
+// is in reflection (Type.Name, Type.FullName, Type.ToString, etc) but
+// over time it could replace the use of TypeHandle.GetName etc for
+// diagnostic messages.
+//
+// ---------------------------------------------------------------------------
+
+
+#ifndef TYPESTRING_H
+#define TYPESTRING_H
+
+#include "common.h"
+#include "class.h"
+#include "typehandle.h"
+#include "sstring.h"
+#include "typekey.h"
+#include "typeparse.h"
+#include "field.h"
+
+class TypeLibExporter;
+class TypeString;
+
+class TypeNameBuilder
+{
+ friend class TypeNameBuilderWrapper;
+
+public:
+ static void QCALLTYPE _ReleaseTypeNameBuilder(TypeNameBuilder * pTnb);
+ static TypeNameBuilder * QCALLTYPE _CreateTypeNameBuilder();
+ static void QCALLTYPE _OpenGenericArguments(TypeNameBuilder * pTnb);
+ static void QCALLTYPE _CloseGenericArguments(TypeNameBuilder *pTnb);
+ static void QCALLTYPE _OpenGenericArgument(TypeNameBuilder * pTnb);
+ static void QCALLTYPE _CloseGenericArgument(TypeNameBuilder * pTnb);
+ static void QCALLTYPE _AddName(TypeNameBuilder * pTnb, LPCWSTR wszName);
+ static void QCALLTYPE _AddPointer(TypeNameBuilder * pTnb);
+ static void QCALLTYPE _AddByRef(TypeNameBuilder * pTnb);
+ static void QCALLTYPE _AddSzArray(TypeNameBuilder * pTnb);
+ static void QCALLTYPE _AddArray(TypeNameBuilder * pTnb, DWORD dwRank);
+ static void QCALLTYPE _AddAssemblySpec(TypeNameBuilder * pTnb, LPCWSTR wszAssemblySpec);
+ static void QCALLTYPE _ToString(TypeNameBuilder * pTnb, QCall::StringHandleOnStack retString);
+ static void QCALLTYPE _Clear(TypeNameBuilder * pTnb);
+
+private:
+ friend class TypeString;
+ friend SString* TypeName::ToString(SString*, BOOL, BOOL, BOOL);
+ friend TypeHandle TypeName::GetTypeWorker(BOOL, BOOL, BOOL, Assembly*, BOOL, BOOL, StackCrawlMark*, Assembly*,
+ ICLRPrivBinder * pPrivHostBinder,
+ BOOL, OBJECTREF *);
+ HRESULT OpenGenericArguments();
+ HRESULT CloseGenericArguments();
+ HRESULT OpenGenericArgument();
+ HRESULT CloseGenericArgument();
+ HRESULT AddName(LPCWSTR szName);
+ HRESULT AddName(LPCWSTR szName, LPCWSTR szNamespace);
+ HRESULT AddPointer();
+ HRESULT AddByRef();
+ HRESULT AddSzArray();
+ HRESULT AddArray(DWORD rank);
+ HRESULT AddAssemblySpec(LPCWSTR szAssemblySpec);
+ HRESULT ToString(BSTR* pszStringRepresentation);
+ HRESULT Clear();
+
+private:
+ class Stack
+ {
+ public:
+ Stack() : m_depth(0) { LIMITED_METHOD_CONTRACT; }
+
+ public:
+ COUNT_T Push(COUNT_T element) { WRAPPER_NO_CONTRACT; *m_stack.Append() = element; m_depth++; return Tos(); }
+ COUNT_T Pop()
+ {
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(GetDepth() > 0);
+ }
+ CONTRACTL_END;
+
+ COUNT_T tos = Tos();
+ m_stack.Delete(m_stack.End() - 1);
+ m_depth--;
+ return tos;
+ }
+ COUNT_T Tos() { WRAPPER_NO_CONTRACT; return m_stack.End()[-1]; }
+ void Clear() { WRAPPER_NO_CONTRACT; while(GetDepth()) Pop(); }
+ COUNT_T GetDepth() { WRAPPER_NO_CONTRACT; return m_depth; }
+
+ private:
+ INT32 m_depth;
+ InlineSArray<COUNT_T, 16> m_stack;
+ };
+
+
+public:
+ typedef enum
+ {
+ ParseStateSTART = 0x0001,
+ ParseStateNAME = 0x0004,
+ ParseStateGENARGS = 0x0008,
+ ParseStatePTRARR = 0x0010,
+ ParseStateBYREF = 0x0020,
+ ParseStateASSEMSPEC = 0x0080,
+ ParseStateERROR = 0x0100,
+ }
+ ParseState;
+
+public:
+ TypeNameBuilder(SString* pStr, ParseState parseState = ParseStateSTART);
+ TypeNameBuilder() { WRAPPER_NO_CONTRACT; m_pStr = &m_str; Clear(); }
+ void SetUseAngleBracketsForGenerics(BOOL value) { m_bUseAngleBracketsForGenerics = value; }
+ void Append(LPCWSTR pStr) { WRAPPER_NO_CONTRACT; m_pStr->Append(pStr); }
+ void Append(WCHAR c) { WRAPPER_NO_CONTRACT; m_pStr->Append(c); }
+ SString* GetString() { WRAPPER_NO_CONTRACT; return m_pStr; }
+
+private:
+ void EscapeName(LPCWSTR szName);
+ void EscapeAssemblyName(LPCWSTR szName);
+ void EscapeEmbeddedAssemblyName(LPCWSTR szName);
+ BOOL CheckParseState(int validState) { WRAPPER_NO_CONTRACT; return ((int)m_parseState & validState) != 0; }
+ //BOOL CheckParseState(int validState) { WRAPPER_NO_CONTRACT; ASSERT(((int)m_parseState & validState) != 0); return TRUE; }
+ HRESULT Fail() { WRAPPER_NO_CONTRACT; m_parseState = ParseStateERROR; return E_FAIL; }
+ void PushOpenGenericArgument();
+ void PopOpenGenericArgument();
+
+private:
+ ParseState m_parseState;
+ SString* m_pStr;
+ InlineSString<256> m_str;
+ DWORD m_instNesting;
+ BOOL m_bFirstInstArg;
+ BOOL m_bNestedName;
+ BOOL m_bHasAssemblySpec;
+ BOOL m_bUseAngleBracketsForGenerics;
+ Stack m_stack;
+};
+
+// Class that's exposed to COM and wraps TypeNameBuilder (so that it can thunk
+// all the entry points in order to perform stack probes).
+class TypeNameBuilderWrapper : public ITypeNameBuilder
+{
+public:
+ virtual HRESULT __stdcall QueryInterface(REFIID riid, void **ppUnk);
+ virtual ULONG __stdcall AddRef();
+ virtual ULONG __stdcall Release();
+
+ virtual HRESULT __stdcall OpenGenericArguments();
+ virtual HRESULT __stdcall CloseGenericArguments();
+ virtual HRESULT __stdcall OpenGenericArgument();
+ virtual HRESULT __stdcall CloseGenericArgument();
+ virtual HRESULT __stdcall AddName(LPCWSTR szName);
+ virtual HRESULT __stdcall AddPointer();
+ virtual HRESULT __stdcall AddByRef();
+ virtual HRESULT __stdcall AddSzArray();
+ virtual HRESULT __stdcall AddArray(DWORD rank);
+ virtual HRESULT __stdcall AddAssemblySpec(LPCWSTR szAssemblySpec);
+ virtual HRESULT __stdcall ToString(BSTR* pszStringRepresentation);
+ virtual HRESULT __stdcall Clear();
+
+ TypeNameBuilderWrapper() : m_ref(0) { WRAPPER_NO_CONTRACT; }
+ virtual ~TypeNameBuilderWrapper() {}
+
+private:
+ LONG m_ref;
+ TypeNameBuilder m_tnb;
+};
+
+// --------------------------------------------------------------------------
+// This type can generate names for types. It is used by reflection methods
+// like System.RuntimeType.RuntimeTypeCache.ConstructName
+//
+
+class TypeString
+{
+ // -----------------------------------------------------------------------
+ // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ // -----------------------------------------------------------------------
+ // Do no change the formatting of these strings as they are used by
+ // serialization, and it would break serialization backwards-compatibility.
+
+public:
+
+ typedef enum
+ {
+ FormatBasic = 0x00000000, // Not a bitmask, simply the tersest flag settings possible
+ FormatNamespace = 0x00000001, // Include namespace and/or enclosing class names in type names
+ FormatFullInst = 0x00000002, // Include namespace and assembly in generic types (regardless of other flag settings)
+ FormatAssembly = 0x00000004, // Include assembly display name in type names
+ FormatSignature = 0x00000008, // Include signature in method names
+ FormatNoVersion = 0x00000010, // Suppress version and culture information in all assembly names
+#ifdef _DEBUG
+ FormatDebug = 0x00000020, // For debug printing of types only
+#endif
+ FormatAngleBrackets = 0x00000040, // Whether generic types are C<T> or C[T]
+ FormatStubInfo = 0x00000080, // Include stub info like {unbox-stub}
+ FormatGenericParam = 0x00000100, // Use !name and !!name for generic type and method parameters
+ }
+ FormatFlags;
+
+public:
+ // Append the name of the type td to the string
+ // The following flags in the FormatFlags argument are significant: FormatNamespace
+ static void AppendTypeDef(SString& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format = FormatNamespace);
+
+ // Append a square-bracket-enclosed, comma-separated list of n type parameters in inst to the string s
+ // and enclose each parameter in square brackets to disambiguate the commas
+ // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion
+ static void AppendInst(SString& s, Instantiation inst, DWORD format = FormatNamespace);
+
+ // Append a representation of the type t to the string s
+ // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion
+ static void AppendType(SString& s, TypeHandle t, DWORD format = FormatNamespace);
+
+ // Append a representation of the type t to the string s, using the generic
+ // instantiation info provided, instead of the instantiation in the TypeHandle.
+ static void AppendType(SString& s, TypeHandle t, Instantiation typeInstantiation, DWORD format = FormatNamespace);
+
+ static void AppendTypeKey(SString& s, TypeKey *pTypeKey, DWORD format = FormatNamespace);
+
+ // Appends the method name and generic instantiation info. This might
+ // look like "Namespace.ClassName[T].Foo[U, V]()"
+ static void AppendMethod(SString& s, MethodDesc *pMD, Instantiation typeInstantiation, const DWORD format = FormatNamespace|FormatSignature);
+
+ // Append a representation of the method m to the string s
+ // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatSignature FormatNoVersion
+ static void AppendMethodInternal(SString& s, MethodDesc *pMD, const DWORD format = FormatNamespace|FormatSignature|FormatStubInfo);
+
+ // Append the field name and generic instantiation info.
+ static void AppendField(SString& s, FieldDesc *pFD, Instantiation typeInstantiation, const DWORD format = FormatNamespace);
+#ifdef _DEBUG
+ // These versions are NOTHROWS. They are meant for diagnostic purposes only
+ // as they may leave "s" in a bad state if there are any problems/exceptions.
+ static void AppendMethodDebug(SString& s, MethodDesc *pMD);
+ static void AppendTypeDebug(SString& s, TypeHandle t);
+ static void AppendTypeKeyDebug(SString& s, TypeKey* pTypeKey);
+#endif
+
+private:
+ friend class TypeLibExporter;
+ friend class TypeNameBuilder;
+ static void AppendMethodImpl(SString& s, MethodDesc *pMD, Instantiation typeInstantiation, const DWORD format);
+ static void AppendTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format = FormatNamespace);
+ static void AppendNestedTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format = FormatNamespace);
+ static void AppendInst(TypeNameBuilder& tnb, Instantiation inst, DWORD format = FormatNamespace);
+ static void AppendType(TypeNameBuilder& tnb, TypeHandle t, Instantiation typeInstantiation, DWORD format = FormatNamespace); // ????
+ static void AppendTypeKey(TypeNameBuilder& tnb, TypeKey *pTypeKey, DWORD format = FormatNamespace);
+ static void AppendParamTypeQualifier(TypeNameBuilder& tnb, CorElementType kind, DWORD rank);
+ static void EscapeSimpleTypeName(SString* ssTypeName, SString* ssEscapedTypeName);
+ static bool ContainsReservedChar(LPCWSTR pTypeName);
+};
+
+#endif
+