diff --git a/src/coreclr/binder/applicationcontext.cpp b/src/coreclr/binder/applicationcontext.cpp index 11369b899935e2..51b97361511ad8 100644 --- a/src/coreclr/binder/applicationcontext.cpp +++ b/src/coreclr/binder/applicationcontext.cpp @@ -96,8 +96,6 @@ namespace BINDER_SPACE // m_pTrustedPlatformAssemblyMap = new SimpleNameToFileNameMap(); - sTrustedPlatformAssemblies.Normalize(); - for (SString::Iterator i = sTrustedPlatformAssemblies.Begin(); i != sTrustedPlatformAssemblies.End(); ) { SString fileName; @@ -110,7 +108,7 @@ namespace BINDER_SPACE break; } - const SimpleNameToFileNameMapEntry *pExistingEntry = m_pTrustedPlatformAssemblyMap->LookupPtr(simpleName.GetUnicode()); + const SimpleNameToFileNameMapEntry *pExistingEntry = m_pTrustedPlatformAssemblyMap->LookupPtr(simpleName); if (pExistingEntry != nullptr) { @@ -135,7 +133,7 @@ namespace BINDER_SPACE { GO_WITH_HRESULT(E_OUTOFMEMORY); } - wcscpy_s(wszSimpleName, simpleName.GetCount() + 1, simpleName.GetUnicode()); + wcscpy_s(wszSimpleName, simpleName.GetCount() + 1, simpleName); } else { @@ -147,7 +145,7 @@ namespace BINDER_SPACE { GO_WITH_HRESULT(E_OUTOFMEMORY); } - wcscpy_s(wszFileName, fileName.GetCount() + 1, fileName.GetUnicode()); + wcscpy_s(wszFileName, fileName.GetCount() + 1, fileName); SimpleNameToFileNameMapEntry mapEntry; mapEntry.m_wszSimpleName = wszSimpleName; @@ -168,7 +166,6 @@ namespace BINDER_SPACE // // Parse PlatformResourceRoots // - sPlatformResourceRoots.Normalize(); for (SString::Iterator i = sPlatformResourceRoots.Begin(); i != sPlatformResourceRoots.End(); ) { SString pathName; @@ -191,7 +188,6 @@ namespace BINDER_SPACE // // Parse AppPaths // - sAppPaths.Normalize(); for (SString::Iterator i = sAppPaths.Begin(); i != sAppPaths.End(); ) { SString pathName; diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index b3edff82d7cbc5..868c585c0398c4 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -292,7 +292,6 @@ namespace BINDER_SPACE // Try to find corelib in the TPA StackSString sCoreLibSimpleName(CoreLibName_W); StackSString sTrustedPlatformAssemblies = Configuration::GetKnobStringValue(W("TRUSTED_PLATFORM_ASSEMBLIES")); - sTrustedPlatformAssemblies.Normalize(); bool found = false; for (SString::Iterator i = sTrustedPlatformAssemblies.Begin(); i != sTrustedPlatformAssemblies.End(); ) @@ -309,7 +308,7 @@ namespace BINDER_SPACE if (simpleName.EqualsCaseInsensitive(sCoreLibSimpleName)) { - sCoreLib = fileName; + sCoreLib = (LPCWSTR)fileName; found = true; break; } @@ -859,7 +858,8 @@ namespace BINDER_SPACE SString assemblyFileName(simpleName); assemblyFileName.Append(candidates[i]); - SString assemblyFilePath(Bundle::AppBundle->BasePath()); + SString assemblyFilePath; + Bundle::AppBundle->BasePath().ConvertToUnicode(assemblyFilePath); assemblyFilePath.Append(assemblyFileName); BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(assemblyFileName, /* pathIsBundleRelative */ true); @@ -891,7 +891,7 @@ namespace BINDER_SPACE // Is assembly on TPA list? SimpleNameToFileNameMap * tpaMap = pApplicationContext->GetTpaList(); - const SimpleNameToFileNameMapEntry *pTpaEntry = tpaMap->LookupPtr(simpleName.GetUnicode()); + const SimpleNameToFileNameMapEntry *pTpaEntry = tpaMap->LookupPtr(simpleName); if (pTpaEntry != nullptr) { if (pTpaEntry->m_wszNIFileName != nullptr) @@ -1011,7 +1011,7 @@ namespace BINDER_SPACE // Obtain assembly meta data { - LPCTSTR szAssemblyPath = const_cast(assemblyPath.GetUnicode()); + LPCTSTR szAssemblyPath = static_cast(assemblyPath); hr = BinderAcquirePEImage(szAssemblyPath, &pPEImage, bundleFileLocation); IF_FAIL_GO(hr); diff --git a/src/coreclr/binder/assemblyname.cpp b/src/coreclr/binder/assemblyname.cpp index 9eea2ee8ba736f..8f72138cbb756c 100644 --- a/src/coreclr/binder/assemblyname.cpp +++ b/src/coreclr/binder/assemblyname.cpp @@ -80,23 +80,21 @@ namespace BINDER_SPACE )); { - StackSString culture; - culture.SetUTF8(amd.szLocale); - culture.Normalize(); + StackEString culture(amd.szLocale); + SString cultureUnicode(culture.MoveToUnicode()); - SString::CIterator itr = culture.Begin(); - if (culture.Find(itr, L';')) + SString::CIterator itr = cultureUnicode.Begin(); + if (cultureUnicode.Find(itr, L';')) { - culture = SString(culture, culture.Begin(), itr-1); + cultureUnicode = SString(cultureUnicode, cultureUnicode.Begin(), itr-1); } - SetCulture(culture); + SetCulture(cultureUnicode); } { - StackSString assemblyName; - assemblyName.SetUTF8(pAssemblyName); - assemblyName.Normalize(); + StackEString assemblyName(pAssemblyName); + SString assemblyNameUnicode(assemblyName.MoveToUnicode()); COUNT_T assemblyNameLength = assemblyName.GetCount(); if (assemblyNameLength == 0 || assemblyNameLength >= MAX_PATH_FNAME) @@ -104,7 +102,7 @@ namespace BINDER_SPACE IF_FAIL_GO(FUSION_E_INVALID_NAME); } - SetSimpleName(assemblyName); + SetSimpleName(assemblyNameUnicode); } // See if the assembly[def] is retargetable (ie, for a generic assembly). @@ -159,10 +157,12 @@ namespace BINDER_SPACE HRESULT AssemblyName::Init(const AssemblyNameData &data) { DWORD flags = data.IdentityFlags; - m_simpleName.SetUTF8(data.Name); + MAKE_WIDEPTR_FROMUTF8(pSimpleName, data.Name); + m_simpleName.Set(pSimpleName); m_version.SetFeatureVersion(data.MajorVersion, data.MinorVersion); m_version.SetServiceVersion(data.BuildNumber, data.RevisionNumber); - m_cultureOrLanguage.SetUTF8(data.Culture); + MAKE_WIDEPTR_FROMUTF8(pCulture, data.Culture); + m_cultureOrLanguage.Set(pCulture); m_publicKeyOrTokenBLOB.Set(data.PublicKeyOrToken, data.PublicKeyOrTokenLength); if ((flags & BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY) != 0) @@ -204,13 +204,13 @@ namespace BINDER_SPACE BOOL AssemblyName::IsCoreLib() { // TODO: Is this simple comparison enough? - return SString::_wcsicmp(GetSimpleName().GetUnicode(), CoreLibName_W) == 0; + return StaticStringHelpers::_wcsicmp(GetSimpleName(), CoreLibName_W) == 0; } bool AssemblyName::IsNeutralCulture() { return m_cultureOrLanguage.IsEmpty() - || SString::_wcsicmp(m_cultureOrLanguage.GetUnicode(), s_neutralCulture) == 0; + || StaticStringHelpers::_wcsicmp(m_cultureOrLanguage, s_neutralCulture) == 0; } ULONG AssemblyName::Hash(DWORD dwIncludeFlags) diff --git a/src/coreclr/binder/bindertracing.cpp b/src/coreclr/binder/bindertracing.cpp index 2da85be540dda0..44ae6bb849cc3c 100644 --- a/src/coreclr/binder/bindertracing.cpp +++ b/src/coreclr/binder/bindertracing.cpp @@ -217,7 +217,7 @@ namespace BinderTracing // Use the error message that would be reported in the file load exception StackSString errorMsg; if (mvidMismatch) - errorMsg.LoadResource(CCompRC::Error, IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT); + LoadResource(errorMsg, CCompRC::Error, IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT); const BindResult::AttemptResult *inContextAttempt = bindResult.GetAttempt(true /*foundInContext*/); const BindResult::AttemptResult *appAssembliesAttempt = bindResult.GetAttempt(false /*foundInContext*/); @@ -229,11 +229,11 @@ namespace BinderTracing TraceStage(Stage::FindInLoadContext, isLastAttempt && FAILED(m_hr) && SUCCEEDED(inContextAttempt->HResult) ? m_hr : inContextAttempt->HResult, inContextAttempt->Assembly, - mvidMismatch && isLastAttempt ? errorMsg.GetUnicode() : nullptr); + mvidMismatch && isLastAttempt ? (LPCWSTR)errorMsg : nullptr); } if (appAssembliesAttempt != nullptr) - TraceStage(Stage::ApplicationAssemblies, FAILED(m_hr) && SUCCEEDED(appAssembliesAttempt->HResult) ? m_hr : appAssembliesAttempt->HResult, appAssembliesAttempt->Assembly, mvidMismatch ? errorMsg.GetUnicode() : nullptr); + TraceStage(Stage::ApplicationAssemblies, FAILED(m_hr) && SUCCEEDED(appAssembliesAttempt->HResult) ? m_hr : appAssembliesAttempt->HResult, appAssembliesAttempt->Assembly, mvidMismatch ? (LPCWSTR)errorMsg : nullptr); } void ResolutionAttemptedOperation::TraceStage(Stage stage, HRESULT hr, BINDER_SPACE::Assembly *resultAssembly, const WCHAR *customError) @@ -246,7 +246,7 @@ namespace BinderTracing if (resultAssembly != nullptr) { resultAssembly->GetAssemblyName()->GetDisplayName(resultAssemblyName, AssemblyName::INCLUDE_VERSION | AssemblyName::INCLUDE_PUBLIC_KEY_TOKEN); - resultAssemblyPath = resultAssembly->GetPEImage()->GetPath(); + resultAssemblyPath.Set(resultAssembly->GetPEImage()->GetPath()); } Result result; @@ -258,7 +258,7 @@ namespace BinderTracing } else if (!m_exceptionMessage.IsEmpty()) { - errorMsg = m_exceptionMessage; + errorMsg.Set(m_exceptionMessage); result = Result::Exception; } else @@ -278,7 +278,7 @@ namespace BinderTracing result = Result::IncompatibleVersion; { - SString errorMsgUtf8(SString::Utf8, "Requested version"); + EString errorMsgUtf8("Requested version"); if (m_assemblyNameObject != nullptr) { const auto &reqVersion = m_assemblyNameObject->GetVersion(); @@ -289,7 +289,7 @@ namespace BinderTracing reqVersion->GetRevision()); } - errorMsgUtf8.AppendUTF8(" is incompatible with found version"); + errorMsgUtf8.Append(" is incompatible with found version"); if (resultAssembly != nullptr) { const auto &foundVersion = resultAssembly->GetAssemblyName()->GetVersion(); @@ -299,17 +299,17 @@ namespace BinderTracing foundVersion->GetBuild(), foundVersion->GetRevision()); } - errorMsg.Set(errorMsgUtf8.GetUnicode()); + errorMsg.Set(errorMsgUtf8.MoveToUnicode()); } break; case FUSION_E_REF_DEF_MISMATCH: result = Result::MismatchedAssemblyName; - errorMsg.Printf(W("Requested assembly name '%s' does not match found assembly name"), m_assemblyName.GetUnicode()); + errorMsg.Printf(W("Requested assembly name '%s' does not match found assembly name"), (LPCWSTR)m_assemblyName); if (resultAssembly != nullptr) { errorMsg.Append(W(" '")); - errorMsg.Append(resultAssemblyName.GetUnicode()); + errorMsg.Append(resultAssemblyName); errorMsg.Append(W("'")); } @@ -359,7 +359,7 @@ namespace BinderTracing else if (resultAssembly != nullptr) { result = Result::Success; - resultAssemblyPath = resultAssembly->GetPath(); + resultAssemblyPath.Set(resultAssembly->GetPath()); resultAssembly->GetDisplayName(resultAssemblyName); } else diff --git a/src/coreclr/binder/defaultassemblybinder.cpp b/src/coreclr/binder/defaultassemblybinder.cpp index 28157a11244cd0..24f0b598c9436c 100644 --- a/src/coreclr/binder/defaultassemblybinder.cpp +++ b/src/coreclr/binder/defaultassemblybinder.cpp @@ -141,7 +141,7 @@ HRESULT DefaultAssemblyBinder::BindUsingPEImage( /* in */ PEImage *pPEImage, // const SString& simpleName = pAssemblyName->GetSimpleName(); SimpleNameToFileNameMap* tpaMap = GetAppContext()->GetTpaList(); - if (tpaMap->LookupPtr(simpleName.GetUnicode()) != NULL) + if (tpaMap->LookupPtr(simpleName) != NULL) { // The simple name of the assembly being requested to be bound was found in the TPA list. // Now, perform the actual bind to see if the assembly was really in the TPA assembly list or not. diff --git a/src/coreclr/binder/inc/applicationcontext.hpp b/src/coreclr/binder/inc/applicationcontext.hpp index 44d9155180b917..71e4f3dcaab0fc 100644 --- a/src/coreclr/binder/inc/applicationcontext.hpp +++ b/src/coreclr/binder/inc/applicationcontext.hpp @@ -46,10 +46,9 @@ namespace BINDER_SPACE } static count_t Hash(const key_t &str) { - SString ssKey(SString::Literal, str); - return ssKey.HashCaseInsensitive(); + return SL(str).HashCaseInsensitive(); } - static BOOL Equals(const key_t &lhs, const key_t &rhs) { LIMITED_METHOD_CONTRACT; return (SString::_wcsicmp(lhs, rhs) == 0); } + static BOOL Equals(const key_t &lhs, const key_t &rhs) { LIMITED_METHOD_CONTRACT; return (StaticStringHelpers::_wcsicmp(lhs, rhs) == 0); } void OnDestructPerEntryCleanupAction(const SimpleNameToFileNameMapEntry & e) { @@ -115,8 +114,8 @@ namespace BINDER_SPACE FailureCache *m_pFailureCache; CRITSEC_COOKIE m_contextCS; - StringArrayList m_platformResourceRoots; - StringArrayList m_appPaths; + StringArrayList m_platformResourceRoots; + StringArrayList m_appPaths; SimpleNameToFileNameMap * m_pTrustedPlatformAssemblyMap; }; diff --git a/src/coreclr/binder/inc/assemblybindercommon.hpp b/src/coreclr/binder/inc/assemblybindercommon.hpp index b3b21587159288..0b7a963adbcd31 100644 --- a/src/coreclr/binder/inc/assemblybindercommon.hpp +++ b/src/coreclr/binder/inc/assemblybindercommon.hpp @@ -33,15 +33,15 @@ namespace BINDER_SPACE /* in */ bool excludeAppPaths, /* out */ Assembly **ppAssembly); - static HRESULT BindToSystem(/* in */ SString &systemDirectory, + static HRESULT BindToSystem(/* in */ SString &systemDirectory, /* out */ Assembly **ppSystemAssembly); static HRESULT BindToSystemSatellite(/* in */ SString &systemDirectory, /* in */ SString &simpleName, /* in */ SString &cultureName, - /* out */ Assembly **ppSystemAssembly); + /* out */ Assembly **ppSystemAssembly); - static HRESULT GetAssembly(/* in */ SString &assemblyPath, + static HRESULT GetAssembly(/* in */ SString &assemblyPath, /* in */ BOOL fIsInTPA, /* out */ Assembly **ppAssembly, /* in */ BundleFileLocation bundleFileLocation = BundleFileLocation::Invalid()); diff --git a/src/coreclr/binder/inc/assemblyhashtraits.hpp b/src/coreclr/binder/inc/assemblyhashtraits.hpp index 9c28151e1dbf4d..35e0038ddd75e7 100644 --- a/src/coreclr/binder/inc/assemblyhashtraits.hpp +++ b/src/coreclr/binder/inc/assemblyhashtraits.hpp @@ -29,7 +29,7 @@ namespace BINDER_SPACE typedef AssemblyName* key_t; - // GetKey, Equals and Hash can throw due to SString + // GetKey, Equals and Hash can throw due to EString static const bool s_NoThrow = false; static key_t GetKey(element_t pAssemblyEntry) diff --git a/src/coreclr/binder/textualidentityparser.cpp b/src/coreclr/binder/textualidentityparser.cpp index 64de57f4399e04..c7d73903fb168a 100644 --- a/src/coreclr/binder/textualidentityparser.cpp +++ b/src/coreclr/binder/textualidentityparser.cpp @@ -190,7 +190,7 @@ namespace BINDER_SPACE { UINT cbPublicKeyOrTokenBLOB = publicKeyOrTokenBLOB.GetSize(); WCHAR *pwzpublicKeyOrToken = - publicKeyOrToken.OpenUnicodeBuffer(cbPublicKeyOrTokenBLOB * 2); + publicKeyOrToken.OpenBuffer(cbPublicKeyOrTokenBLOB * 2); BinToUnicodeHex(publicKeyOrTokenBLOB, cbPublicKeyOrTokenBLOB, pwzpublicKeyOrToken); publicKeyOrToken.CloseBuffer(cbPublicKeyOrTokenBLOB * 2); diff --git a/src/coreclr/classlibnative/bcltype/system.cpp b/src/coreclr/classlibnative/bcltype/system.cpp index 2d517279fad6fa..2b26205ad91657 100644 --- a/src/coreclr/classlibnative/bcltype/system.cpp +++ b/src/coreclr/classlibnative/bcltype/system.cpp @@ -292,7 +292,7 @@ void SystemNative::GenericFailFast(STRINGREF refMesgString, EXCEPTIONREF refExce if (gc.refExceptionForWatsonBucketing != NULL) { GetExceptionMessage(gc.refExceptionForWatsonBucketing, msg); - argExceptionString = msg.GetUnicode(); + argExceptionString = msg; } Thread *pThread = GetThread(); diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index 564aa84cd687eb..190325cee44ddc 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -397,7 +397,7 @@ CompareUtf8(_In_ LPCUTF8 str1, _In_ LPCUTF8 str2, _In_ ULONG32 nameFlags) if (nameFlags & CLRDATA_BYNAME_CASE_INSENSITIVE) { // XXX Microsoft - Convert to Unicode? - return SString::_stricmp(str1, str2); + return StaticStringHelpers::_stricmp(str1, str2); } return strcmp(str1, str2); @@ -2303,7 +2303,7 @@ namespace serialization { namespace bin { // buffer. // - raw_deserialize() generates a value from its binary representation // in a buffer. - // Beyond simple types the APIs below support SString instances. SStrings + // Beyond simple types the APIs below support EString instances. EStrings // are stored as UTF8 strings. //======================================================================== @@ -2468,46 +2468,41 @@ namespace serialization { namespace bin { }; // - // Specialization for SString. - // SString serialization/deserialization is performed to/from a UTF8 + // Specialization for EString. + // EString serialization/deserialization is performed to/from a UTF8 // string. // template<> - class Traits + class Traits> { public: static FORCEINLINE size_t - raw_size(const SString & val) + raw_size(const EString & val) { - StackSString s; - val.ConvertToUTF8(s); // make sure to include the NULL terminator - return s.GetCount() + 1; + return val.GetCount() + 1; } static FORCEINLINE size_t - raw_serialize(BYTE* dest, size_t destSize, const SString & val) + raw_serialize(BYTE* dest, size_t destSize, const EString & val) { // instead of calling raw_size() we inline it here, so we can reuse // the UTF8 string obtained below as an argument to memcpy. - - StackSString s; - val.ConvertToUTF8(s); // make sure to include the NULL terminator - size_t cnt = s.GetCount() + 1; + size_t cnt = val.GetCount() + 1; if (destSize < cnt) { return ErrOverflow; } - memcpy_s(dest, destSize, s.GetUTF8NoConvert(), cnt); + memcpy_s(dest, destSize, (LPCUTF8)val, cnt); return cnt; } static FORCEINLINE size_t - raw_deserialize(SString & val, const BYTE* src, size_t srcSize) + raw_deserialize(EString & val, const BYTE* src, size_t srcSize) { size_t cnt = strnlen((LPCUTF8)src, srcSize) + 1; @@ -2516,11 +2511,7 @@ namespace serialization { namespace bin { { return ErrOverflow; } - - // a literal SString avoids a new allocation + copy - SString sUtf8(SString::Utf8Literal, (LPCUTF8) src); - sUtf8.ConvertToUnicode(val); - + val.Set((LPCUTF8)src); return cnt; } @@ -2528,11 +2519,11 @@ namespace serialization { namespace bin { #ifndef TARGET_UNIX // - // Specialization for SString-derived classes (like SStrings) + // Specialization for EString-derived classes (like EStrings) // template - class Traits::value>::type> - : public Traits + class Traits, T>::value>::type> + : public Traits> { }; #endif // !TARGET_UNIX @@ -2691,9 +2682,9 @@ class DacEENamesStreamable { private: // the hash map storing the interesting mappings of EE* -> Names - MapSHash< TADDR, SString, + MapSHash< TADDR, EString, NoRemoveSHashTraits < - NonDacAwareSHashTraits< MapSHashTraits > + NonDacAwareSHashTraits< MapSHashTraits > > > > m_hash; Reserve_Fnptr m_reserveFn; @@ -2740,7 +2731,7 @@ class DacEENamesStreamable // as a micro-optimization convert to Utf8 here as both raw_size and // raw_serialize are optimized for Utf8... - StackSString seeName; + StackEString seeName; eeName.ConvertToUTF8(seeName); DWORD size = (DWORD)(serialization::bin::raw_size(taEE) + @@ -2750,7 +2741,7 @@ class DacEENamesStreamable if (m_reserveFn(size, m_writeState)) { // if there's still space cache the entry in m_hash - m_hash.AddOrReplace(KeyValuePair(taEE, seeName)); + m_hash.AddOrReplace(KeyValuePair>(taEE, seeName)); return true; } else @@ -2763,7 +2754,11 @@ class DacEENamesStreamable // MethodDesc*) bool FindEEName(TADDR taEE, SString & eeName) const { - return m_hash.Lookup(taEE, &eeName) == TRUE; + StackEString eeNameUTF8; + eeName.ConvertToUTF8(eeNameUTF8); + bool found = m_hash.Lookup(taEE, &eeNameUTF8) == TRUE; + eeNameUTF8.ConvertToUnicode(eeName); + return found; } void Clear() @@ -2804,13 +2799,13 @@ class DacEENamesStreamable for (size_t i = 0; i < hdr.cnt; ++i) { TADDR taEE; - SString eeName; + EString eeName; in >> taEE >> eeName; if (!in) return E_FAIL; - m_hash.AddOrReplace(KeyValuePair(taEE, eeName)); + m_hash.AddOrReplace(KeyValuePair>(taEE, eeName)); } return S_OK; @@ -5659,7 +5654,7 @@ ClrDataAccess::GetFullMethodName( if (symbol) { // Copy as much as we can and truncate the rest. - wcsncpy_s(symbol, symbolChars, s.GetUnicode(), _TRUNCATE); + wcsncpy_s(symbol, symbolChars, s, _TRUNCATE); } if (symbolLen) diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index 6ae350448755d5..2e2546c3e22a97 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -649,7 +649,7 @@ void DacDbiInterfaceImpl::GetAppDomainFullName( AppDomain * pAppDomain = vmAppDomain.GetDacPtr(); // Get the AppDomain name from the VM without changing anything - // We might be able to simplify this, eg. by returning an SString. + // We might be able to simplify this, eg. by returning an EString. bool fIsUtf8; PVOID pRawName = pAppDomain->GetFriendlyNameNoSet(&fIsUtf8); @@ -4218,8 +4218,8 @@ void DacDbiInterfaceImpl::GetModuleSimpleName(VMPTR_Module vmModule, IStringHold Module * pModule = vmModule.GetDacPtr(); LPCUTF8 szNameUtf8 = pModule->GetSimpleName(); - SString convert(SString::Utf8, szNameUtf8); - IfFailThrow(pStrFilename->AssignCopy(convert.GetUnicode())); + MAKE_WIDEPTR_FROMUTF8(convert, szNameUtf8); + IfFailThrow(pStrFilename->AssignCopy(convert)); } HRESULT DacDbiInterfaceImpl::IsModuleMapped(VMPTR_Module pModule, OUT BOOL *isModuleMapped) diff --git a/src/coreclr/debug/daccess/enummem.cpp b/src/coreclr/debug/daccess/enummem.cpp index 0fda825fe90a34..b8a171c1478560 100644 --- a/src/coreclr/debug/daccess/enummem.cpp +++ b/src/coreclr/debug/daccess/enummem.cpp @@ -578,7 +578,7 @@ HRESULT ClrDataAccess::DumpManagedStackTraceStringObject(CLRDataEnumMemoryFlags _ASSERTE(traceCharCount <= orefStackTrace->GetStringLength()); // fill the rest of the string with \0 - WCHAR *buffer = stackTrace.OpenUnicodeBuffer(orefStackTrace->GetStringLength()); + WCHAR *buffer = stackTrace.OpenBuffer(orefStackTrace->GetStringLength()); memset(buffer + traceCharCount, 0, sizeof(WCHAR) * (orefStackTrace->GetStringLength() - traceCharCount)); // replace the string diff --git a/src/coreclr/debug/daccess/inspect.cpp b/src/coreclr/debug/daccess/inspect.cpp index 70753777a96cc9..842f84e8b8936e 100644 --- a/src/coreclr/debug/daccess/inspect.cpp +++ b/src/coreclr/debug/daccess/inspect.cpp @@ -2306,7 +2306,7 @@ ClrDataTypeDefinition::GetName( { StackSString ssClassNameBuf; m_typeHandle.GetName(ssClassNameBuf); - if (wcsncpy_s(nameBuf, bufLen, ssClassNameBuf.GetUnicode(), _TRUNCATE) == STRUNCATE) + if (wcsncpy_s(nameBuf, bufLen, ssClassNameBuf, _TRUNCATE) == STRUNCATE) { status = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } @@ -3474,7 +3474,7 @@ ClrDataTypeInstance::GetName( PAL_CPP_ENDTRY #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS - if (wcsncpy_s(nameBuf, bufLen, ssClassNameBuf.GetUnicode(), _TRUNCATE) == STRUNCATE) + if (wcsncpy_s(nameBuf, bufLen, ssClassNameBuf, _TRUNCATE) == STRUNCATE) { status = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 35aac26d72b222..c3e5568198cc14 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -1433,7 +1433,7 @@ ClrDataAccess::GetMethodDescName(CLRDATA_ADDRESS methodDesc, unsigned int count, if (SUCCEEDED(hr)) { - const WCHAR *val = str.GetUnicode(); + const WCHAR *val = (LPCWSTR)str; if (pNeeded) *pNeeded = str.GetCount() + 1; @@ -1554,7 +1554,7 @@ ClrDataAccess::GetObjectClassName(CLRDATA_ADDRESS obj, unsigned int count, _Inou { StackSString s; TypeString::AppendType(s, TypeHandle(mt), TypeString::FormatNamespace|TypeString::FormatFullInst); - const WCHAR *val = s.GetUnicode(); + const WCHAR *val = (LPCWSTR)s; if (pNeeded) *pNeeded = s.GetCount() + 1; @@ -1842,7 +1842,7 @@ ClrDataAccess::GetMethodTableName(CLRDATA_ADDRESS mt, unsigned int count, _Inout } else { - const WCHAR *val = s.GetUnicode(); + const WCHAR *val = (LPCWSTR)s; if (pNeeded) *pNeeded = s.GetCount() + 1; @@ -2115,7 +2115,7 @@ ClrDataAccess::GetPEFileName(CLRDATA_ADDRESS addr, unsigned int count, _Inout_up if (fileName) { - wcsncpy_s(fileName, count, displayName.GetUnicode(), _TRUNCATE); + wcsncpy_s(fileName, count, (LPCWSTR)displayName, _TRUNCATE); if (count < len) len = count; @@ -2665,7 +2665,7 @@ ClrDataAccess::GetAssemblyName(CLRDATA_ADDRESS assembly, unsigned int count, _In StackSString displayName; pAssembly->GetPEAssembly()->GetDisplayName(displayName, 0); - const WCHAR *val = displayName.GetUnicode(); + const WCHAR *val = (LPCWSTR)displayName; if (pNeeded) *pNeeded = displayName.GetCount() + 1; diff --git a/src/coreclr/debug/di/cordb.cpp b/src/coreclr/debug/di/cordb.cpp index 92337408c390be..5a0ccd91fbd65a 100644 --- a/src/coreclr/debug/di/cordb.cpp +++ b/src/coreclr/debug/di/cordb.cpp @@ -229,7 +229,7 @@ BOOL WINAPI DbgDllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) WszGetModuleFileName(hInstance, rcFile); LOG((LF_CORDB, LL_INFO10000, "DI::DbgDllMain: load right side support from file '%s'\n", - rcFile.GetUnicode())); + (LPCWSTR)rcFile)); } #endif diff --git a/src/coreclr/debug/di/eventredirectionpipeline.cpp b/src/coreclr/debug/di/eventredirectionpipeline.cpp index 382319dc8fe886..7e9a8bf2648dca 100644 --- a/src/coreclr/debug/di/eventredirectionpipeline.cpp +++ b/src/coreclr/debug/di/eventredirectionpipeline.cpp @@ -109,7 +109,7 @@ HRESULT EventRedirectionPipeline::AttachDebuggerToTarget(LPCWSTR szOptions, DWOR m_pBlock->m_versionCookie = EVENT_REDIRECTION_CURRENT_VERSION; s.Printf(m_CommonParams, GetCurrentProcessId(), m_pBlock, szOptions, pidTarget); - lpCommandLine = s.GetUnicode(); + lpCommandLine = s; lpApplicationName = m_DebuggerCmd; // eg, something like L"c:\\debuggers_amd64\\windbg.exe"; diff --git a/src/coreclr/debug/di/module.cpp b/src/coreclr/debug/di/module.cpp index ad5cf926c4eef6..0b261cd23dbe86 100644 --- a/src/coreclr/debug/di/module.cpp +++ b/src/coreclr/debug/di/module.cpp @@ -2566,7 +2566,7 @@ HRESULT CordbModule::CreateReaderForInMemorySymbols(REFIID riid, void** ppObj) InlineSString<_MAX_PATH> ssBuf; IfFailThrow(GetClrModuleDirectory(ssBuf)); IfFailThrow(FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS, - ssBuf.GetUnicode(), + (LPCWSTR)ssBuf, IID_ISymUnmanagedBinder, (void**)&pBinder, NULL)); diff --git a/src/coreclr/debug/di/symbolinfo.cpp b/src/coreclr/debug/di/symbolinfo.cpp index 37cff967d02fea..1454140792b7ee 100644 --- a/src/coreclr/debug/di/symbolinfo.cpp +++ b/src/coreclr/debug/di/symbolinfo.cpp @@ -179,7 +179,6 @@ HRESULT SymbolInfo::SetMethodProps(mdToken method, mdToken cls, LPCWSTR wszName) m_LastMethod.method=method; m_LastMethod.cls=cls; m_LastMethod.wszName=wszName; - m_LastMethod.wszName.Normalize(); } EX_CATCH_HRESULT(hr) return hr; diff --git a/src/coreclr/debug/di/symbolinfo.h b/src/coreclr/debug/di/symbolinfo.h index 5b1291f4cfe598..76b4058d5963fd 100644 --- a/src/coreclr/debug/di/symbolinfo.h +++ b/src/coreclr/debug/di/symbolinfo.h @@ -39,7 +39,7 @@ class SymbolInfo: IMetaDataEmit, IMetaDataImport SString wszName; mdTypeDef tkEnclosing; ClassProps(mdToken c, DWORD f, LPCWSTR name, mdToken tkE): - cls(c),flags(f),wszName(name),tkEnclosing(tkE) {wszName.Normalize();}; + cls(c),flags(f),wszName(name),tkEnclosing(tkE) {} mdTypeDef GetKey() {return cls;}; static COUNT_T Hash(mdTypeDef key) {return key;}; diff --git a/src/coreclr/debug/ee/controller.cpp b/src/coreclr/debug/ee/controller.cpp index 6be73bc8be21a0..4fefa3ecc71a78 100644 --- a/src/coreclr/debug/ee/controller.cpp +++ b/src/coreclr/debug/ee/controller.cpp @@ -7386,7 +7386,7 @@ void DebuggerStepper::TriggerMethodEnter(Thread * thread, // at native offset 0 (before the prolog) and before we get the TME. That means if // we do get the TME, then there was no stub-manager to find us. - SString sLog; + EString sLog; StubManager::DbgGetLog(&sLog); // Assert b/c the Stub-manager should have caught us first. @@ -7398,14 +7398,14 @@ void DebuggerStepper::TriggerMethodEnter(Thread * thread, "See http://team/sites/clrdev/Devdocs/StubManagers.rtf for more information on StubManagers.\n" "Stepper this=0x%p, startMethod='%s::%s'\n" "---------------------------------\n" - "Stub manager log:\n%S" + "Stub manager log:\n%s" "\n" "The thread is now in managed method '%s::%s'.\n" "---------------------------------\n", this, ((m_StepInStartMethod == NULL) ? "unknown" : m_StepInStartMethod->m_pszDebugClassName), ((m_StepInStartMethod == NULL) ? "unknown" : m_StepInStartMethod->m_pszDebugMethodName), - sLog.GetUnicode(), + (LPCUTF8)sLog, pDesc->m_pszDebugClassName, pDesc->m_pszDebugMethodName )); } diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index 032e96457ecc1b..4f845d1ad78b09 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -6876,7 +6876,7 @@ HRESULT Debugger::EDAHelper(PROCESS_INFORMATION *pProcessInfo) bool fHasDebugger = GetCompleteDebuggerLaunchString(&strDbgCommand); if (fHasDebugger) { - wszDbgCommand = strDbgCommand.GetUnicode(); + wszDbgCommand = (LPCWSTR)strDbgCommand; _ASSERTE(wszDbgCommand != NULL); // would have thrown on oom. LOG((LF_CORDB, LL_INFO10000, "D::EDA: launching with command [%S]\n", wszDbgCommand)); @@ -8710,11 +8710,11 @@ int Debugger::NotifyUserOfFault(bool userBreakpoint, DebuggerLaunchSetting dls) } SString text; - text.LoadResource(CCompRC::Error, resIDMessage); + LoadResource(text, CCompRC::Error, resIDMessage); // Format message string using optional parameters StackSString formattedMessage; - formattedMessage.Printf((LPWSTR)text.GetUnicode(), pid, pid, tid, tid); + formattedMessage.Printf((LPCWSTR)text, pid, pid, tid, tid); { // Another potential hang. This may get run on the helper if we have a stack overflow. @@ -8722,7 +8722,7 @@ int Debugger::NotifyUserOfFault(bool userBreakpoint, DebuggerLaunchSetting dls) // lock is very small. SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE; - result = NotifyUserOfFaultMessageBox(W("Application Error"), (LPWSTR)formattedMessage.GetUnicode(), flags); + result = NotifyUserOfFaultMessageBox(W("Application Error"), (LPCWSTR)formattedMessage, flags); } } @@ -14033,7 +14033,7 @@ void SetLSBufferFromSString(Ls_Rs_StringBuffer * pBuffer, SString & str) // Copy string contents (+1 for null terminator) into a LS_RS_Buffer. // Then the RS can pull it out as a null-terminated string. pBuffer->SetLsData( - (BYTE*) str.GetUnicode(), + (BYTE*) (LPCWSTR)str, (str.GetCount() +1)* sizeof(WCHAR) ); } @@ -14168,7 +14168,7 @@ void Debugger::SendMDANotification( if (ThisIsHelperThreadWorker()) { CONSISTENCY_CHECK_MSGF(false, ("MDA '%s' fired on *helper* thread.\r\nDesc:%s", - szName->GetUnicode(), szDescription->GetUnicode() + (LPCWSTR)*szName, (LPCWSTR)*szDescription )); // If for some reason we're wrong about the assert above, we'll just ignore the MDA (rather than potentially deadlock) @@ -14326,7 +14326,7 @@ void Debugger::SendRawLogMessage( pAppDomain); ipce->FirstLogMessage.iLevel = iLevel; - ipce->FirstLogMessage.szCategory.SetString(pCategory->GetUnicode()); + ipce->FirstLogMessage.szCategory.SetString(*pCategory); SetLSBufferFromSString(&ipce->FirstLogMessage.szContent, *pMessage); m_pRCThread->SendIPCEvent(); diff --git a/src/coreclr/debug/ee/debuggermessagebox.cpp b/src/coreclr/debug/ee/debuggermessagebox.cpp index 6ee2311974e04b..1a7c2baa666de5 100644 --- a/src/coreclr/debug/ee/debuggermessagebox.cpp +++ b/src/coreclr/debug/ee/debuggermessagebox.cpp @@ -122,7 +122,7 @@ static int UtilMessageBoxNonLocalized( 0, // category zero 1024, // event identifier NULL, // no user security identifier - message.GetUnicode()); + message); WszOutputDebugString(lpTitle); WszOutputDebugString(lpText); diff --git a/src/coreclr/debug/ee/rcthread.cpp b/src/coreclr/debug/ee/rcthread.cpp index c2d38028ebf30d..3c8b5c4f841b4a 100644 --- a/src/coreclr/debug/ee/rcthread.cpp +++ b/src/coreclr/debug/ee/rcthread.cpp @@ -545,22 +545,11 @@ static LONG _debugFilter(LPEXCEPTION_POINTERS ep, PVOID pv) // We should never AV here. In a debug build, throw up an assert w/ lots of useful (private) info. #ifdef _DEBUG { - // We can't really use SStrings on the helper thread; though if we're at this point, we've already died. + // We can't really use EStrings on the helper thread; though if we're at this point, we've already died. // So go ahead and risk it and use them anyways. - SString sStack; - StackScratchBuffer buffer; + EString sStack; GetStackTraceAtContext(sStack, ep->ContextRecord); - const CHAR *string = NULL; - - EX_TRY - { - string = sStack.GetANSI(buffer); - } - EX_CATCH - { - string = "*Could not retrieve stack*"; - } - EX_END_CATCH(RethrowTerminalExceptions); + const CHAR *string = sStack; CONSISTENCY_CHECK_MSGF(false, ("Unhandled exception on the helper thread.\nEvent=%s(0x%p)\nCode=0x%0x, Ip=0x%p, .cxr=%p, .exr=%p.\n pid=0x%x (%d), tid=0x%x (%d).\n-----\nStack of exception:\n%s\n----\n", diff --git a/src/coreclr/dlls/mscoree/mscoree.cpp b/src/coreclr/dlls/mscoree/mscoree.cpp index c985b88ab30c2e..0b0ad1c8306e4f 100644 --- a/src/coreclr/dlls/mscoree/mscoree.cpp +++ b/src/coreclr/dlls/mscoree/mscoree.cpp @@ -292,7 +292,7 @@ HRESULT SetInternalSystemDirectory() wzSystemDirectory.Set(W('\0')); } - pSystemDirectory = wzSystemDirectory.GetCopyOfUnicodeString(); + pSystemDirectory = wzSystemDirectory.CreateCopyOfString(); if (pSystemDirectory == NULL) { hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); diff --git a/src/coreclr/ilasm/grammar_after.cpp b/src/coreclr/ilasm/grammar_after.cpp index 9df0cc05ec7f04..f6ed580c17637b 100644 --- a/src/coreclr/ilasm/grammar_after.cpp +++ b/src/coreclr/ilasm/grammar_after.cpp @@ -986,7 +986,7 @@ int yylex() { delete [] wzFile; - wzFile = wzFullName.GetCopyOfUnicodeString(); + wzFile = wzFullName.CreateCopyOfString(); } } diff --git a/src/coreclr/ilasm/main.cpp b/src/coreclr/ilasm/main.cpp index 146e8640b3cb47..b6dc8026a9e344 100644 --- a/src/coreclr/ilasm/main.cpp +++ b/src/coreclr/ilasm/main.cpp @@ -620,7 +620,7 @@ extern "C" int _cdecl wmain(int argc, _In_ WCHAR **argv) PathString wzIncludePathBuffer; if (0 != WszGetEnvironmentVariable(W("ILASM_INCLUDE"), wzIncludePathBuffer)) { - wzIncludePath = wzIncludePathBuffer.GetCopyOfUnicodeString(); + wzIncludePath = wzIncludePathBuffer.CreateCopyOfString(); } } diff --git a/src/coreclr/inc/bundle.h b/src/coreclr/inc/bundle.h index 3d55a54b3515b4..f6e2a18bd4e8d4 100644 --- a/src/coreclr/inc/bundle.h +++ b/src/coreclr/inc/bundle.h @@ -32,7 +32,7 @@ struct BundleFileLocation static BundleFileLocation Invalid() { LIMITED_METHOD_CONTRACT; return BundleFileLocation(); } - const SString &Path() const; + const EString &Path() const; bool IsValid() const { LIMITED_METHOD_CONTRACT; return Offset != 0; } }; @@ -41,10 +41,10 @@ class Bundle { public: Bundle(LPCSTR bundlePath, BundleProbeFn *probe); - BundleFileLocation Probe(const SString& path, bool pathIsBundleRelative = false) const; + BundleFileLocation Probe(const EString& path, bool pathIsBundleRelative = false) const; - const SString &Path() const { LIMITED_METHOD_CONTRACT; return m_path; } - const SString &BasePath() const { LIMITED_METHOD_CONTRACT; return m_basePath; } + const EString &Path() const { LIMITED_METHOD_CONTRACT; return m_path; } + const EString &BasePath() const { LIMITED_METHOD_CONTRACT; return m_basePath; } static Bundle* AppBundle; // The BundleInfo for the current app, initialized by coreclr_initialize. static bool AppIsBundle() { LIMITED_METHOD_CONTRACT; return AppBundle != nullptr; } @@ -52,10 +52,10 @@ class Bundle private: - SString m_path; // The path to single-file executable + EString m_path; // The path to single-file executable BundleProbeFn *m_probe; - SString m_basePath; // The prefix to denote a path within the bundle + EString m_basePath; // The prefix to denote a path within the bundle COUNT_T m_basePathLength; }; diff --git a/src/coreclr/inc/check.h b/src/coreclr/inc/check.h index c033965d400f06..ef7f052a38cfd5 100644 --- a/src/coreclr/inc/check.h +++ b/src/coreclr/inc/check.h @@ -60,7 +60,10 @@ // NOTE: you should NEVER use the CHECK class API directly - use the macros below. //-------------------------------------------------------------------------------- -class SString; +template +class EString; + +struct EncodingUTF8; class CHECK { @@ -147,7 +150,7 @@ class CHECK private: #ifdef _DEBUG - static LPCSTR AllocateDynamicMessage(const SString &s); + static LPCSTR AllocateDynamicMessage(const EString &s); #endif }; diff --git a/src/coreclr/inc/clrhost.h b/src/coreclr/inc/clrhost.h index 08721c3b5e0e46..4c122545580fed 100644 --- a/src/coreclr/inc/clrhost.h +++ b/src/coreclr/inc/clrhost.h @@ -23,6 +23,11 @@ #include "debugreturn.h" #include "yieldprocessornormalized.h" +template +class EString; +struct EncodingUnicode; +using SString = EString; + #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) #define _DEBUG_IMPL 1 #endif diff --git a/src/coreclr/inc/corhlprpriv.h b/src/coreclr/inc/corhlprpriv.h index 2c8372860ba2e2..bb17241bc2b606 100644 --- a/src/coreclr/inc/corhlprpriv.h +++ b/src/coreclr/inc/corhlprpriv.h @@ -229,6 +229,12 @@ class CQuickMemoryBase // Convert UTF8 string to UNICODE string, optimized for speed HRESULT ConvertUtf8_UnicodeNoThrow(const char * utf8str) { + if (utf8str == nullptr) + { + WCHAR* buffer = (WCHAR*)AllocNoThrow(sizeof(WCHAR)); + buffer[0] = W('\0'); + return S_OK; + } bool allAscii; DWORD length; @@ -254,9 +260,15 @@ class CQuickMemoryBase // Convert UTF8 string to UNICODE string, optimized for speed void ConvertUtf8_Unicode(const char * utf8str) { + if (utf8str == nullptr) + { + WCHAR* buffer = (WCHAR*)AllocNoThrow(sizeof(WCHAR)); + buffer[0] = W('\0'); + return; + } bool allAscii; DWORD length; - + HRESULT hr = FString::Utf8_Unicode_Length(utf8str, & allAscii, & length); if (SUCCEEDED(hr)) @@ -275,6 +287,12 @@ class CQuickMemoryBase // Convert UNICODE string to UTF8 string, optimized for speed void ConvertUnicode_Utf8(const WCHAR * pString) { + if (pString == nullptr) + { + char* buffer = (char*)AllocNoThrow(sizeof(char)); + buffer[0] = '\0'; + return; + } bool allAscii; DWORD length; diff --git a/src/coreclr/inc/daccess.h b/src/coreclr/inc/daccess.h index af91b845bb735e..c11194f0fcc086 100644 --- a/src/coreclr/inc/daccess.h +++ b/src/coreclr/inc/daccess.h @@ -809,7 +809,11 @@ HRESULT DacVirtualUnwind(ULONG32 threadId, PT_CONTEXT context, PT_KNONVOLATILE_C #endif // TARGET_UNIX #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS -class SString; +template +class EString; +struct EncodingUnicode; +struct EncodingUTF8; +using SString = EString; void DacMdCacheAddEEName(TADDR taEE, const SString& ssEEName); bool DacMdCacheGetEEName(TADDR taEE, SString & ssEEName); #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS diff --git a/src/coreclr/inc/dacvars.h b/src/coreclr/inc/dacvars.h index 68ec3af418f005..ec2c303a83735c 100644 --- a/src/coreclr/inc/dacvars.h +++ b/src/coreclr/inc/dacvars.h @@ -129,7 +129,9 @@ DEFINE_DACVAR(DWORD, dac__g_debuggerWordTLSIndex, g_debuggerWordTLSIndex) #endif DEFINE_DACVAR(DWORD, dac__g_TlsIndex, g_TlsIndex) -DEFINE_DACVAR(PTR_SString, SString__s_Empty, SString::s_Empty) +DEFINE_DACVAR(PTR_SString, StaticStringHelpers__s_EmptyUnicode, StaticStringHelpers::s_EmptyUnicode) +DEFINE_DACVAR(PTR_EString, StaticStringHelpers__s_EmptyUtf8, StaticStringHelpers::s_EmptyUtf8) +DEFINE_DACVAR(PTR_EString, StaticStringHelpers__s_EmptyAscii, StaticStringHelpers::s_EmptyAscii) DEFINE_DACVAR(INT32, ArrayBase__s_arrayBoundsZero, ArrayBase::s_arrayBoundsZero) diff --git a/src/coreclr/inc/debugmacros.h b/src/coreclr/inc/debugmacros.h index aa99719399e16e..a837916e7faf54 100644 --- a/src/coreclr/inc/debugmacros.h +++ b/src/coreclr/inc/debugmacros.h @@ -17,14 +17,17 @@ #undef _ASSERTE #undef VERIFY +template +class EString; + +struct EncodingASCII; + #ifdef __cplusplus extern "C" { #endif // __cplusplus #if defined(_DEBUG) - -class SString; -bool GetStackTraceAtContext(SString & s, struct _CONTEXT * pContext); +bool GetStackTraceAtContext(EString & s, struct _CONTEXT * pContext); bool _DbgBreakCheck(LPCSTR szFile, int iLine, LPCSTR szExpr, BOOL fConstrained = FALSE); diff --git a/src/coreclr/inc/eventtracebase.h b/src/coreclr/inc/eventtracebase.h index 012af669ac67a9..1c9065dae7e569 100644 --- a/src/coreclr/inc/eventtracebase.h +++ b/src/coreclr/inc/eventtracebase.h @@ -681,7 +681,9 @@ class MethodDesc; class MethodTable; class BaseDomain; class AppDomain; -class SString; +struct EncodingUTF8; +template +class EString; class CrawlFrame; class LoaderAllocator; class AssemblyLoaderAllocator; @@ -899,9 +901,9 @@ namespace ETW BOOL fSendILToNativeMapEvent, BOOL fGetCodeIds); static VOID SendEventsForNgenMethods(Module *pModule, DWORD dwEventOptions); - static VOID SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL); + static VOID SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, EString *methodName=NULL, EString *methodSignature=NULL); static VOID SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, PCODE pNativeCodeStartAddress, ReJITID ilCodeId); - static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, PrepareCodeConfig *pConfig = NULL); + static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, EString *methodName=NULL, EString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, PrepareCodeConfig *pConfig = NULL); static VOID SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHelperSize, LPCWSTR pHelperName); static VOID SendMethodDetailsEvent(MethodDesc *pMethodDesc); public: @@ -932,8 +934,8 @@ namespace ETW static VOID GetR2RGetEntryPointStart(MethodDesc *pMethodDesc); static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint); - static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature); - static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig); + static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, EString *methodName, EString *methodSignature); + static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, EString *methodName, EString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig); static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName); static VOID StubsInitialized(PVOID *pHelperStartAddress, PVOID *pHelperNames, LONG ulNoOfHelpers); static VOID MethodRestored(MethodDesc * pMethodDesc); @@ -944,8 +946,8 @@ namespace ETW public: static VOID GetR2RGetEntryPointStart(MethodDesc *pMethodDesc) {}; static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint) {}; - static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature); - static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig); + static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, EString *methodName, EString *methodSignature); + static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, EString *methodName, EString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig); static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName) {}; static VOID StubsInitialized(PVOID *pHelperStartAddress, PVOID *pHelperNames, LONG ulNoOfHelpers) {}; static VOID MethodRestored(MethodDesc * pMethodDesc) {}; diff --git a/src/coreclr/inc/ex.h b/src/coreclr/inc/ex.h index 01e405541dfdeb..d9cf2c0510e644 100644 --- a/src/coreclr/inc/ex.h +++ b/src/coreclr/inc/ex.h @@ -408,7 +408,7 @@ class HRMsgException : public HRException friend bool DebugIsEECxxExceptionPointer(void* pv); protected: - SString m_msg; + SString m_msg; public: HRMsgException(); @@ -573,7 +573,7 @@ class OutOfMemoryException : public Exception } HRESULT GetHR() {LIMITED_METHOD_DAC_CONTRACT; return E_OUTOFMEMORY; } - void GetMessage(SString &result) { WRAPPER_NO_CONTRACT; result.SetASCII("Out Of Memory"); } + void GetMessage(SString &result) { WRAPPER_NO_CONTRACT; result.Set(W("Out Of Memory")); } virtual Exception *Clone(); diff --git a/src/coreclr/inc/formattype.cpp b/src/coreclr/inc/formattype.cpp index 7100fe285ab141..443f6014b3fb5c 100644 --- a/src/coreclr/inc/formattype.cpp +++ b/src/coreclr/inc/formattype.cpp @@ -985,7 +985,7 @@ const char* TrySigUncompressAndDumpSimpleNativeType( PCCOR_SIGNATURE pData, // [IN] compressed data ULONG *pDataOut, // [OUT] the expanded *pData ULONG &cbCur, - SString &buf) + EString &buf) { const char* sz = NULL; ULONG ulSize = CorSigUncompressData(pData, pDataOut); @@ -1053,7 +1053,7 @@ const char* TrySigUncompressAndDumpSimpleNativeType( bool TrySigUncompress(PCCOR_SIGNATURE pData, // [IN] compressed data ULONG *pDataOut, // [OUT] the expanded *pData ULONG &cbCur, - SString &buf) + EString &buf) { ULONG ulSize = CorSigUncompressData(pData, pDataOut); if (ulSize == (ULONG)-1) @@ -1086,7 +1086,7 @@ char* DumpMarshaling(IMDInternalImport* pImport, PCCOR_SIGNATURE pSigNativeType = NULL; ULONG cbNativeType = 0; - SString buf; + EString buf; if (RidFromToken(tok) && SUCCEEDED(pImport->GetFieldMarshal( // return error if no native type associate with the token tok, // [IN] given fielddef @@ -1114,7 +1114,7 @@ char* DumpMarshaling(IMDInternalImport* pImport, break; case NATIVE_TYPE_SAFEARRAY: sz = ""; - buf.AppendASCII(KEYWORD(" safearray")); + buf.Append(KEYWORD(" safearray")); ulData = VT_EMPTY; if (cbCur < cbNativeType) { @@ -1166,7 +1166,7 @@ char* DumpMarshaling(IMDInternalImport* pImport, case VT_CLSID: sz=" clsid"; break; default: sz=NULL; break; } - if(sz) buf.AppendASCII(KEYWORD(sz)); + if(sz) buf.Append(KEYWORD(sz)); else { // buf.AppendPrintf(ERRORMSG(" [ILLEGAL VARIANT TYPE 0x%X]"),ulData & VT_TYPEMASK); @@ -1184,7 +1184,7 @@ char* DumpMarshaling(IMDInternalImport* pImport, case VT_ARRAY|VT_VECTOR: sz = "[] vector"; break; case VT_BYREF|VT_ARRAY|VT_VECTOR: sz = "&[] vector"; break; } - buf.AppendASCII(KEYWORD(sz)); + buf.Append(KEYWORD(sz)); sz=""; // Extract the user defined sub type name. @@ -1220,29 +1220,29 @@ char* DumpMarshaling(IMDInternalImport* pImport, case NATIVE_TYPE_FIXEDSYSSTRING: { sz = ""; - buf.AppendASCII(KEYWORD(" fixed sysstring")); - buf.AppendASCII(" ["); + buf.Append(KEYWORD(" fixed sysstring")); + buf.Append(" ["); if (cbCur < cbNativeType) { if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) goto error; buf.AppendPrintf("%d",ulData); } - buf.AppendASCII("]"); + buf.Append("]"); } break; case NATIVE_TYPE_FIXEDARRAY: { sz = ""; - buf.AppendASCII(KEYWORD(" fixed array")); - buf.AppendASCII(" ["); + buf.Append(KEYWORD(" fixed array")); + buf.Append(" ["); if (cbCur < cbNativeType) { if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) goto error; buf.AppendPrintf("%d",ulData); } - buf.AppendASCII("]"); + buf.Append("]"); if (cbCur < cbNativeType) { sz = TrySigUncompressAndDumpSimpleNativeType(&pSigNativeType[cbCur], &ulData, cbCur, buf); @@ -1253,13 +1253,13 @@ char* DumpMarshaling(IMDInternalImport* pImport, break; case NATIVE_TYPE_INTF: - buf.AppendASCII(KEYWORD(" interface")); + buf.Append(KEYWORD(" interface")); goto DumpIidParamIndex; case NATIVE_TYPE_IUNKNOWN: - buf.AppendASCII(KEYWORD(" iunknown")); + buf.Append(KEYWORD(" iunknown")); goto DumpIidParamIndex; case NATIVE_TYPE_IDISPATCH: - buf.AppendASCII(KEYWORD(" idispatch")); + buf.Append(KEYWORD(" idispatch")); DumpIidParamIndex: sz = " "; if (cbCur < cbNativeType) @@ -1278,8 +1278,8 @@ char* DumpMarshaling(IMDInternalImport* pImport, BOOL fFourStrings = FALSE; sz = ""; - buf.AppendASCII(KEYWORD(" custom")); - buf.AppendASCII(" ("); + buf.Append(KEYWORD(" custom")); + buf.Append(" ("); // Extract the typelib GUID. strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength); cbCur += ByteCountLength; @@ -1298,7 +1298,7 @@ char* DumpMarshaling(IMDInternalImport* pImport, } if(cbCur >= cbNativeType) { - // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); + // buf.Append(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); buf.Clear(); goto error; } @@ -1323,11 +1323,11 @@ char* DumpMarshaling(IMDInternalImport* pImport, VDELETE(strTemp); } } - else buf.AppendASCII("\"\","); + else buf.Append("\"\","); } if(cbCur >= cbNativeType) { - // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); + // buf.Append(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); buf.Clear(); goto error; } @@ -1350,10 +1350,10 @@ char* DumpMarshaling(IMDInternalImport* pImport, VDELETE(strTemp); } } - else buf.AppendASCII("\"\","); + else buf.Append("\"\","); if(cbCur >= cbNativeType) { - // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); + // buf.Append(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); buf.Clear(); goto error; } @@ -1365,7 +1365,7 @@ char* DumpMarshaling(IMDInternalImport* pImport, if(cbCur+strLen > cbNativeType) { - // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); + // buf.Append(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); buf.Clear(); goto error; } @@ -1379,12 +1379,12 @@ char* DumpMarshaling(IMDInternalImport* pImport, memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen); strTemp[strLen] = 0; - buf.AppendASCII("\""); + buf.Append("\""); // Copy the cookie string and transform the embedded nulls into \0's. for (int i = 0; i < strLen - 1; i++, cbCur++) { if (strTemp[i] == 0) - buf.AppendASCII("\\0"); + buf.Append("\\0"); else { buf.AppendPrintf("%c", strTemp[i]); @@ -1396,13 +1396,13 @@ char* DumpMarshaling(IMDInternalImport* pImport, } } else - buf.AppendASCII("\"\""); + buf.Append("\"\""); //_ASSERTE(cbCur <= cbNativeType); } } } } - buf.AppendASCII(")"); + buf.Append(")"); } break; default: @@ -1413,16 +1413,16 @@ char* DumpMarshaling(IMDInternalImport* pImport, } if(*sz) { - buf.AppendASCII(KEYWORD(sz)); + buf.Append(KEYWORD(sz)); if(fAddAsterisk) { - buf.AppendASCII("*"); + buf.Append("*"); fAddAsterisk = FALSE; } if(fAddBrackets) { ULONG ulSizeParam=(ULONG)-1,ulSizeConst=(ULONG)-1; - buf.AppendASCII("["); + buf.Append("["); fAddBrackets = FALSE; if (cbCur < cbNativeType) { @@ -1452,7 +1452,7 @@ char* DumpMarshaling(IMDInternalImport* pImport, { buf.AppendPrintf(" + %d",ulSizeParam); } - buf.AppendASCII("]"); + buf.Append("]"); } } @@ -1463,13 +1463,13 @@ char* DumpMarshaling(IMDInternalImport* pImport, // still can have outstanding asterisk or brackets if(fAddAsterisk) { - buf.AppendASCII("*"); + buf.Append("*"); fAddAsterisk = FALSE; } if(fAddBrackets) { ULONG ulSizeParam=(ULONG)-1,ulSizeConst=(ULONG)-1; - buf.AppendASCII("["); + buf.Append("["); fAddBrackets = FALSE; if (cbCur < cbNativeType) { @@ -1492,9 +1492,9 @@ char* DumpMarshaling(IMDInternalImport* pImport, { buf.AppendPrintf(" + %d",ulSizeParam); } - buf.AppendASCII("]"); + buf.Append("]"); } - buf.AppendASCII(") "); + buf.Append(") "); }// end if(SUCCEEDED error: if (buf.IsEmpty() && cbNativeType != 0) @@ -1504,10 +1504,13 @@ char* DumpMarshaling(IMDInternalImport* pImport, buf.AppendPrintf(" %s({", KEYWORD("marshal")); while (cbNativeType--) buf.AppendPrintf(" %2.2X", *pSigNativeType++); - buf.AppendASCII(" }) "); + buf.Append(" }) "); + + SString wbuf; + buf.ConvertToUnicode(wbuf); char * tgt = szString + strlen(szString); - int sprintf_ret = sprintf_s(tgt, cchszString - (tgt - szString), "%S", buf.GetUnicode()); + int sprintf_ret = sprintf_s(tgt, cchszString - (tgt - szString), "%S", (LPCWSTR)wbuf); if (sprintf_ret == -1) { // Hit an error. Oh well, nothing to do... @@ -1521,7 +1524,9 @@ char* DumpMarshaling(IMDInternalImport* pImport, else { char * tgt = szString + strlen(szString); - int sprintf_ret = sprintf_s(tgt, cchszString - (tgt - szString), "%S", buf.GetUnicode()); + SString wbuf; + buf.ConvertToUnicode(wbuf); + int sprintf_ret = sprintf_s(tgt, cchszString - (tgt - szString), "%S", (LPCWSTR)wbuf); if (sprintf_ret == -1) { // There was an error, possibly with converting the Unicode characters. diff --git a/src/coreclr/inc/longfilepathwrappers.h b/src/coreclr/inc/longfilepathwrappers.h index 3bcac98d5979d6..e0c4df6cd504a6 100644 --- a/src/coreclr/inc/longfilepathwrappers.h +++ b/src/coreclr/inc/longfilepathwrappers.h @@ -3,7 +3,11 @@ #ifndef _WIN_PATH_APIS_WRAPPER_ #define _WIN_PATH_APIS_WRAPPER_ -class SString; + +template +class EString; +struct EncodingUnicode; +using SString = EString; HMODULE LoadLibraryExWrapper( diff --git a/src/coreclr/inc/nsutilpriv.h b/src/coreclr/inc/nsutilpriv.h index 5ea9d0eba2ed6f..45d5fb99e5a278 100644 --- a/src/coreclr/inc/nsutilpriv.h +++ b/src/coreclr/inc/nsutilpriv.h @@ -11,7 +11,13 @@ #define __NSUTILPRIV_H__ template class CQuickArray; -class SString; + +struct EncodingUnicode; +struct EncodingUTF8; + +template +class EString; +using SString = EString; struct ns { @@ -153,6 +159,12 @@ int MakePath( // true ok, false out of memory const WCHAR *szNameSpace, // Namespace for name. const WCHAR *szName); // Final part of name. +static +void MakePath( // throws on out of memory + EString &ssBuf, // Where to put results. + const EString &ssNameSpace, // Namespace for name. + const EString &ssName); // Final part of name. + static void MakePath( // throws on out of memory SString &ssBuf, // Where to put results. @@ -192,9 +204,9 @@ int MakeNestedTypeName( // true ok, false truncation. static void MakeNestedTypeName( // throws on out of memory - SString &ssBuf, // output path for name. - const SString &ssEnclosingName, // Full name for enclosing type - const SString &ssNestedName); // Full name for nested type + EString &ssBuf, // output path for name. + const EString &ssEnclosingName, // Full name for enclosing type + const EString &ssNestedName); // Full name for nested type }; // struct ns #ifndef NAMESPACE_SEPARATOR_CHAR diff --git a/src/coreclr/inc/sbuffer.h b/src/coreclr/inc/sbuffer.h index 05c75faa575840..1de5eeaf0b0f1a 100644 --- a/src/coreclr/inc/sbuffer.h +++ b/src/coreclr/inc/sbuffer.h @@ -27,7 +27,7 @@ // stack preallocation size. // // SBuffer is "subclassable" to add content typeing to the buffer. See SArray and -// SString for examples. +// EString for examples. // -------------------------------------------------------------------------------- @@ -97,6 +97,7 @@ class SBuffer SBuffer(COUNT_T size); SBuffer(const BYTE *buffer, COUNT_T size); explicit SBuffer(const SBuffer &buffer); + SBuffer(SBuffer&& buffer); // Immutable constructor should ONLY be used if buffer will // NEVER BE FREED OR MODIFIED. PERIOD. . @@ -225,7 +226,7 @@ class SBuffer operator const void *() const; operator const BYTE *() const; - // To write directly to the SString's underlying buffer: + // To write directly to the EString's underlying buffer: // 1) Call OpenRawBuffer() and pass it the count of bytes // you need. // 2) That returns a pointer to the raw buffer which you can write to. @@ -297,7 +298,7 @@ class SBuffer //-------------------------------------------------------------------- // We define some extra flags and fields for subclasses (these are specifically - // designed for SString, but use otherwise if desired.) + // designed for EString, but use otherwise if desired.) //-------------------------------------------------------------------- BOOL IsFlag1() const; @@ -397,6 +398,8 @@ class SBuffer return DacInstantiateTypeByAddress(bufAddr, m_size, true); } + void* DacTryGetRawContent() const; + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) const { SUPPORTS_DAC; @@ -508,6 +511,10 @@ class SBuffer WCHAR *m_asStr; // For debugging, view as a unicode string }; + BYTE* GetRawBufferForMove() const; + + COUNT_T GetAllocationForMove() const; + #if _DEBUG protected: // We will update the "revision" of the buffer every time it is potentially reallocation, diff --git a/src/coreclr/inc/sbuffer.inl b/src/coreclr/inc/sbuffer.inl index 7ef7795631c82c..b26f2ab4f58d9c 100644 --- a/src/coreclr/inc/sbuffer.inl +++ b/src/coreclr/inc/sbuffer.inl @@ -114,6 +114,55 @@ inline SBuffer::SBuffer(const SBuffer &buffer) RETURN; } +inline SBuffer::SBuffer(SBuffer&& buffer) + : m_size(0), + m_allocation(NULL), + m_flags(0), + m_buffer(NULL) +{ + CONTRACT_VOID + { + CONSTRUCTOR_CHECK; + PRECONDITION(buffer.Check()); + POSTCONDITION(!buffer.IsAllocated()); + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + if (buffer.IsAllocated()) + { + // If the buffer is allocated, steal it + m_buffer = buffer.m_buffer; + m_allocation = buffer.m_allocation; + m_size = buffer.m_size; + m_flags = buffer.m_flags; + buffer.ClearAllocated(); + buffer.m_allocation = 0; + buffer.m_size = 0; + buffer.SetImmutable(); + } + else if (buffer.IsImmutable()) + { + // If the buffer is immutable, point to the same value. + m_buffer = buffer.m_buffer; + m_allocation = buffer.m_allocation; + m_size = buffer.m_size; + m_flags = buffer.m_flags; + } + else + { + // The buffer might be allocated on the stack as part of the object, so copy the data + Set(buffer); + } + +#ifdef _DEBUG + m_revision = 0; +#endif + + RETURN; +} + inline SBuffer::SBuffer(const BYTE *buffer, COUNT_T size) : m_size(0), m_allocation(0), @@ -890,7 +939,7 @@ static const UINT64 SBUFFER_CANARY_VALUE = UI64(0xD00BED00BED00BAA); // Expose the quantity of padding needed when providing a prealloced // buffer. This is an unrolled version of the actualAllocation calculated -// below for use as a constant value for InlineSString to use. It is +// below for use as a constant value for InlineEString to use. It is // padded with one additional sizeof(SBUFFER_CANARY_VALUE) to account for // possible alignment problems issues (pre- and post-padding). #define SBUFFER_PADDED_SIZE(desiredUsefulSize) \ @@ -910,6 +959,23 @@ static const int SBUFFER_ALIGNMENT = ALIGN_ACCESS; static const int SBUFFER_ALIGNMENT = 4; #endif +FORCEINLINE BYTE* SBuffer::GetRawBufferForMove() const +{ +#ifdef SBUFFER_CANARY_CHECKS + return m_buffer - sizeof(SBUFFER_CANARY_VALUE); +#else + return m_buffer; +#endif +} + +FORCEINLINE COUNT_T SBuffer::GetAllocationForMove() const +{ +#ifdef SBUFFER_CANARY_CHECKS + return (COUNT_T)(m_allocation + sizeof(SBUFFER_CANARY_VALUE) * 2 + AlignmentTrim((SIZE_T)m_buffer + m_allocation, sizeof(SBUFFER_CANARY_VALUE))); +#else + return m_allocation; +#endif +} //---------------------------------------------------------------------------- // Allocate memory, use canaries. //---------------------------------------------------------------------------- diff --git a/src/coreclr/inc/shash.h b/src/coreclr/inc/shash.h index c00fc72c17e646..01bfa5aa336a44 100644 --- a/src/coreclr/inc/shash.h +++ b/src/coreclr/inc/shash.h @@ -737,7 +737,7 @@ struct CaseInsensitiveStringCompareHash static size_t _strcmp(str_t left, str_t right) { - return ::SString::_tstricmp(left, right); + return ::StaticStringHelpers::_tstricmp(left, right); } static size_t _hash(CHAR const *str) @@ -853,11 +853,11 @@ class EMPTY_BASES_DECL WStringSHash : public SHash< StringSHashTraits -class EMPTY_BASES_DECL SStringSHashTraits : public PtrSHashTraits +template +class EMPTY_BASES_DECL EStringSHashTraits : public PtrSHashTraits> { public: - typedef PtrSHashTraits PARENT; + typedef PtrSHashTraits> PARENT; typedef typename PARENT::element_t element_t; typedef typename PARENT::key_t key_t; typedef typename PARENT::count_t count_t; @@ -876,8 +876,8 @@ class EMPTY_BASES_DECL SStringSHashTraits : public PtrSHashTraits -class EMPTY_BASES_DECL SStringSHash : public SHash< SStringSHashTraits > +template +class EMPTY_BASES_DECL EStringSHash : public SHash< EStringSHashTraits > { }; diff --git a/src/coreclr/inc/sstring.h b/src/coreclr/inc/sstring.h index 5f5eeb1078e005..31a214fed9a362 100644 --- a/src/coreclr/inc/sstring.h +++ b/src/coreclr/inc/sstring.h @@ -1,27 +1,27 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- -// SString.h (Safe String) +// EString.h (Safe String) // // --------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------ -// SString is the "standard" string representation for the EE. Its has two purposes. +// EString is the "standard" string representation for the EE. Its has two purposes. // (1) it provides an easy-to-use, relatively efficient, string class for APIs to standardize // on. // (2) it completely encapsulates all "unsafe" string operations - that is, string operations // which yield possible buffer overrun bugs. Typesafe use of this API should help guarantee // safety. // -// A SString is conceptually unicode, although the internal conversion might be delayed as long as possible +// A EString is conceptually unicode, although the internal conversion might be delayed as long as possible // Basically it's up to the implementation whether conversion takes place immediately or is delayed, and if // delayed, what operations trigger the conversion. // // Note that anywhere you express a "position" in a string, it is in terms of the Unicode representation of the // string. // -// If you need a direct non-unicode representation, you will have to provide a fresh SString which can +// If you need a direct non-unicode representation, you will have to provide a fresh EString which can // receive a conversion operation if necessary. // // The alternate encodings available are: @@ -65,324 +65,439 @@ typedef UTF8 *LPUTF8; typedef const UTF8 *LPCUTF8; // ========================================================================================== -// SString is the base class for safe strings. +// EString is the base class for safe strings. // ========================================================================================== +int CaseCompareHelperA(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount); +int CaseCompareHelper(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount); +int CaseHashHelperA(const CHAR *buffer, COUNT_T count); +int CaseHashHelper(const WCHAR *buffer, COUNT_T count); +struct EncodingASCII +{ + using char_t = CHAR; + + inline static int vsnprintf_s( + char_t* const buffer, + size_t const bufferCount, + size_t const maxCount, + char_t const* const format, + va_list argList) + { + return _vsnprintf_s(buffer, bufferCount, maxCount, format, argList); + } -typedef DPTR(class SString) PTR_SString; -class EMPTY_BASES_DECL SString : private SBuffer + inline static size_t strlen(const char_t* str) + { + return ::strlen(str); + } + + inline static int strncmp(const char_t* buffer1, const char_t* buffer2, size_t maxCount) + { + return ::strncmp(buffer1, buffer2, maxCount); + } + + inline static errno_t strncpy_s(char_t* dst, size_t bufferSize, const char_t* src, size_t count) + { + return ::strncpy_s(dst, bufferSize, src, count); + } + + inline static int CaseCompareHelper(const char_t* buffer1, const char_t* buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount) + { + return CaseCompareHelperA(buffer1, buffer2, count, stopOnNull, stopOnCount); + } + + inline static int CaseHashHelper(const char_t* buffer, COUNT_T count) + { + return ::CaseHashHelperA(buffer, count); + } +}; +struct EncodingUnicode { - friend struct _DacGlobals; + using char_t = WCHAR; + + inline static int vsnprintf_s( + char_t* const buffer, + size_t const bufferCount, + size_t const maxCount, + char_t const* const format, + va_list argList) + { + return _vsnwprintf_s(buffer, bufferCount, maxCount, format, argList); + } + + inline static size_t strlen(const char_t* str) + { + return ::wcslen(str); + } -private: - enum Representation + inline static int strncmp(const char_t* buffer1, const char_t* buffer2, size_t maxCount) { - // Note: bits are meaningful: xVS V == Variable? S == Single byte width? - REPRESENTATION_EMPTY = 0x00, // 000 - REPRESENTATION_UNICODE = 0x04, // 100 - REPRESENTATION_ASCII = 0x01, // 001 - REPRESENTATION_UTF8 = 0x03, // 011 - REPRESENTATION_ANSI = 0x07, // 111 - - REPRESENTATION_VARIABLE_MASK = 0x02, - REPRESENTATION_SINGLE_MASK = 0x01, - REPRESENTATION_MASK = 0x07, - }; + return ::wcsncmp(buffer1, buffer2, maxCount); + } - // Minimum guess for Printf buffer size - const static COUNT_T MINIMUM_GUESS = 20; + inline static errno_t strncpy_s(char_t* dst, size_t bufferSize, const char_t* src, size_t count) + { + return ::wcsncpy_s(dst, bufferSize, src, count); + } + inline static int CaseCompareHelper(const char_t* buffer1, const char_t* buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount) + { + return ::CaseCompareHelper(buffer1, buffer2, count, stopOnNull, stopOnCount); + } -#ifdef _DEBUG - // Used to have a public ctor of this form - made it too easy to lose - // utf8 info by accident. Now you have to specify the representation type - // explicitly - this privator ctor prevents reinsertion of this ctor. - explicit SString(const ASCII *) + inline static int CaseHashHelper(const char_t* buffer, COUNT_T count) { - _ASSERTE(!"Don't call this."); + return ::CaseHashHelper(buffer, count); + } +}; +struct EncodingUTF8 +{ + using char_t = CHAR; + + inline static int vsnprintf_s( + char_t* const buffer, + size_t const bufferCount, + size_t const maxCount, + char_t const* const format, + va_list argList) + { + return _vsnprintf_s(buffer, bufferCount, maxCount, format, argList); + } + + inline static size_t strlen(const char_t* str) + { + return ::strlen(str); } -#endif - protected: - class Index; - class UIndex; + inline static int strncmp(const char_t* buffer1, const char_t* buffer2, size_t maxCount) + { + return ::strncmp(buffer1, buffer2, maxCount); + } - friend class Index; - friend class UIndex; + inline static errno_t strncpy_s(char_t* dst, size_t bufferSize, const char* src, size_t count) + { + return ::strncpy_s(dst, bufferSize, src, count); + } - public: + inline static int CaseCompareHelper(const char_t* buffer1, const char_t* buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount) + { + return ::CaseCompareHelperA(buffer1, buffer2, count, stopOnNull, stopOnCount); + } - // UIterator is character-level assignable. - class UIterator; + inline static int CaseHashHelper(const char_t* buffer, COUNT_T count) + { + return ::CaseHashHelperA(buffer, count); + } +}; - // CIterators/Iterator'string must be modified by SString APIs. - class CIterator; - class Iterator; +template +class EString; + +template +using PTR_EString = DPTR(EString); + +using PTR_SString = PTR_EString; + +class StaticStringHelpers +{ + friend struct _DacGlobals; + template + friend class EString; + static const BYTE s_EmptyBuffer[2]; + + SPTR_DECL(EString, s_EmptyUnicode); + SPTR_DECL(EString, s_EmptyUtf8); + SPTR_DECL(EString, s_EmptyAscii); - // Tokens for constructor overloads - enum tagUTF8Literal { Utf8Literal }; - enum tagLiteral { Literal }; - enum tagUTF8 { Utf8 }; - enum tagANSI { Ansi }; - enum tagASCII {Ascii }; + CHECK CheckStartup(); +public: + StaticStringHelpers() = delete; static void Startup(); - static CHECK CheckStartup(); - - static const SString &Empty(); - - SString(); - - explicit SString(const SString &s); - - SString(const SString &s1, const SString &s2); - SString(const SString &s1, const SString &s2, const SString &s3); - SString(const SString &s1, const SString &s2, const SString &s3, const SString &s4); - SString(const SString &s, const CIterator &i, COUNT_T length); - SString(const SString &s, const CIterator &start, const CIterator &end); - SString(const WCHAR *string); - SString(const WCHAR *string, COUNT_T count); - SString(enum tagASCII dummyTag, const ASCII *string); - SString(enum tagASCII dummyTag, const ASCII *string, COUNT_T count); - SString(enum tagUTF8 dummytag, const UTF8 *string); - SString(enum tagUTF8 dummytag, const UTF8 *string, COUNT_T count); - SString(enum tagANSI dummytag, const ANSI *string); - SString(enum tagANSI dummytag, const ANSI *string, COUNT_T count); - SString(WCHAR character); - - // NOTE: Literals MUST be read-only never-freed strings. - SString(enum tagLiteral dummytag, const CHAR *literal); - SString(enum tagUTF8Literal dummytag, const UTF8 *literal); - SString(enum tagLiteral dummytag, const WCHAR *literal); - SString(enum tagLiteral dummytag, const WCHAR *literal, COUNT_T count); - // Set this string to the concatenation of s1,s2,s3,s4 - void Set(const SString &s); - void Set(const SString &s1, const SString &s2); - void Set(const SString &s1, const SString &s2, const SString &s3); - void Set(const SString &s1, const SString &s2, const SString &s3, const SString &s4); + // Helpers for CRT function equivalance. + static int __cdecl _stricmp(const CHAR *buffer1, const CHAR *buffer2); + static int __cdecl _strnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count); - // Set this string to the substring of s, starting at i, of length characters. - void Set(const SString &s, const CIterator &i, COUNT_T length); + static int __cdecl _wcsicmp(const WCHAR *buffer1, const WCHAR *buffer2); + static int __cdecl _wcsnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count); - // Set this string to the substring of s, starting at start and ending at end (exclusive) - void Set(const SString &s, const CIterator &start, const CIterator &end); + // C++ convenience overloads + static int _tstricmp(const CHAR *buffer1, const CHAR *buffer2); + static int _tstricmp(const WCHAR *buffer1, const WCHAR *buffer2); - // Set this string to a copy of the given string - void Set(const WCHAR *string); - void SetASCII(const ASCII *string); - void SetUTF8(const UTF8 *string); - void SetANSI(const ANSI *string); + static int _tstrnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count); + static int _tstrnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count); +}; - // Set this string to a copy of the first count chars of the given string - void Set(const WCHAR *string, COUNT_T count); +template +class EString : protected SBuffer +{ +protected: + using char_t = typename TEncoding::char_t; +public: + enum literal_tag_t { Literal }; + EString(void* buffer, COUNT_T size, bool isAllocated); + class Iterator; + class CIterator; + friend HRESULT LoadResourceAndReturnHR(EString& buffer, CCompRC* pResourceDLL, CCompRC::ResourceCategory eCategory, int resourceID); + EString(); - // Set this string to a prellocated copy of a given string. - // The caller is the owner of the bufffer and has to coordinate its lifetime. - void SetPreallocated(const WCHAR *string, COUNT_T count); + EString(literal_tag_t, const char_t* str) + :SBuffer(Immutable, reinterpret_cast(str), static_cast(((TEncoding::strlen(str) + 1) * sizeof(char_t)))) + { + } - void SetASCII(const ASCII *string, COUNT_T count); + EString(const char_t* str) + :EString() + { + Set(str); + } + EString(const char_t* str, COUNT_T count) + :EString() + { + Set(str, count); + } + + EString(const EString &s, const CIterator &start, const CIterator &end) + :EString() + { + Set(s, start, end); + } - void SetUTF8(const UTF8 *string, COUNT_T count); - void SetANSI(const ANSI *string, COUNT_T count); + explicit EString(const EString& s) + :EString() + { + Set(s); + } - // Set this string to the unicode character - void Set(WCHAR character); + EString(EString&& s) = default; - // Set this string to the UTF8 character - void SetUTF8(CHAR character); + EString(const EString& s, const EString& s1) + :EString() + { + Set(s, s1); + } - // Set this string to the given literal. We share the mem and don't make a copy. - void SetLiteral(const CHAR *literal); - void SetLiteral(const WCHAR *literal); + EString(const EString& s, const EString& s1, const EString& s2) + :EString() + { + Set(s, s1, s2); + } - // ------------------------------------------------------------------ - // Public operations - // ------------------------------------------------------------------ + EString(const EString& s, const EString& s1, const EString& s2, const EString& s3) + :EString() + { + Set(s, s1, s2, s3); + } - // Normalizes the string representation to unicode. This can be used to - // make basic read-only operations non-failing. - void Normalize() const; + EString(const EString &s, const CIterator &i, COUNT_T count); + static const EString& Empty(); + // Return the number of characters in the string (excluding the terminating NULL). - COUNT_T GetCount() const; BOOL IsEmpty() const; - // Return whether a single byte string has all characters which fit in the ASCII set. - // (Note that this will return FALSE if the string has been converted to unicode for any - // reason.) - BOOL IsASCII() const; + // Sets this string to an empty string "". + void Clear(); - // !!!!!!!!!!!!!! WARNING about case insensitive operations !!!!!!!!!!!!!!! - // - // THIS IS NOT SUPPORTED FULLY ON WIN9x - // SString case-insensitive comparison is based off LCMapString, - // which does not work on characters outside the current OS code page. - // - // Case insensitive code in SString is primarily targeted at - // supporting path comparisons, which is supported correctly on 9x, - // since file system names are limited to the OS code page. - // - // !!!!!!!!!!!!!! WARNING about case insensitive operations !!!!!!!!!!!!!!! + // Truncate the string to the iterator position + void Truncate(const Iterator &i); - // Compute a content-based hash value - ULONG Hash() const; - ULONG HashCaseInsensitive() const; + // Make sure that string buffer has room to grow + void Preallocate(COUNT_T characters) const; - // Do a string comparison. Return 0 if the strings - // have the same value, -1 if this is "less than" s, or 1 if - // this is "greater than" s. - int Compare(const SString &s) const; - int CompareCaseInsensitive(const SString &s) const; // invariant locale + // Shrink buffer size as much as possible (reallocate if necessary.) + void Trim() const; - // Do a case sensitive string comparison. Return TRUE if the strings - // have the same value FALSE if not. - BOOL Equals(const SString &s) const; - BOOL EqualsCaseInsensitive(const SString &s) const; // invariant locale - - // Match s to a portion of the string starting at the position. - // Return TRUE if the strings have the same value - // (regardless of representation), FALSE if not. - BOOL Match(const CIterator &i, const SString &s) const; - BOOL MatchCaseInsensitive(const CIterator &i, const SString &s) const; // invariant locale - - BOOL Match(const CIterator &i, WCHAR c) const; - BOOL MatchCaseInsensitive(const CIterator &i, WCHAR c) const; // invariant locale - - // Like match, but advances the iterator past the match - // if successful - BOOL Skip(CIterator &i, const SString &s) const; - BOOL Skip(CIterator &i, WCHAR c) const; - - // Start searching for a match of the given string, starting at - // the given iterator point. - // If a match exists, move the iterator to point to the nearest - // occurrence of s in the string and return TRUE. - // If no match exists, return FALSE and leave the iterator unchanged. - BOOL Find(CIterator &i, const SString &s) const; - BOOL Find(CIterator &i, const WCHAR *s) const; - BOOL FindASCII(CIterator &i, const ASCII *s) const; - BOOL FindUTF8(CIterator &i, const UTF8 *s) const; - BOOL Find(CIterator &i, WCHAR c) const; - - BOOL FindBack(CIterator &i, const SString &s) const; - BOOL FindBack(CIterator &i, const WCHAR *s) const; - BOOL FindBackASCII(CIterator &i, const ASCII *s) const; - BOOL FindBackUTF8(CIterator &i, const UTF8 *s) const; - BOOL FindBack(CIterator &i, WCHAR c) const; - - // Returns TRUE if this string begins with the contents of s - BOOL BeginsWith(const SString &s) const; - BOOL BeginsWithCaseInsensitive(const SString &s) const; // invariant locale + // Returns TRUE if this string begins with the contents of s + BOOL BeginsWith(const EString &s) const { return Match(Begin(), s); } + BOOL BeginsWithCaseInsensitive(const EString &s) const { return MatchCaseInsensitive(Begin(), s); } // invariant locale // Returns TRUE if this string ends with the contents of s - BOOL EndsWith(const SString &s) const; - BOOL EndsWithCaseInsensitive(const SString &s) const; // invariant locale + BOOL EndsWith(const EString& s) const + { + WRAPPER_NO_CONTRACT; - // Sets this string to an empty string "". - void Clear(); + // Need this check due to iterator arithmetic below. + if (GetCount() < s.GetCount()) + { + return FALSE; + } - // Truncate the string to the iterator position - void Truncate(const Iterator &i); + return Match(End() - s.GetCount(), s); + } - // Append s to the end of this string. - void Append(const SString &s); - void Append(const WCHAR *s); - void AppendASCII(const CHAR *s); - void AppendUTF8(const CHAR *s); + BOOL EndsWithCaseInsensitive(const EString &s) const // invariant locale + { + WRAPPER_NO_CONTRACT; - // Append char c to the end of this string. - void Append(const WCHAR c); - void AppendUTF8(const CHAR c); + // Need this check due to iterator arithmetic below. + if (GetCount() < s.GetCount()) + { + return FALSE; + } - // Insert s into this string at the 'position'th character. - void Insert(const Iterator &i, const SString &s); - void Insert(const Iterator &i, const WCHAR *s); - void InsertASCII(const Iterator &i, const CHAR *s); - void InsertUTF8(const Iterator &i, const CHAR *s); + return MatchCaseInsensitive(End() - s.GetCount(), s); + } + + EString &operator= (const EString &s) { WRAPPER_NO_CONTRACT; Set(s); return *this; } + EString &operator= (EString &&s) { WRAPPER_NO_CONTRACT; Set(s); return *this; } // TODO: Look at stealing the buffer from the rhs value if we'd have to reallocate (and always clear the rhs for deterministic behavior). - // Delete substring position + length - void Delete(const Iterator &i, COUNT_T length); + const EString& operator+=(const EString& s) + { + WRAPPER_NO_CONTRACT; + Append(s); + return *this; + } - // Replace character at i with c - void Replace(const Iterator &i, WCHAR c); + operator const char_t* () const + { + return GetRawBuffer(); + } - // Replace substring at (i,i+length) with s - void Replace(const Iterator &i, COUNT_T length, const SString &s); + void Append(const EString &s); - // Make sure that string buffer has room to grow - void Preallocate(COUNT_T characters) const; + void Append(const char_t* s); - // Shrink buffer size as much as possible (reallocate if necessary.) - void Trim() const; + void Append(char_t c); - // ------------------------------------------------------------------ - // Iterators: - // ------------------------------------------------------------------ + // Do a string comparison. Return 0 if the strings + // have the same value, -1 if this is "less than" s, or 1 if + // this is "greater than" s. + int Compare(const EString &s) const; + int CompareCaseInsensitive(const EString& s) const; // invariant locale - // SString splits iterators into two categories. - // - // CIterator and Iterator are cheap to create, but allow only read-only - // access to the string. - // - // UIterator forces a unicode conversion, but allows - // assignment to individual string characters. They are also a bit more - // efficient once created. + // Do a case sensitive string comparison. Return TRUE if the strings + // have the same value FALSE if not. + BOOL Equals(const EString &s) const; + BOOL EqualsCaseInsensitive(const EString &s) const; // invariant locale - // ------------------------------------------------------------------ - // UIterator: - // ------------------------------------------------------------------ + // Set this string to the concatenation of s1,s2,s3,s4 + void Set(const EString &s); - protected: + void Set(const EString& s1, const EString& s2) + { + Preallocate(s1.GetCount() + s2.GetCount()); + Set(s1); + Append(s2); + } - class EMPTY_BASES_DECL UIndex : public SBuffer::Index + void Set(const EString &s1, const EString &s2, const EString &s3) { - friend class SString; - friend class Indexer; + Preallocate(s1.GetCount() + s2.GetCount() + s3.GetCount()); + Set(s1); + Append(s2); + Append(s3); + } - protected: + void Set(const EString &s1, const EString &s2, const EString &s3, const EString &s4) + { + Preallocate(s1.GetCount() + s2.GetCount() + s3.GetCount() + s4.GetCount()); + Set(s1); + Append(s2); + Append(s3); + Append(s4); + } + + // Set this string to the substring of s, starting at i, of length characters. + void Set(const EString &s, const CIterator &i, COUNT_T length); - UIndex(); - UIndex(SString *string, SCOUNT_T index); - WCHAR &GetAt(SCOUNT_T delta) const; - void Skip(SCOUNT_T delta); - SCOUNT_T Subtract(const UIndex &i) const; - CHECK DoCheck(SCOUNT_T delta) const; + // Set this string to the substring of s, starting at start and ending at end (exclusive) + void Set(const EString &s, const CIterator &start, const CIterator &end); - WCHAR *GetUnicode() const; - }; + // Set this string to a copy of the given string + void Set(const char_t*string); - public: + // Set this string to a copy of the first count chars of the given string + void Set(const char_t*string, COUNT_T count); + + void Set(char_t c); + + // Set this string to point to an existing string. The memory will be shared, + // so it is the responsibility of the owner of the parameter to ensure lifetime + // is at least as long as this EString. + void SetLiteral(const char_t* string); + void SetPreallocated(const char_t*string, COUNT_T count); - class EMPTY_BASES_DECL UIterator : public UIndex, public Indexer + void Printf(const char_t* format, ...) { - friend class SString; + WRAPPER_NO_CONTRACT; + + va_list args; + va_start(args, format); + VPrintf(format, args); + va_end(args); + } + + void VPrintf(const char_t* format, va_list args); + + void AppendPrintf(const char_t* format, ...) + { + WRAPPER_NO_CONTRACT; - public: - UIterator() + va_list args; + va_start(args, format); + AppendVPrintf(format, args); + va_end(args); + } + + void AppendVPrintf(const char_t* format, va_list args); + + BOOL FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, + const EString &arg1 = Empty(), const EString &arg2 = Empty(), + const EString &arg3 = Empty(), const EString &arg4 = Empty(), + const EString &arg5 = Empty(), const EString &arg6 = Empty(), + const EString &arg7 = Empty(), const EString &arg8 = Empty(), + const EString &arg9 = Empty(), const EString &arg10 = Empty()) = delete; + + void Resize(COUNT_T count, SBuffer::Preserve preserve = SBuffer::PRESERVE) + { + CONTRACT_VOID { + PRECONDITION(CountToSize(count) >= count); + POSTCONDITION(SizeToCount(GetSize()) == count); + if (count == 0) NOTHROW; else THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; } + CONTRACT_END; - UIterator(SString *string, int index) - : UIndex(string, index) + // If we are resizing to zero, Clear is more efficient + if (count == 0) { + Clear(); + } + else + { + COUNT_T size = CountToSize(count); + + // detect overflow + if (size < count) + ThrowOutOfMemory(); + + SBuffer::Resize(size, preserve); + + if (IsImmutable()) + EnsureMutable(); + + NullTerminate(); } - }; - UIterator BeginUnicode(); - UIterator EndUnicode(); + RETURN; + } + + // Compute a content-based hash value + ULONG Hash() const; + ULONG HashCaseInsensitive() const; + // ------------------------------------------------------------------ + // Iterators: + // ------------------------------------------------------------------ - // For CIterator & Iterator, we try our best to iterate the string without - // modifying it. (Currently, we do require an ASCII or Unicode string - // for simple WCHAR retrival, but you could imagine being more flexible - // going forward - perhaps even supporting iterating multibyte encodings - // directly.) + // EString splits iterators into two categories. // - // Because of the runtime-changable nature of the string, CIterators - // require an extra member to record the character size. They also - // are unable to properly implement GetAt as required by the template - // (since there may not be a direct WCHAR pointer), so they provide - // further customization in a subclass. + // CIterator and Iterator are cheap to create, but allow only read-only + // access to the string. // // Normally the user expects to cast Iterators to CIterators transparently, so // we provide a constructor on CIterator to support this. @@ -391,39 +506,38 @@ class EMPTY_BASES_DECL SString : private SBuffer class EMPTY_BASES_DECL Index : public SBuffer::Index { - friend class SString; + friend class EString; - friend class Indexer; - friend class Indexer; + friend class Indexer; + friend class Indexer; protected: - int m_characterSizeShift; Index(); - Index(SString *string, SCOUNT_T index); + Index(EString *string, SCOUNT_T index); BYTE &GetAt(SCOUNT_T delta) const; void Skip(SCOUNT_T delta); SCOUNT_T Subtract(const Index &i) const; CHECK DoCheck(SCOUNT_T delta) const; - void Resync(const SString *string, BYTE *ptr) const; + void Resync(const EString *string, BYTE *ptr) const; - const WCHAR *GetUnicode() const; - const CHAR *GetASCII() const; + const char_t* GetBuffer() const; public: // Note these should supercede the Indexer versions // since this class comes first in the inheritence list - WCHAR operator*() const; + const char_t& operator*() const; + char_t& operator*(); void operator->() const; - WCHAR operator[](int index) const; + char_t operator[](int index) const; }; public: - class EMPTY_BASES_DECL CIterator : public Index, public Indexer + class EMPTY_BASES_DECL CIterator : public Index, public Indexer { - friend class SString; + friend class EString; public: const Iterator &ConstCast() const @@ -450,20 +564,21 @@ class EMPTY_BASES_DECL SString : private SBuffer { } - CIterator(const SString *string, int index) - : Index(const_cast(string), index) + CIterator(const EString *string, int index) + : Index(const_cast(string), index) { } // explicitly resolve these for gcc - WCHAR operator*() const { return Index::operator*(); } + const char_t& operator*() const { return Index::operator*(); } + char_t& operator*() { return Index::operator*(); } void operator->() const { Index::operator->(); } - WCHAR operator[](int index) const { return Index::operator[](index); } + char_t operator[](int index) const { return Index::operator[](index); } }; - class EMPTY_BASES_DECL Iterator : public Index, public Indexer + class EMPTY_BASES_DECL Iterator : public Index, public Indexer { - friend class SString; + friend class EString; public: operator const CIterator &() const @@ -490,16 +605,16 @@ class EMPTY_BASES_DECL SString : private SBuffer { } - Iterator(SString *string, int index) + Iterator(EString *string, int index) : Index(string, index) { SUPPORTS_DAC; } // explicitly resolve these for gcc - WCHAR operator*() const { return Index::operator*(); } + const char_t& operator*() const { return Index::operator*(); } void operator->() const { Index::operator->(); } - WCHAR operator[](int index) const { return Index::operator[](index); } + char_t operator[](int index) const { return Index::operator[](index); } }; CIterator Begin() const; @@ -508,65 +623,70 @@ class EMPTY_BASES_DECL SString : private SBuffer Iterator Begin(); Iterator End(); - // ------------------------------------------------------------------ - // Conversion: - // ------------------------------------------------------------------ - - // Get a const pointer to the string in the current representation. - // This pointer can not be cached because it will become invalid if - // the SString changes representation or reallocates its buffer. - - // You can always get a unicode string. This will force a conversion - // if necessary. - const WCHAR *GetUnicode() const; - const WCHAR *GetUnicode(const CIterator &i) const; - - void LowerCase(); - void UpperCase(); - - // Helper function to convert string in-place to lower-case (no allocation overhead for SString instance) - static void LowerCase(__inout_z LPWSTR wszString); - - // These routines will use the given scratch string if necessary - // to perform a conversion to the desired representation + char_t operator[](int index) { WRAPPER_NO_CONTRACT; return Begin()[index]; } + char_t operator[](int index) const { WRAPPER_NO_CONTRACT; return Begin()[index]; } + + // Delete substring position + length + void Delete(const Iterator &i, COUNT_T length); - // Use a local declaration of InlineScratchBuffer or StackScratchBuffer for parameters of - // AbstractScratchBuffer. - class AbstractScratchBuffer; + void Replace(Iterator& i, char_t c) + { + *(char_t*)i.m_ptr = c; + } - // These routines will use the given scratch buffer if necessary - // to perform a conversion to the desired representation. Note that - // the lifetime of the pointer return is limited by BOTH the - // scratch string and the source (this) string. - // - // Typical usage: - // - // SString *s = ...; - // { - // StackScratchBuffer buffer; - // const UTF8 *utf8 = s->GetUTF8(buffer); - // CallFoo(utf8); - // } - // // No more pointers to returned buffer allowed. + void Replace(const Iterator &i, COUNT_T length, const EString &s); + void Insert(const Iterator &i, const EString &s); + void Insert(const Iterator &i, const char_t *s); + + BOOL Find(CIterator &i, const EString &s) const; + BOOL Find(CIterator &i, const char_t *s) const { return Find(i, EString(EString::Literal, s)); } + BOOL Find(CIterator &i, char_t s) const; + BOOL FindBack(CIterator &i, const EString &s) const; + BOOL FindBack(CIterator &i, const char_t *s) const { return FindBack(i, EString(EString::Literal, s)); } + BOOL FindBack(CIterator &i, char_t s) const; + BOOL Skip(CIterator &i, const EString &s) const; + BOOL Skip(CIterator &i, char_t s) const; + BOOL Match(const CIterator &i, const EString &s) const; + BOOL Match(const CIterator &i, char_t s) const; + BOOL MatchCaseInsensitive(const CIterator &i, const EString &s) const; + + //Returns a copy of the string, allocated with new[]. The caller is reponsible for lifetime of the string + char_t* CreateCopyOfString() const + { + char_t* copy = new char_t[GetCount() + 1]; + memcpy(copy, GetRawBuffer(), (GetCount() + 1) * sizeof(char_t)); + return copy; + } - const UTF8 *GetUTF8(AbstractScratchBuffer &scratch) const; - const UTF8 *GetUTF8(AbstractScratchBuffer &scratch, COUNT_T *pcbUtf8) const; - const ANSI *GetANSI(AbstractScratchBuffer &scratch) const; + COUNT_T GetAllocation() const + { + CONTRACTL + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; - // Used when the representation is known, throws if the representation doesn't match - const UTF8 *GetUTF8NoConvert() const; + COUNT_T allocation = SBuffer::GetAllocation(); + return ( (allocation > sizeof(char_t)) + ? (allocation - sizeof(char_t)) / sizeof(char_t) : 0 ); + } - // Converts/copies into the given output string - void ConvertToUnicode(SString &dest) const; - void ConvertToANSI(SString &dest) const; - COUNT_T ConvertToUTF8(SString &dest) const; + // Conversion/Move routines + void LowerCase(); + void UpperCase(); + COUNT_T ConvertToUTF8(EString& resultBuffer) const; + COUNT_T ConvertToUnicode(EString& resultBuffer) const; + EString MoveToUTF8(); + EString MoveToUnicode(); //------------------------------------------------------------------- // Accessing the string contents directly //------------------------------------------------------------------- - // To write directly to the SString's underlying buffer: - // 1) Call OpenXXXBuffer() and pass it the count of characters + // To write directly to the EString's underlying buffer: + // 1) Call OpenBuffer() and pass it the count of characters // you need. (Not including the null-terminator). // 2) That returns a pointer to the raw buffer which you can write to. // 3) When you are done writing to the pointer, call CloseBuffer() @@ -574,8 +694,8 @@ class EMPTY_BASES_DECL SString : private SBuffer // the null). The pointer from step 1 is now invalid. // example usage: - // void GetName(SString & str) { - // char * p = str.OpenANSIBuffer(3); + // void GetName(EString & str) { + // char * p = str.OpenBuffer(3); // strcpy(p, "Cat"); // str.CloseBuffer(); // } @@ -592,43 +712,51 @@ class EMPTY_BASES_DECL SString : private SBuffer // In a debug build, Open/Close will do lots of little checks to make sure // you don't buffer overflow while it's opened. In a retail build, this // is a very streamlined action. - - // Open the raw buffer for writing countChars characters (not including the null). - WCHAR *OpenUnicodeBuffer(COUNT_T maxCharCount); - UTF8 *OpenUTF8Buffer(COUNT_T maxSingleCharCount); - ANSI *OpenANSIBuffer(COUNT_T maxSingleCharCount); - - //Returns the unicode string, the caller is reponsible for lifetime of the string - WCHAR *GetCopyOfUnicodeString(); - - // Get the max size that can be passed to OpenUnicodeBuffer without causing allocations. - COUNT_T GetUnicodeAllocation(); + char_t *OpenBuffer(COUNT_T maxCharCount) + { + Resize(maxCharCount); + return (char_t *)SBuffer::OpenRawBuffer(CountToSize(maxCharCount)); + } - // Call after OpenXXXBuffer(). + // Call after OpenBuffer(). // Provide the count of characters actually used (not including the - // null terminator). This will make sure the SString's size is correct + // null terminator). This will make sure the EString's size is correct // and that we have a null-terminator. - void CloseBuffer(COUNT_T finalCount); + void CloseBuffer(COUNT_T finalCount) + { + SBuffer::CloseRawBuffer(CountToSize(finalCount)); + NullTerminate(); + } // Close the buffer. Assumes that we completely filled the buffer // that OpenBuffer() gave back. If we didn't write all the characters, // call CloseBuffer(int) instead. - void CloseBuffer(); + void CloseBuffer() + { + SBuffer::CloseRawBuffer(); + NullTerminate(); + } + // Return the number of characters in the string (excluding the terminating NULL). + COUNT_T GetCount() const + { + return SizeToCount(GetSize()); + } #ifdef DACCESS_COMPILE // DAC access to string functions. // Note that other accessors above are not DAC-safe and will return TARGET pointers into // the string instead of copying the string over to the host. - // @dbgtodo dac support: Prevent usage of such DAC-unsafe SString APIs in DAC code - - // Instantiate a copy of the raw buffer in the host and return a pointer to it - void * DacGetRawContent() const; + // @dbgtodo dac support: Prevent usage of such DAC-unsafe EString APIs in DAC code + void* DacGetRawContent(void) const + { + return SBuffer::DacGetRawContent(); + } // Instantiate a copy of the raw buffer in the host. Requires that the underlying // representation is already unicode. - const WCHAR * DacGetRawUnicode() const; + const WCHAR * DacGetRawUnicode() const = delete; // Copy the string from the target into the provided buffer, converting to unicode if necessary bool DacGetUnicode(COUNT_T bufChars, @@ -642,380 +770,142 @@ class EMPTY_BASES_DECL SString : private SBuffer } #endif - //--------------------------------------------------------------------- - // Utilities - //--------------------------------------------------------------------- - - // WARNING: The MBCS version of printf function are factory for globalization - // issues when used to format Unicode strings (%S). The Unicode versions are - // preferred in this case. - void Printf(const CHAR *format, ...); - void VPrintf(const CHAR *format, va_list args); - void AppendPrintf(const CHAR *format, ...); - void AppendVPrintf(const CHAR *format, va_list args); - - void Printf(const WCHAR *format, ...); - -public: - BOOL LoadResource(CCompRC::ResourceCategory eCategory, int resourceID); - HRESULT LoadResourceAndReturnHR(CCompRC::ResourceCategory eCategory, int resourceID); - HRESULT LoadResourceAndReturnHR(CCompRC* pResourceDLL, CCompRC::ResourceCategory eCategory, int resourceID); - BOOL FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, - const SString &arg1 = Empty(), const SString &arg2 = Empty(), - const SString &arg3 = Empty(), const SString &arg4 = Empty(), - const SString &arg5 = Empty(), const SString &arg6 = Empty(), - const SString &arg7 = Empty(), const SString &arg8 = Empty(), - const SString &arg9 = Empty(), const SString &arg10 = Empty()); - -#if 1 - // @todo - get rid of this and move it outside of SString - void MakeFullNamespacePath(const SString &nameSpace, const SString &name); -#endif - - //-------------------------------------------------------------------- - // Operators - //-------------------------------------------------------------------- - - operator const WCHAR * () const { WRAPPER_NO_CONTRACT; return GetUnicode(); } - - WCHAR operator[](int index) { WRAPPER_NO_CONTRACT; return Begin()[index]; } - WCHAR operator[](int index) const { WRAPPER_NO_CONTRACT; return Begin()[index]; } - - SString &operator= (const SString &s) { WRAPPER_NO_CONTRACT; Set(s); return *this; } - SString &operator+= (const SString &s) { WRAPPER_NO_CONTRACT; Append(s); return *this; } - // ------------------------------------------------------------------- // Check functions // ------------------------------------------------------------------- - - CHECK CheckIteratorRange(const CIterator &i) const; - CHECK CheckIteratorRange(const CIterator &i, COUNT_T length) const; CHECK CheckEmpty() const; static CHECK CheckCount(COUNT_T count); static CHECK CheckRepresentation(int representation); #if CHECK_INVARIANTS - static CHECK CheckASCIIString(const ASCII *string); - static CHECK CheckASCIIString(const ASCII *string, COUNT_T count); + static CHECK CheckASCIIString(const ASCII *string) { CHECK_OK; } + static CHECK CheckASCIIString(const ASCII *string, COUNT_T count) { CHECK_OK; } CHECK Check() const; CHECK Invariant() const; CHECK InternalInvariant() const; #endif // CHECK_INVARIANTS - - // Helpers for CRT function equivalance. - static int __cdecl _stricmp(const CHAR *buffer1, const CHAR *buffer2); - static int __cdecl _strnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count); - - static int __cdecl _wcsicmp(const WCHAR *buffer1, const WCHAR *buffer2); - static int __cdecl _wcsnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count); - - // C++ convenience overloads - static int _tstricmp(const CHAR *buffer1, const CHAR *buffer2); - static int _tstricmp(const WCHAR *buffer1, const WCHAR *buffer2); - - static int _tstrnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count); - static int _tstrnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count); - +private: // ------------------------------------------------------------------- - // Internal routines + // Check functions // ------------------------------------------------------------------- - - protected: - // Use this via InlineSString - SString(void *buffer, COUNT_T size); - - private: - static int CaseCompareHelperA(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount); - static int CaseCompareHelper(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount); - - // Internal helpers: - - static const BYTE s_EmptyBuffer[2]; - - static UINT s_ACP; - - SPTR_DECL(SString,s_Empty); - - COUNT_T GetRawCount() const; - - // Get buffer as appropriate string rep - ASCII *GetRawASCII() const; - UTF8 *GetRawUTF8() const; - ANSI *GetRawANSI() const; - WCHAR *GetRawUnicode() const; - - void InitEmpty(); - - Representation GetRepresentation() const; - void SetRepresentation(Representation representation); - BOOL IsRepresentation(Representation representation) const; - BOOL IsFixedSize() const; - BOOL IsIteratable() const; - BOOL IsSingleByte() const; - - int GetCharacterSizeShift() const; - - COUNT_T SizeToCount(COUNT_T size) const; - COUNT_T CountToSize(COUNT_T count) const; - - COUNT_T GetBufferSizeInCharIncludeNullChar() const; + CHECK CheckIteratorRange(const CIterator &i) const; + CHECK CheckIteratorRange(const CIterator &i, COUNT_T length) const; + void NullTerminate(); + + // Minimum guess for Printf buffer size + const static COUNT_T MINIMUM_GUESS = 20; + + void EnsureWritable() const; BOOL IsLiteral() const; BOOL IsAllocated() const; - BOOL IsBufferOpen() const; - BOOL IsASCIIScanned() const; - void SetASCIIScanned() const; - void SetNormalized() const; - BOOL IsNormalized() const; - void ClearNormalized() const; - void EnsureWritable() const; - void ConvertToFixed() const; - void ConvertToIteratable() const; +protected: + FORCEINLINE char_t* GetRawBuffer() const + { + return reinterpret_cast(m_buffer); + } - void ConvertASCIIToUnicode(SString &dest) const; - void ConvertToUnicode() const; - void ConvertToUnicode(const CIterator &i) const; + FORCEINLINE static COUNT_T SizeToCount(COUNT_T size) + { + return size / sizeof(char_t) - 1; + } - const SString &GetCompatibleString(const SString &s, SString &scratch) const; - const SString &GetCompatibleString(const SString &s, SString &scratch, const CIterator &i) const; - BOOL ScanASCII() const; - void NullTerminate(); + FORCEINLINE static COUNT_T CountToSize(COUNT_T count) + { + return (count + 1) * sizeof(char_t); + } +}; - void Resize(COUNT_T count, Representation representation, - Preserve preserve = DONT_PRESERVE); +using SString = EString; - void OpenBuffer(Representation representation, COUNT_T countChars); -}; +inline SString SL(const WCHAR* str) +{ + return {SString::Literal, str}; +} // =========================================================================== -// InlineSString is used for stack allocation of strings, or when the string contents +// InlineEString is used for stack allocation of strings, or when the string contents // are expected or known to be small. Note that it still supports expandability via // heap allocation if necessary. // =========================================================================== -template -class EMPTY_BASES_DECL InlineSString : public SString +template +class InlineEString : public EString { + using typename EString::char_t; + using typename EString::literal_tag_t; private: - DAC_ALIGNAS(SString) - BYTE m_inline[SBUFFER_PADDED_SIZE(MEMSIZE)]; - + DAC_ALIGNAS(EString) + char_t m_inline[SBUFFER_PADDED_SIZE(MEMSIZE)]; public: - FORCEINLINE InlineSString() - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) - { - WRAPPER_NO_CONTRACT; - } - - FORCEINLINE InlineSString(const SString &s) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) - { - WRAPPER_NO_CONTRACT; - Set(s); - } - - FORCEINLINE InlineSString(const SString &s1, const SString &s2) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) - { - WRAPPER_NO_CONTRACT; - Set(s1, s2); - } - - FORCEINLINE InlineSString(const SString &s1, const SString &s2, const SString &s3) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) - { - WRAPPER_NO_CONTRACT; - Set(s1, s2, s3); - } - - FORCEINLINE InlineSString(const SString &s1, const SString &s2, const SString &s3, const SString &s4) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) - { - WRAPPER_NO_CONTRACT; - Set(s1, s2, s3, s4); - } - - FORCEINLINE InlineSString(const SString &s, const CIterator &start, const CIterator &end) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) - { - WRAPPER_NO_CONTRACT; - Set(s, start, end); - } - - FORCEINLINE InlineSString(const SString &s, const CIterator &i, COUNT_T length) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) - { - WRAPPER_NO_CONTRACT; - Set(s, i, length); - } - - FORCEINLINE InlineSString(const WCHAR *string) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) - { - WRAPPER_NO_CONTRACT; - Set(string); - } - - FORCEINLINE InlineSString(const WCHAR *string, COUNT_T count) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) - { - WRAPPER_NO_CONTRACT; - Set(string, count); - } - - FORCEINLINE InlineSString(enum tagASCII, const CHAR *string) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) - { - WRAPPER_NO_CONTRACT; - SetASCII(string); - } - - FORCEINLINE InlineSString(enum tagASCII, const CHAR *string, COUNT_T count) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + InlineEString() + :EString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE), /* isAllocated */ false) { - WRAPPER_NO_CONTRACT; - SetASCII(string, count); + SBuffer::TweakSize(sizeof(char_t)); + this->GetRawBuffer()[0] = (char_t)0; } - FORCEINLINE InlineSString(tagUTF8 dummytag, const UTF8 *string) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + InlineEString(const char_t c) + :InlineEString() { - WRAPPER_NO_CONTRACT; - SetUTF8(string); + EString::Set(c); } - FORCEINLINE InlineSString(tagUTF8 dummytag, const UTF8 *string, COUNT_T count) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + InlineEString(const char_t* str) + :InlineEString() { - WRAPPER_NO_CONTRACT; - SetUTF8(string, count); + EString::Set(str); } - FORCEINLINE InlineSString(enum tagANSI dummytag, const ANSI *string) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + InlineEString(literal_tag_t, const char_t* str) + :InlineEString() { - WRAPPER_NO_CONTRACT; - SetANSI(string); + EString::SetLiteral(str); } - FORCEINLINE InlineSString(enum tagANSI dummytag, const ANSI *string, COUNT_T count) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + InlineEString(const char_t* str, COUNT_T count) + :InlineEString() { - WRAPPER_NO_CONTRACT; - SetANSI(string, count); - } - - FORCEINLINE InlineSString(WCHAR character) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) - { - WRAPPER_NO_CONTRACT; - Set(character); - } - - FORCEINLINE InlineSString(tagUTF8 dummytag, const UTF8 character) - : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) - { - WRAPPER_NO_CONTRACT; - SetUTF8(character); - } - - FORCEINLINE InlineSString &operator= (const SString &s) - { - WRAPPER_NO_CONTRACT; - Set(s); - return *this; - } - - FORCEINLINE InlineSString &operator= (const InlineSString &s) - { - WRAPPER_NO_CONTRACT; - Set(s); - return *this; + EString::Set(str, count); } }; +template +using InlineSString = InlineEString; + // ================================================================================ -// StackSString is a lot like CQuickBytes. Use it to create an SString object +// StackEString is a lot like CQuickBytes. Use it to create an EString object // using some stack space as a preallocated buffer. // ================================================================================ -typedef InlineSString<512> StackSString; +template +using StackEString = InlineEString<512, TEncoding>; +using StackSString = StackEString; // This is a smaller version for when it is known that the string that's going to // be needed is small and it's preferable not to take up the stack space. -typedef InlineSString<32> SmallStackSString; +template +using SmallStackEString = InlineEString<32, TEncoding>; +using SmallStackSString = SmallStackEString; // To be used specifically for path strings. #ifdef _DEBUG // This is a smaller version for debug builds to exercise the buffer allocation path -typedef InlineSString<32> PathString; -typedef InlineSString<2 * 32> LongPathString; +typedef InlineEString<32, EncodingUnicode> PathString; +typedef InlineEString<2 * 32, EncodingUnicode> LongPathString; #else // Set it to the current MAX_PATH -typedef InlineSString<260> PathString; -typedef InlineSString<2 * 260> LongPathString; +typedef InlineEString<260, EncodingUnicode> PathString; +typedef InlineEString<2 * 260, EncodingUnicode> LongPathString; #endif -// ================================================================================ -// Quick macro to create an SString around a literal string. -// usage: -// s = SL("My literal String"); -// ================================================================================ - -#define SL(_literal) SString(SString::Literal, _literal) - -// ================================================================================ -// ScratchBuffer classes are used by the GetXXX() routines to allocate scratch space in. -// ================================================================================ - -class EMPTY_BASES_DECL SString::AbstractScratchBuffer : private SString -{ - protected: - // Do not use this class directly - use - // ScratchBuffer or StackScratchBuffer. - AbstractScratchBuffer(void *buffer, COUNT_T size); -}; - -template -class EMPTY_BASES_DECL ScratchBuffer : public SString::AbstractScratchBuffer -{ - private: - DAC_ALIGNAS(::SString::AbstractScratchBuffer) - BYTE m_inline[MEMSIZE]; - - public: - ScratchBuffer() - : AbstractScratchBuffer((void *)m_inline, MEMSIZE) - { - WRAPPER_NO_CONTRACT; - } -}; - -typedef ScratchBuffer<256> StackScratchBuffer; - -// ================================================================================ -// Special contract definition - THROWS_UNLESS_NORMALIZED -// this is used for operations which might fail for generalized strings but -// not if the string has already been converted to unicode. Rather than just -// setting this on all conversions to unicode, we only set it when explicitly -// asked. This should expose more potential problems. -// ================================================================================ - -#define THROWS_UNLESS_NORMALIZED \ - if (IsNormalized()) NOTHROW; else THROWS - -#define THROWS_UNLESS_BOTH_NORMALIZED(s) \ - if (IsNormalized() && s.IsNormalized()) NOTHROW; else THROWS - -#define FAULTS_UNLESS_NORMALIZED(stmt) \ - if (IsNormalized()) FORBID_FAULT; else INJECT_FAULT(stmt) - -#define FAULTS_UNLESS_BOTH_NORMALIZED(s, stmt) \ - if (IsNormalized() && s.IsNormalized()) FORBID_FAULT; else INJECT_FAULT(stmt) +BOOL LoadResource(EString& buffer, CCompRC::ResourceCategory eCategory, int resourceID); +HRESULT LoadResourceAndReturnHR(EString& buffer, CCompRC::ResourceCategory eCategory, int resourceID); +HRESULT LoadResourceAndReturnHR(EString& buffer, CCompRC* pResourceDLL, CCompRC::ResourceCategory eCategory, int resourceID); // ================================================================================ // Inline definitions diff --git a/src/coreclr/inc/sstring.inl b/src/coreclr/inc/sstring.inl index 03fc26fe9666cf..fad6fa0c37b225 100644 --- a/src/coreclr/inc/sstring.inl +++ b/src/coreclr/inc/sstring.inl @@ -45,11 +45,79 @@ // Inline implementations. Pay no attention to that man behind the curtain. // --------------------------------------------------------------------------- +// Turn this on to test that these if you are testing common scenarios dealing with +// ASCII strings that do not touch the cases where this family of function differs +// in behavior for expected reasons. +//#define VERIFY_CRT_EQUIVALNCE 1 + +// Helpers for CRT function equivalance. +/* static */ +inline int __cdecl StaticStringHelpers::_stricmp(const CHAR *buffer1, const CHAR *buffer2) { + WRAPPER_NO_CONTRACT; + int returnValue = CaseCompareHelperA(buffer1, buffer2, 0, TRUE, FALSE); +#ifdef VERIFY_CRT_EQUIVALNCE + _ASSERTE((returnValue == 0) == (::_stricmp(buffer1, buffer2) == 0)); +#endif + return returnValue; + +} + +/* static */ +inline int __cdecl StaticStringHelpers::_strnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count) { + WRAPPER_NO_CONTRACT; + int returnValue = CaseCompareHelperA(buffer1, buffer2, count, TRUE, TRUE); +#ifdef VERIFY_CRT_EQUIVALNCE + _ASSERTE((returnValue == 0) == (::_strnicmp(buffer1, buffer2, count) == 0)); +#endif + return returnValue; +} + +/* static */ +inline int __cdecl StaticStringHelpers::_wcsicmp(const WCHAR *buffer1, const WCHAR *buffer2) { + WRAPPER_NO_CONTRACT; + int returnValue = CaseCompareHelper(buffer1, buffer2, 0, TRUE, FALSE); +#ifdef VERIFY_CRT_EQUIVALNCE + _ASSERTE((returnValue == 0) == (::_wcsicmp(buffer1, buffer2) == 0)); +#endif + return returnValue; + +} + +/* static */ +inline int __cdecl StaticStringHelpers::_wcsnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count) { + WRAPPER_NO_CONTRACT; + int returnValue = CaseCompareHelper(buffer1, buffer2, count, TRUE, TRUE); +#ifdef VERIFY_CRT_EQUIVALNCE + _ASSERTE((returnValue == 0) == (::_wcsnicmp(buffer1, buffer2, count) == 0)); +#endif + return returnValue; +} + +inline int StaticStringHelpers::_tstricmp(const CHAR *buffer1, const CHAR *buffer2) +{ + return _stricmp(buffer1, buffer2); +} + +inline int StaticStringHelpers::_tstricmp(const WCHAR *buffer1, const WCHAR *buffer2) +{ + return _wcsicmp(buffer1, buffer2); +} + +inline int StaticStringHelpers::_tstrnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count) +{ + return _strnicmp(buffer1, buffer2, count); +} + +inline int StaticStringHelpers::_tstrnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count) +{ + return _wcsnicmp(buffer1, buffer2, count); +} //---------------------------------------------------------------------------- // Default constructor. Sets the string to the empty string. //---------------------------------------------------------------------------- -inline SString::SString() - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +template +inline EString::EString() + : SBuffer(Immutable, StaticStringHelpers::s_EmptyBuffer, sizeof(char_t)) { #ifdef SSTRING_EXTRA_CHECKS CONTRACT_VOID @@ -69,1067 +137,460 @@ inline SString::SString() #endif } -inline SString::SString(void *buffer, COUNT_T size) - : SBuffer(Prealloc, buffer, size) +template +inline EString::EString(void* buffer, COUNT_T size, bool isAllocated) + : SBuffer(Prealloc, buffer, size) { - SS_CONTRACT_VOID - { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(CheckPointer(buffer)); - PRECONDITION(CheckSize(size)); - SS_POSTCONDITION(IsEmpty()); - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; - } - SS_CONTRACT_END; - - if (size < sizeof(WCHAR)) + // If this buffer was allocated on the heap, that ownership is passed to this instance. + if (isAllocated) { - // Ignore the useless buffer - SetImmutable(s_EmptyBuffer, sizeof(s_EmptyBuffer)); + if (GetRawBuffer() == nullptr) + { + // If we were unable to use the provided buffer, we need to release it as we now own the memory. + DeleteBuffer((BYTE*)buffer, size); + } + else + { + // Make sure to set the Allocated flag so we release it when resizing. + SetAllocated(); + } } - else - { - SBuffer::TweakSize(sizeof(WCHAR)); - GetRawUnicode()[0] = 0; - } - - SS_RETURN; } -inline SString::SString(const SString &s) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +template +inline EString::EString(const EString &s, const CIterator &i, COUNT_T count) + : EString() { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(s.Check()); - SS_POSTCONDITION(Equals(s)); + PRECONDITION(i.Check()); + PRECONDITION(CheckCount(count)); + SS_POSTCONDITION(s.Match(i, *this)); + SS_POSTCONDITION(GetCount() == count); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; - Set(s); + Set(s, i, count); SS_RETURN; } -inline SString::SString(const SString &s1, const SString &s2) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +//----------------------------------------------------------------------------- +// Set this string to the substring from s. +// s - the source string +// start - the character to start at +// length - number of characters to copy from s. +//----------------------------------------------------------------------------- +template +inline void EString::Set(const EString &s, const CIterator &i, COUNT_T count) { SS_CONTRACT_VOID { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(s1.Check()); - PRECONDITION(s2.Check()); + INSTANCE_CHECK; + PRECONDITION(s.Check()); + PRECONDITION(i.Check()); + PRECONDITION(CheckCount(count)); + SS_POSTCONDITION(s.Match(i, *this)); + SS_POSTCONDITION(GetCount() == count); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; - Set(s1, s2); + // @todo: detect case where we can reuse literal? + Resize(count); + SBuffer::Copy(SBuffer::Begin(), i.m_ptr, count * sizeof(char_t)); + NullTerminate(); SS_RETURN; } -inline SString::SString(const SString &s1, const SString &s2, const SString &s3) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +//----------------------------------------------------------------------------- +// Set this string to the substring from s. +// s - the source string +// start - the position to start +// end - the position to end (exclusive) +//----------------------------------------------------------------------------- +template +inline void EString::Set(const EString &s, const CIterator &start, const CIterator &end) { SS_CONTRACT_VOID { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(s1.Check()); - PRECONDITION(s2.Check()); - PRECONDITION(s3.Check()); + INSTANCE_CHECK; + PRECONDITION(s.Check()); + PRECONDITION(start.Check()); + PRECONDITION(s.CheckIteratorRange(start)); + PRECONDITION(end.Check()); + PRECONDITION(s.CheckIteratorRange(end)); + PRECONDITION(end >= start); + SS_POSTCONDITION(s.Match(start, *this)); + SS_POSTCONDITION(GetCount() == (COUNT_T) (end - start)); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; - Set(s1, s2, s3); + Set(s, start, end - start); SS_RETURN; } -inline SString::SString(const SString &s1, const SString &s2, const SString &s3, const SString &s4) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) + +//----------------------------------------------------------------------------- +// Hash the string contents +//----------------------------------------------------------------------------- +template +ULONG EString::Hash() const { - SS_CONTRACT_VOID + SS_CONTRACT(ULONG) { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(s1.Check()); - PRECONDITION(s2.Check()); - PRECONDITION(s3.Check()); - PRECONDITION(s4.Check()); + INSTANCE_CHECK; THROWS; + GC_NOTRIGGER; } SS_CONTRACT_END; - Set(s1, s2, s3, s4); + StackEString buffer; - SS_RETURN; + ConvertToUnicode(buffer); + + SS_RETURN HashString(buffer); } -inline SString::SString(const SString &s, const CIterator &i, COUNT_T count) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +//----------------------------------------------------------------------------- +// Hash the string contents +//----------------------------------------------------------------------------- +template +ULONG EString::HashCaseInsensitive() const { - SS_CONTRACT_VOID + SS_CONTRACT(ULONG) { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(s.Check()); - PRECONDITION(i.Check()); - PRECONDITION(CheckCount(count)); - SS_POSTCONDITION(s.Match(i, *this)); - SS_POSTCONDITION(GetRawCount() == count); - THROWS; + INSTANCE_CHECK; + NOTHROW; GC_NOTRIGGER; } SS_CONTRACT_END; - Set(s, i, count); + ULONG result = TEncoding::CaseHashHelper(GetRawBuffer(), GetCount()); - SS_RETURN; + SS_RETURN result; } -inline SString::SString(const SString &s, const CIterator &start, const CIterator &end) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +// Append s to the end of this string. +template +inline void EString::Append(const EString &s) { SS_CONTRACT_VOID { - SS_CONSTRUCTOR_CHECK; + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); PRECONDITION(s.Check()); - PRECONDITION(start.Check()); - PRECONDITION(s.CheckIteratorRange(start)); - PRECONDITION(end.Check()); - PRECONDITION(s.CheckIteratorRange(end)); - PRECONDITION(start <= end); - SS_POSTCONDITION(s.Match(start, *this)); - SS_POSTCONDITION(GetRawCount() == (COUNT_T) (end - start)); THROWS; - GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; - Set(s, start, end); + Insert(End(), s); SS_RETURN; } -inline SString::SString(const WCHAR *string) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +template +inline void EString::Append(const char_t *string) { SS_CONTRACT_VOID { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - THROWS; GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckPointer(string)); + THROWS; + SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; - Set(string); + // Wrap the string in temporary EString without copying it + EString s(EString::Literal, string); + s.ClearImmutable(); + Append(s); SS_RETURN; } -inline SString::SString(const WCHAR *string, COUNT_T count) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +template +inline void EString::Append(const char_t c) { SS_CONTRACT_VOID { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - PRECONDITION(CheckCount(count)); - THROWS; GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + THROWS; } SS_CONTRACT_END; - Set(string, count); + InlineEString<2 * sizeof(c), TEncoding> s(c); + Append(s); SS_RETURN; } -inline SString::SString(enum tagASCII, const ASCII *string) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +template +BOOL EString::Equals(const EString &s) const { - SS_CONTRACT_VOID + LIMITED_METHOD_CONTRACT; + return Compare(s) == 0; +} + +template +BOOL EString::EqualsCaseInsensitive(const EString &s) const +{ + LIMITED_METHOD_CONTRACT; + return CompareCaseInsensitive(s) == 0; +} + +//----------------------------------------------------------------------------- +// Compare this string's contents to s's contents. +// The comparison does not take into account localization issues like case folding. +// Return 0 if equal, <0 if this < s, >0 is this > s. (same as strcmp). +//----------------------------------------------------------------------------- +template +int EString::Compare(const EString &source) const +{ + CONTRACT(int) { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - PRECONDITION(CheckASCIIString(string)); - THROWS; + INSTANCE_CHECK; + PRECONDITION(source.Check()); + NOTHROW; GC_NOTRIGGER; } - SS_CONTRACT_END; + CONTRACT_END; - SetASCII(string); + COUNT_T smaller; + int equals = 0; + int result = 0; - SS_RETURN; -} + if (GetCount() < source.GetCount()) + { + smaller = GetCount(); + equals = -1; + } + else if (GetCount() > source.GetCount()) + { + smaller = source.GetCount(); + equals = 1; + } + else + { + smaller = GetCount(); + equals = 0; + } + + result = TEncoding::strncmp(GetRawBuffer(), source.GetRawBuffer(), smaller); -inline SString::SString(enum tagASCII, const ASCII *string, COUNT_T count) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) + if (result == 0) + RETURN equals; + else + RETURN result; +} +//----------------------------------------------------------------------------- +// Compare this string's contents to s's contents. +// Return 0 if equal, <0 if this < s, >0 is this > s. (same as strcmp). +//----------------------------------------------------------------------------- +template +int EString::CompareCaseInsensitive(const EString &source) const { - SS_CONTRACT_VOID + CONTRACT(int) { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - PRECONDITION(CheckASCIIString(string, count)); - PRECONDITION(CheckCount(count)); - THROWS; + INSTANCE_CHECK; + PRECONDITION(source.Check()); + NOTHROW; GC_NOTRIGGER; } - SS_CONTRACT_END; + CONTRACT_END; - SetASCII(string, count); + COUNT_T smaller; + int equals = 0; + int result = 0; - SS_RETURN; + if (GetCount() < source.GetCount()) + { + smaller = GetCount(); + equals = -1; + } + else if (GetCount() > source.GetCount()) + { + smaller = source.GetCount(); + equals = 1; + } + else + { + smaller = GetCount(); + equals = 0; + } + + result = TEncoding::CaseCompareHelper(GetRawBuffer(), source.GetRawBuffer(), smaller, FALSE, TRUE); + + if (result == 0) + RETURN equals; + else + RETURN result; } -inline SString::SString(tagUTF8 dummytag, const UTF8 *string) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +template +void EString::Set(const EString& s) { SS_CONTRACT_VOID { - SS_CONSTRUCTOR_CHECK; - // !!! Check for illegal UTF8 encoding? - PRECONDITION(CheckPointer(string, NULL_OK)); + INSTANCE_CHECK; + PRECONDITION(s.Check()); + SS_POSTCONDITION(Equals(s)); THROWS; GC_NOTRIGGER; SUPPORTS_DAC; } SS_CONTRACT_END; - SetUTF8(string); + SBuffer::Set(s); SS_RETURN; } -inline SString::SString(tagUTF8 dummytag, const UTF8 *string, COUNT_T count) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +template +void EString::Set(const char_t* string) { - SS_CONTRACT_VOID + CONTRACT_VOID { - SS_CONSTRUCTOR_CHECK; - // !!! Check for illegal UTF8 encoding? + INSTANCE_CHECK; PRECONDITION(CheckPointer(string, NULL_OK)); - PRECONDITION(CheckCount(count)); THROWS; GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; } - SS_CONTRACT_END; + CONTRACT_END; - SetUTF8(string, count); + if (string == NULL || *string == 0) + Clear(); + else + { + COUNT_T count = static_cast(TEncoding::strlen(string)); + Resize(count); + TEncoding::strncpy_s(GetRawBuffer(), GetSize() / sizeof(char_t), string, count + 1); + } - SS_RETURN; + RETURN; } -inline SString::SString(tagANSI dummytag, const ANSI *string) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +template +void EString::Set(const char_t* string, COUNT_T count) { - SS_CONTRACT_VOID + CONTRACT_VOID { - SS_CONSTRUCTOR_CHECK; + INSTANCE_CHECK; PRECONDITION(CheckPointer(string, NULL_OK)); + PRECONDITION(CheckCount(count)); THROWS; GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; } - SS_CONTRACT_END; + CONTRACT_END; - SetANSI(string); + if (string == NULL || *string == 0) + Clear(); + else + { + Resize(count); + TEncoding::strncpy_s(GetRawBuffer(), GetSize() / sizeof(char_t), string, count); + GetRawBuffer()[count] = static_cast(0); + } - SS_RETURN; + RETURN; } -inline SString::SString(tagANSI dummytag, const ANSI *string, COUNT_T count) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +template +void EString::Set(const char_t c) { - SS_CONTRACT_VOID + CONTRACT_VOID { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - PRECONDITION(CheckCount(count)); + INSTANCE_CHECK; THROWS; GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; } - SS_CONTRACT_END; + CONTRACT_END; - SetANSI(string, count); + if (c == 0) + Clear(); + else + { + Resize(1); + GetRawBuffer()[0] = c; + GetRawBuffer()[1] = static_cast(0); + } - SS_RETURN; + RETURN; } -inline SString::SString(WCHAR character) - : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) -{ - SS_CONTRACT_VOID - { - SS_CONSTRUCTOR_CHECK; - THROWS; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - - Set(character); - - SS_RETURN; -} - -inline SString::SString(tagLiteral dummytag, const ASCII *literal) - : SBuffer(Immutable, (const BYTE *) literal, (COUNT_T) (strlen(literal)+1)*sizeof(CHAR)) -{ - SS_CONTRACT_VOID - { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(CheckPointer(literal)); - PRECONDITION(CheckASCIIString(literal)); - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; - } - SS_CONTRACT_END; - - SetRepresentation(REPRESENTATION_ASCII); - - SS_RETURN; -} - -inline SString::SString(tagUTF8Literal dummytag, const UTF8 *literal) - : SBuffer(Immutable, (const BYTE *) literal, (COUNT_T) (strlen(literal)+1)*sizeof(CHAR)) -{ - SS_CONTRACT_VOID - { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(CheckPointer(literal)); - NOTHROW; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - - SetRepresentation(REPRESENTATION_UTF8); - - SS_RETURN; -} - -inline SString::SString(tagLiteral dummytag, const WCHAR *literal) - : SBuffer(Immutable, (const BYTE *) literal, (COUNT_T) (wcslen(literal)+1)*sizeof(WCHAR)) -{ - SS_CONTRACT_VOID - { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(CheckPointer(literal)); - NOTHROW; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - - SetRepresentation(REPRESENTATION_UNICODE); - SetNormalized(); - - SS_RETURN; -} - -inline SString::SString(tagLiteral dummytag, const WCHAR *literal, COUNT_T count) - : SBuffer(Immutable, (const BYTE *) literal, (count + 1) * sizeof(WCHAR)) -{ - SS_CONTRACT_VOID - { - SS_CONSTRUCTOR_CHECK; - PRECONDITION(CheckPointer(literal)); - NOTHROW; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - - SetRepresentation(REPRESENTATION_UNICODE); - SetNormalized(); - - SS_RETURN; -} - -//----------------------------------------------------------------------------- -// Set this string to s -// s - source string -//----------------------------------------------------------------------------- -inline void SString::Set(const SString &s) -{ - SS_CONTRACT_VOID - { - INSTANCE_CHECK; - PRECONDITION(s.Check()); - SS_POSTCONDITION(Equals(s)); - THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC; - } - SS_CONTRACT_END; - - SBuffer::Set(s); - SetRepresentation(s.GetRepresentation()); - ClearNormalized(); - - SS_RETURN; -} - -//----------------------------------------------------------------------------- -// Set this string to concatenation of s1 and s2 -//----------------------------------------------------------------------------- -inline void SString::Set(const SString &s1, const SString &s2) -{ - SS_CONTRACT_VOID - { - INSTANCE_CHECK; - PRECONDITION(s1.Check()); - PRECONDITION(s2.Check()); - THROWS; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - - Preallocate(s1.GetCount() + s2.GetCount()); - - Set(s1); - Append(s2); - - SS_RETURN; -} - -//----------------------------------------------------------------------------- -// Set this string to concatenation of s1, s2, and s3 -//----------------------------------------------------------------------------- -inline void SString::Set(const SString &s1, const SString &s2, const SString &s3) -{ - SS_CONTRACT_VOID - { - INSTANCE_CHECK; - PRECONDITION(s1.Check()); - PRECONDITION(s2.Check()); - PRECONDITION(s3.Check()); - THROWS; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - - Preallocate(s1.GetCount() + s2.GetCount() + s3.GetCount()); - - Set(s1); - Append(s2); - Append(s3); - - SS_RETURN; -} - -//----------------------------------------------------------------------------- -// Set this string to concatenation of s1, s2, s3, and s4 -//----------------------------------------------------------------------------- -inline void SString::Set(const SString &s1, const SString &s2, const SString &s3, const SString &s4) -{ - SS_CONTRACT_VOID - { - INSTANCE_CHECK; - PRECONDITION(s1.Check()); - PRECONDITION(s2.Check()); - PRECONDITION(s3.Check()); - PRECONDITION(s4.Check()); - THROWS; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - - Preallocate(s1.GetCount() + s2.GetCount() + s3.GetCount() + s4.GetCount()); - - Set(s1); - Append(s2); - Append(s3); - Append(s4); - - SS_RETURN; -} - -//----------------------------------------------------------------------------- -// Set this string to the substring from s. -// s - the source string -// start - the character to start at -// length - number of characters to copy from s. -//----------------------------------------------------------------------------- -inline void SString::Set(const SString &s, const CIterator &i, COUNT_T count) -{ - SS_CONTRACT_VOID - { - INSTANCE_CHECK; - PRECONDITION(s.Check()); - PRECONDITION(i.Check()); - PRECONDITION(CheckCount(count)); - SS_POSTCONDITION(s.Match(i, *this)); - SS_POSTCONDITION(GetRawCount() == count); - THROWS; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - - // @todo: detect case where we can reuse literal? - Resize(count, s.GetRepresentation()); - SBuffer::Copy(SBuffer::Begin(), i.m_ptr, count<= start); - SS_POSTCONDITION(s.Match(start, *this)); - SS_POSTCONDITION(GetRawCount() == (COUNT_T) (end - start)); - THROWS; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - - Set(s, start, end - start); - - SS_RETURN; -} - -// Return a global empty string -inline const SString &SString::Empty() -{ -#ifdef SSTRING_EXTRA_CHECKS - CONTRACTL - { - // POSTCONDITION(RETVAL.IsEmpty()); - PRECONDITION(CheckStartup()); - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - SUPPORTS_DAC; - } - CONTRACTL_END; -#else - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_CANNOT_TAKE_LOCK; - STATIC_CONTRACT_SUPPORTS_DAC; -#endif - - _ASSERTE(s_Empty != NULL); // Did you call SString::Startup()? - return *s_Empty; -} - -// Get a const pointer to the internal buffer as a unicode string. -inline const WCHAR *SString::GetUnicode() const -{ - SS_CONTRACT(const WCHAR *) - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(CheckPointer(RETVAL)); - if (IsRepresentation(REPRESENTATION_UNICODE)) NOTHROW; else THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC; - } - SS_CONTRACT_END; - - ConvertToUnicode(); - - SS_RETURN GetRawUnicode(); -} - -// Normalize the string to unicode. This will make many operations nonfailing. -inline void SString::Normalize() const -{ - SS_CONTRACT_VOID - { - INSTANCE_CHECK; - SS_POSTCONDITION(IsNormalized()); - THROWS_UNLESS_NORMALIZED; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - - ConvertToUnicode(); - SetNormalized(); - - SS_RETURN; -} - -// Get a const pointer to the internal buffer as a unicode string. -inline const WCHAR *SString::GetUnicode(const CIterator &i) const -{ - SS_CONTRACT(const WCHAR *) - { - INSTANCE_CHECK; - PRECONDITION(CheckIteratorRange(i)); - THROWS_UNLESS_NORMALIZED; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - - PRECONDITION(CheckPointer(this)); - - ConvertToUnicode(i); - - SS_RETURN i.GetUnicode(); -} - -// Append s to the end of this string. -inline void SString::Append(const SString &s) -{ - SS_CONTRACT_VOID - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(s.Check()); - THROWS; - SUPPORTS_DAC_HOST_ONLY; - } - SS_CONTRACT_END; - - Insert(End(), s); - - SS_RETURN; -} - -inline void SString::Append(const WCHAR *string) -{ - SS_CONTRACT_VOID - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckPointer(string)); - THROWS; - SUPPORTS_DAC_HOST_ONLY; - } - SS_CONTRACT_END; - - // Wrap the string in temporary SString without copying it - SString s(SString::Literal, string); - s.ClearImmutable(); - Append(s); - - SS_RETURN; -} - -inline void SString::AppendASCII(const CHAR *string) -{ - SS_CONTRACT_VOID - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckPointer(string)); - THROWS; - } - SS_CONTRACT_END; - - StackSString s(SString::Ascii, string); - Append(s); - - SS_RETURN; -} - -inline void SString::AppendUTF8(const CHAR *string) -{ - SS_CONTRACT_VOID - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckPointer(string)); - THROWS; - } - SS_CONTRACT_END; - - StackSString s(SString::Utf8, string); - Append(s); - - SS_RETURN; -} - -inline void SString::Append(const WCHAR c) -{ - SS_CONTRACT_VOID - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - THROWS; - } - SS_CONTRACT_END; - - InlineSString<2 * sizeof(c)> s(c); - Append(s); - - SS_RETURN; -} - -inline void SString::AppendUTF8(const CHAR c) -{ - SS_CONTRACT_VOID - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - THROWS; - SUPPORTS_DAC_HOST_ONLY; - } - SS_CONTRACT_END; - - InlineSString<2 * sizeof(c)> s(SString::Utf8, c); - Append(s); - - SS_RETURN; -} - -// Turn this on to test that these if you are testing common scenarios dealing with -// ASCII strings that do not touch the cases where this family of function differs -// in behavior for expected reasons. -//#define VERIFY_CRT_EQUIVALNCE 1 - -// Helpers for CRT function equivalance. -/* static */ -inline int __cdecl SString::_stricmp(const CHAR *buffer1, const CHAR *buffer2) { - WRAPPER_NO_CONTRACT; - int returnValue = CaseCompareHelperA(buffer1, buffer2, 0, TRUE, FALSE); -#ifdef VERIFY_CRT_EQUIVALNCE - _ASSERTE((returnValue == 0) == (::_stricmp(buffer1, buffer2) == 0)); -#endif - return returnValue; - -} - -/* static */ -inline int __cdecl SString::_strnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count) { - WRAPPER_NO_CONTRACT; - int returnValue = CaseCompareHelperA(buffer1, buffer2, count, TRUE, TRUE); -#ifdef VERIFY_CRT_EQUIVALNCE - _ASSERTE((returnValue == 0) == (::_strnicmp(buffer1, buffer2, count) == 0)); -#endif - return returnValue; -} - -/* static */ -inline int __cdecl SString::_wcsicmp(const WCHAR *buffer1, const WCHAR *buffer2) { - WRAPPER_NO_CONTRACT; - int returnValue = CaseCompareHelper(buffer1, buffer2, 0, TRUE, FALSE); -#ifdef VERIFY_CRT_EQUIVALNCE - _ASSERTE((returnValue == 0) == (::_wcsicmp(buffer1, buffer2) == 0)); -#endif - return returnValue; - -} - -/* static */ -inline int __cdecl SString::_wcsnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count) { - WRAPPER_NO_CONTRACT; - int returnValue = CaseCompareHelper(buffer1, buffer2, count, TRUE, TRUE); -#ifdef VERIFY_CRT_EQUIVALNCE - _ASSERTE((returnValue == 0) == (::_wcsnicmp(buffer1, buffer2, count) == 0)); -#endif - return returnValue; -} - -inline int SString::_tstricmp(const CHAR *buffer1, const CHAR *buffer2) -{ - return _stricmp(buffer1, buffer2); -} - -inline int SString::_tstricmp(const WCHAR *buffer1, const WCHAR *buffer2) -{ - return _wcsicmp(buffer1, buffer2); -} - -inline int SString::_tstrnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count) -{ - return _strnicmp(buffer1, buffer2, count); -} - -inline int SString::_tstrnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count) -{ - return _wcsnicmp(buffer1, buffer2, count); -} - -inline BOOL SString::Match(const CIterator &i, WCHAR c) const -{ - SS_CONTRACT(BOOL) - { - GC_NOTRIGGER; - INSTANCE_CHECK; - PRECONDITION(CheckIteratorRange(i)); - NOTHROW; - } - SS_CONTRACT_END; - - // End() will not throw here - CONTRACT_VIOLATION(ThrowsViolation); - SS_RETURN (i < End() && i[0] == c); -} - -inline BOOL SString::Skip(CIterator &i, const SString &s) const -{ - SS_CONTRACT(BOOL) - { - GC_NOTRIGGER; - INSTANCE_CHECK; - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(s.Check()); - THROWS_UNLESS_BOTH_NORMALIZED(s); - } - SS_CONTRACT_END; - - if (Match(i, s)) - { - i += s.GetRawCount(); - SS_RETURN TRUE; - } - else - SS_RETURN FALSE; -} - -inline BOOL SString::Skip(CIterator &i, WCHAR c) const -{ - SS_CONTRACT(BOOL) - { - GC_NOTRIGGER; - INSTANCE_CHECK; - PRECONDITION(CheckIteratorRange(i)); - NOTHROW; - } - SS_CONTRACT_END; - - if (Match(i, c)) - { - i++; - SS_RETURN TRUE; - } - else - SS_RETURN FALSE; -} - -// Find string within this string. Return TRUE and update iterator if found -inline BOOL SString::Find(CIterator &i, const WCHAR *string) const -{ - SS_CONTRACT(BOOL) - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(CheckPointer(string)); - SS_POSTCONDITION(RETVAL == Match(i, SString(string))); - THROWS; - } - SS_CONTRACT_END; - - StackSString s(string); - SS_RETURN Find(i, s); -} - -inline BOOL SString::FindASCII(CIterator &i, const CHAR *string) const -{ - SS_CONTRACT(BOOL) - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(CheckPointer(string)); - SS_POSTCONDITION(RETVAL == Match(i, SString(SString::Ascii, string))); - THROWS; - } - SS_CONTRACT_END; - - StackSString s(SString::Ascii, string); - SS_RETURN Find(i, s); -} - -inline BOOL SString::FindUTF8(CIterator &i, const CHAR *string) const -{ - SS_CONTRACT(BOOL) - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(CheckPointer(string)); - SS_POSTCONDITION(RETVAL == Match(i, SString(SString::Ascii, string))); - THROWS; - } - SS_CONTRACT_END; - - StackSString s(SString::Utf8, string); - SS_RETURN Find(i, s); -} - -inline BOOL SString::FindBack(CIterator &i, const WCHAR *string) const -{ - SS_CONTRACT(BOOL) - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(CheckPointer(string)); - SS_POSTCONDITION(RETVAL == Match(i, SString(string))); - THROWS; - } - SS_CONTRACT_END; - - StackSString s(string); - SS_RETURN FindBack(i, s); -} - -inline BOOL SString::FindBackASCII(CIterator &i, const CHAR *string) const -{ - SS_CONTRACT(BOOL) - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(CheckPointer(string)); - SS_POSTCONDITION(RETVAL == Match(i, SString(SString::Ascii, string))); - THROWS; - } - SS_CONTRACT_END; - - StackSString s(SString::Ascii, string); - SS_RETURN FindBack(i, s); -} - -inline BOOL SString::FindBackUTF8(CIterator &i, const CHAR *string) const -{ - SS_CONTRACT(BOOL) - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(CheckPointer(string)); - SS_POSTCONDITION(RETVAL == Match(i, SString(SString::Ascii, string))); - THROWS; - } - SS_CONTRACT_END; - - StackSString s(SString::Utf8, string); - SS_RETURN FindBack(i, s); -} - -// Insert string at iterator position -inline void SString::Insert(const Iterator &i, const SString &s) -{ - SS_CONTRACT_VOID - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(s.Check()); - THROWS; - SUPPORTS_DAC_HOST_ONLY; - } - SS_CONTRACT_END; - - Replace(i, 0, s); - - SS_RETURN; -} - -inline void SString::Insert(const Iterator &i, const WCHAR *string) -{ - SS_CONTRACT_VOID - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(CheckPointer(string)); - THROWS; - } - SS_CONTRACT_END; - - StackSString s(string); - Replace(i, 0, s); - - SS_RETURN; -} - -inline void SString::InsertASCII(const Iterator &i, const CHAR *string) -{ - SS_CONTRACT_VOID - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(CheckPointer(string)); - THROWS; - } - SS_CONTRACT_END; - - StackSString s(SString::Ascii, string); - Replace(i, 0, s); - - SS_RETURN; -} - -inline void SString::InsertUTF8(const Iterator &i, const CHAR *string) +template +void EString::SetPreallocated(const char_t* string, COUNT_T count) { SS_CONTRACT_VOID { + INSTANCE_CHECK; + PRECONDITION(CheckPointer(string, NULL_OK)); + PRECONDITION(CheckCount(count)); GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(CheckPointer(string)); - THROWS; + NOTHROW; + SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; - StackSString s(SString::Utf8, string); - Replace(i, 0, s); + SetImmutable(); + SetImmutable((BYTE*) string, static_cast(count * sizeof(char_t))); + ClearAllocated(); SS_RETURN; } -// Delete string at iterator position -inline void SString::Delete(const Iterator &i, COUNT_T length) +template +void EString::SetLiteral(const char_t* string) { SS_CONTRACT_VOID { + INSTANCE_CHECK; + PRECONDITION(CheckPointer(string, NULL_OK)); GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckIteratorRange(i, length)); THROWS; SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; - Replace(i, length, Empty()); + Set(EString(EString::Literal, string)); SS_RETURN; } // Preallocate some space for the string buffer -inline void SString::Preallocate(COUNT_T characters) const +template +inline void EString::Preallocate(COUNT_T characters) const { WRAPPER_NO_CONTRACT; - // Assume unicode since we may get converted - SBuffer::Preallocate(characters * sizeof(WCHAR)); + SBuffer::Preallocate(characters * sizeof(char_t)); } // Trim unused space from the buffer -inline void SString::Trim() const +template +inline void EString::Trim() const { WRAPPER_NO_CONTRACT; - if (GetRawCount() == 0) + if (IsEmpty()) { // Share the global empty string buffer. - const_cast(this)->SBuffer::SetImmutable(s_EmptyBuffer, sizeof(s_EmptyBuffer)); + const_cast(this)->SBuffer::SetImmutable(StaticStringHelpers::s_EmptyBuffer, sizeof(StaticStringHelpers::s_EmptyBuffer)); } else { @@ -1138,136 +599,19 @@ inline void SString::Trim() const } // RETURN true if the string is empty. -inline BOOL SString::IsEmpty() const -{ - SS_CONTRACT(BOOL) - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - NOTHROW; - SUPPORTS_DAC; - } - SS_CONTRACT_END; - - SS_RETURN (GetRawCount() == 0); -} - -// RETURN true if the string rep is ASCII. -inline BOOL SString::IsASCII() const +template +inline BOOL EString::IsEmpty() const { SS_CONTRACT(BOOL) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); NOTHROW; - } - SS_CONTRACT_END; - - SS_RETURN IsRepresentation(REPRESENTATION_ASCII); -} - -// Get the number of characters in the string (excluding the terminating NULL) -inline COUNT_T SString::GetCount() const -{ - SS_CONTRACT(COUNT_T) - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(CheckCount(RETVAL)); - THROWS_UNLESS_NORMALIZED; SUPPORTS_DAC; } SS_CONTRACT_END; - ConvertToFixed(); - - SS_RETURN SizeToCount(GetSize()); -} - -// Private helpers: -// Return the current size of the string (even if it is multibyte) -inline COUNT_T SString::GetRawCount() const -{ - WRAPPER_NO_CONTRACT; - - return SizeToCount(GetSize()); -} - -// Private helpers: -// get string contents as a particular character set: - -inline ASCII *SString::GetRawASCII() const -{ - LIMITED_METHOD_DAC_CONTRACT; - - return (ASCII *) m_buffer; -} - -inline UTF8 *SString::GetRawUTF8() const -{ - LIMITED_METHOD_DAC_CONTRACT; - - return (UTF8 *) m_buffer; -} - -inline ANSI *SString::GetRawANSI() const -{ - LIMITED_METHOD_DAC_CONTRACT; - - return (ANSI *) m_buffer; -} - -inline WCHAR *SString::GetRawUnicode() const -{ - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC_HOST_ONLY; - - return (WCHAR *)m_buffer; -} - -// Private helper: -// get the representation (ansi, unicode, utf8) -inline SString::Representation SString::GetRepresentation() const -{ - WRAPPER_NO_CONTRACT; - - return (Representation) SBuffer::GetRepresentationField(); -} - -// Private helper. -// Set the representation. -inline void SString::SetRepresentation(SString::Representation representation) -{ -#ifdef SSTRING_EXTRA_CHECKS - CONTRACT_VOID - { - GC_NOTRIGGER; - NOTHROW; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckRepresentation(representation)); - POSTCONDITION(GetRepresentation() == representation); - } - CONTRACT_END; -#else //SSTRING_EXTRA_CHECKS - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; -#endif //SSTRING_EXTRA_CHECKS - - SBuffer::SetRepresentationField((int) representation); - - SS_RETURN; -} - -// Private helper: -// Get the amount to shift the byte size to get a character count -inline int SString::GetCharacterSizeShift() const -{ - WRAPPER_NO_CONTRACT; - - // Note that the flag is backwards; we want the default - // value to match the default representation (empty) - return (GetRepresentation()&REPRESENTATION_SINGLE_MASK) == 0; + SS_RETURN (SizeToCount(GetSize()) == 0); } //---------------------------------------------------------------------------- @@ -1275,7 +619,8 @@ inline int SString::GetCharacterSizeShift() const // We know the buffer should be m_count characters. Place a null terminator // in the buffer to make our internal string null-terminated at that length. //---------------------------------------------------------------------------- -FORCEINLINE void SString::NullTerminate() +template +FORCEINLINE void EString::NullTerminate() { SUPPORTS_DAC_HOST_ONLY; #ifdef SSTRING_EXTRA_CHECKS @@ -1293,14 +638,7 @@ FORCEINLINE void SString::NullTerminate() BYTE *end = m_buffer + GetSize(); - if (GetRepresentation()&REPRESENTATION_SINGLE_MASK) - { - ((CHAR *)end)[-1] = 0; - } - else - { - ((WCHAR *)end)[-1] = 0; - } + reinterpret_cast(end)[-1] = 0; SS_RETURN; } @@ -1310,11 +648,12 @@ FORCEINLINE void SString::NullTerminate() // Return true if the string is a literal. // A literal string has immutable memory. //---------------------------------------------------------------------------- -inline BOOL SString::IsLiteral() const +template +inline BOOL EString::IsLiteral() const { WRAPPER_NO_CONTRACT; - return SBuffer::IsImmutable() && (m_buffer != s_EmptyBuffer); + return SBuffer::IsImmutable() && (m_buffer != StaticStringHelpers::s_EmptyBuffer); } //---------------------------------------------------------------------------- @@ -1323,7 +662,8 @@ inline BOOL SString::IsLiteral() const // IsAllocated() will RETURN false for Literal strings and // stack-based strings (the buffer is on the stack) //---------------------------------------------------------------------------- -inline BOOL SString::IsAllocated() const +template +inline BOOL EString::IsAllocated() const { WRAPPER_NO_CONTRACT; @@ -1331,894 +671,1008 @@ inline BOOL SString::IsAllocated() const } //---------------------------------------------------------------------------- -// Return true after we call OpenBuffer(), but before we close it. -// All SString operations are illegal while the buffer is open. +// Assert helper +// Asser that the iterator is within the given string. //---------------------------------------------------------------------------- -#if _DEBUG -inline BOOL SString::IsBufferOpen() const +template +inline CHECK EString::CheckIteratorRange(const CIterator &i) const { - WRAPPER_NO_CONTRACT; - - return SBuffer::IsOpened(); + CANNOT_HAVE_CONTRACT; + CHECK(i >= Begin()); + CHECK(i <= End()); // Note that it's OK to look at the terminating null + CHECK_OK; } -#endif //---------------------------------------------------------------------------- -// Return true if we've scanned the string to see if it is in the ASCII subset. +// Assert helper +// Asser that the iterator is within the given string. //---------------------------------------------------------------------------- -inline BOOL SString::IsASCIIScanned() const +template +inline CHECK EString::CheckIteratorRange(const CIterator &i, COUNT_T length) const { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - return SBuffer::IsFlag1(); + CANNOT_HAVE_CONTRACT; + CHECK(i >= Begin()); + CHECK(i + length <= End()); // Note that it's OK to look at the terminating null + CHECK_OK; } //---------------------------------------------------------------------------- -// Set that we've scanned the string to see if it is in the ASCII subset. +// Assert that the string is empty //---------------------------------------------------------------------------- -inline void SString::SetASCIIScanned() const +template +inline CHECK EString::CheckEmpty() const { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC_HOST_ONLY; - - const_cast(this)->SBuffer::SetFlag1(); + CANNOT_HAVE_CONTRACT; + CHECK(IsEmpty()); + CHECK_OK; } //---------------------------------------------------------------------------- -// Return true if we've normalized the string to unicode +// Check the range of a count //---------------------------------------------------------------------------- -inline BOOL SString::IsNormalized() const +template +inline CHECK EString::CheckCount(COUNT_T count) { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - return SBuffer::IsFlag3(); + CANNOT_HAVE_CONTRACT; + CHECK(CheckSize(count*sizeof(WCHAR))); + CHECK_OK; } +#if CHECK_INVARIANTS //---------------------------------------------------------------------------- -// Set that we've normalized the string to unicode +// Check routine and invariants. //---------------------------------------------------------------------------- -inline void SString::SetNormalized() const -{ - WRAPPER_NO_CONTRACT; - const_cast(this)->SBuffer::SetFlag3(); +template +inline CHECK EString::Check() const +{ + CANNOT_HAVE_CONTRACT; + CHECK(SBuffer::Check()); + CHECK_OK; } -//---------------------------------------------------------------------------- -// Clear normalization -//---------------------------------------------------------------------------- -inline void SString::ClearNormalized() const +template +inline CHECK EString::Invariant() const { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC_HOST_ONLY; + CANNOT_HAVE_CONTRACT; + CHECK(SBuffer::Invariant()); + CHECK_OK; +} - const_cast(this)->SBuffer::ClearFlag3(); +template +inline CHECK EString::InternalInvariant() const +{ + CANNOT_HAVE_CONTRACT; + CHECK(SBuffer::InternalInvariant()); + CHECK(SBuffer::GetSize() >= 2); + CHECK_OK; } +#endif // CHECK_INVARIANTS //---------------------------------------------------------------------------- -// Private helper. -// Check to see if the string representation has single byte size +// EnsureWritable +// Ensures that the buffer is writable //---------------------------------------------------------------------------- -inline BOOL SString::IsSingleByte() const +template +inline void EString::EnsureWritable() const { - STATIC_CONTRACT_NOTHROW; +#ifdef SSTRING_EXTRA_CHECKS + CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + POSTCONDITION(!IsLiteral()); + THROWS; + } + CONTRACT_END; +#else //SSTRING_EXTRA_CHECKS STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_THROWS; +#endif //SSTRING_EXTRA_CHECKS + + if (IsLiteral()) + const_cast(this)->Resize(GetSize(), PRESERVE); - return ((GetRepresentation()&REPRESENTATION_SINGLE_MASK) != 0); + SS_RETURN; } -//---------------------------------------------------------------------------- -// Private helper. -// Check to see if the string representation has fixed size characters -//---------------------------------------------------------------------------- -inline BOOL SString::IsFixedSize() const +//----------------------------------------------------------------------------- +// Create CIterators on the string. +//----------------------------------------------------------------------------- +template +FORCEINLINE typename EString::CIterator EString::Begin() const { - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_SUPPORTS_DAC; + SS_CONTRACT(EString::CIterator) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckValue(RETVAL)); + NOTHROW; + } + SS_CONTRACT_END; - if (GetRepresentation()&REPRESENTATION_VARIABLE_MASK) - return FALSE; - else - return TRUE; + SS_RETURN CIterator(this, 0); } -//---------------------------------------------------------------------------- -// Private helper. -// Check to see if the string representation is appropriate for iteration -//---------------------------------------------------------------------------- -inline BOOL SString::IsIteratable() const +template +FORCEINLINE typename EString::CIterator EString::End() const { - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_SUPPORTS_DAC; + SS_CONTRACT(EString::CIterator) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckValue(RETVAL)); + NOTHROW; + } + SS_CONTRACT_END; + + SS_RETURN CIterator(this, SizeToCount(GetSize())); +} + +//----------------------------------------------------------------------------- +// Create Iterators on the string. +//----------------------------------------------------------------------------- + +template +FORCEINLINE typename EString::Iterator EString::Begin() +{ + SS_CONTRACT(EString::Iterator) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckValue(RETVAL)); + THROWS; // EnsureMutable always throws + SUPPORTS_DAC; + } + SS_CONTRACT_END; - // Note that in many cases ANSI may be fixed width. However we - // currently still do not allow iterating on them, because we would have to - // do character-by-character conversion on a character dereference (which must - // go to unicode) . We may want to adjust this going forward to - // depending on perf in the non-ASCII but fixed width ANSI case. + EnsureMutable(); - return ((GetRepresentation()&REPRESENTATION_VARIABLE_MASK) == 0); + SS_RETURN Iterator(this, 0); } -//---------------------------------------------------------------------------- -// Private helper -// Return the size of the given string in bytes -// in the given representation. -// count does not include the null-terminator, but the RETURN value does. -//---------------------------------------------------------------------------- -inline COUNT_T SString::CountToSize(COUNT_T count) const +template +FORCEINLINE typename EString::Iterator EString::End() { - SS_CONTRACT(COUNT_T) + SS_CONTRACT(EString::Iterator) { GC_NOTRIGGER; - PRECONDITION(CheckCount(count)); - SS_POSTCONDITION(SizeToCount(RETVAL) == count); - NOTHROW; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckValue(RETVAL)); + THROWS; // EnsureMutable always Throws SUPPORTS_DAC; } SS_CONTRACT_END; - SS_RETURN (count+1) << GetCharacterSizeShift(); + EnsureMutable(); + + SS_RETURN Iterator(this, SizeToCount(GetSize())); } -//---------------------------------------------------------------------------- -// Private helper. -// Return the maxmimum count of characters that could fit in a buffer of -// 'size' bytes in the given representation. -// 'size' includes the null terminator, but the RETURN value does not. -//---------------------------------------------------------------------------- -inline COUNT_T SString::SizeToCount(COUNT_T size) const +//----------------------------------------------------------------------------- +// CIterator support routines +//----------------------------------------------------------------------------- + +template +inline EString::Index::Index() +{ + LIMITED_METHOD_CONTRACT; +} + +template +inline EString::Index::Index(EString *string, SCOUNT_T index) + : SBuffer::Index(string, index * sizeof(char_t)) { - SS_CONTRACT(COUNT_T) + SS_CONTRACT_VOID { GC_NOTRIGGER; - PRECONDITION(CheckSize(size)); - SS_POSTCONDITION(CountToSize(RETVAL) == size); + PRECONDITION(CheckPointer(string)); + PRECONDITION(DoCheck(0)); + SS_POSTCONDITION(CheckPointer(this)); + // POSTCONDITION(Subtract(string->Begin()) == index); contract violation - fix later NOTHROW; + CANNOT_TAKE_LOCK; SUPPORTS_DAC; } SS_CONTRACT_END; - SS_RETURN (size >> GetCharacterSizeShift()) - 1; + SS_RETURN; } -//---------------------------------------------------------------------------- -// Private helper. -// Return the maxmimum count of characters that could fit in the current -// buffer including NULL terminator. -//---------------------------------------------------------------------------- -inline COUNT_T SString::GetBufferSizeInCharIncludeNullChar() const +template +inline BYTE &EString::Index::GetAt(SCOUNT_T delta) const { - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_SUPPORTS_DAC; + LIMITED_METHOD_DAC_CONTRACT; - return (GetSize() >> GetCharacterSizeShift()); + return m_ptr[delta * sizeof(char_t)]; } - - -//---------------------------------------------------------------------------- -// Assert helper -// Asser that the iterator is within the given string. -//---------------------------------------------------------------------------- -inline CHECK SString::CheckIteratorRange(const CIterator &i) const +template +inline void EString::Index::Skip(SCOUNT_T delta) { - CANNOT_HAVE_CONTRACT; - CHECK(i >= Begin()); - CHECK(i <= End()); // Note that it's OK to look at the terminating null - CHECK_OK; -} + LIMITED_METHOD_DAC_CONTRACT; -//---------------------------------------------------------------------------- -// Assert helper -// Asser that the iterator is within the given string. -//---------------------------------------------------------------------------- -inline CHECK SString::CheckIteratorRange(const CIterator &i, COUNT_T length) const -{ - CANNOT_HAVE_CONTRACT; - CHECK(i >= Begin()); - CHECK(i + length <= End()); // Note that it's OK to look at the terminating null - CHECK_OK; + m_ptr += delta * sizeof(char_t); } -//---------------------------------------------------------------------------- -// Assert that the string is empty -//---------------------------------------------------------------------------- -inline CHECK SString::CheckEmpty() const +template +inline SCOUNT_T EString::Index::Subtract(const Index &i) const { - CANNOT_HAVE_CONTRACT; - CHECK(IsEmpty()); - CHECK_OK; + LIMITED_METHOD_DAC_CONTRACT; + + return (SCOUNT_T) ((m_ptr - i.m_ptr) / (SCOUNT_T)sizeof(char_t)); } -//---------------------------------------------------------------------------- -// Check the range of a count -//---------------------------------------------------------------------------- -inline CHECK SString::CheckCount(COUNT_T count) +template +inline CHECK EString::Index::DoCheck(SCOUNT_T delta) const { CANNOT_HAVE_CONTRACT; - CHECK(CheckSize(count*sizeof(WCHAR))); +#if _DEBUG + const EString *string = (const EString *) GetContainerDebug(); + + CHECK(m_ptr + (delta * sizeof(char_t)) >= string->m_buffer); + CHECK(m_ptr + (delta * sizeof(char_t)) < string->m_buffer + string->GetSize()); +#endif CHECK_OK; } -//---------------------------------------------------------------------------- -// Check the representation field -//---------------------------------------------------------------------------- -inline CHECK SString::CheckRepresentation(int representation) +template +inline void EString::Index::Resync(const EString *string, BYTE *ptr) const { - CANNOT_HAVE_CONTRACT; - CHECK(representation == REPRESENTATION_EMPTY - || representation == REPRESENTATION_UNICODE - || representation == REPRESENTATION_ASCII - || representation == REPRESENTATION_UTF8 - || representation == REPRESENTATION_ANSI); - CHECK((representation & REPRESENTATION_MASK) == representation); + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; - CHECK_OK; + SBuffer::Index::Resync(string, ptr); } -#if CHECK_INVARIANTS -//---------------------------------------------------------------------------- -// Assert helper. Check that the string only uses the ASCII subset of -// codes. -//---------------------------------------------------------------------------- -inline CHECK SString::CheckASCIIString(const CHAR *string) +template +inline auto EString::Index::operator*() const -> const char_t& { - CANNOT_HAVE_CONTRACT; - if (string != NULL) - CHECK(CheckASCIIString(string, (int) strlen(string))); - CHECK_OK; + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + return *reinterpret_cast(&GetAt(0)); } -inline CHECK SString::CheckASCIIString(const CHAR *string, COUNT_T count) +template +inline auto EString::Index::operator*() -> char_t& { - CANNOT_HAVE_CONTRACT; -#if _DEBUG - const CHAR *sEnd = string + count; - while (string < sEnd) - { - CHECK_MSG((*string & 0x80) == 0x00, "Found non-ASCII character in string."); - string++; - } -#endif - CHECK_OK; -} + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; -//---------------------------------------------------------------------------- -// Check routine and invariants. -//---------------------------------------------------------------------------- + return *reinterpret_cast(&GetAt(0)); +} -inline CHECK SString::Check() const +template +inline void EString::Index::operator->() const { - CANNOT_HAVE_CONTRACT; - CHECK(SBuffer::Check()); - CHECK_OK; + LIMITED_METHOD_CONTRACT; } -inline CHECK SString::Invariant() const +template +inline auto EString::Index::operator[](int index) const -> char_t { - CANNOT_HAVE_CONTRACT; - CHECK(SBuffer::Invariant()); - CHECK_OK; + WRAPPER_NO_CONTRACT; + + return *reinterpret_cast(&GetAt(index)); } -inline CHECK SString::InternalInvariant() const +template +inline auto EString::Index::GetBuffer() const -> const char_t* { - CANNOT_HAVE_CONTRACT; - CHECK(SBuffer::InternalInvariant()); - CHECK(SBuffer::GetSize() >= 2); - if (IsNormalized()) - CHECK(IsRepresentation(REPRESENTATION_UNICODE)); - CHECK_OK; + WRAPPER_NO_CONTRACT; + return reinterpret_cast(m_ptr); } -#endif // CHECK_INVARIANTS -//---------------------------------------------------------------------------- -// Return a writeable buffer that can store 'countChars'+1 unicode characters. -// Call CloseBuffer when done. -//---------------------------------------------------------------------------- -inline WCHAR *SString::OpenUnicodeBuffer(COUNT_T countChars) +#ifdef _DEBUG +// +// Check the Printf use for potential globalization bugs. %S formatting +// specifier does Unicode->Ansi or Ansi->Unicode conversion using current +// C-locale. This almost always means globalization bug in the CLR codebase. +// +// Ideally, we would elimitate %S from all format strings. Unfortunately, +// %S is too widespread in non-shipping code that such cleanup is not feasible. +// +template +void CheckForFormatStringGlobalizationIssues(const EString &format, const EString &result) { - SS_CONTRACT(WCHAR*) + CONTRACTL { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckCount(countChars)); -#if _DEBUG - SS_POSTCONDITION(IsBufferOpen()); -#endif - SS_POSTCONDITION(GetRawCount() == countChars); - SS_POSTCONDITION(GetRepresentation() == REPRESENTATION_UNICODE || countChars == 0); - SS_POSTCONDITION(CheckPointer(RETVAL)); THROWS; + GC_NOTRIGGER; + DEBUG_ONLY; } - SS_CONTRACT_END; + CONTRACTL_END; - OpenBuffer(REPRESENTATION_UNICODE, countChars); - SS_RETURN GetRawUnicode(); -} + BOOL fDangerousFormat = FALSE; -//---------------------------------------------------------------------------- -// Return a copy of the underlying buffer, the caller is responsible for managing -// the returned memory -//---------------------------------------------------------------------------- -inline WCHAR *SString::GetCopyOfUnicodeString() -{ - SS_CONTRACT(WCHAR*) + // Check whether the format string contains the %S formatting specifier + typename EString::CIterator itrFormat = format.Begin(); + while (*itrFormat) { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(CheckPointer(buffer)); - THROWS; + if (*itrFormat++ == '%') + { + // Handle the complex format strings like %blahS + if (*itrFormat++ == 'S') + { + fDangerousFormat = TRUE; + break; + } + } } - SS_CONTRACT_END; - NewArrayHolder buffer = NULL; - buffer = new WCHAR[GetCount() +1]; - wcscpy_s(buffer, GetCount() + 1, GetUnicode()); + if (fDangerousFormat) + { + BOOL fNonAsciiUsed = FALSE; - SS_RETURN buffer.Extract(); -} + // Now check whether there are any non-ASCII characters in the output. -//---------------------------------------------------------------------------- -// Return a writeable buffer that can store 'countChars'+1 ansi characters. -// Call CloseBuffer when done. -//---------------------------------------------------------------------------- -inline ANSI *SString::OpenANSIBuffer(COUNT_T countChars) -{ - SS_CONTRACT(ANSI*) - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckCount(countChars)); -#if _DEBUG - SS_POSTCONDITION(IsBufferOpen()); -#endif - SS_POSTCONDITION(GetRawCount() == countChars); - SS_POSTCONDITION(GetRepresentation() == REPRESENTATION_ANSI || countChars == 0); - SS_POSTCONDITION(CheckPointer(RETVAL)); - THROWS; - } - SS_CONTRACT_END; + // Check whether the result contains non-Ascii characters + typename EString::CIterator itrResult = format.Begin(); + while (*itrResult) + { + if (*itrResult++ > 127) + { + fNonAsciiUsed = TRUE; + break; + } + } - OpenBuffer(REPRESENTATION_ANSI, countChars); - SS_RETURN GetRawANSI(); + CONSISTENCY_CHECK_MSGF(!fNonAsciiUsed, + ("Non-ASCII string was produced by %%S format specifier. This is likely globalization bug." + "To fix this, change the format string to %%s and do the correct encoding at the Printf callsite")); + } } +#endif -//---------------------------------------------------------------------------- -// Return a writeable buffer that can store 'countChars'+1 ansi characters. -// Call CloseBuffer when done. -//---------------------------------------------------------------------------- -inline UTF8 *SString::OpenUTF8Buffer(COUNT_T countBytes) +//----------------------------------------------------------------------------- +// Truncate this string to count characters. +//----------------------------------------------------------------------------- +template +void EString::Truncate(const Iterator &i) { - SS_CONTRACT(UTF8*) + SS_CONTRACT_VOID { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckCount(countBytes)); -#if _DEBUG - SS_POSTCONDITION(IsBufferOpen()); -#endif - SS_POSTCONDITION(GetRawCount() == countBytes); - SS_POSTCONDITION(GetRepresentation() == REPRESENTATION_UTF8 || countBytes == 0); - SS_POSTCONDITION(CheckPointer(RETVAL)); + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + SS_POSTCONDITION(GetCount() == i - Begin()); THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; - OpenBuffer(REPRESENTATION_UTF8, countBytes); - SS_RETURN GetRawUTF8(); + COUNT_T size = i - Begin(); + + Resize(size, PRESERVE); + + i.Resync(this, (BYTE *) (GetRawBuffer() + size)); + + SS_RETURN; } -//---------------------------------------------------------------------------- -// Private helper to open a raw buffer. -// Called by public functions to open the buffer in the specific -// representation. -// While the buffer is opened, all other operations are illegal. Call -// CloseBuffer() when done. -//---------------------------------------------------------------------------- -inline void SString::OpenBuffer(SString::Representation representation, COUNT_T countChars) +//----------------------------------------------------------------------------- +// This is essentially a specialized version of the above for size 0 +//----------------------------------------------------------------------------- +template +void EString::Clear() { -#ifdef SSTRING_EXTRA_CHECKS CONTRACT_VOID { + INSTANCE_CHECK; + POSTCONDITION(IsEmpty()); + NOTHROW; GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - PRECONDITION_MSG(!IsBufferOpen(), "Can't nest calls to OpenBuffer()"); - PRECONDITION(CheckRepresentation(representation)); - PRECONDITION(CheckSize(countChars)); -#if _DEBUG - POSTCONDITION(IsBufferOpen()); -#endif - POSTCONDITION(GetRawCount() == countChars); - POSTCONDITION(GetRepresentation() == representation || countChars == 0); - THROWS; + SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; -#else - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_THROWS; + + if (IsImmutable()) + { + // Use shared empty string rather than allocating a new buffer + static_assert(sizeof(char_t) <= sizeof(StaticStringHelpers::s_EmptyBuffer), "Empty buffer size must be as large as or larger than the size of a character."); + SBuffer::SetImmutable(StaticStringHelpers::s_EmptyBuffer, sizeof(char_t)); + } + else + { + // Leave allocated buffer for future growth + SBuffer::TweakSize(sizeof(char_t)); + m_buffer[0] = 0; + } + + RETURN; +} + + +#ifndef EBADF +#define EBADF 9 #endif - Resize(countChars, representation); +#ifndef ENOMEM +#define ENOMEM 12 +#endif - SBuffer::OpenRawBuffer(CountToSize(countChars)); +#ifndef ERANGE +#define ERANGE 34 +#endif - SS_RETURN; -} +template +void CheckForFormatStringGlobalizationIssues(const EString &format, const EString &result); -//---------------------------------------------------------------------------- -// Get the max size that can be passed to OpenUnicodeBuffer without causing -// allocations. -//---------------------------------------------------------------------------- -inline COUNT_T SString::GetUnicodeAllocation() +template +void EString::VPrintf(const char_t* format, va_list args) { - CONTRACTL + CONTRACT_VOID { INSTANCE_CHECK; - NOTHROW; + PRECONDITION(CheckPointer(format)); + THROWS; GC_NOTRIGGER; } - CONTRACTL_END; + CONTRACT_END; - COUNT_T allocation = GetAllocation(); - return ( (allocation > sizeof(WCHAR)) - ? (allocation - sizeof(WCHAR)) / sizeof(WCHAR) : 0 ); + va_list ap; + // sprintf gives us no means to know how many characters are written + // other than guessing and trying + + if (GetCount() > 0) + { + // First, try to use the existing buffer + va_copy(ap, args); + int result = TEncoding::vsnprintf_s((char_t*)m_buffer, GetCount()+1, _TRUNCATE, format, ap); + va_end(ap); + + if (result >= 0) + { + // succeeded + Resize(result, PRESERVE); + EString sss(format); + INDEBUG(CheckForFormatStringGlobalizationIssues(sss, *this)); + RETURN; + } + } + + // Make a guess how long the result will be (note this will be doubled) + + COUNT_T guess = (COUNT_T) TEncoding::strlen(format)+1; + if (guess < GetCount()) + guess = GetCount(); + if (guess < MINIMUM_GUESS) + guess = MINIMUM_GUESS; + + while (TRUE) + { + // Double the previous guess - eventually we will get enough space + guess *= 2; + Resize(guess); + + // Clear errno to avoid false alarms + errno = 0; + + va_copy(ap, args); + int result = TEncoding::vsnprintf_s((char_t*)m_buffer, GetCount()+1, _TRUNCATE, format, ap); + va_end(ap); + + if (result >= 0) + { + Resize(result, PRESERVE); + EString sss(format); + INDEBUG(CheckForFormatStringGlobalizationIssues(sss, *this)); + RETURN; + } + + if (errno==ENOMEM) + { + ThrowOutOfMemory(); + } + else + if (errno!=0 && errno!=EBADF && errno!=ERANGE) + { + CONSISTENCY_CHECK_MSG(FALSE, "vsnprintf_s failed. Potential globalization bug."); + ThrowHR(HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION)); + } + } + RETURN; } -//---------------------------------------------------------------------------- -// Close an open buffer. Assumes that we wrote exactly number of characters -// we requested in OpenBuffer. -//---------------------------------------------------------------------------- -inline void SString::CloseBuffer() + +template<> +inline BOOL EString::FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, + const EString &arg1, const EString &arg2, + const EString &arg3, const EString &arg4, + const EString &arg5, const EString &arg6, + const EString &arg7, const EString &arg8, + const EString &arg9, const EString &arg10) { - SS_CONTRACT_VOID + CONTRACT(BOOL) { - GC_NOTRIGGER; -#if _DEBUG - PRECONDITION_MSG(IsBufferOpen(), "Can only CloseBuffer() after a call to OpenBuffer()"); -#endif - SS_POSTCONDITION(CheckPointer(this)); + INSTANCE_CHECK; THROWS; + GC_NOTRIGGER; } - SS_CONTRACT_END; - - SBuffer::CloseRawBuffer(); - NullTerminate(); + CONTRACT_END; - SS_RETURN; -} + const WCHAR *args[] = {arg1, arg2, arg3, arg4, + arg5, arg6, arg7, arg8, + arg9, arg10}; -//---------------------------------------------------------------------------- -// CloseBuffer() tells the SString that we're done using the unsafe buffer. -// countChars is the count of characters actually used (so we can set m_count). -// This is important if we request a buffer larger than what we actually -// used. -//---------------------------------------------------------------------------- -inline void SString::CloseBuffer(COUNT_T finalCount) -{ - SS_CONTRACT_VOID + if (GetCount() > 0) { - GC_NOTRIGGER; -#if _DEBUG - PRECONDITION_MSG(IsBufferOpen(), "Can only CloseBuffer() after a call to OpenBuffer()"); -#endif - PRECONDITION(CheckSize(finalCount)); - SS_POSTCONDITION(CheckPointer(this)); - SS_POSTCONDITION(GetRawCount() == finalCount); - THROWS; - } - SS_CONTRACT_END; + // First, try to use our existing buffer to hold the result. + Resize(GetCount()); - SBuffer::CloseRawBuffer(CountToSize(finalCount)); - NullTerminate(); + DWORD result = ::WszFormatMessage(dwFlags | FORMAT_MESSAGE_ARGUMENT_ARRAY, + lpSource, dwMessageId, dwLanguageId, + GetRawBuffer(), GetCount()+1, (va_list*)args); - SS_RETURN; -} + // Although we cannot directly detect truncation, we can tell if we + // used up all the space (in which case we will assume truncation.) -//---------------------------------------------------------------------------- -// EnsureWritable -// Ensures that the buffer is writable -//---------------------------------------------------------------------------- -inline void SString::EnsureWritable() const -{ -#ifdef SSTRING_EXTRA_CHECKS - CONTRACT_VOID - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - POSTCONDITION(!IsLiteral()); - THROWS; + if (result != 0 && result < GetCount()) + { + if (GetRawBuffer()[result-1] == W(' ')) + { + GetRawBuffer()[result-1] = W('\0'); + result -= 1; + } + Resize(result, PRESERVE); + RETURN TRUE; + } } - CONTRACT_END; -#else //SSTRING_EXTRA_CHECKS - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_THROWS; -#endif //SSTRING_EXTRA_CHECKS - if (IsLiteral()) - const_cast(this)->Resize(GetRawCount(), GetRepresentation(), PRESERVE); + // We don't have enough space in our buffer, do dynamic allocation. + LocalAllocHolder string; - SS_RETURN; + DWORD result = ::WszFormatMessage(dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, + lpSource, dwMessageId, dwLanguageId, + (LPWSTR)(LPWSTR*)&string, 0, (va_list*)args); + + if (result == 0) + RETURN FALSE; + else + { + if (string[result-1] == W(' ')) + string[result-1] = W('\0'); + + Set(string); + RETURN TRUE; + } } -//----------------------------------------------------------------------------- -// Convert the internal representation to be a fixed size -//----------------------------------------------------------------------------- -inline void SString::ConvertToFixed() const +#ifdef DACCESS_COMPILE +template<> +inline const WCHAR * EString::DacGetRawUnicode() const { - SS_CONTRACT_VOID + if (IsEmpty()) { - GC_NOTRIGGER; - SS_PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(IsFixedSize()); - THROWS_UNLESS_NORMALIZED; - SUPPORTS_DAC; + return W(""); } - SS_CONTRACT_END; - - // If we're already fixed size, great. - if (IsFixedSize()) - SS_RETURN; - // See if we can coerce it to ASCII. - if (ScanASCII()) - SS_RETURN; + return static_cast(SBuffer::DacTryGetRawContent()); +} +#endif - // Convert to unicode then. - ConvertToUnicode(); +template +void EString::AppendVPrintf(const char_t* format, va_list args) +{ + WRAPPER_NO_CONTRACT; - SS_RETURN; + StackEString s; + s.VPrintf(format, args); + Append(s); } -//----------------------------------------------------------------------------- -// Convert the internal representation to be an iteratable one (current -// requirements here are that it be trivially convertable to unicode chars.) -//----------------------------------------------------------------------------- -inline void SString::ConvertToIteratable() const +template<> +inline COUNT_T EString::ConvertToUnicode(EString &s) const { - SS_CONTRACT_VOID + CONTRACT(COUNT_T) { + THROWS; GC_NOTRIGGER; - SS_PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(IsIteratable()); - THROWS_UNLESS_NORMALIZED; - SUPPORTS_DAC; + SUPPORTS_DAC_HOST_ONLY; } - SS_CONTRACT_END; + CONTRACT_END; - // If we're already iteratable, great. - if (IsIteratable()) - SS_RETURN; + // Handle the empty case. + if (IsEmpty()) + { + s.Clear(); + RETURN GetCount() + 1; + } - // See if we can coerce it to ASCII. - if (ScanASCII()) - SS_RETURN; + CONSISTENCY_CHECK(CheckPointer(GetRawBuffer())); + CONSISTENCY_CHECK(GetCount() > 0); - // Convert to unicode then. - ConvertToUnicode(); + // If dest is the same as this, then we need to preserve on resize. + WCHAR* buf = s.OpenBuffer(GetCount()); - SS_RETURN; -} + // Make sure the buffer is big enough. + CONSISTENCY_CHECK(s.GetAllocation() >= GetCount()); -//----------------------------------------------------------------------------- -// Create iterators on the string. -//----------------------------------------------------------------------------- + // This is a poor man's widen. Since we know that the representation is ASCII, + // we can just pad the string with a bunch of zero-value bytes. Of course, + // we move from the end of the string to the start so that we can convert in + // place (in the case that dest.GetRawBuffer() == this.GetRawBuffer()). + WCHAR *outBuf = buf + s.GetCount(); + ASCII *inBuf = GetRawBuffer() + GetCount(); -inline SString::UIterator SString::BeginUnicode() -{ - SS_CONTRACT(SString::UIterator) + while (GetRawBuffer() <= inBuf) { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(CheckValue(RETVAL)); - THROWS; + CONSISTENCY_CHECK(buf <= outBuf); + // The casting zero-extends the value, thus giving us the zero-valued byte. + *outBuf = (WCHAR) *inBuf; + outBuf--; + inBuf--; } - SS_CONTRACT_END; + + s.CloseBuffer(); - ConvertToUnicode(); - EnsureWritable(); - - SS_RETURN UIterator(this, 0); + RETURN GetCount() + 1; } -inline SString::UIterator SString::EndUnicode() +template +EString EString::MoveToUTF8() { - SS_CONTRACT(SString::UIterator) + StackEString buff; + ConvertToUTF8(buff); + if (IsAllocated()) { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(CheckValue(RETVAL)); - THROWS; + ClearAllocated(); + EString result(GetRawBufferForMove(), GetAllocationForMove(), /* isAllocated */ true); + SetImmutable(); // Set the existing value as immutable to get SBuffer to reuse the immutable buffer we're setting + SetImmutable(StaticStringHelpers::s_EmptyBuffer, sizeof(StaticStringHelpers::s_EmptyBuffer)); + result.Set(buff); + return result; } - SS_CONTRACT_END; - - ConvertToUnicode(); - EnsureWritable(); - - SS_RETURN UIterator(this, GetCount()); + return std::move(buff); } -//----------------------------------------------------------------------------- -// Create CIterators on the string. -//----------------------------------------------------------------------------- - -FORCEINLINE SString::CIterator SString::Begin() const +template +EString EString::MoveToUnicode() { - SS_CONTRACT(SString::CIterator) + StackEString buff; + ConvertToUnicode(buff); + if (IsAllocated()) { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(CheckValue(RETVAL)); - THROWS_UNLESS_NORMALIZED; + ClearAllocated(); + EString result(GetRawBufferForMove(), GetAllocationForMove(), /* isAllocated */ true); + SetImmutable(); // Set the existing value as immutable to get SBuffer to reuse the immutable buffer we're setting + SetImmutable(StaticStringHelpers::s_EmptyBuffer, sizeof(StaticStringHelpers::s_EmptyBuffer)); + result.Set(buff); + return result; } - SS_CONTRACT_END; - - ConvertToIteratable(); - - SS_RETURN CIterator(this, 0); + return std::move(buff); } -FORCEINLINE SString::CIterator SString::End() const +template<> +inline EString EString::MoveToUnicode() { - SS_CONTRACT(SString::CIterator) + // ASCII -> Unicode conversion supports in-place conversion if the buffer is large enough. + if (IsAllocated() && SBuffer::GetAllocation() > GetCount() * sizeof(WCHAR)) { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(CheckValue(RETVAL)); - THROWS_UNLESS_NORMALIZED; + ClearAllocated(); + EString result(GetRawBufferForMove(), GetAllocationForMove(), /* isAllocated */ true); + ConvertToUnicode(result); + SetImmutable(); // Set the existing value as immutable to get SBuffer to reuse the immutable buffer we're setting + SetImmutable(StaticStringHelpers::s_EmptyBuffer, sizeof(StaticStringHelpers::s_EmptyBuffer)); + return result; } - SS_CONTRACT_END; - - ConvertToIteratable(); - SS_RETURN CIterator(this, GetCount()); + StackEString buff; + ConvertToUnicode(buff); + return std::move(buff); } -//----------------------------------------------------------------------------- -// Create Iterators on the string. -//----------------------------------------------------------------------------- -FORCEINLINE SString::Iterator SString::Begin() +// Insert string at iterator position +template +inline void EString::Insert(const Iterator &i, const EString &s) { - SS_CONTRACT(SString::Iterator) + SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(CheckValue(RETVAL)); - THROWS; // EnsureMutable always throws - SUPPORTS_DAC; + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(s.Check()); + THROWS; + SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; - ConvertToIteratable(); - EnsureMutable(); + Replace(i, 0, s); - SS_RETURN Iterator(this, 0); + SS_RETURN; } -FORCEINLINE SString::Iterator SString::End() +template +inline void EString::Insert(const Iterator &i, const char_t *string) { - SS_CONTRACT(SString::Iterator) + SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(CheckValue(RETVAL)); - THROWS; // EnsureMutable always Throws - SUPPORTS_DAC; + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(CheckPointer(string)); + THROWS; } SS_CONTRACT_END; - ConvertToIteratable(); - EnsureMutable(); + StackEString s(string); + Replace(i, 0, s); - SS_RETURN Iterator(this, GetCount()); + SS_RETURN; } - //----------------------------------------------------------------------------- -// CIterator support routines +// Replace the substring specified by position, length with the given string s. //----------------------------------------------------------------------------- - -inline SString::Index::Index() -{ - LIMITED_METHOD_CONTRACT; -} - -inline SString::Index::Index(SString *string, SCOUNT_T index) - : SBuffer::Index(string, index<GetCharacterSizeShift()) +template +void EString::Replace(const Iterator &i, COUNT_T length, const EString &s) { - SS_CONTRACT_VOID + CONTRACT_VOID { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i, length)); + PRECONDITION(s.Check()); + POSTCONDITION(Match(i, s)); + THROWS; GC_NOTRIGGER; - PRECONDITION(CheckPointer(string)); - PRECONDITION(string->IsIteratable()); - PRECONDITION(DoCheck(0)); - SS_POSTCONDITION(CheckPointer(this)); - // POSTCONDITION(Subtract(string->Begin()) == index); contract violation - fix later - NOTHROW; - CANNOT_TAKE_LOCK; - SUPPORTS_DAC; + SUPPORTS_DAC_HOST_ONLY; } - SS_CONTRACT_END; - - m_characterSizeShift = string->GetCharacterSizeShift(); + CONTRACT_END; - SS_RETURN; -} + COUNT_T deleteSize = length * sizeof(char_t); + COUNT_T insertSize = s.GetCount() * sizeof(char_t); -inline BYTE &SString::Index::GetAt(SCOUNT_T delta) const -{ - LIMITED_METHOD_DAC_CONTRACT; + SBuffer::Replace(i, deleteSize, insertSize); + SBuffer::Copy(i, s.m_buffer, insertSize); - return m_ptr[delta< +// Delete string at iterator position +inline void EString::Delete(const Iterator &i, COUNT_T length) { - LIMITED_METHOD_DAC_CONTRACT; - - m_ptr += (delta<>m_characterSizeShift); + SS_RETURN; } -inline CHECK SString::Index::DoCheck(SCOUNT_T delta) const -{ - CANNOT_HAVE_CONTRACT; -#if _DEBUG - const SString *string = (const SString *) GetContainerDebug(); - - CHECK(m_ptr + (delta<= string->m_buffer); - CHECK(m_ptr + (delta<m_buffer + string->GetSize()); -#endif - CHECK_OK; -} -inline void SString::Index::Resync(const SString *string, BYTE *ptr) const +template +BOOL EString::Find(CIterator& i, const EString& s) const { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - SBuffer::Index::Resync(string, ptr); - - const_cast(this)->m_characterSizeShift = string->GetCharacterSizeShift(); + CONTRACT(BOOL) + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(s.Check()); + POSTCONDITION(RETVAL == Match(i, s)); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + COUNT_T count = s.GetCount(); + const char_t *start = i.GetBuffer(); + const char_t *end = GetRawBuffer() + GetCount() - count; + while (start <= end) + { + if (TEncoding::strncmp(start, s.GetRawBuffer(), count) == 0) + { + i.Resync(this, (BYTE*) start); + RETURN TRUE; + } + start++; + } + RETURN FALSE; } - -inline const WCHAR *SString::Index::GetUnicode() const +template +BOOL EString::Find(CIterator& i, char_t s) const { - LIMITED_METHOD_CONTRACT; + CONTRACT(BOOL) + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + POSTCONDITION(RETVAL == Match(i, s)); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; - return (const WCHAR *) m_ptr; + const char_t *start = i.GetBuffer(); + const char_t *end = GetRawBuffer() + GetCount() - 1; + while (start <= end) + { + if (*start == s) + { + i.Resync(this, (BYTE*) start); + RETURN TRUE; + } + start++; + } + RETURN FALSE; } -inline const CHAR *SString::Index::GetASCII() const +template +BOOL EString::FindBack(CIterator& i, const EString& s) const { - LIMITED_METHOD_CONTRACT; - - return (const CHAR *) m_ptr; + CONTRACT(BOOL) + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(s.Check()); + POSTCONDITION(RETVAL == Match(i, s)); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + COUNT_T count = s.GetCount(); + const char_t *start = GetRawBuffer() + GetCount() - count; + if (start > i.GetBuffer()) + { + start = i.GetBuffer(); + } + const char_t *end = GetRawBuffer(); + while (start >= end) + { + if (TEncoding::strncmp(start, s.GetRawBuffer(), count) == 0) + { + i.Resync(this, (BYTE*) start); + RETURN TRUE; + } + start--; + } + RETURN FALSE; } -inline WCHAR SString::Index::operator*() const +template +BOOL EString::FindBack(CIterator& i, char_t s) const { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if (m_characterSizeShift == 0) - return *(CHAR*)&GetAt(0); - else - return *(WCHAR*)&GetAt(0); -} + CONTRACT(BOOL) + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + POSTCONDITION(RETVAL == Match(i, s)); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + const char_t *start = GetRawBuffer() + GetCount() - 1; + if (start > i.GetBuffer()) + { + start = i.GetBuffer(); + } + const char_t *end = GetRawBuffer(); + while (start >= end) + { + if (*start == s) + { + i.Resync(this, (BYTE*) start); + RETURN TRUE; + } + start--; + } -inline void SString::Index::operator->() const -{ - LIMITED_METHOD_CONTRACT; + RETURN FALSE; } -inline WCHAR SString::Index::operator[](int index) const +template +inline BOOL EString::Skip(CIterator &i, const EString &s) const { - WRAPPER_NO_CONTRACT; + SS_CONTRACT(BOOL) + { + GC_NOTRIGGER; + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(s.Check()); + NOTHROW; + } + SS_CONTRACT_END; - if (m_characterSizeShift == 0) - return *(CHAR*)&GetAt(index); + if (Match(i, s)) + { + i += s.GetCount(); + SS_RETURN TRUE; + } else - return *(WCHAR*)&GetAt(index); -} - -//----------------------------------------------------------------------------- -// Iterator support routines -//----------------------------------------------------------------------------- - -inline SString::UIndex::UIndex() -{ - LIMITED_METHOD_CONTRACT; + SS_RETURN FALSE; } -inline SString::UIndex::UIndex(SString *string, SCOUNT_T index) - : SBuffer::Index(string, index*sizeof(WCHAR)) +template +inline BOOL EString::Skip(CIterator &i, char_t c) const { - SS_CONTRACT_VOID + SS_CONTRACT(BOOL) { GC_NOTRIGGER; - PRECONDITION(CheckPointer(string)); - PRECONDITION(string->IsRepresentation(REPRESENTATION_UNICODE)); - PRECONDITION(DoCheck(0)); - SS_POSTCONDITION(CheckPointer(this)); + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); NOTHROW; - CANNOT_TAKE_LOCK; } SS_CONTRACT_END; - SS_RETURN; -} - -inline WCHAR &SString::UIndex::GetAt(SCOUNT_T delta) const -{ - LIMITED_METHOD_CONTRACT; - - return ((WCHAR*)m_ptr)[delta]; + if (Match(i, c)) + { + i++; + SS_RETURN TRUE; + } + else + SS_RETURN FALSE; } -inline void SString::UIndex::Skip(SCOUNT_T delta) +template +inline BOOL EString::Match(const CIterator& i, const EString& s) const { - LIMITED_METHOD_CONTRACT; + CONTRACT(BOOL) + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(s.Check()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; - m_ptr += delta * sizeof(WCHAR); -} + COUNT_T remaining = End() - i; + COUNT_T count = s.GetCount(); -inline SCOUNT_T SString::UIndex::Subtract(const UIndex &i) const -{ - WRAPPER_NO_CONTRACT; + if (remaining < count) + { + RETURN FALSE; + } - return (SCOUNT_T) (GetUnicode() - i.GetUnicode()); + RETURN (TEncoding::strncmp(i.GetBuffer(), s.GetRawBuffer(), count) == 0); } -inline CHECK SString::UIndex::DoCheck(SCOUNT_T delta) const +template +inline BOOL EString::MatchCaseInsensitive(const CIterator& i, const EString& s) const { - CANNOT_HAVE_CONTRACT; -#if _DEBUG - const SString *string = (const SString *) GetContainerDebug(); - - CHECK(GetUnicode() + delta >= string->GetRawUnicode()); - CHECK(GetUnicode() + delta <= string->GetRawUnicode() + string->GetCount()); -#endif + CONTRACT(BOOL) + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(s.Check()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; - CHECK_OK; -} + COUNT_T remaining = End() - i; + COUNT_T count = s.GetCount(); -inline WCHAR *SString::UIndex::GetUnicode() const -{ - LIMITED_METHOD_CONTRACT; + if (remaining < count) + { + RETURN FALSE; + } - return (WCHAR*) m_ptr; + RETURN (TEncoding::CaseCompareHelper(i.GetBuffer(), s.GetRawBuffer(), count, FALSE, TRUE) == 0); } -//----------------------------------------------------------------------------- -// Opaque scratch buffer class routines -//----------------------------------------------------------------------------- -inline SString::AbstractScratchBuffer::AbstractScratchBuffer(void *buffer, COUNT_T size) - : SString(buffer, size) +template +inline BOOL EString::Match(const CIterator &i, char_t c) const { - SS_CONTRACT_VOID + SS_CONTRACT(BOOL) { GC_NOTRIGGER; - PRECONDITION(CheckPointer(buffer)); - PRECONDITION(CheckCount(size)); + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); NOTHROW; } SS_CONTRACT_END; - SS_RETURN; + // End() will not throw here + CONTRACT_VIOLATION(ThrowsViolation); + SS_RETURN (i < End() && i[0] == c); } #ifdef _MSC_VER diff --git a/src/coreclr/inc/stringarraylist.h b/src/coreclr/inc/stringarraylist.h index 5001ad7c469258..254f59dc1feec8 100644 --- a/src/coreclr/inc/stringarraylist.h +++ b/src/coreclr/inc/stringarraylist.h @@ -6,25 +6,28 @@ // -// StringArrayList is a simple class which is used to contain a growable +// EStringArrayList is a simple class which is used to contain a growable // list of Strings, stored in chunks. Based on top of ArrayList #include "arraylist.h" - -class StringArrayList +template +class EStringArrayList { ArrayList m_Elements; public: DWORD GetCount() const; - SString& operator[] (DWORD idx) const; - SString& Get (DWORD idx) const; + EString& operator[] (DWORD idx) const; + EString& Get (DWORD idx) const; #ifndef DACCESS_COMPILE - void Append(const SString& string); - void AppendIfNotThere(const SString& string); + void Append(const EString& string); + void AppendIfNotThere(const EString& string); #endif - ~StringArrayList(); + ~EStringArrayList(); }; +struct EncodingUnicode; + +using StringArrayList = EStringArrayList; #include "stringarraylist.inl" #endif diff --git a/src/coreclr/inc/stringarraylist.inl b/src/coreclr/inc/stringarraylist.inl index b82f95735a4dea..3a226ac659756b 100644 --- a/src/coreclr/inc/stringarraylist.inl +++ b/src/coreclr/inc/stringarraylist.inl @@ -3,27 +3,31 @@ #include "ex.h" -inline SString& StringArrayList::operator[] (DWORD idx) const +template +inline EString& EStringArrayList::operator[] (DWORD idx) const { WRAPPER_NO_CONTRACT; return Get(idx); } -inline SString& StringArrayList::Get (DWORD idx) const +template +inline EString& EStringArrayList::Get (DWORD idx) const { WRAPPER_NO_CONTRACT; - PTR_SString ppRet=(PTR_SString)m_Elements.Get(idx); + PTR_EString ppRet=(PTR_EString)m_Elements.Get(idx); return *ppRet; } -inline DWORD StringArrayList::GetCount() const +template +inline DWORD EStringArrayList::GetCount() const { WRAPPER_NO_CONTRACT; return m_Elements.GetCount(); } #ifndef DACCESS_COMPILE -inline void StringArrayList::Append(const SString& string) +template +inline void EStringArrayList::Append(const EString& string) { CONTRACTL { @@ -31,13 +35,13 @@ inline void StringArrayList::Append(const SString& string) GC_NOTRIGGER; } CONTRACTL_END; - NewHolder pAdd=new SString(string); - pAdd->Normalize(); + NewHolder> pAdd = new EString(string); IfFailThrow(m_Elements.Append(pAdd)); pAdd.SuppressRelease(); } -inline void StringArrayList::AppendIfNotThere(const SString& string) +template +inline void EStringArrayList::AppendIfNotThere(const EString& string) { CONTRACTL { @@ -56,7 +60,8 @@ inline void StringArrayList::AppendIfNotThere(const SString& string) #endif -inline StringArrayList::~StringArrayList() +template +inline EStringArrayList::~EStringArrayList() { CONTRACTL { @@ -68,7 +73,7 @@ inline StringArrayList::~StringArrayList() #ifndef DACCESS_COMPILE for (DWORD i=0;i< GetCount() ;i++) { - delete (SString*)m_Elements.Get(i); + delete (EString*)m_Elements.Get(i); } #endif } diff --git a/src/coreclr/inc/utilcode.h b/src/coreclr/inc/utilcode.h index 7191833998d4d3..53fcc3eb62e4c1 100644 --- a/src/coreclr/inc/utilcode.h +++ b/src/coreclr/inc/utilcode.h @@ -61,7 +61,9 @@ #define CoreLibSatelliteNameLen 32 #define LegacyCoreLibName_A "mscorlib" -class StringArrayList; +template +class EStringArrayList; +struct EncodingUnicode; #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) #define _DEBUG_IMPL 1 @@ -585,7 +587,7 @@ typedef WCHAR LocaleIDValue[LOCALE_NAME_MAX_LENGTH]; // - The id is used as a key to map to a dll hinstance. // Callback to obtain both the culture name and the culture's parent culture name -typedef HRESULT (*FPGETTHREADUICULTURENAMES)(__inout StringArrayList* pCultureNames); +typedef HRESULT (*FPGETTHREADUICULTURENAMES)(EStringArrayList* pCultureNames); const LPCWSTR UICULTUREID_DONTCARE = NULL; typedef int (*FPGETTHREADUICULTUREID)(LocaleIDValue*); @@ -704,7 +706,7 @@ class CCulturedHInstance }; #ifndef DACCESS_COMPILE -void AddThreadPreferredUILanguages(StringArrayList* pArray); +void AddThreadPreferredUILanguages(EStringArrayList* pArray); #endif //***************************************************************************** // CCompRC manages string Resource access for COM+. This includes loading @@ -967,17 +969,6 @@ void MakePath(_Out_ CQuickWSTR &path, WCHAR * FullPath(_Out_writes_ (maxlen) WCHAR *UserBuf, const WCHAR *path, size_t maxlen); -//***************************************************************************** -// -// SString version of the path functions. -// -//***************************************************************************** -void SplitPath(_In_ SString const &path, - __inout_opt SString *drive, - __inout_opt SString *dir, - __inout_opt SString *fname, - __inout_opt SString *ext); - #include "ostype.h" #define CLRGetTickCount64() GetTickCount64() diff --git a/src/coreclr/md/compiler/disp.cpp b/src/coreclr/md/compiler/disp.cpp index 26f1e2ec789134..d6c6618a140cee 100644 --- a/src/coreclr/md/compiler/disp.cpp +++ b/src/coreclr/md/compiler/disp.cpp @@ -63,7 +63,7 @@ Disp::DefineScope( { #ifdef FEATURE_METADATA_EMIT HRESULT hr = S_OK; - PathString szFileName(PathString::Literal, W("file:")); + SString szFileName(SString::Literal, W("file:")); PathString szFileNameSuffix; BEGIN_ENTRYPOINT_NOTHROW; diff --git a/src/coreclr/md/compiler/importhelper.cpp b/src/coreclr/md/compiler/importhelper.cpp index 743a78e67799fb..3e0432be462a30 100644 --- a/src/coreclr/md/compiler/importhelper.cpp +++ b/src/coreclr/md/compiler/importhelper.cpp @@ -1364,8 +1364,8 @@ HRESULT ImportHelper::FindAssemblyRef( LPCUTF8 szAssemblyRefName; IfFailRet(pMiniMd->getNameOfAssemblyRef(pRec, &szAssemblyRefName)); - if (SString::_stricmp(szAssemblyRefName, "mscorlib") && - SString::_stricmp(szAssemblyRefName, "microsoft.visualc")) + if (StaticStringHelpers::_stricmp(szAssemblyRefName, "mscorlib") && + StaticStringHelpers::_stricmp(szAssemblyRefName, "microsoft.visualc")) { if (pRec->GetBuildNumber() != usBuildNumber) continue; diff --git a/src/coreclr/md/compiler/mdutil.cpp b/src/coreclr/md/compiler/mdutil.cpp index 55ac77e9a3aa7a..11da5e0b151419 100644 --- a/src/coreclr/md/compiler/mdutil.cpp +++ b/src/coreclr/md/compiler/mdutil.cpp @@ -268,7 +268,7 @@ HRESULT LOADEDMODULES::FindCachedReadOnlyEntry( #ifdef FEATURE_CASE_SENSITIVE_FILESYSTEM if (wcscmp(szName, pszName) == 0) #else - if (SString::_wcsicmp(szName, pszName) == 0) + if (StaticStringHelpers::_wcsicmp(szName, pszName) == 0) #endif { ULONG cRefs; @@ -302,7 +302,7 @@ HRESULT LOADEDMODULES::FindCachedReadOnlyEntry( #ifdef FEATURE_CASE_SENSITIVE_FILESYSTEM if (wcscmp(szName, pszName) == 0) #else - if (SString::_wcsicmp(szName, pszName) == 0) + if (StaticStringHelpers::_wcsicmp(szName, pszName) == 0) #endif { ULONG cRefs; diff --git a/src/coreclr/md/enc/liteweightstgdbrw.cpp b/src/coreclr/md/enc/liteweightstgdbrw.cpp index 7ae079d3a8a64a..4673d82108f391 100644 --- a/src/coreclr/md/enc/liteweightstgdbrw.cpp +++ b/src/coreclr/md/enc/liteweightstgdbrw.cpp @@ -970,7 +970,7 @@ HRESULT CLiteWeightStgdbRW::Save( IfFailGo(SetFileName(szDatabase)); } } - else if ((szDatabase != NULL) && (SString::_wcsicmp(szDatabase, m_wszFileName) != 0)) + else if ((szDatabase != NULL) && (StaticStringHelpers::_wcsicmp(szDatabase, m_wszFileName) != 0)) { // Save the file name. IfFailGo(SetFileName(szDatabase)); diff --git a/src/coreclr/md/enc/stgio.cpp b/src/coreclr/md/enc/stgio.cpp index f37f868d62516c..65049a0dece4c4 100644 --- a/src/coreclr/md/enc/stgio.cpp +++ b/src/coreclr/md/enc/stgio.cpp @@ -314,11 +314,11 @@ HRESULT StgIO::Open( // Return code. { WCHAR rcExt[_MAX_PATH]; SplitPath(szName, NULL, 0, NULL, 0, NULL, 0, rcExt, _MAX_PATH); - if (SString::_wcsicmp(rcExt, W(".obj")) == 0) + if (StaticStringHelpers::_wcsicmp(rcExt, W(".obj")) == 0) { m_FileType = FILETYPE_NTOBJ; } - else if (SString::_wcsicmp(rcExt, W(".tlb")) == 0) + else if (StaticStringHelpers::_wcsicmp(rcExt, W(".tlb")) == 0) { m_FileType = FILETYPE_TLB; } diff --git a/src/coreclr/md/enc/stgtiggerstorage.cpp b/src/coreclr/md/enc/stgtiggerstorage.cpp index d5203659138d36..1c0a1e410e8a63 100644 --- a/src/coreclr/md/enc/stgtiggerstorage.cpp +++ b/src/coreclr/md/enc/stgtiggerstorage.cpp @@ -742,7 +742,7 @@ TiggerStorage::FindStream( return CLDB_E_FILE_CORRUPT; } - if (SString::_stricmp(p->GetName(), szName) == 0) + if (StaticStringHelpers::_stricmp(p->GetName(), szName) == 0) { *stream = p; return S_OK; @@ -755,7 +755,7 @@ TiggerStorage::FindStream( { for (int j = 0; j < m_Streams.Count(); j++) { - if (SString::_stricmp(m_Streams[j].GetName(), szName) == 0) + if (StaticStringHelpers::_stricmp(m_Streams[j].GetName(), szName) == 0) { *stream = &m_Streams[j]; return S_OK; diff --git a/src/coreclr/nativeaot/Runtime/eventtrace.cpp b/src/coreclr/nativeaot/Runtime/eventtrace.cpp index 6dc625168fa25a..4a326b9ee5acf2 100644 --- a/src/coreclr/nativeaot/Runtime/eventtrace.cpp +++ b/src/coreclr/nativeaot/Runtime/eventtrace.cpp @@ -1116,7 +1116,7 @@ void BulkTypeEventLogger::FireBulkTypeEvent() #ifdef FEATURE_NATIVEAOT EventDataDescCreate(&EventData[iDesc++], L"", sizeof(WCHAR)); #else // FEATURE_NATIVEAOT - LPCWSTR wszName = m_rgBulkTypeValues[iTypeData].sName.GetUnicode(); + LPCWSTR wszName = (LPCWSTR)m_rgBulkTypeValues[iTypeData].sName; EventDataDescCreate( &EventData[iDesc++], (wszName == NULL) ? L"" : wszName, @@ -3898,7 +3898,7 @@ void ETW::ExceptionLog::ExceptionThrown(CrawlFrame* pCf, BOOL bIsReThrownExcepti gc.exceptionMessageRef = ((EXCEPTIONREF)gc.exceptionObj)->GetMessage(); TypeHandle exceptionTypeHandle = (gc.exceptionObj)->GetTypeHandle(); exceptionTypeHandle.GetName(exceptionType); - WCHAR* exceptionTypeName = (WCHAR*)exceptionType.GetUnicode(); + WCHAR* exceptionTypeName = (WCHAR*)(LPCWSTR)exceptionType; if (gc.exceptionMessageRef != NULL) { @@ -4852,7 +4852,7 @@ void ETW::LoaderLog::SendAssemblyEvent(Assembly* pAssembly, DWORD dwEventOptions SString sAssemblyPath; pAssembly->GetDisplayName(sAssemblyPath); - LPWSTR lpszAssemblyPath = (LPWSTR)sAssemblyPath.GetUnicode(); + LPWSTR lpszAssemblyPath = (LPWSTR)(LPCWSTR)sAssemblyPath; /* prepare events args for ETW and ETM */ #ifndef FEATURE_DTRACE @@ -5228,7 +5228,7 @@ void ETW::LoaderLog::SendModuleEvent(Module* pModule, DWORD dwEventOptions, BOOL if (bIsDynamicAssembly || ModuleILPath == NULL || wcslen(ModuleILPath) <= 2) { moduleName.SetUTF8(pModule->GetSimpleName()); - ModuleILPath = (PWCHAR)moduleName.GetUnicode(); + ModuleILPath = (PWCHAR)(LPCWSTR)moduleName; ModuleNativePath = (PWCHAR)pEmptyString; } @@ -5238,8 +5238,8 @@ void ETW::LoaderLog::SendModuleEvent(Module* pModule, DWORD dwEventOptions, BOOL szDtraceOutput2 = (PCWSTR)ModuleNativePath; // Convert PDB paths to UNICODE - StackSString managedPdbPath(SString::Utf8, cvInfoIL.path); - StackSString nativePdbPath(SString::Utf8, cvInfoNative.path); + StackEString managedPdbPath(cvInfoIL.path); + StackEString nativePdbPath(cvInfoNative.path); #else // !FEATURE_DTRACE // since DTrace do not support UNICODE string, they need to be converted to ANSI string INT32 nSizeOfILPath = WideCharToMultiByte(ModuleILPath, szDtraceOutput1); diff --git a/src/coreclr/utilcode/ccomprc.cpp b/src/coreclr/utilcode/ccomprc.cpp index ef02e67c7131cc..6236e2c6879c0b 100644 --- a/src/coreclr/utilcode/ccomprc.cpp +++ b/src/coreclr/utilcode/ccomprc.cpp @@ -588,8 +588,8 @@ HRESULT CCompRC::LoadLibraryHelper(HRESOURCEDLL *pHInst, _ASSERTE(m_pResourceFile != NULL); - // must initialize before calling SString::Empty() - SString::Startup(); + // must initialize before calling StaticStringHelpers::Empty() + StaticStringHelpers::Startup(); // Try and get both the culture fallback sequence @@ -618,7 +618,7 @@ HRESULT CCompRC::LoadLibraryHelper(HRESOURCEDLL *pHInst, PathString rcPathName(rcPath); - if (!rcPathName.EndsWith(W("\\"))) + if (!rcPathName.EndsWith(SL(W("\\")))) { rcPathName.Append(W("\\")); } @@ -672,7 +672,7 @@ HRESULT CCompRC::LoadLibraryThrows(HRESOURCEDLL * pHInst) _ASSERTE(!"CCompRC::LoadLibraryThrows not implemented for SELF_NO_HOST"); hr = E_NOTIMPL; #else // SELF_NO_HOST - PathString rcPath; // Path to resource DLL. + PathString rcPath; // Path to resource DLL. // Try first in the same directory as this dll. diff --git a/src/coreclr/utilcode/check.cpp b/src/coreclr/utilcode/check.cpp index 4d7a0c741632e6..a50758a40deac5 100644 --- a/src/coreclr/utilcode/check.cpp +++ b/src/coreclr/utilcode/check.cpp @@ -107,27 +107,25 @@ void CHECK::Trigger(LPCSTR reason) STATIC_CONTRACT_GC_NOTRIGGER; const char *messageString = NULL; - NewHolder pScratch(NULL); - NewHolder pMessage(NULL); + NewHolder> pMessage(NULL); EX_TRY { FAULT_NOT_FATAL(); - pScratch = new StackScratchBuffer(); - pMessage = new StackSString(); + pMessage = new StackEString(); - pMessage->AppendASCII(reason); - pMessage->AppendASCII(": "); + pMessage->Append(reason); + pMessage->Append(": "); if (m_message != NULL) - pMessage->AppendASCII((m_message != (LPCSTR)1) ? m_message : ""); + pMessage->Append((m_message != (LPCSTR)1) ? m_message : ""); #if _DEBUG - pMessage->AppendASCII("FAILED: "); - pMessage->AppendASCII(m_condition); + pMessage->Append("FAILED: "); + pMessage->Append(m_condition); #endif - messageString = pMessage->GetANSI(*pScratch); + messageString = *pMessage; } EX_CATCH { @@ -174,7 +172,7 @@ void CHECK::Setup(LPCSTR message, LPCSTR condition, LPCSTR file, INT line) FAULT_NOT_FATAL(); // Try to build a stack of condition failures - StackSString context; + StackEString context; context.Printf("%s\n\t%s%s FAILED: %s\n\t\t%s, line: %d", m_condition, message && *message ? message : "", @@ -224,7 +222,7 @@ LPCSTR CHECK::FormatMessage(LPCSTR messageFormat, ...) else { // This path is only run in debug. TakesLockViolation suppresses - // problems with SString below. + // problems with EString below. CONTRACT_VIOLATION(FaultNotFatal|TakesLockViolation); EX_TRY @@ -235,7 +233,7 @@ LPCSTR CHECK::FormatMessage(LPCSTR messageFormat, ...) va_list args; va_start( args, messageFormat); - SString s; + EString s; s.VPrintf(messageFormat, args); va_end(args); @@ -254,14 +252,12 @@ LPCSTR CHECK::FormatMessage(LPCSTR messageFormat, ...) return result; } -LPCSTR CHECK::AllocateDynamicMessage(const SString &s) +LPCSTR CHECK::AllocateDynamicMessage(const EString &s) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; - // Make a copy of it. - StackScratchBuffer buffer; - const char * pMsg = s.GetANSI(buffer); + const char * pMsg = s; // Must copy that into our own field. size_t len = strlen(pMsg) + 1; diff --git a/src/coreclr/utilcode/clrconfig.cpp b/src/coreclr/utilcode/clrconfig.cpp index aaa33a6e4b03f2..4d3e1f4a1db4c6 100644 --- a/src/coreclr/utilcode/clrconfig.cpp +++ b/src/coreclr/utilcode/clrconfig.cpp @@ -195,20 +195,20 @@ namespace if (len != 0) { - ret = temp.GetCopyOfUnicodeString(); + ret = temp.CreateCopyOfString(); #if defined(DEBUG) && !defined(SELF_NO_HOST) // Validate the cache and no-cache logic result in the same answer SString nameToConvert(name); - SString nameAsUTF8; + EString nameAsUTF8; nameToConvert.ConvertToUTF8(nameAsUTF8); - SString valueAsUTF8; + EString valueAsUTF8; temp.ConvertToUTF8(valueAsUTF8); - CLRConfigNoCache nonCache = CLRConfigNoCache::Get(nameAsUTF8.GetUTF8NoConvert(), noPrefix); + CLRConfigNoCache nonCache = CLRConfigNoCache::Get((LPCUTF8)nameAsUTF8, noPrefix); LPCSTR valueNoCache = nonCache.AsString(); - _ASSERTE(SString::_stricmp(valueNoCache, valueAsUTF8.GetUTF8NoConvert()) == 0); + _ASSERTE(StaticStringHelpers::_stricmp(valueNoCache, (LPCUTF8)valueAsUTF8) == 0); #endif // defined(DEBUG) && !defined(SELF_NO_HOST) } } @@ -662,13 +662,13 @@ void CLRConfig::Initialize() { // Check the prefix if(matchC - && SString::_wcsnicmp(wszName, COMPLUS_PREFIX, LEN_OF_COMPLUS_PREFIX) == 0) + && StaticStringHelpers::_wcsnicmp(wszName, COMPLUS_PREFIX, LEN_OF_COMPLUS_PREFIX) == 0) { wszName += LEN_OF_COMPLUS_PREFIX; s_EnvNames.Add(wszName, (DWORD) (wszCurr - wszName)); } else if (matchD - && SString::_wcsnicmp(wszName, DOTNET_PREFIX, LEN_OF_DOTNET_PREFIX) == 0) + && StaticStringHelpers::_wcsnicmp(wszName, DOTNET_PREFIX, LEN_OF_DOTNET_PREFIX) == 0) { wszName += LEN_OF_DOTNET_PREFIX; s_EnvNames.Add(wszName, (DWORD) (wszCurr - wszName)); diff --git a/src/coreclr/utilcode/debug.cpp b/src/coreclr/utilcode/debug.cpp index 3f4c74d420f9d1..c6eef990ea0166 100644 --- a/src/coreclr/utilcode/debug.cpp +++ b/src/coreclr/utilcode/debug.cpp @@ -29,7 +29,7 @@ void CreateCrashDumpIfEnabled(bool stackoverflow = false); // Global state counter to implement SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE. Volatile g_DbgSuppressAllocationAsserts = 0; -static void GetExecutableFileNameUtf8(SString& value) +static void GetExecutableFileNameUtf8(EString& value) { CONTRACTL { @@ -38,8 +38,8 @@ static void GetExecutableFileNameUtf8(SString& value) } CONTRACTL_END; - SString tmp; - WCHAR * pCharBuf = tmp.OpenUnicodeBuffer(_MAX_PATH); + InlineSString<_MAX_PATH> tmp; + WCHAR * pCharBuf = tmp.OpenBuffer(_MAX_PATH); DWORD numChars = GetModuleFileNameW(0 /* Get current executable */, pCharBuf, _MAX_PATH); tmp.CloseBuffer(numChars); @@ -242,7 +242,7 @@ VOID LogAssert( szFile, iLine, szExpr)); - LOG((LF_ASSERT, LL_FATALERROR, "RUNNING EXE: %ws\n", exename.GetUnicode())); + LOG((LF_ASSERT, LL_FATALERROR, "RUNNING EXE: %ws\n", (LPCWSTR)exename)); } //***************************************************************************** @@ -337,7 +337,7 @@ bool _DbgBreakCheck( // Check for ignore all. for (i = 0, psData = pDBGIFNORE->Ptr(); i < pDBGIFNORE->Count(); i++, psData++) { - if (psData->iLine == iLine && SString::_stricmp(psData->rcFile, szFile) == 0 && psData->bIgnore == true) + if (psData->iLine == iLine && StaticStringHelpers::_stricmp(psData->rcFile, szFile) == 0 && psData->bIgnore == true) { return false; } @@ -347,7 +347,7 @@ bool _DbgBreakCheck( char formatBuffer[4096]; - SString modulePath; + EString modulePath; BOOL formattedMessages = FALSE; // If we are low on memory we cannot even format a message. If this happens we want to @@ -364,7 +364,7 @@ bool _DbgBreakCheck( " Image: %s\n\n", GetCurrentProcessId(), GetCurrentProcessId(), GetCurrentThreadId(), GetCurrentThreadId(), - szExpr, szFile, iLine, modulePath.GetUTF8NoConvert()); + szExpr, szFile, iLine, (LPCUTF8)modulePath); formattedMessages = TRUE; } @@ -607,7 +607,7 @@ VOID DbgAssertDialog(const char *szFile, int iLine, const char *szExpr) // Returns true if successful, false on failure (such as OOM). // This never throws. //----------------------------------------------------------------------------- -bool GetStackTraceAtContext(SString & s, CONTEXT * pContext) +extern "C" bool GetStackTraceAtContext(EString & s, CONTEXT * pContext) { SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE; STATIC_CONTRACT_DEBUG_ONLY; @@ -624,7 +624,7 @@ bool GetStackTraceAtContext(SString & s, CONTEXT * pContext) // If we have a supplied context, then don't skip any frames. Else we'll // be using the current context, so skip this frame. const int cSkip = (pContext == NULL) ? 1 : 0; - char * szString = s.OpenANSIBuffer(cchMaxAssertStackLevelStringLen * cTotal); + char * szString = s.OpenBuffer(cchMaxAssertStackLevelStringLen * cTotal); GetStringFromStackLevels(cSkip, cTotal, szString, pContext); s.CloseBuffer((COUNT_T) strlen(szString)); @@ -671,8 +671,8 @@ void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, cons __FreeBuildDebugBreak(); - SString buffer; - SString modulePath; + EString buffer; + EString modulePath; GetExecutableFileNameUtf8(modulePath); @@ -680,11 +680,11 @@ void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, cons " File: %s, Line: %d Image:\n%s\n", GetCurrentProcessId(), GetCurrentProcessId(), GetCurrentThreadId(), GetCurrentThreadId(), - szExpr, szFile, iLine, modulePath.GetUTF8NoConvert()); - OutputDebugStringUtf8(buffer.GetUTF8NoConvert()); + szExpr, szFile, iLine, (LPCUTF8)modulePath); + OutputDebugStringUtf8(buffer); // Write out the error to the console - printf(buffer.GetUTF8NoConvert()); + printf(buffer); // Log to the stress log. Note that we can't include the szExpr b/c that // may not be a string literal (particularly for formatt-able asserts). diff --git a/src/coreclr/utilcode/ex.cpp b/src/coreclr/utilcode/ex.cpp index f898fb1fe550ff..1da3abfccdb23b 100644 --- a/src/coreclr/utilcode/ex.cpp +++ b/src/coreclr/utilcode/ex.cpp @@ -831,13 +831,13 @@ void SEHException::GetMessage(SString &string) { if (m_exception.ExceptionCode != 0) { - string.Printf("Exception code 0x%.8x", m_exception.ExceptionCode); + string.Printf(W("Exception code 0x%.8x"), m_exception.ExceptionCode); } else { // If we don't have a valid exception code, then give a generic message that's a little nicer than // "code 0x00000000". - string.Printf("Unknown exception"); + string.Append(W("Unknown exception")); } } } @@ -930,7 +930,7 @@ void DelegatingException::GetMessage(SString &result) { // If we don't have a valid exception code, then give a generic message // that's a little nicer than "code 0x00000000". - result.Printf("Unknown exception"); + result.Append(W("Unknown exception")); } } // void DelegatingException::GetMessage() @@ -1011,7 +1011,7 @@ void DECLSPEC_NORETURN ThrowHR(HRESULT hr, UINT uText) // We won't check the return value here. If it fails, we'll just // throw the HR - sExceptionText.LoadResource(CCompRC::Error, uText); + LoadResource(sExceptionText, CCompRC::Error, uText); EX_THROW(HRMsgException, (hr, sExceptionText)); } @@ -1162,7 +1162,7 @@ void GetHRMsg(HRESULT hr, SString &result, BOOL bNoGeekStuff/* = FALSE*/) if (FAILED(hr) && HRESULT_FACILITY(hr) == FACILITY_URT && HRESULT_CODE(hr) < MAX_URT_HRESULT_CODE) { - fHaveDescr = strDescr.LoadResource(CCompRC::Error, MSG_FOR_URT_HR(hr)); + fHaveDescr = LoadResource(strDescr, CCompRC::Error, MSG_FOR_URT_HR(hr)); } else { @@ -1185,10 +1185,10 @@ void GetHRMsg(HRESULT hr, SString &result, BOOL bNoGeekStuff/* = FALSE*/) if (!bNoGeekStuff) { - SString geekStuffUtf8; + EString geekStuffUtf8; if (fHaveDescr) { - geekStuffUtf8.AppendUTF8(" ("); + geekStuffUtf8.Append(" ("); } geekStuffUtf8.AppendPrintf("0x%.8X", hr); @@ -1201,10 +1201,10 @@ void GetHRMsg(HRESULT hr, SString &result, BOOL bNoGeekStuff/* = FALSE*/) if (fHaveDescr) { - geekStuffUtf8.AppendUTF8(")"); + geekStuffUtf8.Append(")"); } - result.Append(geekStuffUtf8); + result.Append(geekStuffUtf8.MoveToUnicode()); } } diff --git a/src/coreclr/utilcode/loaderheap.cpp b/src/coreclr/utilcode/loaderheap.cpp index 7638031add7db1..e69d969a782449 100644 --- a/src/coreclr/utilcode/loaderheap.cpp +++ b/src/coreclr/utilcode/loaderheap.cpp @@ -397,7 +397,7 @@ struct LoaderHeapEvent size_t m_dwSize; //Actual size of block (including validation tags, padding, everything) - void Describe(SString *pSString) + void Describe(EString *pEString) { CONTRACTL { @@ -407,10 +407,10 @@ struct LoaderHeapEvent } CONTRACTL_END - pSString->AppendASCII("\n"); + pEString->Append("\n"); { - StackSString buf; + StackEString buf; if (m_allocationType == kFreedMem) { buf.Printf(" Freed at: %s (line %d)\n", m_szFile, m_lineNum); @@ -420,59 +420,59 @@ struct LoaderHeapEvent { buf.Printf(" Allocated at: %s (line %d)\n", m_szFile, m_lineNum); } - pSString->Append(buf); + pEString->Append(buf); } if (!QuietValidate()) { - pSString->AppendASCII(" *** THIS BLOCK HAS BEEN CORRUPTED ***\n"); + pEString->Append(" *** THIS BLOCK HAS BEEN CORRUPTED ***\n"); } { - StackSString buf; + StackEString buf; buf.Printf(" Type: "); switch (m_allocationType) { case kAllocMem: - buf.AppendASCII("AllocMem()\n"); + buf.Append("AllocMem()\n"); break; case kFreedMem: - buf.AppendASCII("Free\n"); + buf.Append("Free\n"); break; default: break; } - pSString->Append(buf); + pEString->Append(buf); } { - StackSString buf; + StackEString buf; buf.Printf(" Start of block: 0x%p\n", m_pMem); - pSString->Append(buf); + pEString->Append(buf); } { - StackSString buf; + StackEString buf; buf.Printf(" End of block: 0x%p\n", ((BYTE*)m_pMem) + m_dwSize - 1); - pSString->Append(buf); + pEString->Append(buf); } { - StackSString buf; + StackEString buf; buf.Printf(" Requested size: %lu (0x%lx)\n", (ULONG)m_dwRequestedSize, (ULONG)m_dwRequestedSize); - pSString->Append(buf); + pEString->Append(buf); } { - StackSString buf; + StackEString buf; buf.Printf(" Actual size: %lu (0x%lx)\n", (ULONG)m_dwSize, (ULONG)m_dwSize); - pSString->Append(buf); + pEString->Append(buf); } - pSString->AppendASCII("\n"); + pEString->Append("\n"); } @@ -608,10 +608,10 @@ class LoaderHeapSniffer } - static VOID PitchSniffer(SString *pSString) + static VOID PitchSniffer(EString *pEString) { WRAPPER_NO_CONTRACT; - pSString->AppendASCII("\n" + pEString->Append("\n" "\nBecause call-tracing wasn't turned on, we couldn't provide details about who last owned the affected memory block. To get more precise diagnostics," "\nset the following registry DWORD value:" "\n" @@ -1550,7 +1550,7 @@ void UnlockedLoaderHeap::UnlockedBackoutMem(void *pMem, { CONTRACT_VIOLATION(ThrowsViolation|FaultViolation); // We're reporting a heap corruption - who cares about violations - StackSString message; + StackEString message; message.Printf("HEAP VIOLATION: Invalid BackoutMem() call made at:\n" "\n" " File: %s\n" @@ -1578,22 +1578,22 @@ void UnlockedLoaderHeap::UnlockedBackoutMem(void *pMem, if (m_dwDebugFlags & kCallTracing) { - message.AppendASCII("*** CALLTRACING ENABLED ***\n"); + message.Append("*** CALLTRACING ENABLED ***\n"); LoaderHeapEvent *pEvent = LoaderHeapSniffer::FindEvent(this, pMem); if (!pEvent) { - message.AppendASCII("This pointer doesn't appear to have come from this LoaderHeap.\n"); + message.Append("This pointer doesn't appear to have come from this LoaderHeap.\n"); } else { - message.AppendASCII(pMem == pEvent->m_pMem ? "We have the following data about this pointer:" : "This pointer points to the middle of the following block:"); + message.Append(pMem == pEvent->m_pMem ? "We have the following data about this pointer:" : "This pointer points to the middle of the following block:"); pEvent->Describe(&message); } } if (pTag->m_dwRequestedSize != dwRequestedSize) { - StackSString buf; + StackEString buf; buf.Printf( "Possible causes:\n" "\n" @@ -1608,7 +1608,7 @@ void UnlockedLoaderHeap::UnlockedBackoutMem(void *pMem, } else { - message.AppendASCII("This memory block is completely unrecognizable.\n"); + message.Append("This memory block is completely unrecognizable.\n"); } @@ -1617,8 +1617,7 @@ void UnlockedLoaderHeap::UnlockedBackoutMem(void *pMem, LoaderHeapSniffer::PitchSniffer(&message); } - StackScratchBuffer scratch; - DbgAssertDialog(szFile, lineNum, (char*) message.GetANSI(scratch)); + DbgAssertDialog(szFile, lineNum, message); } } @@ -2164,7 +2163,7 @@ void LoaderHeapSniffer::ValidateFreeList(UnlockedLoaderHeap *pHeap) } { - StackSString message; + StackEString message; message.Printf("A loaderheap freelist has been corrupted. The bytes at or near address 0x%p appears to have been overwritten. We expected to see %s here.\n" "\n" @@ -2181,7 +2180,7 @@ void LoaderHeapSniffer::ValidateFreeList(UnlockedLoaderHeap *pHeap) if (!(pHeap->m_dwDebugFlags & pHeap->kCallTracing)) { - message.AppendASCII("\nThe usual reason is that someone wrote past the end of a block or wrote into a block after freeing it." + message.Append("\nThe usual reason is that someone wrote past the end of a block or wrote into a block after freeing it." "\nOf course, the culprit is long gone so it's probably too late to debug this now. Try turning on call-tracing" "\nand reproing. We can attempt to find out who last owned the surrounding pieces of memory." "\n" @@ -2196,16 +2195,16 @@ void LoaderHeapSniffer::ValidateFreeList(UnlockedLoaderHeap *pHeap) { LoaderHeapEvent *pBadAddrEvent = FindEvent(pHeap, pBadAddr); - message.AppendASCII("*** CALL TRACING ENABLED ***\n\n"); + message.Append("*** CALL TRACING ENABLED ***\n\n"); if (pBadAddrEvent) { - message.AppendASCII("\nThe last known owner of the corrupted address was:\n"); + message.Append("\nThe last known owner of the corrupted address was:\n"); pBadAddrEvent->Describe(&message); } else { - message.AppendASCII("\nNo known owner of last corrupted address.\n"); + message.Append("\nNo known owner of last corrupted address.\n"); } LoaderHeapEvent *pPrevEvent = FindEvent(pHeap, ((BYTE*)pProbeThis) - 1); @@ -2215,14 +2214,14 @@ void LoaderHeapSniffer::ValidateFreeList(UnlockedLoaderHeap *pHeap) pPrevEvent != NULL && ( ((UINT_PTR)pProbeThis) - ((UINT_PTR)(pPrevEvent->m_pMem)) + pPrevEvent->m_dwSize ) < 1024) { - message.AppendASCII("\nThis block is located close to the corruption point. "); + message.Append("\nThis block is located close to the corruption point. "); if (!pHeap->IsInterleaved() && pPrevEvent->QuietValidate()) { - message.AppendASCII("If it was overrun, it might have caused this."); + message.Append("If it was overrun, it might have caused this."); } else { - message.AppendASCII("*** CORRUPTION DETECTED IN THIS BLOCK ***"); + message.Append("*** CORRUPTION DETECTED IN THIS BLOCK ***"); } pPrevEvent->Describe(&message); pPrevEvent = FindEvent(pHeap, ((BYTE*)(pPrevEvent->m_pMem)) - 1); @@ -2231,8 +2230,7 @@ void LoaderHeapSniffer::ValidateFreeList(UnlockedLoaderHeap *pHeap) } - StackScratchBuffer scratch; - DbgAssertDialog(__FILE__, __LINE__, (char*) message.GetANSI(scratch)); + DbgAssertDialog(__FILE__, __LINE__, message); } diff --git a/src/coreclr/utilcode/longfilepathwrappers.cpp b/src/coreclr/utilcode/longfilepathwrappers.cpp index 472033bd660297..d4378f5fe617a1 100644 --- a/src/coreclr/utilcode/longfilepathwrappers.cpp +++ b/src/coreclr/utilcode/longfilepathwrappers.cpp @@ -62,7 +62,7 @@ LoadLibraryExWrapper( LongFile::NormalizeDirectorySeparators(path); #endif //HOST_WINDOWS - ret = LoadLibraryExW(path.GetUnicode(), hFile, dwFlags); + ret = LoadLibraryExW(path, hFile, dwFlags); } lastError = GetLastError(); @@ -108,7 +108,7 @@ CreateFileWrapper( if (SUCCEEDED(LongFile::NormalizePath(path))) { - ret = CreateFileW(path.GetUnicode(), + ret = CreateFileW(path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, @@ -156,7 +156,7 @@ GetFileAttributesWrapper( if (SUCCEEDED(LongFile::NormalizePath(path))) { ret = GetFileAttributesW( - path.GetUnicode() + path ); } @@ -200,7 +200,7 @@ GetFileAttributesExWrapper( if (SUCCEEDED(LongFile::NormalizePath(path))) { ret = GetFileAttributesExW( - path.GetUnicode(), + path, fInfoLevelId, lpFileInformation ); @@ -245,7 +245,7 @@ DeleteFileWrapper( if (SUCCEEDED(LongFile::NormalizePath(path))) { ret = DeleteFileW( - path.GetUnicode() + path ); } @@ -287,7 +287,7 @@ SearchPathWrapper( EX_TRY { - LongPathString Existingpath(LongPathString::Literal, lpPath); + SString Existingpath(SString::Literal, lpPath); if (lpPath != NULL) { @@ -297,7 +297,7 @@ SearchPathWrapper( } else { - lpPath = Existingpath.GetUnicode(); + lpPath = Existingpath; } } @@ -314,14 +314,14 @@ SearchPathWrapper( } else { - COUNT_T size = lpBuffer.GetUnicodeAllocation() + 1; + COUNT_T size = lpBuffer.GetAllocation() + 1; ret = SearchPathW( lpPath, lpFileName, lpExtension, size, - lpBuffer.OpenUnicodeBuffer(size - 1), + lpBuffer.OpenBuffer(size - 1), lpFilePart ); @@ -333,7 +333,7 @@ SearchPathWrapper( lpFileName, lpExtension, ret, - lpBuffer.OpenUnicodeBuffer(ret - 1), + lpBuffer.OpenBuffer(ret - 1), lpFilePart ); } @@ -377,11 +377,11 @@ GetModuleFileNameWrapper( EX_TRY { - COUNT_T size = buffer.GetUnicodeAllocation() + 1; + COUNT_T size = buffer.GetAllocation() + 1; ret = GetModuleFileNameW( hModule, - buffer.OpenUnicodeBuffer(size - 1), + buffer.OpenBuffer(size - 1), (DWORD)size ); @@ -392,7 +392,7 @@ GetModuleFileNameWrapper( size = size * 2; ret = GetModuleFileNameW( hModule, - buffer.OpenUnicodeBuffer(size - 1), + buffer.OpenBuffer(size - 1), (DWORD)size ); @@ -437,7 +437,7 @@ DWORD WINAPI GetTempPathWrapper( ret = GetTempPathW( size, - lpBuffer.OpenUnicodeBuffer(size - 1) + lpBuffer.OpenBuffer(size - 1) ); lastError = GetLastError(); @@ -478,7 +478,7 @@ DWORD WINAPI GetCurrentDirectoryWrapper( ret = GetCurrentDirectoryW( size, - lpBuffer.OpenUnicodeBuffer(size - 1) + lpBuffer.OpenBuffer(size - 1) ); lastError = GetLastError(); @@ -516,11 +516,11 @@ DWORD WINAPI GetEnvironmentVariableWrapper( EX_TRY { - COUNT_T size = lpBuffer.GetUnicodeAllocation() + 1; + COUNT_T size = lpBuffer.GetAllocation() + 1; ret = GetEnvironmentVariableW( lpName, - lpBuffer.OpenUnicodeBuffer(size - 1), + lpBuffer.OpenBuffer(size - 1), size ); @@ -536,7 +536,7 @@ DWORD WINAPI GetEnvironmentVariableWrapper( lpBuffer.CloseBuffer(); ret = GetEnvironmentVariableW( lpName, - lpBuffer.OpenUnicodeBuffer(size - 1), + lpBuffer.OpenBuffer(size - 1), size); } @@ -589,8 +589,8 @@ CopyFileExWrapper( if (SUCCEEDED(LongFile::NormalizePath(Existingpath)) && SUCCEEDED(LongFile::NormalizePath(Newpath))) { ret = CopyFileExW( - Existingpath.GetUnicode(), - Newpath.GetUnicode(), + Existingpath, + Newpath, lpProgressRoutine, lpData, pbCancel, @@ -708,11 +708,11 @@ HRESULT LongFile::NormalizePath(SString & path) } - COUNT_T size = path.GetUnicodeAllocation() + 1; - WCHAR* buffer = path.OpenUnicodeBuffer(size - 1); + COUNT_T size = path.GetAllocation() + 1; + WCHAR* buffer = path.OpenBuffer(size - 1); ret = GetFullPathNameW( - originalPath.GetUnicode(), + originalPath, size - prefixLen, //memory avilable for path after reserving for prefix (buffer + prefixLen), //reserve memory for prefix NULL @@ -727,10 +727,10 @@ HRESULT LongFile::NormalizePath(SString & path) { path.CloseBuffer(); size = ret + prefixLen; - buffer = path.OpenUnicodeBuffer(size -1); + buffer = path.OpenBuffer(size -1); ret = GetFullPathNameW( - originalPath.GetUnicode(), + originalPath, ret, // memory required for the path (buffer + prefixLen), //reserve memory for prefix NULL @@ -744,13 +744,13 @@ HRESULT LongFile::NormalizePath(SString & path) } } - SString fullpath(SString::Literal,buffer + prefixLen); + SString fullpath(SString::Literal, buffer + prefixLen); //Check if the resolved path is a UNC. By default we assume relative path to resolve to disk if (fullpath.BeginsWith(SL(UNCPathPrefix)) && prefixLen != prefix.GetCount() - (COUNT_T)wcslen(UNCPATHPREFIX)) { //Remove the leading '\\' from the UNC path to be replaced with UNCExtendedPathPrefix - fullpath.Replace(fullpath.Begin(), (COUNT_T)wcslen(UNCPATHPREFIX), UNCExtendedPathPrefix); + fullpath.Replace(fullpath.Begin(), (COUNT_T)wcslen(UNCPATHPREFIX), SL(UNCExtendedPathPrefix)); path.CloseBuffer(); path.Set(fullpath); } @@ -758,7 +758,7 @@ HRESULT LongFile::NormalizePath(SString & path) { //wcscpy_s always termintes with NULL, so we are saving the character that will be overwriiten WCHAR temp = buffer[prefix.GetCount()]; - wcscpy_s(buffer, prefix.GetCount() + 1, prefix.GetUnicode()); + wcscpy_s(buffer, prefix.GetCount() + 1, prefix); buffer[prefix.GetCount()] = temp; path.CloseBuffer(ret + prefixLen); } diff --git a/src/coreclr/utilcode/makepath.cpp b/src/coreclr/utilcode/makepath.cpp index 161e859455327d..828558edd911d0 100644 --- a/src/coreclr/utilcode/makepath.cpp +++ b/src/coreclr/utilcode/makepath.cpp @@ -152,7 +152,7 @@ void MakePath ( // Returns the directory for clr module. So, if path was for "C:\Dir1\Dir2\Filename.DLL", -// then this would return "C:\Dir1\Dir2\" (note the trailing backslash).HRESULT GetClrModuleDirectory(SString& wszPath) +// then this would return "C:\Dir1\Dir2\" (note the trailing backslash).HRESULT GetClrModuleDirectory(EString& wszPath) HRESULT GetClrModuleDirectory(SString& wszPath) { CONTRACTL @@ -180,9 +180,9 @@ HRESULT GetClrModuleDirectory(SString& wszPath) // Warning: The input file name string might be destroyed. // // Arguments: -// pPathString - [in] SString with file name +// pPathString - [in] EString with file name // -// pBuffer - [out] SString . +// pBuffer - [out] EString . // // Return Value: // S_OK - Output buffer contains path name. diff --git a/src/coreclr/utilcode/namespaceutil.cpp b/src/coreclr/utilcode/namespaceutil.cpp index 5b6d3d9f95bee8..bac805df0be053 100644 --- a/src/coreclr/utilcode/namespaceutil.cpp +++ b/src/coreclr/utilcode/namespaceutil.cpp @@ -482,7 +482,37 @@ int ns::MakePath( // true ok, false out of memory return ns::MakePath(szOut, iLen, szNameSpace, szName); } // int ns::MakePath() -void ns::MakePath( // throws on out of memory +void ns::MakePath( // throws on out of memory + EString &ssBuf, // Where to put results. + const EString &ssNameSpace, // Namespace for name. + const EString &ssName) // Final part of name. +{ + STATIC_CONTRACT_THROWS; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_FAULT; + + ssBuf.Clear(); + + if (!ssNameSpace.IsEmpty()) + { + if (ssName.IsEmpty()) + { + ssBuf.Set(ssNameSpace); + } + else + { + EString s(EString::Literal, NAMESPACE_SEPARATOR_STR); + ssBuf.Set(ssNameSpace, s); + } + } + + if (!ssName.IsEmpty()) + { + ssBuf.Append(ssName); + } +} + +void ns::MakePath( // throws on out of memory SString &ssBuf, // Where to put results. const SString &ssNameSpace, // Namespace for name. const SString &ssName) // Final part of name. @@ -662,9 +692,9 @@ int ns::MakeNestedTypeName( // true ok, false truncation. } // int ns::MakeNestedTypeName() void ns::MakeNestedTypeName( // throws on out of memory - SString &ssBuf, // output path for name. - const SString &ssEnclosingName, // Full name for enclosing type - const SString &ssNestedName) // Full name for nested type + EString &ssBuf, // output path for name. + const EString &ssEnclosingName, // Full name for enclosing type + const EString &ssNestedName) // Full name for nested type { STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_NOTRIGGER; @@ -672,7 +702,7 @@ void ns::MakeNestedTypeName( // throws on out of memory ssBuf.Clear(); ssBuf.Append(ssEnclosingName); - ssBuf.Append(NESTED_SEPARATOR_WCHAR); + ssBuf.Append(NESTED_SEPARATOR_STR); ssBuf.Append(ssNestedName); } diff --git a/src/coreclr/utilcode/pedecoder.cpp b/src/coreclr/utilcode/pedecoder.cpp index 209db00f9e40bf..dc72f5339a3749 100644 --- a/src/coreclr/utilcode/pedecoder.cpp +++ b/src/coreclr/utilcode/pedecoder.cpp @@ -1492,7 +1492,7 @@ CHECK PEDecoder::CheckILOnlyImportDlls() const CHECK(CheckRva(nameRVA, (COUNT_T) sizeof("mscoree.dll"))); // Make sure the name is equal to mscoree - CHECK(SString::_stricmp( (char *)GetRvaData(nameRVA), "mscoree.dll") == 0); + CHECK(StaticStringHelpers::_stricmp( (char *)GetRvaData(nameRVA), "mscoree.dll") == 0); // Check the Hint/Name table. CHECK(CheckILOnlyImportByNameTable(VAL32(IMAGE_IMPORT_DESC_FIELD(pID[0], OriginalFirstThunk)))); @@ -1538,7 +1538,7 @@ CHECK PEDecoder::CheckILOnlyImportByNameTable(RVA rva) const IMAGE_IMPORT_BY_NAME *import = (IMAGE_IMPORT_BY_NAME*) GetRvaData(importRVA); - CHECK(SString::_stricmp((char *) import->Name, DLL_NAME) == 0 || _stricmp((char *) import->Name, EXE_NAME) == 0); + CHECK(StaticStringHelpers::_stricmp((char *) import->Name, DLL_NAME) == 0 || _stricmp((char *) import->Name, EXE_NAME) == 0); CHECK_OK; } diff --git a/src/coreclr/utilcode/posterror.cpp b/src/coreclr/utilcode/posterror.cpp index 78926f090593cd..e44900f62f9ae6 100644 --- a/src/coreclr/utilcode/posterror.cpp +++ b/src/coreclr/utilcode/posterror.cpp @@ -74,7 +74,7 @@ HRESULT UtilLoadResourceString(CCompRC::ResourceCategory eCategory, UINT iResour HRESULT retVal = E_OUTOFMEMORY; - SString::Startup(); + StaticStringHelpers::Startup(); EX_TRY { CCompRC *pResourceDLL = CCompRC::GetDefaultResourceDll(); diff --git a/src/coreclr/utilcode/safewrap.cpp b/src/coreclr/utilcode/safewrap.cpp index 40708191ea2049..abd15cd3616b0d 100644 --- a/src/coreclr/utilcode/safewrap.cpp +++ b/src/coreclr/utilcode/safewrap.cpp @@ -5,7 +5,7 @@ // // -// This file contains wrapper functions for Win32 API's that take SStrings +// This file contains wrapper functions for Win32 API's that take EStrings // and use CLR-safe holders. // // See guidelines in SafeWrap.h for writing these APIs. diff --git a/src/coreclr/utilcode/sbuffer.cpp b/src/coreclr/utilcode/sbuffer.cpp index 215efefb199fc6..aa77a57b5a0b12 100644 --- a/src/coreclr/utilcode/sbuffer.cpp +++ b/src/coreclr/utilcode/sbuffer.cpp @@ -142,4 +142,24 @@ void SBuffer::Replace(const Iterator &i, COUNT_T deleteSize, COUNT_T insertSize) RETURN; } +#ifdef DACCESS_COMPILE +void* SBuffer::DacTryGetRawContent() const +{ + HRESULT status = S_OK; + void* buf = NULL; + EX_TRY + { + buf = SBuffer::DacGetRawContent(); + } + EX_CATCH_HRESULT(status); + if (SUCCEEDED(status)) + { + return buf; + } + else + { + return NULL; + } +} +#endif diff --git a/src/coreclr/utilcode/splitpath.cpp b/src/coreclr/utilcode/splitpath.cpp index f5100ef72d3271..bd3f6e78b5bd91 100644 --- a/src/coreclr/utilcode/splitpath.cpp +++ b/src/coreclr/utilcode/splitpath.cpp @@ -203,56 +203,3 @@ void SplitPathInterior( } } } - -/*** -*SplitPath() - split a path name into its individual components -* -*Purpose: -* to split a path name into its individual components -* -*Entry: -* path - SString representing the path name to be parsed -* drive - Out SString for drive component -* dir - Out SString for subdirectory component -* fname - Out SString for file base name component -* ext - Out SString for file name extension component -* -*Exit: -* drive - Drive string. Includes ':' if a drive was given. -* dir - Subdirectory string. Includes leading and trailing -* '/' or '\', if any. -* fname - File base name -* ext - File extension, if any. Includes leading '.'. -* -*Exceptions: -* -*******************************************************************************/ - -void SplitPath(_In_ SString const &path, - __inout_opt SString *drive, - __inout_opt SString *dir, - __inout_opt SString *fname, - __inout_opt SString *ext) -{ - LPCWSTR wzDrive, wzDir, wzFname, wzExt; - size_t cchDrive, cchDir, cchFname, cchExt; - - SplitPathInterior(path, - &wzDrive, &cchDrive, - &wzDir, &cchDir, - &wzFname, &cchFname, - &wzExt, &cchExt); - - if (drive != NULL) - drive->Set(wzDrive, (COUNT_T)cchDrive); - - if (dir != NULL) - dir->Set(wzDir, (COUNT_T)cchDir); - - if (fname != NULL) - fname->Set(wzFname, (COUNT_T)cchFname); - - if (ext != NULL) - ext->Set(wzExt, (COUNT_T)cchExt); -} - diff --git a/src/coreclr/utilcode/sstring.cpp b/src/coreclr/utilcode/sstring.cpp index ec3c340ff23d3c..b5f7ea96950dfc 100644 --- a/src/coreclr/utilcode/sstring.cpp +++ b/src/coreclr/utilcode/sstring.cpp @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- -// SString.cpp +// EString.cpp // // --------------------------------------------------------------------------- @@ -21,42 +21,55 @@ //----------------------------------------------------------------------------- // Have one internal, well-known, literal for the empty string. -const BYTE SString::s_EmptyBuffer[2] = { 0 }; +const BYTE StaticStringHelpers::s_EmptyBuffer[2] = { 0 }; -// @todo: these need to be initialized by calling GetACP() - -UINT SString::s_ACP = 0; +SPTR_IMPL(EString, StaticStringHelpers, s_EmptyUnicode); +SPTR_IMPL(EString, StaticStringHelpers, s_EmptyUtf8); +SPTR_IMPL(EString, StaticStringHelpers, s_EmptyAscii); #ifndef DACCESS_COMPILE -static BYTE s_EmptySpace[sizeof(SString)] = { 0 }; -#endif // DACCESS_COMPILE - -SPTR_IMPL(SString,SString,s_Empty); +namespace +{ + alignas(SString) + BYTE emptyUnicodeSpace[(sizeof(SString))] = { 0 }; + alignas(EString) + BYTE emptyUtf8Space[(sizeof(EString))] = { 0 }; + alignas(EString) + BYTE emptyAsciiSpace[(sizeof(EString))] = { 0 }; +} +#endif -void SString::Startup() +void StaticStringHelpers::Startup() { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; - - if (s_ACP == 0) - { - UINT ACP = GetACP(); - + #ifndef DACCESS_COMPILE - s_Empty = PTR_SString(new (s_EmptySpace) SString()); - s_Empty->SetNormalized(); -#endif // DACCESS_COMPILE - + if (s_EmptyUnicode == NULL) + { + s_EmptyUnicode = PTR_SString(new (emptyUnicodeSpace) SString()); + MemoryBarrier(); + } + if (s_EmptyUtf8 == NULL) + { + s_EmptyUtf8 = PTR_EString(new (emptyUtf8Space) EString()); + MemoryBarrier(); + } + if (s_EmptyAscii == NULL) + { + s_EmptyAscii = PTR_EString(new (emptyAsciiSpace) EString()); MemoryBarrier(); - s_ACP = ACP; } +#endif // DACCESS_COMPILE } -CHECK SString::CheckStartup() +CHECK StaticStringHelpers::CheckStartup() { WRAPPER_NO_CONTRACT; - - CHECK(s_Empty != NULL); + + CHECK(s_EmptyUnicode != NULL); + CHECK(s_EmptyUtf8 != NULL); + CHECK(s_EmptyAscii != NULL); CHECK_OK; } @@ -112,8 +125,7 @@ static WCHAR MapChar(WCHAR wc, DWORD dwFlags) #define SIMPLE_UPCASE(x) (IS_LOWER_A_TO_Z(x) ? ((x) - W('a') + W('A')) : (x)) #define SIMPLE_DOWNCASE(x) (IS_UPPER_A_TO_Z(x) ? ((x) - W('A') + W('a')) : (x)) -/* static */ -int SString::CaseCompareHelper(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount) +int CaseCompareHelper(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount) { LIMITED_METHOD_CONTRACT; @@ -155,8 +167,7 @@ int SString::CaseCompareHelper(const WCHAR *buffer1, const WCHAR *buffer2, COUNT #define CAN_SIMPLE_UPCASE_ANSI(x) (((x) >= 0x20) && ((x) <= 0x7f)) #define SIMPLE_UPCASE_ANSI(x) (IS_LOWER_A_TO_Z(x) ? ((x) - 'a' + 'A') : (x)) -/* static */ -int SString::CaseCompareHelperA(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount) +int CaseCompareHelperA(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount) { LIMITED_METHOD_CONTRACT; @@ -207,7 +218,7 @@ int CaseHashHelper(const WCHAR *buffer, COUNT_T count) return hash; } -static int CaseHashHelperA(const CHAR *buffer, COUNT_T count) +int CaseHashHelperA(const CHAR *buffer, COUNT_T count) { LIMITED_METHOD_CONTRACT; @@ -225,2345 +236,368 @@ static int CaseHashHelperA(const CHAR *buffer, COUNT_T count) return hash; } -//----------------------------------------------------------------------------- -// Set this string to a copy of the unicode string -//----------------------------------------------------------------------------- -void SString::Set(const WCHAR *string) +template<> +COUNT_T EString::ConvertToUTF8(EString& s) const { - CONTRACT_VOID + CONTRACT(COUNT_T) { - INSTANCE_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); + PRECONDITION(s.Check()); THROWS; GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; - - if (string == NULL || *string == 0) - Clear(); - else - { - Resize((COUNT_T) wcslen(string), REPRESENTATION_UNICODE); - wcscpy_s(GetRawUnicode(), GetBufferSizeInCharIncludeNullChar(), string); - } - - RETURN; + s.Set(GetRawBuffer()); + RETURN GetCount() + 1; } -//----------------------------------------------------------------------------- -// Set this string to a copy of the first count characters of the given -// unicode string. -//----------------------------------------------------------------------------- -void SString::Set(const WCHAR *string, COUNT_T count) +template<> +COUNT_T EString::ConvertToUTF8(EString &s) const { - SS_CONTRACT_VOID + CONTRACT(COUNT_T) { - INSTANCE_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - PRECONDITION(CheckCount(count)); + PRECONDITION(s.Check()); THROWS; GC_NOTRIGGER; } - SS_CONTRACT_END; - - if (count == 0) - Clear(); - else - { - Resize(count, REPRESENTATION_UNICODE); - wcsncpy_s(GetRawUnicode(), GetBufferSizeInCharIncludeNullChar(), string, count); - GetRawUnicode()[count] = 0; - } + CONTRACT_END; - SS_RETURN; + s.Set(GetRawBuffer()); + RETURN GetCount() + 1; } -//----------------------------------------------------------------------------- -// Set this string to a point to the first count characters of the given -// preallocated unicode string (shallow copy). -//----------------------------------------------------------------------------- -void SString::SetPreallocated(const WCHAR *string, COUNT_T count) +template<> +COUNT_T SString::ConvertToUTF8(EString& s) const { - SS_CONTRACT_VOID + CONTRACT(COUNT_T) { - INSTANCE_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - PRECONDITION(CheckCount(count)); - SS_POSTCONDITION(IsEmpty()); + PRECONDITION(s.Check()); + THROWS; GC_NOTRIGGER; - NOTHROW; SUPPORTS_DAC_HOST_ONLY; } - SS_CONTRACT_END; - - SetImmutable(); - SetImmutable((BYTE*) string, count*2); - ClearAllocated(); - SetRepresentation(REPRESENTATION_UNICODE); - - SS_RETURN; -} + CONTRACT_END; + // @todo: use WC_NO_BEST_FIT_CHARS + bool allAscii; + DWORD length; -//----------------------------------------------------------------------------- -// Set this string to a copy of the given ansi string -//----------------------------------------------------------------------------- -void SString::SetASCII(const ASCII *string) -{ - SS_CONTRACT_VOID - { - INSTANCE_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - PRECONDITION(CheckASCIIString(string)); - THROWS; - GC_NOTRIGGER; - } - SS_CONTRACT_END; + HRESULT hr = FString::Unicode_Utf8_Length(GetRawBuffer(), & allAscii, & length); - if (string == NULL || *string == 0) - Clear(); - else + if (SUCCEEDED(hr)) { - Resize((COUNT_T) strlen(string), REPRESENTATION_ASCII); - strcpy_s(GetRawUTF8(), GetBufferSizeInCharIncludeNullChar(), string); - } + LPUTF8 buffer = s.OpenBuffer(length); - SS_RETURN; -} + //FString::Unicode_Utf8 expects an array all the time + //we optimize the empty string by replacing it with null for EString above in Resize + if (length > 0) + { + hr = FString::Unicode_Utf8(GetRawBuffer(), allAscii, buffer, length); + } -//----------------------------------------------------------------------------- -// Set this string to a copy of the first count characters of the given -// ascii string -//----------------------------------------------------------------------------- -void SString::SetASCII(const ASCII *string, COUNT_T count) -{ - SS_CONTRACT_VOID - { - INSTANCE_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - PRECONDITION(CheckASCIIString(string, count)); - PRECONDITION(CheckCount(count)); - THROWS; - GC_NOTRIGGER; + s.CloseBuffer(); } - SS_CONTRACT_END; - if (count == 0) - Clear(); - else - { - Resize(count, REPRESENTATION_ASCII); - strncpy_s(GetRawASCII(), GetBufferSizeInCharIncludeNullChar(), string, count); - GetRawASCII()[count] = 0; - } + IfFailThrow(hr); - SS_RETURN; + RETURN length + 1; } -//----------------------------------------------------------------------------- -// Set this string to a copy of the given UTF8 string -//----------------------------------------------------------------------------- -void SString::SetUTF8(const UTF8 *string) +template<> +COUNT_T EString::ConvertToUnicode(SString& s) const { - SS_CONTRACT_VOID + CONTRACT(COUNT_T) { - // !!! Check for illegal UTF8 encoding? - INSTANCE_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); + PRECONDITION(s.Check()); THROWS; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } - SS_CONTRACT_END; + CONTRACT_END; + COUNT_T length = WszMultiByteToWideChar(CP_UTF8, 0, GetRawBuffer(), GetCount()+1, 0, 0); + if (length == 0) + ThrowLastError(); - if (string == NULL || *string == 0) - Clear(); - else - { - Resize((COUNT_T) strlen(string), REPRESENTATION_UTF8); - strcpy_s(GetRawUTF8(), GetBufferSizeInCharIncludeNullChar(), string); - } + LPWSTR buffer = s.OpenBuffer(length - 1); + + length = WszMultiByteToWideChar(CP_UTF8, 0, GetRawBuffer(), GetCount()+1, buffer, length); + s.CloseBuffer(); + if (length == 0) + ThrowLastError(); - SS_RETURN; + RETURN length + 1; } -//----------------------------------------------------------------------------- -// Set this string to a copy of the first count characters of the given -// UTF8 string. -//----------------------------------------------------------------------------- -void SString::SetUTF8(const UTF8 *string, COUNT_T count) +template<> +COUNT_T SString::ConvertToUnicode(SString& s) const { - SS_CONTRACT_VOID + CONTRACT(COUNT_T) { - // !!! Check for illegal UTF8 encoding? - INSTANCE_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - PRECONDITION(CheckCount(count)); + PRECONDITION(s.Check()); THROWS; GC_NOTRIGGER; } - SS_CONTRACT_END; - - if (count == 0) - Clear(); - else - { - Resize(count, REPRESENTATION_UTF8); - strncpy_s(GetRawUTF8(), GetBufferSizeInCharIncludeNullChar(), string, count); - GetRawUTF8()[count] = 0; - } + CONTRACT_END; - SS_RETURN; + s.Set(GetRawBuffer()); + RETURN GetCount() + 1; } - //----------------------------------------------------------------------------- -// Set this string to a copy of the given ANSI string +// Convert string to unicode lowercase using the invariant culture +// Note: Please don't use it in PATH as multiple character can map to the same +// lower case symbol //----------------------------------------------------------------------------- -void SString::SetANSI(const ANSI *string) + +template<> +void SString::LowerCase() { SS_CONTRACT_VOID { - INSTANCE_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - THROWS; GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckPointer(RETVAL)); + THROWS; + SUPPORTS_DAC; } SS_CONTRACT_END; - - if (string == NULL || *string == 0) - Clear(); - else + for (WCHAR *pwch = GetRawBuffer(); pwch < GetRawBuffer() + GetCount(); ++pwch) { - Resize((COUNT_T) strlen(string), REPRESENTATION_ANSI); - strcpy_s(GetRawANSI(), GetBufferSizeInCharIncludeNullChar(), string); + *pwch = (CAN_SIMPLE_DOWNCASE(*pwch) ? SIMPLE_DOWNCASE(*pwch) : MapChar(*pwch, LCMAP_LOWERCASE)); } - - SS_RETURN; } - -//----------------------------------------------------------------------------- -// Set this string to a copy of the first count characters of the given -// ANSI string. -//----------------------------------------------------------------------------- -void SString::SetANSI(const ANSI *string, COUNT_T count) +template<> +void EString::LowerCase() { SS_CONTRACT_VOID { - INSTANCE_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - PRECONDITION(CheckCount(count)); - THROWS; GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckPointer(RETVAL)); + THROWS; + SUPPORTS_DAC; } SS_CONTRACT_END; - if (count == 0) - Clear(); - else - { - Resize(count, REPRESENTATION_ANSI); - strncpy_s(GetRawANSI(), GetBufferSizeInCharIncludeNullChar(), string, count); - GetRawANSI()[count] = 0; - } + StackSString buffer; + ConvertToUnicode(buffer); - SS_RETURN; + buffer.LowerCase(); + buffer.ConvertToUTF8(*this); } -//----------------------------------------------------------------------------- -// Set this string to the given unicode character -//----------------------------------------------------------------------------- -void SString::Set(WCHAR character) +template<> +void EString::LowerCase() { SS_CONTRACT_VOID { - INSTANCE_CHECK; - THROWS; GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckPointer(RETVAL)); + THROWS; + SUPPORTS_DAC; } SS_CONTRACT_END; - if (character == 0) - Clear(); - else + StackSString buffer; + ConvertToUnicode(buffer); + + for (CHAR *pwch = GetRawBuffer(); pwch < GetRawBuffer() + GetCount(); ++pwch) { - Resize(1, REPRESENTATION_UNICODE); - GetRawUnicode()[0] = character; - GetRawUnicode()[1] = 0; + *pwch = (CHAR)tolower(*pwch); } - - SS_RETURN; } //----------------------------------------------------------------------------- -// Set this string to the given UTF8 character +// Convert string to unicode uppercase using the invariant culture +// Note: Please don't use it in PATH as multiple character can map to the same +// upper case symbol //----------------------------------------------------------------------------- -void SString::SetUTF8(CHAR character) + + +template<> +void SString::UpperCase() { SS_CONTRACT_VOID { - INSTANCE_CHECK; - THROWS; GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckPointer(RETVAL)); + THROWS; + SUPPORTS_DAC; } SS_CONTRACT_END; - - if (character == 0) - Clear(); - else + for (WCHAR *pwch = GetRawBuffer(); pwch < GetRawBuffer() + GetCount(); ++pwch) { - Resize(1, REPRESENTATION_UTF8); - GetRawUTF8()[0] = character; - GetRawUTF8()[1] = 0; + *pwch = (CAN_SIMPLE_UPCASE(*pwch) ? SIMPLE_UPCASE(*pwch) : MapChar(*pwch, LCMAP_UPPERCASE)); } - - SS_RETURN; } - - -//----------------------------------------------------------------------------- -// Set this string to the given ansi literal. -// This will share the memory and not make a copy. -//----------------------------------------------------------------------------- -void SString::SetLiteral(const ASCII *literal) +template<> +void EString::UpperCase() { SS_CONTRACT_VOID { - INSTANCE_CHECK; - PRECONDITION(CheckPointer(literal)); - PRECONDITION(CheckASCIIString(literal)); - THROWS; GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckPointer(RETVAL)); + THROWS; + SUPPORTS_DAC; } SS_CONTRACT_END; - SString s(Literal, literal); - Set(s); + StackSString buffer; + ConvertToUnicode(buffer); - SS_RETURN; + buffer.UpperCase(); + buffer.ConvertToUTF8(*this); } -//----------------------------------------------------------------------------- -// Set this string to the given unicode literal. -// This will share the memory and not make a copy. -//----------------------------------------------------------------------------- -void SString::SetLiteral(const WCHAR *literal) +template<> +void EString::UpperCase() { SS_CONTRACT_VOID { - INSTANCE_CHECK; - PRECONDITION(CheckPointer(literal)); - THROWS; GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckPointer(RETVAL)); + THROWS; + SUPPORTS_DAC; } SS_CONTRACT_END; - SString s(Literal, literal); - Set(s); - - SS_RETURN; -} + StackSString buffer; + ConvertToUnicode(buffer); -//----------------------------------------------------------------------------- -// Hash the string contents -//----------------------------------------------------------------------------- -ULONG SString::Hash() const -{ - SS_CONTRACT(ULONG) + for (CHAR *pwch = GetRawBuffer(); pwch < GetRawBuffer() + GetCount(); ++pwch) { - INSTANCE_CHECK; - THROWS_UNLESS_NORMALIZED; - GC_NOTRIGGER; + *pwch = (CHAR)toupper(*pwch); } - SS_CONTRACT_END; - - ConvertToUnicode(); - - SS_RETURN HashString(GetRawUnicode()); } -//----------------------------------------------------------------------------- -// Hash the string contents -//----------------------------------------------------------------------------- -ULONG SString::HashCaseInsensitive() const -{ - SS_CONTRACT(ULONG) - { - INSTANCE_CHECK; - THROWS_UNLESS_NORMALIZED; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - ConvertToIteratable(); +#ifdef DACCESS_COMPILE +//--------------------------------------------------------------------------------------- +// +// Copy the string from the target into the provided buffer, converting to unicode if necessary +// +// Arguments: +// cBufChars - size of pBuffer in count of unicode characters. +// pBuffer - a buffer of cBufChars unicode chars. +// pcNeedChars - space to store the number of unicode chars in the EString. +// +// Returns: +// true if successful - and buffer is filled with the unicode representation of +// the string. +// false if unsuccessful. +// +template<> +bool SString::DacGetUnicode(COUNT_T cBufChars, + _Inout_updates_z_(cBufChars) WCHAR * pBuffer, + COUNT_T * pcNeedChars) const +{ + SUPPORTS_DAC; - ULONG result; + PVOID pContent = NULL; + int iPage = CP_ACP; - switch (GetRepresentation()) + if (IsEmpty()) { - case REPRESENTATION_UNICODE: - case REPRESENTATION_EMPTY: - result = CaseHashHelper(GetRawUnicode(), GetRawCount()); - break; - - case REPRESENTATION_ASCII: - result = CaseHashHelperA(GetRawASCII(), GetRawCount()); - break; - - default: - UNREACHABLE(); + if (pcNeedChars) + { + *pcNeedChars = 1; + } + if (pBuffer && cBufChars) + { + pBuffer[0] = 0; + } + return true; } - SS_RETURN result; -} - -//----------------------------------------------------------------------------- -// Truncate this string to count characters. -//----------------------------------------------------------------------------- -void SString::Truncate(const Iterator &i) -{ - SS_CONTRACT_VOID + HRESULT status = S_OK; + EX_TRY { - INSTANCE_CHECK; - PRECONDITION(CheckIteratorRange(i)); - SS_POSTCONDITION(GetRawCount() == i - Begin()); - THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; + pContent = SBuffer::DacGetRawContent(); } - SS_CONTRACT_END; - - CONSISTENCY_CHECK(IsFixedSize()); - - COUNT_T size = i - Begin(); + EX_CATCH_HRESULT(status); - Resize(size, GetRepresentation(), PRESERVE); + if (SUCCEEDED(status) && pContent != NULL) + { + if (pcNeedChars) + { + *pcNeedChars = GetCount() + 1; + } - i.Resync(this, (BYTE *) (GetRawUnicode() + size)); + if (pBuffer && cBufChars) + { + if (cBufChars > GetCount() + 1) + { + cBufChars = GetCount() + 1; + } + memcpy(pBuffer, pContent, cBufChars * sizeof(*pBuffer)); + pBuffer[cBufChars - 1] = 0; + } - SS_RETURN; -} - -//----------------------------------------------------------------------------- -// Convert the ASCII representation for this String to Unicode. We can do this -// quickly and in-place (if this == &dest), which is why it is optimized. -//----------------------------------------------------------------------------- -void SString::ConvertASCIIToUnicode(SString &dest) const -{ - CONTRACT_VOID - { - PRECONDITION(IsRepresentation(REPRESENTATION_ASCII)); - POSTCONDITION(dest.IsRepresentation(REPRESENTATION_UNICODE)); - THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; - } - CONTRACT_END; - - // Handle the empty case. - if (IsEmpty()) - { - dest.Clear(); - RETURN; - } - - CONSISTENCY_CHECK(CheckPointer(GetRawASCII())); - CONSISTENCY_CHECK(GetRawCount() > 0); - - // If dest is the same as this, then we need to preserve on resize. - dest.Resize(GetRawCount(), REPRESENTATION_UNICODE, - this == &dest ? PRESERVE : DONT_PRESERVE); - - // Make sure the buffer is big enough. - CONSISTENCY_CHECK(dest.GetAllocation() > (GetRawCount() * sizeof(WCHAR))); - - // This is a poor man's widen. Since we know that the representation is ASCII, - // we can just pad the string with a bunch of zero-value bytes. Of course, - // we move from the end of the string to the start so that we can convert in - // place (in the case that &dest == this). - WCHAR *outBuf = dest.GetRawUnicode() + dest.GetRawCount(); - ASCII *inBuf = GetRawASCII() + GetRawCount(); - - while (GetRawASCII() <= inBuf) - { - CONSISTENCY_CHECK(dest.GetRawUnicode() <= outBuf); - // The casting zero-extends the value, thus giving us the zero-valued byte. - *outBuf = (WCHAR) *inBuf; - outBuf--; - inBuf--; - } - - RETURN; -} - -//----------------------------------------------------------------------------- -// Convert the internal representation for this String to Unicode. -//----------------------------------------------------------------------------- -void SString::ConvertToUnicode() const -{ - CONTRACT_VOID - { - POSTCONDITION(IsRepresentation(REPRESENTATION_UNICODE)); - if (IsRepresentation(REPRESENTATION_UNICODE)) NOTHROW; else THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; - } - CONTRACT_END; - - if (!IsRepresentation(REPRESENTATION_UNICODE)) - { - if (IsRepresentation(REPRESENTATION_ASCII)) - { - ConvertASCIIToUnicode(*(const_cast(this))); - } - else - { - StackSString s; - ConvertToUnicode(s); - PREFIX_ASSUME(!s.IsImmutable()); - (const_cast(this))->Set(s); - } - } - - RETURN; -} - -//----------------------------------------------------------------------------- -// Convert the internal representation for this String to Unicode, while -// preserving the iterator if the conversion is done. -//----------------------------------------------------------------------------- -void SString::ConvertToUnicode(const CIterator &i) const -{ - CONTRACT_VOID - { - PRECONDITION(i.Check()); - POSTCONDITION(IsRepresentation(REPRESENTATION_UNICODE)); - if (IsRepresentation(REPRESENTATION_UNICODE)) NOTHROW; else THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; - } - CONTRACT_END; - - if (!IsRepresentation(REPRESENTATION_UNICODE)) - { - CONSISTENCY_CHECK(IsFixedSize()); - - COUNT_T index = 0; - // Get the current index of the iterator - if (i.m_ptr != NULL) - { - CONSISTENCY_CHECK(GetCharacterSizeShift() == 0); - index = (COUNT_T) (i.m_ptr - m_buffer); - } - - if (IsRepresentation(REPRESENTATION_ASCII)) - { - ConvertASCIIToUnicode(*(const_cast(this))); - } - else - { - StackSString s; - ConvertToUnicode(s); - (const_cast(this))->Set(s); - } - - // Move the iterator to the new location. - if (i.m_ptr != NULL) - { - i.Resync(this, (BYTE *) (GetRawUnicode() + index)); - } - } - - RETURN; -} - -//----------------------------------------------------------------------------- -// Set s to be a copy of this string's contents, but in the unicode format. -//----------------------------------------------------------------------------- -void SString::ConvertToUnicode(SString &s) const -{ - CONTRACT_VOID - { - PRECONDITION(s.Check()); - POSTCONDITION(s.IsRepresentation(REPRESENTATION_UNICODE)); - THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; - } - CONTRACT_END; - - int page = 0; - - switch (GetRepresentation()) - { - case REPRESENTATION_EMPTY: - s.Clear(); - RETURN; - - case REPRESENTATION_UNICODE: - s.Set(*this); - RETURN; - - case REPRESENTATION_UTF8: - page = CP_UTF8; - break; - - case REPRESENTATION_ASCII: - ConvertASCIIToUnicode(s); - RETURN; - - case REPRESENTATION_ANSI: - page = CP_ACP; - break; - - default: - UNREACHABLE(); - } - - COUNT_T length = WszMultiByteToWideChar(page, 0, GetRawANSI(), GetRawCount()+1, 0, 0); - if (length == 0) - ThrowLastError(); - - s.Resize(length-1, REPRESENTATION_UNICODE); - - length = WszMultiByteToWideChar(page, 0, GetRawANSI(), GetRawCount()+1, s.GetRawUnicode(), length); - if (length == 0) - ThrowLastError(); - - RETURN; -} - -//----------------------------------------------------------------------------- -// Set s to be a copy of this string's contents, but in the ANSI format. -//----------------------------------------------------------------------------- -void SString::ConvertToANSI(SString &s) const -{ - CONTRACT_VOID - { - PRECONDITION(s.Check()); - POSTCONDITION(s.IsRepresentation(REPRESENTATION_ANSI)); - THROWS; - GC_NOTRIGGER; - } - CONTRACT_END; - - switch (GetRepresentation()) - { - case REPRESENTATION_EMPTY: - s.Clear(); - RETURN; - - case REPRESENTATION_ASCII: - case REPRESENTATION_ANSI: - s.Set(*this); - RETURN; - - case REPRESENTATION_UTF8: - // No direct conversion to ANSI - ConvertToUnicode(); - FALLTHROUGH; - - case REPRESENTATION_UNICODE: - break; - - default: - UNREACHABLE(); - } - - // @todo: use WC_NO_BEST_FIT_CHARS - COUNT_T length = WszWideCharToMultiByte(CP_ACP, 0, GetRawUnicode(), GetRawCount()+1, - NULL, 0, NULL, NULL); - - s.Resize(length-1, REPRESENTATION_ANSI); - - // @todo: use WC_NO_BEST_FIT_CHARS - length = WszWideCharToMultiByte(CP_ACP, 0, GetRawUnicode(), GetRawCount()+1, - s.GetRawANSI(), length, NULL, NULL); - if (length == 0) - ThrowLastError(); - - RETURN; -} - -//----------------------------------------------------------------------------- -// Set s to be a copy of this string's contents, but in the utf8 format. -//----------------------------------------------------------------------------- -COUNT_T SString::ConvertToUTF8(SString &s) const -{ - CONTRACT(COUNT_T) - { - PRECONDITION(s.Check()); - POSTCONDITION(s.IsRepresentation(REPRESENTATION_UTF8)); - THROWS; - GC_NOTRIGGER; - } - CONTRACT_END; - - switch (GetRepresentation()) - { - case REPRESENTATION_EMPTY: - s.Clear(); - RETURN 1; - - case REPRESENTATION_ASCII: - case REPRESENTATION_UTF8: - s.Set(*this); - RETURN s.GetRawCount()+1; - - case REPRESENTATION_ANSI: - // No direct conversion from ANSI to UTF8 - ConvertToUnicode(); - FALLTHROUGH; - - case REPRESENTATION_UNICODE: - break; - - default: - UNREACHABLE(); - } - - // @todo: use WC_NO_BEST_FIT_CHARS - bool allAscii; - DWORD length; - - HRESULT hr = FString::Unicode_Utf8_Length(GetRawUnicode(), & allAscii, & length); - - if (SUCCEEDED(hr)) - { - s.Resize(length, REPRESENTATION_UTF8); - - //FString::Unicode_Utf8 expects an array all the time - //we optimize the empty string by replacing it with null for SString above in Resize - if (length > 0) - { - hr = FString::Unicode_Utf8(GetRawUnicode(), allAscii, (LPSTR) s.GetRawUTF8(), length); - } - } - - IfFailThrow(hr); - - RETURN length + 1; -} - -//----------------------------------------------------------------------------- -// Replace a single character with another character. -//----------------------------------------------------------------------------- -void SString::Replace(const Iterator &i, WCHAR c) -{ - CONTRACT_VOID - { - INSTANCE_CHECK; - PRECONDITION(CheckIteratorRange(i, 1)); - POSTCONDITION(Match(i, c)); - THROWS; - GC_NOTRIGGER; - } - CONTRACT_END; - - if (IsRepresentation(REPRESENTATION_ASCII) && ((c&~0x7f) == 0)) - { - *(BYTE*)i.m_ptr = (BYTE) c; - } - else - { - ConvertToUnicode(i); - - *(USHORT*)i.m_ptr = c; - } - - RETURN; -} - -//----------------------------------------------------------------------------- -// Replace the substring specified by position, length with the given string s. -//----------------------------------------------------------------------------- -void SString::Replace(const Iterator &i, COUNT_T length, const SString &s) -{ - CONTRACT_VOID - { - INSTANCE_CHECK; - PRECONDITION(CheckIteratorRange(i, length)); - PRECONDITION(s.Check()); - POSTCONDITION(Match(i, s)); - THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; - } - CONTRACT_END; - - Representation representation = GetRepresentation(); - if (representation == REPRESENTATION_EMPTY) - { - // This special case contains some optimizations (like literal sharing). - Set(s); - ConvertToIteratable(); - i.Resync(this, m_buffer); - } - else - { - StackSString temp; - const SString &source = GetCompatibleString(s, temp, i); - - COUNT_T deleteSize = length< i.GetUnicode()) - start = i.GetUnicode(); - const WCHAR *end = GetRawUnicode(); - - while (start >= end) - { - if (wcsncmp(start, source.GetRawUnicode(), count) == 0) - { - i.Resync(this, (BYTE*) start); - RETURN TRUE; - } - start--; - } - } - break; - - case REPRESENTATION_ANSI: - case REPRESENTATION_ASCII: - { - COUNT_T count = source.GetRawCount(); - const CHAR *start = GetRawASCII() + GetRawCount() - count; - if (start > i.GetASCII()) - start = i.GetASCII(); - const CHAR *end = GetRawASCII(); - - while (start >= end) - { - if (strncmp(start, source.GetRawASCII(), count) == 0) - { - i.Resync(this, (BYTE*) start); - RETURN TRUE; - } - start--; - } - } - break; - - case REPRESENTATION_EMPTY: - { - if (source.GetRawCount() == 0) - RETURN TRUE; - } - break; - - case REPRESENTATION_UTF8: - default: - UNREACHABLE(); - } - - RETURN FALSE; -} - -//----------------------------------------------------------------------------- -// Find s in this string, working backwards staring at i. -// Return TRUE and update iterator if found. -//----------------------------------------------------------------------------- -BOOL SString::FindBack(CIterator &i, WCHAR c) const -{ - CONTRACT(BOOL) - { - INSTANCE_CHECK; - PRECONDITION(CheckIteratorRange(i)); - POSTCONDITION(RETVAL == Match(i, c)); - THROWS_UNLESS_NORMALIZED; - GC_NOTRIGGER; - } - CONTRACT_END; - - // Get a compatible string from s - if (c & ~0x7f) - ConvertToUnicode(i); - - switch (GetRepresentation()) - { - case REPRESENTATION_UNICODE: - { - const WCHAR *start = GetRawUnicode() + GetRawCount() - 1; - if (start > i.GetUnicode()) - start = i.GetUnicode(); - const WCHAR *end = GetRawUnicode(); - - while (start >= end) - { - if (*start == c) - { - i.Resync(this, (BYTE*) start); - RETURN TRUE; - } - start--; - } - } - break; - - case REPRESENTATION_ANSI: - case REPRESENTATION_ASCII: - { - const CHAR *start = GetRawASCII() + GetRawCount() - 1; - if (start > i.GetASCII()) - start = i.GetASCII(); - const CHAR *end = GetRawASCII(); - - while (start >= end) - { - if (*start == c) - { - i.Resync(this, (BYTE*) start); - RETURN TRUE; - } - start--; - } - } - break; - - case REPRESENTATION_EMPTY: - break; - - case REPRESENTATION_UTF8: - default: - UNREACHABLE(); - } - - RETURN FALSE; -} - -//----------------------------------------------------------------------------- -// Returns TRUE if this string begins with the contents of s -//----------------------------------------------------------------------------- -BOOL SString::BeginsWith(const SString &s) const -{ - WRAPPER_NO_CONTRACT; - - return Match(Begin(), s); -} - -//----------------------------------------------------------------------------- -// Returns TRUE if this string begins with the contents of s -//----------------------------------------------------------------------------- -BOOL SString::BeginsWithCaseInsensitive(const SString &s) const -{ - WRAPPER_NO_CONTRACT; - - return MatchCaseInsensitive(Begin(), s); -} - -//----------------------------------------------------------------------------- -// Returns TRUE if this string ends with the contents of s -//----------------------------------------------------------------------------- -BOOL SString::EndsWith(const SString &s) const -{ - WRAPPER_NO_CONTRACT; - - // Need this check due to iterator arithmetic below. - if (GetCount() < s.GetCount()) - { - return FALSE; - } - - return Match(End() - s.GetCount(), s); -} - -//----------------------------------------------------------------------------- -// Returns TRUE if this string ends with the contents of s -//----------------------------------------------------------------------------- -BOOL SString::EndsWithCaseInsensitive(const SString &s) const -{ - WRAPPER_NO_CONTRACT; - - // Need this check due to iterator arithmetic below. - if (GetCount() < s.GetCount()) - { - return FALSE; - } - - return MatchCaseInsensitive(End() - s.GetCount(), s); -} - -//----------------------------------------------------------------------------- -// Compare this string's contents to s's contents. -// The comparison does not take into account localization issues like case folding. -// Return 0 if equal, <0 if this < s, >0 is this > s. (same as strcmp). -//----------------------------------------------------------------------------- -int SString::Compare(const SString &s) const -{ - CONTRACT(int) - { - INSTANCE_CHECK; - PRECONDITION(s.Check()); - THROWS_UNLESS_BOTH_NORMALIZED(s); - GC_NOTRIGGER; - } - CONTRACT_END; - - StackSString temp; - const SString &source = GetCompatibleString(s, temp); - - COUNT_T smaller; - int equals = 0; - int result = 0; - - if (GetRawCount() < source.GetRawCount()) - { - smaller = GetRawCount(); - equals = -1; - } - else if (GetRawCount() > source.GetRawCount()) - { - smaller = source.GetRawCount(); - equals = 1; - } - else - { - smaller = GetRawCount(); - equals = 0; - } - - switch (GetRepresentation()) - { - case REPRESENTATION_UNICODE: - result = wcsncmp(GetRawUnicode(), source.GetRawUnicode(), smaller); - break; - - case REPRESENTATION_ASCII: - case REPRESENTATION_ANSI: - result = strncmp(GetRawASCII(), source.GetRawASCII(), smaller); - break; - - case REPRESENTATION_EMPTY: - result = 0; - break; - - default: - case REPRESENTATION_UTF8: - UNREACHABLE(); - } - - if (result == 0) - RETURN equals; - else - RETURN result; -} - -//----------------------------------------------------------------------------- -// Compare this string's contents to s's contents. -// Return 0 if equal, <0 if this < s, >0 is this > s. (same as strcmp). -//----------------------------------------------------------------------------- - -int SString::CompareCaseInsensitive(const SString &s) const -{ - CONTRACT(int) - { - INSTANCE_CHECK; - PRECONDITION(s.Check()); - THROWS_UNLESS_BOTH_NORMALIZED(s); - GC_NOTRIGGER; - } - CONTRACT_END; - - StackSString temp; - const SString &source = GetCompatibleString(s, temp); - - COUNT_T smaller; - int equals = 0; - int result = 0; - - if (GetRawCount() < source.GetRawCount()) - { - smaller = GetRawCount(); - equals = -1; - } - else if (GetRawCount() > source.GetRawCount()) - { - smaller = source.GetRawCount(); - equals = 1; - } - else - { - smaller = GetRawCount(); - equals = 0; - } - - switch (GetRepresentation()) - { - case REPRESENTATION_UNICODE: - case REPRESENTATION_ANSI: - result = CaseCompareHelper(GetRawUnicode(), source.GetRawUnicode(), smaller, FALSE, TRUE); - break; - - case REPRESENTATION_ASCII: - result = CaseCompareHelperA(GetRawASCII(), source.GetRawASCII(), smaller, FALSE, TRUE); - break; - - case REPRESENTATION_EMPTY: - result = 0; - break; - - default: - case REPRESENTATION_UTF8: - UNREACHABLE(); - } - - if (result == 0) - RETURN equals; - else - RETURN result; -} - -//----------------------------------------------------------------------------- -// Compare this string's contents to s's contents. -// The comparison does not take into account localization issues like case folding. -// Return 1 if equal, 0 if not. -//----------------------------------------------------------------------------- -BOOL SString::Equals(const SString &s) const -{ - CONTRACT(BOOL) - { - INSTANCE_CHECK; - PRECONDITION(s.Check()); - THROWS_UNLESS_BOTH_NORMALIZED(s); - FAULTS_UNLESS_BOTH_NORMALIZED(s, ThrowOutOfMemory()); - GC_NOTRIGGER; - } - CONTRACT_END; - - StackSString temp; - const SString &source = GetCompatibleString(s, temp); - - COUNT_T count = GetRawCount(); - - if (count != source.GetRawCount()) - RETURN FALSE; - - switch (GetRepresentation()) - { - case REPRESENTATION_UNICODE: - RETURN (wcsncmp(GetRawUnicode(), source.GetRawUnicode(), count) == 0); - - case REPRESENTATION_ASCII: - case REPRESENTATION_ANSI: - RETURN (strncmp(GetRawASCII(), source.GetRawASCII(), count) == 0); - - case REPRESENTATION_EMPTY: - RETURN TRUE; - - default: - case REPRESENTATION_UTF8: - UNREACHABLE(); - } - - RETURN FALSE; -} - -//----------------------------------------------------------------------------- -// Compare this string's contents case insensitively to s's contents. -// Return 1 if equal, 0 if not. -//----------------------------------------------------------------------------- -BOOL SString::EqualsCaseInsensitive(const SString &s) const -{ - CONTRACT(BOOL) - { - INSTANCE_CHECK; - PRECONDITION(s.Check()); - THROWS_UNLESS_BOTH_NORMALIZED(s); - FAULTS_UNLESS_BOTH_NORMALIZED(s, ThrowOutOfMemory()); - GC_NOTRIGGER; - } - CONTRACT_END; - - StackSString temp; - const SString &source = GetCompatibleString(s, temp); - - COUNT_T count = GetRawCount(); - - if (count != source.GetRawCount()) - RETURN FALSE; - - switch (GetRepresentation()) - { - case REPRESENTATION_UNICODE: - case REPRESENTATION_ANSI: - RETURN (CaseCompareHelper(GetRawUnicode(), source.GetRawUnicode(), count, FALSE, TRUE) == 0); - - case REPRESENTATION_ASCII: - RETURN (CaseCompareHelperA(GetRawASCII(), source.GetRawASCII(), count, FALSE, TRUE) == 0); - - case REPRESENTATION_EMPTY: - RETURN TRUE; - - default: - case REPRESENTATION_UTF8: - UNREACHABLE(); - } - - RETURN FALSE; -} - -//----------------------------------------------------------------------------- -// Compare s's contents to the substring starting at position -// The comparison does not take into account localization issues like case folding. -// Return TRUE if equal, FALSE if not -//----------------------------------------------------------------------------- -BOOL SString::Match(const CIterator &i, const SString &s) const -{ - CONTRACT(BOOL) - { - INSTANCE_CHECK; - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(s.Check()); - THROWS_UNLESS_BOTH_NORMALIZED(s); - GC_NOTRIGGER; - } - CONTRACT_END; - - StackSString temp; - const SString &source = GetCompatibleString(s, temp, i); - - COUNT_T remaining = End() - i; - COUNT_T count = source.GetRawCount(); - - if (remaining < count) - RETURN FALSE; - - switch (GetRepresentation()) - { - case REPRESENTATION_UNICODE: - RETURN (wcsncmp(i.GetUnicode(), source.GetRawUnicode(), count) == 0); - - case REPRESENTATION_ASCII: - case REPRESENTATION_ANSI: - RETURN (strncmp(i.GetASCII(), source.GetRawASCII(), count) == 0); - - case REPRESENTATION_EMPTY: - RETURN TRUE; - - default: - case REPRESENTATION_UTF8: - UNREACHABLE(); - } - - RETURN FALSE; -} - -//----------------------------------------------------------------------------- -// Compare s's contents case insensitively to the substring starting at position -// Return TRUE if equal, FALSE if not -//----------------------------------------------------------------------------- -BOOL SString::MatchCaseInsensitive(const CIterator &i, const SString &s) const -{ - CONTRACT(BOOL) - { - INSTANCE_CHECK; - PRECONDITION(CheckIteratorRange(i)); - PRECONDITION(s.Check()); - THROWS_UNLESS_BOTH_NORMALIZED(s); - GC_NOTRIGGER; - } - CONTRACT_END; - - StackSString temp; - const SString &source = GetCompatibleString(s, temp, i); - - COUNT_T remaining = End() - i; - COUNT_T count = source.GetRawCount(); - - if (remaining < count) - RETURN FALSE; - - switch (GetRepresentation()) - { - case REPRESENTATION_UNICODE: - case REPRESENTATION_ANSI: - RETURN (CaseCompareHelper(i.GetUnicode(), source.GetRawUnicode(), count, FALSE, TRUE) == 0); - - case REPRESENTATION_ASCII: - RETURN (CaseCompareHelperA(i.GetASCII(), source.GetRawASCII(), count, FALSE, TRUE) == 0); - - case REPRESENTATION_EMPTY: - RETURN TRUE; - - default: - case REPRESENTATION_UTF8: - UNREACHABLE(); - } - - RETURN FALSE; -} - -//----------------------------------------------------------------------------- -// Compare c case insensitively to the character at position -// Return TRUE if equal, FALSE if not -//----------------------------------------------------------------------------- -BOOL SString::MatchCaseInsensitive(const CIterator &i, WCHAR c) const -{ - SS_CONTRACT(BOOL) - { - GC_NOTRIGGER; - INSTANCE_CHECK; - PRECONDITION(CheckIteratorRange(i)); - NOTHROW; - } - SS_CONTRACT_END; - - // End() will not throw here - CONTRACT_VIOLATION(ThrowsViolation); - if (i >= End()) - SS_RETURN FALSE; - - WCHAR test = i[0]; - - SS_RETURN (test == c - || ((CAN_SIMPLE_UPCASE(test) ? SIMPLE_UPCASE(test) : MapChar(test, LCMAP_UPPERCASE)) - == (CAN_SIMPLE_UPCASE(c) ? SIMPLE_UPCASE(c) : MapChar(c, LCMAP_UPPERCASE)))); -} - -//----------------------------------------------------------------------------- -// Convert string to unicode lowercase using the invariant culture -// Note: Please don't use it in PATH as multiple character can map to the same -// lower case symbol -//----------------------------------------------------------------------------- -void SString::LowerCase() -{ - SS_CONTRACT_VOID - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(CheckPointer(RETVAL)); - if (IsRepresentation(REPRESENTATION_UNICODE)) NOTHROW; else THROWS; - SUPPORTS_DAC; - } - SS_CONTRACT_END; - - ConvertToUnicode(); - - for (WCHAR *pwch = GetRawUnicode(); pwch < GetRawUnicode() + GetRawCount(); ++pwch) - { - *pwch = (CAN_SIMPLE_DOWNCASE(*pwch) ? SIMPLE_DOWNCASE(*pwch) : MapChar(*pwch, LCMAP_LOWERCASE)); - } -} - -//----------------------------------------------------------------------------- -// Convert null-terminated string to lowercase using the invariant culture -//----------------------------------------------------------------------------- -//static -void SString::LowerCase(__inout_z LPWSTR wszString) -{ - SS_CONTRACT_VOID - { - GC_NOTRIGGER; - NOTHROW; - SUPPORTS_DAC; - } - SS_CONTRACT_END; - - if (wszString == NULL) - { - return; - } - - for (WCHAR * pwch = wszString; *pwch != '\0'; ++pwch) - { - *pwch = (CAN_SIMPLE_DOWNCASE(*pwch) ? SIMPLE_DOWNCASE(*pwch) : MapChar(*pwch, LCMAP_LOWERCASE)); - } -} - -//----------------------------------------------------------------------------- -// Convert string to unicode uppercase using the invariant culture -// Note: Please don't use it in PATH as multiple character can map to the same -// upper case symbol -//----------------------------------------------------------------------------- -void SString::UpperCase() -{ - SS_CONTRACT_VOID - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(CheckPointer(RETVAL)); - if (IsRepresentation(REPRESENTATION_UNICODE)) NOTHROW; else THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC; - } - SS_CONTRACT_END; - - ConvertToUnicode(); - - for (WCHAR *pwch = GetRawUnicode(); pwch < GetRawUnicode() + GetRawCount(); ++pwch) - { - *pwch = (CAN_SIMPLE_UPCASE(*pwch) ? SIMPLE_UPCASE(*pwch) : MapChar(*pwch, LCMAP_UPPERCASE)); - } -} - -//----------------------------------------------------------------------------- -// Get a const pointer to the internal buffer as an ANSI string. -//----------------------------------------------------------------------------- -const CHAR *SString::GetANSI(AbstractScratchBuffer &scratch) const -{ - SS_CONTRACT(const CHAR *) - { - INSTANCE_CHECK_NULL; - THROWS; - GC_NOTRIGGER; - } - SS_CONTRACT_END; - - if (IsRepresentation(REPRESENTATION_ANSI)) - SS_RETURN GetRawANSI(); - - ConvertToANSI((SString&)scratch); - SS_RETURN ((SString&)scratch).GetRawANSI(); -} - -//----------------------------------------------------------------------------- -// Get a const pointer to the internal buffer as a UTF8 string. -//----------------------------------------------------------------------------- -const UTF8 *SString::GetUTF8(AbstractScratchBuffer &scratch) const -{ - CONTRACT(const UTF8 *) - { - INSTANCE_CHECK_NULL; - THROWS; - GC_NOTRIGGER; - } - CONTRACT_END; - - if (IsRepresentation(REPRESENTATION_UTF8)) - RETURN GetRawUTF8(); - - ConvertToUTF8((SString&)scratch); - RETURN ((SString&)scratch).GetRawUTF8(); -} - -const UTF8 *SString::GetUTF8(AbstractScratchBuffer &scratch, COUNT_T *pcbUtf8) const -{ - CONTRACT(const UTF8 *) - { - INSTANCE_CHECK_NULL; - THROWS; - GC_NOTRIGGER; - } - CONTRACT_END; - - if (IsRepresentation(REPRESENTATION_UTF8)) - { - *pcbUtf8 = GetRawCount() + 1; - RETURN GetRawUTF8(); - } - - *pcbUtf8 = ConvertToUTF8((SString&)scratch); - RETURN ((SString&)scratch).GetRawUTF8(); -} - -//----------------------------------------------------------------------------- -// Get a const pointer to the internal buffer which must already be a UTF8 string. -// This avoids the need to create a scratch buffer we know will never be used. -//----------------------------------------------------------------------------- -const UTF8 *SString::GetUTF8NoConvert() const -{ - CONTRACT(const UTF8 *) - { - INSTANCE_CHECK_NULL; - THROWS; - GC_NOTRIGGER; - } - CONTRACT_END; - - if (IsRepresentation(REPRESENTATION_UTF8)) - RETURN GetRawUTF8(); - - ThrowHR(E_INVALIDARG); -} - -//----------------------------------------------------------------------------- -// Safe version of sprintf. -// Prints formatted ansi text w/ var args to this buffer. -//----------------------------------------------------------------------------- -void SString::Printf(const CHAR *format, ...) -{ - WRAPPER_NO_CONTRACT; - - va_list args; - va_start(args, format); - VPrintf(format, args); - va_end(args); -} - -#ifdef _DEBUG -// -// Check the Printf use for potential globalization bugs. %S formatting -// specifier does Unicode->Ansi or Ansi->Unicode conversion using current -// C-locale. This almost always means globalization bug in the CLR codebase. -// -// Ideally, we would elimitate %S from all format strings. Unfortunately, -// %S is too widespread in non-shipping code that such cleanup is not feasible. -// -static void CheckForFormatStringGlobalizationIssues(const SString &format, const SString &result) -{ - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - DEBUG_ONLY; - } - CONTRACTL_END; - - BOOL fDangerousFormat = FALSE; - - // Check whether the format string contains the %S formatting specifier - SString::CIterator itrFormat = format.Begin(); - while (*itrFormat) - { - if (*itrFormat++ == '%') - { - // Handle the complex format strings like %blahS - if (*itrFormat++ == 'S') - { - fDangerousFormat = TRUE; - break; - } - } - } - - if (fDangerousFormat) - { - BOOL fNonAsciiUsed = FALSE; - - // Now check whether there are any non-ASCII characters in the output. - - // Check whether the result contains non-Ascii characters - SString::CIterator itrResult = format.Begin(); - while (*itrResult) - { - if (*itrResult++ > 127) - { - fNonAsciiUsed = TRUE; - break; - } - } - - CONSISTENCY_CHECK_MSGF(!fNonAsciiUsed, - ("Non-ASCII string was produced by %%S format specifier. This is likely globalization bug." - "To fix this, change the format string to %%s and do the correct encoding at the Printf callsite")); - } -} -#endif - -#ifndef EBADF -#define EBADF 9 -#endif - -#ifndef ENOMEM -#define ENOMEM 12 -#endif - -#ifndef ERANGE -#define ERANGE 34 -#endif - -#if defined(_MSC_VER) -#undef va_copy -#define va_copy(dest,src) (dest = src) -#endif - -void SString::VPrintf(const CHAR *format, va_list args) -{ - CONTRACT_VOID - { - INSTANCE_CHECK; - PRECONDITION(CheckPointer(format)); - THROWS; - GC_NOTRIGGER; - } - CONTRACT_END; - - va_list ap; - // sprintf gives us no means to know how many characters are written - // other than guessing and trying - - if (GetRawCount() > 0) - { - // First, try to use the existing buffer - va_copy(ap, args); - int result = _vsnprintf_s(GetRawANSI(), GetRawCount()+1, _TRUNCATE, format, ap); - va_end(ap); - - if (result >=0) - { - // Succeeded in writing. Now resize - - Resize(result, REPRESENTATION_ANSI, PRESERVE); - SString sss(Ansi, format); - INDEBUG(CheckForFormatStringGlobalizationIssues(sss, *this)); - RETURN; - } - } - - // Make a guess how long the result will be (note this will be doubled) - - COUNT_T guess = (COUNT_T) strlen(format)+1; - if (guess < GetRawCount()) - guess = GetRawCount(); - if (guess < MINIMUM_GUESS) - guess = MINIMUM_GUESS; - - while (TRUE) - { - // Double the previous guess - eventually we will get enough space - guess *= 2; - Resize(guess, REPRESENTATION_ANSI); - - // Clear errno to avoid false alarms - errno = 0; - - va_copy(ap, args); - int result = _vsnprintf_s(GetRawANSI(), GetRawCount()+1, _TRUNCATE, format, ap); - va_end(ap); - - if (result >= 0) - { - // Succeed in writing. Shrink the buffer to fit exactly. - Resize(result, REPRESENTATION_ANSI, PRESERVE); - SString sss(Ansi, format); - INDEBUG(CheckForFormatStringGlobalizationIssues(sss, *this)); - RETURN; - } - - if (errno==ENOMEM) - { - ThrowOutOfMemory(); - } - else - if (errno!=0 && errno!=EBADF && errno!=ERANGE) - { - CONSISTENCY_CHECK_MSG(FALSE, "_vsnprintf_s failed. Potential globalization bug."); - ThrowHR(HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION)); - } - } - RETURN; -} - -void SString::Printf(const WCHAR *format, ...) -{ - CONTRACT_VOID - { - INSTANCE_CHECK; - PRECONDITION(CheckPointer(format)); - THROWS; - GC_NOTRIGGER; - } - CONTRACT_END; - - // sprintf gives us no means to know how many characters are written - // other than guessing and trying - - if (GetRawCount() > 0) - { - // First, try to use the existing buffer - va_list args; - va_start(args, format); - int result = _vsnwprintf_s(GetRawUnicode(), GetRawCount()+1, _TRUNCATE, format, args); - va_end(args); - - if (result >= 0) - { - // succeeded - Resize(result, REPRESENTATION_UNICODE, PRESERVE); - SString sss(format); - INDEBUG(CheckForFormatStringGlobalizationIssues(sss, *this)); - RETURN; - } - } - - // Make a guess how long the result will be (note this will be doubled) - - COUNT_T guess = (COUNT_T) wcslen(format)+1; - if (guess < GetRawCount()) - guess = GetRawCount(); - if (guess < MINIMUM_GUESS) - guess = MINIMUM_GUESS; - - while (TRUE) - { - // Double the previous guess - eventually we will get enough space - guess *= 2; - Resize(guess, REPRESENTATION_UNICODE); - - // Clear errno to avoid false alarms - errno = 0; - - va_list args; - va_start(args, format); - int result = _vsnwprintf_s(GetRawUnicode(), GetRawCount()+1, _TRUNCATE, format, args); - va_end(args); - - if (result >= 0) - { - Resize(result, REPRESENTATION_UNICODE, PRESERVE); - SString sss(format); - INDEBUG(CheckForFormatStringGlobalizationIssues(sss, *this)); - RETURN; - } - - if (errno==ENOMEM) - { - ThrowOutOfMemory(); - } - else - if (errno!=0 && errno!=EBADF && errno!=ERANGE) - { - CONSISTENCY_CHECK_MSG(FALSE, "_vsnwprintf_s failed. Potential globalization bug."); - ThrowHR(HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION)); - } - } - RETURN; -} - -void SString::AppendPrintf(const CHAR *format, ...) -{ - WRAPPER_NO_CONTRACT; - - va_list args; - va_start(args, format); - AppendVPrintf(format, args); - va_end(args); -} - -void SString::AppendVPrintf(const CHAR *format, va_list args) -{ - WRAPPER_NO_CONTRACT; - - StackSString s; - s.VPrintf(format, args); - Append(s); -} - -//---------------------------------------------------------------------------- -// LoadResource - moved to sstring_com.cpp -//---------------------------------------------------------------------------- - -//---------------------------------------------------------------------------- -// Format the message and put the contents in this string -//---------------------------------------------------------------------------- - -BOOL SString::FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, - const SString &arg1, const SString &arg2, - const SString &arg3, const SString &arg4, - const SString &arg5, const SString &arg6, - const SString &arg7, const SString &arg8, - const SString &arg9, const SString &arg10) -{ - CONTRACT(BOOL) - { - INSTANCE_CHECK; - THROWS; - GC_NOTRIGGER; - } - CONTRACT_END; - - const WCHAR *args[] = {arg1.GetUnicode(), arg2.GetUnicode(), arg3.GetUnicode(), arg4.GetUnicode(), - arg5.GetUnicode(), arg6.GetUnicode(), arg7.GetUnicode(), arg8.GetUnicode(), - arg9.GetUnicode(), arg10.GetUnicode()}; - - if (GetRawCount() > 0) - { - // First, try to use our existing buffer to hold the result. - Resize(GetRawCount(), REPRESENTATION_UNICODE); - - DWORD result = ::WszFormatMessage(dwFlags | FORMAT_MESSAGE_ARGUMENT_ARRAY, - lpSource, dwMessageId, dwLanguageId, - GetRawUnicode(), GetRawCount()+1, (va_list*)args); - - // Although we cannot directly detect truncation, we can tell if we - // used up all the space (in which case we will assume truncation.) - - if (result != 0 && result < GetRawCount()) - { - if (GetRawUnicode()[result-1] == W(' ')) - { - GetRawUnicode()[result-1] = W('\0'); - result -= 1; - } - Resize(result, REPRESENTATION_UNICODE, PRESERVE); - RETURN TRUE; - } - } - - // We don't have enough space in our buffer, do dynamic allocation. - LocalAllocHolder string; - - DWORD result = ::WszFormatMessage(dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, - lpSource, dwMessageId, dwLanguageId, - (LPWSTR)(LPWSTR*)&string, 0, (va_list*)args); - - if (result == 0) - RETURN FALSE; - else - { - if (string[result-1] == W(' ')) - string[result-1] = W('\0'); - - Set(string); - RETURN TRUE; - } -} - -#if 1 -//---------------------------------------------------------------------------- -// Helper -//---------------------------------------------------------------------------- - -// @todo -this should be removed and placed outside of SString -void SString::MakeFullNamespacePath(const SString &nameSpace, const SString &name) -{ - CONTRACT_VOID - { - INSTANCE_CHECK; - THROWS; - GC_NOTRIGGER; - } - CONTRACT_END; - - if (nameSpace.GetRepresentation() == REPRESENTATION_UTF8 - && name.GetRepresentation() == REPRESENTATION_UTF8) - { - const UTF8 *ns = nameSpace.GetRawUTF8(); - const UTF8 *n = name.GetRawUTF8(); - COUNT_T count = ns::GetFullLength(ns, n)-1; - Resize(count, REPRESENTATION_UTF8); - if (count > 0) - ns::MakePath(GetRawUTF8(), count+1, ns, n); - } - else - { - const WCHAR *ns = nameSpace; - const WCHAR *n = name; - COUNT_T count = ns::GetFullLength(ns, n)-1; - Resize(count, REPRESENTATION_UNICODE); - if (count > 0) - ns::MakePath(GetRawUnicode(), count+1, ns, n); - } - - RETURN; -} -#endif - - - -//---------------------------------------------------------------------------- -// Private helper. -// Check to see if the string fits the suggested representation -//---------------------------------------------------------------------------- -BOOL SString::IsRepresentation(Representation representation) const -{ - CONTRACT(BOOL) - { - PRECONDITION(CheckRepresentation(representation)); - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC; - } - CONTRACT_END; - - Representation currentRepresentation = GetRepresentation(); - - // If representations are the same, cool. - if (currentRepresentation == representation) - RETURN TRUE; - - // If we have an empty representation, we match everything - if (currentRepresentation == REPRESENTATION_EMPTY) - RETURN TRUE; - - // If we're a 1 byte charset, there are some more chances to match - if (currentRepresentation != REPRESENTATION_UNICODE - && representation != REPRESENTATION_UNICODE) - { - // If we're ASCII, we can be any 1 byte rep - if (currentRepresentation == REPRESENTATION_ASCII) - RETURN TRUE; - - // We really want to be ASCII - scan to see if we qualify - if (ScanASCII()) - RETURN TRUE; - } - - // Sorry, must convert. - RETURN FALSE; -} - -//---------------------------------------------------------------------------- -// Private helper. -// Get the contents of the given string in a form which is compatible with our -// string (and is in a fixed character set.) Updates the given iterator -// if necessary to keep it in sync. -//---------------------------------------------------------------------------- -const SString &SString::GetCompatibleString(const SString &s, SString &scratch, const CIterator &i) const -{ - CONTRACTL - { - PRECONDITION(s.Check()); - PRECONDITION(scratch.Check()); - PRECONDITION(scratch.CheckEmpty()); - THROWS_UNLESS_BOTH_NORMALIZED(s); - GC_NOTRIGGER; - SUPPORTS_DAC; - } - CONTRACTL_END; - - // Since we have an iterator, we should be fixed size already - CONSISTENCY_CHECK(IsFixedSize()); - - switch (GetRepresentation()) - { - case REPRESENTATION_EMPTY: - return s; - - case REPRESENTATION_ASCII: - if (s.IsRepresentation(REPRESENTATION_ASCII)) - return s; - - // We can't in general convert to ASCII, so try unicode. - ConvertToUnicode(i); - FALLTHROUGH; - - case REPRESENTATION_UNICODE: - if (s.IsRepresentation(REPRESENTATION_UNICODE)) - return s; - - // @todo: we could convert s to unicode - is that a good policy???? - s.ConvertToUnicode(scratch); - return scratch; - - case REPRESENTATION_UTF8: - case REPRESENTATION_ANSI: - // These should all be impossible since we have an CIterator on us. - default: - UNREACHABLE_MSG("Unexpected string representation"); - } - - return s; -} - -//---------------------------------------------------------------------------- -// Private helper. -// Get the contents of the given string in a form which is compatible with our -// string (and is in a fixed character set.) -// May convert our string to unicode. -//---------------------------------------------------------------------------- -const SString &SString::GetCompatibleString(const SString &s, SString &scratch) const -{ - CONTRACTL - { - PRECONDITION(s.Check()); - PRECONDITION(scratch.Check()); - PRECONDITION(scratch.CheckEmpty()); - THROWS_UNLESS_BOTH_NORMALIZED(s); - GC_NOTRIGGER; - } - CONTRACTL_END; - - // First, make sure we have a fixed size. - ConvertToFixed(); - - switch (GetRepresentation()) - { - case REPRESENTATION_EMPTY: - return s; - - case REPRESENTATION_ANSI: - if (s.IsRepresentation(REPRESENTATION_ANSI)) - return s; - - s.ConvertToANSI(scratch); - return scratch; - - case REPRESENTATION_ASCII: - if (s.IsRepresentation(REPRESENTATION_ASCII)) - return s; - - // We can't in general convert to ASCII, so try unicode. - ConvertToUnicode(); - FALLTHROUGH; - - case REPRESENTATION_UNICODE: - if (s.IsRepresentation(REPRESENTATION_UNICODE)) - return s; - - // @todo: we could convert s to unicode in place - is that a good policy???? - s.ConvertToUnicode(scratch); - return scratch; - - case REPRESENTATION_UTF8: - default: - UNREACHABLE(); - } - - return s; -} - -//---------------------------------------------------------------------------- -// Private helper. -// If we have a 1 byte representation, scan the buffer to see if we can gain -// some conversion flexibility by labelling it ASCII -//---------------------------------------------------------------------------- -BOOL SString::ScanASCII() const -{ - CONTRACT(BOOL) - { - POSTCONDITION(IsRepresentation(REPRESENTATION_ASCII) || IsASCIIScanned()); - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC; - } - CONTRACT_END; - - if (!IsASCIIScanned()) - { - const CHAR *c = GetRawANSI(); - const CHAR *cEnd = c + GetRawCount(); - while (c < cEnd) - { - if (*c & 0x80) - break; - c++; - } - if (c == cEnd) - { - const_cast(this)->SetRepresentation(REPRESENTATION_ASCII); - RETURN TRUE; - } - else - const_cast(this)->SetASCIIScanned(); - } - RETURN FALSE; -} - -//---------------------------------------------------------------------------- -// Private helper. -// Resize updates the geometry of the string and ensures that -// the space can be written to. -// count - number of characters (not including null) to hold -// preserve - if we realloc, do we copy data from old to new? -//---------------------------------------------------------------------------- - -void SString::Resize(COUNT_T count, SString::Representation representation, Preserve preserve) -{ - CONTRACT_VOID - { - PRECONDITION(CountToSize(count) >= count); - POSTCONDITION(IsRepresentation(representation)); - POSTCONDITION(GetRawCount() == count); - if (count == 0) NOTHROW; else THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; - } - CONTRACT_END; - - // If we are resizing to zero, Clear is more efficient - if (count == 0) - { - Clear(); - } - else - { - SetRepresentation(representation); - - COUNT_T size = CountToSize(count); - - // detect overflow - if (size < count) - ThrowOutOfMemory(); - - ClearNormalized(); - - SBuffer::Resize(size, preserve); - - if (IsImmutable()) - EnsureMutable(); - - NullTerminate(); - } - - RETURN; -} - -//----------------------------------------------------------------------------- -// This is essentially a specialized version of the above for size 0 -//----------------------------------------------------------------------------- -void SString::Clear() -{ - CONTRACT_VOID - { - INSTANCE_CHECK; - POSTCONDITION(IsEmpty()); - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; - } - CONTRACT_END; - - SetRepresentation(REPRESENTATION_EMPTY); - - if (IsImmutable()) - { - // Use shared empty string rather than allocating a new buffer - SBuffer::SetImmutable(s_EmptyBuffer, sizeof(s_EmptyBuffer)); - } - else - { - // Leave allocated buffer for future growth - SBuffer::TweakSize(sizeof(WCHAR)); - GetRawUnicode()[0] = 0; + return true; } - - RETURN; + return false; } - - -#ifdef DACCESS_COMPILE - //--------------------------------------------------------------------------------------- // -// Return a pointer to the raw buffer -// -// Returns: -// A pointer to the raw string buffer. -// -void * SString::DacGetRawContent() const -{ - if (IsEmpty()) - { - return NULL; - } - - switch (GetRepresentation()) - { - case REPRESENTATION_EMPTY: - return NULL; - - case REPRESENTATION_UNICODE: - case REPRESENTATION_UTF8: - case REPRESENTATION_ASCII: - case REPRESENTATION_ANSI: - // Note: no need to call DacInstantiateString because we know the exact length already. - return SBuffer::DacGetRawContent(); - - default: - DacNotImpl(); - return NULL; - } -} - -//--------------------------------------------------------------------------------------- +// Copy the string from the target into the provided buffer, converting to unicode if necessary // -// Return a pointer to the raw buffer as a pointer to a unicode string. Does not -// do conversion, and thus requires that the representation already be in unicode. +// Arguments: +// cBufChars - size of pBuffer in count of unicode characters. +// pBuffer - a buffer of cBufChars unicode chars. +// pcNeedChars - space to store the number of unicode chars in the EString. // // Returns: -// A pointer to the raw string buffer as a unicode string. +// true if successful - and buffer is filled with the unicode representation of +// the string. +// false if unsuccessful. // -const WCHAR * SString::DacGetRawUnicode() const +template<> +bool EString::DacGetUnicode(COUNT_T cBufChars, + _Inout_updates_z_(cBufChars) WCHAR * pBuffer, + COUNT_T * pcNeedChars) const { - if (IsEmpty() || (GetRepresentation() == REPRESENTATION_EMPTY)) - { - return W(""); - } + SUPPORTS_DAC; + + PVOID pContent = NULL; - if (GetRepresentation() != REPRESENTATION_UNICODE) + if (IsEmpty()) { - DacError(E_UNEXPECTED); + if (pcNeedChars) + { + *pcNeedChars = 1; + } + if (pBuffer && cBufChars) + { + pBuffer[0] = 0; + } + return true; } HRESULT status = S_OK; - WCHAR* wszBuf = NULL; EX_TRY { - wszBuf = static_cast(SBuffer::DacGetRawContent()); + pContent = SBuffer::DacGetRawContent(); } EX_CATCH_HRESULT(status); - if (SUCCEEDED(status)) - { - return wszBuf; - } - else + if (SUCCEEDED(status) && pContent != NULL) { - return NULL; + if (pcNeedChars) + { + *pcNeedChars = WszMultiByteToWideChar(CP_ACP, 0, reinterpret_cast(pContent), -1, NULL, 0); + } + if (pBuffer && cBufChars) + { + if (!WszMultiByteToWideChar(CP_ACP, 0, reinterpret_cast(pContent), -1, pBuffer, cBufChars)) + { + return false; + } + } + return true; } + return false; } - //--------------------------------------------------------------------------------------- // // Copy the string from the target into the provided buffer, converting to unicode if necessary @@ -2571,23 +605,23 @@ const WCHAR * SString::DacGetRawUnicode() const // Arguments: // cBufChars - size of pBuffer in count of unicode characters. // pBuffer - a buffer of cBufChars unicode chars. -// pcNeedChars - space to store the number of unicode chars in the SString. +// pcNeedChars - space to store the number of unicode chars in the EString. // // Returns: // true if successful - and buffer is filled with the unicode representation of // the string. // false if unsuccessful. // -bool SString::DacGetUnicode(COUNT_T cBufChars, +template<> +bool EString::DacGetUnicode(COUNT_T cBufChars, _Inout_updates_z_(cBufChars) WCHAR * pBuffer, COUNT_T * pcNeedChars) const { SUPPORTS_DAC; PVOID pContent = NULL; - int iPage = CP_ACP; - if (IsEmpty() || (GetRepresentation() == REPRESENTATION_EMPTY)) + if (IsEmpty()) { if (pcNeedChars) { @@ -2609,53 +643,98 @@ bool SString::DacGetUnicode(COUNT_T cBufChars, if (SUCCEEDED(status) && pContent != NULL) { - switch (GetRepresentation()) + if (pcNeedChars) { - - case REPRESENTATION_UNICODE: - - if (pcNeedChars) + *pcNeedChars = WszMultiByteToWideChar(CP_UTF8, 0, reinterpret_cast(pContent), -1, NULL, 0); + } + if (pBuffer && cBufChars) + { + if (!WszMultiByteToWideChar(CP_UTF8, 0, reinterpret_cast(pContent), -1, pBuffer, cBufChars)) { - *pcNeedChars = GetCount() + 1; + return false; } + } + return true; + } + return false; +} - if (pBuffer && cBufChars) - { - if (cBufChars > GetCount() + 1) - { - cBufChars = GetCount() + 1; - } - memcpy(pBuffer, pContent, cBufChars * sizeof(*pBuffer)); - pBuffer[cBufChars - 1] = 0; - } +#endif //DACCESS_COMPILE - return true; +// Return a global empty string +template<> +const SString &SString::Empty() +{ +#ifdef SSTRING_EXTRA_CHECKS + CONTRACTL + { + // POSTCONDITION(RETVAL.IsEmpty()); + PRECONDITION(StaticStringHelpers::CheckStartup()); + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACTL_END; +#else + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + STATIC_CONTRACT_SUPPORTS_DAC; +#endif - case REPRESENTATION_UTF8: - iPage = CP_UTF8; - FALLTHROUGH; - case REPRESENTATION_ASCII: - case REPRESENTATION_ANSI: - // iPage defaults to CP_ACP. - if (pcNeedChars) - { - *pcNeedChars = WszMultiByteToWideChar(iPage, 0, reinterpret_cast(pContent), -1, NULL, 0); - } - if (pBuffer && cBufChars) - { - if (!WszMultiByteToWideChar(iPage, 0, reinterpret_cast(pContent), -1, pBuffer, cBufChars)) - { - return false; - } - } - return true; + _ASSERTE(StaticStringHelpers::s_EmptyUnicode != NULL); // Did you call StaticStringHelpers::Startup()? + return *StaticStringHelpers::s_EmptyUnicode; +} - default: - DacNotImpl(); - return false; - } +// Return a global empty string +template<> +const EString &EString::Empty() +{ +#ifdef SSTRING_EXTRA_CHECKS + CONTRACTL + { + // POSTCONDITION(RETVAL.IsEmpty()); + PRECONDITION(StaticStringHelpers::CheckStartup()); + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; } - return false; + CONTRACTL_END; +#else + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + STATIC_CONTRACT_SUPPORTS_DAC; +#endif + + _ASSERTE(StaticStringHelpers::s_EmptyUtf8 != NULL); // Did you call StaticStringHelpers::Startup()? + return *StaticStringHelpers::s_EmptyUtf8; } -#endif //DACCESS_COMPILE +// Return a global empty string +template<> +const EString &EString::Empty() +{ +#ifdef SSTRING_EXTRA_CHECKS + CONTRACTL + { + // POSTCONDITION(RETVAL.IsEmpty()); + PRECONDITION(StaticStringHelpers::CheckStartup()); + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACTL_END; +#else + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + STATIC_CONTRACT_SUPPORTS_DAC; +#endif + + _ASSERTE(StaticStringHelpers::s_EmptyAscii != NULL); // Did you call StaticStringHelpers::Startup()? + return *StaticStringHelpers::s_EmptyAscii; +} diff --git a/src/coreclr/utilcode/sstring_com.cpp b/src/coreclr/utilcode/sstring_com.cpp index 396ec95d73593f..e8264671169d2e 100644 --- a/src/coreclr/utilcode/sstring_com.cpp +++ b/src/coreclr/utilcode/sstring_com.cpp @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- -// SString_COM.cpp +// EString_COM.cpp // --------------------------------------------------------------------------- @@ -15,22 +15,21 @@ //---------------------------------------------------------------------------- // Load the string resource into this string. //---------------------------------------------------------------------------- -BOOL SString::LoadResource(CCompRC::ResourceCategory eCategory, int resourceID) +BOOL LoadResource(EString& buffer, CCompRC::ResourceCategory eCategory, int resourceID) { - return SUCCEEDED(LoadResourceAndReturnHR(eCategory, resourceID)); + return SUCCEEDED(LoadResourceAndReturnHR(buffer, eCategory, resourceID)); } -HRESULT SString::LoadResourceAndReturnHR(CCompRC::ResourceCategory eCategory, int resourceID) +HRESULT LoadResourceAndReturnHR(EString& buffer, CCompRC::ResourceCategory eCategory, int resourceID) { WRAPPER_NO_CONTRACT; - return LoadResourceAndReturnHR(NULL, eCategory,resourceID); + return LoadResourceAndReturnHR(buffer, NULL, eCategory,resourceID); } -HRESULT SString::LoadResourceAndReturnHR(CCompRC* pResourceDLL, CCompRC::ResourceCategory eCategory, int resourceID) +HRESULT LoadResourceAndReturnHR(EString& buffer, CCompRC* pResourceDLL, CCompRC::ResourceCategory eCategory, int resourceID) { CONTRACT(BOOL) { - INSTANCE_CHECK; NOTHROW; } CONTRACT_END; @@ -50,8 +49,8 @@ HRESULT SString::LoadResourceAndReturnHR(CCompRC* pResourceDLL, CCompRC::Resourc EX_TRY { - if (GetRawCount() == 0) - Resize(DEFAULT_RESOURCE_STRING_SIZE, REPRESENTATION_UNICODE); + if (buffer.GetCount() == 0) + buffer.Resize(DEFAULT_RESOURCE_STRING_SIZE, {}); while (TRUE) { @@ -59,35 +58,33 @@ HRESULT SString::LoadResourceAndReturnHR(CCompRC* pResourceDLL, CCompRC::Resourc // In fatal error reporting scenarios, we may not have enough memory to // allocate a larger buffer. - hr = pResourceDLL->LoadString(eCategory, resourceID, GetRawUnicode(), GetRawCount()+1, &size); + hr = pResourceDLL->LoadString(eCategory, resourceID, const_cast((LPCWSTR)buffer), buffer.GetCount()+1, &size); if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { if (FAILED(hr)) { - Clear(); + buffer.Clear(); break; } // Although we cannot generally detect truncation, we can tell if we // used up all the space (in which case we will assume truncation.) - if (size < (int)GetRawCount()) + if (size < (int)buffer.GetCount()) { break; } } // Double the size and try again. - Resize(size*2, REPRESENTATION_UNICODE); + buffer.Resize(size*2, {}); } if (SUCCEEDED(hr)) { - Truncate(Begin() + (COUNT_T) wcslen(GetRawUnicode())); + buffer.Truncate(buffer.Begin() + (COUNT_T) wcslen(buffer.GetRawBuffer())); } - Normalize(); - } EX_CATCH { @@ -98,4 +95,4 @@ HRESULT SString::LoadResourceAndReturnHR(CCompRC* pResourceDLL, CCompRC::Resourc #endif //!FEATURE_UTILCODE_NO_DEPENDENCIES RETURN hr; -} // SString::LoadResourceAndReturnHR +} diff --git a/src/coreclr/utilcode/util.cpp b/src/coreclr/utilcode/util.cpp index 58423a704e970a..cf6c938dc41e4b 100644 --- a/src/coreclr/utilcode/util.cpp +++ b/src/coreclr/utilcode/util.cpp @@ -201,7 +201,7 @@ namespace EX_CATCH_HRESULT(hr); IfFailRet(hr); - wszDllPath = ssDllName.GetUnicode(); + wszDllPath = ssDllName; #else // HOST_WINDOWS return E_FAIL; #endif // HOST_WINDOWS @@ -2969,7 +2969,7 @@ namespace Reg if ((WszRegQueryValueEx(hTargetKey, wszValueName, 0, &type, 0, &size) == ERROR_SUCCESS) && type == REG_SZ && size > 0) { - LPWSTR wszValueBuf = ssValue.OpenUnicodeBuffer(static_cast((size / sizeof(WCHAR)) - 1)); + LPWSTR wszValueBuf = ssValue.OpenBuffer(static_cast((size / sizeof(WCHAR)) - 1)); LONG lResult = WszRegQueryValueEx( hTargetKey, wszValueName, @@ -3018,7 +3018,7 @@ namespace Reg if (SUCCEEDED(hr = ReadStringValue(hKey, wszSubKey, wszName, ssValue))) { *pwszValue = new WCHAR[ssValue.GetCount() + 1]; - wcscpy_s(*pwszValue, ssValue.GetCount() + 1, ssValue.GetUnicode()); + wcscpy_s(*pwszValue, ssValue.GetCount() + 1, ssValue); } } EX_CATCH_HRESULT(hr); @@ -3048,7 +3048,7 @@ namespace Com // Query HKCR first to retain backwards compat with previous implementation where HKCR was only queried. // This is being done due to registry caching. This value will be used if the process integrity is medium or less. - HRESULT hkcrResult = Clr::Util::Reg::ReadStringValue(HKEY_CLASSES_ROOT, ssKeyName.GetUnicode(), nullptr, ssValue); + HRESULT hkcrResult = Clr::Util::Reg::ReadStringValue(HKEY_CLASSES_ROOT, ssKeyName, nullptr, ssValue); // HKCR is a virtualized registry hive that weaves together HKCU\Software\Classes and HKLM\Software\Classes // Processes with high integrity or greater should only read from HKLM to avoid being hijacked by medium @@ -3073,7 +3073,7 @@ namespace Com // Force to use HKLM StackSString ssHklmKeyName(SL(W("SOFTWARE\\Classes\\"))); ssHklmKeyName.Append(ssKeyName); - return Clr::Util::Reg::ReadStringValue(HKEY_LOCAL_MACHINE, ssHklmKeyName.GetUnicode(), nullptr, ssValue); + return Clr::Util::Reg::ReadStringValue(HKEY_LOCAL_MACHINE, ssHklmKeyName, nullptr, ssValue); } return hkcrResult; diff --git a/src/coreclr/utilcode/util_nodependencies.cpp b/src/coreclr/utilcode/util_nodependencies.cpp index 45874f0df86eb8..ad2d4bcd0bf9df 100644 --- a/src/coreclr/utilcode/util_nodependencies.cpp +++ b/src/coreclr/utilcode/util_nodependencies.cpp @@ -280,7 +280,7 @@ void GetDebuggerSettingInfo(SString &ssDebuggerString, BOOL *pfAuto) DWORD cchDebuggerString = MAX_LONGPATH; INDEBUG(DWORD cchOldDebuggerString = cchDebuggerString); - WCHAR * buf = ssDebuggerString.OpenUnicodeBuffer(cchDebuggerString); + WCHAR * buf = ssDebuggerString.OpenBuffer(cchDebuggerString); HRESULT hr = GetDebuggerSettingInfoWorker(buf, &cchDebuggerString, pfAuto); ssDebuggerString.CloseBuffer(cchDebuggerString); @@ -289,12 +289,12 @@ void GetDebuggerSettingInfo(SString &ssDebuggerString, BOOL *pfAuto) _ASSERTE(cchDebuggerString > cchOldDebuggerString); INDEBUG(cchOldDebuggerString = cchDebuggerString); - buf = ssDebuggerString.OpenUnicodeBuffer(cchDebuggerString); + buf = ssDebuggerString.OpenBuffer(cchDebuggerString); hr = GetDebuggerSettingInfoWorker(buf, &cchDebuggerString, pfAuto); ssDebuggerString.CloseBuffer(cchDebuggerString); } - if (*ssDebuggerString.GetUnicode() == W('\0')) + if (*(const WCHAR*)ssDebuggerString == W('\0')) { ssDebuggerString.Clear(); } diff --git a/src/coreclr/utilcode/utilcode.natvis b/src/coreclr/utilcode/utilcode.natvis index 7756270b164cdc..489b762ca4dbc5 100644 --- a/src/coreclr/utilcode/utilcode.natvis +++ b/src/coreclr/utilcode/utilcode.natvis @@ -7,15 +7,16 @@ The .NET Foundation licenses this file to you under the MIT license. - - [Empty] - [Unicode] {m_buffer,su} - [ASCII] {m_buffer,s} - [UTF8] {m_buffer,s8} - [ANSI] {m_buffer,s} - m_buffer,su - m_buffer,s - m_buffer,s8 - m_buffer,s + + [Unicode] {m_buffer,su} + m_buffer,su + + + [ASCII] {m_buffer,s} + m_buffer,s + + + [UTF8] {m_buffer,s8} + m_buffer,s8 diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index dd6541a1f74379..2496246cb329a3 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -822,7 +822,7 @@ void AppDomain::SetNativeDllSearchDirectories(LPCWSTR wszNativeDllSearchDirector { if (qualifiedPath[len - 1] != DIRECTORY_SEPARATOR_CHAR_W) { - qualifiedPath.Append(DIRECTORY_SEPARATOR_CHAR_W); + qualifiedPath.Append(DIRECTORY_SEPARATOR_STR_W); } NewHolder stringHolder(new SString(qualifiedPath)); @@ -1178,19 +1178,17 @@ void SystemDomain::Init() ThrowHR(hr); // GetInternalSystemDirectory returns a size, including the null! - WCHAR* buffer = m_SystemDirectory.OpenUnicodeBuffer(size - 1); + WCHAR* buffer = m_SystemDirectory.OpenBuffer(size - 1); IfFailThrow(GetInternalSystemDirectory(buffer, &size)); m_SystemDirectory.CloseBuffer(); - m_SystemDirectory.Normalize(); // At this point m_SystemDirectory should already be canonicalized m_BaseLibrary.Append(m_SystemDirectory); - if (!m_BaseLibrary.EndsWith(DIRECTORY_SEPARATOR_CHAR_W)) + if (!m_BaseLibrary.EndsWith(SL(DIRECTORY_SEPARATOR_STR_W))) { - m_BaseLibrary.Append(DIRECTORY_SEPARATOR_CHAR_W); + m_BaseLibrary.Append(DIRECTORY_SEPARATOR_STR_W); } m_BaseLibrary.Append(g_pwBaseLibrary); - m_BaseLibrary.Normalize(); LoadBaseSystemClasses(); @@ -3150,7 +3148,8 @@ void AppDomain::SetFriendlyName(LPCWSTR pwzFriendlyName, BOOL fDebuggerCares/*=T if (m_pRootAssembly) { - tmpFriendlyName.SetUTF8(m_pRootAssembly->GetSimpleName()); + MAKE_WIDEPTR_FROMUTF8(pSimpleName, m_pRootAssembly->GetSimpleName()); + tmpFriendlyName.Set(pSimpleName); SString::Iterator i = tmpFriendlyName.End(); if (tmpFriendlyName.FindBack(i, '.')) @@ -3162,11 +3161,7 @@ void AppDomain::SetFriendlyName(LPCWSTR pwzFriendlyName, BOOL fDebuggerCares/*=T } } - tmpFriendlyName.Normalize(); - - m_friendlyName = tmpFriendlyName; - m_friendlyName.Normalize(); if(g_pDebugInterface) { diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index de8264b59842df..e13d13c85d75be 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -1452,7 +1452,7 @@ class CollectibleAssemblyHolder : public BaseWrapper<_Type, CollectibleAssemblyH // Stores binding information about failed assembly loads for DAC // struct FailedAssembly { - SString displayName; + EString displayName; HRESULT error; void Initialize(AssemblySpec *pSpec, Exception *ex) @@ -1465,7 +1465,7 @@ struct FailedAssembly { } CONTRACTL_END; - displayName.SetASCII(pSpec->GetName()); + displayName.Set(pSpec->GetName()); error = ex->GetHR(); // @@ -2196,7 +2196,7 @@ class AppDomain : public BaseDomain // The one and only AppDomain SPTR_DECL(AppDomain, m_pTheAppDomain); - SString m_friendlyName; + SString m_friendlyName; PTR_Assembly m_pRootAssembly; // General purpose flags. @@ -2581,12 +2581,12 @@ class SystemDomain : public BaseDomain return FALSE; } - BOOL IsBaseLibrarySatellite(SString &path) + BOOL IsBaseLibrarySatellite(EString &path) { WRAPPER_NO_CONTRACT; // See if it is the installation path to corelib.resources - SString s(SString::Ascii,g_psBaseLibrarySatelliteAssemblyName); + EString s(g_psBaseLibrarySatelliteAssemblyName); if (path.EqualsCaseInsensitive(s)) return TRUE; diff --git a/src/coreclr/vm/array.cpp b/src/coreclr/vm/array.cpp index 402acdb7a53233..65325a0520b7d5 100644 --- a/src/coreclr/vm/array.cpp +++ b/src/coreclr/vm/array.cpp @@ -401,9 +401,8 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy if(dwComponentSize > MAX_SIZE_FOR_VALUECLASS_IN_ARRAY) { StackSString ssElemName; elemTypeHnd.GetName(ssElemName); - - StackScratchBuffer scratch; - elemTypeHnd.GetAssembly()->ThrowTypeLoadException(ssElemName.GetUTF8(scratch), IDS_CLASSLOAD_VALUECLASSTOOLARGE); + MAKE_UTF8PTR_FROMWIDE(szElemName, ssElemName); + elemTypeHnd.GetAssembly()->ThrowTypeLoadException(szElemName, IDS_CLASSLOAD_VALUECLASSTOOLARGE); } } @@ -510,8 +509,7 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy #ifdef _DEBUG StackSString debugName; TypeString::AppendType(debugName, TypeHandle(pMT)); - StackScratchBuffer buff; - const char* pDebugNameUTF8 = debugName.GetUTF8(buff); + MAKE_UTF8PTR_FROMWIDE(pDebugNameUTF8, debugName); S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8))+S_SIZE_T(1); if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); size_t len = safeLen.Value(); @@ -657,8 +655,8 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy StackSString ssElemName; elemTypeHnd.GetName(ssElemName); - StackScratchBuffer scratch; - elemTypeHnd.GetAssembly()->ThrowTypeLoadException(ssElemName.GetUTF8(scratch), + MAKE_UTF8PTR_FROMWIDE(scratch, ssElemName); + elemTypeHnd.GetAssembly()->ThrowTypeLoadException(scratch, IDS_CLASSLOAD_VALUECLASSTOOLARGE); } diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index e72b6bfe575275..87b04d24e16c50 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -990,13 +990,10 @@ Module *Assembly::FindModuleByName(LPCSTR pszModuleName) } CONTRACT_END; - SString moduleName(SString::Utf8, pszModuleName); + EString moduleName(pszModuleName); moduleName.LowerCase(); - StackScratchBuffer buffer; - pszModuleName = moduleName.GetUTF8(buffer); - - mdFile kFile = GetManifestFileToken(pszModuleName); + mdFile kFile = GetManifestFileToken(moduleName); if (kFile == mdTokenNil) ThrowHR(COR_E_UNAUTHORIZEDACCESS); @@ -1770,13 +1767,9 @@ BOOL Assembly::IsInstrumentedHelper() (*szZapBBInstr == '\0') || (*szAssemblyName == '\0')) return false; - // Convert to unicode so that we can do a case insensitive comparison - - SString instrumentedAssemblyNamesList(SString::Utf8, szZapBBInstr); - SString assemblyName(SString::Utf8, szAssemblyName); - - const WCHAR *wszInstrumentedAssemblyNamesList = instrumentedAssemblyNamesList.GetUnicode(); - const WCHAR *wszAssemblyName = assemblyName.GetUnicode(); + // Convert to unicode so that we can do a case insensitive comparison + MAKE_WIDEPTR_FROMUTF8(wszInstrumentedAssemblyNamesList, szZapBBInstr); + MAKE_WIDEPTR_FROMUTF8(wszAssemblyName, szAssemblyName); // wszInstrumentedAssemblyNamesList is a space separated list of assembly names. // We need to determine if wszAssemblyName is in this list. @@ -1801,11 +1794,11 @@ BOOL Assembly::IsInstrumentedHelper() if (pNextSpace == NULL) { // We have reached the last name in the list. There are no more spaces. - return (SString::_wcsicmp(wszAssemblyName, pCur) == 0); + return (StaticStringHelpers::_wcsicmp(wszAssemblyName, pCur) == 0); } else { - if (SString::_wcsnicmp(wszAssemblyName, pCur, static_cast(pNextSpace - pCur)) == 0) + if (StaticStringHelpers::_wcsnicmp(wszAssemblyName, pCur, static_cast(pNextSpace - pCur)) == 0) return true; } } @@ -2059,12 +2052,15 @@ void DECLSPEC_NORETURN Assembly::ThrowBadImageException(LPCUTF8 pszNameSpace, StackSString displayName; GetDisplayName(displayName); - StackSString fullName; - SString sNameSpace(SString::Utf8, pszNameSpace); - SString sTypeName(SString::Utf8, pszTypeName); - fullName.MakeFullNamespacePath(sNameSpace, sTypeName); + StackEString fullName; + EString sNameSpace(pszNameSpace); + EString sTypeName(pszTypeName); + ns::MakePath(fullName, sNameSpace, sTypeName); + + StackSString fullNameW; + fullName.ConvertToUnicode(fullNameW); - COMPlusThrowHR(COR_E_BADIMAGEFORMAT, resIDWhy, fullName, displayName); + COMPlusThrowHR(COR_E_BADIMAGEFORMAT, resIDWhy, fullNameW, displayName); } #endif // #ifndef DACCESS_COMPILE @@ -2232,7 +2228,7 @@ ReleaseHolder FriendAssemblyDescriptor::CreateFriendAs } // Convert the string to Unicode. - StackSString displayName(SString::Utf8, szString, cbString); + StackEString displayName(szString, cbString); // Create an AssemblyNameObject from the string. FriendAssemblyNameHolder pFriendAssemblyName; diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index a0879b0290c0fa..6710384dcf5b5e 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -75,7 +75,7 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* p if (pAssemblyNameParts->_pName == NULL) COMPlusThrow(kArgumentException, W("Format_StringZeroLength")); - StackSString ssName; + StackEString ssName; SString(SString::Literal, pAssemblyNameParts->_pName).ConvertToUTF8(ssName); AssemblyMetaDataInternal asmInfo; @@ -85,13 +85,13 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* p asmInfo.usBuildNumber = pAssemblyNameParts->_build; asmInfo.usRevisionNumber = pAssemblyNameParts->_revision; - SmallStackSString ssLocale; + SmallStackEString ssLocale; if (pAssemblyNameParts->_pCultureName != NULL) SString(SString::Literal, pAssemblyNameParts->_pCultureName).ConvertToUTF8(ssLocale); - asmInfo.szLocale = (pAssemblyNameParts->_pCultureName != NULL) ? ssLocale.GetUTF8NoConvert() : NULL; + asmInfo.szLocale = (pAssemblyNameParts->_pCultureName != NULL) ? (LPCUTF8)ssLocale : NULL; // Initialize spec - spec.Init(ssName.GetUTF8NoConvert(), &asmInfo, + spec.Init((LPCUTF8)ssName, &asmInfo, pAssemblyNameParts->_pPublicKeyOrToken, pAssemblyNameParts->_cbPublicKeyOrToken, pAssemblyNameParts->_flags); if (pParentAssembly != NULL) @@ -543,8 +543,7 @@ extern "C" BYTE * QCALLTYPE AssemblyNative_GetResource(QCall::AssemblyHandle pAs // Get the name in UTF8 SString name(SString::Literal, wszName); - StackScratchBuffer scratch; - LPCUTF8 pNameUTF8 = name.GetUTF8(scratch); + MAKE_UTF8PTR_FROMWIDE(pNameUTF8, name); if (*pNameUTF8 == '\0') COMPlusThrow(kArgumentException, W("Format_StringZeroLength")); @@ -573,8 +572,7 @@ extern "C" INT32 QCALLTYPE AssemblyNative_GetManifestResourceInfo(QCall::Assembl // Get the name in UTF8 SString name(SString::Literal, wszName); - StackScratchBuffer scratch; - LPCUTF8 pNameUTF8 = name.GetUTF8(scratch); + MAKE_UTF8PTR_FROMWIDE(pNameUTF8, name); if (*pNameUTF8 == '\0') COMPlusThrow(kArgumentException, W("Format_StringZeroLength")); @@ -698,7 +696,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetModule(QCall::AssemblyHandle pAssemb if SUCCEEDED(pAssembly->GetModule()->GetScopeName(&pModuleName)) { - if (::SString::_stricmp(pModuleName, szModuleName) == 0) + if (::StaticStringHelpers::_stricmp(pModuleName, szModuleName) == 0) pModule = pAssembly->GetModule(); } @@ -1103,10 +1101,10 @@ extern "C" void QCALLTYPE AssemblyNative_GetImageRuntimeVersion(QCall::AssemblyH LPCSTR pszVersion = NULL; IfFailThrow(pPEAssembly->GetMDImport()->GetVersionString(&pszVersion)); - SString version(SString::Utf8, pszVersion); + EString version(pszVersion); // Allocate a managed string that contains the version and return it. - retString.Set(version); + retString.Set((LPCUTF8)version); END_QCALL; } diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index 14ad9e680b122f..6664ea47b6264d 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -232,8 +232,8 @@ void AssemblySpec::AssemblyNameInit(ASSEMBLYNAMEREF* pAsmName) StackSString ssName; if (m_pAssemblyName != NULL) - SString(SString::Utf8Literal, m_pAssemblyName).ConvertToUnicode(ssName); - nameParts._pName = (m_pAssemblyName != NULL) ? ssName.GetUnicode() : NULL; + EString(EString::Literal, m_pAssemblyName).ConvertToUnicode(ssName); + nameParts._pName = (m_pAssemblyName != NULL) ? (LPCWSTR)ssName : NULL; nameParts._major = m_context.usMajorVersion; nameParts._minor = m_context.usMinorVersion; @@ -242,8 +242,8 @@ void AssemblySpec::AssemblyNameInit(ASSEMBLYNAMEREF* pAsmName) SmallStackSString ssLocale; if (m_context.szLocale != NULL) - SString(SString::Utf8Literal, m_context.szLocale).ConvertToUnicode(ssLocale); - nameParts._pCultureName = (m_context.szLocale != NULL) ? ssLocale.GetUnicode() : NULL; + EString(EString::Literal, m_context.szLocale).ConvertToUnicode(ssLocale); + nameParts._pCultureName = (m_context.szLocale != NULL) ? (LPCWSTR)ssLocale : NULL; nameParts._pPublicKeyOrToken = m_pbPublicKeyOrToken; nameParts._cbPublicKeyOrToken = m_cbPublicKeyOrToken; @@ -275,13 +275,15 @@ void AssemblySpec::InitializeAssemblyNameRef(_In_ BINDER_SPACE::AssemblyName* as AssemblySpec spec; spec.InitializeWithAssemblyIdentity(assemblyName); - StackScratchBuffer nameBuffer; - spec.SetName(assemblyName->GetSimpleName().GetUTF8(nameBuffer)); + StackEString nameUTF8; + assemblyName->GetSimpleName().ConvertToUTF8(nameUTF8); + spec.SetName(nameUTF8); - StackScratchBuffer cultureBuffer; + StackEString cultureUTF8; if (assemblyName->Have(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CULTURE)) { - LPCSTR culture = assemblyName->IsNeutralCulture() ? "" : assemblyName->GetCulture().GetUTF8(cultureBuffer); + assemblyName->GetCulture().ConvertToUTF8(cultureUTF8); + LPCSTR culture = assemblyName->IsNeutralCulture() ? "" : cultureUTF8; spec.SetCulture(culture); } @@ -497,7 +499,7 @@ Assembly *AssemblySpec::LoadAssembly(LPCWSTR pFilePath) pILImage = PEImage::OpenImage(pFilePath, MDInternalImport_Default, - Bundle::ProbeAppBundle(pFilePath)); + Bundle::ProbeAppBundle(SL(pFilePath))); // Need to verify that this is a valid CLR assembly. if (!pILImage->CheckILFormat()) @@ -542,8 +544,10 @@ HRESULT AssemblySpec::EmitToken( EX_TRY { - SmallStackSString ssName; + SmallStackEString ssName; GetName(ssName); + SmallStackSString ssNameW; + ssName.ConvertToUnicode(ssNameW); ASSEMBLYMETADATA AMD; @@ -577,7 +581,7 @@ HRESULT AssemblySpec::EmitToken( hr = pEmit->DefineAssemblyRef(pbPublicKeyToken, cbPublicKeyToken, - ssName.GetUnicode(), + (LPCWSTR)ssNameW, &AMD, NULL, 0, @@ -587,7 +591,7 @@ HRESULT AssemblySpec::EmitToken( else { hr = pEmit->DefineAssemblyRef(m_pbPublicKeyOrToken, m_cbPublicKeyOrToken, - ssName.GetUnicode(), + (LPCWSTR)ssNameW, &AMD, NULL, 0, diff --git a/src/coreclr/vm/baseassemblyspec.cpp b/src/coreclr/vm/baseassemblyspec.cpp index fbc0afad966c01..bc2bdc8b802ee9 100644 --- a/src/coreclr/vm/baseassemblyspec.cpp +++ b/src/coreclr/vm/baseassemblyspec.cpp @@ -38,7 +38,7 @@ BOOL BaseAssemblySpec::IsCoreLib() size_t iNameLen = strlen(m_pAssemblyName); return ( (iNameLen >= CoreLibNameLen) && ( (!stricmpUTF8(m_pAssemblyName, g_psBaseLibrary)) || - ( (!SString::_strnicmp(m_pAssemblyName, g_psBaseLibraryName, CoreLibNameLen)) && + ( (!StaticStringHelpers::_strnicmp(m_pAssemblyName, g_psBaseLibraryName, CoreLibNameLen)) && ( (iNameLen == CoreLibNameLen) || (m_pAssemblyName[CoreLibNameLen] == ',') ) ) ) ); } @@ -74,7 +74,7 @@ BOOL BaseAssemblySpec::IsCoreLibSatellite() const // we allow name to be of the form System.Private.CoreLib.resources.dll only BOOL r = ( (m_cbPublicKeyOrToken == sizeof(CORELIB_PUBLICKEY)) && (iNameLen >= CoreLibSatelliteNameLen) && - (!SString::_strnicmp(m_pAssemblyName, g_psBaseLibrarySatelliteAssemblyName, CoreLibSatelliteNameLen)) && + (!StaticStringHelpers::_strnicmp(m_pAssemblyName, g_psBaseLibrarySatelliteAssemblyName, CoreLibSatelliteNameLen)) && ( (iNameLen == CoreLibSatelliteNameLen) || (m_pAssemblyName[CoreLibSatelliteNameLen] == ',') ) ); r = r && ( memcmp(m_pbPublicKeyOrToken,CORELIB_PUBLICKEY,sizeof(CORELIB_PUBLICKEY)) == 0); diff --git a/src/coreclr/vm/baseassemblyspec.h b/src/coreclr/vm/baseassemblyspec.h index 77180a3db980e8..084181b14d68dd 100644 --- a/src/coreclr/vm/baseassemblyspec.h +++ b/src/coreclr/vm/baseassemblyspec.h @@ -51,8 +51,8 @@ class BaseAssemblySpec HRESULT Init(mdToken tkAssemblyRef, IMDInternalImport *pImport); HRESULT Init(mdAssembly tkAssemblyRef, IMetaDataAssemblyImport* pImport); - void Init(SString& assemblyDisplayName); - HRESULT InitNoThrow(SString& assemblyDisplayName); + void Init(const EString& assemblyDisplayName); + HRESULT InitNoThrow(const EString& assemblyDisplayName); // Note that this method does not clone the fields! VOID CopyFrom(const BaseAssemblySpec *pSpec); @@ -77,7 +77,7 @@ class BaseAssemblySpec DWORD Hash(); LPCSTR GetName() const; - inline void GetName(SString & ssName) const { WRAPPER_NO_CONTRACT; ssName.SetUTF8(GetName()); } + inline void GetName(EString & ssName) const { WRAPPER_NO_CONTRACT; ssName.Set(GetName()); } void SetName(LPCSTR szName); diff --git a/src/coreclr/vm/baseassemblyspec.inl b/src/coreclr/vm/baseassemblyspec.inl index 1d79bf50a7ffef..e864d07badcdb4 100644 --- a/src/coreclr/vm/baseassemblyspec.inl +++ b/src/coreclr/vm/baseassemblyspec.inl @@ -17,10 +17,10 @@ inline int BaseAssemblySpec::CompareStrings(LPCUTF8 string1, LPCUTF8 string2) { WRAPPER_NO_CONTRACT; - SString s1; - SString s2; - s1.SetUTF8(string1); - s2.SetUTF8(string2); + EString s1; + EString s2; + s1.Set(string1); + s2.Set(string2); return s1.CompareCaseInsensitive(s2); } diff --git a/src/coreclr/vm/binder.cpp b/src/coreclr/vm/binder.cpp index d9cfb45acda1a8..8edb0d88580844 100644 --- a/src/coreclr/vm/binder.cpp +++ b/src/coreclr/vm/binder.cpp @@ -648,7 +648,7 @@ static BOOL IsStrInArray(const char* sStr, size_t len, const char* aStrArray[], STANDARD_VM_CONTRACT; for (int i = 0; i < nSize; i++) { - if (SString::_strnicmp(aStrArray[i], sStr, (COUNT_T)len) == 0) + if (StaticStringHelpers::_strnicmp(aStrArray[i], sStr, (COUNT_T)len) == 0) { return TRUE; } @@ -800,14 +800,13 @@ static void FCallCheckSignature(MethodDesc* pMD, PCODE pImpl) size_t len = pUnmanagedTypeEnd - pUnmanagedArg; // generate the unmanaged argument signature to show them in the error message if possible - StackSString ssUnmanagedType(SString::Ascii, pUnmanagedArg, (COUNT_T)len); - StackScratchBuffer buffer; - const char * pUnManagedType = ssUnmanagedType.GetANSI(buffer); + StackEString ssUnmanagedType(pUnmanagedArg, (COUNT_T)len); + const char * pUnManagedType = ssUnmanagedType; if (expectedType != NULL) { // when managed type is well known - if (!(strlen(expectedType) == len && SString::_strnicmp(expectedType, pUnmanagedArg, (COUNT_T)len) == 0)) + if (!(strlen(expectedType) == len && StaticStringHelpers::_strnicmp(expectedType, pUnmanagedArg, (COUNT_T)len) == 0)) { printf("CheckExtended: The managed and unmanaged fcall signatures do not match, Method: %s:%s. Argument: %d Expecting: %s Actual: %s\n", pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, argIndex, expectedType, pUnManagedType); } diff --git a/src/coreclr/vm/bundle.cpp b/src/coreclr/vm/bundle.cpp index a51ed906b710d3..42460e940eac23 100644 --- a/src/coreclr/vm/bundle.cpp +++ b/src/coreclr/vm/bundle.cpp @@ -15,7 +15,7 @@ Bundle *Bundle::AppBundle = nullptr; -const SString &BundleFileLocation::Path() const +const EString &BundleFileLocation::Path() const { LIMITED_METHOD_CONTRACT; @@ -36,7 +36,7 @@ Bundle::Bundle(LPCSTR bundlePath, BundleProbeFn *probe) _ASSERTE(probe != nullptr); - m_path.SetUTF8(bundlePath); + m_path.Set(bundlePath); m_probe = probe; // The bundle-base path is the directory containing the single-file bundle. @@ -45,11 +45,11 @@ Bundle::Bundle(LPCSTR bundlePath, BundleProbeFn *probe) LPCSTR pos = strrchr(bundlePath, DIRECTORY_SEPARATOR_CHAR_A); _ASSERTE(pos != nullptr); size_t baseLen = pos - bundlePath + 1; // Include DIRECTORY_SEPARATOR_CHAR_A in m_basePath - m_basePath.SetUTF8(bundlePath, (COUNT_T)baseLen); + m_basePath.Set(bundlePath, (COUNT_T)baseLen); m_basePathLength = (COUNT_T)baseLen; } -BundleFileLocation Bundle::Probe(const SString& path, bool pathIsBundleRelative) const +BundleFileLocation Bundle::Probe(const EString& path, bool pathIsBundleRelative) const { STANDARD_VM_CONTRACT; @@ -60,15 +60,14 @@ BundleFileLocation Bundle::Probe(const SString& path, bool pathIsBundleRelative) // Bundle.Probe("path/to/exe/lib.dll") => m_probe("lib.dll") // Bundle.Probe("path/to/exe/and/some/more/lib.dll") => m_probe("and/some/more/lib.dll") - StackScratchBuffer scratchBuffer; - LPCSTR utf8Path(path.GetUTF8(scratchBuffer)); + LPCSTR utf8Path(path); if (!pathIsBundleRelative) { #ifdef TARGET_UNIX - if (wcsncmp(m_basePath, path, m_basePath.GetCount()) == 0) + if (strncmp(m_basePath, path, m_basePath.GetCount()) == 0) #else - if (_wcsnicmp(m_basePath, path, m_basePath.GetCount()) == 0) + if (strncmp(m_basePath, path, m_basePath.GetCount()) == 0) #endif // TARGET_UNIX { utf8Path += m_basePathLength; // m_basePath includes count for DIRECTORY_SEPARATOR_CHAR_W @@ -103,5 +102,8 @@ BundleFileLocation Bundle::ProbeAppBundle(const SString& path, bool pathIsBundle { STANDARD_VM_CONTRACT; - return AppIsBundle() ? AppBundle->Probe(path, pathIsBundleRelative) : BundleFileLocation::Invalid(); + StackEString pathUtf8; + path.ConvertToUTF8(pathUtf8); + + return AppIsBundle() ? AppBundle->Probe(pathUtf8, pathIsBundleRelative) : BundleFileLocation::Invalid(); } diff --git a/src/coreclr/vm/callhelpers.cpp b/src/coreclr/vm/callhelpers.cpp index da342a1b1f01b3..22c566cdf39123 100644 --- a/src/coreclr/vm/callhelpers.cpp +++ b/src/coreclr/vm/callhelpers.cpp @@ -601,8 +601,8 @@ void CallDefaultConstructor(OBJECTREF ref) if (!pMT->HasDefaultConstructor()) { - SString ctorMethodName(SString::Utf8, COR_CTOR_METHOD_NAME); - COMPlusThrowNonLocalized(kMissingMethodException, ctorMethodName.GetUnicode()); + SString ctorMethodName(COR_CTOR_METHOD_NAME_W); + COMPlusThrowNonLocalized(kMissingMethodException, (LPCWSTR)ctorMethodName); } GCPROTECT_BEGIN (ref); diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index 4ffba8ab8a3c6c..ee6f85e69d53c7 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -2471,7 +2471,7 @@ ISymUnmanagedReader *Module::GetISymUnmanagedReader(void) RETURN (NULL); } symbolReaderPath.Append(NATIVE_SYMBOL_READER_DLL); - hr = FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS, symbolReaderPath.GetUnicode(), IID_ISymUnmanagedBinder, (void**)&pBinder, NULL); + hr = FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS, (LPCWSTR)symbolReaderPath, IID_ISymUnmanagedBinder, (void**)&pBinder, NULL); if (FAILED(hr)) { RETURN (NULL); @@ -3408,7 +3408,8 @@ DomainAssembly *Module::LoadModule(AppDomain *pDomain, mdFile kFile) NULL)); } - SString name(SString::Utf8, psModuleName); + SString name; + EString(psModuleName).ConvertToUnicode(name); EEFileLoadException::Throw(name, COR_E_MULTIMODULEASSEMBLIESDIALLOWED, NULL); RETURN NULL; } diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index ff980ed5cfd178..48d17fd4e7d7c9 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -59,7 +59,6 @@ class DomainModule; struct DomainLocalModule; class SystemDomain; class Module; -class SString; class Pending; class MethodTable; class AppDomain; diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 36d63aa9e771dc..1bc164d196ae83 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -596,9 +596,9 @@ void EEStartupHelper() #endif - // SString initialization - // This needs to be done before config because config uses SString::Empty() - SString::Startup(); + // EString initialization + // This needs to be done before config because config uses StaticStringHelpers::Empty() + StaticStringHelpers::Startup(); IfFailGo(EEConfig::Setup()); @@ -1926,9 +1926,9 @@ static HRESULT GetThreadUICultureNames(__inout StringArrayList* pCultureNames) // coreclr.dll!CCompRC::GetLibrary // coreclr.dll!CCompRC::LoadString // coreclr.dll!CCompRC::LoadString - // coreclr.dll!SString::LoadResourceAndReturnHR - // coreclr.dll!SString::LoadResourceAndReturnHR - // coreclr.dll!SString::LoadResource + // coreclr.dll!LoadResourceAndReturnHR + // coreclr.dll!LoadResourceAndReturnHR + // coreclr.dll!LoadResource // coreclr.dll!EventReporter::EventReporter // coreclr.dll!EEPolicy::LogFatalError // coreclr.dll!EEPolicy::HandleFatalError @@ -1976,7 +1976,7 @@ static HRESULT GetThreadUICultureNames(__inout StringArrayList* pCultureNames) sCulture.Set(id); #ifndef TARGET_UNIX - if (!::GetLocaleInfoEx((LPCWSTR)sCulture, LOCALE_SPARENT, sParentCulture.OpenUnicodeBuffer(static_cast(cchParentCultureName)),static_cast(cchParentCultureName))) + if (!::GetLocaleInfoEx((LPCWSTR)sCulture, LOCALE_SPARENT, sParentCulture.OpenBuffer(static_cast(cchParentCultureName)),static_cast(cchParentCultureName))) { hr = HRESULT_FROM_GetLastError(); } @@ -2056,9 +2056,9 @@ static int GetThreadUICultureId(_Out_ LocaleIDValue* pLocale) // coreclr.dll!CCompRC::GetLibrary // coreclr.dll!CCompRC::LoadString // coreclr.dll!CCompRC::LoadString - // coreclr.dll!SString::LoadResourceAndReturnHR - // coreclr.dll!SString::LoadResourceAndReturnHR - // coreclr.dll!SString::LoadResource + // coreclr.dll!LoadResourceAndReturnHR + // coreclr.dll!LoadResourceAndReturnHR + // coreclr.dll!LoadResource // coreclr.dll!EventReporter::EventReporter // coreclr.dll!EEPolicy::LogFatalError // coreclr.dll!EEPolicy::HandleFatalError diff --git a/src/coreclr/vm/class.cpp b/src/coreclr/vm/class.cpp index 6a51768b103699..8cc2248c8375af 100644 --- a/src/coreclr/vm/class.cpp +++ b/src/coreclr/vm/class.cpp @@ -1787,11 +1787,11 @@ TypeHandle MethodTable::SetupCoClassForInterface() IfFailThrow(cap.GetNonNullString(&szName, &cbName)); // Copy the name to a temporary buffer and NULL terminate it. - StackSString ss(SString::Utf8, szName, cbName); + StackEString ss(szName, cbName); // Try to load the class using its name as a fully qualified name. If that fails, // then we try to load it in the assembly of the current class. - CoClassType = TypeName::GetTypeUsingCASearchRules(ss.GetUnicode(), GetAssembly()); + CoClassType = TypeName::GetTypeUsingCASearchRules(ss, GetAssembly()); // Cache the coclass type GetClass_NoLogging()->SetCoClassForInterface(CoClassType); @@ -1834,21 +1834,21 @@ void MethodTable::GetEventInterfaceInfo(MethodTable **ppSrcItfClass, MethodTable IfFailThrow(cap.GetNonNullString(&szName, &cbName)); // Copy the name to a temporary buffer and NULL terminate it. - StackSString ss(SString::Utf8, szName, cbName); + StackEString ss(szName, cbName); // Try to load the class using its name as a fully qualified name. If that fails, // then we try to load it in the assembly of the current class. - SrcItfType = TypeName::GetTypeUsingCASearchRules(ss.GetUnicode(), GetAssembly()); + SrcItfType = TypeName::GetTypeUsingCASearchRules(ss, GetAssembly()); // Retrieve the COM event provider class name. IfFailThrow(cap.GetNonNullString(&szName, &cbName)); // Copy the name to a temporary buffer and NULL terminate it. - ss.SetUTF8(szName, cbName); + ss.Set(szName, cbName); // Try to load the class using its name as a fully qualified name. If that fails, // then we try to load it in the assembly of the current class. - EventProvType = TypeName::GetTypeUsingCASearchRules(ss.GetUnicode(), GetAssembly()); + EventProvType = TypeName::GetTypeUsingCASearchRules(ss, GetAssembly()); // Set the source interface and event provider classes. *ppSrcItfClass = SrcItfType.GetMethodTable(); @@ -1988,7 +1988,7 @@ SString &MethodTable::_GetFullyQualifiedNameForClassNestedAwareInternal(SString return ssBuf; } - StackSString ssName(SString::Utf8, pszName); + StackEString ssName(pszName); mdTypeDef mdEncl = GetCl(); IMDInternalImport *pImport = GetMDImport(); @@ -2000,8 +2000,8 @@ SString &MethodTable::_GetFullyQualifiedNameForClassNestedAwareInternal(SString RedirectFunctor redirectFunctor; if (IsTdNested(dwAttr)) { - StackSString ssFullyQualifiedName; - StackSString ssPath; + StackEString ssFullyQualifiedName; + StackEString ssPath; // Build the nesting chain. while (SUCCEEDED(pImport->GetNestedClassProps(mdEncl, &mdEncl))) @@ -2014,17 +2014,21 @@ SString &MethodTable::_GetFullyQualifiedNameForClassNestedAwareInternal(SString &szEnclNameSpace)); ns::MakePath(ssPath, - StackSString(SString::Utf8, redirectFunctor(szEnclNameSpace)), - StackSString(SString::Utf8, szEnclName)); + StackEString(redirectFunctor(szEnclNameSpace)), + StackEString(szEnclName)); ns::MakeNestedTypeName(ssFullyQualifiedName, ssPath, ssName); ssName = ssFullyQualifiedName; } } + StackEString ss; + ns::MakePath( - ssBuf, - StackSString(SString::Utf8, redirectFunctor(pszNamespace)), ssName); + ss, + StackEString(redirectFunctor(pszNamespace)), ssName); + + ss.ConvertToUnicode(ssBuf); return ssBuf; } @@ -2073,9 +2077,13 @@ SString &MethodTable::_GetFullyQualifiedNameForClass(SString &ssBuf) LPCUTF8 szName; IfFailThrow(GetMDImport()->GetNameOfTypeDef(GetCl(), &szName, &szNamespace)); - ns::MakePath(ssBuf, - StackSString(SString::Utf8, szNamespace), - StackSString(SString::Utf8, szName)); + StackEString ss; + + ns::MakePath(ss, + StackEString(szNamespace), + StackEString(szName)); + + ss.ConvertToUnicode(ssBuf); } return ssBuf; @@ -2210,7 +2218,7 @@ void MethodTable::DebugRecursivelyDumpInstanceFields(LPCUTF8 pszClassName, BOOL EX_TRY { - StackSString ssBuff; + StackEString ssBuff; DWORD cParentInstanceFields; DWORD i; @@ -2236,7 +2244,7 @@ void MethodTable::DebugRecursivelyDumpInstanceFields(LPCUTF8 pszClassName, BOOL // Display them if(debug) { ssBuff.Printf("%s:\n", pszClassName); - OutputDebugStringUtf8(ssBuff.GetUTF8NoConvert()); + OutputDebugStringUtf8(ssBuff); } else { LOG((LF_CLASSLOADER, LL_ALWAYS, "%s:\n", pszClassName)); @@ -2250,7 +2258,7 @@ void MethodTable::DebugRecursivelyDumpInstanceFields(LPCUTF8 pszClassName, BOOL #endif if(debug) { ssBuff.Printf("offset %3d %s\n", pFD->GetOffset_NoLogging(), pFD->GetName()); - OutputDebugStringUtf8(ssBuff.GetUTF8NoConvert()); + OutputDebugStringUtf8(ssBuff); } else { LOG((LF_CLASSLOADER, LL_ALWAYS, "offset %3d %s\n", pFD->GetOffset_NoLogging(), pFD->GetName())); @@ -2282,7 +2290,7 @@ void MethodTable::DebugDumpFieldLayout(LPCUTF8 pszClassName, BOOL debug) EX_TRY { - StackSString ssBuff; + StackEString ssBuff; DWORD i; DWORD cParentInstanceFields; @@ -2299,7 +2307,7 @@ void MethodTable::DebugDumpFieldLayout(LPCUTF8 pszClassName, BOOL debug) if (debug) { ssBuff.Printf("Field layout for '%s':\n\n", pszClassName); - OutputDebugStringUtf8(ssBuff.GetUTF8NoConvert()); + OutputDebugStringUtf8(ssBuff); } else { @@ -2326,7 +2334,7 @@ void MethodTable::DebugDumpFieldLayout(LPCUTF8 pszClassName, BOOL debug) FieldDesc *pFD = GetClass()->GetFieldDescList() + ((GetNumInstanceFields()-cParentInstanceFields) + i); if(debug) { ssBuff.Printf("offset %3d %s\n", pFD->GetOffset_NoLogging(), pFD->GetName()); - OutputDebugStringUtf8(ssBuff.GetUTF8NoConvert()); + OutputDebugStringUtf8(ssBuff); } else { @@ -2399,12 +2407,12 @@ MethodTable::DebugDumpGCDesc( EX_TRY { - StackSString ssBuff; + StackEString ssBuff; if (fDebug) { ssBuff.Printf("GC description for '%s':\n\n", pszClassName); - OutputDebugStringUtf8(ssBuff.GetUTF8NoConvert()); + OutputDebugStringUtf8(ssBuff); } else { @@ -2438,7 +2446,7 @@ MethodTable::DebugDumpGCDesc( pSeries->GetSeriesOffset() - OBJECT_SIZE, pSeries->GetSeriesSize(), pSeries->GetSeriesSize() + GetBaseSize() ); - OutputDebugStringUtf8(ssBuff.GetUTF8NoConvert()); + OutputDebugStringUtf8(ssBuff); } else { diff --git a/src/coreclr/vm/class.h b/src/coreclr/vm/class.h index 3093feae45bfdd..a723fed63840fb 100644 --- a/src/coreclr/vm/class.h +++ b/src/coreclr/vm/class.h @@ -507,30 +507,30 @@ typedef struct #define DEFAULT_NONSTACK_CLASSNAME_SIZE (MAX_CLASSNAME_LENGTH/4) #define DefineFullyQualifiedNameForClass() \ - ScratchBuffer _scratchbuffer_; \ - InlineSString _ssclsname_; + InlineEString _utf8_; \ + InlineEString _ssclsname_; #define DefineFullyQualifiedNameForClassOnStack() \ ScratchBuffer _scratchbuffer_; \ - InlineSString _ssclsname_; + InlineEString _ssclsname_; #define DefineFullyQualifiedNameForClassW() \ - InlineSString _ssclsname_w_; + InlineEString _ssclsname_w_; #define DefineFullyQualifiedNameForClassWOnStack() \ - InlineSString _ssclsname_w_; + InlineEString _ssclsname_w_; #define GetFullyQualifiedNameForClassNestedAware(pClass) \ - pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_).GetUTF8(_scratchbuffer_) + (pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_), _ssclsname_.ConvertToUTF8(_utf8_), (LPCUTF8)_utf8_) #define GetFullyQualifiedNameForClassNestedAwareW(pClass) \ - pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_w_).GetUnicode() + pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_w_) #define GetFullyQualifiedNameForClass(pClass) \ - pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_) + (pClass->_GetFullyQualifiedNameForClass(_ssclsname_), _ssclsname_.ConvertToUTF8(_utf8_), (LPCUTF8)_utf8_) #define GetFullyQualifiedNameForClassW(pClass) \ - pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode() + pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_) // Structure containing EEClass fields used by a minority of EEClass instances. This separation allows us to // save memory and improve the density of accessed fields in the EEClasses themselves. This class is reached diff --git a/src/coreclr/vm/classhash.cpp b/src/coreclr/vm/classhash.cpp index 005a3925657316..1e1e85813ce3aa 100644 --- a/src/coreclr/vm/classhash.cpp +++ b/src/coreclr/vm/classhash.cpp @@ -200,19 +200,15 @@ static void ConstructKeyFromDataCaseInsensitive(EEClassHashTable::ConstructKeyCa } CONTRACTL_END - LPUTF8 Key[2]; + LPCUTF8 Key[2]; - StackSString nameSpace(SString::Utf8, pszNameSpace); + StackEString nameSpace(pszNameSpace); nameSpace.LowerCase(); + Key[0] = nameSpace; - StackScratchBuffer nameSpaceBuffer; - Key[0] = (LPUTF8)nameSpace.GetUTF8(nameSpaceBuffer); - - StackSString name(SString::Utf8, pszName); + StackEString name(pszName); name.LowerCase(); - - StackScratchBuffer nameBuffer; - Key[1] = (LPUTF8)name.GetUTF8(nameBuffer); + Key[1] = name; pCallback->UseKeys(Key); } @@ -291,7 +287,7 @@ VOID EEClassHashTable::ConstructKeyFromData(PTR_EEClassHashEntry pEntry, // IN if (!m_bCaseInsensitive) { - LPUTF8 Key[2]; + LPCUTF8 Key[2]; Key[0] = pszNameSpace; Key[1] = pszName; @@ -348,7 +344,7 @@ EEClassHashEntry_t *EEClassHashTable::InsertValue(LPCUTF8 pszNamespace, LPCUTF8 class ConstructKeyCallbackValidate : public EEClassHashTable::ConstructKeyCallback { public: - virtual void UseKeys(_In_reads_(2) LPUTF8 *Key) + virtual void UseKeys(_In_reads_(2) LPCUTF8 *Key) { LIMITED_METHOD_CONTRACT; STATIC_CONTRACT_DEBUG_ONLY; @@ -688,7 +684,7 @@ EEClassHashEntry_t * EEClassHashTable::GetValue(const NameHandle* pName, PTR_VOI class ConstructKeyCallbackCompare : public EEClassHashTable::ConstructKeyCallback { public: - virtual void UseKeys(_In_reads_(2) LPUTF8 *pKey1) + virtual void UseKeys(_In_reads_(2) LPCUTF8 *pKey1) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; @@ -752,7 +748,7 @@ BOOL EEClassHashTable::CompareKeys(PTR_EEClassHashEntry pEntry, LPCUTF8 * pKey2) class ConstructKeyCallbackCaseInsensitive : public EEClassHashTable::ConstructKeyCallback { public: - virtual void UseKeys(_In_reads_(2) LPUTF8 *key) + virtual void UseKeys(_In_reads_(2) LPCUTF8 *key) { WRAPPER_NO_CONTRACT; diff --git a/src/coreclr/vm/classhash.h b/src/coreclr/vm/classhash.h index 4fd943165b4787..3d0cef81cb51dc 100644 --- a/src/coreclr/vm/classhash.h +++ b/src/coreclr/vm/classhash.h @@ -86,7 +86,7 @@ class EEClassHashTable : public DacEnumerableHashTableGetApproxEnclosingMethodTable()); MAKE_FULLY_QUALIFIED_MEMBER_NAME(szFullName, NULL, szClassName, szMember, ""); - result.SetUTF8(szFullName); + MAKE_WIDEPTR_FROMUTF8(wszFullName, szFullName); + result.Set(wszFullName); return TRUE; } @@ -1240,7 +1242,8 @@ BOOL EEMethodException::GetThrowableMessage(SString &result) SigFormat sigFormatter(tmp, szMember); const char * sigStr = sigFormatter.GetCStringParmsOnly(); MAKE_FULLY_QUALIFIED_MEMBER_NAME(szFullName, NULL, szClassName, szMember, sigStr); - result.SetUTF8(szFullName); + MAKE_WIDEPTR_FROMUTF8(wszFullName, szFullName); + result.Set(wszFullName); return TRUE; } @@ -1385,7 +1388,7 @@ EETypeLoadException::EETypeLoadException(LPCUTF8 pszNameSpace, LPCUTF8 pTypeName LPCWSTR pAssemblyName, LPCUTF8 pMessageArg, UINT resIDWhy) : EEException(kTypeLoadException), m_pAssemblyName(pAssemblyName), - m_pMessageArg(SString::Utf8, pMessageArg), + m_pMessageArg(SString::Empty()), m_resIDWhy(resIDWhy) { CONTRACTL @@ -1396,19 +1399,23 @@ EETypeLoadException::EETypeLoadException(LPCUTF8 pszNameSpace, LPCUTF8 pTypeName } CONTRACTL_END; + EString(pMessageArg).ConvertToUnicode(m_pMessageArg); + if(pszNameSpace) { - SString sNameSpace(SString::Utf8, pszNameSpace); - SString sTypeName(SString::Utf8, pTypeName); - m_fullName.MakeFullNamespacePath(sNameSpace, sTypeName); + EString sNameSpace(pszNameSpace); + EString sTypeName(pTypeName); + EString fullName; + ns::MakePath(fullName, sNameSpace, sTypeName); + fullName.ConvertToUnicode(m_fullName); } else if (pTypeName) { - m_fullName.SetUTF8(pTypeName); + m_fullName.Set(EString(pTypeName).MoveToUnicode()); } else { - m_fullName.SetUTF8(""); + m_fullName.Set(W("")); } } @@ -1417,8 +1424,9 @@ EETypeLoadException::EETypeLoadException(LPCWSTR pFullName, LPCUTF8 pMessageArg, UINT resIDWhy) : EEException(kTypeLoadException), + m_fullName(pFullName), m_pAssemblyName(pAssemblyName), - m_pMessageArg(SString::Utf8, pMessageArg), + m_pMessageArg(SString::Empty()), m_resIDWhy(resIDWhy) { CONTRACTL @@ -1428,21 +1436,34 @@ EETypeLoadException::EETypeLoadException(LPCWSTR pFullName, MODE_ANY; } CONTRACTL_END; + + EString(pMessageArg).ConvertToUnicode(m_pMessageArg); +} - MAKE_UTF8PTR_FROMWIDE(name, pFullName); - m_fullName.SetUTF8(name); +EETypeLoadException::EETypeLoadException(LPCWSTR pFullName, + LPCWSTR pAssemblyName, + LPCWSTR pMessageArg, + UINT resIDWhy) + : EEException(kTypeLoadException), + m_fullName(pFullName), + m_pAssemblyName(pAssemblyName), + m_pMessageArg(pMessageArg), + m_resIDWhy(resIDWhy) +{ + LIMITED_METHOD_CONTRACT; } void EETypeLoadException::GetMessage(SString &result) { WRAPPER_NO_CONTRACT; + SString fullNameUnicode; + m_fullName.ConvertToUnicode(fullNameUnicode); GetResourceMessage(IDS_CLASSLOAD_GENERAL, result, - m_fullName, m_pAssemblyName, m_pMessageArg); + fullNameUnicode, m_pAssemblyName, m_pMessageArg); } OBJECTREF EETypeLoadException::CreateThrowable() { - CONTRACTL { GC_TRIGGERS; @@ -1776,7 +1797,7 @@ void DECLSPEC_NORETURN EEFileLoadException::Throw(PEAssembly *parent, COMPlusThrowOM(); StackSString name; - name.Printf("%d bytes loaded from ", size); + name.Printf(W("%d bytes loaded from "), size); StackSString parentName; parent->GetDisplayName(parentName); diff --git a/src/coreclr/vm/clrex.h b/src/coreclr/vm/clrex.h index 492104704b3ed3..91620e4a8f5869 100644 --- a/src/coreclr/vm/clrex.h +++ b/src/coreclr/vm/clrex.h @@ -488,7 +488,7 @@ class EEMethodException : public EEException private: MethodDesc *m_pMD; MethodDesc *m_pAccessingMD; - SString m_additionalContext; + SString m_additionalContext; UINT m_messageID; public: @@ -527,7 +527,7 @@ class EETypeAccessException : public EEException private: MethodTable *m_pMT; MethodDesc *m_pAccessingMD; - SString m_additionalContext; + SString m_additionalContext; UINT m_messageID; public: @@ -620,6 +620,9 @@ class EETypeLoadException : public EEException OBJECTREF CreateThrowable(); protected: + + EETypeLoadException(LPCWSTR pFullTypeName, + LPCWSTR pAssemblyName, LPCWSTR pMessageArg, UINT resIDWhy); virtual Exception *CloneHelper() { @@ -628,15 +631,15 @@ class EETypeLoadException : public EEException } private: - EETypeLoadException(const InlineSString<64> &fullName, LPCWSTR pAssemblyName, + EETypeLoadException(const InlineEString<64, EncodingUTF8> &fullName, LPCWSTR pAssemblyName, const SString &pMessageArg, UINT resIDWhy) : EEException(kTypeLoadException), - m_fullName(fullName), m_pAssemblyName(pAssemblyName), m_pMessageArg(pMessageArg), m_resIDWhy(resIDWhy) { - WRAPPER_NO_CONTRACT; + LIMITED_METHOD_CONTRACT; + fullName.ConvertToUnicode(m_fullName); } @@ -964,7 +967,7 @@ inline EEMessageException::EEMessageException(HRESULT hr) { WRAPPER_NO_CONTRACT; - m_arg1.Printf("%.8x", hr); + m_arg1.Printf(W("%.8x"), hr); } //----------------------------------------------------------------------------- diff --git a/src/coreclr/vm/clrtocomcall.cpp b/src/coreclr/vm/clrtocomcall.cpp index b161c10404dd94..db45e0cabebcc4 100644 --- a/src/coreclr/vm/clrtocomcall.cpp +++ b/src/coreclr/vm/clrtocomcall.cpp @@ -94,9 +94,9 @@ ComPlusCallInfo *ComPlusCall::PopulateComPlusCallMethodDesc(MethodDesc* pMD, DWO // the method does not implement any interface StackSString ssClassName; pMT->_GetFullyQualifiedNameForClass(ssClassName); - StackSString ssMethodName(SString::Utf8, pMD->GetName()); + MAKE_WIDEPTR_FROMUTF8(ssMethodName, pMD->GetName()); - COMPlusThrow(kInvalidOperationException, IDS_EE_COMIMPORT_METHOD_NO_INTERFACE, ssMethodName.GetUnicode(), ssClassName.GetUnicode()); + COMPlusThrow(kInvalidOperationException, IDS_EE_COMIMPORT_METHOD_NO_INTERFACE, (LPCWSTR)ssMethodName, (LPCWSTR)ssClassName); } pComInfo->m_cachedComSlot = pItfMD->GetComSlot(); diff --git a/src/coreclr/vm/clsload.cpp b/src/coreclr/vm/clsload.cpp index 8667c8e905ce08..0550ac2275429b 100644 --- a/src/coreclr/vm/clsload.cpp +++ b/src/coreclr/vm/clsload.cpp @@ -1322,13 +1322,15 @@ bool CompareNameHandleWithTypeHandleNoThrow( // This block is specifically designed to handle transient faults such // as OOM exceptions. CONTRACT_VIOLATION(FaultViolation | ThrowsViolation); - StackSString ssBuiltName; + StackEString ssBuiltName; ns::MakePath(ssBuiltName, - StackSString(SString::Utf8, pName->GetNameSpace()), - StackSString(SString::Utf8, pName->GetName())); + StackEString(pName->GetNameSpace()), + StackEString(pName->GetName())); StackSString ssName; typeHnd.GetName(ssName); - fRet = ssName.Equals(ssBuiltName) == TRUE; + StackSString wssBuiltName; + ssBuiltName.ConvertToUnicode(wssBuiltName); + fRet = ssName.Equals(wssBuiltName) == TRUE; } EX_CATCH { @@ -1745,19 +1747,13 @@ VOID ClassLoader::CreateCanonicallyCasedKey(LPCUTF8 pszNameSpace, LPCUTF8 pszNam } CONTRACTL_END - StackSString nameSpace(SString::Utf8, pszNameSpace); + StackEString nameSpace(pszNameSpace); nameSpace.LowerCase(); + pszNameSpace = nameSpace; - StackScratchBuffer nameSpaceBuffer; - pszNameSpace = nameSpace.GetUTF8(nameSpaceBuffer); - - - StackSString name(SString::Utf8, pszName); + StackEString name(pszName); name.LowerCase(); - - StackScratchBuffer nameBuffer; - pszName = name.GetUTF8(nameBuffer); - + pszName = name; size_t iNSLength = strlen(pszNameSpace); size_t iNameLength = strlen(pszName); @@ -2825,7 +2821,7 @@ TypeHandle ClassLoader::DoIncrementalLoad(TypeKey *pTypeKey, TypeHandle typeHnd, { SString name; TypeString::AppendTypeKeyDebug(name, pTypeKey); - LOG((LF_CLASSLOADER, LL_INFO10000, "PHASEDLOAD: About to do incremental load of type %S (%p) from level %s\n", name.GetUnicode(), typeHnd.AsPtr(), classLoadLevelName[currentLevel])); + LOG((LF_CLASSLOADER, LL_INFO10000, "PHASEDLOAD: About to do incremental load of type %S (%p) from level %s\n", (LPCWSTR)name, typeHnd.AsPtr(), classLoadLevelName[currentLevel])); } #endif @@ -3220,7 +3216,7 @@ TypeHandle ClassLoader::LoadTypeHandleForTypeKey(TypeKey *pTypeKey, { SString name; TypeString::AppendTypeKeyDebug(name, pTypeKey); - LOG((LF_CLASSLOADER, LL_INFO10000, "PHASEDLOAD: LoadTypeHandleForTypeKey for type %S to level %s\n", name.GetUnicode(), classLoadLevelName[targetLevel])); + LOG((LF_CLASSLOADER, LL_INFO10000, "PHASEDLOAD: LoadTypeHandleForTypeKey for type %S to level %s\n", (LPCWSTR)name, classLoadLevelName[targetLevel])); CrstHolder unresolvedClassLockHolder(&m_UnresolvedClassLock); m_pUnresolvedClassHash->Dump(); } diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index 1b7caaef542018..945b6198470d39 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -1895,7 +1895,7 @@ static void LoadAndInitializeJIT(LPCWSTR pwzJitName DEBUGARG(LPCWSTR pwzJitPath) SString sJitName(pwzJitName); CoreClrFolderHolder.Replace(iter + 1, CoreClrFolderHolder.End() - (iter + 1), sJitName); - *phJit = CLRLoadLibrary(CoreClrFolderHolder.GetUnicode()); + *phJit = CLRLoadLibrary(CoreClrFolderHolder); if (*phJit != NULL) { hr = S_OK; diff --git a/src/coreclr/vm/codepitchingmanager.cpp b/src/coreclr/vm/codepitchingmanager.cpp index 6badd9746d44f5..2ef321633c62c7 100644 --- a/src/coreclr/vm/codepitchingmanager.cpp +++ b/src/coreclr/vm/codepitchingmanager.cpp @@ -126,7 +126,7 @@ static COUNT_T GetFullHash(MethodDesc* pMD) COUNT_T hash = HashStringA(moduleName); // Start the hash with the Module name - SString className, methodName, methodSig; + EString className, methodName, methodSig; pMD->GetMethodInfo(className, methodName, methodSig); @@ -229,7 +229,7 @@ static void LookupOrCreateInPitchingCandidate(MethodDesc* pMD, ULONG sizeOfCode) #ifdef _DEBUG if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchPrintStat) != 0) { - SString className, methodName, methodSig; + EString className, methodName, methodSig; pMD->GetMethodInfo(className, methodName, methodSig); StackScratchBuffer scratch; @@ -415,7 +415,7 @@ void MethodDesc::PitchNativeCode() if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchPrintStat) != 0) { - SString className, methodName, methodSig; + EString className, methodName, methodSig; GetMethodInfo(className, methodName, methodSig); StackScratchBuffer scratch; diff --git a/src/coreclr/vm/comcallablewrapper.cpp b/src/coreclr/vm/comcallablewrapper.cpp index 37a763e7b26f0f..f99380a0f3a84a 100644 --- a/src/coreclr/vm/comcallablewrapper.cpp +++ b/src/coreclr/vm/comcallablewrapper.cpp @@ -674,12 +674,10 @@ void SimpleComCallWrapper::BuildRefCountLogMessage(LPCSTR szOperation, StackSStr { EX_TRY { - SString className; - className.SetUTF8(pszClassName); - SString nameSpace; - nameSpace.SetUTF8(pszNamespace); - SString operation; - nameSpace.SetUTF8(szOperation); + MAKE_WIDEPTR_FROMUTF8(classNameUnicode, pszClassName); + MAKE_WIDEPTR_FROMUTF8(namespaceUnicode, pszNamespace); + MAKE_WIDEPTR_FROMUTF8(operationUnicode, szOperation); + FireEtwCCWRefCountChange( handle, @@ -687,7 +685,7 @@ void SimpleComCallWrapper::BuildRefCountLogMessage(LPCSTR szOperation, StackSStr this, dwEstimatedRefCount, NULL, // domain value is not interesting in CoreCLR - className.GetUnicode(), nameSpace.GetUnicode(), operation.GetUnicode(), GetClrInstanceId()); + classNameUnicode, namespaceUnicode, operationUnicode, GetClrInstanceId()); } EX_CATCH { } @@ -698,11 +696,14 @@ void SimpleComCallWrapper::BuildRefCountLogMessage(LPCSTR szOperation, StackSStr { EX_TRY { - ssMessage.Printf("LogCCWRefCountChange[%s]: '%s.%s', Object=poi(%p)", - szOperation, - pszNamespace, - pszClassName, - handle); + StackSString ssClassName; + TypeString::AppendType(ssClassName, TypeHandle(m_pMT)); + MAKE_WIDEPTR_FROMUTF8(wszOperation, szOperation); + + ssMessage.Printf(W("LogCCWRefCountChange[%s]: '%s', Object=poi(%p)"), + wszOperation, // %s operation + (LPCWSTR)ssClassName, // %s type name + handle); // %p Object } EX_CATCH { } @@ -726,8 +727,8 @@ void SimpleComCallWrapper::LogRefCount(ComCallWrapper *pWrap, StackSString &ssMe { EX_TRY { - ssMessage.AppendPrintf(", RefCount=%u\n", dwRefCountToLog); - OutputDebugStringUtf8(ssMessage.GetUTF8NoConvert()); + ssMessage.AppendPrintf(W(", RefCount=%u\n"), dwRefCountToLog); + WszOutputDebugString(ssMessage); } EX_CATCH { } @@ -4171,7 +4172,7 @@ void ComCallWrapperTemplate::CheckParentComVisibility(BOOL fForIDispatch) SString invisParentType; TypeString::AppendType(thisType, m_thClass); TypeString::AppendType(invisParentType, invisParent->m_thClass); - COMPlusThrow(kInvalidOperationException, IDS_EE_COM_INVISIBLE_PARENT, thisType.GetUnicode(), invisParentType.GetUnicode()); + COMPlusThrow(kInvalidOperationException, IDS_EE_COM_INVISIBLE_PARENT, thisType, invisParentType); } } @@ -4775,7 +4776,7 @@ ComCallWrapperTemplate* ComCallWrapperTemplate::CreateTemplate(TypeHandle thClas SString ssName; thClass.GetName(ssName); LOG((LF_CORPROF, LL_INFO100, "COMClassicVTableCreated Class:%ls, IID:%ls, vTbl:%#08x\n", - ssName.GetUnicode(), rIID, pComVtable)); + (LPCWSTR)ssName, rIID, pComVtable)); #else LOG((LF_CORPROF, LL_INFO100, "COMClassicVTableCreated TypeHandle:%#x, IID:{%08x-...}, vTbl:%#08x\n", thClass.AsPtr(), IClassXIID.Data1, pComVtable)); diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 53616e81c0f65a..b03b44ae378e76 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -925,8 +925,9 @@ FCIMPL5(FC_BOOL_RET, COMDelegate::BindToMethodName, // get the name in UTF8 format SString wszName(SString::Literal, gc.methodName->GetBuffer()); - StackScratchBuffer utf8Name; - LPCUTF8 szNameStr = wszName.GetUTF8(utf8Name); + StackEString utf8Name; + wszName.ConvertToUTF8(utf8Name); + LPCUTF8 szNameStr = utf8Name; // pick a proper compare function typedef int (__cdecl *UTF8StringCompareFuncPtr)(const char *, const char *); @@ -2013,16 +2014,16 @@ void COMDelegate::ThrowIfInvalidUnmanagedCallersOnlyUsage(MethodDesc* pMD) CONTRACTL_END; if (!pMD->IsStatic()) - EX_THROW(EEResourceException, (kInvalidProgramException, W("InvalidProgram_NonStaticMethod"))); + EX_THROW(EEResourceException, (kInvalidProgramException, SL(W("InvalidProgram_NonStaticMethod")))); // No generic methods if (pMD->HasClassOrMethodInstantiation()) - EX_THROW(EEResourceException, (kInvalidProgramException, W("InvalidProgram_GenericMethod"))); + EX_THROW(EEResourceException, (kInvalidProgramException, SL(W("InvalidProgram_GenericMethod")))); // Arguments - Scenarios involving UnmanagedCallersOnly are handled during the jit. bool unmanagedCallersOnlyRequiresMarshalling = false; if (NDirect::MarshalingRequired(pMD, NULL, NULL, unmanagedCallersOnlyRequiresMarshalling)) - EX_THROW(EEResourceException, (kInvalidProgramException, W("InvalidProgram_NonBlittableTypes"))); + EX_THROW(EEResourceException, (kInvalidProgramException, SL(W("InvalidProgram_NonBlittableTypes")))); } BOOL COMDelegate::NeedsWrapperDelegate(MethodDesc* pTargetMD) diff --git a/src/coreclr/vm/commodule.cpp b/src/coreclr/vm/commodule.cpp index eeaa33d55091dc..3dc29bc92b8ca1 100644 --- a/src/coreclr/vm/commodule.cpp +++ b/src/coreclr/vm/commodule.cpp @@ -60,7 +60,7 @@ extern "C" mdTypeRef QCALLTYPE ModuleBuilder_GetTypeRef(QCall::ModuleHandle pMod } } - LPCWSTR wszFullNameUnescaped = ssNameUnescaped.GetUnicode(); + LPCWSTR wszFullNameUnescaped = (LPCWSTR)ssNameUnescaped; Assembly * pThisAssembly = pModule->GetClassLoader()->GetAssembly(); Assembly * pRefedAssembly = pRefedModule->GetClassLoader()->GetAssembly(); @@ -662,10 +662,10 @@ static void ReplaceNiExtension(SString& fileName, PCWSTR pwzOldSuffix, PCWSTR pw { STANDARD_VM_CONTRACT; - if (fileName.EndsWithCaseInsensitive(pwzOldSuffix)) + if (fileName.EndsWithCaseInsensitive(SL(pwzOldSuffix))) { COUNT_T oldSuffixLen = (COUNT_T)wcslen(pwzOldSuffix); - fileName.Replace(fileName.End() - oldSuffixLen, oldSuffixLen, pwzNewSuffix); + fileName.Replace(fileName.End() - oldSuffixLen, oldSuffixLen, SL(pwzNewSuffix)); } } diff --git a/src/coreclr/vm/commtmemberinfomap.cpp b/src/coreclr/vm/commtmemberinfomap.cpp index 4b9745317f8231..14e8b119ec03c3 100644 --- a/src/coreclr/vm/commtmemberinfomap.cpp +++ b/src/coreclr/vm/commtmemberinfomap.cpp @@ -87,7 +87,7 @@ class CWStrHash : public CChainedHash } CONTRACTL_END; - return SString::_wcsicmp(reinterpret_cast(pData),reinterpret_cast(pItem)->szName); + return StaticStringHelpers::_wcsicmp(reinterpret_cast(pData),reinterpret_cast(pItem)->szName); } }; // class CWStrHash : public CChainedHash @@ -768,7 +768,7 @@ void ComMTMemberInfoMap::GetMethodPropsForMeth( pName = rName.Ptr(); // If this is a "ToString" method, make it a property get. - if (SString::_wcsicmp(pName, szDefaultToString) == 0) + if (StaticStringHelpers::_wcsicmp(pName, szDefaultToString) == 0) { rProps[ix].semantic = msGetter; rProps[ix].bFunction2Getter = TRUE; @@ -881,14 +881,14 @@ void ComMTMemberInfoMap::EliminateDuplicateNames( if (!rProps[iTst].bMemberVisible) continue; - if (SString::_wcsicmp(rProps[iCur].pName, rProps[iTst].pName) == 0) + if (StaticStringHelpers::_wcsicmp(rProps[iCur].pName, rProps[iTst].pName) == 0) bDup = TRUE; } // If OK with other members, check with base interface names. for (iTst=0; !bDup && iTst(EString::Literal, m_pAssemblyName).ConvertToUnicode(sSimpleName); if (m_context.szLocale != NULL) - SString(SString::Utf8Literal, m_context.szLocale).ConvertToUnicode(sCultureName); + EString(EString::Literal, m_context.szLocale).ConvertToUnicode(sCultureName); hr = BINDER_SPACE::AssemblyBinderCommon::BindToSystemSatellite(sSystemDirectory, sSimpleName, sCultureName, &pPrivAsm); } @@ -156,7 +156,7 @@ STDAPI BinderAcquireImport(PEImage *pPEImage, return hr; } -void BaseAssemblySpec::Init(SString& assemblyDisplayName) +void BaseAssemblySpec::Init(const EString& assemblyDisplayName) { CONTRACTL { @@ -166,7 +166,7 @@ void BaseAssemblySpec::Init(SString& assemblyDisplayName) } CONTRACTL_END; - PCWSTR pAssemblyDisplayName = assemblyDisplayName.GetUnicode(); + MAKE_WIDEPTR_FROMUTF8(pAssemblyDisplayName, assemblyDisplayName); GCX_COOP(); @@ -185,7 +185,7 @@ extern "C" void QCALLTYPE AssemblyName_InitializeAssemblySpec(NativeAssemblyName BEGIN_QCALL; - StackSString ssName; + StackEString ssName; SString(SString::Literal, pAssemblyNameParts->_pName).ConvertToUTF8(ssName); AssemblyMetaDataInternal asmInfo; @@ -195,13 +195,13 @@ extern "C" void QCALLTYPE AssemblyName_InitializeAssemblySpec(NativeAssemblyName asmInfo.usBuildNumber = pAssemblyNameParts->_build; asmInfo.usRevisionNumber = pAssemblyNameParts->_revision; - SmallStackSString ssLocale; + SmallStackEString ssLocale; if (pAssemblyNameParts->_pCultureName != NULL) SString(SString::Literal, pAssemblyNameParts->_pCultureName).ConvertToUTF8(ssLocale); - asmInfo.szLocale = (pAssemblyNameParts->_pCultureName != NULL) ? ssLocale.GetUTF8NoConvert() : NULL; + asmInfo.szLocale = (pAssemblyNameParts->_pCultureName != NULL) ? (LPCUTF8)ssLocale : NULL; // Initialize spec - pAssemblySpec->Init(ssName.GetUTF8NoConvert(), &asmInfo, + pAssemblySpec->Init((LPCUTF8)ssName, &asmInfo, pAssemblyNameParts->_pPublicKeyOrToken, pAssemblyNameParts->_cbPublicKeyOrToken, pAssemblyNameParts->_flags); // Copy and own any fields we do not own @@ -210,7 +210,7 @@ extern "C" void QCALLTYPE AssemblyName_InitializeAssemblySpec(NativeAssemblyName END_QCALL; } -HRESULT BaseAssemblySpec::InitNoThrow(SString& assemblyDisplayName) +HRESULT BaseAssemblySpec::InitNoThrow(const EString& assemblyDisplayName) { CONTRACTL { @@ -346,9 +346,9 @@ VOID BaseAssemblySpec::GetDisplayName(DWORD flags, SString &result) const flags=ASM_DISPLAYF_FULL; BINDER_SPACE::AssemblyIdentity assemblyIdentity; - SString tmpString; + EString tmpString; - tmpString.SetUTF8(m_pAssemblyName); + tmpString.Set(m_pAssemblyName); if ((m_ownedFlags & BAD_NAME_OWNED) != 0) { @@ -376,7 +376,7 @@ VOID BaseAssemblySpec::GetDisplayName(DWORD flags, SString &result) const assemblyIdentity.SetHave(BINDER_SPACE::AssemblyIdentity::IDENTITY_FLAG_CULTURE); if ((m_context.szLocale != NULL) && (m_context.szLocale[0] != 0)) { - tmpString.SetUTF8(m_context.szLocale); + tmpString.Set(m_context.szLocale); tmpString.ConvertToUnicode(assemblyIdentity.m_cultureOrLanguage); } } diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index 68b26039c0543e..f6c07bc1599001 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -272,7 +272,16 @@ void SetCommandLineArgs(LPCWSTR pwzAssemblyPath, int argc, LPCWSTR* argv) GCPROTECT_BEGIN(gc); gc.cmdLineArgs = (PTRARRAYREF)AllocateObjectArray(argc + 1 /* arg[0] should be the exe name*/, g_pStringClass); - OBJECTREF orAssemblyPath = StringObject::NewString(Bundle::AppIsBundle() ? static_cast(Bundle::AppBundle->Path()) : pwzAssemblyPath); + OBJECTREF orAssemblyPath = NULL; + if (Bundle::AppIsBundle()) + { + MAKE_WIDEPTR_FROMUTF8(appBundlePath, Bundle::AppBundle->Path()); + orAssemblyPath = StringObject::NewString(appBundlePath); + } + else + { + orAssemblyPath = StringObject::NewString(pwzAssemblyPath); + } gc.cmdLineArgs->SetAt(0, orAssemblyPath); for (int i = 0; i < argc; ++i) @@ -450,16 +459,14 @@ HRESULT CorHost2::ExecuteInDefaultAppDomain(LPCWSTR pwzAssemblyPath, Assembly *pAssembly = AssemblySpec::LoadAssembly(pwzAssemblyPath); SString szTypeName(pwzTypeName); - StackScratchBuffer buff1; - const char* szTypeNameUTF8 = szTypeName.GetUTF8(buff1); + StackEString typeName(szTypeName.MoveToUTF8()); MethodTable *pMT = ClassLoader::LoadTypeByNameThrowing(pAssembly, NULL, - szTypeNameUTF8).AsMethodTable(); + typeName).AsMethodTable(); SString szMethodName(pwzMethodName); - StackScratchBuffer buff; - const char* szMethodNameUTF8 = szMethodName.GetUTF8(buff); - MethodDesc *pMethodMD = MemberLoader::FindMethod(pMT, szMethodNameUTF8, &gsig_SM_Str_RetInt); + StackEString methodName(szMethodName.MoveToUTF8()); + MethodDesc *pMethodMD = MemberLoader::FindMethod(pMT, methodName, &gsig_SM_Str_RetInt); if (!pMethodMD) { @@ -742,12 +749,13 @@ HRESULT CorHost2::CreateDelegate( MAKE_UTF8PTR_FROMWIDE(szClassName, wszClassName); MAKE_UTF8PTR_FROMWIDE(szMethodName, wszMethodName); + MAKE_UTF8PTR_FROMWIDE(szAssemblyName, wszAssemblyName); { GCX_PREEMP(); AssemblySpec spec; - SString ssAssemblyName(wszAssemblyName); + EString ssAssemblyName(szAssemblyName); spec.Init(ssAssemblyName); Assembly* pAsm=spec.LoadAssembly(FILE_ACTIVE); diff --git a/src/coreclr/vm/customattribute.cpp b/src/coreclr/vm/customattribute.cpp index 00c9150cddd712..ab73f3b2686543 100644 --- a/src/coreclr/vm/customattribute.cpp +++ b/src/coreclr/vm/customattribute.cpp @@ -17,8 +17,6 @@ #include "runtimehandles.h" #include "typestring.h" -typedef InlineFactory, 16> SStringFactory; - /*static*/ TypeHandle Attribute::GetTypeForEnum(LPCUTF8 szEnumName, COUNT_T cbEnumName, DomainAssembly* pDomainAssembly) { @@ -33,9 +31,8 @@ TypeHandle Attribute::GetTypeForEnum(LPCUTF8 szEnumName, COUNT_T cbEnumName, Dom } CONTRACTL_END; - StackScratchBuffer buff; - StackSString sszEnumName(SString::Utf8, szEnumName, cbEnumName); - return TypeName::GetTypeUsingCASearchRules(sszEnumName.GetUTF8(buff), pDomainAssembly->GetAssembly()); + StackEString sszEnumName(szEnumName, cbEnumName); + return TypeName::GetTypeUsingCASearchRules(sszEnumName, pDomainAssembly->GetAssembly()); } /*static*/ @@ -389,12 +386,13 @@ HRESULT Attribute::ParseCaNamedArgs( IfFailGo(Attribute::ParseCaType(ca, pNamedArgType, pDomainAssembly, &ss)); LPCSTR szLoadedEnumName = NULL; - StackScratchBuffer buff; + StackEString buff; if (pNamedArgType->tag == SERIALIZATION_TYPE_ENUM || (pNamedArgType->tag == SERIALIZATION_TYPE_SZARRAY && pNamedArgType->arrayType == SERIALIZATION_TYPE_ENUM )) { - szLoadedEnumName = ss.GetUTF8(buff); + ss.ConvertToUTF8(buff); + szLoadedEnumName = buff; } // Get name of Arg. @@ -471,7 +469,7 @@ HRESULT Attribute::ParseCaNamedArgs( } /*static*/ -HRESULT Attribute::InitCaType(CustomAttributeType* pType, Factory* pSstringFactory, Factory* pStackScratchBufferFactory, CaType* pCaType) +HRESULT Attribute::InitCaType(CustomAttributeType* pType, Factory* pSstringFactory, Factory>* pStackScratchBufferFactory, CaType* pCaType) { CONTRACTL { THROWS; @@ -484,18 +482,20 @@ HRESULT Attribute::InitCaType(CustomAttributeType* pType, Factory* pSst HRESULT hr = S_OK; SString* psszName = NULL; - StackScratchBuffer* scratchBuffer = NULL; + EString* scratchBuffer = NULL; IfNullGo(psszName = pSstringFactory->Create()); IfNullGo(scratchBuffer = pStackScratchBufferFactory->Create()); psszName->Set(pType->m_enumName == NULL ? NULL : pType->m_enumName->GetBuffer()); + psszName->ConvertToUTF8(*scratchBuffer); + pCaType->Init( pType->m_tag, pType->m_arrayType, pType->m_enumType, - psszName->GetUTF8(*scratchBuffer), + *scratchBuffer, (ULONG)psszName->GetCount()); ErrExit: @@ -539,7 +539,7 @@ FCIMPL5(VOID, Attribute::ParseAttributeArguments, void* pCa, INT32 cCa, // on what we can allocate inline here. Leave the Windows versions alone to retain the perf benefits // since we don't have the same constraints. NewHolder pCaValueArrayFactory = new InlineFactory, 4>(); - InlineFactory stackScratchBufferFactory; + InlineFactory, 4> utf8EStringFactory; InlineFactory sstringFactory; #else // __GNUC__ @@ -552,10 +552,8 @@ FCIMPL5(VOID, Attribute::ParseAttributeArguments, void* pCa, INT32 cCa, InlineFactory, 4> caValueArrayFactory; InlineFactory, 4> *pCaValueArrayFactory = &caValueArrayFactory; - // Need one StackScratchBuffer per ctor arg and two per named arg - InlineFactory stackScratchBufferFactory; - - // Need one SString per ctor arg and two per named arg + // Need one EString per ctor arg and two per named arg + InlineFactory, 4> utf8EStringFactory; InlineFactory sstringFactory; #endif // __GNUC__ @@ -573,7 +571,7 @@ FCIMPL5(VOID, Attribute::ParseAttributeArguments, void* pCa, INT32 cCa, for (COUNT_T i = 0; i < cArgs; i ++) { CaType caType; - IfFailGo(Attribute::InitCaType(&gc.pArgs[i].m_type, &sstringFactory, &stackScratchBufferFactory, &caType)); + IfFailGo(Attribute::InitCaType(&gc.pArgs[i].m_type, &sstringFactory, &utf8EStringFactory, &caType)); pCaArgs[i].Init(caType); } @@ -595,18 +593,19 @@ FCIMPL5(VOID, Attribute::ParseAttributeArguments, void* pCa, INT32 cCa, CustomAttributeNamedArgument* pNamedArg = &gc.pNamedArgs[i]; CaType caType; - IfFailGo(Attribute::InitCaType(&pNamedArg->m_type, &sstringFactory, &stackScratchBufferFactory, &caType)); + IfFailGo(Attribute::InitCaType(&pNamedArg->m_type, &sstringFactory, &utf8EStringFactory, &caType)); SString* psszName = NULL; IfNullGo(psszName = sstringFactory.Create()); psszName->Set(pNamedArg->m_argumentName->GetBuffer()); - StackScratchBuffer* scratchBuffer = NULL; - IfNullGo(scratchBuffer = stackScratchBufferFactory.Create()); + EString* scratchBuffer = NULL; + IfNullGo(scratchBuffer = utf8EStringFactory.Create()); + psszName->ConvertToUTF8(*scratchBuffer); pCaNamedArgs[i].Init( - psszName->GetUTF8(*scratchBuffer), + *scratchBuffer, pNamedArg->m_propertyOrField, caType); } diff --git a/src/coreclr/vm/customattribute.h b/src/coreclr/vm/customattribute.h index ac95fa80af9952..c61f4917ad38a0 100644 --- a/src/coreclr/vm/customattribute.h +++ b/src/coreclr/vm/customattribute.h @@ -139,7 +139,7 @@ class Attribute static HRESULT InitCaType( CustomAttributeType* pType, Factory* pSstringFactory, - Factory* pStackScratchBufferFactory, + Factory>* pStackScratchBufferFactory, CaType* pCaType); static HRESULT ParseCaType( diff --git a/src/coreclr/vm/debugdebugger.cpp b/src/coreclr/vm/debugdebugger.cpp index 46d5b81631c714..819c81dd7f36c4 100644 --- a/src/coreclr/vm/debugdebugger.cpp +++ b/src/coreclr/vm/debugdebugger.cpp @@ -261,7 +261,7 @@ extern "C" void QCALLTYPE DebugDebugger_Log(INT32 Level, PCWSTR pwzModule, PCWST { if (IsLoggingHelper() ) { - // Copy log message and category into our own SString to protect against GC + // Copy log message and category into our own EString to protect against GC // Strings may contain embedded nulls, but we need to handle null-terminated // strings, so use truncate now. StackSString switchName; diff --git a/src/coreclr/vm/disassembler.cpp b/src/coreclr/vm/disassembler.cpp index 51c48a112655e9..373e3767d97735 100644 --- a/src/coreclr/vm/disassembler.cpp +++ b/src/coreclr/vm/disassembler.cpp @@ -85,7 +85,7 @@ namespace libPath.Append(sysDirectory); libPath.Append(libFileName); - LPCWSTR libraryName = libPath.GetUnicode(); + LPCWSTR libraryName = (LPCWSTR)libPath; return CLRLoadLibrary(libraryName); } } diff --git a/src/coreclr/vm/dispatchinfo.cpp b/src/coreclr/vm/dispatchinfo.cpp index 676162b2ebccd4..c98544ced267c5 100644 --- a/src/coreclr/vm/dispatchinfo.cpp +++ b/src/coreclr/vm/dispatchinfo.cpp @@ -222,7 +222,7 @@ HRESULT DispatchMemberInfo::GetIDsOfParameters(_In_reads_(NumNames) WCHAR **astr aDispIds[cNames] = DISPID_UNKNOWN; // Retrieve the appropriate string comparation function. - UnicodeStringCompareFuncPtr StrCompFunc = bCaseSensitive ? wcscmp : SString::_wcsicmp; + UnicodeStringCompareFuncPtr StrCompFunc = bCaseSensitive ? wcscmp : StaticStringHelpers::_wcsicmp; GCPROTECT_BEGIN(ParamArray) { @@ -1761,7 +1761,7 @@ void DispatchInfo::InvokeMemberWorker(DispatchMemberInfo* pDispMemberInfo, } else { - pObjs->MemberName = (OBJECTREF)StringObject::NewString(pDispMemberInfo->m_strName.GetUnicode()); + pObjs->MemberName = (OBJECTREF)StringObject::NewString(pDispMemberInfo->m_strName); } // If there are named arguments, then set up the array of named arguments diff --git a/src/coreclr/vm/dispatchinfo.h b/src/coreclr/vm/dispatchinfo.h index 623a56c7ab0c5e..e64286dc7515bf 100644 --- a/src/coreclr/vm/dispatchinfo.h +++ b/src/coreclr/vm/dispatchinfo.h @@ -181,7 +181,7 @@ struct DispatchMemberInfo DispParamMarshaler** m_apParamMarshaler; BOOL* m_pParamInOnly; DispatchMemberInfo* m_pNext; - SString m_strName; + SString m_strName; EnumMemberTypes m_enumType; int m_iNumParams; CultureAwareStates m_CultureAwareState; diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index dceb6f6b89f7fe..8bf334cdfa8aed 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -925,12 +925,11 @@ class ILStubState : public StubState } // - // Truncates a SString by first converting it to unicode and truncate it + // Truncates a EString by first converting it to unicode and truncate it // if it is larger than size. "..." will be appended if it is truncated. // void TruncateUnicodeString(SString &string, COUNT_T bufSize) { - string.Normalize(); if ((string.GetCount() + 1) * sizeof(WCHAR) > bufSize) { _ASSERTE(bufSize / sizeof(WCHAR) > 4); @@ -958,7 +957,8 @@ class ILStubState : public StubState // Interop Method Information // MethodDesc *pTargetMD = m_slIL.GetTargetMD(); - SString strNamespaceOrClassName, strMethodName, strMethodSignature; + SString strNamespaceOrClassName; + EString strMethodName, strMethodSignature; UINT64 uModuleId = 0; if (pTargetMD) @@ -970,7 +970,8 @@ class ILStubState : public StubState // // Stub Method Signature // - SString stubNamespaceOrClassName, stubMethodName, stubMethodSignature; + SString stubNamespaceOrClassName; + EString stubMethodName, stubMethodSignature; pStubMD->GetMethodInfoWithNewSig(stubNamespaceOrClassName, stubMethodName, stubMethodSignature); IMDInternalImport *pStubImport = pStubMD->GetModule()->GetMDImport(); @@ -978,12 +979,12 @@ class ILStubState : public StubState CQuickBytes qbLocal; PrettyPrintSig(pbLocalSig, (DWORD)cbSig, NULL, &qbLocal, pStubImport, NULL); - SString strLocalSig(SString::Utf8, (LPCUTF8)qbLocal.Ptr()); + EString strLocalSig((LPCUTF8)qbLocal.Ptr()); // // Native Signature // - SString strNativeSignature; + EString strNativeSignature {}; if (m_dwStubFlags & NDIRECTSTUB_FL_REVERSE_INTEROP) { // Reverse interop. Use StubSignature @@ -999,18 +1000,18 @@ class ILStubState : public StubState PrettyPrintSig(pCallTargetSig, cCallTargetSig, "", &qbCallTargetSig, pStubImport, NULL); - strNativeSignature.SetUTF8((LPCUTF8)qbCallTargetSig.Ptr()); + strNativeSignature.Set((LPCUTF8)qbCallTargetSig.Ptr()); } // // Dump IL stub code // - SString strILStubCode; + EString strILStubCode; strILStubCode.Preallocate(4096); // Preallocate 4K bytes to avoid unnecessary growth strILStubCode.AppendPrintf("// Code size\t%d (0x%04x)\n", cbCode, cbCode); strILStubCode.AppendPrintf(".maxstack %d \n", maxStack); - strILStubCode.AppendPrintf(".locals %s\n", strLocalSig.GetUTF8NoConvert()); + strILStubCode.AppendPrintf(".locals %s\n", (LPCUTF8)strLocalSig); m_slIL.LogILStub(jitFlags, &strILStubCode); @@ -1061,12 +1062,19 @@ class ILStubState : public StubState // // Truncate string fields. Make sure the whole event is less than 64KB // + + SString strMethodNameW, strMethodSignatureW, strNativeSignatureW, stubMethodSignatureW, strILStubCodeW; + strMethodName.ConvertToUnicode(strMethodNameW); + strMethodSignature.ConvertToUnicode(strMethodSignatureW); + strNativeSignature.ConvertToUnicode(strNativeSignatureW); + stubMethodSignature.ConvertToUnicode(stubMethodSignatureW); + strILStubCode.ConvertToUnicode(strILStubCodeW); TruncateUnicodeString(strNamespaceOrClassName, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE); - TruncateUnicodeString(strMethodName, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE); - TruncateUnicodeString(strMethodSignature, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE); - TruncateUnicodeString(strNativeSignature, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE); - TruncateUnicodeString(stubMethodSignature, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE); - TruncateUnicodeString(strILStubCode, ETW_IL_STUB_EVENT_CODE_STRING_FIELD_MAXSIZE); + TruncateUnicodeString(strMethodNameW, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE); + TruncateUnicodeString(strMethodSignatureW, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE); + TruncateUnicodeString(strNativeSignatureW, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE); + TruncateUnicodeString(stubMethodSignatureW, ETW_IL_STUB_EVENT_STRING_FIELD_MAXSIZE); + TruncateUnicodeString(strILStubCodeW, ETW_IL_STUB_EVENT_CODE_STRING_FIELD_MAXSIZE); // // Fire ETW event @@ -1077,12 +1085,12 @@ class ILStubState : public StubState (UINT64)pStubMD, // StubMethodIdentifier dwFlags, // StubFlags dwToken, // ManagedInteropMethodToken - strNamespaceOrClassName.GetUnicode(), // ManagedInteropMethodNamespace - strMethodName.GetUnicode(), // ManagedInteropMethodName - strMethodSignature.GetUnicode(), // ManagedInteropMethodSignature - strNativeSignature.GetUnicode(), // NativeSignature - stubMethodSignature.GetUnicode(), // StubMethodSigature - strILStubCode.GetUnicode() // StubMethodILCode + (LPCWSTR)strNamespaceOrClassName, // ManagedInteropMethodNamespace + (LPCWSTR)strMethodNameW, // ManagedInteropMethodName + (LPCWSTR)strMethodSignatureW, // ManagedInteropMethodSignature + (LPCWSTR)strNativeSignatureW, // NativeSignature + (LPCWSTR)stubMethodSignatureW, // StubMethodSigature + (LPCWSTR)strILStubCodeW // StubMethodILCode ); } // EtwOnILStubGenerated #endif // DACCESS_COMPILE @@ -4518,14 +4526,16 @@ HRESULT FindPredefinedILStubMethod(MethodDesc *pTargetMD, DWORD dwStubFlags, Met ULONG cbMethodName; IfFailRet(parser.GetNonEmptyString(&pMethodName, &cbMethodName)); - StackSString typeName(SString::Utf8, pTypeName, cbTypeName); - StackSString methodName(SString::Utf8, pMethodName, cbMethodName); + StackSString typeName; + EString(pTypeName, cbTypeName).ConvertToUnicode(typeName); + StackSString methodName; + EString(pMethodName, cbMethodName).ConvertToUnicode(methodName); // // Retrieve the type // TypeHandle stubClassType; - stubClassType = TypeName::GetTypeUsingCASearchRules(typeName.GetUnicode(), pTargetMT->GetAssembly()); + stubClassType = TypeName::GetTypeUsingCASearchRules((LPCWSTR)typeName, pTargetMT->GetAssembly()); MethodTable *pStubClassMT = stubClassType.AsMethodTable(); @@ -4541,8 +4551,8 @@ HRESULT FindPredefinedILStubMethod(MethodDesc *pTargetMD, DWORD dwStubFlags, Met COMPlusThrow( kArgumentException, IDS_EE_INTEROP_STUB_CA_MUST_BE_WITHIN_SAME_ASSEMBLY, - stubClassName.GetUnicode(), - targetInterfaceName.GetUnicode() + (LPCWSTR)stubClassName, + (LPCWSTR)targetInterfaceName ); } @@ -4551,7 +4561,7 @@ HRESULT FindPredefinedILStubMethod(MethodDesc *pTargetMD, DWORD dwStubFlags, Met COMPlusThrow( kArgumentException, IDS_EE_INTEROP_STUB_CA_STUB_CLASS_MUST_NOT_BE_GENERIC, - stubClassName.GetUnicode() + (LPCWSTR)stubClassName ); } @@ -4560,7 +4570,7 @@ HRESULT FindPredefinedILStubMethod(MethodDesc *pTargetMD, DWORD dwStubFlags, Met COMPlusThrow( kArgumentException, IDS_EE_INTEROP_STUB_CA_STUB_CLASS_MUST_NOT_BE_INTERFACE, - stubClassName.GetUnicode() + (LPCWSTR)stubClassName ); } @@ -4628,10 +4638,8 @@ HRESULT FindPredefinedILStubMethod(MethodDesc *pTargetMD, DWORD dwStubFlags, Met // // Find method using name + signature // - StackScratchBuffer buffer; - LPCUTF8 szMethodNameUTF8 = methodName.GetUTF8(buffer); pStubMD = MemberLoader::FindMethod(stubClassType.GetMethodTable(), - szMethodNameUTF8, + pMethodName, pStubSig, pcStubSig, pTargetMT->GetModule()); @@ -4643,21 +4651,24 @@ HRESULT FindPredefinedILStubMethod(MethodDesc *pTargetMD, DWORD dwStubFlags, Met PrettyPrintSig( pStubSig, pcStubSig, - szMethodNameUTF8, + pMethodName, &qbSig, pTargetMD->GetMDImport(), NULL); // Unfortunately the PrettyPrintSig doesn't print 'static' when the function is static // so we need to append 'static' here. No need to localize - SString signature(SString::Utf8, (LPCUTF8)"static "); - signature.AppendUTF8((LPCUTF8) qbSig.Ptr()); + EString signature((LPCUTF8)"static "); + signature.Append((LPCUTF8) qbSig.Ptr()); + + SString sigW; + signature.ConvertToUnicode(sigW); COMPlusThrow( kMissingMethodException, IDS_EE_INTEROP_STUB_CA_STUB_METHOD_MISSING, - signature.GetUnicode(), - stubClassName.GetUnicode() + (LPCWSTR)sigW, + (LPCWSTR)stubClassName ); } @@ -4681,13 +4692,12 @@ HRESULT FindPredefinedILStubMethod(MethodDesc *pTargetMD, DWORD dwStubFlags, Met pStubMD, NULL)) { - StackSString interopMethodName(SString::Utf8, pTargetMD->GetName()); - + MAKE_WIDEPTR_FROMUTF8(interopMethodName, pTargetMD->GetName()); COMPlusThrow( kMethodAccessException, IDS_EE_INTEROP_STUB_CA_NO_ACCESS_TO_STUB_METHOD, - interopMethodName.GetUnicode(), - methodName.GetUnicode() + (LPCWSTR)interopMethodName, + (LPCWSTR)methodName ); } @@ -4930,7 +4940,7 @@ namespace _ASSERTE(pSigDesc->m_pMT != nullptr); StackSString strTypeName; TypeString::AppendType(strTypeName, TypeHandle(pSigDesc->m_pMT)); - COMPlusThrow(kTypeLoadException, IDS_CANNOT_MARSHAL_RECURSIVE_DEF, strTypeName.GetUnicode()); + COMPlusThrow(kTypeLoadException, IDS_CANNOT_MARSHAL_RECURSIVE_DEF, (LPCWSTR)strTypeName); } UNREACHABLE_MSG("unexpected deadlock in IL stub generation!"); } @@ -4965,7 +4975,7 @@ namespace _ASSERTE(pSigDesc->m_pMT != nullptr); StackSString strTypeName; TypeString::AppendType(strTypeName, TypeHandle(pSigDesc->m_pMT)); - COMPlusThrow(kTypeLoadException, IDS_CANNOT_MARSHAL_RECURSIVE_DEF, strTypeName.GetUnicode()); + COMPlusThrow(kTypeLoadException, IDS_CANNOT_MARSHAL_RECURSIVE_DEF, (LPCWSTR)strTypeName); } UNREACHABLE_MSG("unexpected deadlock in IL stub generation!"); } @@ -5487,7 +5497,7 @@ namespace if (!fSuccess) { - StackSString ssLibName(SString::Utf8, pMD->GetLibName()); + MAKE_WIDEPTR_FROMUTF8(wsLibName, pMD->GetLibName()); WCHAR wszEPName[50]; if (WszMultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pMD->GetEntrypointName(), -1, wszEPName, sizeof(wszEPName)/sizeof(WCHAR)) == 0) @@ -5496,9 +5506,9 @@ namespace wszEPName[1] = W('\0'); } #ifdef TARGET_UNIX - COMPlusThrow(kEntryPointNotFoundException, IDS_EE_NDIRECT_GETPROCADDRESS_UNIX, ssLibName.GetUnicode(), wszEPName); + COMPlusThrow(kEntryPointNotFoundException, IDS_EE_NDIRECT_GETPROCADDRESS_UNIX, (LPCWSTR)wsLibName, wszEPName); #else - COMPlusThrow(kEntryPointNotFoundException, IDS_EE_NDIRECT_GETPROCADDRESS_WIN, ssLibName.GetUnicode(), wszEPName); + COMPlusThrow(kEntryPointNotFoundException, IDS_EE_NDIRECT_GETPROCADDRESS_WIN, (LPCWSTR)wsLibName, wszEPName); #endif } } diff --git a/src/coreclr/vm/dllimportcallback.cpp b/src/coreclr/vm/dllimportcallback.cpp index 65d2afd7d05128..659eb42468d238 100644 --- a/src/coreclr/vm/dllimportcallback.cpp +++ b/src/coreclr/vm/dllimportcallback.cpp @@ -304,20 +304,20 @@ VOID __fastcall UMEntryThunk::ReportViolation(UMEntryThunk* pEntryThunk) MethodDesc* pMethodDesc = pEntryThunk->GetMethod(); SString namespaceOrClassName; - SString methodName; - SString moduleName; + EString methodName; + EString moduleName; pMethodDesc->GetMethodInfoNoSig(namespaceOrClassName, methodName); - moduleName.SetUTF8(pMethodDesc->GetModule()->GetSimpleName()); + moduleName.Set(pMethodDesc->GetModule()->GetSimpleName()); SString message; - message.Printf(W("A callback was made on a garbage collected delegate of type '%s!%s::%s'."), - moduleName.GetUnicode(), - namespaceOrClassName.GetUnicode(), - methodName.GetUnicode()); + message.Printf(W("A callback was made on a garbage collected delegate of type '%S!%s::%S'."), + (LPCSTR)moduleName, + (LPCWSTR)namespaceOrClassName, + (LPCSTR)methodName); - EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_FAILFAST, message.GetUnicode()); + EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_FAILFAST, (LPCWSTR)message); } UMThunkMarshInfo::~UMThunkMarshInfo() diff --git a/src/coreclr/vm/dwbucketmanager.hpp b/src/coreclr/vm/dwbucketmanager.hpp index 6eb0e9438b5f32..a76533584dbe17 100644 --- a/src/coreclr/vm/dwbucketmanager.hpp +++ b/src/coreclr/vm/dwbucketmanager.hpp @@ -963,7 +963,7 @@ bool BaseBucketParamsManager::GetFileVersionInfoForModule(Module* pModule, USHOR // if we failed to get the version info from the native image then fall back to the IL image. if (!succeeded) { - LPCWSTR modulePath = pPEAssembly->GetPath().GetUnicode(); + LPCWSTR modulePath = pPEAssembly->GetPath(); if (modulePath != NULL && modulePath != SString::Empty() && SUCCEEDED(DwGetFileVersionInfo(modulePath, major, minor, build, revision))) { succeeded = true; @@ -1107,7 +1107,7 @@ int BaseBucketParamsManager::CopyStringToBucket(_Out_writes_(targetMaxLength) LP if (slen < srcLen) { // maybe -- check. - if (SString::_wcsicmp(&pSource[srcLen - slen], truncations[i]) == 0) + if (StaticStringHelpers::_wcsicmp(&pSource[srcLen - slen], truncations[i]) == 0) { // yes, the string does have this suffix. drop it. srcLen -= slen; diff --git a/src/coreclr/vm/dwreport.cpp b/src/coreclr/vm/dwreport.cpp index 2e05f131cdf34d..034daa30762d71 100644 --- a/src/coreclr/vm/dwreport.cpp +++ b/src/coreclr/vm/dwreport.cpp @@ -160,136 +160,6 @@ HRESULT DwGetFileVersionInfo( return result; } -// Read the description from the resource section. -// -// Parameters -// wszFilePath Path to a file from which to extract the description -// pBuf [out] Put description here. -// cchBuf [in] Size of buf, wide chars. -// -// Returns -// The number of characters stored. Zero if error or no description. -// -// Exceptions -// None -//------------------------------------------------------------------------------ -int DwGetAppDescription( // Number of characters written. - _In_z_ LPCWSTR wszFilePath, // Path to the executable. - SString& pBuf // Put description here. - ) // Size of buf, wide chars. -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - - DWORD dwHandle = 0; - DWORD bufSize = 0; // Size of allocation for VersionInfo. - DWORD ret; - - // Find the buffer size for the version info structure we need to create - EX_TRY - { - bufSize = GetFileVersionInfoSizeW(wszFilePath, &dwHandle); - } - EX_CATCH - { - bufSize = 0; - } - EX_END_CATCH(SwallowAllExceptions); - - if (!bufSize) - { - return 0; - } - - // Allocate the buffer for the version info structure - // _alloca() can't return NULL -- raises STATUS_STACK_OVERFLOW. - BYTE* pVersionInfoBuffer = reinterpret_cast< BYTE* >(_alloca(bufSize)); - - // Extract the version information blob. The version information - // contains much more than the actual item of interest. - { - // If the previoud GetFileVersionInfoSizeW succeeds, version.dll has been loaded - // in the process, and delay load of GetFileVersionInfoW will not throw. - CONTRACT_VIOLATION(ThrowsViolation); - ret = GetFileVersionInfoW(wszFilePath, dwHandle, bufSize, pVersionInfoBuffer); - } - - if (!ret) - { - return 0; - } - - // Extract the description. - - // Get the language and codepage for the version info. - UINT size = 0; - struct - { - WORD language; - WORD codePage; - }* translation; - - { - // If the previoud GetFileVersionInfoSizeW succeeds, version.dll has been loaded - // in the process, and delay load of GetFileVersionInfoW will not throw. - CONTRACT_VIOLATION(ThrowsViolation); - ret = VerQueryValueW(pVersionInfoBuffer, W("\\VarFileInfo\\Translation"), - reinterpret_cast< void **>(&translation), &size); - } - - if (!ret || size == 0) - { - return 0; - } - - // Build the query key for the language-specific file description resource. - WCHAR buf[64]; //----+----1----+----2----+----3----+----4----+ - _snwprintf_s(buf, ARRAY_SIZE(buf), _TRUNCATE, W("\\StringFileInfo\\%04x%04x\\FileDescription"), - translation->language, translation->codePage); - - // Get the file description. - WCHAR* fileDescription; - { - // If the previoud GetFileVersionInfoSizeW succeeds, version.dll has been loaded - // in the process, and delay load of GetFileVersionInfoW will not throw. - CONTRACT_VIOLATION(ThrowsViolation); - ret = VerQueryValueW(pVersionInfoBuffer, buf, - reinterpret_cast< void** >(&fileDescription), &size); - } - - // If the call failed, or there is no file description, done. - if (!ret || size == 0) - { - return 0; - } - - // If the description is a single space, ignore it. - if (wcscmp(fileDescription, W(" ")) == 0) - { - return 0; - } - - // Copy back the description. - EX_TRY - { - wcsncpy_s(pBuf.OpenUnicodeBuffer(size), size, fileDescription, size); - pBuf.CloseBuffer(size); - } - EX_CATCH - { - size = 0; - } - EX_END_CATCH(SwallowAllExceptions); - - - return size; -} // int DwGetAppDescription() - //------------------------------------------------------------------------------ // Description // Extract the assembly version from an executable. diff --git a/src/coreclr/vm/eeconfig.cpp b/src/coreclr/vm/eeconfig.cpp index 3b4ad3176e6dac..f8370270534db9 100644 --- a/src/coreclr/vm/eeconfig.cpp +++ b/src/coreclr/vm/eeconfig.cpp @@ -381,9 +381,9 @@ HRESULT EEConfig::sync() { // just keep the name LPCWSTR pwszName = wcsrchr(wszFileName, W('\\')); - pwszName = (pwszName == NULL) ? wszFileName.GetUnicode() : (pwszName + 1); + pwszName = (pwszName == NULL) ? (LPCWSTR)wszFileName : (pwszName + 1); - if (SString::_wcsicmp(pwszName,pszGCStressExe) == 0) + if (StaticStringHelpers::_wcsicmp(pwszName,pszGCStressExe) == 0) { bGCStressAndHeapVerifyAllowed = true; } diff --git a/src/coreclr/vm/eedbginterfaceimpl.cpp b/src/coreclr/vm/eedbginterfaceimpl.cpp index 5d2edfb2c02929..28ae25d126fe3b 100644 --- a/src/coreclr/vm/eedbginterfaceimpl.cpp +++ b/src/coreclr/vm/eedbginterfaceimpl.cpp @@ -1229,8 +1229,8 @@ bool EEDbgInterfaceImpl::TraceFrame(Thread *thread, { SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE; FAULT_NOT_FATAL(); - SString buffer; - StubManager::DbgWriteLog(" td=%S\n", trace->DbgToString(buffer)); + EString buffer; + StubManager::DbgWriteLog(" td=%s\n", trace->DbgToString(buffer)); } else { @@ -1275,8 +1275,8 @@ bool EEDbgInterfaceImpl::TraceManager(Thread *thread, { // Should never be on helper thread FAULT_NOT_FATAL(); - SString buffer; - StubManager::DbgWriteLog(" td=%S\n", trace->DbgToString(buffer)); + EString buffer; + StubManager::DbgWriteLog(" td=%s\n", trace->DbgToString(buffer)); } else { diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index a1c909128adda2..d2897427955b8e 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -234,7 +234,7 @@ class CallStackLogger MethodDesc* pMD = m_frames[index]; TypeString::AppendMethodInternal(str, pMD, TypeString::FormatNamespace|TypeString::FormatFullInst|TypeString::FormatSignature); - PrintToStdErrW(str.GetUnicode()); + PrintToStdErrW((LPCWSTR)str); PrintToStdErrA("\n"); } @@ -256,9 +256,9 @@ class CallStackLogger if (m_largestCommonStartLength != 0) { SmallStackSString repeatStr; - repeatStr.AppendPrintf("Repeat %d times:\n", m_largestCommonStartRepeat); + repeatStr.AppendPrintf(W("Repeat %d times:\n"), m_largestCommonStartRepeat); - PrintToStdErrW(repeatStr.GetUnicode()); + PrintToStdErrW((LPCWSTR)repeatStr); PrintToStdErrA("--------------------------------\n"); for (int i = 0; i < m_largestCommonStartLength; i++) { @@ -290,7 +290,7 @@ inline void LogCallstackForLogWorker(Thread* pThread) SmallStackSString WordAt; - if (!WordAt.LoadResource(CCompRC::Optional, IDS_ER_WORDAT)) + if (!LoadResource(WordAt, CCompRC::Optional, IDS_ER_WORDAT)) { WordAt.Set(W(" at")); } @@ -298,13 +298,13 @@ inline void LogCallstackForLogWorker(Thread* pThread) { WordAt.Insert(WordAt.Begin(), W(" ")); } - WordAt += W(" "); + WordAt += SL(W(" ")); CallStackLogger logger; pThread->StackWalkFrames(&CallStackLogger::LogCallstackForLogCallback, &logger, QUICKUNWIND | FUNCTIONSONLY | ALLOW_ASYNC_STACK_WALK); - logger.PrintStackTrace(WordAt.GetUnicode()); + logger.PrintStackTrace((LPCWSTR)WordAt); } @@ -460,9 +460,9 @@ void EEPolicy::LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage else { // Fetch the localized Fatal Execution Engine Error text or fall back on a hardcoded variant if things get dire. - InlineSString<80> ssMessage; - InlineSString<80> ssErrorFormat; - if(!ssErrorFormat.LoadResource(CCompRC::Optional, IDS_ER_UNMANAGEDFAILFASTMSG )) + InlineEString<80, EncodingUnicode> ssMessage; + InlineEString<80, EncodingUnicode> ssErrorFormat; + if(!LoadResource(ssErrorFormat, CCompRC::Optional, IDS_ER_UNMANAGEDFAILFASTMSG )) ssErrorFormat.Set(W("at IP 0x%x (0x%x) with exit code 0x%x.")); SmallStackSString addressString; addressString.Printf(W("%p"), pExceptionInfo? (PVOID)pExceptionInfo->ExceptionRecord->ExceptionAddress : (PVOID)address); diff --git a/src/coreclr/vm/encee.cpp b/src/coreclr/vm/encee.cpp index 301101d7a1f510..bbbd5e1773968f 100644 --- a/src/coreclr/vm/encee.cpp +++ b/src/coreclr/vm/encee.cpp @@ -138,12 +138,12 @@ HRESULT EditAndContinueModule::ApplyEditAndContinue( int ec; fn.Printf(W("ApplyChanges.%d.dmeta"), m_applyChangesCount); FILE *fp; - ec = _wfopen_s(&fp, fn.GetUnicode(), W("wb")); + ec = _wfopen_s(&fp, (LPCWSTR)fn, W("wb")); _ASSERTE(SUCCEEDED(ec)); fwrite(pDeltaMD, 1, cbDeltaMD, fp); fclose(fp); fn.Printf(W("ApplyChanges.%d.dil"), m_applyChangesCount); - ec = _wfopen_s(&fp, fn.GetUnicode(), W("wb")); + ec = _wfopen_s(&fp, (LPCWSTR)fn, W("wb")); _ASSERTE(SUCCEEDED(ec)); fwrite(pDeltaIL, 1, cbDeltaIL, fp); fclose(fp); @@ -557,7 +557,7 @@ PCODE EditAndContinueModule::JitUpdatedFunction( MethodDesc *pMD, } EX_CATCH { #ifdef _DEBUG { - // This is debug-only code to print out the error string, but SString can throw. + // This is debug-only code to print out the error string, but EString can throw. // This function is no-throw, and we can't put an EX_TRY inside an EX_CATCH block, so // we just have the violation. CONTRACT_VIOLATION(ThrowsViolation); @@ -565,12 +565,12 @@ PCODE EditAndContinueModule::JitUpdatedFunction( MethodDesc *pMD, StackSString exceptionMessage; SString errorMessage; GetExceptionMessage(GET_THROWABLE(), exceptionMessage); - errorMessage.AppendASCII("**Error: Probable rude edit.**\n\n" - "EnCModule::JITUpdatedFunction JIT failed with the following exception:\n\n"); + errorMessage.Append(W("**Error: Probable rude edit.**\n\n") + W("EnCModule::JITUpdatedFunction JIT failed with the following exception:\n\n")); errorMessage.Append(exceptionMessage); - StackScratchBuffer buffer; - DbgAssertDialog(__FILE__, __LINE__, errorMessage.GetANSI(buffer)); - LOG((LF_ENC, LL_INFO100, errorMessage.GetANSI(buffer))); + EString buffer(errorMessage.MoveToUTF8()); + DbgAssertDialog(__FILE__, __LINE__, buffer); + LOG((LF_ENC, LL_INFO100, (LPCUTF8)buffer)); } #endif } EX_END_CATCH(SwallowAllExceptions) diff --git a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h index 6c35c8fa501982..ae06a8e27cdafa 100644 --- a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h @@ -1369,10 +1369,9 @@ ep_rt_method_get_full_name ( EX_TRY { SString method_name; - StackScratchBuffer conversion; - TypeString::AppendMethodInternal (method_name, method, TypeString::FormatNamespace | TypeString::FormatSignature); - const ep_char8_t *method_name_utf8 = method_name.GetUTF8 (conversion); + EString conversion(method_name.MoveToUTF8()); + const ep_char8_t *method_name_utf8 = conversion; if (method_name_utf8) { size_t method_name_utf8_len = strlen (method_name_utf8) + 1; size_t to_copy = method_name_utf8_len < name_len ? method_name_utf8_len : name_len; diff --git a/src/coreclr/vm/eventpipeadapter.h b/src/coreclr/vm/eventpipeadapter.h index 93cb7a49408ed6..9092a1455686ab 100644 --- a/src/coreclr/vm/eventpipeadapter.h +++ b/src/coreclr/vm/eventpipeadapter.h @@ -328,7 +328,7 @@ class EventPipeAdapter final } CONTRACTL_END; - ep_char8_t *providerNameUTF8 = ep_rt_utf16_to_utf8_string(reinterpret_cast(providerName.GetUnicode ()), -1); + ep_char8_t *providerNameUTF8 = ep_rt_utf16_to_utf8_string(reinterpret_cast((LPCWSTR)providerName), -1); EventPipeProvider * provider = ep_create_provider (providerNameUTF8, callback, NULL, NULL); ep_rt_utf8_string_free (providerNameUTF8); return provider; diff --git a/src/coreclr/vm/eventreporter.cpp b/src/coreclr/vm/eventreporter.cpp index 74a14b9aa1c02a..ed7efcf5a21309 100644 --- a/src/coreclr/vm/eventreporter.cpp +++ b/src/coreclr/vm/eventreporter.cpp @@ -50,9 +50,9 @@ EventReporter::EventReporter(EventReporterType type) fBufferFull = FALSE; - InlineSString<256> ssMessage; + InlineEString<256, EncodingUnicode> ssMessage; - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_APPLICATION)) + if(!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_APPLICATION)) m_Description.Append(W("Application: ")); else { @@ -71,7 +71,7 @@ EventReporter::EventReporter(EventReporterType type) else { ssMessage.Clear(); - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_UNKNOWN)) + if(!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_UNKNOWN)) m_Description.Append(W("unknown\n")); else { @@ -81,7 +81,7 @@ EventReporter::EventReporter(EventReporterType type) } ssMessage.Clear(); - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_FRAMEWORK_VERSION)) + if(!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_FRAMEWORK_VERSION)) m_Description.Append(W("CoreCLR Version: ")); else { @@ -99,7 +99,7 @@ EventReporter::EventReporter(EventReporterType type) switch(m_eventType) { case ERT_UnhandledException: - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTION)) + if(!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTION)) m_Description.Append(W("Description: The process was terminated due to an unhandled exception.")); else { @@ -109,7 +109,7 @@ EventReporter::EventReporter(EventReporterType type) break; case ERT_ManagedFailFast: - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_MANAGEDFAILFAST)) + if(!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_MANAGEDFAILFAST)) m_Description.Append(W("Description: The application requested process termination through System.Environment.FailFast.")); else { @@ -119,7 +119,7 @@ EventReporter::EventReporter(EventReporterType type) break; case ERT_UnmanagedFailFast: - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_UNMANAGEDFAILFAST)) + if(!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_UNMANAGEDFAILFAST)) m_Description.Append(W("Description: The process was terminated due to an internal error in the .NET Runtime ")); else { @@ -129,7 +129,7 @@ EventReporter::EventReporter(EventReporterType type) case ERT_StackOverflow: // Fetch the localized Stack Overflow Error text or fall back on a hardcoded variant if things get dire. - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_STACK_OVERFLOW)) + if(!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_STACK_OVERFLOW)) m_Description.Append(W("Description: The process was terminated due to a stack overflow.")); else { @@ -139,7 +139,7 @@ EventReporter::EventReporter(EventReporterType type) break; case ERT_CodeContractFailed: - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_CODECONTRACT_FAILED)) + if(!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_CODECONTRACT_FAILED)) m_Description.Append(W("Description: The application encountered a bug. A managed code contract (precondition, postcondition, object invariant, or assert) failed.")); else { @@ -202,7 +202,7 @@ void EventReporter::AddDescription(SString& s) if (m_eventType == ERT_ManagedFailFast) { SmallStackSString ssMessage; - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_MANAGEDFAILFASTMSG)) + if(!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_MANAGEDFAILFASTMSG)) m_Description.Append(W("Message: ")); else { @@ -212,7 +212,7 @@ void EventReporter::AddDescription(SString& s) else if (m_eventType == ERT_UnhandledException) { SmallStackSString ssMessage; - if (!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTIONMSG)) + if (!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTIONMSG)) { m_Description.Append(W("Exception Info: ")); } @@ -224,7 +224,7 @@ void EventReporter::AddDescription(SString& s) else if (m_eventType == ERT_CodeContractFailed) { SmallStackSString ssMessage; - if (!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_CODECONTRACT_DETAILMSG)) + if (!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_CODECONTRACT_DETAILMSG)) m_Description.Append(W("Contract details: ")); else m_Description.Append(ssMessage); @@ -253,8 +253,8 @@ void EventReporter::BeginStackTrace() } CONTRACTL_END; _ASSERTE (m_eventType == ERT_UnhandledException || m_eventType == ERT_ManagedFailFast || m_eventType == ERT_CodeContractFailed); - InlineSString<80> ssMessage; - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_STACK)) + InlineEString<80, EncodingUnicode> ssMessage; + if(!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_STACK)) m_Description.Append(W("Stack:\n")); else { @@ -292,7 +292,7 @@ void EventReporter::AddStackTrace(SString& s) { // Load the truncation message StackSString truncate; - if (!truncate.LoadResource(CCompRC::Optional, IDS_ER_MESSAGE_TRUNCATE)) + if (!LoadResource(truncate, CCompRC::Optional, IDS_ER_MESSAGE_TRUNCATE)) { truncate.Set(W("The remainder of the message was truncated.")); } @@ -347,8 +347,8 @@ void EventReporter::AddFailFastStackTrace(SString& s) CONTRACTL_END; _ASSERTE(m_eventType == ERT_ManagedFailFast); - InlineSString<80> ssMessage; - if (!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTION)) + InlineEString<80, EncodingUnicode> ssMessage; + if (!LoadResource(ssMessage, CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTION)) { m_Description.Append(W("Exception stack:\n")); } @@ -415,7 +415,7 @@ void EventReporter::Report() 0, eventID, NULL, - m_Description.GetUnicode() + m_Description ); if (dwRetVal != ERROR_SUCCESS) @@ -525,8 +525,7 @@ StackWalkAction LogCallstackForEventReporterCallback( MethodDesc *pMD = pCF->GetFunction(); _ASSERTE(pMD != NULL); - StackSString str; - str = *pWordAt; + StackSString str(*pWordAt); TypeString::AppendMethodInternal(str, pMD, TypeString::FormatNamespace|TypeString::FormatFullInst|TypeString::FormatSignature); pReporter->AddStackTrace(str); @@ -549,7 +548,7 @@ void LogCallstackForEventReporterWorker(EventReporter& reporter) Thread* pThread = GetThread(); SmallStackSString WordAt; - if (!WordAt.LoadResource(CCompRC::Optional, IDS_ER_WORDAT)) + if (!LoadResource(WordAt, CCompRC::Optional, IDS_ER_WORDAT)) { WordAt.Set(W(" at")); } @@ -557,7 +556,7 @@ void LogCallstackForEventReporterWorker(EventReporter& reporter) { WordAt.Insert(WordAt.Begin(), W(" ")); } - WordAt += W(" "); + WordAt += SL(W(" ")); LogCallstackData data = { &reporter, &WordAt @@ -639,8 +638,7 @@ void ReportExceptionStackHelper(OBJECTREF exObj, EventReporter& reporter, SmallS for (int j = 0; j < stackFramesData.cElements; j++) { - StackSString str; - str = wordAt; + StackSString str(wordAt); TypeString::AppendMethodInternal(str, stackFramesData.pElements[j].pFunc, TypeString::FormatNamespace | TypeString::FormatFullInst | TypeString::FormatSignature); reporter.AddStackTrace(str); } @@ -673,19 +671,19 @@ void DoReportForUnhandledNativeException(PEXCEPTION_POINTERS pExceptionInfo) EX_TRY { StackSString s; - InlineSString<80> ssErrorFormat; - if (!ssErrorFormat.LoadResource(CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTIONINFO)) - ssErrorFormat.Set(W("exception code %1, exception address %2")); - SmallStackSString exceptionCodeString; - exceptionCodeString.Printf(W("%x"), pExceptionInfo->ExceptionRecord->ExceptionCode); - SmallStackSString addressString; - addressString.Printf(W("%p"), (PVOID)pExceptionInfo->ExceptionRecord->ExceptionAddress); - s.FormatMessage(FORMAT_MESSAGE_FROM_STRING, (LPCWSTR)ssErrorFormat, 0, 0, exceptionCodeString, addressString); - reporter.AddDescription(s); - if (pThread) - { - LogCallstackForEventReporter(reporter); - } + InlineEString<80, EncodingUnicode> ssErrorFormat; + if (!LoadResource(ssErrorFormat, CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTIONINFO)) + ssErrorFormat.Set(W("exception code %1, exception address %2")); + SmallStackSString exceptionCodeString; + exceptionCodeString.Printf(W("%x"), pExceptionInfo->ExceptionRecord->ExceptionCode); + SmallStackSString addressString; + addressString.Printf(W("%p"), (PVOID)pExceptionInfo->ExceptionRecord->ExceptionAddress); + s.FormatMessage(FORMAT_MESSAGE_FROM_STRING, (LPCWSTR)ssErrorFormat, 0, 0, exceptionCodeString, addressString); + reporter.AddDescription(s); + if (pThread) + { + LogCallstackForEventReporter(reporter); + } } EX_CATCH { diff --git a/src/coreclr/vm/eventreporter.h b/src/coreclr/vm/eventreporter.h index 9b600e76cd4aea..0884954d52d202 100644 --- a/src/coreclr/vm/eventreporter.h +++ b/src/coreclr/vm/eventreporter.h @@ -43,7 +43,7 @@ class EventReporter EventReporterType m_eventType; // We use 2048 which is large enough for most task. This allows us to avoid // unnecessary memory allocation. - InlineSString<2048> m_Description; + InlineEString<2048, EncodingUnicode> m_Description; // Flag to indicate if the buffer is full BOOL fBufferFull; diff --git a/src/coreclr/vm/eventtrace.cpp b/src/coreclr/vm/eventtrace.cpp index 06bc3e67a3fc45..5417f7e7aa6de3 100644 --- a/src/coreclr/vm/eventtrace.cpp +++ b/src/coreclr/vm/eventtrace.cpp @@ -1670,7 +1670,7 @@ void BulkTypeEventLogger::FireBulkTypeEvent() // Do var-sized data individually per field - LPCWSTR wszName = target.sName.GetUnicode(); + LPCWSTR wszName = target.sName; if (wszName == NULL) { m_pBulkTypeEventBuffer[iSize++] = 0; @@ -1886,7 +1886,6 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) { th.GetName(pVal->sName); } - pVal->sName.Normalize(); } EX_CATCH { @@ -4795,7 +4794,7 @@ VOID ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept gc.exceptionMessageRef = ((EXCEPTIONREF)gc.exceptionObj)->GetMessage(); TypeHandle exceptionTypeHandle = (gc.exceptionObj)->GetTypeHandle(); exceptionTypeHandle.GetName(exceptionType); - WCHAR *exceptionTypeName = (WCHAR *)exceptionType.GetUnicode(); + const WCHAR *exceptionTypeName = (const WCHAR *)exceptionType; if(gc.exceptionMessageRef != NULL) { @@ -4852,7 +4851,7 @@ VOID ETW::ExceptionLog::ExceptionCatchBegin(MethodDesc * pMethodDesc, PVOID pEnt FireEtwExceptionCatchStart((uint64_t)pEntryEIP, (uint64_t)pMethodDesc, - methodName.GetUnicode(), + methodName, GetClrInstanceId()); } EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); @@ -4892,7 +4891,7 @@ VOID ETW::ExceptionLog::ExceptionFinallyBegin(MethodDesc * pMethodDesc, PVOID pE FireEtwExceptionFinallyStart((uint64_t)pEntryEIP, (uint64_t)pMethodDesc, - methodName.GetUnicode(), + methodName, GetClrInstanceId()); } EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); @@ -4932,7 +4931,7 @@ VOID ETW::ExceptionLog::ExceptionFilterBegin(MethodDesc * pMethodDesc, PVOID pEn FireEtwExceptionFilterStart((uint64_t)pEntryEIP, (uint64_t)pMethodDesc, - methodName.GetUnicode(), + methodName, GetClrInstanceId()); } EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); @@ -5377,14 +5376,17 @@ VOID ETW::MethodLog::GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPo { SendMethodDetailsEvent(pMethodDesc); - SString tNamespace, tMethodName, tMethodSignature; + SString tNamespace, tMethodNameW, tMethodSignatureW; + EString tMethodName, tMethodSignature; pMethodDesc->GetMethodInfo(tNamespace, tMethodName, tMethodSignature); + tMethodName.ConvertToUnicode(tMethodNameW); + tMethodSignature.ConvertToUnicode(tMethodSignatureW); FireEtwR2RGetEntryPoint( (UINT64)pMethodDesc, - (PCWSTR)tNamespace.GetUnicode(), - (PCWSTR)tMethodName.GetUnicode(), - (PCWSTR)tMethodSignature.GetUnicode(), + (PCWSTR)tNamespace, + (PCWSTR)tMethodNameW, + (PCWSTR)tMethodSignatureW, pEntryPoint, GetClrInstanceId()); @@ -5458,12 +5460,15 @@ VOID ETW::MethodLog::LogMethodInstrumentationData(MethodDesc* method, uint32_t c else ulMethodToken = (ULONG)method->GetMemberDef_NoLogging(); - SString tNamespace, tMethodName, tMethodSignature; + SString tNamespace, tMethodNameW, tMethodSignatureW; + EString tMethodName, tMethodSignature; method->GetMethodInfo(tNamespace, tMethodName, tMethodSignature); + tMethodName.ConvertToUnicode(tMethodNameW); + tMethodSignature.ConvertToUnicode(tMethodSignatureW); - PCWSTR pNamespace = (PCWSTR)tNamespace.GetUnicode(); - PCWSTR pMethodName = (PCWSTR)tMethodName.GetUnicode(); - PCWSTR pMethodSignature = (PCWSTR)tMethodSignature.GetUnicode(); + PCWSTR pNamespace = (PCWSTR)tNamespace; + PCWSTR pMethodName = (PCWSTR)tMethodNameW; + PCWSTR pMethodSignature = (PCWSTR)tMethodSignatureW; // Send data in 40,000 byte chunks uint32_t chunkIndex = 0; @@ -5493,7 +5498,7 @@ VOID ETW::MethodLog::LogMethodInstrumentationData(MethodDesc* method, uint32_t c /*******************************************************/ /* This is called by the runtime when a method is jitted completely */ /*******************************************************/ -VOID ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig) +VOID ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, EString *methodName, EString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig) { CONTRACTL { NOTHROW; @@ -5530,7 +5535,7 @@ VOID ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrC /*************************************************/ /* This is called by the runtime when method jitting started */ /*************************************************/ -VOID ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature) +VOID ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, EString *methodName, EString *methodSignature) { CONTRACTL { NOTHROW; @@ -6058,7 +6063,7 @@ VOID ETW::LoaderLog::SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions SString sAssemblyPath; pAssembly->GetDisplayName(sAssemblyPath); - LPWSTR lpszAssemblyPath = (LPWSTR)sAssemblyPath.GetUnicode(); + LPCWSTR lpszAssemblyPath = (LPCWSTR)sAssemblyPath; /* prepare events args for ETW and ETM */ szDtraceOutput1 = (PCWSTR)lpszAssemblyPath; @@ -6326,7 +6331,7 @@ VOID ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL CV_INFO_PDB70 cvInfoNative = {0}; GetCodeViewInfo(pModule, &cvInfoIL, &cvInfoNative); - PWCHAR ModuleILPath=(PWCHAR)W(""), ModuleNativePath=(PWCHAR)W(""); + LPCWSTR ModuleILPath=(LPCWSTR)W(""), ModuleNativePath=(LPCWSTR)W(""); if(bFireDomainModuleEvents) { @@ -6334,20 +6339,20 @@ VOID ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL } LPCWSTR pEmptyString = W(""); - SString moduleName = SString::Empty(); if(!bIsDynamicAssembly) { - ModuleILPath = (PWCHAR)pModule->GetAssembly()->GetPEAssembly()->GetPEImage()->GetPath().GetUnicode(); - ModuleNativePath = (PWCHAR)pEmptyString; + ModuleILPath = (LPCWSTR)pModule->GetAssembly()->GetPEAssembly()->GetPEImage()->GetPath(); + ModuleNativePath = (LPCWSTR)pEmptyString; } // if we do not have a module path yet, we put the module name if(bIsDynamicAssembly || ModuleILPath==NULL || wcslen(ModuleILPath) <= 2) { - moduleName.SetUTF8(pModule->GetSimpleName()); - ModuleILPath = (PWCHAR)moduleName.GetUnicode(); - ModuleNativePath = (PWCHAR)pEmptyString; + SString moduleName; + EString(pModule->GetSimpleName()).ConvertToUnicode(moduleName); + ModuleILPath = (LPCWSTR)moduleName; + ModuleNativePath = (LPCWSTR)pEmptyString; } /* prepare events args for ETW and ETM */ @@ -6355,8 +6360,8 @@ VOID ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL szDtraceOutput2 = (PCWSTR)ModuleNativePath; // Convert PDB paths to UNICODE - StackSString managedPdbPath(SString::Utf8, cvInfoIL.path); - StackSString nativePdbPath(SString::Utf8, cvInfoNative.path); + MAKE_WIDEPTR_FROMUTF8(managedPdbPath, cvInfoIL.path); + MAKE_WIDEPTR_FROMUTF8(nativePdbPath, cvInfoNative.path); if(bFireDomainModuleEvents) { @@ -6487,7 +6492,7 @@ done:; /*****************************************************************/ /* This routine is used to send an ETW event just before a method starts jitting*/ /*****************************************************************/ -VOID ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature) +VOID ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName, EString *methodName, EString *methodSignature) { CONTRACTL { THROWS; @@ -6534,7 +6539,8 @@ VOID ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *n ulMethodILSize = (ULONG)ILHeader.GetCodeSize(); } - SString tNamespace, tMethodName, tMethodSignature; + SString tNamespace; + EString tMethodName, tMethodSignature; if(!namespaceOrClassName|| !methodName|| !methodSignature || (methodName->IsEmpty() && namespaceOrClassName->IsEmpty() && methodSignature->IsEmpty())) { pMethodDesc->GetMethodInfo(tNamespace, tMethodName, tMethodSignature); @@ -6545,9 +6551,11 @@ VOID ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *n // fire method information /* prepare events args for ETW and ETM */ - szDtraceOutput1 = (PCWSTR)namespaceOrClassName->GetUnicode(); - szDtraceOutput2 = (PCWSTR)methodName->GetUnicode(); - szDtraceOutput3 = (PCWSTR)methodSignature->GetUnicode(); + szDtraceOutput1 = (PCWSTR)*namespaceOrClassName; + MAKE_WIDEPTR_FROMUTF8(methodNameW, *methodName); + MAKE_WIDEPTR_FROMUTF8(methodSignatureW, *methodSignature); + szDtraceOutput2 = (PCWSTR)methodNameW; + szDtraceOutput3 = (PCWSTR)methodSignatureW; FireEtwMethodJittingStarted_V1(ullMethodIdentifier, ullModuleID, @@ -6563,7 +6571,7 @@ VOID ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *n /****************************************************************************/ /* This routine is used to send a method load/unload or rundown event */ /****************************************************************************/ -VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig) +VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName, EString *methodName, EString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig) { CONTRACTL { THROWS; @@ -6676,8 +6684,9 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio } else ulMethodToken = (ULONG)pMethodDesc->GetMemberDef_NoLogging(); - - SString tNamespace, tMethodName, tMethodSignature; + + SString tNamespace; + EString tMethodName, tMethodSignature; // if verbose method load info needed, only then // find method name and signature and fire verbose method load info @@ -6690,15 +6699,17 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio methodName = &tMethodName; methodSignature = &tMethodSignature; } - pNamespaceName = (PWCHAR)namespaceOrClassName->GetUnicode(); - pMethodName = (PWCHAR)methodName->GetUnicode(); - pMethodSignature = (PWCHAR)methodSignature->GetUnicode(); + pNamespaceName = (PWCHAR)namespaceOrClassName; + pMethodName = (PWCHAR)methodName; + pMethodSignature = (PWCHAR)methodSignature; } /* prepare events args for ETW and ETM */ - szDtraceOutput1 = (PCWSTR)pNamespaceName; - szDtraceOutput2 = (PCWSTR)pMethodName; - szDtraceOutput3 = (PCWSTR)pMethodSignature; + szDtraceOutput1 = (PCWSTR)*namespaceOrClassName; + MAKE_WIDEPTR_FROMUTF8(methodNameW, *methodName); + MAKE_WIDEPTR_FROMUTF8(methodSignatureW, *methodSignature); + szDtraceOutput2 = (PCWSTR)methodNameW; + szDtraceOutput3 = (PCWSTR)methodSignatureW; SendMethodDetailsEvent(pMethodDesc); diff --git a/src/coreclr/vm/eventtracepriv.h b/src/coreclr/vm/eventtracepriv.h index b262a4fd787da5..f7cebb66c1bd53 100644 --- a/src/coreclr/vm/eventtracepriv.h +++ b/src/coreclr/vm/eventtracepriv.h @@ -7,7 +7,7 @@ // clients of eventtrace.cpp, and thus don't belong in eventtrace.h. Also, since // inclusions of this file are tightly controlled (basically just by eventtrace.cpp), we // can assume some classes are defined that aren't necessarily defined when eventtrace.h -// is #included (e.g., StackSString and StackSArray). +// is #included (e.g., StackEString and StackSArray). // // diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index ae9e2fa714c226..5b1a4477b95ad5 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -213,7 +213,7 @@ ULONG GetExceptionMessage(OBJECTREF throwable, GetExceptionMessage(throwable, result); ULONG length = result.GetCount(); - LPCWSTR chars = result.GetUnicode(); + LPCWSTR chars = (LPCWSTR)result; if (length < bufferLength) { @@ -4030,7 +4030,7 @@ LPCWSTR g_createDumpCommandLine = nullptr; static void BuildCreateDumpCommandLine( - SString& commandLine, + EString& commandLine, LPCWSTR dumpName, int dumpType, bool diag) @@ -4040,14 +4040,16 @@ BuildCreateDumpCommandLine( PathString coreclrPath; if (GetClrModulePathName(coreclrPath)) { - SString::CIterator lastBackslash = coreclrPath.End(); - if (coreclrPath.FindBack(lastBackslash, W('\\'))) + SmallStackEString coreclrPathUtf8; + coreclrPath.ConvertToUTF8(coreclrPathUtf8); + EString::CIterator lastBackslash = coreclrPathUtf8.End(); + if (coreclrPathUtf8.FindBack(lastBackslash, W('\\'))) { - commandLine.Set(coreclrPath, coreclrPath.Begin(), lastBackslash + 1); + commandLine.Set(coreclrPathUtf8, coreclrPathUtf8.Begin(), lastBackslash + 1); } } - commandLine.AppendASCII(DumpGeneratorName); + commandLine.Append(DumpGeneratorName); if (dumpName != nullptr) { @@ -4146,7 +4148,7 @@ GenerateCrashDump( int dumpType, bool diag) { - SString commandLine; + EString commandLine; if (dumpType < 1 || dumpType > 4) { return false; @@ -4156,7 +4158,9 @@ GenerateCrashDump( dumpName = nullptr; } BuildCreateDumpCommandLine(commandLine, dumpName, dumpType, diag); - return LaunchCreateDump(commandLine); + SString commandLineW; + commandLine.ConvertToUnicode(commandLineW); + return LaunchCreateDump(commandLineW); } void @@ -4169,9 +4173,11 @@ InitializeCrashDump() int dumpType = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgMiniDumpType); DWORD diag = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_CreateDumpDiagnostics); - SString commandLine; + EString commandLine; BuildCreateDumpCommandLine(commandLine, dumpName, dumpType, diag == 1); - g_createDumpCommandLine = commandLine.GetCopyOfUnicodeString(); + SString commandLineW; + commandLine.ConvertToUnicode(commandLineW); + g_createDumpCommandLine = commandLineW.CreateCopyOfString(); } } @@ -5084,7 +5090,7 @@ static SString GetExceptionMessageWrapper(Thread* pThread, OBJECTREF throwable) GetExceptionMessage(throwable, result); UNINSTALL_NESTED_EXCEPTION_HANDLER(); - return result; + return std::move(result); } void STDMETHODCALLTYPE @@ -5668,7 +5674,7 @@ static BOOL GetManagedFormatStringForResourceID(CCompRC::ResourceCategory eCateg STANDARD_VM_CONTRACT; StackSString temp; - if (!temp.LoadResource(eCategory, resId)) + if (!LoadResource(temp, eCategory, resId)) return FALSE; SString::Iterator itr = temp.Begin(); @@ -7247,11 +7253,10 @@ VEH_ACTION WINAPI CLRVectoredExceptionHandlerPhase3(PEXCEPTION_POINTERS pExcepti // #if defined(_DEBUG) const char * pStack = ""; - StackScratchBuffer buffer; - SString sStack; + EString sStack; if (GetStackTraceAtContext(sStack, pContext)) { - pStack = sStack.GetANSI(buffer); + pStack = sStack; } DWORD tid = GetCurrentThreadId(); @@ -11177,20 +11182,20 @@ VOID ThrowBadFormatWorker(UINT resID, LPCWSTR imageName DEBUGARG(_In_z_ const ch SString msgStr; SString resStr; - if (resID == 0 || !resStr.LoadResource(CCompRC::Optional, resID)) + if (resID == 0 || !LoadResource(resStr, CCompRC::Optional, resID)) { - resStr.LoadResource(CCompRC::Error, BFA_BAD_IL); // "Bad IL format." + LoadResource(resStr, CCompRC::Error, BFA_BAD_IL); // "Bad IL format." } msgStr += resStr; if ((imageName != NULL) && (imageName[0] != 0)) { SString suffixResStr; - if (suffixResStr.LoadResource(CCompRC::Optional, COR_E_BADIMAGEFORMAT)) // "The format of the file '%1' is invalid." + if (LoadResource(suffixResStr, CCompRC::Optional, COR_E_BADIMAGEFORMAT)) // "The format of the file '%1' is invalid." { SString suffixMsgStr; - suffixMsgStr.FormatMessage(FORMAT_MESSAGE_FROM_STRING, (LPCWSTR)suffixResStr, 0, 0, imageName); - msgStr.AppendASCII(" "); + suffixMsgStr.FormatMessage(FORMAT_MESSAGE_FROM_STRING, (LPCWSTR)suffixResStr, 0, 0, SL(imageName)); + msgStr.Append(W(" ")); msgStr += suffixMsgStr; } } @@ -11198,10 +11203,12 @@ VOID ThrowBadFormatWorker(UINT resID, LPCWSTR imageName DEBUGARG(_In_z_ const ch #ifdef _DEBUG if (0 != strcmp(cond, "FALSE")) { - msgStr += W(" (Failed condition: "); // this is in DEBUG only - not going to localize it. - SString condStr(SString::Ascii, cond); - msgStr += condStr; - msgStr += W(")"); + msgStr += SL(W(" (Failed condition: ")); // this is in DEBUG only - not going to localize it. + EString condStr(cond); + SString condStrW; + condStr.ConvertToUnicode(condStrW); + msgStr += condStrW; + msgStr += SL(W(")")); } #endif ThrowHR(COR_E_BADIMAGEFORMAT, msgStr); @@ -11521,11 +11528,11 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrow(RuntimeExceptionKind reKind, LPCWSTR wsz if (pInnerException == NULL) { - EX_THROW(EEResourceException, (reKind, wszResourceName)); + EX_THROW(EEResourceException, (reKind, SString(wszResourceName))); } else { - EX_THROW_WITH_INNER(EEResourceException, (reKind, wszResourceName), pInnerException); + EX_THROW_WITH_INNER(EEResourceException, (reKind, SString(wszResourceName)), pInnerException); } } @@ -11757,10 +11764,11 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(EXCEPINFO *pExcepInfo) // Throw an InvalidCastException //========================================================================== -VOID GetAssemblyDetailInfo(SString &sType, - SString &sAssemblyDisplayName, + +VOID GetAssemblyDetailInfo(SString &sType, + SString &sAssemblyDisplayName, PEAssembly *pPEAssembly, - SString &sAssemblyDetailInfo) + SString &sAssemblyDetailInfo) { WRAPPER_NO_CONTRACT; @@ -11771,22 +11779,22 @@ VOID GetAssemblyDetailInfo(SString &sType, if (pPEAssembly->GetPath().IsEmpty()) { - sFormat.LoadResource(CCompRC::Debugging, IDS_EE_CANNOTCAST_HELPER_BYTE); + LoadResource(sFormat, CCompRC::Debugging, IDS_EE_CANNOTCAST_HELPER_BYTE); - sAssemblyDetailInfo.Printf(sFormat.GetUnicode(), - sType.GetUnicode(), - sAssemblyDisplayName.GetUnicode(), - sAlcName.GetUnicode()); + sAssemblyDetailInfo.Printf((LPCWSTR)sFormat, + (LPCWSTR)sType, + (LPCWSTR)sAssemblyDisplayName, + (LPCWSTR)sAlcName); } else { - sFormat.LoadResource(CCompRC::Debugging, IDS_EE_CANNOTCAST_HELPER_PATH); + LoadResource(sFormat, CCompRC::Debugging, IDS_EE_CANNOTCAST_HELPER_PATH); - sAssemblyDetailInfo.Printf(sFormat.GetUnicode(), - sType.GetUnicode(), - sAssemblyDisplayName.GetUnicode(), - sAlcName.GetUnicode(), - pPEAssembly->GetPath().GetUnicode()); + sAssemblyDetailInfo.Printf((LPCWSTR)sFormat, + (LPCWSTR)sType, + (LPCWSTR)sAssemblyDisplayName, + (LPCWSTR)sAlcName, + (LPCWSTR)pPEAssembly->GetPath()); } } @@ -11831,12 +11839,12 @@ VOID CheckAndThrowSameTypeAndAssemblyInvalidCastException(TypeHandle thCastFrom, thCastFrom.GetName(strCastFromName); thCastTo.GetName(strCastToName); - SString typeA = SL(W("A")); + SString typeA(SString::Literal, W("A")); GetAssemblyDetailInfo(typeA, sAssemblyFromDisplayName, pPEAssemblyTypeFrom, sAssemblyDetailInfoFrom); - SString typeB = SL(W("B")); + SString typeB(SString::Literal, W("B")); GetAssemblyDetailInfo(typeB, sAssemblyToDisplayName, pPEAssemblyTypeTo, @@ -11844,10 +11852,10 @@ VOID CheckAndThrowSameTypeAndAssemblyInvalidCastException(TypeHandle thCastFrom, COMPlusThrow(kInvalidCastException, IDS_EE_CANNOTCASTSAME, - strCastFromName.GetUnicode(), - strCastToName.GetUnicode(), - sAssemblyDetailInfoFrom.GetUnicode(), - sAssemblyDetailInfoTo.GetUnicode()); + (LPCWSTR)strCastFromName, + (LPCWSTR)strCastToName, + (LPCWSTR)sAssemblyDetailInfoFrom, + (LPCWSTR)sAssemblyDetailInfoTo); } } @@ -11859,11 +11867,11 @@ VOID RealCOMPlusThrowInvalidCastException(TypeHandle thCastFrom, TypeHandle thCa MODE_COOPERATIVE; } CONTRACTL_END; - // Use an InlineSString with a size of MAX_CLASSNAME_LENGTH + 1 to prevent + // Use an InlineEString with a size of MAX_CLASSNAME_LENGTH + 1 to prevent // TypeHandle::GetName from having to allocate a new block of memory. This // significantly improves the performance of throwing an InvalidCastException. - InlineSString strCastFromName; - InlineSString strCastToName; + InlineEString strCastFromName; + InlineEString strCastToName; thCastTo.GetName(strCastToName); { @@ -11873,7 +11881,7 @@ VOID RealCOMPlusThrowInvalidCastException(TypeHandle thCastFrom, TypeHandle thCa { CheckAndThrowSameTypeAndAssemblyInvalidCastException(thCastFrom, thCastTo); } - COMPlusThrow(kInvalidCastException, IDS_EE_CANNOTCAST, strCastFromName.GetUnicode(), strCastToName.GetUnicode()); + COMPlusThrow(kInvalidCastException, IDS_EE_CANNOTCAST, (LPCWSTR)strCastFromName, (LPCWSTR)strCastToName); } } diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index beb8015f598ef4..5b476a1ce28eea 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -3029,7 +3029,7 @@ CLRUnwindStatus ExceptionTracker::ProcessManagedCallFrame( SString msg; GET_EXCEPTION()->GetMessage(msg); msg.Insert(msg.Begin(), W("Cannot resolve EH clause:\n")); - EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_FAILFAST, msg.GetUnicode()); + EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_FAILFAST, msg); } EX_END_CATCH(RethrowTransientExceptions); diff --git a/src/coreclr/vm/gcenv.ee.cpp b/src/coreclr/vm/gcenv.ee.cpp index 02537f0dd7f545..2463e6f1c9a3e4 100644 --- a/src/coreclr/vm/gcenv.ee.cpp +++ b/src/coreclr/vm/gcenv.ee.cpp @@ -1490,14 +1490,15 @@ namespace bool GCToEEInterface::CreateThread(void (*threadStart)(void*), void* arg, bool is_suspendable, const char* name) { - InlineSString wideName; + InlineEString wideName; const WCHAR* namePtr = nullptr; EX_TRY { if (name != nullptr) { - wideName.SetUTF8(name); - namePtr = wideName.GetUnicode(); + MAKE_WIDEPTR_FROMUTF8(wname, name); + wideName.Set(wname); + namePtr = wideName; } } EX_CATCH diff --git a/src/coreclr/vm/gcheaputilities.cpp b/src/coreclr/vm/gcheaputilities.cpp index 088af916fc5bd0..c0ea9c5ab037ba 100644 --- a/src/coreclr/vm/gcheaputilities.cpp +++ b/src/coreclr/vm/gcheaputilities.cpp @@ -164,7 +164,7 @@ HMODULE LoadStandaloneGc(LPCWSTR libFileName) PathString libPath = GetInternalSystemDirectory(); libPath.Append(libFileName); - LPCWSTR libraryName = libPath.GetUnicode(); + LPCWSTR libraryName = (LPCWSTR)libPath; LOG((LF_GC, LL_INFO100, "Loading standalone GC from path %S\n", libraryName)); return CLRLoadLibrary(libraryName); } diff --git a/src/coreclr/vm/gctoclreventsink.cpp b/src/coreclr/vm/gctoclreventsink.cpp index 5eb30d8210d75a..5fe7110a11877e 100644 --- a/src/coreclr/vm/gctoclreventsink.cpp +++ b/src/coreclr/vm/gctoclreventsink.cpp @@ -164,7 +164,7 @@ void GCToCLREventSink::FireGCAllocationTick_V4(uint64_t allocationAmount, void * typeId = nullptr; const WCHAR * name = nullptr; - InlineSString strTypeName; + InlineEString strTypeName; EX_TRY { TypeHandle th = GetThread()->GetTHAllocContextObj(); @@ -172,7 +172,7 @@ void GCToCLREventSink::FireGCAllocationTick_V4(uint64_t allocationAmount, if (th != 0) { th.GetName(strTypeName); - name = strTypeName.GetUnicode(); + name = (LPCWSTR)strTypeName; typeId = th.GetMethodTable(); } } @@ -199,7 +199,7 @@ void GCToCLREventSink::FirePinObjectAtGCTime(void* object, uint8_t** ppObject) Object* obj = (Object*)object; - InlineSString strTypeName; + InlineEString strTypeName; EX_TRY { @@ -214,7 +214,7 @@ void GCToCLREventSink::FirePinObjectAtGCTime(void* object, uint8_t** ppObject) FireEtwPinObjectAtGCTime(ppObject, object, obj->GetSize(), - strTypeName.GetUnicode(), + (LPCWSTR)strTypeName, GetClrInstanceId()); } EX_CATCH {} diff --git a/src/coreclr/vm/gdbjit.cpp b/src/coreclr/vm/gdbjit.cpp index 525ca50a28c2b8..59d7880bf2eb9b 100644 --- a/src/coreclr/vm/gdbjit.cpp +++ b/src/coreclr/vm/gdbjit.cpp @@ -1293,11 +1293,11 @@ void FunctionMember::DumpMangledNamespaceAndMethod(char *buf, int &offset, const void FunctionMember::DumpLinkageName(char* ptr, int& offset) { SString namespaceOrClassName; - SString methodName; + EString methodName; md->GetMethodInfoNoSig(namespaceOrClassName, methodName); - SString utf8namespaceOrClassName; - SString utf8methodName; + EString utf8namespaceOrClassName; + EString utf8methodName; namespaceOrClassName.ConvertToUTF8(utf8namespaceOrClassName); methodName.ConvertToUTF8(utf8methodName); diff --git a/src/coreclr/vm/generics.cpp b/src/coreclr/vm/generics.cpp index fea2ce22645fdf..df23530b354707 100644 --- a/src/coreclr/vm/generics.cpp +++ b/src/coreclr/vm/generics.cpp @@ -185,11 +185,12 @@ ClassLoader::CreateTypeHandleForNonCanonicalGenericInstantiation( { StackSString debugTypeKeyName; TypeString::AppendTypeKeyDebug(debugTypeKeyName, pTypeKey); - LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: New instantiation requested: %S\n", debugTypeKeyName.GetUnicode())); + LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: New instantiation requested: %S\n", (LPCWSTR)debugTypeKeyName)); - StackScratchBuffer buf; - if (g_pConfig->ShouldBreakOnInstantiation(debugTypeKeyName.GetUTF8(buf))) - CONSISTENCY_CHECK_MSGF(false, ("BreakOnInstantiation: typename '%s' ", debugTypeKeyName.GetUTF8(buf))); + StackEString buf; + debugTypeKeyName.ConvertToUTF8(buf); + if (g_pConfig->ShouldBreakOnInstantiation(buf)) + CONSISTENCY_CHECK_MSGF(false, ("BreakOnInstantiation: typename '%s' ", (LPCUTF8)buf)); } #endif // _DEBUG @@ -474,14 +475,13 @@ ClassLoader::CreateTypeHandleForNonCanonicalGenericInstantiation( // Name for debugging StackSString debug_ClassNameString; TypeString::AppendTypeKey(debug_ClassNameString, pTypeKey, TypeString::FormatNamespace | TypeString::FormatAngleBrackets | TypeString::FormatFullInst); - StackScratchBuffer debug_ClassNameBuffer; - const char *debug_szClassNameBuffer = debug_ClassNameString.GetUTF8(debug_ClassNameBuffer); - S_SIZE_T safeLen = S_SIZE_T(strlen(debug_szClassNameBuffer)) + S_SIZE_T(1); + const EString debug_ClassNameBuffer(debug_ClassNameString.MoveToUTF8()); + S_SIZE_T safeLen = S_SIZE_T(strlen(debug_ClassNameBuffer)) + S_SIZE_T(1); if (safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); size_t len = safeLen.Value(); char *debug_szClassName = (char *)pamTracker->Track(pAllocator->GetLowFrequencyHeap()->AllocMem(safeLen)); - strcpy_s(debug_szClassName, len, debug_szClassNameBuffer); + strcpy_s(debug_szClassName, len, debug_ClassNameBuffer); pMT->SetDebugClassName(debug_szClassName); // Debugging information diff --git a/src/coreclr/vm/genmeth.cpp b/src/coreclr/vm/genmeth.cpp index 24b47038c296f4..fdba857d7573c4 100644 --- a/src/coreclr/vm/genmeth.cpp +++ b/src/coreclr/vm/genmeth.cpp @@ -383,7 +383,7 @@ InstantiatedMethodDesc::NewInstantiatedMethodDesc(MethodTable *pExactMT, DWORD dictionarySlotSize; DWORD dictionaryAllocSize = DictionaryLayout::GetDictionarySizeFromLayout(pGenericMDescInRepMT->GetNumGenericMethodArgs(), pDL, &dictionarySlotSize); LOG((LF_JIT, LL_INFO1000, "GENERICS: Created new dictionary layout for dictionary of slot size %d / alloc size %d for %S\n", - dictionarySlotSize, dictionaryAllocSize, name.GetUnicode())); + dictionarySlotSize, dictionaryAllocSize, (LPCWSTR)name)); } #endif // _DEBUG } @@ -475,8 +475,9 @@ InstantiatedMethodDesc::NewInstantiatedMethodDesc(MethodTable *pExactMT, #ifdef _DEBUG SString name; TypeString::AppendMethodDebug(name, pNewMD); - StackScratchBuffer buff; - const char* pDebugNameUTF8 = name.GetUTF8(buff); + EString nameUTF8; + name.ConvertToUTF8(nameUTF8); + const char* pDebugNameUTF8 = (LPCUTF8)nameUTF8; const char* verb = "Created"; if (pWrappedMD) LOG((LF_CLASSLOADER, LL_INFO1000, @@ -1644,7 +1645,7 @@ BOOL MethodDesc::SatisfiesMethodConstraints(TypeHandle thParent, BOOL fThrowIfNo SString sParentName; TypeString::AppendType(sParentName, thParent); - SString sMethodName(SString::Utf8, GetName()); + MAKE_WIDEPTR_FROMUTF8(sMethodName, GetName()); SString sActualParamName; TypeString::AppendType(sActualParamName, methodInst[i]); @@ -1654,10 +1655,10 @@ BOOL MethodDesc::SatisfiesMethodConstraints(TypeHandle thParent, BOOL fThrowIfNo COMPlusThrow(kVerificationException, IDS_EE_METHOD_CONSTRAINTS_VIOLATION, - sParentName.GetUnicode(), - sMethodName.GetUnicode(), - sActualParamName.GetUnicode(), - sFormalParamName.GetUnicode() + (LPCWSTR)sParentName, + (LPCWSTR)sMethodName, + (LPCWSTR)sActualParamName, + (LPCWSTR)sFormalParamName ); diff --git a/src/coreclr/vm/interopconverter.cpp b/src/coreclr/vm/interopconverter.cpp index 4f951c97634037..02c0ce2bd1d547 100644 --- a/src/coreclr/vm/interopconverter.cpp +++ b/src/coreclr/vm/interopconverter.cpp @@ -71,7 +71,7 @@ namespace pMTClass->_GetFullyQualifiedNameForClass(ssDestClsName); COMPlusThrow(kInvalidCastException, IDS_EE_CANNOTCAST, - ssObjClsName.GetUnicode(), ssDestClsName.GetUnicode()); + (LPCWSTR)ssObjClsName, (LPCWSTR)ssDestClsName); } } diff --git a/src/coreclr/vm/interoputil.cpp b/src/coreclr/vm/interoputil.cpp index dd5443c0c75b85..04f7e4de15863b 100644 --- a/src/coreclr/vm/interoputil.cpp +++ b/src/coreclr/vm/interoputil.cpp @@ -130,7 +130,7 @@ HRESULT SetupErrorInfo(OBJECTREF pThrownObject) { PrintToStdOutW(W(".NET exception in COM\n")); if (!message.IsEmpty()) - PrintToStdOutW(message.GetUnicode()); + PrintToStdOutW(message); else PrintToStdOutW(W("No exception info available")); } @@ -1864,13 +1864,13 @@ DefaultInterfaceType GetDefaultInterfaceForClassInternal(TypeHandle hndClass, Ty IfFailThrow(cap.GetNonNullString(&szStr, &cbStr)); // Allocate a new buffer that will contain the name of the default COM interface. - StackSString defItf(SString::Utf8, szStr, cbStr); + StackEString defItf(szStr, cbStr); // Load the default COM interface specified in the CA. { GCX_COOP(); - DefItfType = TypeName::GetTypeUsingCASearchRules(defItf.GetUnicode(), pClassMT->GetAssembly()); + DefItfType = TypeName::GetTypeUsingCASearchRules(defItf, pClassMT->GetAssembly()); // If the type handle isn't a named type, then throw an exception using // the name of the type obtained from pCurrInterfaces. @@ -1879,9 +1879,11 @@ DefaultInterfaceType GetDefaultInterfaceForClassInternal(TypeHandle hndClass, Ty // This should only occur for TypeDesc's. StackSString ssClassName; DefineFullyQualifiedNameForClassW() + StackSString defItfName; + defItf.ConvertToUnicode(defItfName); COMPlusThrow(kTypeLoadException, IDS_EE_INVALIDCOMDEFITF, GetFullyQualifiedNameForClassW(pClassMT), - defItf.GetUnicode()); + defItfName); } // Otherwise, if the type is not an interface thrown an exception using the actual @@ -1893,7 +1895,7 @@ DefaultInterfaceType GetDefaultInterfaceForClassInternal(TypeHandle hndClass, Ty pClassMT->_GetFullyQualifiedNameForClass(ssClassName); DefItfType.GetMethodTable()->_GetFullyQualifiedNameForClass(ssInvalidItfName); COMPlusThrow(kTypeLoadException, IDS_EE_INVALIDCOMDEFITF, - ssClassName.GetUnicode(), ssInvalidItfName.GetUnicode()); + ssClassName, ssInvalidItfName); } // Make sure the class implements the interface. @@ -1904,7 +1906,7 @@ DefaultInterfaceType GetDefaultInterfaceForClassInternal(TypeHandle hndClass, Ty pClassMT->_GetFullyQualifiedNameForClass(ssClassName); DefItfType.GetMethodTable()->_GetFullyQualifiedNameForClass(ssInvalidItfName); COMPlusThrow(kTypeLoadException, IDS_EE_COMDEFITFNOTSUPPORTED, - ssClassName.GetUnicode(), ssInvalidItfName.GetUnicode()); + ssClassName, ssInvalidItfName); } } @@ -2149,11 +2151,12 @@ void GetComSourceInterfacesForClass(MethodTable *pMT, CQuickArray if (!ItfType.GetMethodTable()) { // This should only occur for TypeDesc's. - StackSString ssInvalidItfName(SString::Utf8, pCurrInterfaces); + StackSString ssInvalidItfName; + EString(pCurrInterfaces).ConvertToUnicode(ssInvalidItfName); DefineFullyQualifiedNameForClassW() COMPlusThrow(kTypeLoadException, IDS_EE_INVALIDCOMSOURCEITF, GetFullyQualifiedNameForClassW(pMT), - ssInvalidItfName.GetUnicode()); + ssInvalidItfName); } // Otherwise, if the type is not an interface thrown an exception using the actual @@ -2165,7 +2168,7 @@ void GetComSourceInterfacesForClass(MethodTable *pMT, CQuickArray pMT->_GetFullyQualifiedNameForClass(ssClassName); ItfType.GetMethodTable()->_GetFullyQualifiedNameForClass(ssInvalidItfName); COMPlusThrow(kTypeLoadException, IDS_EE_INVALIDCOMSOURCEITF, - ssClassName.GetUnicode(), ssInvalidItfName.GetUnicode()); + ssClassName, ssInvalidItfName); } // Ensure the source interface is not generic. @@ -2176,7 +2179,7 @@ void GetComSourceInterfacesForClass(MethodTable *pMT, CQuickArray pMT->_GetFullyQualifiedNameForClass(ssClassName); ItfType.GetMethodTable()->_GetFullyQualifiedNameForClass(ssInvalidItfName); COMPlusThrow(kTypeLoadException, IDS_EE_INVALIDCOMSOURCEITF, - ssClassName.GetUnicode(), ssInvalidItfName.GetUnicode()); + ssClassName, ssInvalidItfName); } @@ -3269,7 +3272,7 @@ void IUInvokeDispMethod( aNamesToConvert[0] = (*pStrName)->GetBuffer(); // Check to see if the name is for a standard DISPID. - if (SString::_wcsnicmp(aNamesToConvert[0], STANDARD_DISPID_PREFIX, STANDARD_DISPID_PREFIX_LENGTH) == 0) + if (StaticStringHelpers::_wcsnicmp(aNamesToConvert[0], STANDARD_DISPID_PREFIX, STANDARD_DISPID_PREFIX_LENGTH) == 0) { // The name is for a standard DISPID so extract it from the name. MemberID = ExtractStandardDispId(aNamesToConvert[0]); @@ -3285,7 +3288,7 @@ void IUInvokeDispMethod( strTmpName = pNamedArgsData[i]->GetBuffer(); // Check to see if the name is for a standard DISPID. - if (SString::_wcsnicmp(strTmpName, STANDARD_DISPID_PREFIX, STANDARD_DISPID_PREFIX_LENGTH) != 0) + if (StaticStringHelpers::_wcsnicmp(strTmpName, STANDARD_DISPID_PREFIX, STANDARD_DISPID_PREFIX_LENGTH) != 0) COMPlusThrow(kArgumentException, IDS_EE_NON_STD_NAME_WITH_STD_DISPID); // The name is for a standard DISPID so extract it from the name. @@ -3371,7 +3374,7 @@ void IUInvokeDispMethod( if (FAILED(hr)) { // Check to see if the user wants to invoke the new enum member. - if (cNamesToConvert == 1 && SString::_wcsicmp(aNamesToConvert[0], GET_ENUMERATOR_METHOD_NAME) == 0) + if (cNamesToConvert == 1 && StaticStringHelpers::_wcsicmp(aNamesToConvert[0], GET_ENUMERATOR_METHOD_NAME) == 0) { // Invoke the new enum member. MemberID = DISPID_NEWENUM; diff --git a/src/coreclr/vm/interoputil.h b/src/coreclr/vm/interoputil.h index 5fa476a3fddb3b..5ff2a8a5fc6fbb 100644 --- a/src/coreclr/vm/interoputil.h +++ b/src/coreclr/vm/interoputil.h @@ -394,6 +394,8 @@ IUnknown* MarshalObjectToInterface(OBJECTREF* ppObject, MethodTable* pItfMT, Met void UnmarshalObjectFromInterface(OBJECTREF *ppObjectDest, IUnknown **ppUnkSrc, MethodTable *pItfMT, MethodTable *pClassMT, DWORD dwFlags); #define DEFINE_ASM_QUAL_TYPE_NAME(varname, typename, asmname) static const char varname##[] = { typename##", "##asmname## }; +#define W2(x) W(x) +#define DEFINE_ASM_QUAL_TYPE_NAME_W(varname, typename, asmname) static const WCHAR varname##[] = { W2(typename##", "##asmname##) }; #else // FEATURE_COMINTEROP inline HRESULT EnsureComStartedNoThrow() diff --git a/src/coreclr/vm/invokeutil.cpp b/src/coreclr/vm/invokeutil.cpp index 944490f280b721..ec062073d79c02 100644 --- a/src/coreclr/vm/invokeutil.cpp +++ b/src/coreclr/vm/invokeutil.cpp @@ -772,10 +772,11 @@ void InvokeUtil::SetValidField(CorElementType fldType, if (pField->IsStatic() && pDeclMT->IsClassInited() && IsFdInitOnly(pField->GetAttributes())) { DefineFullyQualifiedNameForClassW(); - SString ssFieldName(SString::Utf8, pField->GetName()); + SString ssFieldName; + EString(pField->GetName()).ConvertToUnicode(ssFieldName); COMPlusThrow(kFieldAccessException, IDS_EE_CANNOT_SET_INITONLY_STATIC_FIELD, - ssFieldName.GetUnicode(), + ssFieldName, GetFullyQualifiedNameForClassW(pDeclMT)); } diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index bc06ec12eb4cfa..ede6b5f8782be6 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -3378,7 +3378,7 @@ int CEEInfo::appendClassName(_Outptr_opt_result_buffer_(*pnBufLen) char16_t** (fNamespace ? TypeString::FormatNamespace : 0) | (fFullInst ? TypeString::FormatFullInst : 0) | (fAssembly ? TypeString::FormatAssembly : 0)); - const WCHAR* szString = ss.GetUnicode(); + const WCHAR* szString = (LPCWSTR)ss; nLen = (int)wcslen(szString); if (*pnBufLen > 0) { @@ -6186,10 +6186,16 @@ const char* CEEInfo::getMethodName (CORINFO_METHOD_HANDLE ftnHnd, const char** s if (pMT->IsArray()) { ssClsNameBuff.Clear(); - ssClsNameBuff.SetUTF8(pMT->GetDebugClassName()); + ssClsNameBuff.Set(pMT->GetDebugClassName()); } else - pMT->_GetFullyQualifiedNameForClassNestedAware(ssClsNameBuff); + { + SString className; + pMT->_GetFullyQualifiedNameForClassNestedAware(className); + MAKE_UTF8PTR_FROMWIDE(classNamePtr, (LPCWSTR)className); + ssClsNameBuff.Clear(); + ssClsNameBuff.Set(classNamePtr); + } } else { @@ -6200,7 +6206,7 @@ const char* CEEInfo::getMethodName (CORINFO_METHOD_HANDLE ftnHnd, const char** s // GetDebugClassName - which doesn't calculate the class name everytime. // This results in huge saving in Ngen time for checked builds. ssClsNameBuff.Clear(); - ssClsNameBuff.SetUTF8(pMT->GetDebugClassName()); + ssClsNameBuff.Set(pMT->GetDebugClassName()); #ifdef FEATURE_SYMDIFF } @@ -6208,9 +6214,14 @@ const char* CEEInfo::getMethodName (CORINFO_METHOD_HANDLE ftnHnd, const char** s // Append generic instantiation at the end Instantiation inst = pMT->GetInstantiation(); if (!inst.IsEmpty()) - TypeString::AppendInst(ssClsNameBuff, inst); + { + SString instantiation; + TypeString::AppendInst(instantiation, inst); + MAKE_UTF8PTR_FROMWIDE(instantiationPtr, (LPCWSTR)instantiation); + ssClsNameBuff.Append(instantiationPtr); + } - *scopeName = ssClsNameBuff.GetUTF8(ssClsNameBuffScratch); + *scopeName = (LPCUTF8)ssClsNameBuff; #else // !_DEBUG // since this is for diagnostic purposes only, // give up on the namespace, as we don't have a buffer to concat it @@ -7964,46 +7975,49 @@ void CEEInfo::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd, if (LoggingOn(LF_JIT, LL_INFO100000)) { SString currentMethodName; - currentMethodName.AppendUTF8(m_pMethodBeingCompiled->GetModule_NoLogging()->GetPEAssembly()->GetSimpleName()); - currentMethodName.Append(L'/'); + MAKE_WIDEPTR_FROMUTF8(currentSimpleName, m_pMethodBeingCompiled->GetModule_NoLogging()->GetPEAssembly()->GetSimpleName()); + currentMethodName.Append(currentSimpleName); + currentMethodName.Append(W('/')); TypeString::AppendMethodInternal(currentMethodName, m_pMethodBeingCompiled, TypeString::FormatBasic); SString inlineeMethodName; if (GetMethod(inlineeHnd)) { - inlineeMethodName.AppendUTF8(GetMethod(inlineeHnd)->GetModule_NoLogging()->GetPEAssembly()->GetSimpleName()); - inlineeMethodName.Append(L'/'); + MAKE_WIDEPTR_FROMUTF8(inlineeSimpleName, GetMethod(inlineeHnd)->GetModule_NoLogging()->GetPEAssembly()->GetSimpleName()); + inlineeMethodName.Append(inlineeSimpleName); + inlineeMethodName.Append(W('/')); TypeString::AppendMethodInternal(inlineeMethodName, GetMethod(inlineeHnd), TypeString::FormatBasic); } else { - inlineeMethodName.AppendASCII( "" ); + inlineeMethodName.Append( W("")); } SString inlinerMethodName; if (GetMethod(inlinerHnd)) { - inlinerMethodName.AppendUTF8(GetMethod(inlinerHnd)->GetModule_NoLogging()->GetPEAssembly()->GetSimpleName()); + MAKE_WIDEPTR_FROMUTF8(inlinerSimpleName, GetMethod(inlinerHnd)->GetModule_NoLogging()->GetPEAssembly()->GetSimpleName()); + inlinerMethodName.Append(inlinerSimpleName); inlinerMethodName.Append(L'/'); TypeString::AppendMethodInternal(inlinerMethodName, GetMethod(inlinerHnd), TypeString::FormatBasic); } else { - inlinerMethodName.AppendASCII(""); + inlinerMethodName.Append(W("")); } if (dontInline(inlineResult)) { LOG((LF_JIT, LL_INFO100000, "While compiling '%S', inline of '%S' into '%S' failed because: '%s'.\n", - currentMethodName.GetUnicode(), inlineeMethodName.GetUnicode(), - inlinerMethodName.GetUnicode(), reason)); + (LPCWSTR)currentMethodName, (LPCWSTR)inlineeMethodName, + (LPCWSTR)inlinerMethodName, reason)); } else if(inlineResult == INLINE_PASS) { LOG((LF_JIT, LL_INFO100000, "While compiling '%S', inline of '%S' into '%S' succeeded.\n", - currentMethodName.GetUnicode(), inlineeMethodName.GetUnicode(), - inlinerMethodName.GetUnicode())); + (LPCWSTR)currentMethodName, (LPCWSTR)inlineeMethodName, + (LPCWSTR)inlinerMethodName)); } } @@ -8015,55 +8029,57 @@ void CEEInfo::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd, CLR_JITTRACING_KEYWORD) && (inlineResult <= INLINE_PASS)) // Only report pass, and failure inliner information. The various informative reports such as INLINE_CHECK_CAN_INLINE_SUCCESS are not to be reported via ETW { - SString methodBeingCompiledNames[3]; - SString inlinerNames[3]; - SString inlineeNames[3]; + SString methodBeingCompiledNamespace, methodBeingCompiledMethodName, methodBeingCompiledMethodSignature; + SString inlinerNamespace, inlinerMethodName, inlinerMethodSignature; + SString inlineeNamespace, inlineeMethodName, inlineeMethodSignature; MethodDesc * methodBeingCompiled = m_pMethodBeingCompiled; -#define GMI(pMD, strArray) \ +#define GMI(pMD, targetName) \ do { \ if (pMD) { \ - (pMD)->GetMethodInfo((strArray)[0], (strArray)[1], (strArray)[2]); \ + EString methodName, methodSignature; \ + (pMD)->GetMethodInfo(targetName ## Namespace, methodName, methodSignature); \ + methodName.ConvertToUnicode(targetName ## MethodName); \ + methodSignature.ConvertToUnicode(targetName ## MethodSignature); \ } else { \ - (strArray)[0].Set(W("")); \ - (strArray)[1].Set(W("")); \ - (strArray)[2].Set(W("")); \ + (targetName ## Namespace).Set(W("")); \ + (targetName ## MethodName).Set(W("")); \ + (targetName ## MethodSignature).Set(W("")); \ } } while (0) - GMI(methodBeingCompiled, methodBeingCompiledNames); - GMI(GetMethod(inlinerHnd), inlinerNames); - GMI(GetMethod(inlineeHnd), inlineeNames); + GMI(methodBeingCompiled, methodBeingCompiled); + GMI(GetMethod(inlinerHnd), inliner); + GMI(GetMethod(inlineeHnd), inlinee); #undef GMI if (dontInline(inlineResult)) { const char * str = (reason ? reason : ""); - SString strReason; - strReason.SetANSI(str); - - - FireEtwMethodJitInliningFailed(methodBeingCompiledNames[0].GetUnicode(), - methodBeingCompiledNames[1].GetUnicode(), - methodBeingCompiledNames[2].GetUnicode(), - inlinerNames[0].GetUnicode(), - inlinerNames[1].GetUnicode(), - inlinerNames[2].GetUnicode(), - inlineeNames[0].GetUnicode(), - inlineeNames[1].GetUnicode(), - inlineeNames[2].GetUnicode(), + MAKE_WIDEPTR_FROMANSI(strW, str); + SString strReason(strW); + + FireEtwMethodJitInliningFailed((LPCWSTR)methodBeingCompiledNamespace, + (LPCWSTR)methodBeingCompiledMethodName, + (LPCWSTR)methodBeingCompiledMethodSignature, + (LPCWSTR)inlinerNamespace, + (LPCWSTR)inlinerMethodName, + (LPCWSTR)inlinerMethodSignature, + (LPCWSTR)inlineeNamespace, + (LPCWSTR)inlineeMethodName, + (LPCWSTR)inlineeMethodSignature, inlineResult == INLINE_NEVER, - strReason.GetUnicode(), + (LPCWSTR)strReason, GetClrInstanceId()); } else if(inlineResult == INLINE_PASS) { - FireEtwMethodJitInliningSucceeded(methodBeingCompiledNames[0].GetUnicode(), - methodBeingCompiledNames[1].GetUnicode(), - methodBeingCompiledNames[2].GetUnicode(), - inlinerNames[0].GetUnicode(), - inlinerNames[1].GetUnicode(), - inlinerNames[2].GetUnicode(), - inlineeNames[0].GetUnicode(), - inlineeNames[1].GetUnicode(), - inlineeNames[2].GetUnicode(), + FireEtwMethodJitInliningSucceeded((LPCWSTR)methodBeingCompiledNamespace, + (LPCWSTR)methodBeingCompiledMethodName, + (LPCWSTR)methodBeingCompiledMethodSignature, + (LPCWSTR)inlinerNamespace, + (LPCWSTR)inlinerMethodName, + (LPCWSTR)inlinerMethodSignature, + (LPCWSTR)inlineeNamespace, + (LPCWSTR)inlineeMethodName, + (LPCWSTR)inlineeMethodSignature, GetClrInstanceId()); } @@ -8224,7 +8240,7 @@ void CEEInfo::reportTailCallDecision (CORINFO_METHOD_HANDLE callerHnd, } else { - calleeMethodName.AppendASCII( "" ); + calleeMethodName.Append(W( "" )); } SString callerMethodName; @@ -8235,14 +8251,14 @@ void CEEInfo::reportTailCallDecision (CORINFO_METHOD_HANDLE callerHnd, } else { - callerMethodName.AppendASCII( "" ); + callerMethodName.Append(W( "" )); } if (tailCallResult == TAILCALL_FAIL) { LOG((LF_JIT, LL_INFO100000, "While compiling '%S', %Splicit tail call from '%S' to '%S' failed because: '%s'.\n", - currentMethodName.GetUnicode(), fIsTailPrefix ? W("ex") : W("im"), - callerMethodName.GetUnicode(), calleeMethodName.GetUnicode(), reason)); + (LPCWSTR)currentMethodName, fIsTailPrefix ? W("ex") : W("im"), + (LPCWSTR)callerMethodName, (LPCWSTR)calleeMethodName, reason)); } else { @@ -8252,8 +8268,8 @@ void CEEInfo::reportTailCallDecision (CORINFO_METHOD_HANDLE callerHnd, _ASSERTE(tailCallResult >= 0 && (size_t)tailCallResult < ARRAY_SIZE(tailCallType)); LOG((LF_JIT, LL_INFO100000, "While compiling '%S', %Splicit tail call from '%S' to '%S' generated as a %s.\n", - currentMethodName.GetUnicode(), fIsTailPrefix ? W("ex") : W("im"), - callerMethodName.GetUnicode(), calleeMethodName.GetUnicode(), tailCallType[tailCallResult])); + (LPCWSTR)currentMethodName, fIsTailPrefix ? W("ex") : W("im"), + (LPCWSTR)callerMethodName, (LPCWSTR)calleeMethodName, tailCallType[tailCallResult])); } } @@ -8264,54 +8280,57 @@ void CEEInfo::reportTailCallDecision (CORINFO_METHOD_HANDLE callerHnd, TRACE_LEVEL_VERBOSE, CLR_JITTRACING_KEYWORD)) { - SString methodBeingCompiledNames[3]; - SString callerNames[3]; - SString calleeNames[3]; + SString methodBeingCompiledNamespace, methodBeingCompiledMethodName, methodBeingCompiledMethodSignature; + SString callerNamespace, callerMethodName, callerMethodSignature; + SString calleeNamespace, calleeMethodName, calleeMethodSignature; MethodDesc * methodBeingCompiled = m_pMethodBeingCompiled; -#define GMI(pMD, strArray) \ +#define GMI(pMD, targetName) \ do { \ if (pMD) { \ - (pMD)->GetMethodInfo((strArray)[0], (strArray)[1], (strArray)[2]); \ + EString methodName, methodSignature; \ + (pMD)->GetMethodInfo(targetName ## Namespace, methodName, methodSignature); \ + methodName.ConvertToUnicode(targetName ## MethodName); \ + methodSignature.ConvertToUnicode(targetName ## MethodSignature); \ } else { \ - (strArray)[0].Set(W("")); \ - (strArray)[1].Set(W("")); \ - (strArray)[2].Set(W("")); \ + (targetName ## Namespace).Set(W("")); \ + (targetName ## MethodName).Set(W("")); \ + (targetName ## MethodSignature).Set(W("")); \ } } while (0) - GMI(methodBeingCompiled, methodBeingCompiledNames); - GMI(GetMethod(callerHnd), callerNames); - GMI(GetMethod(calleeHnd), calleeNames); + GMI(methodBeingCompiled, methodBeingCompiled); + GMI(GetMethod(callerHnd), caller); + GMI(GetMethod(calleeHnd), callee); #undef GMI if (tailCallResult == TAILCALL_FAIL) { const char * str = (reason ? reason : ""); - SString strReason; - strReason.SetANSI(str); - - FireEtwMethodJitTailCallFailed(methodBeingCompiledNames[0].GetUnicode(), - methodBeingCompiledNames[1].GetUnicode(), - methodBeingCompiledNames[2].GetUnicode(), - callerNames[0].GetUnicode(), - callerNames[1].GetUnicode(), - callerNames[2].GetUnicode(), - calleeNames[0].GetUnicode(), - calleeNames[1].GetUnicode(), - calleeNames[2].GetUnicode(), + MAKE_WIDEPTR_FROMANSI(strW, str); + SString strReason(strW); + + FireEtwMethodJitTailCallFailed((LPCWSTR)methodBeingCompiledNamespace, + (LPCWSTR)methodBeingCompiledMethodName, + (LPCWSTR)methodBeingCompiledMethodSignature, + (LPCWSTR)callerNamespace, + (LPCWSTR)callerMethodName, + (LPCWSTR)callerMethodSignature, + (LPCWSTR)calleeNamespace, + (LPCWSTR)calleeMethodName, + (LPCWSTR)calleeMethodSignature, fIsTailPrefix, - strReason.GetUnicode(), + (LPCWSTR)strReason, GetClrInstanceId()); } else { - FireEtwMethodJitTailCallSucceeded(methodBeingCompiledNames[0].GetUnicode(), - methodBeingCompiledNames[1].GetUnicode(), - methodBeingCompiledNames[2].GetUnicode(), - callerNames[0].GetUnicode(), - callerNames[1].GetUnicode(), - callerNames[2].GetUnicode(), - calleeNames[0].GetUnicode(), - calleeNames[1].GetUnicode(), - calleeNames[2].GetUnicode(), + FireEtwMethodJitTailCallSucceeded((LPCWSTR)methodBeingCompiledNamespace, + (LPCWSTR)methodBeingCompiledMethodName, + (LPCWSTR)methodBeingCompiledMethodSignature, + (LPCWSTR)callerNamespace, + (LPCWSTR)callerMethodName, + (LPCWSTR)callerMethodSignature, + (LPCWSTR)calleeNamespace, + (LPCWSTR)calleeMethodName, + (LPCWSTR)calleeMethodSignature, fIsTailPrefix, tailCallResult, GetClrInstanceId()); @@ -9139,8 +9158,10 @@ const char* CEEInfo::getFieldName (CORINFO_FIELD_HANDLE fieldHnd, const char** s if (!t.IsNull()) { #ifdef _DEBUG - t.GetName(ssClsNameBuff); - *scopeName = ssClsNameBuff.GetUTF8(ssClsNameBuffScratch); + SString className; + t.GetName(className); + className.ConvertToUTF8(ssClsNameBuff); + *scopeName = (LPCUTF8)ssClsNameBuff; #else // !_DEBUG // since this is for diagnostic purposes only, // give up on the namespace, as we don't have a buffer to concat it @@ -10659,7 +10680,7 @@ int CEEInfo::doAssert(const char* szFile, int iLine, const char* szExpr) W("%hs\n") W(" File: %hs Line: %d\n"), szExpr, szFile, iLine); - COMPlusThrowNonLocalized(kInvalidProgramException, output.GetUnicode()); + COMPlusThrowNonLocalized(kInvalidProgramException, (LPCWSTR)output); } result = _DbgBreakCheck(szFile, iLine, szExpr); @@ -12259,7 +12280,7 @@ static CorJitResult CompileMethodWithEtwWrapper(EEJitManager *jitMgr, STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_MODE_PREEMPTIVE; - SString namespaceOrClassName, methodName, methodSignature; + EString namespaceOrClassName, methodName, methodSignature; // Fire an ETW event to mark the beginning of JIT'ing ETW::MethodLog::MethodJitting(reinterpret_cast(info->ftn), &namespaceOrClassName, &methodName, &methodSignature); @@ -12771,12 +12792,12 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, if (LoggingOn(LF_JIT, LL_INFO10000)) TypeString::AppendMethodDebug(methodString, ftn); - LOG((LF_JIT, LL_INFO10000, "{ Jitting method (%p) %S %s\n", ftn, methodString.GetUnicode(), ftn->m_pszDebugMethodSignature)); + LOG((LF_JIT, LL_INFO10000, "{ Jitting method (%p) %S %s\n", ftn, (LPCWSTR)methodString, ftn->m_pszDebugMethodSignature)); } #if 0 - if (!SString::_stricmp(cls,"ENC") && - (!SString::_stricmp(name,"G"))) + if (!StaticStringHelpers::_stricmp(cls,"ENC") && + (!StaticStringHelpers::_stricmp(name,"G"))) { static count = 0; count++; @@ -12806,7 +12827,7 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, if (LoggingOn(LF_VERIFIER, LL_INFO100)) TypeString::AppendMethodDebug(methodString, ftn); - LOG((LF_VERIFIER, LL_INFO100, "{ Will verify method (%p) %S %s\n", ftn, methodString.GetUnicode(), ftn->m_pszDebugMethodSignature)); + LOG((LF_VERIFIER, LL_INFO100, "{ Will verify method (%p) %S %s\n", ftn, (LPCWSTR)methodString, ftn->m_pszDebugMethodSignature)); } #endif //_DEBUG @@ -12939,16 +12960,16 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, SString moduleName; ftn->GetModule()->GetDomainAssembly()->GetPEAssembly()->GetPathOrCodeBase(moduleName); - MAKE_UTF8PTR_FROMWIDE(moduleNameUtf8, moduleName.GetUnicode()); + MAKE_UTF8PTR_FROMWIDE(moduleNameUtf8, moduleName); - SString codeBase; + EString codeBase; codeBase.AppendPrintf("%s,0x%x,%d,%d\n", moduleNameUtf8, //module name ftn->GetMemberDef(), //method token (unsigned)(methodJitTimeStop.QuadPart - methodJitTimeStart.QuadPart), //cycle count methodInfo.ILCodeSize //il size ); - OutputDebugStringUtf8(codeBase.GetUTF8NoConvert()); + OutputDebugStringUtf8(codeBase); } #endif // PERF_TRACK_METHOD_JITTIMES @@ -13731,21 +13752,20 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, else { // Verification failures are failfast events - DefineFullyQualifiedNameForClassW(); - SString fatalErrorString; - fatalErrorString.Printf(W("Verify_TypeLayout '%s' failed to verify type layout"), - GetFullyQualifiedNameForClassW(pMT)); + DefineFullyQualifiedNameForClass(); + EString fatalErrorString; + fatalErrorString.Printf("Verify_TypeLayout '%s' failed to verify type layout", + GetFullyQualifiedNameForClass(pMT)); #ifdef _DEBUG { - StackScratchBuffer buf; - _ASSERTE_MSG(false, fatalErrorString.GetUTF8(buf)); + _ASSERTE_MSG(false, fatalErrorString); // Run through the type layout logic again, after the assert, makes debugging easy TypeLayoutCheck(pMT, pBlob, /* printDiff */ TRUE); } #endif - EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(-1, fatalErrorString.GetUnicode()); + EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(-1, (LPCWSTR)fatalErrorString.MoveToUnicode()); return FALSE; } } @@ -13804,13 +13824,13 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, if ((fieldOffset != actualFieldOffset) || (baseOffset != actualBaseOffset)) { // Verification failures are failfast events - DefineFullyQualifiedNameForClassW(); - SString ssFieldName(SString::Utf8, pField->GetName()); + DefineFullyQualifiedNameForClass(); + EString ssFieldName(pField->GetName()); - SString fatalErrorString; - fatalErrorString.Printf(W("Verify_FieldOffset '%s.%s' Field offset %d!=%d(actual) || baseOffset %d!=%d(actual)"), - GetFullyQualifiedNameForClassW(pEnclosingMT), - ssFieldName.GetUnicode(), + EString fatalErrorString; + fatalErrorString.Printf("Verify_FieldOffset '%s.%s' Field offset %d!=%d(actual) || baseOffset %d!=%d(actual)", + (LPCUTF8)GetFullyQualifiedNameForClass(pEnclosingMT), + (LPCUTF8)ssFieldName, fieldOffset, actualFieldOffset, baseOffset, @@ -13818,12 +13838,11 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, #ifdef _DEBUG { - StackScratchBuffer buf; - _ASSERTE_MSG(false, fatalErrorString.GetUTF8(buf)); + _ASSERTE_MSG(false, fatalErrorString); } #endif - EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(-1, fatalErrorString.GetUnicode()); + EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(-1, (LPCWSTR)fatalErrorString.MoveToUnicode()); return FALSE; } result = 1; @@ -13932,20 +13951,21 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, SString fatalErrorString; fatalErrorString.Printf(W("Verify_VirtualFunctionOverride Decl Method '%s' on type '%s' is '%s'(actual) instead of expected '%s'(from compiler)"), - methodNameDecl.GetUnicode(), - GetFullyQualifiedNameForClassW(thImpl.GetMethodTable()), - methodNameImplRuntime.GetUnicode(), - methodNameImplCompiler.GetUnicode()); + (LPCWSTR)methodNameDecl, + (LPCWSTR)GetFullyQualifiedNameForClassW(thImpl.GetMethodTable()), + (LPCWSTR)methodNameImplRuntime, + (LPCWSTR)methodNameImplCompiler); #ifdef _DEBUG { - StackScratchBuffer buf; - _ASSERTE_MSG(false, fatalErrorString.GetUTF8(buf)); + EString buf; + fatalErrorString.ConvertToUTF8(buf); + _ASSERTE_MSG(false, buf); } #endif _ASSERTE(!IsDebuggerPresent() && "Stop on assert here instead of fatal error for ease of live debugging"); - EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(-1, fatalErrorString.GetUnicode()); + EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(-1, (LPCWSTR)fatalErrorString); return FALSE; } diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 492b2fbe5fe12e..80d458c8a96ba0 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -519,8 +519,7 @@ class CEEInfo : public ICorJitInfo #endif #ifdef _DEBUG - InlineSString ssClsNameBuff; - ScratchBuffer ssClsNameBuffScratch; + InlineEString ssClsNameBuff; #endif public: diff --git a/src/coreclr/vm/marshalnative.cpp b/src/coreclr/vm/marshalnative.cpp index ad9bc0fa3feb04..617300e1b56016 100644 --- a/src/coreclr/vm/marshalnative.cpp +++ b/src/coreclr/vm/marshalnative.cpp @@ -274,7 +274,7 @@ FCIMPL2(UINT32, MarshalNative::SizeOfClass, ReflectClassBaseObject* refClassUNSA // It isn't marshalable so throw an ArgumentException. StackSString strTypeName; TypeString::AppendType(strTypeName, th); - COMPlusThrow(kArgumentException, IDS_CANNOT_MARSHAL, strTypeName.GetUnicode(), NULL, NULL); + COMPlusThrow(kArgumentException, IDS_CANNOT_MARSHAL, strTypeName, NULL, NULL); } } @@ -319,7 +319,7 @@ FCIMPL1(UINT32, MarshalNative::OffsetOfHelper, ReflectFieldObject *pFieldUNSAFE) // It isn't marshalable so throw an ArgumentException. StackSString strTypeName; TypeString::AppendType(strTypeName, th); - COMPlusThrow(kArgumentException, IDS_CANNOT_MARSHAL, strTypeName.GetUnicode(), NULL, NULL); + COMPlusThrow(kArgumentException, IDS_CANNOT_MARSHAL, strTypeName, NULL, NULL); } EEClassNativeLayoutInfo const* pNativeLayoutInfo = th.GetMethodTable()->GetNativeLayoutInfo(); diff --git a/src/coreclr/vm/memberload.cpp b/src/coreclr/vm/memberload.cpp index 57e4bd342e4e7e..a69780456a49c5 100644 --- a/src/coreclr/vm/memberload.cpp +++ b/src/coreclr/vm/memberload.cpp @@ -1085,7 +1085,7 @@ MemberLoader::FindMethod( // Retrieve the right comparition function to use. UTF8StringCompareFuncPtr StrCompFunc = FM_GetStrCompFunc(flags); - SString targetName(SString::Utf8Literal, pszName); + EString targetName(EString::Literal, pszName); ULONG targetNameHash = targetName.HashCaseInsensitive(); // Statistically it's most likely for a method to be found in non-vtable portion of this class's members, then in the @@ -1254,7 +1254,7 @@ MemberLoader::FindMethodByName(MethodTable * pMT, LPCUTF8 pszName, FM_Flags flag // Retrieve the right comparison function to use. UTF8StringCompareFuncPtr StrCompFunc = FM_GetStrCompFunc(flags); - SString targetName(SString::Utf8, pszName); + EString targetName(pszName); ULONG targetNameHash = targetName.HashCaseInsensitive(); // Scan all classes in the hierarchy, starting at the current class and @@ -1483,7 +1483,7 @@ MemberLoader::FindField(MethodTable * pMT, LPCUTF8 pszName, PCCOR_SIGNATURE pSig if (pMT->IsArray()) return NULL; - SString targetName(SString::Utf8Literal, pszName); + EString targetName(EString::Literal, pszName); ULONG targetNameHash = targetName.HashCaseInsensitive(); EEClass * pClass = pMT->GetClass(); diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 8b7f075c1b50b7..4fae4a6759c5e1 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -290,7 +290,7 @@ LPCUTF8 MethodDesc::GetName() /* * Function to get a method's name, its namespace */ -VOID MethodDesc::GetMethodInfoNoSig(SString &namespaceOrClassName, SString &methodName) +VOID MethodDesc::GetMethodInfoNoSig(SString &namespaceOrClassName, EString &methodName) { static LPCWSTR pDynamicClassName = W("dynamicClass"); @@ -301,13 +301,13 @@ VOID MethodDesc::GetMethodInfoNoSig(SString &namespaceOrClassName, SString &meth TypeString::AppendType(namespaceOrClassName, TypeHandle(GetMethodTable())); // name - methodName.AppendUTF8(GetName()); + methodName.Append(GetName()); } /* * Function to get a method's name, its namespace and signature (legacy format) */ -VOID MethodDesc::GetMethodInfo(SString &namespaceOrClassName, SString &methodName, SString &methodSignature) +VOID MethodDesc::GetMethodInfo(SString &namespaceOrClassName, EString &methodName, EString &methodSignature) { GetMethodInfoNoSig(namespaceOrClassName, methodName); @@ -318,13 +318,13 @@ VOID MethodDesc::GetMethodInfo(SString &namespaceOrClassName, SString &methodNam GetSig(&pSig, &cSig); PrettyPrintSigInternalLegacy(pSig, cSig, " ", &qbOut, GetMDImport()); - methodSignature.AppendUTF8((char *)qbOut.Ptr()); + methodSignature.Append((char *)qbOut.Ptr()); } /* * Function to get a method's name, its namespace and signature (new format) */ -VOID MethodDesc::GetMethodInfoWithNewSig(SString &namespaceOrClassName, SString &methodName, SString &methodSignature) +VOID MethodDesc::GetMethodInfoWithNewSig(SString &namespaceOrClassName, EString &methodName, EString &methodSignature) { GetMethodInfoNoSig(namespaceOrClassName, methodName); @@ -335,7 +335,7 @@ VOID MethodDesc::GetMethodInfoWithNewSig(SString &namespaceOrClassName, SString GetSig(&pSig, &cSig); PrettyPrintSig(pSig, (DWORD)cSig, "", &qbOut, GetMDImport(), NULL); - methodSignature.AppendUTF8((char *)qbOut.Ptr()); + methodSignature.Append((char *)qbOut.Ptr()); } /* @@ -344,7 +344,8 @@ VOID MethodDesc::GetMethodInfoWithNewSig(SString &namespaceOrClassName, SString */ VOID MethodDesc::GetFullMethodInfo(SString& fullMethodSigName) { - SString namespaceOrClassName, methodName; + SString namespaceOrClassName; + EString methodName; GetMethodInfoNoSig(namespaceOrClassName, methodName); // signature @@ -352,19 +353,19 @@ VOID MethodDesc::GetFullMethodInfo(SString& fullMethodSigName) ULONG cSig = 0; PCCOR_SIGNATURE pSig; - SString methodFullName; - StackScratchBuffer namespaceNameBuffer, methodNameBuffer; + EString methodFullName; + StackEString namespaceNameBuffer(namespaceOrClassName.MoveToUTF8()); methodFullName.AppendPrintf( (LPCUTF8)"[%s] %s::%s", GetModule()->GetAssembly()->GetSimpleName(), - namespaceOrClassName.GetUTF8(namespaceNameBuffer), - methodName.GetUTF8(methodNameBuffer)); + (LPCUTF8)namespaceNameBuffer, + (LPCUTF8)methodName); GetSig(&pSig, &cSig); - StackScratchBuffer buffer; - PrettyPrintSig(pSig, (DWORD)cSig, methodFullName.GetUTF8(buffer), &qbOut, GetMDImport(), NULL); - fullMethodSigName.AppendUTF8((char *)qbOut.Ptr()); + PrettyPrintSig(pSig, (DWORD)cSig, (LPCUTF8)methodFullName, &qbOut, GetMDImport(), NULL); + MAKE_WIDEPTR_FROMUTF8(sigStr, (char*)qbOut.Ptr()); + fullMethodSigName.Append(sigStr); } #endif @@ -3695,11 +3696,11 @@ void ComPlusCallMethodDesc::InitComEventCallInfo() pItfMT->_GetFullyQualifiedNameForClass(ssEvItfName); // Convert the method name to unicode. - StackSString ssMethodName(SString::Utf8, pItfMD->GetName()); + MAKE_WIDEPTR_FROMUTF8(ssMethodName, pItfMD->GetName()); // Throw the exception. COMPlusThrow(kTypeLoadException, IDS_EE_METHOD_NOT_FOUND_ON_EV_PROV, - ssMethodName.GetUnicode(), ssEvItfName.GetUnicode(), ssEvProvClassName.GetUnicode()); + (LPCWSTR)ssMethodName, (LPCWSTR)ssEvItfName, (LPCWSTR)ssEvProvClassName); } } #endif // FEATURE_COMINTEROP diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index bc58090dd587d7..7ad0f6000c8c04 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -1642,9 +1642,9 @@ class MethodDesc PCODE DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMode = CallerGCMode::Unknown); - VOID GetMethodInfo(SString &namespaceOrClassName, SString &methodName, SString &methodSignature); - VOID GetMethodInfoWithNewSig(SString &namespaceOrClassName, SString &methodName, SString &methodSignature); - VOID GetMethodInfoNoSig(SString &namespaceOrClassName, SString &methodName); + VOID GetMethodInfo(SString &namespaceOrClassName, EString &methodName, EString &methodSignature); + VOID GetMethodInfoWithNewSig(SString &namespaceOrClassName, EString &methodName, EString &methodSignature); + VOID GetMethodInfoNoSig(SString &namespaceOrClassName, EString &methodName); VOID GetFullMethodInfo(SString& fullMethodSigName); typedef void (*WalkValueTypeParameterFnPtr)(Module *pModule, mdToken token, Module *pDefModule, mdToken tkDefToken, const SigParser *ptr, SigTypeContext *pTypeContext, void *pData); diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index 013b201f653d9b..d3fd3d226b0003 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -4188,7 +4188,7 @@ static VOID DoAccessibilityCheck(MethodTable *pAskingMT, MethodTable *pTargetMT, _ASSERTE((resIDWhy == (UINT)E_ACCESSDENIED) || (resIDWhy == (UINT)IDS_CLASSLOAD_INTERFACE_NO_ACCESS)); TypeString::AppendType(targetName, TypeHandle((resIDWhy == (UINT)E_ACCESSDENIED) ? pTargetMT : pAskingMT)); - COMPlusThrow(kTypeLoadException, resIDWhy, targetName.GetUnicode(), displayName.GetUnicode()); + COMPlusThrow(kTypeLoadException, resIDWhy, (LPCWSTR)targetName, (LPCWSTR)displayName); } } @@ -4656,7 +4656,7 @@ void MethodTable::DoFullyLoad(Generics::RecursionGraph * const pVisited, const { SString name; TypeString::AppendTypeDebug(name, this); - LOG((LF_CLASSLOADER, LL_INFO10000, "PHASEDLOAD: Completed full dependency load of type %S\n", name.GetUnicode())); + LOG((LF_CLASSLOADER, LL_INFO10000, "PHASEDLOAD: Completed full dependency load of type %S\n", (LPCWSTR)name)); } #endif diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index ffb90a935cacf2..f8bc03af29d001 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -1342,15 +1342,18 @@ MethodTableBuilder::BuildMethodTableThrowing( pszDebugName = pszDebugNamespace = "Invalid TypeDef record"; } - StackSString debugName(SString::Utf8, pszDebugName); + StackEString debugName(pszDebugName); // If there is an instantiation, update the debug name to include instantiation type names. if (bmtGenerics->HasInstantiation()) { - StackSString debugName(SString::Utf8, GetDebugClassName()); - TypeString::AppendInst(debugName, bmtGenerics->GetInstantiation(), TypeString::FormatBasic); - StackScratchBuffer buff; - const char* pDebugNameUTF8 = debugName.GetUTF8(buff); + StackEString debugName(GetDebugClassName()); + StackSString instantiation; + TypeString::AppendInst(instantiation, bmtGenerics->GetInstantiation(), TypeString::FormatBasic); + StackEString instantiationUTF8; + instantiation.ConvertToUTF8(instantiationUTF8); + debugName.Append(instantiationUTF8); + const char* pDebugNameUTF8 = (LPCUTF8)debugName; S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8)) + S_SIZE_T(1); if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); @@ -1362,10 +1365,10 @@ MethodTableBuilder::BuildMethodTableThrowing( pszDebugName = (LPCUTF8)name; } - LOG((LF_CLASSLOADER, LL_INFO1000, "Loading class \"%s%s%S\" from module \"%ws\" in domain 0x%p %s\n", + LOG((LF_CLASSLOADER, LL_INFO1000, "Loading class \"%s%s%s\" from module \"%ws\" in domain 0x%p %s\n", *pszDebugNamespace ? pszDebugNamespace : "", *pszDebugNamespace ? NAMESPACE_SEPARATOR_STR : "", - debugName.GetUnicode(), + (LPCUTF8)debugName, pModule->GetDebugName(), pModule->GetDomain(), (pModule->IsSystem()) ? "System Domain" : "" @@ -1894,8 +1897,9 @@ MethodTableBuilder::BuildMethodTableThrowing( MethodDesc *pMD = methIt->GetUnboxedMethodDesc(); StackSString name; TypeString::AppendMethodDebug(name, pMD); - StackScratchBuffer buff; - const char* pDebugNameUTF8 = name.GetUTF8(buff); + StackEString nameUTF8; + name.ConvertToUTF8(nameUTF8); + const char* pDebugNameUTF8 = (LPCUTF8)nameUTF8; S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8)) + S_SIZE_T(1); if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); size_t len = safeLen.Value(); @@ -1906,11 +1910,11 @@ MethodTableBuilder::BuildMethodTableThrowing( { MethodDesc *pMD = methIt->GetMethodDesc(); - StackSString name; TypeString::AppendMethodDebug(name, pMD); - StackScratchBuffer buff; - const char* pDebugNameUTF8 = name.GetUTF8(buff); + StackEString nameUTF8; + name.ConvertToUTF8(nameUTF8); + const char* pDebugNameUTF8 = (LPCUTF8)nameUTF8; S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8))+S_SIZE_T(1); if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); size_t len = safeLen.Value(); diff --git a/src/coreclr/vm/mlinfo.cpp b/src/coreclr/vm/mlinfo.cpp index 471cbb1165aaf6..7c98811f591178 100644 --- a/src/coreclr/vm/mlinfo.cpp +++ b/src/coreclr/vm/mlinfo.cpp @@ -32,8 +32,8 @@ static const char ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE[] = {""}; static const int ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE_LEN = ARRAY_SIZE(ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE); - DEFINE_ASM_QUAL_TYPE_NAME(COLOR_TRANSLATOR_ASM_QUAL_TYPE_NAME, g_ColorTranslatorClassName, g_DrawingAsmName); - DEFINE_ASM_QUAL_TYPE_NAME(COLOR_ASM_QUAL_TYPE_NAME, g_ColorClassName, g_DrawingAsmName); + DEFINE_ASM_QUAL_TYPE_NAME_W(COLOR_TRANSLATOR_ASM_QUAL_TYPE_NAME_W, g_ColorTranslatorClassName, g_DrawingAsmName); + DEFINE_ASM_QUAL_TYPE_NAME_W(COLOR_ASM_QUAL_TYPE_NAME_W, g_ColorClassName, g_DrawingAsmName); #define OLECOLOR_TO_SYSTEMCOLOR_METH_NAME "FromOle" #define SYSTEMCOLOR_TO_OLECOLOR_METH_NAME "ToOle" @@ -665,9 +665,9 @@ VOID ThrowInteropParamException(UINT resID, UINT paramIdx) paramString.Printf(W("parameter #%u"), paramIdx); SString errorString(W("Unknown error.")); - errorString.LoadResource(CCompRC::Error, resID); + LoadResource(errorString, CCompRC::Error, resID); - COMPlusThrow(kMarshalDirectiveException, IDS_EE_BADMARSHAL_ERROR_MSG, paramString.GetUnicode(), errorString.GetUnicode()); + COMPlusThrow(kMarshalDirectiveException, IDS_EE_BADMARSHAL_ERROR_MSG, paramString, errorString); } #ifdef _DEBUG @@ -758,15 +758,15 @@ OleColorMarshalingInfo::OleColorMarshalingInfo() : } CONTRACTL_END; - SString qualifiedColorTranslatorTypeName(SString::Utf8, COLOR_TRANSLATOR_ASM_QUAL_TYPE_NAME); + SString qualifiedColorTranslatorTypeName(COLOR_TRANSLATOR_ASM_QUAL_TYPE_NAME_W); // Load the color translator class. - TypeHandle hndColorTranslatorType = TypeName::GetTypeFromAsmQualifiedName(qualifiedColorTranslatorTypeName.GetUnicode()); + TypeHandle hndColorTranslatorType = TypeName::GetTypeFromAsmQualifiedName(qualifiedColorTranslatorTypeName); - SString qualifiedColorTypeName(SString::Utf8, COLOR_ASM_QUAL_TYPE_NAME); + SString qualifiedColorTypeName(COLOR_ASM_QUAL_TYPE_NAME_W); // Load the color class. - m_hndColorType = TypeName::GetTypeFromAsmQualifiedName(qualifiedColorTypeName.GetUnicode()); + m_hndColorType = TypeName::GetTypeFromAsmQualifiedName(qualifiedColorTypeName); // Retrieve the method to convert an OLE_COLOR to a System.Drawing.Color. m_OleColorToSystemColorMD = MemberLoader::FindMethodByName(hndColorTranslatorType.GetMethodTable(), OLECOLOR_TO_SYSTEMCOLOR_METH_NAME); @@ -912,11 +912,11 @@ CustomMarshalerHelper *EEMarshalingData::GetCustomMarshalerHelper(Assembly *pAss _ASSERTE(strMarshalerTypeName && strCookie && !hndManagedType.IsNull()); // Append a NULL terminator to the marshaler type name. - SString strCMMarshalerTypeName(SString::Utf8, strMarshalerTypeName, cMarshalerTypeNameBytes); + EString strCMMarshalerTypeName(strMarshalerTypeName, cMarshalerTypeNameBytes); // Load the custom marshaler class. BOOL fNameIsAsmQualified = FALSE; - hndCustomMarshalerType = TypeName::GetTypeUsingCASearchRules(strCMMarshalerTypeName.GetUTF8NoConvert(), pAssembly, &fNameIsAsmQualified); + hndCustomMarshalerType = TypeName::GetTypeUsingCASearchRules((LPCUTF8)strCMMarshalerTypeName, pAssembly, &fNameIsAsmQualified); if (hndCustomMarshalerType.IsGenericTypeDefinition()) { @@ -2065,11 +2065,10 @@ MarshalInfo::MarshalInfo(Module* pModule, { if (ParamInfo.m_cSafeArrayUserDefTypeNameBytes > 0) { - // Load the type. Use an SString for the string since we need to NULL terminate the string + // Load the type. Use an EString for the string since we need to NULL terminate the string // that comes from the metadata. - StackScratchBuffer utf8Name; - SString safeArrayUserDefTypeName(SString::Utf8, ParamInfo.m_strSafeArrayUserDefTypeName, ParamInfo.m_cSafeArrayUserDefTypeNameBytes); - thElement = TypeName::GetTypeUsingCASearchRules(safeArrayUserDefTypeName.GetUTF8(utf8Name), pAssembly); + EString safeArrayUserDefTypeName(ParamInfo.m_strSafeArrayUserDefTypeName, ParamInfo.m_cSafeArrayUserDefTypeNameBytes); + thElement = TypeName::GetTypeUsingCASearchRules(safeArrayUserDefTypeName, pAssembly); } } else @@ -2529,14 +2528,15 @@ void MarshalInfo::ThrowTypeLoadExceptionForInvalidFieldMarshal(FieldDesc* pField { DefineFullyQualifiedNameForClassW(); - StackSString ssFieldName(SString::Utf8, pFieldDesc->GetName()); + StackSString ssFieldName; + StackEString(pFieldDesc->GetName()).ConvertToUnicode(ssFieldName); StackSString errorString(W("Unknown error.")); - errorString.LoadResource(CCompRC::Error, resID); + LoadResource(errorString, CCompRC::Error, resID); COMPlusThrow(kTypeLoadException, IDS_EE_BADMARSHALFIELD_ERROR_MSG, GetFullyQualifiedNameForClassW(pFieldDesc->GetEnclosingMethodTable()), - ssFieldName.GetUnicode(), errorString.GetUnicode()); + ssFieldName, errorString); } @@ -3252,34 +3252,33 @@ VOID MarshalInfo::DumpMarshalInfo(Module* pModule, SigPointer sig, const SigType if (LoggingOn(LF_MARSHALER, LL_INFO10)) { - SString logbuf; - StackScratchBuffer scratch; + EString logbuf; IMDInternalImport *pInternalImport = pModule->GetMDImport(); - logbuf.AppendASCII("------------------------------------------------------------\n"); - LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch))); + logbuf.Append("------------------------------------------------------------\n"); + LOG((LF_MARSHALER, LL_INFO10, (LPCUTF8)logbuf)); logbuf.Clear(); - logbuf.AppendASCII("Managed type: "); + logbuf.Append("Managed type: "); if (m_byref) - logbuf.AppendASCII("Byref "); + logbuf.Append("Byref "); TypeHandle th = sig.GetTypeHandleNT(pModule, pTypeContext); if (th.IsNull()) - logbuf.AppendASCII(""); + logbuf.Append(""); else { SigFormat sigfmt; sigfmt.AddType(th); - logbuf.AppendUTF8(sigfmt.GetCString()); + logbuf.Append(sigfmt.GetCString()); } - logbuf.AppendASCII("\n"); - LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch))); + logbuf.Append("\n"); + LOG((LF_MARSHALER, LL_INFO10, (LPCUTF8)logbuf)); logbuf.Clear(); - logbuf.AppendASCII("NativeType : "); + logbuf.Append("NativeType : "); PCCOR_SIGNATURE pvNativeType; ULONG cbNativeType; if (token == mdParamDefNil @@ -3287,7 +3286,7 @@ VOID MarshalInfo::DumpMarshalInfo(Module* pModule, SigPointer sig, const SigType &pvNativeType, &cbNativeType) != S_OK) { - logbuf.AppendASCII(""); + logbuf.Append(""); } else { @@ -3296,10 +3295,10 @@ VOID MarshalInfo::DumpMarshalInfo(Module* pModule, SigPointer sig, const SigType { char num[100]; sprintf_s(num, ARRAY_SIZE(num), "0x%lx ", (ULONG)*pvNativeType); - logbuf.AppendASCII(num); + logbuf.Append(num); switch (*(pvNativeType++)) { -#define XXXXX(nt) case nt: logbuf.AppendASCII("(" #nt ")"); break; +#define XXXXX(nt) case nt: logbuf.Append("(" #nt ")"); break; XXXXX(NATIVE_TYPE_BOOLEAN) XXXXX(NATIVE_TYPE_I1) @@ -3356,65 +3355,65 @@ VOID MarshalInfo::DumpMarshalInfo(Module* pModule, SigPointer sig, const SigType case NATIVE_TYPE_CUSTOMMARSHALER: { int strLen = 0; - logbuf.AppendASCII("(NATIVE_TYPE_CUSTOMMARSHALER)"); + logbuf.Append("(NATIVE_TYPE_CUSTOMMARSHALER)"); // Skip the typelib guid. - logbuf.AppendASCII(" "); + logbuf.Append(" "); strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType); if (strLen) { - BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen); + BYTE* p = (BYTE*)logbuf.OpenBuffer(strLen); memcpyNoGCRefs(p, pvNativeType, strLen); logbuf.CloseBuffer(); - logbuf.AppendASCII("\0"); + logbuf.Append("\0"); pvNativeType += strLen; cbNativeType -= strLen + 1; // Skip the name of the native type. - logbuf.AppendASCII(" "); + logbuf.Append(" "); } strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType); if (strLen) { - BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen); + BYTE* p = (BYTE*)logbuf.OpenBuffer(strLen); memcpyNoGCRefs(p, pvNativeType, strLen); logbuf.CloseBuffer(); - logbuf.AppendASCII("\0"); + logbuf.Append("\0"); pvNativeType += strLen; cbNativeType -= strLen + 1; // Extract the name of the custom marshaler. - logbuf.AppendASCII(" "); + logbuf.Append(" "); } strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType); if (strLen) { - BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen); + BYTE* p = (BYTE*)logbuf.OpenBuffer(strLen); memcpyNoGCRefs(p, pvNativeType, strLen); logbuf.CloseBuffer(); - logbuf.AppendASCII("\0"); + logbuf.Append("\0"); pvNativeType += strLen; cbNativeType -= strLen + 1; // Extract the cookie string. - logbuf.AppendASCII(" "); + logbuf.Append(" "); } strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType); if (strLen) { - BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen); + BYTE* p = (BYTE*)logbuf.OpenBuffer(strLen); memcpyNoGCRefs(p, pvNativeType, strLen); logbuf.CloseBuffer(); - logbuf.AppendASCII("\0"); + logbuf.Append("\0"); pvNativeType += strLen; cbNativeType -= strLen + 1; @@ -3424,42 +3423,42 @@ VOID MarshalInfo::DumpMarshalInfo(Module* pModule, SigPointer sig, const SigType } default: - logbuf.AppendASCII("(?)"); + logbuf.Append("(?)"); } - logbuf.AppendASCII(" "); + logbuf.Append(" "); } } - logbuf.AppendASCII("\n"); - LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch))); + logbuf.Append("\n"); + LOG((LF_MARSHALER, LL_INFO10, (LPCUTF8)logbuf)); logbuf.Clear(); - logbuf.AppendASCII("MarshalType : "); + logbuf.Append("MarshalType : "); { char num[100]; sprintf_s(num, ARRAY_SIZE(num), "0x%lx ", (ULONG)m_type); - logbuf.AppendASCII(num); + logbuf.Append(num); } switch (m_type) { - #define DEFINE_MARSHALER_TYPE(mt, mc) case mt: logbuf.AppendASCII( #mt " (IL" #mc ")"); break; + #define DEFINE_MARSHALER_TYPE(mt, mc) case mt: logbuf.Append( #mt " (IL" #mc ")"); break; #include "mtypes.h" case MARSHAL_TYPE_UNKNOWN: - logbuf.AppendASCII("MARSHAL_TYPE_UNKNOWN (illegal combination)"); + logbuf.Append("MARSHAL_TYPE_UNKNOWN (illegal combination)"); break; default: - logbuf.AppendASCII("MARSHAL_TYPE_???"); + logbuf.Append("MARSHAL_TYPE_???"); break; } - logbuf.AppendASCII("\n"); + logbuf.Append("\n"); - logbuf.AppendASCII("Metadata In/Out : "); + logbuf.Append("Metadata In/Out : "); if (TypeFromToken(token) != mdtParamDef || token == mdParamDefNil) - logbuf.AppendASCII(""); + logbuf.Append(""); else { @@ -3468,30 +3467,30 @@ VOID MarshalInfo::DumpMarshalInfo(Module* pModule, SigPointer sig, const SigType LPCSTR szParamName_Ignore; if (FAILED(pInternalImport->GetParamDefProps(token, &usSequence, &dwAttr, &szParamName_Ignore))) { - logbuf.AppendASCII("Invalid ParamDef record "); + logbuf.Append("Invalid ParamDef record "); } else { if (IsPdIn(dwAttr)) - logbuf.AppendASCII("In "); + logbuf.Append("In "); if (IsPdOut(dwAttr)) - logbuf.AppendASCII("Out "); + logbuf.Append("Out "); } } - logbuf.AppendASCII("\n"); + logbuf.Append("\n"); - logbuf.AppendASCII("Effective In/Out : "); + logbuf.Append("Effective In/Out : "); if (m_in) - logbuf.AppendASCII("In "); + logbuf.Append("In "); if (m_out) - logbuf.AppendASCII("Out "); + logbuf.Append("Out "); - logbuf.AppendASCII("\n"); + logbuf.Append("\n"); - LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch))); + LOG((LF_MARSHALER, LL_INFO10, (LPCUTF8)logbuf)); logbuf.Clear(); } } // MarshalInfo::DumpMarshalInfo diff --git a/src/coreclr/vm/multicorejit.cpp b/src/coreclr/vm/multicorejit.cpp index 1a697a283bdda3..84983860d8cff2 100644 --- a/src/coreclr/vm/multicorejit.cpp +++ b/src/coreclr/vm/multicorejit.cpp @@ -48,11 +48,10 @@ void MulticoreJitFireEtwA(const WCHAR * pAction, const char * pTarget, int p1, i { if (EventEnabledMulticoreJit()) { - SString wTarget; + MAKE_WIDEPTR_FROMUTF8(wTargetStr, pTarget); + SString wTarget(wTargetStr); - wTarget.SetUTF8(pTarget); - - FireEtwMulticoreJit(GetClrInstanceId(), pAction, wTarget.GetUnicode(), p1, p2, p3); + FireEtwMulticoreJit(GetClrInstanceId(), pAction, (LPCWSTR)wTarget, p1, p2, p3); } } EX_CATCH @@ -309,12 +308,11 @@ bool RecorderModuleInfo::SetModule(Module * pMod) simpleName.Set((const BYTE *) pModuleName, lenModuleName); // SBuffer::Set copies over name SString sAssemblyName; - StackScratchBuffer scratch; pMod->GetAssembly()->GetPEAssembly()->GetDisplayName(sAssemblyName); - LPCUTF8 pAssemblyName = sAssemblyName.GetUTF8(scratch); - unsigned lenAssemblyName = sAssemblyName.GetCount(); - assemblyName.Set((const BYTE *) pAssemblyName, lenAssemblyName); + EString sAssemblyNameUTF8(sAssemblyName.MoveToUTF8()); + unsigned lenAssemblyName = sAssemblyNameUTF8.GetCount(); + assemblyName.Set((const BYTE *) (LPCUTF8)sAssemblyNameUTF8, lenAssemblyName); return moduleVersion.GetModuleVersion(pMod); @@ -554,7 +552,7 @@ HRESULT MulticoreJitRecorder::WriteOutput(IStream * pStream) MulticoreJitTrace(("New profile: %d modules, %d methods", m_ModuleCount, m_JitInfoCount)); - _FireEtwMulticoreJit(W("WRITEPROFILE"), m_fullFileName.GetUnicode(), m_ModuleCount, m_JitInfoCount, 0); + _FireEtwMulticoreJit(W("WRITEPROFILE"), (LPCWSTR)m_fullFileName, m_ModuleCount, m_JitInfoCount, 0); return hr; } @@ -920,7 +918,7 @@ HRESULT MulticoreJitRecorder::StopProfile(bool appDomainShutdown) hr = WriteOutput(); } - MulticoreJitTrace(("StopProfile: Save new profile to %S, hr=0x%x", m_fullFileName.GetUnicode(), hr)); + MulticoreJitTrace(("StopProfile: Save new profile to %S, hr=0x%x", (LPCWSTR)m_fullFileName, hr)); return hr; } @@ -998,7 +996,7 @@ HRESULT MulticoreJitRecorder::StartProfile(const WCHAR * pRoot, const WCHAR * pF if ((len != 0) && (m_fullFileName[len - 1] != W('\\'))) { - m_fullFileName.Append(W('\\')); + m_fullFileName.Append(W("\\")); } m_fullFileName.Append(pFile); @@ -1050,7 +1048,7 @@ HRESULT MulticoreJitRecorder::StartProfile(const WCHAR * pRoot, const WCHAR * pF player.SuppressRelease(); } - MulticoreJitTrace(("ProcessProfile('%S') returns %x", m_fullFileName.GetUnicode(), hr1)); + MulticoreJitTrace(("ProcessProfile('%S') returns %x", (LPCWSTR)m_fullFileName, hr1)); // Ignore error, even when we can't play back the file, we can still record new one @@ -1064,7 +1062,7 @@ HRESULT MulticoreJitRecorder::StartProfile(const WCHAR * pRoot, const WCHAR * pF MulticoreJitTrace(("StartProfile('%S', '%S', %d) returns %x", pRoot, pFile, suffix, hr)); - _FireEtwMulticoreJit(W("STARTPROFILE"), m_fullFileName.GetUnicode(), hr, 0, 0); + _FireEtwMulticoreJit(W("STARTPROFILE"), (LPCWSTR)m_fullFileName, hr, 0, 0); return hr; } diff --git a/src/coreclr/vm/multicorejit.h b/src/coreclr/vm/multicorejit.h index 7a61c22fd8b458..2b36a59b08337a 100644 --- a/src/coreclr/vm/multicorejit.h +++ b/src/coreclr/vm/multicorejit.h @@ -204,15 +204,14 @@ class MulticoreJitManager // incremented for every StartProfile/StopProfile/AbortProfile call to signal older players to quit // We're just afraid of keeping pointer to player - MulticoreJitRecorder * m_pMulticoreJitRecorder; // pointer to current recorder - SString m_profileRoot; // profile root string - LONG m_fSetProfileRootCalled; // SetProfileRoot has been called - LONG m_fAutoStartCalled; - bool m_fRecorderActive; // Manager open for recording/event, turned on when initialized properly, turned off when at full capacity - CrstExplicitInit m_playerLock; // Thread protection (accessing m_pMulticoreJitRecorder) - MulticoreJitPlayerStat m_stats; // Statistics: normally gathered by player, written to profile - - MulticoreJitCodeStorage m_MulticoreJitCodeStorage; + MulticoreJitRecorder * m_pMulticoreJitRecorder; // pointer to current recorder + SString m_profileRoot; // profile root string + LONG m_fSetProfileRootCalled; // SetProfileRoot has been called + LONG m_fAutoStartCalled; + bool m_fRecorderActive; // Manager open for recording/event, turned on when initialized properly, turned off when at full capacity + CrstExplicitInit m_playerLock; // Thread protection (accessing m_pMulticoreJitRecorder) + MulticoreJitPlayerStat m_stats; // Statistics: normally gathered by player, written to profile + MulticoreJitCodeStorage m_MulticoreJitCodeStorage; public: diff --git a/src/coreclr/vm/multicorejitimpl.h b/src/coreclr/vm/multicorejitimpl.h index 8e94fc91ac3641..dca11fd0d476ae 100644 --- a/src/coreclr/vm/multicorejitimpl.h +++ b/src/coreclr/vm/multicorejitimpl.h @@ -306,7 +306,7 @@ friend class MulticoreJitRecorder; HRESULT ReadCheckFile(const WCHAR * pFileName); - DomainAssembly * LoadAssembly(SString & assemblyName); + DomainAssembly * LoadAssembly(const EString & assemblyName); public: @@ -606,7 +606,7 @@ class MulticoreJitRecorder private: AppDomain * m_pDomain; // AutoStartProfile could be called from SystemDomain AssemblyBinder * m_pBinder; - SString m_fullFileName; + SString m_fullFileName; MulticoreJitPlayerStat & m_stats; RecorderModuleInfo * m_ModuleList; diff --git a/src/coreclr/vm/multicorejitplayer.cpp b/src/coreclr/vm/multicorejitplayer.cpp index dd48014046446f..40bee6dedaf98d 100644 --- a/src/coreclr/vm/multicorejitplayer.cpp +++ b/src/coreclr/vm/multicorejitplayer.cpp @@ -296,7 +296,7 @@ void PlayerModuleInfo::Dump(const CHAR * prefix, int index) DEBUG_ONLY_FUNCTION; #endif - StackSString ssBuff(SString::Utf8, prefix); + StackEString ssBuff(prefix); ssBuff.AppendPrintf("[%2d]: ", index); const ModuleVersion & ver = m_pRecord->version; @@ -309,16 +309,16 @@ void PlayerModuleInfo::Dump(const CHAR * prefix, int index) for (i = 0; i < m_pRecord->ModuleNameLen(); i ++) { - ssBuff.AppendUTF8(m_pRecord->GetModuleName()[i]); + ssBuff.Append(m_pRecord->GetModuleName()[i]); } while (i < 32) { - ssBuff.AppendUTF8(' '); + ssBuff.Append(' '); i ++; } - MulticoreJitTrace(("%s", ssBuff.GetUTF8NoConvert())); + MulticoreJitTrace(("%s", (LPCUTF8)ssBuff)); } #endif @@ -776,8 +776,7 @@ HRESULT MulticoreJitProfilePlayer::HandleModuleInfoRecord(unsigned moduleTo, uns if (!mod.m_pModule) { // Get the assembly name. - SString assemblyName; - assemblyName.SetASCII(mod.m_pRecord->GetAssemblyName(), mod.m_pRecord->AssemblyNameLen()); + EString assemblyName(mod.m_pRecord->GetAssemblyName(), mod.m_pRecord->AssemblyNameLen()); // Load the assembly. DomainAssembly * pDomainAssembly = LoadAssembly(assemblyName); @@ -819,7 +818,7 @@ HRESULT MulticoreJitProfilePlayer::HandleModuleInfoRecord(unsigned moduleTo, uns return hr; } -DomainAssembly * MulticoreJitProfilePlayer::LoadAssembly(SString & assemblyName) +DomainAssembly * MulticoreJitProfilePlayer::LoadAssembly(const EString & assemblyName) { STANDARD_VM_CONTRACT; diff --git a/src/coreclr/vm/nativeimage.cpp b/src/coreclr/vm/nativeimage.cpp index f4859a0e6c4148..3c7e9fed021567 100644 --- a/src/coreclr/vm/nativeimage.cpp +++ b/src/coreclr/vm/nativeimage.cpp @@ -19,28 +19,28 @@ BOOL AssemblyNameIndexHashTraits::Equals(LPCUTF8 a, LPCUTF8 b) { WRAPPER_NO_CONTRACT; - return SString(SString::Utf8Literal, a).CompareCaseInsensitive(SString(SString::Utf8Literal, b)) == 0; + return EString(EString::Literal, a).CompareCaseInsensitive(EString(EString::Literal, b)) == 0; } AssemblyNameIndexHashTraits::count_t AssemblyNameIndexHashTraits::Hash(LPCUTF8 s) { WRAPPER_NO_CONTRACT; - return SString(SString::Utf8Literal, s).HashCaseInsensitive(); + return EString(EString::Literal, s).HashCaseInsensitive(); } BOOL NativeImageIndexTraits::Equals(LPCUTF8 a, LPCUTF8 b) { WRAPPER_NO_CONTRACT; - return SString(SString::Utf8Literal, a).CompareCaseInsensitive(SString(SString::Utf8Literal, b)) == 0; + return EString(EString::Literal, a).CompareCaseInsensitive(EString(EString::Literal, b)) == 0; } NativeImageIndexTraits::count_t NativeImageIndexTraits::Hash(LPCUTF8 a) { WRAPPER_NO_CONTRACT; - return SString(SString::Utf8Literal, a).HashCaseInsensitive(); + return EString(EString::Literal, a).HashCaseInsensitive(); } NativeImage::NativeImage(AssemblyBinder *pAssemblyBinder, PEImageLayout *pImageLayout, LPCUTF8 imageFileName) @@ -134,7 +134,7 @@ NativeImage *NativeImage::Open( } } - SString path = componentModule->GetPath(); + SString path(componentModule->GetPath()); SString::Iterator lastPathSeparatorIter = path.End(); size_t pathDirLength = 0; if (PEAssembly::FindLastPathSeparator(path, lastPathSeparatorIter)) @@ -142,7 +142,8 @@ NativeImage *NativeImage::Open( pathDirLength = (lastPathSeparatorIter - path.Begin()) + 1; } - SString compositeImageFileName(SString::Utf8, nativeImageFileName); + SString compositeImageFileName; + EString(nativeImageFileName).ConvertToUnicode(compositeImageFileName); SString fullPath; fullPath.Set(path, path.Begin(), (COUNT_T)pathDirLength); fullPath += compositeImageFileName; @@ -196,7 +197,7 @@ NativeImage *NativeImage::Open( continue; } - fullPath.Append(DIRECTORY_SEPARATOR_CHAR_W); + fullPath.Append(DIRECTORY_SEPARATOR_STR_W); fullPath += compositeImageFileName; EX_TRY @@ -217,7 +218,7 @@ NativeImage *NativeImage::Open( // Failed to locate the native composite R2R image LOG((LF_LOADER, LL_ALWAYS, "LOADER: failed to load native image '%s' for component assembly '%S' using search paths: '%S'\n", nativeImageFileName, - path.GetUnicode(), + (LPCWSTR)path, searchPathsConfig != nullptr ? searchPathsConfig : W(""))); RaiseFailFastException(nullptr, nullptr, 0); } @@ -316,18 +317,22 @@ void NativeImage::CheckAssemblyMvid(Assembly *assembly) const static const size_t MVID_TEXT_LENGTH = 39; WCHAR assemblyMvidText[MVID_TEXT_LENGTH]; StringFromGUID2(assemblyMvid, assemblyMvidText, MVID_TEXT_LENGTH); + MAKE_UTF8PTR_FROMWIDE(assemblyMvidTextUTF8, assemblyMvidText); WCHAR componentMvidText[MVID_TEXT_LENGTH]; StringFromGUID2(*componentMvid, componentMvidText, MVID_TEXT_LENGTH); + MAKE_UTF8PTR_FROMWIDE(componentMvidTextUTF8, componentMvidText); - SString message; - message.Printf(W("MVID mismatch between loaded assembly '%s' (MVID = %s) and an assembly with the same simple name embedded in the native image '%s' (MVID = %s)"), - SString(SString::Utf8, assembly->GetSimpleName()).GetUnicode(), - assemblyMvidText, - SString(SString::Utf8, GetFileName()).GetUnicode(), - componentMvidText); + EString message; + message.Printf("MVID mismatch between loaded assembly '%s' (MVID = %s) and an assembly with the same simple name embedded in the native image '%s' (MVID = %s)", + assembly->GetSimpleName(), + assemblyMvidTextUTF8, + GetFileName(), + componentMvidTextUTF8); - EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_FAILFAST, message.GetUnicode()); + MAKE_WIDEPTR_FROMUTF8(messageW, message); + + EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_FAILFAST, messageW); } #endif diff --git a/src/coreclr/vm/nativeimage.h b/src/coreclr/vm/nativeimage.h index e4195d37be3f9e..d1897fb9a82506 100644 --- a/src/coreclr/vm/nativeimage.h +++ b/src/coreclr/vm/nativeimage.h @@ -23,7 +23,7 @@ struct AssemblyNameIndex class AssemblyNameIndexHashTraits : public NoRemoveSHashTraits< DefaultSHashTraits > { public: - // Similar to BaseAssemblySpec::CompareStrings, we're using temporary SStrings that throw + // Similar to BaseAssemblySpec::CompareStrings, we're using temporary EStrings that throw // for case-insensitive UTF8 assembly name comparisons. static const bool s_NoThrow = false; @@ -42,7 +42,7 @@ typedef DPTR(class NativeImage) PTR_NativeImage; class NativeImageIndexTraits : public NoRemoveSHashTraits> { public: - // Similar to BaseAssemblySpec::CompareStrings, we're using temporary SStrings that throw + // Similar to BaseAssemblySpec::CompareStrings, we're using temporary EStrings that throw // for case-insensitive UTF8 assembly name comparisons. static const bool s_NoThrow = false; diff --git a/src/coreclr/vm/nativelibrary.cpp b/src/coreclr/vm/nativelibrary.cpp index 891ce486352930..015e3036b1e97e 100644 --- a/src/coreclr/vm/nativelibrary.cpp +++ b/src/coreclr/vm/nativelibrary.cpp @@ -95,7 +95,7 @@ namespace return m_hr; } - SString& GetMessage() + EString& GetMessage() { return m_message; } @@ -105,9 +105,11 @@ namespace STANDARD_VM_CONTRACT; #if defined(__APPLE__) - COMPlusThrow(kDllNotFoundException, IDS_EE_NDIRECT_LOADLIB_MAC, libraryNameOrPath.GetUnicode(), GetMessage()); + MAKE_WIDEPTR_FROMUTF8(message, GetMessage()); + COMPlusThrow(kDllNotFoundException, IDS_EE_NDIRECT_LOADLIB_MAC, (LPCWSTR)libraryNameOrPath, message); #elif defined(TARGET_UNIX) - COMPlusThrow(kDllNotFoundException, IDS_EE_NDIRECT_LOADLIB_LINUX, libraryNameOrPath.GetUnicode(), GetMessage()); + MAKE_WIDEPTR_FROMUTF8(message, GetMessage()); + COMPlusThrow(kDllNotFoundException, IDS_EE_NDIRECT_LOADLIB_LINUX, (LPCWSTR)libraryNameOrPath, message); #else // __APPLE__ HRESULT theHRESULT = GetHR(); if (theHRESULT == HRESULT_FROM_WIN32(ERROR_BAD_EXE_FORMAT)) @@ -118,7 +120,7 @@ namespace { SString hrString; GetHRMsg(theHRESULT, hrString); - COMPlusThrow(kDllNotFoundException, IDS_EE_NDIRECT_LOADLIB_WIN, libraryNameOrPath.GetUnicode(), hrString); + COMPlusThrow(kDllNotFoundException, IDS_EE_NDIRECT_LOADLIB_WIN, (LPCWSTR)libraryNameOrPath, hrString); } #endif // TARGET_UNIX @@ -137,12 +139,12 @@ namespace void SetMessage(LPCSTR message) { - m_message = SString(SString::Utf8, message); + m_message = message; } HRESULT m_hr; DWORD m_priorityOfLastError; - SString m_message; + EString m_message; }; // class LoadLibErrorTracker // Load the library directly and return the raw system handle @@ -246,8 +248,8 @@ NATIVE_LIBRARY_HANDLE NativeLibrary::LoadLibraryFromPath(LPCWSTR libraryPath, BO if (throwOnError && (hmod == nullptr)) { - SString libraryPathSString(libraryPath); - errorTracker.Throw(libraryPathSString); + SString libraryPathEString(libraryPath); + errorTracker.Throw(libraryPathEString); } return hmod; } @@ -302,8 +304,8 @@ namespace STANDARD_VM_CONTRACT; // This is replicating quick check from the OS implementation of api sets. - return SString::_wcsnicmp(wszLibName, W("api-"), 4) == 0 || - SString::_wcsnicmp(wszLibName, W("ext-"), 4) == 0; + return StaticStringHelpers::_wcsnicmp(wszLibName, W("api-"), 4) == 0 || + StaticStringHelpers::_wcsnicmp(wszLibName, W("ext-"), 4) == 0; } #endif // !TARGET_UNIX @@ -585,9 +587,9 @@ namespace // or an existing known extension. This is done due to issues with case-sensitive file systems // on Windows. The Windows loader always appends ".DLL" as opposed to the more common ".dll". if (libNameIsRelativePath - && !libName.EndsWith(W(".")) - && !libName.EndsWithCaseInsensitive(W(".dll")) - && !libName.EndsWithCaseInsensitive(W(".exe"))) + && !libName.EndsWith(SL(W("."))) + && !libName.EndsWithCaseInsensitive(SL(W(".dll"))) + && !libName.EndsWithCaseInsensitive(SL(W(".exe")))) { libNameVariations[varCount++] = NameSuffixFmt; } @@ -700,18 +702,14 @@ namespace while (COMCharacter::nativeIsWhiteSpace(*(++szComma))); AssemblySpec spec; - SString ssAssemblyDisplayName(SString::Utf8, szComma); + EString ssAssemblyDisplayName(szComma); if (SUCCEEDED(spec.InitNoThrow(ssAssemblyDisplayName))) { // Need to perform case insensitive hashing. - SString moduleName(SString::Utf8, szLibName); + EString moduleName(szLibName); moduleName.LowerCase(); - - StackScratchBuffer buffer; - szLibName = (LPSTR)moduleName.GetUTF8(buffer); - Assembly *pAssembly = spec.LoadAssembly(FILE_LOADED); - Module *pModule = pAssembly->FindModuleByName(szLibName); + Module *pModule = pAssembly->FindModuleByName(moduleName); hmod = LocalLoadLibraryHelper(pModule->GetPath(), loadWithAlteredPathFlags | dllImportSearchPathFlags, pErrorTracker); } @@ -783,8 +781,8 @@ NATIVE_LIBRARY_HANDLE NativeLibrary::LoadLibraryByName(LPCWSTR libraryName, Asse if (throwOnError) { - SString libraryPathSString(libraryName); - errorTracker.Throw(libraryPathSString); + SString libraryPathEString(libraryName); + errorTracker.Throw(libraryPathEString); } return hmod; @@ -864,7 +862,8 @@ NATIVE_LIBRARY_HANDLE NativeLibrary::LoadLibraryFromMethodDesc(NDirectMethodDesc if (pMD->GetLibName() == NULL) COMPlusThrow(kEntryPointNotFoundException, IDS_EE_NDIRECT_GETPROCADDRESS_NONAME); - StackSString ssLibName(SString::Utf8, pMD->GetLibName()); + MAKE_WIDEPTR_FROMUTF8(libName, pMD->GetLibName()); + SString ssLibName(SString::Literal, libName); errorTracker.Throw(ssLibName); } diff --git a/src/coreclr/vm/object.cpp b/src/coreclr/vm/object.cpp index be228446be88bb..10aa817a357f0b 100644 --- a/src/coreclr/vm/object.cpp +++ b/src/coreclr/vm/object.cpp @@ -259,7 +259,7 @@ STRINGREF AllocateString(SString sstr) COUNT_T length = sstr.GetCount(); // count of WCHARs excluding terminating NULL STRINGREF strObj = AllocateString(length); - memcpyNoGCRefs(strObj->GetBuffer(), sstr.GetUnicode(), length*sizeof(WCHAR)); + memcpyNoGCRefs(strObj->GetBuffer(), (LPCWSTR)sstr, length*sizeof(WCHAR)); return strObj; } diff --git a/src/coreclr/vm/olevariant.cpp b/src/coreclr/vm/olevariant.cpp index 6f90f9a3ff8a2c..1c6b7caf51923f 100644 --- a/src/coreclr/vm/olevariant.cpp +++ b/src/coreclr/vm/olevariant.cpp @@ -1793,7 +1793,7 @@ void OleVariant::MarshalInterfaceArrayOleToCom(void *oleArray, BASEARRAYREF *pCo obj->GetMethodTable()->_GetFullyQualifiedNameForClass(ssObjClsName); pElementMT->_GetFullyQualifiedNameForClass(ssDestClsName); COMPlusThrow(kInvalidCastException, IDS_EE_CANNOTCAST, - ssObjClsName.GetUnicode(), ssDestClsName.GetUnicode()); + (LPCWSTR)ssObjClsName, (LPCWSTR)ssDestClsName); } // @@ -4711,7 +4711,7 @@ void OleVariant::ConvertValueClassToVariant(OBJECTREF *pBoxedValueClass, VARIANT // Indicate that conversion of the class to variant without a registered type lib is not supported StackSString className; pValueClassMT->_GetFullyQualifiedNameForClass(className); - COMPlusThrow(kNotSupportedException, IDS_EE_CLASS_TO_VARIANT_TLB_NOT_REG, className.GetUnicode()); + COMPlusThrow(kNotSupportedException, IDS_EE_CLASS_TO_VARIANT_TLB_NOT_REG, (LPCWSTR)className); } else { diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index 95ceb1564a19b1..e626c8b809c86e 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -61,7 +61,7 @@ static void ValidatePEFileMachineType(PEAssembly *pPEAssembly) StackSString name; pPEAssembly->GetDisplayName(name); - COMPlusThrow(kBadImageFormatException, IDS_CLASSLOAD_WRONGCPU, name.GetUnicode()); + COMPlusThrow(kBadImageFormatException, IDS_CLASSLOAD_WRONGCPU, (LPCWSTR)name); } return; // If we got here, all is good. @@ -736,7 +736,6 @@ PEAssembly::PEAssembly( #if _DEBUG GetPathOrCodeBase(m_debugName); - m_debugName.Normalize(); m_pDebugName = m_debugName; #endif } @@ -918,14 +917,14 @@ void PEAssembly::PathToUrl(SString &string) if (i[0] == W('\\')) { // Network path - string.Insert(i, SL("file://")); - string.Skip(i, SL("file://")); + string.Insert(i, SL(W("file://"))); + string.Skip(i, SL(W("file://"))); } else { // Disk path - string.Insert(i, SL("file:///")); - string.Skip(i, SL("file:///")); + string.Insert(i, SL(W("file:///"))); + string.Skip(i, SL(W("file:///"))); } #else // Unix doesn't have a distinction between a network or a local path diff --git a/src/coreclr/vm/peassembly.h b/src/coreclr/vm/peassembly.h index b63709bb7aa548..9173101972a8dc 100644 --- a/src/coreclr/vm/peassembly.h +++ b/src/coreclr/vm/peassembly.h @@ -394,7 +394,7 @@ class PEAssembly final #ifdef _DEBUG LPCWSTR m_pDebugName; - SString m_debugName; + SString m_debugName; #endif // IL image, NULL if dynamic diff --git a/src/coreclr/vm/peimage.cpp b/src/coreclr/vm/peimage.cpp index b9bb8ff068b1f0..561251474fd2db 100644 --- a/src/coreclr/vm/peimage.cpp +++ b/src/coreclr/vm/peimage.cpp @@ -192,7 +192,7 @@ CHECK PEImage::CheckCanonicalFullPath(const SString &path) { // Drive path i++; - SString sDrivePath(SString::Literal, ":\\"); + SString sDrivePath(SString::Literal, W(":\\")); CCHECK(path.Skip(i, sDrivePath)); } else @@ -207,8 +207,8 @@ CHECK PEImage::CheckCanonicalFullPath(const SString &path) { // Check for . or .. - SString sParentDir(SString::Ascii, ".."); - SString sCurrentDir(SString::Ascii, "."); + SString sParentDir(SString::Literal, W("..")); + SString sCurrentDir(SString::Literal, W(".")); if ((path.Skip(i, sParentDir) || path.Skip(i, sCurrentDir)) && (path.Match(i, '\\'))) { @@ -407,8 +407,8 @@ void PEImage::OpenMDImport() // LPCSTR strModuleName; IfFailThrow(m_pMDImport->GetScopeProps(&strModuleName, NULL)); - m_sModuleFileNameHintUsedByDac.SetUTF8(strModuleName); - m_sModuleFileNameHintUsedByDac.Normalize(); + MAKE_WIDEPTR_FROMUTF8(wstrModuleName, strModuleName); + m_sModuleFileNameHintUsedByDac.Set(wstrModuleName); } } } @@ -960,7 +960,8 @@ HRESULT PEImage::TryOpenFile(bool takeLock) return S_OK; ErrorModeHolder mode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); - m_hFile=WszCreateFile((LPCWSTR)GetPathToLoad(), + SString pathToLoad = GetPathToLoad(); + m_hFile=WszCreateFile((LPCWSTR)pathToLoad, GENERIC_READ #if TARGET_WINDOWS // the file may have native code sections, make sure we are allowed to execute the file diff --git a/src/coreclr/vm/peimage.h b/src/coreclr/vm/peimage.h index f353cebe978d14..838d8f30a94979 100644 --- a/src/coreclr/vm/peimage.h +++ b/src/coreclr/vm/peimage.h @@ -135,7 +135,7 @@ class PEImage final BOOL HasPath(); ULONG GetPathHash(); const SString& GetPath(); - const SString& GetPathToLoad(); + SString GetPathToLoad(); LPCWSTR GetPathForErrorMessages() { return GetPath(); } BOOL IsFile(); @@ -225,7 +225,7 @@ class PEImage final } PEImageLocator(PEImage * pImage) - : m_pPath(pImage->m_path.GetUnicode()) + : m_pPath(pImage->m_path) { m_bIsInBundle = pImage->IsInBundle(); } @@ -291,11 +291,11 @@ class PEImage final // Instance fields // ------------------------------------------------------------ - SString m_path; - LONG m_refCount; + SString m_path; + LONG m_refCount; // means this is a unique (deduped) instance. - BOOL m_bInHashMap; + BOOL m_bInHashMap; // If this image is located within a single-file bundle, the location within the bundle. // If m_bundleFileLocation is valid, it takes precedence over m_path for loading. diff --git a/src/coreclr/vm/peimage.inl b/src/coreclr/vm/peimage.inl index 19668be89f97ce..60ac07d0998d72 100644 --- a/src/coreclr/vm/peimage.inl +++ b/src/coreclr/vm/peimage.inl @@ -32,11 +32,18 @@ inline const SString &PEImage::GetPath() return m_path; } -inline const SString& PEImage::GetPathToLoad() +inline SString PEImage::GetPathToLoad() { LIMITED_METHOD_DAC_CONTRACT; - return IsInBundle() ? m_bundleFileLocation.Path() : m_path; + if (IsInBundle()) + { + SString bundleLocation; + m_bundleFileLocation.Path().ConvertToUnicode(bundleLocation); + return bundleLocation; + } + + return m_path; } inline INT64 PEImage::GetOffset() const @@ -72,7 +79,7 @@ inline void PEImage::SetModuleFileNameHintForDAC() // Grab module name only for triage dumps where full paths are excluded // because may contain PII data. // m_sModuleFileNameHintUsedByDac will just point to module name starting character. - const WCHAR* pStartPath = m_path.GetUnicode(); + const WCHAR* pStartPath = m_path; COUNT_T nChars = m_path.GetCount(); if (pStartPath != NULL && nChars > 0 && nChars <= MAX_PATH) { @@ -287,7 +294,6 @@ inline void PEImage::Init(LPCWSTR pPath, BundleFileLocation bundleFileLocation) CONTRACTL_END; m_path = pPath; - m_path.Normalize(); m_bundleFileLocation = bundleFileLocation; SetModuleFileNameHintForDAC(); } diff --git a/src/coreclr/vm/pendingload.cpp b/src/coreclr/vm/pendingload.cpp index 1bc384befab56c..9b9f4863633813 100644 --- a/src/coreclr/vm/pendingload.cpp +++ b/src/coreclr/vm/pendingload.cpp @@ -217,7 +217,7 @@ void PendingTypeLoadTable::Dump() SString name; TypeKey entryTypeKey = pSearch->pData->GetTypeKey(); TypeString::AppendTypeKeyDebug(name, &entryTypeKey); - LOG((LF_CLASSLOADER, LL_INFO10000, " Entry %S with handle %p at level %s\n", name.GetUnicode(), pSearch->pData->m_typeHandle.AsPtr(), + LOG((LF_CLASSLOADER, LL_INFO10000, " Entry %S with handle %p at level %s\n", (LPCWSTR)name, pSearch->pData->m_typeHandle.AsPtr(), pSearch->pData->m_typeHandle.IsNull() ? "not-applicable" : classLoadLevelName[pSearch->pData->m_typeHandle.GetLoadLevel()])); } } diff --git a/src/coreclr/vm/pendingload.h b/src/coreclr/vm/pendingload.h index 2094d76f863309..fb1fe248d5bd0c 100644 --- a/src/coreclr/vm/pendingload.h +++ b/src/coreclr/vm/pendingload.h @@ -44,7 +44,7 @@ class PendingTypeLoadEntry { SString name; TypeString::AppendTypeKeyDebug(name, &m_typeKey); - LOG((LF_CLASSLOADER, LL_INFO10000, "PHASEDLOAD: Creating loading entry for type %S\n", name.GetUnicode())); + LOG((LF_CLASSLOADER, LL_INFO10000, "PHASEDLOAD: Creating loading entry for type %S\n", (LPCWSTR)name)); } #endif diff --git a/src/coreclr/vm/perfinfo.cpp b/src/coreclr/vm/perfinfo.cpp index 667223fedc6058..d9e48999de523d 100644 --- a/src/coreclr/vm/perfinfo.cpp +++ b/src/coreclr/vm/perfinfo.cpp @@ -22,7 +22,7 @@ PerfInfo::PerfInfo(int pid) } SString path; - path.Printf("%Sperfinfo-%d.map", tempPath.GetUnicode(), pid); + path.Printf(W("%sperfinfo-%d.map"), (LPCWSTR)tempPath, pid); OpenFile(path); } @@ -55,10 +55,10 @@ void PerfInfo::LogImage(PEAssembly* pPEAssembly, WCHAR* guid) } } - value.Printf("%S%c%S%c%p", path.GetUnicode(), sDelimiter, guid, sDelimiter, baseAddr); + value.Printf(W("%s%c%s%c%p"), (LPCWSTR)path, sDelimiter, guid, sDelimiter, baseAddr); SString command; - command.Printf("%s", "ImageLoad"); + command.Printf(W("%s"), W("ImageLoad")); WriteLine(command, value); } @@ -80,14 +80,14 @@ void PerfInfo::WriteLine(SString& type, SString& value) } SString line; - line.Printf("%S%c%S%c\n", - type.GetUnicode(), sDelimiter, value.GetUnicode(), sDelimiter); + line.Printf(W("%s%c%s%c\n"), + (LPCWSTR)type, sDelimiter, (LPCWSTR)value, sDelimiter); EX_TRY { - StackScratchBuffer scratch; - const char* strLine = line.GetANSI(scratch); - ULONG inCount = line.GetCount(); + EString lineUTF8(line.MoveToUTF8()); + const char* strLine = lineUTF8; + ULONG inCount = lineUTF8.GetCount(); ULONG outCount; m_Stream->Write(strLine, inCount, &outCount); @@ -109,7 +109,7 @@ void PerfInfo::OpenFile(SString& path) if (m_Stream != nullptr) { - HRESULT hr = m_Stream->OpenForWrite(path.GetUnicode()); + HRESULT hr = m_Stream->OpenForWrite((LPCWSTR)path); if (FAILED(hr)) { delete m_Stream; diff --git a/src/coreclr/vm/perfmap.cpp b/src/coreclr/vm/perfmap.cpp index 4abbc11e077391..10751a157ecc37 100644 --- a/src/coreclr/vm/perfmap.cpp +++ b/src/coreclr/vm/perfmap.cpp @@ -99,7 +99,7 @@ PerfMap::PerfMap(int pid) } SString path; - path.Printf("%Sperf-%d.map", &tempPath, pid); + path.Printf(W("%sperf-%d.map"), &tempPath, pid); // Open the map file for writing. OpenFile(path); @@ -142,7 +142,7 @@ void PerfMap::OpenFile(SString& path) m_FileStream = new (nothrow) CFileStream(); if(m_FileStream != nullptr) { - HRESULT hr = m_FileStream->OpenForWrite(path.GetUnicode()); + HRESULT hr = m_FileStream->OpenForWrite((LPCWSTR)path); if(FAILED(hr)) { delete m_FileStream; @@ -152,7 +152,7 @@ void PerfMap::OpenFile(SString& path) } // Write a line to the map file. -void PerfMap::WriteLine(SString& line) +void PerfMap::WriteLine(EString& line) { STANDARD_VM_CONTRACT; @@ -160,8 +160,7 @@ void PerfMap::WriteLine(SString& line) { // Write the line. // The PAL already takes a lock when writing, so we don't need to do so here. - StackScratchBuffer scratch; - const char * strLine = line.GetANSI(scratch); + const char * strLine = line; ULONG inCount = line.GetCount(); ULONG outCount; m_FileStream->Write(strLine, inCount, &outCount); @@ -199,21 +198,21 @@ void PerfMap::LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, cons EX_TRY { // Get the full method signature. - SString name; - pMethod->GetFullMethodInfo(name); + SString nameW; + pMethod->GetFullMethodInfo(nameW); + EString name(nameW.MoveToUTF8()); // Build the map file line. - StackScratchBuffer scratch; if (optimizationTier != nullptr && s_ShowOptimizationTiers) { name.AppendPrintf("[%s]", optimizationTier); } - SString line; - line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, name.GetANSI(scratch)); + EString line; + line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, (LPCUTF8)name); // Write the line. WriteLine(line); - PAL_PerfJitDump_LogMethod((void*)pCode, codeSize, name.GetANSI(scratch), nullptr, nullptr); + PAL_PerfJitDump_LogMethod((void*)pCode, codeSize, name, nullptr, nullptr); } EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); } @@ -295,31 +294,31 @@ void PerfMap::LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode) EX_TRY { // Get the full method signature. - SString name; - pMethod->GetFullMethodInfo(name); - - StackScratchBuffer scratch; + SString nameW; + pMethod->GetFullMethodInfo(nameW); + EString name(nameW.MoveToUTF8()); if (s_ShowOptimizationTiers) { - name.Append(W("[PreJIT]")); + name.Append("[PreJIT]"); } // NGEN can split code between hot and cold sections which are separate in memory. // Emit an entry for each section if it is used. if (methodRegionInfo.hotSize > 0) { - PAL_PerfJitDump_LogMethod((void*)methodRegionInfo.hotStartAddress, methodRegionInfo.hotSize, name.GetANSI(scratch), nullptr, nullptr); + PAL_PerfJitDump_LogMethod((void*)methodRegionInfo.hotStartAddress, methodRegionInfo.hotSize, name, nullptr, nullptr); } if (methodRegionInfo.coldSize > 0) { if (s_ShowOptimizationTiers) { - pMethod->GetFullMethodInfo(name); - name.Append(W("[PreJit-cold]")); + pMethod->GetFullMethodInfo(nameW); + name = nameW.MoveToUTF8(); + name.AppendPrintf("[PreJit-cold]"); } - PAL_PerfJitDump_LogMethod((void*)methodRegionInfo.coldStartAddress, methodRegionInfo.coldSize, name.GetANSI(scratch), nullptr, nullptr); + PAL_PerfJitDump_LogMethod((void*)methodRegionInfo.coldStartAddress, methodRegionInfo.coldSize, name, nullptr, nullptr); } } EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); @@ -348,15 +347,14 @@ void PerfMap::LogStubs(const char* stubType, const char* stubOwner, PCODE pCode, } // Build the map file line. - StackScratchBuffer scratch; - SString name; + EString name; name.Printf("stub<%d> %s<%s>", ++(s_Current->m_StubsMapped), stubType, stubOwner); - SString line; - line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, name.GetANSI(scratch)); + EString line; + line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, (LPCUTF8)name); // Write the line. s_Current->WriteLine(line); - PAL_PerfJitDump_LogMethod((void*)pCode, codeSize, name.GetANSI(scratch), nullptr, nullptr); + PAL_PerfJitDump_LogMethod((void*)pCode, codeSize, name, nullptr, nullptr); } EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); } @@ -398,7 +396,7 @@ NativeImagePerfMap::NativeImagePerfMap(Assembly * pAssembly, BSTR pDestPath) // Build the path to the perfmap file, which consists of .ni..map. // Example: /tmp/System.Private.CoreLib.ni.{GUID}.map SString sDestPerfMapPath; - sDestPerfMapPath.Printf("%S%s.ni.%S.map", pDestPath, lpcSimpleName, wszSignature); + sDestPerfMapPath.Printf(W("%s%S.ni.%s.map"), pDestPath, lpcSimpleName, wszSignature); // Open the perf map file. OpenFile(sDestPerfMapPath); diff --git a/src/coreclr/vm/perfmap.h b/src/coreclr/vm/perfmap.h index 587a776e682760..f173493de67814 100644 --- a/src/coreclr/vm/perfmap.h +++ b/src/coreclr/vm/perfmap.h @@ -40,7 +40,7 @@ class PerfMap PerfMap(int pid); // Write a line to the map file. - void WriteLine(SString & line); + void WriteLine(EString & line); protected: // Construct a new map without a specified file name. diff --git a/src/coreclr/vm/pgo.cpp b/src/coreclr/vm/pgo.cpp index 7f7115d1f3c560..ebf84343e11f59 100644 --- a/src/coreclr/vm/pgo.cpp +++ b/src/coreclr/vm/pgo.cpp @@ -217,13 +217,12 @@ void PgoManager::WritePgoData() fprintf(pgoDataFile, s_MethodHeaderString, pgoData->header.codehash, pgoData->header.methodhash, pgoData->header.ilSize, schemaItems); - SString tClass, tMethodName, tMethodSignature; + SString tClass; + EString tMethodName, tMethodSignature; pgoData->header.method->GetMethodInfo(tClass, tMethodName, tMethodSignature); - StackScratchBuffer nameBuffer; - StackScratchBuffer nameBuffer2; - fprintf(pgoDataFile, "MethodName: %s.%s\n", tClass.GetUTF8(nameBuffer), tMethodName.GetUTF8(nameBuffer2)); - fprintf(pgoDataFile, "Signature: %s\n", tMethodSignature.GetUTF8(nameBuffer)); + fprintf(pgoDataFile, "MethodName: %s.%s\n", (LPCUTF8)tClass.MoveToUTF8(), (LPCUTF8)tMethodName); + fprintf(pgoDataFile, "Signature: %s\n", (LPCUTF8)tMethodSignature); uint8_t* data = pgoData->header.GetData(); @@ -262,7 +261,6 @@ void PgoManager::WritePgoData() else { StackSString ss; - StackScratchBuffer nameBuffer; TypeString::AppendType(ss, th, TypeString::FormatNamespace | TypeString::FormatFullInst | TypeString::FormatAssembly); if (ss.GetCount() > 8192) { @@ -270,7 +268,9 @@ void PgoManager::WritePgoData() } else { - fprintf(pgoDataFile, s_TypeHandle, ss.GetUTF8(nameBuffer)); + StackEString ssUtf8; + ss.ConvertToUTF8(ssUtf8); + fprintf(pgoDataFile, s_TypeHandle, (LPCUTF8)ssUtf8); } } break; @@ -289,7 +289,8 @@ void PgoManager::WritePgoData() } else { - SString garbage1, tMethodName, garbage2; + SString garbage1; + EString tMethodName, garbage2; md->GetMethodInfo(garbage1, tMethodName, garbage2); StackSString tTypeName; TypeString::AppendType(tTypeName, TypeHandle(md->GetMethodTable()), TypeString::FormatNamespace | TypeString::FormatFullInst | TypeString::FormatAssembly); @@ -301,9 +302,7 @@ void PgoManager::WritePgoData() } else { - StackScratchBuffer methodNameBuffer; - StackScratchBuffer typeBuffer; - fprintf(pgoDataFile, "MethodHandle: %s|@|%s", tMethodName.GetUTF8(methodNameBuffer), tTypeName.GetUTF8(typeBuffer)); + fprintf(pgoDataFile, "MethodHandle: %s|@|%s", (LPCUTF8)tMethodName, (LPCUTF8)tTypeName.MoveToUTF8()); } } break; @@ -854,8 +853,8 @@ HRESULT PgoManager::getPgoInstrumentationResults(MethodDesc* pMD, BYTE** pAlloca { if (kind == ICorJitInfo::PgoInstrumentationKind::TypeHandle) { - StackSString ts(SString::Utf8, string); - TypeHandle th = TypeName::GetTypeManaged(ts.GetUnicode(), NULL, FALSE, FALSE, FALSE, NULL, NULL); + MAKE_WIDEPTR_FROMUTF8(ts, string); + TypeHandle th = TypeName::GetTypeManaged((LPCWSTR)ts, NULL, FALSE, FALSE, FALSE, NULL, NULL); newPtr = (INT_PTR)th.AsPtr(); } else @@ -866,12 +865,12 @@ HRESULT PgoManager::getPgoInstrumentationResults(MethodDesc* pMD, BYTE** pAlloca char* sep = strstr(string, "|@|"); if (sep != nullptr) { - StackSString typeString(SString::Utf8, sep + 3); - StackSString methodString(SString::Utf8, string, (COUNT_T)(sep - string)); - TypeHandle th = TypeName::GetTypeManaged(typeString.GetUnicode(), NULL, FALSE, FALSE, FALSE, NULL, NULL); + MAKE_WIDEPTR_FROMUTF8(typeString, sep + 3); + StackEString methodString(string, (COUNT_T)(sep - string)); + TypeHandle th = TypeName::GetTypeManaged((LPCWSTR)typeString, NULL, FALSE, FALSE, FALSE, NULL, NULL); if (!th.IsNull()) { - MethodDesc* pMD = MemberLoader::FindMethodByName(th.GetMethodTable(), methodString.GetUTF8NoConvert()); + MethodDesc* pMD = MemberLoader::FindMethodByName(th.GetMethodTable(), (LPCUTF8)methodString); newPtr = (INT_PTR)pMD; } } diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index e1ff1a2ac43a21..8ff4f202148562 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -815,7 +815,8 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J } else { - SString namespaceOrClassName, methodName, methodSignature; + SString namespaceOrClassName; + EString methodName, methodSignature; // Methods that may be interpreted defer this notification until it is certain // we are jitting and not interpreting in CompileMethodWithEtwWrapper. diff --git a/src/coreclr/vm/profilinghelper.cpp b/src/coreclr/vm/profilinghelper.cpp index 285bcaab9887ce..4e3dccd6cd23e5 100644 --- a/src/coreclr/vm/profilinghelper.cpp +++ b/src/coreclr/vm/profilinghelper.cpp @@ -232,7 +232,7 @@ CRITSEC_COOKIE ProfilingAPIUtility::s_csStatus = NULL; // // static -void ProfilingAPIUtility::AppendSupplementaryInformation(int iStringResource, SString * pString) +void ProfilingAPIUtility::AppendSupplementaryInformation(int iStringResource, EString * pString) { CONTRACTL { @@ -246,7 +246,9 @@ void ProfilingAPIUtility::AppendSupplementaryInformation(int iStringResource, SS CONTRACTL_END; StackSString supplementaryInformation; - if (!supplementaryInformation.LoadResource( + + if (!LoadResource( + supplementaryInformation, CCompRC::Debugging, IDS_PROF_SUPPLEMENTARY_INFO )) @@ -255,12 +257,12 @@ void ProfilingAPIUtility::AppendSupplementaryInformation(int iStringResource, SS return; } - StackSString supplementaryInformationUtf8; + EString supplementaryInformationUtf8; supplementaryInformation.ConvertToUTF8(supplementaryInformationUtf8); - pString->AppendUTF8(" "); + pString->Append(" "); pString->AppendPrintf( - supplementaryInformationUtf8.GetUTF8NoConvert(), + supplementaryInformationUtf8, GetCurrentProcessId(), iStringResource); } @@ -298,7 +300,9 @@ void ProfilingAPIUtility::LogProfEventVA( CONTRACTL_END; StackSString messageFromResource; - if (!messageFromResource.LoadResource( + + if (!LoadResource( + messageFromResource, CCompRC::Debugging, iStringResourceID )) @@ -307,25 +311,21 @@ void ProfilingAPIUtility::LogProfEventVA( return; } - StackSString messageFromResourceUtf8; - messageFromResource.ConvertToUTF8(messageFromResourceUtf8); + StackEString messageFromResourceUtf8(messageFromResource.MoveToUTF8()); - StackSString messageToLog; - messageToLog.VPrintf(messageFromResourceUtf8.GetUTF8NoConvert(), insertionArgs); + EString messageToLogUTF8; + messageToLogUTF8.VPrintf(messageFromResourceUtf8, insertionArgs); - AppendSupplementaryInformation(iStringResourceID, &messageToLog); + AppendSupplementaryInformation(iStringResourceID, &messageToLogUTF8); - if (EventEnabledProfilerMessage()) - { - StackSString messageToLogUtf16; - messageToLog.ConvertToUnicode(messageToLogUtf16); + StackSString messageToLog; + messageToLogUTF8.ConvertToUnicode(messageToLog); - // Write to ETW and EventPipe with the message - FireEtwProfilerMessage(GetClrInstanceId(), messageToLogUtf16.GetUnicode()); - } + // Write to ETW and EventPipe with the message + FireEtwProfilerMessage(GetClrInstanceId(), (LPCWSTR)messageToLog); // Ouput debug strings for diagnostic messages. - OutputDebugStringUtf8(messageToLog.GetUTF8NoConvert()); + OutputDebugStringUtf8(messageToLogUTF8); } // See code:ProfilingAPIUtility.LogProfEventVA for description of arguments. @@ -741,8 +741,8 @@ HRESULT ProfilingAPIUtility::AttemptLoadDelayedStartupProfilers() HRESULT hr = LoadProfiler( kStartupLoad, pClsid, - (LPCSTR)clsidUtf8, - item->path.GetUnicode(), + clsidUtf8, + item->path, NULL, // No client data for startup load 0); // No client data for startup load if (FAILED(hr)) @@ -919,11 +919,11 @@ HRESULT ProfilingAPIUtility::DoPreInitialization( CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_ProfAPI_ProfilerCompatibilitySetting, &wszProfilerCompatibilitySetting); if (wszProfilerCompatibilitySetting != NULL) { - if (SString::_wcsicmp(wszProfilerCompatibilitySetting, W("EnableV2Profiler")) == 0) + if (StaticStringHelpers::_wcsicmp(wszProfilerCompatibilitySetting, W("EnableV2Profiler")) == 0) { profilerCompatibilityFlag = kEnableV2Profiler; } - else if (SString::_wcsicmp(wszProfilerCompatibilitySetting, W("PreventLoad")) == 0) + else if (StaticStringHelpers::_wcsicmp(wszProfilerCompatibilitySetting, W("PreventLoad")) == 0) { profilerCompatibilityFlag = kPreventLoad; } diff --git a/src/coreclr/vm/profilinghelper.h b/src/coreclr/vm/profilinghelper.h index 72899d5ba37ce1..698f6fb30979d1 100644 --- a/src/coreclr/vm/profilinghelper.h +++ b/src/coreclr/vm/profilinghelper.h @@ -111,7 +111,7 @@ class ProfilingAPIUtility static HRESULT AttemptLoadDelayedStartupProfilers(); static HRESULT AttemptLoadProfilerList(); - static void AppendSupplementaryInformation(int iStringResource, SString * pString); + static void AppendSupplementaryInformation(int iStringResource, EString * pString); static void LogProfEventVA( int iStringResourceID, diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index 4c827783d51b4a..2347297a0e877e 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -4110,9 +4110,9 @@ HRESULT ProfToEEInterfaceImpl::GetModuleInfo2(ModuleID moduleId, LPCUTF8 szScopeName = NULL; if ((*wszFileName == W('\0')) && SUCCEEDED(pModule->GetScopeName(&szScopeName))) { - strScopeName.SetUTF8(szScopeName); - strScopeName.Normalize(); - wszFileName = strScopeName.GetUnicode(); + MAKE_WIDEPTR_FROMUTF8(wszScopeName, szScopeName); + strScopeName.Set(wszScopeName); + wszFileName = strScopeName; } ULONG trueLen = (ULONG)(wcslen(wszFileName) + 1); @@ -5646,7 +5646,7 @@ HRESULT ProfToEEInterfaceImpl::GetAssemblyInfo(AssemblyID assemblyId, { CONTRACTL { - // SString::SString throws + // EString constructor throws THROWS; // Yay! @@ -5685,13 +5685,13 @@ HRESULT ProfToEEInterfaceImpl::GetAssemblyInfo(AssemblyID assemblyId, if (pcchName || szName) { // Get the friendly name of the assembly - SString name(SString::Utf8, pAssembly->GetSimpleName()); + SString name(EString(pAssembly->GetSimpleName()).MoveToUnicode()); const COUNT_T nameLength = name.GetCount() + 1; if ((NULL != szName) && (cchName > 0)) { - wcsncpy_s(szName, cchName, name.GetUnicode(), min(nameLength, cchName - 1)); + wcsncpy_s(szName, cchName, name, min(nameLength, cchName - 1)); } if (NULL != pcchName) @@ -6473,9 +6473,9 @@ HRESULT ProfToEEInterfaceImpl::GetDynamicFunctionInfo(FunctionID functionId, *pcchName = 0; StackSString ss; - ss.SetUTF8(pMethDesc->GetName()); - ss.Normalize(); - LPCWSTR methodName = ss.GetUnicode(); + MAKE_WIDEPTR_FROMUTF8(pName, pMethDesc->GetName()); + ss.Set(pName); + LPCWSTR methodName = ss; ULONG trueLen = (ULONG)(wcslen(methodName) + 1); diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp index d2228aeba4bbb0..1b0b3a21cc2865 100644 --- a/src/coreclr/vm/readytoruninfo.cpp +++ b/src/coreclr/vm/readytoruninfo.cpp @@ -408,7 +408,7 @@ static void LogR2r(const char *msg, PEAssembly *pPEAssembly) // Append process ID to the log file name, so multiple processes can log at the same time. StackSString fullname; fullname.Printf(W("%s.%u"), wszReadyToRunLogFile.GetValue(), GetCurrentProcessId()); - r2rLogFile = _wfopen(fullname.GetUnicode(), W("w")); + r2rLogFile = _wfopen((LPCWSTR)fullname, W("w")); } else r2rLogFile = NULL; @@ -431,7 +431,7 @@ static void LogR2r(const char *msg, PEAssembly *pPEAssembly) if (r2rLogFile == NULL) return; - fprintf(r2rLogFile, "%s: \"%S\".\n", msg, pPEAssembly->GetPath().GetUnicode()); + fprintf(r2rLogFile, "%s: \"%S\".\n", msg, (LPCWSTR)pPEAssembly->GetPath()); fflush(r2rLogFile); } diff --git a/src/coreclr/vm/rtlfunctions.cpp b/src/coreclr/vm/rtlfunctions.cpp index 23f662b4d600ae..7cb88c1c13a750 100644 --- a/src/coreclr/vm/rtlfunctions.cpp +++ b/src/coreclr/vm/rtlfunctions.cpp @@ -96,14 +96,14 @@ VOID InstallEEFunctionTable ( if (ssTempName.GetCount() < MAX_LONGPATH) { - wcscpy_s(rgwModuleName, MAX_LONGPATH, ssTempName.GetUnicode()); + wcscpy_s(rgwModuleName, MAX_LONGPATH, ssTempName); // publish result InterlockedExchangeT(&wszModuleName, rgwModuleName); } else { - NewArrayHolder wzTempName(DuplicateStringThrowing(ssTempName.GetUnicode())); + NewArrayHolder wzTempName(DuplicateStringThrowing(ssTempName)); // publish result if (InterlockedCompareExchangeT(&wszModuleName, (LPWSTR)wzTempName, nullptr) == nullptr) diff --git a/src/coreclr/vm/runtimecallablewrapper.cpp b/src/coreclr/vm/runtimecallablewrapper.cpp index 84c0c5bdcd0292..0538619064b7a9 100644 --- a/src/coreclr/vm/runtimecallablewrapper.cpp +++ b/src/coreclr/vm/runtimecallablewrapper.cpp @@ -70,14 +70,16 @@ void ComClassFactory::ThrowHRMsg(HRESULT hr, DWORD dwMsgResID) // Obtain the textual representation of the HRESULT. StringFromGUID2(m_rclsid, strClsid, sizeof(strClsid) / sizeof(WCHAR)); - SString strHRHex; + EString strHRHex; strHRHex.Printf("%.8x", hr); + SString strHRHexW; + strHRHex.ConvertToUnicode(strHRHexW); // Obtain the description of the HRESULT. GetHRMsg(hr, strHRDescription); // Load the appropriate resource and throw - COMPlusThrowHR(hr, dwMsgResID, strHRHex, strClsid, strHRDescription.GetUnicode()); + COMPlusThrowHR(hr, dwMsgResID, strHRHexW, strClsid, strHRDescription); } //------------------------------------------------------------- @@ -510,17 +512,19 @@ IClassFactory *ComClassFactory::GetIClassFactory() // Obtain the textual representation of the HRESULT. StringFromGUID2(m_rclsid, strClsid, sizeof(strClsid) / sizeof(WCHAR)); - SString strHRHex; + EString strHRHex; strHRHex.Printf("%.8x", hr); + SString strHRHexW; + strHRHex.ConvertToUnicode(strHRHexW); // Obtain the description of the HRESULT. GetHRMsg(hr, strHRDescription); // Throw the actual exception indicating we couldn't find the class factory. if (m_wszServer == NULL) - COMPlusThrowHR(hr, IDS_EE_LOCAL_COGETCLASSOBJECT_FAILED, strHRHex, strClsid, strHRDescription.GetUnicode()); + COMPlusThrowHR(hr, IDS_EE_LOCAL_COGETCLASSOBJECT_FAILED, strHRHexW, strClsid, strHRDescription); else - COMPlusThrowHR(hr, IDS_EE_REMOTE_COGETCLASSOBJECT_FAILED, strHRHex, strClsid, m_wszServer, strHRDescription.GetUnicode()); + COMPlusThrowHR(hr, IDS_EE_REMOTE_COGETCLASSOBJECT_FAILED, strHRHexW, strClsid, m_wszServer, strHRDescription); } RETURN pClassFactory; @@ -2601,11 +2605,11 @@ void ComObject::ThrowInvalidCastException(OBJECTREF *pObj, MethodTable *pCastToM IID *pNativeIID = NULL; GUID iid; - // Use an InlineSString with a size of MAX_CLASSNAME_LENGTH + 1 to prevent + // Use an InlineEString with a size of MAX_CLASSNAME_LENGTH + 1 to prevent // TypeHandle::GetName from having to allocate a new block of memory. This // significantly improves the performance of throwing an InvalidCastException. - InlineSString strComObjClassName; - InlineSString strCastToName; + InlineEString strComObjClassName; + InlineEString strCastToName; TypeHandle thClass = (*pObj)->GetTypeHandle(); TypeHandle thCastTo = TypeHandle(pCastToMT); @@ -2631,7 +2635,7 @@ void ComObject::ThrowInvalidCastException(OBJECTREF *pObj, MethodTable *pCastToM // no longer fails now, we still need to throw, so throw a generic invalid cast exception. if (SUCCEEDED(hr)) { - COMPlusThrow(kInvalidCastException, IDS_EE_CANNOTCAST, strComObjClassName.GetUnicode(), strCastToName.GetUnicode()); + COMPlusThrow(kInvalidCastException, IDS_EE_CANNOTCAST, strComObjClassName, strCastToName); } // Convert the IID to a string. @@ -2656,13 +2660,13 @@ void ComObject::ThrowInvalidCastException(OBJECTREF *pObj, MethodTable *pCastToM WCHAR strSrcItfIID[39]; StringFromGUID2(SrcItfIID, strSrcItfIID, sizeof(strSrcItfIID) / sizeof(WCHAR)); - COMPlusThrow(kInvalidCastException, IDS_EE_RCW_INVALIDCAST_EVENTITF, strHRDescription.GetUnicode(), strComObjClassName.GetUnicode(), - strCastToName.GetUnicode(), strIID, strSrcItfIID); + COMPlusThrow(kInvalidCastException, IDS_EE_RCW_INVALIDCAST_EVENTITF, strHRDescription, strComObjClassName, + strCastToName, strIID, strSrcItfIID); } else if (thCastTo == TypeHandle(CoreLibBinder::GetClass(CLASS__IENUMERABLE))) { COMPlusThrow(kInvalidCastException, IDS_EE_RCW_INVALIDCAST_IENUMERABLE, - strHRDescription.GetUnicode(), strComObjClassName.GetUnicode(), strCastToName.GetUnicode(), strIID); + strHRDescription, strComObjClassName, strCastToName, strIID); } else if ((pNativeIID = MngStdInterfaceMap::GetNativeIIDForType(thCastTo)) != NULL) { @@ -2676,19 +2680,19 @@ void ComObject::ThrowInvalidCastException(OBJECTREF *pObj, MethodTable *pCastToM // If this function was called, it means the QI call failed in the past. If it // no longer fails now, we still need to throw, so throw a generic invalid cast exception. if (SUCCEEDED(hr2)) - COMPlusThrow(kInvalidCastException, IDS_EE_CANNOTCAST, strComObjClassName.GetUnicode(), strCastToName.GetUnicode()); + COMPlusThrow(kInvalidCastException, IDS_EE_CANNOTCAST, strComObjClassName, strCastToName); // Obtain the textual description of the 2nd HRESULT. SString strHR2Description; GetHRMsg(hr2, strHR2Description); - COMPlusThrow(kInvalidCastException, IDS_EE_RCW_INVALIDCAST_MNGSTDITF, strHRDescription.GetUnicode(), strComObjClassName.GetUnicode(), - strCastToName.GetUnicode(), strIID, strNativeItfIID, strHR2Description.GetUnicode()); + COMPlusThrow(kInvalidCastException, IDS_EE_RCW_INVALIDCAST_MNGSTDITF, strHRDescription, strComObjClassName, + strCastToName, strIID, strNativeItfIID, strHR2Description); } else { COMPlusThrow(kInvalidCastException, IDS_EE_RCW_INVALIDCAST_ITF, - strHRDescription.GetUnicode(), strComObjClassName.GetUnicode(), strCastToName.GetUnicode(), strIID); + strHRDescription, strComObjClassName, strCastToName, strIID); } } else @@ -2702,21 +2706,21 @@ void ComObject::ThrowInvalidCastException(OBJECTREF *pObj, MethodTable *pCastToM { // An attempt was made to cast an __ComObject to ComImport metadata defined type. COMPlusThrow(kInvalidCastException, IDS_EE_RCW_INVALIDCAST_COMOBJ_TO_MD, - strComObjClassName.GetUnicode(), strCastToName.GetUnicode()); + strComObjClassName, strCastToName); } else { // An attempt was made to cast an instance of a ComImport metadata defined type to // a different non ComImport metadata defined type. COMPlusThrow(kInvalidCastException, IDS_EE_RCW_INVALIDCAST_MD_TO_MD, - strComObjClassName.GetUnicode(), strCastToName.GetUnicode()); + strComObjClassName, strCastToName); } } else { // An attempt was made to cast this RCW to a non ComObjectType class. COMPlusThrow(kInvalidCastException, IDS_EE_RCW_INVALIDCAST_TO_NON_COMOBJTYPE, - strComObjClassName.GetUnicode(), strCastToName.GetUnicode()); + strComObjClassName, strCastToName); } } diff --git a/src/coreclr/vm/runtimehandles.cpp b/src/coreclr/vm/runtimehandles.cpp index c849a0a53d5eb3..7d1605e7f69db8 100644 --- a/src/coreclr/vm/runtimehandles.cpp +++ b/src/coreclr/vm/runtimehandles.cpp @@ -48,10 +48,10 @@ extern "C" BOOL QCALLTYPE MdUtf8String_EqualsCaseInsensitive(LPCUTF8 szLhs, LPCU // At this point, both the left and right strings are guaranteed to have the // same length. - StackSString lhs(SString::Utf8, szLhs, stringNumBytes); - StackSString rhs(SString::Utf8, szRhs, stringNumBytes); + StackEString lhs(szLhs, stringNumBytes); + StackEString rhs(szRhs, stringNumBytes); - // We can use SString for simple case insensitive compares + // We can use EString for simple case insensitive compares fStringsEqual = lhs.EqualsCaseInsensitive(rhs); END_QCALL; @@ -70,7 +70,7 @@ extern "C" ULONG QCALLTYPE MdUtf8String_HashCaseInsensitive(LPCUTF8 sz, INT32 st BEGIN_QCALL; - StackSString str(SString::Utf8, sz, stringNumBytes); + StackEString str(sz, stringNumBytes); hashValue = str.HashCaseInsensitive(); END_QCALL; diff --git a/src/coreclr/vm/sigformat.cpp b/src/coreclr/vm/sigformat.cpp index 2225be54cd7bd5..08d496d19b8307 100644 --- a/src/coreclr/vm/sigformat.cpp +++ b/src/coreclr/vm/sigformat.cpp @@ -561,11 +561,13 @@ void SigFormat::AddType(TypeHandle th) case ELEMENT_TYPE_VAR: case ELEMENT_TYPE_MVAR: { - StackScratchBuffer scratch; StackSString name; th.GetName(name); - AddString(name.GetANSI(scratch)); + StackEString nameUTF8; + name.ConvertToUTF8(nameUTF8); + + AddString((LPCUTF8)nameUTF8); break; } diff --git a/src/coreclr/vm/stubgen.cpp b/src/coreclr/vm/stubgen.cpp index a1dae94859cc0d..c8064fd1d016bc 100644 --- a/src/coreclr/vm/stubgen.cpp +++ b/src/coreclr/vm/stubgen.cpp @@ -24,15 +24,15 @@ // ....[.....\xxxxx]..0... -> ....[xxxxx]..0... // ^ ^ ^ -void DumpIL_RemoveFullPath(SString &strTokenFormatting) +void DumpIL_RemoveFullPath(EString &strTokenFormatting) { STANDARD_VM_CONTRACT; if (strTokenFormatting.IsEmpty()) return; - SString::Iterator begin = strTokenFormatting.Begin(); - SString::Iterator end = strTokenFormatting.End(); - SString::Iterator leftBracket = strTokenFormatting.Begin(); + auto begin = strTokenFormatting.Begin(); + auto end = strTokenFormatting.End(); + auto leftBracket = strTokenFormatting.Begin(); // Find the first '[' in the string. while ((leftBracket != end) && (*leftBracket != '[')) @@ -42,7 +42,7 @@ void DumpIL_RemoveFullPath(SString &strTokenFormatting) if (leftBracket != end) { - SString::Iterator lastSlash = strTokenFormatting.End() - 1; + auto lastSlash = strTokenFormatting.End() - 1; // Find the last '\\' in the string. while ((lastSlash != leftBracket) && (*lastSlash != '\\')) @@ -57,7 +57,7 @@ void DumpIL_RemoveFullPath(SString &strTokenFormatting) } } -void ILStubLinker::DumpIL_FormatToken(mdToken token, SString &strTokenFormatting) +void ILStubLinker::DumpIL_FormatToken(mdToken token, EString &strTokenFormatting) { void* pvLookupRetVal = (void*)POISONC; _ASSERTE(strTokenFormatting.IsEmpty()); @@ -70,7 +70,9 @@ void ILStubLinker::DumpIL_FormatToken(mdToken token, SString &strTokenFormatting pvLookupRetVal = pMD; CONSISTENCY_CHECK(CheckPointer(pMD)); - pMD->GetFullMethodInfo(strTokenFormatting); + StackSString methodInfo; + pMD->GetFullMethodInfo(methodInfo); + methodInfo.ConvertToUTF8(strTokenFormatting); } else if (TypeFromToken(token) == mdtTypeDef) { @@ -105,11 +107,10 @@ void ILStubLinker::DumpIL_FormatToken(mdToken token, SString &strTokenFormatting SString typeName; TypeString::AppendType(typeName, TypeHandle(pFD->GetApproxEnclosingMethodTable())); - - SString typeNameUtf8; - typeName.ConvertToUTF8(typeNameUtf8); - SString strFieldName(SString::Utf8, pFD->GetName()); - strTokenFormatting.Printf("%s::%s", typeNameUtf8.GetUTF8NoConvert(), strFieldName.GetUTF8NoConvert()); + EString strFieldName(pFD->GetName()); + strTokenFormatting.Append(typeName.MoveToUTF8()); + strTokenFormatting.Append("::"); + strTokenFormatting.Append(strFieldName); } else if (TypeFromToken(token) == mdtModule) { @@ -139,7 +140,7 @@ void ILStubLinker::DumpIL_FormatToken(mdToken token, SString &strTokenFormatting CQuickBytes sigStr; PrettyPrintSig(pSig, cbSig, "", &sigStr, pIMDI, NULL); - strTokenFormatting.SetUTF8((LPUTF8)sigStr.Ptr()); + strTokenFormatting.Set((LPUTF8)sigStr.Ptr()); } else { @@ -458,27 +459,27 @@ ILStubLinker::LogILInstruction( bool isLabeled, INT iCurStack, ILInstruction * pInstruction, - SString * pDumpILStubCode) + EString * pDumpILStubCode) { STANDARD_VM_CONTRACT; // // format label // - SString strLabel; + EString strLabel; if (isLabeled) { - strLabel.Printf("IL_%04x:", (uint32_t)curOffset); + strLabel.Printf("IL_%04x:", curOffset); } else { - strLabel.SetUTF8(" "); + strLabel.Set(" "); } // // format opcode // - SString strOpcode; + EString strOpcode; ILCodeStream::ILInstrEnum instr = (ILCodeStream::ILInstrEnum)pInstruction->uInstruction; // Set the width of the opcode to 15. @@ -489,11 +490,11 @@ ILStubLinker::LogILInstruction( // static const size_t c_cchPreallocateArgument = 512; - SString strArgument; + EString strArgument; strArgument.Preallocate(c_cchPreallocateArgument); static const size_t c_cchPreallocateTokenName = 1024; - SString strTokenName; + EString strTokenName; strTokenName.Preallocate(c_cchPreallocateTokenName); if (ILCodeStream::IsBranchInstruction(instr)) @@ -550,13 +551,13 @@ ILStubLinker::LogILInstruction( // if (pDumpILStubCode) { - pDumpILStubCode->AppendPrintf("%s /*(%2d)*/ %s %s %s\n", strLabel.GetUTF8NoConvert(), iCurStack, strOpcode.GetUTF8NoConvert(), - strArgument.GetUTF8NoConvert(), strTokenName.GetUTF8NoConvert()); + pDumpILStubCode->AppendPrintf("%s /*(%2d)*/ %s %s %s\n", (LPCUTF8)strLabel, iCurStack, (LPCUTF8)strOpcode, + (LPCUTF8)strArgument, (LPCUTF8)strTokenName); } else { - LOG((LF_STUBS, LL_INFO1000, "%s (%2d) %s %s %s\n", strLabel.GetUTF8NoConvert(), iCurStack, \ - strOpcode.GetUTF8NoConvert(), strArgument.GetUTF8NoConvert(), strTokenName.GetUTF8NoConvert())); + LOG((LF_STUBS, LL_INFO1000, "%s (%2d) %s %s %s\n", (LPCUTF8)strLabel, iCurStack, \ + (LPCUTF8)strOpcode, (LPCUTF8)strArgument, (LPCUTF8)strTokenName)); } } // ILStubLinker::LogILInstruction @@ -568,7 +569,7 @@ ILStubLinker::LogILStubWorker( UINT numInstr, size_t * pcbCode, INT * piCurStack, - SString * pDumpILStubCode) + EString * pDumpILStubCode) { CONTRACTL { @@ -650,7 +651,7 @@ static void LogJitFlags(DWORD facility, DWORD level, CORJIT_FLAGS jitFlags) } } -void ILStubLinker::LogILStub(CORJIT_FLAGS jitFlags, SString *pDumpILStubCode) +void ILStubLinker::LogILStub(CORJIT_FLAGS jitFlags, EString *pDumpILStubCode) { CONTRACTL { diff --git a/src/coreclr/vm/stubgen.h b/src/coreclr/vm/stubgen.h index 257bd245ec798c..ba602344e69a61 100644 --- a/src/coreclr/vm/stubgen.h +++ b/src/coreclr/vm/stubgen.h @@ -557,11 +557,11 @@ class ILStubLinker void ClearCodeStreams(); - void LogILStub(CORJIT_FLAGS jitFlags, SString *pDumpILStubCode = NULL); + void LogILStub(CORJIT_FLAGS jitFlags, EString *pDumpILStubCode = NULL); protected: - void DumpIL_FormatToken(mdToken token, SString &strTokenFormatting); - void LogILStubWorker(ILInstruction* pInstrBuffer, UINT numInstr, size_t* pcbCode, INT* piCurStack, SString *pDumpILStubCode = NULL); - void LogILInstruction(size_t curOffset, bool isLabeled, INT iCurStack, ILInstruction* pInstruction, SString *pDumpILStubCode = NULL); + void DumpIL_FormatToken(mdToken token, EString &strTokenFormatting); + void LogILStubWorker(ILInstruction* pInstrBuffer, UINT numInstr, size_t* pcbCode, INT* piCurStack, EString *pDumpILStubCode = NULL); + void LogILInstruction(size_t curOffset, bool isLabeled, INT iCurStack, ILInstruction* pInstruction, EString *pDumpILStubCode = NULL); private: ILCodeStream* m_pCodeStreamList; diff --git a/src/coreclr/vm/stubhelpers.cpp b/src/coreclr/vm/stubhelpers.cpp index 0ba31d449f538d..4469146c8ab417 100644 --- a/src/coreclr/vm/stubhelpers.cpp +++ b/src/coreclr/vm/stubhelpers.cpp @@ -123,8 +123,9 @@ void StubHelpers::FormatValidationMessage(MethodDesc *pMD, SString &ssErrorStrin pMD->GetMethodTable()->_GetFullyQualifiedNameForClass(ssClassName); ssErrorString.Append(ssClassName); - ssErrorString.Append(NAMESPACE_SEPARATOR_CHAR); - ssErrorString.AppendUTF8(pMD->GetName()); + ssErrorString.Append(NAMESPACE_SEPARATOR_WCHAR); + MAKE_WIDEPTR_FROMUTF8(methodName, pMD->GetName()); + ssErrorString.Append(methodName); ssErrorString.Append(W("'.")); } @@ -163,7 +164,7 @@ void StubHelpers::ProcessByrefValidationList() EX_TRY { FormatValidationMessage(entry.pMD, errorString); - EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, errorString.GetUnicode()); + EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, (LPCWSTR)errorString); } EX_CATCH { @@ -833,7 +834,7 @@ FCIMPL3(void, StubHelpers::ValidateObject, Object *pObjUNSAFE, MethodDesc *pMD, EX_CATCH { FormatValidationMessage(ResolveInteropMethod(pThisUNSAFE, pMD), errorString); - EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, errorString.GetUnicode()); + EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, (LPCWSTR)errorString); } EX_END_CATCH_UNREACHABLE; diff --git a/src/coreclr/vm/stubmgr.cpp b/src/coreclr/vm/stubmgr.cpp index fa233bdc594784..87dc0c51dc3bd2 100644 --- a/src/coreclr/vm/stubmgr.cpp +++ b/src/coreclr/vm/stubmgr.cpp @@ -53,7 +53,7 @@ void LogTraceDestination(const char * szHint, PCODE stubAddr, TraceDestination * #ifdef _DEBUG // Get a string representation of this TraceDestination // Uses the supplied buffer to store the memory (or may return a string literal). -const WCHAR * TraceDestination::DbgToString(SString & buffer) +const char * TraceDestination::DbgToString(EString & buffer) { CONTRACTL { @@ -63,12 +63,12 @@ const WCHAR * TraceDestination::DbgToString(SString & buffer) } CONTRACTL_END; - const WCHAR * pValue = W("unknown"); + const char * pValue = "unknown"; #ifndef DACCESS_COMPILE if (!StubManager::IsStubLoggingEnabled()) { - return W(""); + return ""; } // Now that we know we're not interop-debugging, we can safely call new. SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE; @@ -82,50 +82,50 @@ const WCHAR * TraceDestination::DbgToString(SString & buffer) { case TRACE_ENTRY_STUB: buffer.Printf("TRACE_ENTRY_STUB(addr=0x%p)", GetAddress()); - pValue = buffer.GetUnicode(); + pValue = (LPCUTF8)buffer; break; case TRACE_STUB: buffer.Printf("TRACE_STUB(addr=0x%p)", GetAddress()); - pValue = buffer.GetUnicode(); + pValue = (LPCUTF8)buffer; break; case TRACE_UNMANAGED: buffer.Printf("TRACE_UNMANAGED(addr=0x%p)", GetAddress()); - pValue = buffer.GetUnicode(); + pValue = (LPCUTF8)buffer; break; case TRACE_MANAGED: buffer.Printf("TRACE_MANAGED(addr=0x%p)", GetAddress()); - pValue = buffer.GetUnicode(); + pValue = (LPCUTF8)buffer; break; case TRACE_UNJITTED_METHOD: { MethodDesc * md = this->GetMethodDesc(); buffer.Printf("TRACE_UNJITTED_METHOD(md=0x%p, %s::%s)", md, md->m_pszDebugClassName, md->m_pszDebugMethodName); - pValue = buffer.GetUnicode(); + pValue = (LPCUTF8)buffer; } break; case TRACE_FRAME_PUSH: buffer.Printf("TRACE_FRAME_PUSH(addr=0x%p)", GetAddress()); - pValue = buffer.GetUnicode(); + pValue = (LPCUTF8)buffer; break; case TRACE_MGR_PUSH: buffer.Printf("TRACE_MGR_PUSH(addr=0x%p, sm=%s)", GetAddress(), this->GetStubManager()->DbgGetName()); - pValue = buffer.GetUnicode(); + pValue = (LPCUTF8)buffer; break; case TRACE_OTHER: - pValue = W("TRACE_OTHER"); + pValue = "TRACE_OTHER"; break; } } EX_CATCH { - pValue = W("(OOM while printing TD)"); + pValue = "(OOM while printing TD)"; } EX_END_CATCH(SwallowAllExceptions); #endif @@ -196,7 +196,7 @@ void TraceDestination::InitForUnjittedMethod(MethodDesc * pDesc) // Initialize statics. #ifdef _DEBUG -SString * StubManager::s_pDbgStubManagerLog = NULL; +EString * StubManager::s_pDbgStubManagerLog = NULL; CrstStatic StubManager::s_DbgLogCrst; #endif @@ -541,8 +541,8 @@ BOOL StubManager::TraceStub(PCODE stubStartAddress, TraceDestination *trace) { SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE; FAULT_NOT_FATAL(); - SString buffer; - DbgWriteLog(" td=%S\n", trace->DbgToString(buffer)); + EString buffer; + DbgWriteLog(" td=%s\n", trace->DbgToString(buffer)); } else { @@ -739,7 +739,7 @@ void StubManager::TerminateStubManagers() //----------------------------------------------------------- bool StubManager::IsStubLoggingEnabled() { - // Our current logging impl uses SString, which uses new(), which can't be called + // Our current logging impl uses EString, which uses new(), which can't be called // on the helper thread. (B/c it may deadlock. See SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE) // We avoid this by just not logging when native-debugging. @@ -786,7 +786,7 @@ void StubManager::DbgBeginLog(TADDR addrCallInstruction, TADDR addrCallTarget) { if (s_pDbgStubManagerLog == NULL) { - s_pDbgStubManagerLog = new SString(); + s_pDbgStubManagerLog = new EString(); } s_pDbgStubManagerLog->Clear(); } @@ -863,7 +863,7 @@ void StubManager::DbgWriteLog(const CHAR *format, ...) return; } - // Suppress asserts about lossy encoding conversion in SString::Printf + // Suppress asserts about lossy encoding conversion in StaticStringHelpers::Printf CHECK chk; BOOL fEntered = chk.EnterAssert(); @@ -888,7 +888,7 @@ void StubManager::DbgWriteLog(const CHAR *format, ...) //----------------------------------------------------------- // Get the log as a string. //----------------------------------------------------------- -void StubManager::DbgGetLog(SString * pStringOut) +void StubManager::DbgGetLog(EString * pStringOut) { #ifndef DACCESS_COMPILE CONTRACTL diff --git a/src/coreclr/vm/stubmgr.h b/src/coreclr/vm/stubmgr.h index 719db338443627..f05de1b1abc286 100644 --- a/src/coreclr/vm/stubmgr.h +++ b/src/coreclr/vm/stubmgr.h @@ -66,7 +66,6 @@ enum TraceType }; class StubManager; -class SString; class DebuggerRCThread; @@ -86,7 +85,7 @@ class TraceDestination // Get a string representation of this TraceDestination // Uses the supplied buffer to store the memory (or may return a string literal). // This will also print the TD's arguments. - const WCHAR * DbgToString(SString &buffer); + const char * DbgToString(EString &buffer); #endif // Initialize for unmanaged code. @@ -298,11 +297,11 @@ class StubManager static void DbgWriteLog(const CHAR *format, ...); // Get the log as a string. - static void DbgGetLog(SString * pStringOut); + static void DbgGetLog(EString * pStringOut); protected: - // Implement log as a SString. - static SString * s_pDbgStubManagerLog; + // Implement log as a EString. + static EString * s_pDbgStubManagerLog; static CrstStatic s_DbgLogCrst; diff --git a/src/coreclr/vm/typedesc.cpp b/src/coreclr/vm/typedesc.cpp index 89c0e53e6ba88e..e10665dc516dd6 100644 --- a/src/coreclr/vm/typedesc.cpp +++ b/src/coreclr/vm/typedesc.cpp @@ -178,7 +178,7 @@ void TypeDesc::ConstructName(CorElementType kind, { THROWS; GC_NOTRIGGER; - INJECT_FAULT(COMPlusThrowOM()); // SString operations can allocate. + INJECT_FAULT(COMPlusThrowOM()); // EString operations can allocate. } CONTRACTL_END @@ -238,14 +238,16 @@ void TypeDesc::ConstructName(CorElementType kind, default: LPCUTF8 namesp = CorTypeInfo::GetNamespace(kind); if(namesp && *namesp) { - ssBuff.AppendUTF8(namesp); + MAKE_WIDEPTR_FROMUTF8(wnamesp, namesp); + ssBuff.Append(wnamesp); ssBuff.Append(W('.')); } LPCUTF8 name = CorTypeInfo::GetName(kind); BAD_FORMAT_NOTHROW_ASSERT(name); if (name && *name) { - ssBuff.AppendUTF8(name); + MAKE_WIDEPTR_FROMUTF8(wname, name); + ssBuff.Append(wname); } } } diff --git a/src/coreclr/vm/typehandle.cpp b/src/coreclr/vm/typehandle.cpp index c0b194c86e9fac..86ca7a656682ab 100644 --- a/src/coreclr/vm/typehandle.cpp +++ b/src/coreclr/vm/typehandle.cpp @@ -1344,8 +1344,10 @@ BOOL SatisfiesClassConstraints(TypeHandle instanceTypeHnd, TypeHandle typicalTyp if (!bSatisfiesConstraints) { - SString argNum; + SmallStackEString argNum; argNum.Printf("%d", i); + SmallStackSString argNumW; + argNum.ConvertToUnicode(argNumW); SString typicalTypeHndName; TypeString::AppendType(typicalTypeHndName, typicalTypeHnd); @@ -1358,7 +1360,7 @@ BOOL SatisfiesClassConstraints(TypeHandle instanceTypeHnd, TypeHandle typicalTyp COMPlusThrow(kTypeLoadException, IDS_EE_CLASS_CONSTRAINTS_VIOLATION, - argNum, + argNumW, actualParamName, typicalTypeHndName, formalParamName @@ -1503,50 +1505,50 @@ CHECK TypeHandle::CheckMatchesKey(TypeKey *pKey) const { MethodTable *pMT = AsMethodTable(); CHECK_MSGF(pMT->GetInternalCorElementType() == pKey->GetKind(), - ("CorElementType %d of Array MethodTable does not match key %S", pMT->GetArrayElementType(), typeKeyString.GetUnicode())); + ("CorElementType %d of Array MethodTable does not match key %S", pMT->GetArrayElementType(), (LPCWSTR)typeKeyString)); CHECK_MSGF(pMT->GetArrayElementTypeHandle() == pKey->GetElementType(), - ("Element type of Array MethodTable does not match key %S",typeKeyString.GetUnicode())); + ("Element type of Array MethodTable does not match key %S",(LPCWSTR)typeKeyString)); CHECK_MSGF(pMT->GetRank() == pKey->GetRank(), - ("Rank %d of Array MethodTable does not match key %S", pMT->GetRank(), typeKeyString.GetUnicode())); + ("Rank %d of Array MethodTable does not match key %S", pMT->GetRank(), (LPCWSTR)typeKeyString)); } else if (IsTypeDesc()) { TypeDesc *pTD = AsTypeDesc(); CHECK_MSGF(pTD->GetInternalCorElementType() == pKey->GetKind(), - ("CorElementType %d of TypeDesc does not match key %S", pTD->GetInternalCorElementType(), typeKeyString.GetUnicode())); + ("CorElementType %d of TypeDesc does not match key %S", pTD->GetInternalCorElementType(), (LPCWSTR)typeKeyString)); if (CorTypeInfo::IsModifier(pKey->GetKind())) { CHECK_MSGF(pTD->GetTypeParam() == pKey->GetElementType(), - ("Element type of TypeDesc does not match key %S",typeKeyString.GetUnicode())); + ("Element type of TypeDesc does not match key %S",(LPCWSTR)typeKeyString)); } } else { MethodTable *pMT = AsMethodTable(); - CHECK_MSGF(pMT->GetModule() == pKey->GetModule(), ("Module of MethodTable does not match key %S", typeKeyString.GetUnicode())); + CHECK_MSGF(pMT->GetModule() == pKey->GetModule(), ("Module of MethodTable does not match key %S", (LPCWSTR)typeKeyString)); CHECK_MSGF(pMT->GetCl() == pKey->GetTypeToken(), ("TypeDef %x of Methodtable does not match TypeDef %x of key %S", pMT->GetCl(), pKey->GetTypeToken(), - typeKeyString.GetUnicode())); + (LPCWSTR)typeKeyString)); if (pMT->IsTypicalTypeDefinition()) { CHECK_MSGF(pKey->GetNumGenericArgs() == 0 && !pKey->HasInstantiation(), - ("Key %S for Typical MethodTable has non-zero number of generic arguments", typeKeyString.GetUnicode())); + ("Key %S for Typical MethodTable has non-zero number of generic arguments", (LPCWSTR)typeKeyString)); } else { CHECK_MSGF(pMT->GetNumGenericArgs() == pKey->GetNumGenericArgs(), - ("Number of generic params %d in MethodTable does not match key %S", pMT->GetNumGenericArgs(), typeKeyString.GetUnicode())); + ("Number of generic params %d in MethodTable does not match key %S", pMT->GetNumGenericArgs(), (LPCWSTR)typeKeyString)); if (pKey->HasInstantiation()) { for (DWORD i = 0; i < pMT->GetNumGenericArgs(); i++) { CHECK_MSGF(pMT->GetInstantiation()[i] == pKey->GetInstantiation()[i], - ("Generic argument %d in MethodTable does not match key %S", i, typeKeyString.GetUnicode())); + ("Generic argument %d in MethodTable does not match key %S", i, (LPCWSTR)typeKeyString)); } } } @@ -1578,12 +1580,12 @@ CHECK TypeHandle::CheckLoadLevel(ClassLoadLevel requiredLevel) ClassLoadLevel actualLevel = GetLoadLevel(); if (actualLevel < requiredLevel) { - // SString debugTypeName; + // EString debugTypeName; // TypeString::AppendTypeDebug(debugTypeName, *this); CHECK(actualLevel >= requiredLevel); // CHECK_MSGF(actualLevel >= requiredLevel, // ("Type has not been sufficiently loaded (actual level is %d, required level is %d)", - // /* debugTypeName.GetUnicode(), */ actualLevel, requiredLevel /* classLoadLevelName[actualLevel], classLoadLevelName[requiredLevel] */)); + // /* (LPCWSTR)debugTypeName, */ actualLevel, requiredLevel /* classLoadLevelName[actualLevel], classLoadLevelName[requiredLevel] */)); } CONSISTENCY_CHECK((actualLevel > CLASS_LOAD_UNRESTORED) == IsRestored()); CONSISTENCY_CHECK((actualLevel == CLASS_LOAD_UNRESTOREDTYPEKEY) == HasUnrestoredTypeKey()); diff --git a/src/coreclr/vm/typeparse.cpp b/src/coreclr/vm/typeparse.cpp index 0defa23f4cf072..dd4304d852bfb7 100644 --- a/src/coreclr/vm/typeparse.cpp +++ b/src/coreclr/vm/typeparse.cpp @@ -30,7 +30,7 @@ SString* TypeName::ToString(SString* pBuf, BOOL bAssemblySpec, BOOL bSignature, TypeNameBuilder tnb(pBuf); for (COUNT_T i = 0; i < m_names.GetCount(); i ++) - tnb.AddName(m_names[i]->GetUnicode()); + tnb.AddName(*m_names[i]); return pBuf; } @@ -131,11 +131,11 @@ extern "C" void QCALLTYPE TypeName_CreateTypeNameParser(LPCWSTR wszTypeName, QCa { StackSString buf; StackSString msg(W("typeName@")); - COUNT_T size = buf.GetUnicodeAllocation(); - _itow_s(error, buf.OpenUnicodeBuffer(size), size, /*radix*/10); + COUNT_T size = buf.GetAllocation(); + _itow_s(error, buf.OpenBuffer(size), size, /*radix*/10); buf.CloseBuffer(); msg.Append(buf); - COMPlusThrowArgumentException(msg.GetUnicode(), NULL); + COMPlusThrowArgumentException(msg, NULL); } } @@ -186,7 +186,7 @@ extern "C" void QCALLTYPE TypeName_GetNames(TypeName * pTypeName, QCall::ObjectH for (COUNT_T i = 0; i < count; i++) { - STRINGREF str = StringObject::NewString(names[i]->GetUnicode()); + STRINGREF str = StringObject::NewString(*names[i]); pReturnNames->SetAt(i, str); } @@ -807,8 +807,9 @@ TypeHandle TypeName::GetTypeUsingCASearchRules(LPCUTF8 szTypeName, Assembly *pRe STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_FAULT; - StackSString sszAssemblyQualifiedName(SString::Utf8, szTypeName); - return GetTypeUsingCASearchRules(sszAssemblyQualifiedName.GetUnicode(), pRequestingAssembly, pfNameIsAsmQualified, bDoVisibilityChecks); + StackEString sszAssemblyQualifiedName(szTypeName); + MAKE_WIDEPTR_FROMUTF8(wszAssemblyQualifiedName, szTypeName); + return GetTypeUsingCASearchRules(wszAssemblyQualifiedName, pRequestingAssembly, pfNameIsAsmQualified, bDoVisibilityChecks); } TypeHandle TypeName::GetTypeUsingCASearchRules(LPCWSTR szTypeName, Assembly *pRequestingAssembly, BOOL *pfNameIsAsmQualified/* = NULL*/, BOOL bDoVisibilityChecks/* = TRUE*/) @@ -840,11 +841,11 @@ TypeHandle TypeName::GetTypeUsingCASearchRules(LPCWSTR szTypeName, Assembly *pRe { StackSString buf; StackSString msg(W("typeName@")); - COUNT_T size = buf.GetUnicodeAllocation(); - _itow_s(error,buf.OpenUnicodeBuffer(size),size,10); + COUNT_T size = buf.GetAllocation(); + _itow_s(error,buf.OpenBuffer(size),size,10); buf.CloseBuffer(); msg.Append(buf); - COMPlusThrowArgumentException(msg.GetUnicode(), NULL); + COMPlusThrowArgumentException(msg, NULL); } if (pfNameIsAsmQualified) @@ -927,11 +928,11 @@ TypeHandle TypeName::GetTypeUsingCASearchRules(LPCWSTR szTypeName, Assembly *pRe StackSString buf; StackSString msg(W("typeName@")); - COUNT_T size = buf.GetUnicodeAllocation(); - _itow_s(error, buf.OpenUnicodeBuffer(size), size, /*radix*/10); + COUNT_T size = buf.GetAllocation(); + _itow_s(error, buf.OpenBuffer(size), size, /*radix*/10); buf.CloseBuffer(); msg.Append(buf); - COMPlusThrowArgumentException(msg.GetUnicode(), NULL); + COMPlusThrowArgumentException(msg, NULL); } BOOL bPeriodPrefix = szTypeName[0] == W('.'); @@ -957,11 +958,11 @@ TypeHandle TypeName::GetTypeUsingCASearchRules(LPCWSTR szTypeName, Assembly *pRe StackSString buf; StackSString msg(W("typeName@")); - COUNT_T size = buf.GetUnicodeAllocation(); - _itow_s(error-1,buf.OpenUnicodeBuffer(size),size,10); + COUNT_T size = buf.GetAllocation(); + _itow_s(error-1,buf.OpenBuffer(size),size,10); buf.CloseBuffer(); msg.Append(buf); - COMPlusThrowArgumentException(msg.GetUnicode(), NULL); + COMPlusThrowArgumentException(msg, NULL); } result = pTypeName->GetTypeWorker( @@ -1012,11 +1013,11 @@ TypeHandle TypeName::GetTypeUsingCASearchRules(LPCWSTR szTypeName, Assembly *pRe { StackSString buf; StackSString msg(W("typeName@")); - COUNT_T size = buf.GetUnicodeAllocation(); - _itow_s(error,buf.OpenUnicodeBuffer(size),size,10); + COUNT_T size = buf.GetAllocation(); + _itow_s(error,buf.OpenBuffer(size),size,10); buf.CloseBuffer(); msg.Append(buf); - COMPlusThrowArgumentException(msg.GetUnicode(), NULL); + COMPlusThrowArgumentException(msg, NULL); } return pTypeName->GetTypeFromAsm(); @@ -1141,10 +1142,11 @@ TypeHandle TypeName::GetTypeFromAsm() { TypeNameBuilder tnb; for (COUNT_T i = 0; i < GetNames().GetCount(); i ++) - tnb.AddName(GetNames()[i]->GetUnicode()); + tnb.AddName(*(GetNames()[i])); - StackScratchBuffer bufFullName; - DomainAssembly* pDomainAssembly = pDomain->RaiseTypeResolveEventThrowing(pRequestingAssembly?pRequestingAssembly->GetDomainAssembly():NULL,tnb.GetString()->GetANSI(bufFullName), pAsmRef); + EString bufFullName; + tnb.GetString()->ConvertToUTF8(bufFullName); + DomainAssembly* pDomainAssembly = pDomain->RaiseTypeResolveEventThrowing(pRequestingAssembly?pRequestingAssembly->GetDomainAssembly():NULL, bufFullName, pAsmRef); if (pDomainAssembly) th = GetTypeHaveAssembly(pDomainAssembly->GetAssembly(), bThrowIfNotFound, bIgnoreCase, pKeepAlive); } @@ -1229,12 +1231,12 @@ TypeHandle TypeName::GetTypeFromAsm() if (th.IsNull() && bThrowIfNotFound) { StackSString buf; - LPCWSTR wszName = ToString(&buf)->GetUnicode(); + LPCWSTR wszName = *ToString(&buf); MAKE_UTF8PTR_FROMWIDE(szName, wszName); if (GetAssembly() && !GetAssembly()->IsEmpty()) { - ThrowTypeLoadException(NULL, szName, GetAssembly()->GetUnicode(), NULL, IDS_CLASSLOAD_GENERAL); + ThrowTypeLoadException(NULL, szName, *GetAssembly(), NULL, IDS_CLASSLOAD_GENERAL); } else if (pAssemblyGetType) { @@ -1303,8 +1305,9 @@ TypeName::GetTypeHaveAssemblyHelper( if (bIgnoreCase) name.LowerCase(); - StackScratchBuffer buffer; - typeName.SetName(name.GetUTF8(buffer)); + StackEString buffer; + name.ConvertToUTF8(buffer); + typeName.SetName(buffer); // typeName.m_pBucket gets set here if the type is found // it will be used in the next iteration to look up the nested type @@ -1407,7 +1410,8 @@ DomainAssembly * LoadDomainAssembly( AssemblySpec spec; DomainAssembly *pDomainAssembly = NULL; - StackSString ssAssemblyName(*psszAssemblySpec); + StackEString ssAssemblyName; + psszAssemblySpec->ConvertToUTF8(ssAssemblyName); spec.Init(ssAssemblyName); if (pRequestingAssembly) diff --git a/src/coreclr/vm/typeparse.h b/src/coreclr/vm/typeparse.h index 2f1854da236dcf..f4d9bdd93e0ea8 100644 --- a/src/coreclr/vm/typeparse.h +++ b/src/coreclr/vm/typeparse.h @@ -319,7 +319,7 @@ class TypeName public: - SString* GetAssembly() { WRAPPER_NO_CONTRACT; return &m_assembly; } + InlineEString<128, EncodingUnicode>* GetAssembly() { WRAPPER_NO_CONTRACT; return &m_assembly; } SArray& GetNames() { WRAPPER_NO_CONTRACT; return m_names; } SArray& GetGenericArguments() { WRAPPER_NO_CONTRACT; return m_genericArguments; } SArray& GetSignature() { WRAPPER_NO_CONTRACT; return m_signature; } @@ -339,7 +339,7 @@ class TypeName } CONTRACTL_END; - return m_names.AppendEx(m_nestNameFactory.Create()); + return m_names.AppendEx((SString*)m_nestNameFactory.Create()); } void SetByRef() { WRAPPER_NO_CONTRACT; m_signature.Append(ELEMENT_TYPE_BYREF); } @@ -397,8 +397,8 @@ class TypeName InlineSArray m_signature; InlineSArray m_genericArguments; InlineSArray m_names; - InlineSString<128> m_assembly; - Factory > m_nestNameFactory; + InlineEString<128, EncodingUnicode> m_assembly; + Factory > m_nestNameFactory; }; extern "C" void QCALLTYPE TypeName_CreateTypeNameParser (LPCWSTR wszTypeName, QCall::ObjectHandleOnStack pNames, BOOL throwOnError); diff --git a/src/coreclr/vm/typestring.cpp b/src/coreclr/vm/typestring.cpp index 0a05972721a1a2..7526e450aa2d45 100644 --- a/src/coreclr/vm/typestring.cpp +++ b/src/coreclr/vm/typestring.cpp @@ -349,8 +349,9 @@ HRESULT TypeNameBuilder::AddArray(DWORD rank) // Only taken in an error path, runtime will not load arrays of more than 32 dimensions const UTF8 fmt[] = "[%d]"; UTF8 strTmp[ARRAY_SIZE(fmt) + MaxUnsigned32BitDecString]; - _snprintf_s(strTmp, ARRAY_SIZE(strTmp), _TRUNCATE, fmt, rank); - Append(strTmp); + int length = _snprintf_s(strTmp, ARRAY_SIZE(strTmp), _TRUNCATE, fmt, rank); + MAKE_WIDEPTR_FROMUTF8N(strTmpW, strTmp, length); + Append(strTmpW); } else { @@ -502,16 +503,18 @@ void TypeString::AppendTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, const WCHAR *wszNameSpace = NULL; - InlineSString<128> ssName(SString::Utf8, szName); - InlineSString<128> ssNameSpace; + MAKE_WIDEPTR_FROMUTF8(wszName, szName); + InlineEString<128, EncodingUnicode> ssName(wszName); + InlineEString<128, EncodingUnicode> wszNamespaceStr; if (format & FormatNamespace) { - ssNameSpace.SetUTF8(szNameSpace); - wszNameSpace = ssNameSpace.GetUnicode(); + InlineEString<128, EncodingUTF8> ssNameSpace(szNameSpace); + ssNameSpace.ConvertToUnicode(wszNamespaceStr); + wszNameSpace = wszNamespaceStr; } - tnb.AddName(ssName.GetUnicode(), wszNameSpace); + tnb.AddName(ssName, wszNameSpace); RETURN; } @@ -750,9 +753,11 @@ void TypeString::AppendType(TypeNameBuilder& tnb, TypeHandle ty, Instantiation t else szPrefix = "!!"; - SmallStackSString pName(SString::Utf8, szPrefix); - pName.AppendUTF8(szName); - tnb.AddName(pName.GetUnicode()); + SmallStackEString pName(szPrefix); + pName.Append(szName); + SmallStackSString pNameW; + pName.ConvertToUnicode(pNameW); + tnb.AddName(pNameW); format &= ~FormatAssembly; } @@ -806,14 +811,15 @@ void TypeString::AppendType(TypeNameBuilder& tnb, TypeHandle ty, Instantiation t StackSString pAssemblyName; #ifdef DACCESS_COMPILE - pAssemblyName.SetUTF8(pAssembly->GetSimpleName()); + StackEString pAssemblyNameUTF8(pAssembly->GetSimpleName()); + pAssemblyNameUTF8.ConvertToUnicode(pAssemblyName); #else pAssembly->GetDisplayName(pAssemblyName, ASM_DISPLAYF_PUBLIC_KEY_TOKEN | ASM_DISPLAYF_CONTENT_TYPE | (format & FormatNoVersion ? 0 : ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE)); #endif - tnb.AddAssemblySpec(pAssemblyName.GetUnicode()); + tnb.AddAssemblySpec(pAssemblyName); } @@ -871,12 +877,13 @@ void TypeString::AppendMethodImpl(SString& ss, MethodDesc *pMD, Instantiation ty { if (pMD->IsLCGMethod()) { - SString sss(SString::Literal, "DynamicClass"); + SString sss(SString::Literal, W("DynamicClass")); ss += sss; } else if (pMD->IsILStub()) { - SString sss(SString::Literal, ILStubResolver::GetStubClassName(pMD)); + MAKE_WIDEPTR_FROMUTF8(stubClassName, ILStubResolver::GetStubClassName(pMD)); + SString sss(SString::Literal, stubClassName); ss += sss; } } @@ -886,9 +893,10 @@ void TypeString::AppendMethodImpl(SString& ss, MethodDesc *pMD, Instantiation ty AppendType(ss, th, typeInstantiation, format); } - SString sss1(SString::Literal, NAMESPACE_SEPARATOR_STR); + SString sss1(SString::Literal, NAMESPACE_SEPARATOR_WSTR); ss += sss1; - SString sss2(SString::Utf8, pMD->GetName()); + MAKE_WIDEPTR_FROMUTF8(methodName, pMD->GetName()); + SString sss2(methodName); ss += sss2; if (pMD->HasMethodInstantiation() && !pMD->IsGenericMethodDefinition()) @@ -901,40 +909,40 @@ void TypeString::AppendMethodImpl(SString& ss, MethodDesc *pMD, Instantiation ty // @TODO: The argument list should be formatted nicely using AppendType() SigFormat sigFormatter(pMD, th); - const char* sigStr = sigFormatter.GetCStringParmsOnly(); - SString sss(SString::Utf8, sigStr); + MAKE_WIDEPTR_FROMUTF8(sig, sigFormatter.GetCStringParmsOnly()); + SString sss(sig); ss += sss; } if (format & FormatStubInfo) { if (pMD->IsInstantiatingStub()) { - SString sss(SString::Literal, "{inst-stub}"); + SString sss(SString::Literal, W("{inst-stub}")); ss += sss; } if (pMD->IsUnboxingStub()) { - SString sss(SString::Literal, "{unbox-stub}"); + SString sss(SString::Literal, W("{unbox-stub}")); ss += sss; } if (pMD->IsSharedByGenericMethodInstantiations()) { - SString sss(SString::Literal, "{method-shared}"); + SString sss(SString::Literal, W("{method-shared}")); ss += sss; } else if (pMD->IsSharedByGenericInstantiations()) { - SString sss(SString::Literal, "{shared}"); + SString sss(SString::Literal, W("{shared}")); ss += sss; } if (pMD->RequiresInstMethodTableArg()) { - SString sss(SString::Literal, "{requires-mt-arg}"); + SString sss(SString::Literal, W("{requires-mt-arg}")); ss += sss; } if (pMD->RequiresInstMethodDescArg()) { - SString sss(SString::Literal, "{requires-mdesc-arg}"); + SString sss(SString::Literal, W("{requires-mdesc-arg}")); ss += sss; } } @@ -957,8 +965,9 @@ void TypeString::AppendField(SString& s, FieldDesc *pFD, Instantiation typeInsta TypeHandle th(pFD->GetApproxEnclosingMethodTable()); AppendType(s, th, typeInstantiation, format); - s.AppendUTF8(NAMESPACE_SEPARATOR_STR); - s.AppendUTF8(pFD->GetName()); + s.Append(NAMESPACE_SEPARATOR_WSTR); + MAKE_WIDEPTR_FROMUTF8(pName, pFD->GetName()); + s.Append(pName); } } @@ -1125,13 +1134,14 @@ void TypeString::AppendTypeKey(TypeNameBuilder& tnb, TypeKey *pTypeKey, DWORD fo StackSString pAssemblyName; #ifdef DACCESS_COMPILE - pAssemblyName.SetUTF8(pAssembly->GetSimpleName()); + StackEString pAssemblyNameUTF8(pAssembly->GetSimpleName()); + pAssemblyNameUTF8.ConvertToUnicode(pAssemblyName); #else pAssembly->GetDisplayName(pAssemblyName, ASM_DISPLAYF_PUBLIC_KEY_TOKEN | ASM_DISPLAYF_CONTENT_TYPE | (format & FormatNoVersion ? 0 : ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE)); #endif - tnb.AddAssemblySpec(pAssemblyName.GetUnicode()); + tnb.AddAssemblySpec(pAssemblyName); } RETURN; @@ -1159,7 +1169,7 @@ void TypeString::AppendTypeKey(SString& ss, TypeKey *pTypeKey, DWORD format) /*static*/ void TypeString::EscapeSimpleTypeName(SString* ssTypeName, SString* ssEscapedTypeName) { - SString::Iterator itr = ssTypeName->Begin(); + auto itr = ssTypeName->Begin(); WCHAR c; while ((c = *itr++) != W('\0')) { diff --git a/src/coreclr/vm/typestring.h b/src/coreclr/vm/typestring.h index df54ed76b5bec5..2de79397115882 100644 --- a/src/coreclr/vm/typestring.h +++ b/src/coreclr/vm/typestring.h @@ -103,8 +103,6 @@ class TypeNameBuilder 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); } - void Append(LPCUTF8 pStr) { WRAPPER_NO_CONTRACT; m_pStr->AppendUTF8(pStr); } - void Append(UTF8 c) { WRAPPER_NO_CONTRACT; m_pStr->AppendUTF8(c); } SString* GetString() { WRAPPER_NO_CONTRACT; return m_pStr; } private: @@ -120,7 +118,7 @@ class TypeNameBuilder private: ParseState m_parseState; SString* m_pStr; - InlineSString<256> m_str; + InlineEString<256, EncodingUnicode> m_str; DWORD m_instNesting; BOOL m_bFirstInstArg; BOOL m_bNestedName; diff --git a/src/coreclr/vm/util.cpp b/src/coreclr/vm/util.cpp index 53ce3a32edbddc..5c51657085d66b 100644 --- a/src/coreclr/vm/util.cpp +++ b/src/coreclr/vm/util.cpp @@ -1902,7 +1902,7 @@ int GetRandomInt(int maxVal) return g_random.Next(maxVal); } -// These wrap the SString:L:CompareCaseInsenstive function in a way that makes it +// These wrap the EString:L:CompareCaseInsenstive function in a way that makes it // easy to fix code that uses _stricmp. _stricmp should be avoided as it uses the current // C-runtime locale rather than the invariance culture. // @@ -1919,8 +1919,8 @@ int __cdecl stricmpUTF8(const char* szStr1, const char* szStr2) } CONTRACTL_END - SString sStr1 (SString::Utf8, szStr1); - SString sStr2 (SString::Utf8, szStr2); + EString sStr1 (szStr1); + EString sStr2 (szStr2); return sStr1.CompareCaseInsensitive(sStr2); } diff --git a/src/coreclr/vm/util.hpp b/src/coreclr/vm/util.hpp index f72212595e87db..a19f5263cb01d9 100644 --- a/src/coreclr/vm/util.hpp +++ b/src/coreclr/vm/util.hpp @@ -777,7 +777,7 @@ class DACNotify void DACNotifyCompilationFinished(MethodDesc *pMethodDesc, PCODE pCode); -// These wrap the SString:L:CompareCaseInsenstive function in a way that makes it +// These wrap the EString:L:CompareCaseInsenstive function in a way that makes it // easy to fix code that uses _stricmp. _stricmp should be avoided as it uses the current // C-runtime locale rather than the invariance culture. // diff --git a/src/coreclr/vm/virtualcallstub.cpp b/src/coreclr/vm/virtualcallstub.cpp index db3bfaf9881ee5..5b89e15851b3d2 100644 --- a/src/coreclr/vm/virtualcallstub.cpp +++ b/src/coreclr/vm/virtualcallstub.cpp @@ -136,9 +136,10 @@ void VirtualCallStubManager::StartupLogging() EX_TRY { FAULT_NOT_FATAL(); // We handle filecreation problems locally - SString str; + EString str; str.Printf("StubLog_%d.log", GetCurrentProcessId()); - g_hStubLogFile = WszCreateFile (str.GetUnicode(), + SString strW(str.MoveToUnicode()); + g_hStubLogFile = WszCreateFile (strW, GENERIC_WRITE, 0, 0, @@ -2192,7 +2193,7 @@ VirtualCallStubManager::Resolver( DefineFullyQualifiedNameForClassW(); pTokenMD->GetFullMethodInfo(methodName); - COMPlusThrowHR(COR_E_MISSINGMETHOD, COR_E_MISSINGMETHOD, GetFullyQualifiedNameForClassNestedAwareW(pMT), methodName.GetUnicode()); + COMPlusThrowHR(COR_E_MISSINGMETHOD, COR_E_MISSINGMETHOD, GetFullyQualifiedNameForClassNestedAwareW(pMT), methodName); } else #endif // FEATURE_COMINTEROP diff --git a/src/coreclr/vm/weakreferencenative.cpp b/src/coreclr/vm/weakreferencenative.cpp index c61467b8cf111e..38b6fedbb63edf 100644 --- a/src/coreclr/vm/weakreferencenative.cpp +++ b/src/coreclr/vm/weakreferencenative.cpp @@ -321,7 +321,7 @@ NOINLINE Object* LoadComWeakReferenceTarget(WEAKREFERENCEREF weakReference, Type SString resolvedTypeName; TypeString::AppendType(resolvedTypeName, rcwType, TypeString::FormatNamespace | TypeString::FormatFullInst | TypeString::FormatAssembly); - COMPlusThrow(kInvalidCastException, IDS_EE_NATIVE_COM_WEAKREF_BAD_TYPE, weakReferenceTypeName.GetUnicode(), resolvedTypeName.GetUnicode()); + COMPlusThrow(kInvalidCastException, IDS_EE_NATIVE_COM_WEAKREF_BAD_TYPE, weakReferenceTypeName, resolvedTypeName); } WeakHandleSpinLockHolder handle(AcquireWeakHandleSpinLock(gc.weakReference), &gc.weakReference);