Index: icu46/source/common/ustr_cnv.c |
=================================================================== |
--- icu46/source/common/ustr_cnv.c (revision 0) |
+++ icu46/source/common/ustr_cnv.c (revision 0) |
@@ -0,0 +1,253 @@ |
+/* |
+******************************************************************************* |
+* |
+* Copyright (C) 1998-2010, International Business Machines |
+* Corporation and others. All Rights Reserved. |
+* |
+******************************************************************************* |
+* file name: ustr_cnv.c |
+* 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 |
Property changes on: icu46/source/common/ustr_cnv.c |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |