char * DnD_GetLastDirName(const char *str) // IN { size_t end = strlen(str); size_t start; size_t res = 0; if (end != 0 && DIRSEPC == str[end - 1]) { end--; } if (end == 0) { return 0; } start = end; while (start && DIRSEPC != str[start - 1]) { start--; } /* There should be at lease 1 DIRSEPC before end. */ if (start == 0) { return 0; } res = end - start; return Unicode_AllocWithLength(str + start, res, STRING_ENCODING_UTF8); }
Unicode File_StripSlashes(ConstUnicode path) // IN: { Unicode result, volume, dir, base; /* * SplitName handles all drive letter/UNC/whatever cases, all we * have to do is make sure the dir part is stripped of slashes if * there isn't a base part. */ File_SplitName(path, &volume, &dir, &base); if (!Unicode_IsEmpty(dir) && Unicode_IsEmpty(base)) { char *dir2 = Unicode_GetAllocBytes(dir, STRING_ENCODING_UTF8); size_t i = strlen(dir2); /* * Don't strip first slash on Windows, since we want at least * one slash to trail a drive letter/colon or UNC specifier. */ #if defined(_WIN32) while ((i > 1) && (('/' == dir2[i - 1]) || ('\\' == dir2[i - 1]))) { #else while ((i > 0) && ('/' == dir2[i - 1])) { #endif i--; } Unicode_Free(dir); dir = Unicode_AllocWithLength(dir2, i, STRING_ENCODING_UTF8); free(dir2); } result = Unicode_Join(volume, dir, base, NULL); Unicode_Free(volume); Unicode_Free(dir); Unicode_Free(base); return result; } /* *----------------------------------------------------------------------------- * * File_MapPathPrefix -- * * Given a path and a newPrefix -> oldPrefix mapping, transform * oldPath according to the mapping. * * Results: * The new path, or NULL if there is no mapping. * * Side effects: * The returned string is allocated, free it. * *----------------------------------------------------------------------------- */ char * File_MapPathPrefix(const char *oldPath, // IN: const char **oldPrefixes, // IN: const char **newPrefixes, // IN: size_t numPrefixes) // IN: { int i; size_t oldPathLen = strlen(oldPath); for (i = 0; i < numPrefixes; i++) { char *newPath; char *oldPrefix; char *newPrefix; size_t oldPrefixLen; oldPrefix = File_StripSlashes(oldPrefixes[i]); newPrefix = File_StripSlashes(newPrefixes[i]); oldPrefixLen = strlen(oldPrefix); /* * If the prefix matches on a DIRSEPS boundary, or the prefix is the * whole string, replace it. * * If we don't insist on matching a whole directory name, we could * mess things of if one directory is a substring of another. * * Perform a case-insensitive compare on Windows. (There are * case-insensitive filesystems on MacOS also, but the problem * is more acute with Windows because of frequent drive-letter * case mismatches. So in lieu of actually asking the * filesystem, let's just go with a simple ifdef for now.) */ if ((oldPathLen >= oldPrefixLen) && #ifdef _WIN32 (Str_Strncasecmp(oldPath, oldPrefix, oldPrefixLen) == 0) && #else (Str_Strncmp(oldPath, oldPrefix, oldPrefixLen) == 0) && #endif (strchr(VALID_DIRSEPS, oldPath[oldPrefixLen]) || (oldPath[oldPrefixLen] == '\0'))) { size_t newPrefixLen = strlen(newPrefix); size_t newPathLen = (oldPathLen - oldPrefixLen) + newPrefixLen; ASSERT(newPathLen > 0); ASSERT(oldPathLen >= oldPrefixLen); newPath = Util_SafeMalloc((newPathLen + 1) * sizeof(char)); memcpy(newPath, newPrefix, newPrefixLen); memcpy(newPath + newPrefixLen, oldPath + oldPrefixLen, oldPathLen - oldPrefixLen + 1); /* * It should only match once. Weird self-referencing mappings * aren't allowed. */ free(oldPrefix); free(newPrefix); return newPath; } free(oldPrefix); free(newPrefix); } return NULL; }
char * Unicode_Normalize(const char *str, // IN UnicodeNormalizationForm form) // IN { UNormalizationMode mode; UChar *uchars; char *result; int32_t normalizedLen; UErrorCode status = U_ZERO_ERROR; UCharIterator strIter; UBool neededToNormalize = FALSE; uiter_setUTF8(&strIter, (const char *)str, -1); switch (form) { case UNICODE_NORMAL_FORM_C: mode = UNORM_NFC; break; case UNICODE_NORMAL_FORM_D: mode = UNORM_NFD; break; default: NOT_REACHED(); } normalizedLen = unorm_next(&strIter, NULL, 0, mode, 0, TRUE, &neededToNormalize, &status); if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) { // We expect U_BUFFER_OVERFLOW_ERROR here. Anything else is a problem. ASSERT(U_SUCCESS(status)); return NULL; } uchars = Util_SafeMalloc(sizeof *uchars * normalizedLen); // Reset back to the beginning of the UTF-8 input. (*strIter.move)(&strIter, 0, UITER_START); status = U_ZERO_ERROR; normalizedLen = unorm_next(&strIter, uchars, normalizedLen, mode, 0, TRUE, &neededToNormalize, &status); if (U_FAILURE(status)) { ASSERT(U_SUCCESS(status)); return NULL; } result = Unicode_AllocWithLength(uchars, normalizedLen * 2, STRING_ENCODING_UTF16); free(uchars); return result; }