NS_IMETHODIMP nsCollationMacUC::AllocateRawSortKey(int32_t strength, const nsAString& stringIn, uint8_t** key, uint32_t* outLen) { NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_ARG_POINTER(key); NS_ENSURE_ARG_POINTER(outLen); nsresult res = EnsureCollator(strength); NS_ENSURE_SUCCESS(res, res); uint32_t stringInLen = stringIn.Length(); const UChar* str = (const UChar*)PromiseFlatString(stringIn).get(); int32_t keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, nullptr, 0); NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE); // Since key is freed elsewhere with PR_Free, allocate with PR_Malloc. uint8_t* newKey = (uint8_t*)PR_Malloc(keyLength + 1); if (!newKey) { return NS_ERROR_OUT_OF_MEMORY; } keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, newKey, keyLength + 1); NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE); *key = newKey; *outLen = keyLength; return NS_OK; }
NS_IMETHODIMP nsCollationMacUC::CompareString(int32_t strength, const nsAString& string1, const nsAString& string2, int32_t* result) { NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_ARG_POINTER(result); *result = 0; nsresult rv = EnsureCollator(strength); NS_ENSURE_SUCCESS(rv, rv); UCollationResult uresult; uresult = ucol_strcoll(mCollatorICU, (const UChar*)PromiseFlatString(string1).get(), string1.Length(), (const UChar*)PromiseFlatString(string2).get(), string2.Length()); int32_t res; switch (uresult) { case UCOL_LESS: res = -1; break; case UCOL_EQUAL: res = 0; break; case UCOL_GREATER: res = 1; break; default: MOZ_CRASH("ucol_strcoll returned bad UCollationResult"); } *result = res; return NS_OK; }
/*---------------------------------------------------------------------------------------------- Generate the sort key as a "SAFEARRAY". ----------------------------------------------------------------------------------------------*/ STDMETHODIMP LgIcuCollator::get_SortKeyVariant(BSTR bstrValue, LgCollatingOptions colopt, VARIANT * psaKey) { BEGIN_COM_METHOD; ChkComBstrArgN(bstrValue); ChkComArgPtr(psaKey); psaKey->vt = VT_NULL; EnsureCollator(); int32_t cbKey = keySize; byte rgbKey[keySize+1]; Vector<byte> vbKey; byte * pbKey = GetSortKey(bstrValue, rgbKey, &cbKey, vbKey); // Allocate the safe array. SAFEARRAYBOUND rgsabound[1]; rgsabound[0].lLbound = 0; rgsabound[0].cElements = cbKey; SAFEARRAY FAR * psa = ::SafeArrayCreate(VT_UI1, 1, rgsabound); // Copy the key data to the safe array. byte * pbOut; CheckHr(::SafeArrayAccessData(psa, (void HUGEP **)&pbOut)); memcpy(pbOut, pbKey, cbKey); CheckHr(::SafeArrayUnaccessData(psa)); // Push the safe array to the output pointer. psaKey->vt = VT_UI1 | VT_ARRAY; V_ARRAY(psaKey) = psa; return S_OK; END_COM_METHOD(g_fact, IID_ILgCollatingEngine); }
/*---------------------------------------------------------------------------------------------- Do a direct string comparison. Note that, contrary to what the contract implies, this routine is not more efficient than the client just retrieving the keys and comparing them. OPTIMIZE: would we benefit significantly by implementing this using CompareString? Unfortunately, it is hard to avoid the need to do the WideCharToMultiByte conversion for the whole of both strings... ----------------------------------------------------------------------------------------------*/ STDMETHODIMP LgIcuCollator::Compare(BSTR bstrValue1, BSTR bstrValue2, LgCollatingOptions colopt, int * pnVal) { BEGIN_COM_METHOD ChkComBstrArgN(bstrValue1); ChkComBstrArgN(bstrValue2); ChkComOutPtr(pnVal); EnsureCollator(); int32_t cbKey1 = keySize; byte rgbKey1[keySize+1]; Vector<byte> vbKey1; byte * pbKey1 = GetSortKey(bstrValue1, rgbKey1, &cbKey1, vbKey1); int32_t cbKey2 = keySize; byte rgbKey2[keySize+1]; Vector<byte> vbKey2; byte * pbKey2 = GetSortKey(bstrValue2, rgbKey2, &cbKey2, vbKey2); *pnVal = strcmp((char *)pbKey1, (char *)pbKey2); return S_OK; END_COM_METHOD(g_fact, IID_ILgCollatingEngine); }
/*---------------------------------------------------------------------------------------------- Initialize the collating engine to the given locale. ----------------------------------------------------------------------------------------------*/ STDMETHODIMP LgIcuCollator::Open(BSTR bstrLocale) { BEGIN_COM_METHOD; ChkComBstrArgN(bstrLocale); if (m_pCollator) { delete m_pCollator; m_pCollator = NULL; } m_stuLocale = bstrLocale; EnsureCollator(); END_COM_METHOD(g_fact, IID_ILgCollatingEngine); }
/*---------------------------------------------------------------------------------------------- Do a direct string comparison using "SAFEARRAY"s. Note that, contrary to what the contract implies, this routine is not more efficient than the client just retrieving the keys and comparing them. OPTIMIZE: would we benefit significantly by implementing this using CompareString? Unfortunately, it is hard to avoid the need to do the WideCharToMultiByte conversion for the whole of both strings... ----------------------------------------------------------------------------------------------*/ STDMETHODIMP LgIcuCollator::CompareVariant(VARIANT saKey1, VARIANT saKey2, LgCollatingOptions colopt, int * pnVal) { BEGIN_COM_METHOD; ChkComOutPtr(pnVal); #if WIN32 EnsureCollator(); UINT cDim = ::SafeArrayGetDim(V_ARRAY(&saKey1)); if (cDim != 1) return E_INVALIDARG; UINT cElemSize = ::SafeArrayGetElemsize(V_ARRAY(&saKey1)); if (cElemSize != 1) return E_INVALIDARG; cDim = ::SafeArrayGetDim(V_ARRAY(&saKey2)); if (cDim != 1) return E_INVALIDARG; cElemSize = ::SafeArrayGetElemsize(V_ARRAY(&saKey2)); if (cElemSize != 1) return E_INVALIDARG; byte * pbKey1; CheckHr(::SafeArrayAccessData(V_ARRAY(&saKey1), (void HUGEP **)&pbKey1)); byte * pbKey2; CheckHr(::SafeArrayAccessData(V_ARRAY(&saKey2), (void HUGEP **)&pbKey2)); if (pbKey1 == NULL) { *pnVal = 1; } else if (pbKey2 == NULL) { *pnVal = -1; } else { *pnVal = strcmp((char *)pbKey1, (char *)pbKey2); } CheckHr(::SafeArrayUnaccessData(V_ARRAY(&saKey1))); CheckHr(::SafeArrayUnaccessData(V_ARRAY(&saKey2))); return S_OK; #else // TODO-Linux: does this need porting? printf("Warning: using unported method LgIcuCollator::CompareVariant\n"); fflush(stdout); #endif //WIN32 END_COM_METHOD(g_fact, IID_ILgCollatingEngine); }
NS_IMETHODIMP nsCollationMacUC::AllocateRawSortKey(int32_t strength, const nsAString& stringIn, uint8_t** key, uint32_t* outLen) { NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_ARG_POINTER(key); NS_ENSURE_ARG_POINTER(outLen); nsresult res = EnsureCollator(strength); NS_ENSURE_SUCCESS(res, res); uint32_t stringInLen = stringIn.Length(); uint32_t maxKeyLen = (1 + stringInLen) * kCollationValueSizeFactor * sizeof(UCCollationValue); if (maxKeyLen > mBufferLen) { uint32_t newBufferLen = mBufferLen; do { newBufferLen *= 2; } while (newBufferLen < maxKeyLen); void *newBuffer = PR_Malloc(newBufferLen); if (!newBuffer) return NS_ERROR_OUT_OF_MEMORY; PR_FREEIF(mBuffer); mBuffer = newBuffer; mBufferLen = newBufferLen; } ItemCount actual; OSStatus err = ::UCGetCollationKey(mCollator, (const UniChar*) PromiseFlatString(stringIn).get(), (UniCharCount) stringInLen, (ItemCount) (mBufferLen / sizeof(UCCollationValue)), &actual, (UCCollationValue *)mBuffer); NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE); uint32_t keyLength = actual * sizeof(UCCollationValue); void *newKey = PR_Malloc(keyLength); if (!newKey) return NS_ERROR_OUT_OF_MEMORY; memcpy(newKey, mBuffer, keyLength); *key = (uint8_t *)newKey; *outLen = keyLength; return NS_OK; }
NS_IMETHODIMP nsCollationMacUC::CompareString(int32_t strength, const nsAString& string1, const nsAString& string2, int32_t* result) { NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_ARG_POINTER(result); *result = 0; nsresult res = EnsureCollator(strength); NS_ENSURE_SUCCESS(res, res); *result = 0; OSStatus err; err = ::UCCompareText(mCollator, (const UniChar *) PromiseFlatString(string1).get(), (UniCharCount) string1.Length(), (const UniChar *) PromiseFlatString(string2).get(), (UniCharCount) string2.Length(), nullptr, (SInt32*) result); NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE); return NS_OK; }
/*---------------------------------------------------------------------------------------------- Generate the sort key as a byte * ----------------------------------------------------------------------------------------------*/ byte * LgIcuCollator::GetSortKey(BSTR bstrValue, byte* prgbKey, int32_t* pcbKey) { byte * pbKey; int32_t crgbKey = *pcbKey; EnsureCollator(); *pcbKey = m_pCollator->getSortKey(bstrValue, BstrLen(bstrValue), prgbKey, crgbKey); if (*pcbKey > crgbKey) { // sort key is too long, the caller has to pass us a bigger buffer. pbKey = NULL; } else { // sort key is less than 1024 bytes pbKey = prgbKey; } return pbKey; }
NS_IMETHODIMP nsCollationMacUC::CompareString(int32_t strength, const nsAString& string1, const nsAString& string2, int32_t* result) { NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_ARG_POINTER(result); *result = 0; nsresult res = EnsureCollator(strength); NS_ENSURE_SUCCESS(res, res); if (mUseICU) { UCollationResult uresult; uresult = ucol_strcoll(mCollatorICU, (const UChar*)PromiseFlatString(string1).get(), string1.Length(), (const UChar*)PromiseFlatString(string2).get(), string2.Length()); int32_t res; switch (uresult) { case UCOL_LESS: res = -1; break; case UCOL_EQUAL: res = 0; break; case UCOL_GREATER: res = 1; break; default: MOZ_CRASH("ucol_strcoll returned bad UCollationResult"); } *result = res; return NS_OK; } *result = 0; OSStatus err; err = ::UCCompareText(mCollator, (const UniChar *) PromiseFlatString(string1).get(), (UniCharCount) string1.Length(), (const UniChar *) PromiseFlatString(string2).get(), (UniCharCount) string2.Length(), nullptr, (SInt32*) result); NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE); return NS_OK; }
NS_IMETHODIMP nsCollationMacUC::AllocateRawSortKey(int32_t strength, const nsAString& stringIn, uint8_t** key, uint32_t* outLen) { NS_ENSURE_TRUE(mInit, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_ARG_POINTER(key); NS_ENSURE_ARG_POINTER(outLen); nsresult res = EnsureCollator(strength); NS_ENSURE_SUCCESS(res, res); uint32_t stringInLen = stringIn.Length(); if (mUseICU) { const UChar* str = (const UChar*)PromiseFlatString(stringIn).get(); int32_t keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, nullptr, 0); NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE); // Since key is freed elsewhere with PR_Free, allocate with PR_Malloc. uint8_t* newKey = (uint8_t*)PR_Malloc(keyLength + 1); if (!newKey) { return NS_ERROR_OUT_OF_MEMORY; } keyLength = ucol_getSortKey(mCollatorICU, str, stringInLen, newKey, keyLength + 1); NS_ENSURE_TRUE((stringInLen == 0 || keyLength > 0), NS_ERROR_FAILURE); *key = newKey; *outLen = keyLength; return NS_OK; } uint32_t maxKeyLen = (1 + stringInLen) * kCollationValueSizeFactor * sizeof(UCCollationValue); if (maxKeyLen > mBufferLen) { uint32_t newBufferLen = mBufferLen; do { newBufferLen *= 2; } while (newBufferLen < maxKeyLen); void* newBuffer = moz_malloc(newBufferLen); if (!newBuffer) { return NS_ERROR_OUT_OF_MEMORY; } if (mBuffer) { moz_free(mBuffer); mBuffer = nullptr; } mBuffer = newBuffer; mBufferLen = newBufferLen; } ItemCount actual; OSStatus err = ::UCGetCollationKey(mCollator, (const UniChar*) PromiseFlatString(stringIn).get(), (UniCharCount) stringInLen, (ItemCount) (mBufferLen / sizeof(UCCollationValue)), &actual, (UCCollationValue *)mBuffer); NS_ENSURE_TRUE((err == noErr), NS_ERROR_FAILURE); uint32_t keyLength = actual * sizeof(UCCollationValue); // Since key is freed elsewhere with PR_Free, allocate with PR_Malloc. void* newKey = PR_Malloc(keyLength); if (!newKey) { return NS_ERROR_OUT_OF_MEMORY; } memcpy(newKey, mBuffer, keyLength); *key = (uint8_t *)newKey; *outLen = keyLength; return NS_OK; }