static bool_t DynXdrSetPos(XDR *xdrs, // IN u_int pos) // IN { DynXdrData *priv = (DynXdrData *) xdrs->x_private; if (pos <= DynBuf_GetAllocatedSize(&priv->data)) { DynBuf_SetSize(&priv->data, (size_t) pos); return TRUE; } return FALSE; }
Bool DynArray_SetCount(DynArray *a, // IN/OUT unsigned int c) // IN { size_t needed, allocated; ASSERT(a); needed = c * a->width; allocated = DynBuf_GetAllocatedSize(&a->buf); if (allocated < needed) { if (!DynBuf_Enlarge(&a->buf, needed)) { return FALSE; } } DynBuf_SetSize(&a->buf, needed); return TRUE; }
Bool StrUtil_VDynBufPrintf(DynBuf *b, // IN/OUT const char *fmt, // IN va_list args) // IN { /* * Arbitrary lower-limit on buffer size allocation, to avoid doing * many tiny enlarge operations. */ const size_t minAllocSize = 128; while (1) { int i; size_t size = DynBuf_GetSize(b); size_t allocSize = DynBuf_GetAllocatedSize(b); /* Make sure the buffer isn't still unallocated */ if (allocSize < minAllocSize) { Bool success = DynBuf_Enlarge(b, minAllocSize); if (!success) { return FALSE; } continue; } /* * Is there any allocated-but-not-occupied space? If so, try the printf. * If there was no space to begin with, or Str_Vsnprintf() ran out of * space, this will fail. */ if (allocSize - size > 0) { va_list tmpArgs; va_copy(tmpArgs, args); i = Str_Vsnprintf((char *) DynBuf_Get(b) + size, allocSize - size, fmt, tmpArgs); va_end(tmpArgs); } else { i = -1; } if (i >= 0) { /* * Success. Enlarge the buffer. * * The ASSERT here is to verify that printf() isn't lying * about the length of the string it wrote. This actually * happens, believe it or not. See bug 253674. */ ASSERT(i + size == allocSize || ((char *)DynBuf_Get(b))[i + size] == '\0'); DynBuf_SetSize(b, size + i); break; } else { /* * Failure. We must grow the buffer first. Note that this is * just a minimum size- dynbuf will probably decide to double * the actual reallocated buffer size. */ Bool success = DynBuf_Enlarge(b, size + minAllocSize); if (!success) { return FALSE; } } } return TRUE; }
Bool CodeSet_GenericToGenericDb(const char *codeIn, // IN const char *bufIn, // IN size_t sizeIn, // IN const char *codeOut, // IN unsigned int flags, // IN DynBuf *db) // IN/OUT { Bool result = FALSE; UErrorCode uerr; const char *bufInCur; const char *bufInEnd; UChar bufPiv[1024]; UChar *bufPivSource; UChar *bufPivTarget; UChar *bufPivEnd; char *bufOut; char *bufOutCur; char *bufOutEnd; size_t bufOutSize; size_t bufOutOffset; UConverter *cvin = NULL; UConverter *cvout = NULL; UConverterToUCallback toUCb; UConverterFromUCallback fromUCb; ASSERT(codeIn); ASSERT(sizeIn == 0 || bufIn); ASSERT(codeOut); ASSERT(db); ASSERT((CSGTG_NORMAL == flags) || (CSGTG_TRANSLIT == flags) || (CSGTG_IGNORE == flags)); if (dontUseIcu) { // fall back return CodeSetOld_GenericToGenericDb(codeIn, bufIn, sizeIn, codeOut, flags, db); } /* * Trivial case. */ if ((0 == sizeIn) || (NULL == bufIn)) { result = TRUE; goto exit; } /* * Open converters. */ uerr = U_ZERO_ERROR; cvin = ucnv_open(codeIn, &uerr); if (!cvin) { goto exit; } uerr = U_ZERO_ERROR; cvout = ucnv_open(codeOut, &uerr); if (!cvout) { goto exit; } /* * Set callbacks according to flags. */ switch (flags) { case CSGTG_NORMAL: toUCb = UCNV_TO_U_CALLBACK_STOP; fromUCb = UCNV_FROM_U_CALLBACK_STOP; break; case CSGTG_TRANSLIT: toUCb = UCNV_TO_U_CALLBACK_SUBSTITUTE; fromUCb = UCNV_FROM_U_CALLBACK_SUBSTITUTE; break; case CSGTG_IGNORE: toUCb = UCNV_TO_U_CALLBACK_SKIP; fromUCb = UCNV_FROM_U_CALLBACK_SKIP; break; default: NOT_IMPLEMENTED(); break; } uerr = U_ZERO_ERROR; ucnv_setToUCallBack(cvin, toUCb, NULL, NULL, NULL, &uerr); if (U_ZERO_ERROR != uerr) { goto exit; } uerr = U_ZERO_ERROR; ucnv_setFromUCallBack(cvout, fromUCb, NULL, NULL, NULL, &uerr); if (U_ZERO_ERROR != uerr) { goto exit; } /* * Convert using ucnv_convertEx(). * As a starting guess, make the output buffer the same size as * the input string (with a fudge constant added in to avoid degen * cases). */ bufInCur = bufIn; bufInEnd = bufIn + sizeIn; bufOutSize = sizeIn + 4; bufOutOffset = 0; bufPivSource = bufPiv; bufPivTarget = bufPiv; bufPivEnd = bufPiv + ARRAYSIZE(bufPiv); for (;;) { if (!DynBuf_Enlarge(db, bufOutSize)) { goto exit; } bufOut = DynBuf_Get(db); bufOutCur = bufOut + bufOutOffset; bufOutSize = DynBuf_GetAllocatedSize(db); bufOutEnd = bufOut + bufOutSize; uerr = U_ZERO_ERROR; ucnv_convertEx(cvout, cvin, &bufOutCur, bufOutEnd, &bufInCur, bufInEnd, bufPiv, &bufPivSource, &bufPivTarget, bufPivEnd, FALSE, TRUE, &uerr); if (!U_FAILURE(uerr)) { /* * "This was a triumph. * I'm making a note here: * HUGE SUCCESS. * It's hard to overstate * my satisfaction." */ break; } if (U_BUFFER_OVERFLOW_ERROR != uerr) { // failure goto exit; } /* * Our guess at 'bufOutSize' was obviously wrong, just double it. * We'll be reallocating bufOut, so will need to recompute bufOutCur * based on bufOutOffset. */ bufOutSize *= 2; bufOutOffset = bufOutCur - bufOut; } /* * Set final size and return. */ DynBuf_SetSize(db, bufOutCur - bufOut); result = TRUE; exit: if (cvin) { ucnv_close(cvin); } if (cvout) { ucnv_close(cvout); } return result; }
Bool CodeSet_Init(const char *icuDataDir) // IN: ICU data file location in Current code page. // Default is used if NULL. { DynBuf dbpath; #ifdef _WIN32 DWORD attribs; utf16_t *modPath = NULL; utf16_t *lastSlash; utf16_t *wpath; HANDLE hFile = INVALID_HANDLE_VALUE; HANDLE hMapping = NULL; void *memMappedData = NULL; #else struct stat finfo; #endif char *path = NULL; Bool ret = FALSE; DynBuf_Init(&dbpath); #ifdef USE_ICU /* * We're using system ICU, which finds its own data. So nothing to * do here. */ dontUseIcu = FALSE; ret = TRUE; goto exit; #endif /* * ********************* WARNING * Must avoid recursive calls into the codeset library here, hence * the idiotic hoop-jumping. DO NOT change any of these calls to * wrapper equivalents or call any other functions that may perform * string conversion. * ********************* WARNING */ #ifdef _WIN32 // { #if vmx86_devel /* * Devel builds use toolchain directory first. */ { WCHAR icuFilePath[MAX_PATH] = { 0 }; DWORD n = ExpandEnvironmentStringsW(ICU_DATA_FILE_PATH, icuFilePath, ARRAYSIZE(icuFilePath)); if (n > 0 && n < ARRAYSIZE(icuFilePath)) { attribs = GetFileAttributesW(icuFilePath); if ((INVALID_FILE_ATTRIBUTES != attribs) || (attribs & FILE_ATTRIBUTE_DIRECTORY) == 0) { if (!CodeSetOld_Utf16leToCurrent((const char *) icuFilePath, n * sizeof *icuFilePath, &path, NULL)) { goto exit; } goto found; } } } #endif if (icuDataDir) { /* * Data file must be in the specified directory. */ size_t length = strlen(icuDataDir); if (!DynBuf_Append(&dbpath, icuDataDir, length)) { goto exit; } if (length && icuDataDir[length - 1] != DIRSEPC) { if (!DynBuf_Append(&dbpath, DIRSEPS, strlen(DIRSEPS))) { goto exit; } } if (!DynBuf_Append(&dbpath, ICU_DATA_FILE, strlen(ICU_DATA_FILE)) || !DynBuf_Append(&dbpath, "\0", 1)) { goto exit; } /* * Check for file existence. */ attribs = GetFileAttributesA(DynBuf_Get(&dbpath)); if ((INVALID_FILE_ATTRIBUTES == attribs) || (attribs & FILE_ATTRIBUTE_DIRECTORY)) { goto exit; } path = (char *) DynBuf_Detach(&dbpath); } else { /* * Data file must be in the directory of the current module * (i.e. the module that contains CodeSet_Init()). */ HMODULE hModule = W32Util_GetModuleByAddress((void *) CodeSet_Init); if (!hModule) { goto exit; } modPath = CodeSetGetModulePath(hModule); if (!modPath) { goto exit; } lastSlash = wcsrchr(modPath, DIRSEPC_W); if (!lastSlash) { goto exit; } *lastSlash = L'\0'; if (!DynBuf_Append(&dbpath, modPath, wcslen(modPath) * sizeof(utf16_t)) || !DynBuf_Append(&dbpath, DIRSEPS_W, wcslen(DIRSEPS_W) * sizeof(utf16_t)) || !DynBuf_Append(&dbpath, ICU_DATA_FILE_W, wcslen(ICU_DATA_FILE_W) * sizeof(utf16_t)) || !DynBuf_Append(&dbpath, L"\0", 2)) { goto exit; } /* * Since u_setDataDirectory can't handle UTF-16, we would have to * now convert this path to local encoding. But that fails when * the module is in a path containing characters not in the * local encoding (see 282524). So we'll memory-map the file * instead and call udata_setCommonData() below. */ wpath = (utf16_t *) DynBuf_Get(&dbpath); hFile = CreateFileW(wpath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == hFile) { goto exit; } hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (NULL == hMapping) { goto exit; } memMappedData = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); if (NULL == memMappedData) { goto exit; } } #else // } _WIN32 { #if vmx86_devel { char *modPath; char *lastSlash; /* * Devel builds use toolchain directory first. */ if (stat(ICU_DATA_FILE_PATH, &finfo) >= 0 && !S_ISDIR(finfo.st_mode)) { if ((path = strdup(ICU_DATA_FILE_PATH)) == NULL) { goto exit; } goto found; } /* * Then we try module directory, if we can get it. */ modPath = CodeSetGetModulePath(HGMP_PRIVILEGE); if (modPath) { lastSlash = strrchr(modPath, DIRSEPC); if (lastSlash) { *lastSlash = '\0'; if (DynBuf_Append(&dbpath, modPath, strlen(modPath)) && DynBuf_Append(&dbpath, DIRSEPS, strlen(DIRSEPS)) && DynBuf_Append(&dbpath, ICU_DATA_FILE, strlen(ICU_DATA_FILE)) && DynBuf_Append(&dbpath, "\0", 1)) { if ((stat((const char *) DynBuf_Get(&dbpath), &finfo) >= 0) && !S_ISDIR(finfo.st_mode)) { free(modPath); path = DynBuf_Detach(&dbpath); goto found; } else { DynBuf_SetSize(&dbpath, 0); } } } free(modPath); } } #endif // vmx86_devel /* * Data file is either in POSIX_ICU_DIR or user specified dir. */ if (!icuDataDir) { icuDataDir = POSIX_ICU_DIR; } if (!DynBuf_Append(&dbpath, icuDataDir, strlen(icuDataDir)) || !DynBuf_Append(&dbpath, DIRSEPS, strlen(DIRSEPS)) || !DynBuf_Append(&dbpath, ICU_DATA_FILE, strlen(ICU_DATA_FILE)) || !DynBuf_Append(&dbpath, "\0", 1)) { goto exit; } /* * Check for file existence. (DO NOT CHANGE TO 'stat' WRAPPER). */ path = (char *) DynBuf_Detach(&dbpath); if (stat(path, &finfo) < 0 || S_ISDIR(finfo.st_mode)) { goto exit; } #endif // } _WIN32 #if vmx86_devel found: #endif #ifdef _WIN32 if (memMappedData) { /* * Tell ICU to use this mapped data. */ UErrorCode uerr = U_ZERO_ERROR; ASSERT(memMappedData); udata_setCommonData(memMappedData, &uerr); if (uerr != U_ZERO_ERROR) { UnmapViewOfFile(memMappedData); goto exit; } } else { #endif /* * Tell ICU to use this directory. */ u_setDataDirectory(path); #ifdef _WIN32 } #endif dontUseIcu = FALSE; ret = TRUE; exit: if (!ret) { /* * There was an error initing ICU, but if we can fall back on * non-ICU (old CodeSet) then things are OK. */ if (CODESET_CAN_FALLBACK_ON_NON_ICU) { ret = TRUE; dontUseIcu = TRUE; #ifdef _WIN32 OutputDebugStringW(L"CodeSet_Init: no ICU\n"); #endif } } #ifdef _WIN32 free(modPath); if (hMapping) { CloseHandle(hMapping); } if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } #endif free(path); DynBuf_Destroy(&dbpath); return ret; }
StdIO_Status StdIO_ReadNextLine(FILE *stream, // IN: char **buf, // OUT: size_t maxBufLength, // IN: size_t *count) // OUT: { DynBuf b; ASSERT(stream); ASSERT(buf); DynBuf_Init(&b); for (;;) { char *data; size_t size; size_t max; size_t nr; /* * The dynamic buffer must be at least 2 bytes large, so that at least * 1 stream byte and fgets()'s NUL byte can fit --hpreg */ if (DynBuf_Enlarge(&b, 2) == FALSE) { errno = ENOMEM; goto error; } /* Read the next chunk of line directly in the dynamic buffer --hpreg */ data = DynBuf_Get(&b); size = DynBuf_GetSize(&b); if (maxBufLength != 0 && size > maxBufLength) { errno = E2BIG; goto error; } max = DynBuf_GetAllocatedSize(&b); nr = max - size; if (SuperFgets(stream, &nr, data + size) == NULL) { goto error; } size += nr; DynBuf_SetSize(&b, size); if (size < max) { /* SuperFgets() found end-of-line */ if (size == 0 && feof(stream)) { /* Reached end-of-file before reading anything */ DynBuf_Destroy(&b); return StdIO_EOF; } break; } /* * No line terminator found yet, we need a larger buffer to do the next * SuperFgets() --hpreg */ } /* There is a line in the buffer --hpreg */ /* NUL terminator --hpreg */ if (DynBuf_Append(&b, "", 1) == FALSE) { errno = ENOMEM; goto error; } *buf = DynBuf_Get(&b); if (count) { *count = DynBuf_GetSize(&b) - 1; } return StdIO_Success; error: DynBuf_Destroy(&b); return StdIO_Error; }