ConstUnicode Unicode_GetStatic(const char *asciiBytes, // IN Bool unescape) // IN { Unicode result = NULL; HashTable *stringTable; if (unescape) { stringTable = HashTable_AllocOnce(&UnicodeUnescapedStringTable, 4096, HASH_FLAG_ATOMIC | HASH_STRING_KEY, UnicodeHashFree); } else { stringTable = HashTable_AllocOnce(&UnicodeStringTable, 4096, HASH_FLAG_ATOMIC | HASH_STRING_KEY, UnicodeHashFree); } /* * Attempt a lookup for the key value; if it is found things are easy and * fine. Otherwise HashTable_LookupOrInsert is used to attempt to enter * the data in a racey manner. Should multiple threads attempt to enter * the same key concurrently one thread will get the entered data and the * other threads will detect that their entries were rejected; they * discard their copies of the data and use the entered data (values * will be stable). */ if (!HashTable_Lookup(stringTable, asciiBytes, (void **) &result)) { Unicode newData = UnicodeAllocStatic(asciiBytes, unescape); if (newData) { result = HashTable_LookupOrInsert(stringTable, asciiBytes, newData); if (result != newData) { Unicode_Free(newData); } } } return result; }
static HolderContext * MXUserGetHolderContext(MXUserRWLock *lock) // IN: { HolderContext *result; void *threadID = MXUserCastedThreadID(); ASSERT(lock->holderTable); if (!HashTable_Lookup(lock->holderTable, threadID, (void **) &result)) { HolderContext *newContext = Util_SafeMalloc(sizeof(HolderContext)); newContext->holdStart = 0; newContext->state = RW_UNLOCKED; result = HashTable_LookupOrInsert(lock->holderTable, threadID, (void *) newContext); if (result != newContext) { free(newContext); } } return result; }
const char * Err_Errno2String(Err_Number errorNumber) // IN { HashTable *numTable; HashTable *ptrTable; ErrInfo *info; ErrInfo *oldInfo; Err_Number oldErrno = Err_Errno(); ASSERT(errorNumber != ERR_INVALID); /* * Look up the error in numTable. * Or insert it if it's not there. */ numTable = NUMTABLE(); if (!HashTable_Lookup(numTable, (void *) (uintptr_t) errorNumber, (void **) &info)) { char buf[2048]; const char *p; size_t n; /* * Convert number to string and build the info structure. */ p = ErrErrno2String(errorNumber, buf, sizeof buf); info = Util_SafeMalloc(sizeof *info); info->number = errorNumber; info->string = Util_SafeStrdup(p); /* * To be safe, make sure the end of the string is at * a UTF-8 boundary, but we can only do this when the * string is in our buffer (it may not be). */ n = strlen(info->string); n = CodeSet_Utf8FindCodePointBoundary(info->string, n); info->string[n] = '\0'; /* * Try to insert new info into numTable. * If that fails, then we must have lost out to someone else. * Use theirs in that case. */ oldInfo = HashTable_LookupOrInsert(numTable, (void *) (uintptr_t) errorNumber, info); if (oldInfo != info) { ASSERT(oldInfo->number == info->number); ASSERT(Str_Strcmp(oldInfo->string, info->string) == 0); free(info->string); free(info); info = oldInfo; } } /* * Try to insert info into ptrTable. * We need to do it even if we didn't create this entry, * because we may get here before the other guy (who created * the entry and inserted it into numTable). */ ptrTable = PTRTABLE(); oldInfo = HashTable_LookupOrInsert(ptrTable, info->string, info); ASSERT(oldInfo == info); #if defined VMX86_DEBUG && defined __linux__ { HashTable *strTable = STRTABLE(); ErrInfo *i = HashTable_LookupOrInsert(strTable, info->string, info); ASSERT(i == info); } #endif Err_SetErrno(oldErrno); return info->string; }
static HashTable * SNEBuildHash(const char **compatEnviron) // IN: original "compatibility" environment { HashTable *environTable; const char **p; /* * Number of buckets picked arbitrarily. We're more interested in having an * associative array than raw table performance. */ environTable = HashTable_Alloc(64, HASH_STRING_KEY | HASH_FLAG_COPYKEY, free); for (p = compatEnviron; p && *p; p++) { const size_t prefixLength = sizeof "VMWARE_" - 1; char *key; char *value; unsigned int index; index = 0; key = StrUtil_GetNextToken(&index, *p, "="); if (!key) { /* XXX Must empty environment variables still contain a '=' delimiter? */ Debug("%s: Encountered environment entry without '='.\n", __func__); continue; } /* * Copy the value beginning after the '=' delimiter (even if it's empty). */ ++index; value = Util_SafeStrdup(&(*p)[index]); if (StrUtil_StartsWith(key, "VMWARE_") && key[prefixLength] != '\0' && (value[0] == '0' || value[0] == '1')) { /* * Okay, this appears to be one of the wrapper's variables, so let's * figure out the original environment variable name (by just indexing * past the prefix) and value (by indexing past the "was this variable * in the native environment?" marker). * * XXX Should we move this marker to a separate header? */ char *realKey = &key[prefixLength]; char *realValue = (value[0] == '0') ? NULL : Util_SafeStrdup(&value[1]); HashTable_ReplaceOrInsert(environTable, realKey, realValue); } else { HashTable_LookupOrInsert(environTable, key, value); } /* * The hash table makes a copy of our key, and it takes ownership of inserted * values (via our passed freeing function). So that means we're responsible * for freeing 'key', but -not- 'value'. */ free(key); } return environTable; }