char * Unicode_ToTitle(const char *str, // IN const char *locale) // IN { UCaseMap *caseMap; UErrorCode status = U_ZERO_ERROR; char *utf8Dest; const char *utf8Src = (const char *)str; int32_t utf8SrcLen = strlen(utf8Src); int32_t destCapacity = utf8SrcLen + 1; int32_t destLen; char *result = NULL; // Most title-case operations don't change the length of the string. utf8Dest = (char *)Util_SafeMalloc(destCapacity); caseMap = ucasemap_open(locale, 0, &status); if (U_FAILURE(status)) { goto out; } destLen = ucasemap_utf8ToTitle(caseMap, utf8Dest, destCapacity, utf8Src, utf8SrcLen, &status); if (status != U_BUFFER_OVERFLOW_ERROR) { goto out; } // If we need a bigger buffer, then reallocate and retry. destCapacity = destLen + 1; utf8Dest = (char *)Util_SafeRealloc(utf8Dest, destCapacity); status = U_ZERO_ERROR; destLen = ucasemap_utf8ToTitle(caseMap, utf8Dest, destCapacity, utf8Src, utf8SrcLen, &status); out: ucasemap_close(caseMap); if (U_SUCCESS(status) && status != U_STRING_NOT_TERMINATED_WARNING) { result = utf8Dest; } else { ASSERT(U_SUCCESS(status)); ASSERT(status != U_STRING_NOT_TERMINATED_WARNING); } return result; }
void StrUtil_SafeStrcat(char **prefix, // IN/OUT const char *str) // IN { char *tmp; size_t plen = *prefix != NULL ? strlen(*prefix) : 0; size_t slen = strlen(str); /* Check for overflow */ VERIFY((size_t)-1 - plen > slen + 1); tmp = Util_SafeRealloc(*prefix, plen + slen + 1 /* NUL */); memcpy(tmp + plen, str, slen + 1 /* NUL */); *prefix = tmp; }
void StrUtil_SafeStrcat(char **prefix, // IN/OUT: const char *str) // IN: { char *tmp; size_t plen = (*prefix == NULL) ? 0 : strlen(*prefix); size_t slen = strlen(str); /* * If we're manipulating strings that are anywhere near max(size_t)/2 in * length we're doing something very wrong. Avoid potential overflow by * checking for "insane" operations. Prevent the problem before it gets * started. */ VERIFY((plen < (SIZE_MAX/2)) && (slen < (SIZE_MAX/2))); tmp = Util_SafeRealloc(*prefix, plen + slen + 1 /* NUL */); memcpy(tmp + plen, str, slen + 1 /* NUL */); *prefix = tmp; }
char * Unicode_ToLower(const char *str, // IN const char *locale) // IN { UCaseMap *caseMap; UErrorCode status = U_ZERO_ERROR; char *utf8Dest; const char *utf8Src = (const char *)str; int32_t utf8SrcLen = strlen(utf8Src); int32_t destCapacity = utf8SrcLen + 1; int32_t destLen; char *result = NULL; /* * XXX TODO: This and the two following functions are substantially * identical. Refactor them! (Note that ucasemap_utf8ToTitle * takes a non-const UCaseMap, so we can't just use pointers to * functions unless we cast.) */ // Most lower-case operations don't change the length of the string. utf8Dest = (char *)Util_SafeMalloc(destCapacity); caseMap = ucasemap_open(locale, 0, &status); if (U_FAILURE(status)) { goto out; } destLen = ucasemap_utf8ToLower(caseMap, utf8Dest, destCapacity, utf8Src, utf8SrcLen, &status); if (status != U_BUFFER_OVERFLOW_ERROR) { goto out; } // If we need a bigger buffer, then reallocate and retry. destCapacity = destLen + 1; utf8Dest = (char *)Util_SafeRealloc(utf8Dest, destCapacity); status = U_ZERO_ERROR; destLen = ucasemap_utf8ToLower(caseMap, utf8Dest, destCapacity, utf8Src, utf8SrcLen, &status); out: ucasemap_close(caseMap); if (U_SUCCESS(status) && status != U_STRING_NOT_TERMINATED_WARNING) { result = utf8Dest; } else { ASSERT(U_SUCCESS(status)); ASSERT(status != U_STRING_NOT_TERMINATED_WARNING); } return result; }
LONG Win32U_AllocRegQueryValueEx(HKEY keyName, // IN: LPCSTR valueName, // IN: can be NULL LPDWORD reserved, // IN: reserved LPDWORD type, // OUT/OPT: can be NULL LPBYTE *data, // OUT: LPDWORD dataSize) // OUT: { LONG ret; utf16_t *valueNameW = Unicode_GetAllocUTF16(valueName); DWORD valueType; char *rawData = NULL; DWORD rawDataSize = 0; DWORD bufferSize = 0; ASSERT(data); ASSERT(dataSize); ASSERT(reserved == NULL); *data = NULL; *dataSize = 0; ret = RegQueryValueExW(keyName, valueNameW, reserved, NULL, NULL, &bufferSize); if (ret != ERROR_SUCCESS || bufferSize == 0) { bufferSize = 256; } /* * This loops with a growing buffer because: * * The registry value could be modified between calls to * RegQueryValueExW. * * RegQueryValueExW will never tell us how large a buffer we need * for HKEY_PERFORMANCE_DATA values. */ while (TRUE) { rawData = Util_SafeRealloc(rawData, bufferSize); rawDataSize = bufferSize; ret = RegQueryValueExW(keyName, valueNameW, reserved, &valueType, rawData, &rawDataSize); if (ERROR_MORE_DATA != ret) { break; } bufferSize *= 2; } if (ERROR_SUCCESS != ret) { goto exit; } ASSERT(rawDataSize <= bufferSize); /* Write back the data */ switch (valueType) { /* Do UTF-16->UTF-8 conversion for string types. */ case REG_SZ: case REG_MULTI_SZ: case REG_EXPAND_SZ: { size_t sizeOut; if (!CodeSet_Utf16leToUtf8(rawData, rawDataSize, data, &sizeOut)) { /* * Someone may not have set the right data size. Let's try * to convert up to NUL if one is found. */ DWORD lenInBytes = rawDataSize; const utf16_t *p1 = (utf16_t*)rawData; const utf16_t *p2 = (utf16_t*)&rawData[rawDataSize]; if (valueType == REG_MULTI_SZ) { /* look for four NUL bytes */ while (p1 < p2) { for (; *p1 != 0 && p1 < p2; p1++) { } p1++; if (p1 < p2 && *p1 == 0) { lenInBytes = (char *)p1 - rawData + 2; break; } } } else { for (; *p1 != 0 && p1 < p2; p1++) { } if (p1 < p2) { lenInBytes = (char *)p1 - rawData + 2; } } ASSERT(lenInBytes <= rawDataSize); ASSERT(lenInBytes % 2 == 0); if (lenInBytes >= rawDataSize || !CodeSet_Utf16leToUtf8(rawData, lenInBytes, data, &sizeOut)) { ret = ERROR_INVALID_DATA; goto exit; } } *dataSize = sizeOut; break; } default: /* Shrink the buffer down to what we actually used. */ *data = Util_SafeRealloc(rawData, rawDataSize); *dataSize = rawDataSize; rawData = NULL; break; } /* Write back the type information if asked for */ if (type) { *type = valueType; } exit: free(valueNameW); free(rawData); return ret; }