]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/ustr_cnv.cpp
ICU-551.24.tar.gz
[apple/icu.git] / icuSources / common / ustr_cnv.cpp
diff --git a/icuSources/common/ustr_cnv.cpp b/icuSources/common/ustr_cnv.cpp
new file mode 100644 (file)
index 0000000..b33c6a5
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+*******************************************************************************
+*
+*   Copyright (C) 1998-2014, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+*******************************************************************************
+*   file name:  ustr_cnv.cpp
+*   encoding:   US-ASCII
+*   tab size:   8 (not used)
+*   indentation:4
+*
+*   created on: 2004aug24
+*   created by: Markus W. Scherer
+*
+*   Character conversion functions moved here from ustring.c
+*/
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_CONVERSION
+
+#include "unicode/ustring.h"
+#include "unicode/ucnv.h"
+#include "cstring.h"
+#include "cmemory.h"
+#include "umutex.h"
+#include "ustr_cnv.h"
+
+/* mutexed access to a shared default converter ----------------------------- */
+
+static UConverter *gDefaultConverter = NULL;
+
+U_CAPI UConverter* U_EXPORT2
+u_getDefaultConverter(UErrorCode *status)
+{
+    UConverter *converter = NULL;
+    
+    if (gDefaultConverter != NULL) {
+        umtx_lock(NULL);
+        
+        /* need to check to make sure it wasn't taken out from under us */
+        if (gDefaultConverter != NULL) {
+            converter = gDefaultConverter;
+            gDefaultConverter = NULL;
+        }
+        umtx_unlock(NULL);
+    }
+
+    /* if the cache was empty, create a converter */
+    if(converter == NULL) {
+        converter = ucnv_open(NULL, status);
+        if(U_FAILURE(*status)) {
+            ucnv_close(converter);
+            converter = NULL;
+        }
+    }
+
+    return converter;
+}
+
+U_CAPI void U_EXPORT2
+u_releaseDefaultConverter(UConverter *converter)
+{
+    if(gDefaultConverter == NULL) {
+        if (converter != NULL) {
+            ucnv_reset(converter);
+        }
+        umtx_lock(NULL);
+
+        if(gDefaultConverter == NULL) {
+            gDefaultConverter = converter;
+            converter = NULL;
+        }
+        umtx_unlock(NULL);
+    }
+
+    if(converter != NULL) {
+        ucnv_close(converter);
+    }
+}
+
+U_CAPI void U_EXPORT2
+u_flushDefaultConverter()
+{
+    UConverter *converter = NULL;
+    
+    if (gDefaultConverter != NULL) {
+        umtx_lock(NULL);
+        
+        /* need to check to make sure it wasn't taken out from under us */
+        if (gDefaultConverter != NULL) {
+            converter = gDefaultConverter;
+            gDefaultConverter = NULL;
+        }
+        umtx_unlock(NULL);
+    }
+
+    /* if the cache was populated, flush it */
+    if(converter != NULL) {
+         ucnv_close(converter);
+    }
+}
+
+
+/* conversions between char* and UChar* ------------------------------------- */
+
+/* maximum string length for u_uastrcpy() and u_austrcpy() implementations */
+#define MAX_STRLEN 0x0FFFFFFF
+
+/*
+ returns the minimum of (the length of the null-terminated string) and n.
+*/
+static int32_t u_astrnlen(const char *s1, int32_t n)
+{
+    int32_t len = 0;
+
+    if (s1)
+    {
+        while (n-- && *(s1++))
+        {
+            len++;
+        }
+    }
+    return len;
+}
+
+U_CAPI UChar*  U_EXPORT2
+u_uastrncpy(UChar *ucs1,
+           const char *s2,
+           int32_t n)
+{
+  UChar *target = ucs1;
+  UErrorCode err = U_ZERO_ERROR;
+  UConverter *cnv = u_getDefaultConverter(&err);
+  if(U_SUCCESS(err) && cnv != NULL) {
+    ucnv_reset(cnv);
+    ucnv_toUnicode(cnv,
+                   &target,
+                   ucs1+n,
+                   &s2,
+                   s2+u_astrnlen(s2, n),
+                   NULL,
+                   TRUE,
+                   &err);
+    ucnv_reset(cnv); /* be good citizens */
+    u_releaseDefaultConverter(cnv);
+    if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
+      *ucs1 = 0; /* failure */
+    }
+    if(target < (ucs1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */
+      *target = 0;  /* terminate */
+    }
+  } else {
+    *ucs1 = 0;
+  }
+  return ucs1;
+}
+
+U_CAPI UChar*  U_EXPORT2
+u_uastrcpy(UChar *ucs1,
+          const char *s2 )
+{
+  UErrorCode err = U_ZERO_ERROR;
+  UConverter *cnv = u_getDefaultConverter(&err);
+  if(U_SUCCESS(err) && cnv != NULL) {
+    ucnv_toUChars(cnv,
+                    ucs1,
+                    MAX_STRLEN,
+                    s2,
+                    (int32_t)uprv_strlen(s2),
+                    &err);
+    u_releaseDefaultConverter(cnv);
+    if(U_FAILURE(err)) {
+      *ucs1 = 0;
+    }
+  } else {
+    *ucs1 = 0;
+  }
+  return ucs1;
+}
+
+/*
+ returns the minimum of (the length of the null-terminated string) and n.
+*/
+static int32_t u_ustrnlen(const UChar *ucs1, int32_t n)
+{
+    int32_t len = 0;
+
+    if (ucs1)
+    {
+        while (n-- && *(ucs1++))
+        {
+            len++;
+        }
+    }
+    return len;
+}
+
+U_CAPI char*  U_EXPORT2
+u_austrncpy(char *s1,
+        const UChar *ucs2,
+        int32_t n)
+{
+  char *target = s1;
+  UErrorCode err = U_ZERO_ERROR;
+  UConverter *cnv = u_getDefaultConverter(&err);
+  if(U_SUCCESS(err) && cnv != NULL) {
+    ucnv_reset(cnv);
+    ucnv_fromUnicode(cnv,
+                  &target,
+                  s1+n,
+                  &ucs2,
+                  ucs2+u_ustrnlen(ucs2, n),
+                  NULL,
+                  TRUE,
+                  &err);
+    ucnv_reset(cnv); /* be good citizens */
+    u_releaseDefaultConverter(cnv);
+    if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
+      *s1 = 0; /* failure */
+    }
+    if(target < (s1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */
+      *target = 0;  /* terminate */
+    }
+  } else {
+    *s1 = 0;
+  }
+  return s1;
+}
+
+U_CAPI char*  U_EXPORT2
+u_austrcpy(char *s1,
+         const UChar *ucs2 )
+{
+  UErrorCode err = U_ZERO_ERROR;
+  UConverter *cnv = u_getDefaultConverter(&err);
+  if(U_SUCCESS(err) && cnv != NULL) {
+    int32_t len = ucnv_fromUChars(cnv,
+                  s1,
+                  MAX_STRLEN,
+                  ucs2,
+                  -1,
+                  &err);
+    u_releaseDefaultConverter(cnv);
+    s1[len] = 0;
+  } else {
+    *s1 = 0;
+  }
+  return s1;
+}
+
+#endif