static Variant HHVM_STATIC_METHOD(Locale, acceptFromHttp, const String& header) { UErrorCode error = U_ZERO_ERROR; UEnumeration *avail = ures_openAvailableLocales(nullptr, &error); ULOC_CHECK(error, false); char out[MAX_LOCALE_LEN]; UAcceptResult result; error = U_ZERO_ERROR; int len = uloc_acceptLanguageFromHTTP(out, sizeof(out), &result, header.c_str(), avail, &error); uenum_close(avail); ULOC_CHECK(error, false); if (len < 0 || result == ULOC_ACCEPT_FAILED) { return false; } return String(out, len, CopyString); }
static Variant HHVM_STATIC_METHOD(ResourceBundle, getLocales, const String& bundleName) { UErrorCode error = U_ZERO_ERROR; auto le = ures_openAvailableLocales(bundleName.c_str(), &error); if (U_FAILURE(error)) { s_intl_error->setError(error, "Cannot fetch locales list"); return false; } error = U_ZERO_ERROR; uenum_reset(le, &error); if (U_FAILURE(error)) { s_intl_error->setError(error, "Cannot iterate locales list"); return false; } Array ret = Array::Create(); const char *entry; int32_t entry_len; while ((entry = uenum_next(le, &entry_len, &error))) { ret.append(String(entry, entry_len, CopyString)); } return ret; }
const Hashtable * LocaleUtility::getAvailableLocaleNames(const UnicodeString & bundleID) { // LocaleUtility_cache is a hash-of-hashes. The top-level keys // are path strings ('bundleID') passed to // ures_openAvailableLocales. The top-level values are // second-level hashes. The second-level keys are result strings // from ures_openAvailableLocales. The second-level values are // garbage ((void*)1 or other random pointer). UErrorCode status = U_ZERO_ERROR; Hashtable * cache; umtx_lock(NULL); cache = LocaleUtility_cache; umtx_unlock(NULL); if (cache == NULL) { cache = new Hashtable(status); if (cache == NULL || U_FAILURE(status)) { return NULL; // catastrophic failure; e.g. out of memory } cache->setValueDeleter(uhash_deleteHashtable); Hashtable * h; // set this to final LocaleUtility_cache value umtx_lock(NULL); h = LocaleUtility_cache; if (h == NULL) { LocaleUtility_cache = h = cache; cache = NULL; ucln_common_registerCleanup(UCLN_COMMON_SERVICE, service_cleanup); } umtx_unlock(NULL); if (cache != NULL) { delete cache; } cache = h; } U_ASSERT(cache != NULL); Hashtable * htp; umtx_lock(NULL); htp = (Hashtable *) cache->get(bundleID); umtx_unlock(NULL); if (htp == NULL) { htp = new Hashtable(status); if (htp && U_SUCCESS(status)) { CharString cbundleID; cbundleID.appendInvariantChars(bundleID, status); const char * path = cbundleID.isEmpty() ? NULL : cbundleID.data(); UEnumeration * uenum = ures_openAvailableLocales(path, &status); for (;;) { const UChar * id = uenum_unext(uenum, NULL, &status); if (id == NULL) { break; } htp->put(UnicodeString(id), (void *)htp, status); } uenum_close(uenum); if (U_FAILURE(status)) { delete htp; return NULL; } umtx_lock(NULL); cache->put(bundleID, (void *)htp, status); umtx_unlock(NULL); } } return htp; }