Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: src/installer-ca/dutil/strutil.cpp

Issue 11521026: initial custom action library, "hello, world" quality (Closed)
Patch Set: Created Sept. 3, 2013, 12:48 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/installer-ca/dutil/strutil.cpp
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/installer-ca/dutil/strutil.cpp
@@ -0,0 +1,755 @@
+//-------------------------------------------------------------------------------------------------
+// <copyright file="strutil.cpp" company="Outercurve Foundation">
+// Copyright (c) 2004, Outercurve Foundation.
+// This software is released under Microsoft Reciprocal License (MS-RL).
+// The license and further copyright text can be found in the file
+// LICENSE.TXT at the root directory of the distribution.
+// </copyright>
+//
+// <summary>
+// String helper functions.
+// </summary>
+//-------------------------------------------------------------------------------------------------
+
+#include "../precomp.h"
+
+#define ARRAY_GROWTH_SIZE 5
+
+// Forward declarations.
+static HRESULT StrAllocStringMapInvariant(
+ __deref_out_z LPWSTR* pscz,
+ __in_z LPCWSTR wzSource,
+ __in int cchSource,
+ __in DWORD dwMapFlags
+ );
+
+/********************************************************************
+StrAlloc - allocates or reuses dynamic string memory
+
+NOTE: caller is responsible for freeing ppwz even if function fails
+********************************************************************/
+extern "C" HRESULT DAPI DAPI StrAlloc(
+ __deref_out_ecount_part(cch, 0) LPWSTR* ppwz,
+ __in DWORD_PTR cch
+ )
+{
+ Assert(ppwz && cch);
+
+ HRESULT hr = S_OK;
+ LPWSTR pwz = NULL;
+
+ if (cch >= MAXDWORD / sizeof(WCHAR))
+ {
+ hr = E_OUTOFMEMORY;
+ ExitOnFailure1(hr, "Not enough memory to allocate string of size: %u", cch);
+ }
+
+ if (*ppwz)
+ {
+ pwz = static_cast<LPWSTR>(MemReAlloc(*ppwz, sizeof(WCHAR) * cch, FALSE));
+ }
+ else
+ {
+ pwz = static_cast<LPWSTR>(MemAlloc(sizeof(WCHAR) * cch, TRUE));
+ }
+
+ ExitOnNull1(pwz, hr, E_OUTOFMEMORY, "failed to allocate string, len: %u", cch);
+
+ *ppwz = pwz;
+LExit:
+ return hr;
+}
+
+
+/********************************************************************
+StrTrimCapacity - Frees any unnecessary memory associated with a string.
+ Purely used for optimization, generally only when a string
+ has been changing size, and will no longer grow.
+
+NOTE: caller is responsible for freeing ppwz even if function fails
+********************************************************************/
+HRESULT DAPI StrTrimCapacity(
+ __deref_out_z LPWSTR* ppwz
+ )
+{
+ Assert(ppwz);
+
+ HRESULT hr = S_OK;
+ DWORD_PTR cchLen = 0;
+
+ hr = ::StringCchLengthW(*ppwz, STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>(&cchLen));
+ ExitOnFailure(hr, "Failed to calculate length of string");
+
+ ++cchLen; // Add 1 for null-terminator
+
+ hr = StrAlloc(ppwz, cchLen);
+ ExitOnFailure(hr, "Failed to reallocate string");
+
+LExit:
+ return hr;
+}
+
+
+/********************************************************************
+StrTrimWhitespace - allocates or reuses dynamic string memory and copies
+ in an existing string, excluding whitespace
+
+NOTE: caller is responsible for freeing ppwz even if function fails
+********************************************************************/
+HRESULT DAPI StrTrimWhitespace(
+ __deref_out_z LPWSTR* ppwz,
+ __in_z LPCWSTR wzSource
+ )
+{
+ HRESULT hr = S_OK;
+ int i = 0;
+ LPWSTR sczResult = NULL;
+
+ // Ignore beginning whitespace
+ while (L' ' == *wzSource || L'\t' == *wzSource)
+ {
+ wzSource++;
+ }
+
+ i = lstrlenW(wzSource);
+ // Overwrite ending whitespace with null characters
+ if (0 < i)
+ {
+ // start from the last non-null-terminator character in the array
+ for (i = i - 1; i > 0; --i)
+ {
+ if (L' ' != wzSource[i] && L'\t' != wzSource[i])
+ {
+ break;
+ }
+ }
+
+ ++i;
+ }
+
+ hr = StrAllocString(&sczResult, wzSource, i);
+ ExitOnFailure(hr, "Failed to copy result string");
+
+ // Output result
+ *ppwz = sczResult;
+ sczResult = NULL;
+
+LExit:
+ ReleaseStr(sczResult);
+
+ return hr;
+}
+
+
+
+
+
+/********************************************************************
+StrAllocString - allocates or reuses dynamic string memory and copies in an existing string
+
+NOTE: caller is responsible for freeing ppwz even if function fails
+NOTE: cchSource does not have to equal the length of wzSource
+NOTE: if cchSource == 0, length of wzSource is used instead
+********************************************************************/
+extern "C" HRESULT DAPI StrAllocString(
+ __deref_out_ecount_z(cchSource+1) LPWSTR* ppwz,
+ __in_z LPCWSTR wzSource,
+ __in DWORD_PTR cchSource
+ )
+{
+ Assert(ppwz && wzSource); // && *wzSource);
+
+ HRESULT hr = S_OK;
+ DWORD_PTR cch = 0;
+
+ if (*ppwz)
+ {
+ cch = MemSize(*ppwz); // get the count in bytes so we can check if it failed (returns -1)
+ if (-1 == cch)
+ {
+ hr = E_INVALIDARG;
+ ExitOnFailure(hr, "failed to get size of destination string");
+ }
+ cch /= sizeof(WCHAR); //convert the count in bytes to count in characters
+ }
+
+ if (0 == cchSource)
+ {
+ cchSource = lstrlenW(wzSource);
+ }
+
+ DWORD_PTR cchNeeded;
+ hr = ::ULongPtrAdd(cchSource, 1, &cchNeeded); // add one for the null terminator
+ ExitOnFailure(hr, "source string is too long");
+
+ if (cch < cchNeeded)
+ {
+ cch = cchNeeded;
+ hr = StrAlloc(ppwz, cch);
+ ExitOnFailure(hr, "failed to allocate string from string.");
+ }
+
+ // copy everything (the NULL terminator will be included)
+ hr = ::StringCchCopyNExW(*ppwz, cch, wzSource, cchSource, NULL, NULL, STRSAFE_FILL_BEHIND_NULL);
+
+LExit:
+ return hr;
+}
+
+
+
+
+
+/********************************************************************
+StrAllocConcat - allocates or reuses dynamic string memory and adds an existing string
+
+NOTE: caller is responsible for freeing ppwz even if function fails
+NOTE: cchSource does not have to equal the length of wzSource
+NOTE: if cchSource == 0, length of wzSource is used instead
+********************************************************************/
+extern "C" HRESULT DAPI StrAllocConcat(
+ __deref_out_z LPWSTR* ppwz,
+ __in_z LPCWSTR wzSource,
+ __in DWORD_PTR cchSource
+ )
+{
+ Assert(ppwz && wzSource); // && *wzSource);
+
+ HRESULT hr = S_OK;
+ DWORD_PTR cch = 0;
+ DWORD_PTR cchLen = 0;
+
+ if (*ppwz)
+ {
+ cch = MemSize(*ppwz); // get the count in bytes so we can check if it failed (returns -1)
+ if (-1 == cch)
+ {
+ hr = E_INVALIDARG;
+ ExitOnFailure(hr, "failed to get size of destination string");
+ }
+ cch /= sizeof(WCHAR); //convert the count in bytes to count in characters
+
+ hr = ::StringCchLengthW(*ppwz, STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>(&cchLen));
+ ExitOnFailure(hr, "Failed to calculate length of string");
+ }
+
+ Assert(cchLen <= cch);
+
+ if (0 == cchSource)
+ {
+ hr = ::StringCchLengthW(wzSource, STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>(&cchSource));
+ ExitOnFailure(hr, "Failed to calculate length of string");
+ }
+
+ if (cch - cchLen < cchSource + 1)
+ {
+ cch = (cchSource + cchLen + 1) * 2;
+ hr = StrAlloc(ppwz, cch);
+ ExitOnFailure1(hr, "failed to allocate string from string: %ls", wzSource);
+ }
+
+ if (*ppwz)
+ {
+ hr = ::StringCchCatNExW(*ppwz, cch, wzSource, cchSource, NULL, NULL, STRSAFE_FILL_BEHIND_NULL);
+ }
+ else
+ {
+ hr = E_UNEXPECTED;
+ ExitOnFailure(hr, "for some reason our buffer is still null");
+ }
+
+LExit:
+ return hr;
+}
+
+
+
+
+
+/********************************************************************
+StrAllocFormatted - allocates or reuses dynamic string memory and formats it
+
+NOTE: caller is responsible for freeing ppwz even if function fails
+********************************************************************/
+extern "C" HRESULT DAPI StrAllocFormatted(
+ __deref_out_z LPWSTR* ppwz,
+ __in __format_string LPCWSTR wzFormat,
+ ...
+ )
+{
+ Assert(ppwz && wzFormat && *wzFormat);
+
+ HRESULT hr = S_OK;
+ va_list args;
+
+ va_start(args, wzFormat);
+ hr = StrAllocFormattedArgs(ppwz, wzFormat, args);
+ va_end(args);
+
+ return hr;
+}
+
+
+
+
+/********************************************************************
+StrAllocFormattedArgs - allocates or reuses dynamic string memory
+and formats it with the passed in args
+
+NOTE: caller is responsible for freeing ppwz even if function fails
+********************************************************************/
+extern "C" HRESULT DAPI StrAllocFormattedArgs(
+ __deref_out_z LPWSTR* ppwz,
+ __in __format_string LPCWSTR wzFormat,
+ __in va_list args
+ )
+{
+ Assert(ppwz && wzFormat && *wzFormat);
+
+ HRESULT hr = S_OK;
+ DWORD_PTR cch = 0;
+ LPWSTR pwzOriginal = NULL;
+ DWORD_PTR cchOriginal = 0;
+
+ if (*ppwz)
+ {
+ cch = MemSize(*ppwz); // get the count in bytes so we can check if it failed (returns -1)
+ if (-1 == cch)
+ {
+ hr = E_INVALIDARG;
+ ExitOnFailure(hr, "failed to get size of destination string");
+ }
+ cch /= sizeof(WCHAR); //convert the count in bytes to count in characters
+
+ cchOriginal = lstrlenW(*ppwz);
+ }
+
+ if (0 == cch) // if there is no space in the string buffer
+ {
+ cch = 256;
+ hr = StrAlloc(ppwz, cch);
+ ExitOnFailure1(hr, "failed to allocate string to format: %ls", wzFormat);
+ }
+
+ // format the message (grow until it fits or there is a failure)
+ do
+ {
+ hr = ::StringCchVPrintfW(*ppwz, cch, wzFormat, args);
+ if (STRSAFE_E_INSUFFICIENT_BUFFER == hr)
+ {
+ if (!pwzOriginal)
+ {
+ // this allows you to pass the original string as a formatting argument and not crash
+ // save the original string and free it after the printf is complete
+ pwzOriginal = *ppwz;
+ *ppwz = NULL;
+ // StringCchVPrintfW starts writing to the string...
+ // NOTE: this hack only works with sprintf(&pwz, "%s ...", pwz, ...);
+ pwzOriginal[cchOriginal] = 0;
+ }
+ cch *= 2;
+ hr = StrAlloc(ppwz, cch);
+ ExitOnFailure1(hr, "failed to allocate string to format: %ls", wzFormat);
+ hr = S_FALSE;
+ }
+ } while (S_FALSE == hr);
+ ExitOnFailure(hr, "failed to format string");
+
+LExit:
+ ReleaseStr(pwzOriginal);
+
+ return hr;
+}
+
+
+
+
+
+
+/********************************************************************
+StrMaxLength - returns maximum number of characters that can be stored in dynamic string p
+
+NOTE: assumes Unicode string
+********************************************************************/
+extern "C" HRESULT DAPI StrMaxLength(
+ __in LPCVOID p,
+ __out DWORD_PTR* pcch
+ )
+{
+ Assert(pcch);
+
+ HRESULT hr = S_OK;
+
+ if (p)
+ {
+ *pcch = MemSize(p); // get size of entire buffer
+ if (-1 == *pcch)
+ {
+ ExitFunction1(hr = E_FAIL);
+ }
+
+ *pcch /= sizeof(WCHAR); // reduce to count of characters
+ }
+ else
+ {
+ *pcch = 0;
+ }
+ Assert(S_OK == hr);
+
+LExit:
+ return hr;
+}
+
+
+/********************************************************************
+StrSize - returns count of bytes in dynamic string p
+
+********************************************************************/
+extern "C" HRESULT DAPI StrSize(
+ __in LPCVOID p,
+ __out DWORD_PTR* pcb
+ )
+{
+ Assert(p && pcb);
+
+ HRESULT hr = S_OK;
+
+ *pcb = MemSize(p);
+ if (-1 == *pcb)
+ {
+ hr = E_FAIL;
+ }
+
+ return hr;
+}
+
+/********************************************************************
+StrFree - releases dynamic string memory allocated by any StrAlloc*() functions
+
+********************************************************************/
+extern "C" HRESULT DAPI StrFree(
+ __in LPVOID p
+ )
+{
+ Assert(p);
+
+ HRESULT hr = MemFree(p);
+ ExitOnFailure(hr, "failed to free string");
+
+LExit:
+ return hr;
+}
+
+
+/****************************************************************************
+wcsistr - case insensitive find a substring
+
+****************************************************************************/
+extern "C" LPCWSTR wcsistr(
+ __in_z LPCWSTR wzString,
+ __in_z LPCWSTR wzCharSet
+ )
+{
+ LPCWSTR wzSource = wzString;
+ LPCWSTR wzSearch = NULL;
+ DWORD_PTR cchSourceIndex = 0;
+
+ // Walk through wzString (the source string) one character at a time
+ while (*wzSource)
+ {
+ cchSourceIndex = 0;
+ wzSearch = wzCharSet;
+
+ // Look ahead in the source string until we get a full match or we hit the end of the source
+ while (L'\0' != wzSource[cchSourceIndex] && L'\0' != *wzSearch && towlower(wzSource[cchSourceIndex]) == towlower(*wzSearch))
+ {
+ ++cchSourceIndex;
+ ++wzSearch;
+ }
+
+ // If we found it, return the point that we found it at
+ if (L'\0' == *wzSearch)
+ {
+ return wzSource;
+ }
+
+ // Walk ahead one character
+ ++wzSource;
+ }
+
+ return NULL;
+}
+
+/****************************************************************************
+StrStringToInt16 - converts a string to a signed 16-bit integer.
+
+****************************************************************************/
+extern "C" HRESULT DAPI StrStringToInt16(
+ __in_z LPCWSTR wzIn,
+ __in DWORD cchIn,
+ __out SHORT* psOut
+ )
+{
+ HRESULT hr = S_OK;
+ LONGLONG ll = 0;
+
+ hr = StrStringToInt64(wzIn, cchIn, &ll);
+ ExitOnFailure(hr, "Failed to parse int64.");
+
+ if (SHORT_MAX < ll || SHORT_MIN > ll)
+ {
+ ExitFunction1(hr = DISP_E_OVERFLOW);
+ }
+ *psOut = (SHORT)ll;
+
+LExit:
+ return hr;
+}
+
+/****************************************************************************
+StrStringToUInt16 - converts a string to an unsigned 16-bit integer.
+
+****************************************************************************/
+extern "C" HRESULT DAPI StrStringToUInt16(
+ __in_z LPCWSTR wzIn,
+ __in DWORD cchIn,
+ __out USHORT* pusOut
+ )
+{
+ HRESULT hr = S_OK;
+ ULONGLONG ull = 0;
+
+ hr = StrStringToUInt64(wzIn, cchIn, &ull);
+ ExitOnFailure(hr, "Failed to parse uint64.");
+
+ if (USHORT_MAX < ull)
+ {
+ ExitFunction1(hr = DISP_E_OVERFLOW);
+ }
+ *pusOut = (USHORT)ull;
+
+LExit:
+ return hr;
+}
+
+/****************************************************************************
+StrStringToInt32 - converts a string to a signed 32-bit integer.
+
+****************************************************************************/
+extern "C" HRESULT DAPI StrStringToInt32(
+ __in_z LPCWSTR wzIn,
+ __in DWORD cchIn,
+ __out INT* piOut
+ )
+{
+ HRESULT hr = S_OK;
+ LONGLONG ll = 0;
+
+ hr = StrStringToInt64(wzIn, cchIn, &ll);
+ ExitOnFailure(hr, "Failed to parse int64.");
+
+ if (INT_MAX < ll || INT_MIN > ll)
+ {
+ ExitFunction1(hr = DISP_E_OVERFLOW);
+ }
+ *piOut = (INT)ll;
+
+LExit:
+ return hr;
+}
+
+/****************************************************************************
+StrStringToUInt32 - converts a string to an unsigned 32-bit integer.
+
+****************************************************************************/
+extern "C" HRESULT DAPI StrStringToUInt32(
+ __in_z LPCWSTR wzIn,
+ __in DWORD cchIn,
+ __out UINT* puiOut
+ )
+{
+ HRESULT hr = S_OK;
+ ULONGLONG ull = 0;
+
+ hr = StrStringToUInt64(wzIn, cchIn, &ull);
+ ExitOnFailure(hr, "Failed to parse uint64.");
+
+ if (UINT_MAX < ull)
+ {
+ ExitFunction1(hr = DISP_E_OVERFLOW);
+ }
+ *puiOut = (UINT)ull;
+
+LExit:
+ return hr;
+}
+
+/****************************************************************************
+StrStringToInt64 - converts a string to a signed 64-bit integer.
+
+****************************************************************************/
+extern "C" HRESULT DAPI StrStringToInt64(
+ __in_z LPCWSTR wzIn,
+ __in DWORD cchIn,
+ __out LONGLONG* pllOut
+ )
+{
+ HRESULT hr = S_OK;
+ DWORD i = 0;
+ INT iSign = 1;
+ INT nDigit = 0;
+ LARGE_INTEGER liValue = { };
+
+ // get string length if not provided
+ if (0 >= cchIn)
+ {
+ cchIn = lstrlenW(wzIn);
+ if (0 >= cchIn)
+ {
+ ExitFunction1(hr = E_INVALIDARG);
+ }
+ }
+
+ // check sign
+ if (L'-' == wzIn[0])
+ {
+ if (1 >= cchIn)
+ {
+ ExitFunction1(hr = E_INVALIDARG);
+ }
+ i = 1;
+ iSign = -1;
+ }
+
+ // read digits
+ while (i < cchIn)
+ {
+ nDigit = wzIn[i] - L'0';
+ if (0 > nDigit || 9 < nDigit)
+ {
+ ExitFunction1(hr = E_INVALIDARG);
+ }
+ liValue.QuadPart = liValue.QuadPart * 10 + nDigit * iSign;
+
+ if ((liValue.HighPart ^ iSign) & INT_MIN)
+ {
+ ExitFunction1(hr = DISP_E_OVERFLOW);
+ }
+ ++i;
+ }
+
+ *pllOut = liValue.QuadPart;
+
+LExit:
+ return hr;
+}
+
+/****************************************************************************
+StrStringToUInt64 - converts a string to an unsigned 64-bit integer.
+
+****************************************************************************/
+extern "C" HRESULT DAPI StrStringToUInt64(
+ __in_z LPCWSTR wzIn,
+ __in DWORD cchIn,
+ __out ULONGLONG* pullOut
+ )
+{
+ HRESULT hr = S_OK;
+ DWORD i = 0;
+ DWORD nDigit = 0;
+ ULONGLONG ullValue = 0;
+ ULONGLONG ull = 0;
+
+ // get string length if not provided
+ if (0 >= cchIn)
+ {
+ cchIn = lstrlenW(wzIn);
+ if (0 >= cchIn)
+ {
+ ExitFunction1(hr = E_INVALIDARG);
+ }
+ }
+
+ // read digits
+ while (i < cchIn)
+ {
+ nDigit = wzIn[i] - L'0';
+ if (9 < nDigit)
+ {
+ ExitFunction1(hr = E_INVALIDARG);
+ }
+ ull = (ULONGLONG)(ullValue * 10 + nDigit);
+
+ if (ull < ullValue)
+ {
+ ExitFunction1(hr = DISP_E_OVERFLOW);
+ }
+ ullValue = ull;
+ ++i;
+ }
+
+ *pullOut = ullValue;
+
+LExit:
+ return hr;
+}
+
+/****************************************************************************
+StrStringToUpper - alters the given string in-place to be entirely uppercase
+
+****************************************************************************/
+void DAPI StrStringToUpper(
+ __inout_z LPWSTR wzIn
+ )
+{
+ ::CharUpperBuffW(wzIn, lstrlenW(wzIn));
+}
+
+/****************************************************************************
+StrStringToLower - alters the given string in-place to be entirely lowercase
+
+****************************************************************************/
+void DAPI StrStringToLower(
+ __inout_z LPWSTR wzIn
+ )
+{
+ ::CharLowerBuffW(wzIn, lstrlenW(wzIn));
+}
+
+
+
+
+/****************************************************************************
+StrAllocStringMapInvariant - helper function for the ToUpper and ToLower.
+
+Note: Assumes source and destination buffers will be the same.
+****************************************************************************/
+static HRESULT StrAllocStringMapInvariant(
+ __deref_out_z LPWSTR* pscz,
+ __in_z LPCWSTR wzSource,
+ __in int cchSource,
+ __in DWORD dwMapFlags
+ )
+{
+ HRESULT hr = S_OK;
+
+ hr = StrAllocString(pscz, wzSource, cchSource);
+ ExitOnFailure(hr, "Failed to allocate a copy of the source string.");
+
+ if (0 == cchSource)
+ {
+ // Need the actual string size for LCMapString. This includes the null-terminator
+ // but LCMapString doesn't care either way.
+ hr = ::StringCchLengthW(*pscz, INT_MAX, reinterpret_cast<size_t*>(&cchSource));
+ ExitOnFailure(hr, "Failed to get the length of the string.");
+ }
+
+ // Convert the copy of the string to upper or lower case in-place.
+ if (0 == ::LCMapStringW(LOCALE_INVARIANT, dwMapFlags, *pscz, cchSource, *pscz, cchSource))
+ {
+ ExitWithLastError(hr, "Failed to convert the string case.");
+ }
+
+LExit:
+ return hr;
+}

Powered by Google App Engine
This is Rietveld