summaryrefslogtreecommitdiff
path: root/src/couch/priv/icu_driver/couch_icu_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/couch/priv/icu_driver/couch_icu_driver.c')
-rw-r--r--src/couch/priv/icu_driver/couch_icu_driver.c74
1 files changed, 68 insertions, 6 deletions
diff --git a/src/couch/priv/icu_driver/couch_icu_driver.c b/src/couch/priv/icu_driver/couch_icu_driver.c
index 4d9bb982d..ffccf2e9d 100644
--- a/src/couch/priv/icu_driver/couch_icu_driver.c
+++ b/src/couch/priv/icu_driver/couch_icu_driver.c
@@ -30,6 +30,8 @@ specific language governing permissions and limitations under the License.
#include <string.h> /* for memcpy */
#endif
+#define BUFFER_SIZE 1024
+
typedef struct {
ErlDrvPort port;
@@ -54,6 +56,8 @@ static ErlDrvData couch_drv_start(ErlDrvPort port, char *buff)
UErrorCode status = U_ZERO_ERROR;
couch_drv_data* pData = (couch_drv_data*)driver_alloc(sizeof(couch_drv_data));
+ set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
+
if (pData == NULL)
return ERL_DRV_ERROR_GENERAL;
@@ -84,14 +88,17 @@ ErlDrvSSizeT
return_control_result(void* pLocalResult, int localLen,
char **ppRetBuf, ErlDrvSizeT returnLen)
{
+ ErlDrvBinary* buf = NULL;
+
if (*ppRetBuf == NULL || localLen > returnLen) {
- *ppRetBuf = (char*)driver_alloc_binary(localLen);
- if(*ppRetBuf == NULL) {
- return -1;
- }
+ buf = driver_alloc_binary(localLen);
+ memcpy(buf->orig_bytes, pLocalResult, localLen);
+ *ppRetBuf = (char*) buf;
+ return localLen;
+ } else {
+ memcpy(*ppRetBuf, pLocalResult, localLen);
+ return localLen;
}
- memcpy(*ppRetBuf, pLocalResult, localLen);
- return localLen;
}
static ErlDrvSSizeT
@@ -147,6 +154,61 @@ couch_drv_control(ErlDrvData drv_data, unsigned int command,
return return_control_result(&response, sizeof(response), rbuf, rlen);
}
+ case 2: /* GET_SORT_KEY: */
+ {
+
+ UChar source[BUFFER_SIZE];
+ UChar* sourcePtr = source;
+ int32_t sourceLen = BUFFER_SIZE;
+
+ uint8_t sortKey[BUFFER_SIZE];
+ uint8_t* sortKeyPtr = sortKey;
+ int32_t sortKeyLen = BUFFER_SIZE;
+
+ int32_t inputLen;
+
+ UErrorCode status = U_ZERO_ERROR;
+ ErlDrvSSizeT res;
+
+ /* first 32bits are the length */
+ memcpy(&inputLen, pBuf, sizeof(inputLen));
+ pBuf += sizeof(inputLen);
+
+ u_strFromUTF8(sourcePtr, BUFFER_SIZE, &sourceLen, pBuf, inputLen, &status);
+
+ if (sourceLen >= BUFFER_SIZE) {
+ /* reset status or next u_strFromUTF8 call will auto-fail */
+ status = U_ZERO_ERROR;
+ sourcePtr = (UChar*) malloc(sourceLen * sizeof(UChar));
+ u_strFromUTF8(sourcePtr, sourceLen, NULL, pBuf, inputLen, &status);
+ if (U_FAILURE(status)) {
+ rbuf = NULL;
+ return 0;
+ }
+ } else if (U_FAILURE(status)) {
+ rbuf = NULL;
+ return 0;
+ }
+
+ sortKeyLen = ucol_getSortKey(pData->coll, sourcePtr, sourceLen, sortKeyPtr, BUFFER_SIZE);
+
+ if (sortKeyLen > BUFFER_SIZE) {
+ sortKeyPtr = (uint8_t*) malloc(sortKeyLen);
+ ucol_getSortKey(pData->coll, sourcePtr, sourceLen, sortKeyPtr, sortKeyLen);
+ }
+
+ res = return_control_result(sortKeyPtr, sortKeyLen, rbuf, rlen);
+
+ if (sourcePtr != source) {
+ free(sourcePtr);
+ }
+
+ if (sortKeyPtr != sortKey) {
+ free(sortKeyPtr);
+ }
+
+ return res;
+ }
default:
return -1;