summaryrefslogtreecommitdiffstats
path: root/intl/icu/source/io/ufmt_cmn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'intl/icu/source/io/ufmt_cmn.cpp')
-rw-r--r--intl/icu/source/io/ufmt_cmn.cpp259
1 files changed, 259 insertions, 0 deletions
diff --git a/intl/icu/source/io/ufmt_cmn.cpp b/intl/icu/source/io/ufmt_cmn.cpp
new file mode 100644
index 0000000000..3d8f6413d8
--- /dev/null
+++ b/intl/icu/source/io/ufmt_cmn.cpp
@@ -0,0 +1,259 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+******************************************************************************
+*
+* Copyright (C) 1998-2014, International Business Machines
+* Corporation and others. All Rights Reserved.
+*
+******************************************************************************
+*
+* File ufmt_cmn.c
+*
+* Modification History:
+*
+* Date Name Description
+* 12/02/98 stephen Creation.
+* 03/12/99 stephen Modified for new C API.
+* 03/15/99 stephen Added defaultCPToUnicode, unicodeToDefaultCP
+* 07/19/99 stephen Fixed bug in defaultCPToUnicode
+******************************************************************************
+*/
+
+#include "cstring.h"
+#include "cmemory.h"
+#include "ufmt_cmn.h"
+#include "unicode/uchar.h"
+#include "unicode/ucnv.h"
+#include "ustr_cnv.h"
+
+#if !UCONFIG_NO_CONVERSION
+
+
+#define DIGIT_0 0x0030
+#define DIGIT_9 0x0039
+#define LOWERCASE_A 0x0061
+#define UPPERCASE_A 0x0041
+#define LOWERCASE_Z 0x007A
+#define UPPERCASE_Z 0x005A
+
+int
+ufmt_digitvalue(char16_t c)
+{
+ if( ((c>=DIGIT_0)&&(c<=DIGIT_9)) ||
+ ((c>=LOWERCASE_A)&&(c<=LOWERCASE_Z)) ||
+ ((c>=UPPERCASE_A)&&(c<=UPPERCASE_Z)) )
+ {
+ return c - DIGIT_0 - (c >= 0x0041 ? (c >= 0x0061 ? 39 : 7) : 0);
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+UBool
+ufmt_isdigit(char16_t c,
+ int32_t radix)
+{
+ int digitVal = ufmt_digitvalue(c);
+
+ return (UBool)(digitVal < radix && digitVal >= 0);
+}
+
+#define TO_UC_DIGIT(a) a <= 9 ? (DIGIT_0 + a) : (0x0037 + a)
+#define TO_LC_DIGIT(a) a <= 9 ? (DIGIT_0 + a) : (0x0057 + a)
+
+void
+ufmt_64tou(char16_t *buffer,
+ int32_t *len,
+ uint64_t value,
+ uint8_t radix,
+ UBool uselower,
+ int32_t minDigits)
+{
+ int32_t length = 0;
+ uint32_t digit;
+ char16_t *left, *right, temp;
+
+ do {
+ digit = (uint32_t)(value % radix);
+ value = value / radix;
+ buffer[length++] = (char16_t)(uselower ? TO_LC_DIGIT(digit)
+ : TO_UC_DIGIT(digit));
+ } while(value);
+
+ /* pad with zeroes to make it minDigits long */
+ if(minDigits != -1 && length < minDigits) {
+ while(length < minDigits && length < *len)
+ buffer[length++] = DIGIT_0; /*zero padding */
+ }
+
+ /* reverse the buffer */
+ left = buffer;
+ right = buffer + length;
+ while(left < --right) {
+ temp = *left;
+ *left++ = *right;
+ *right = temp;
+ }
+
+ *len = length;
+}
+
+void
+ufmt_ptou(char16_t *buffer,
+ int32_t *len,
+ void *value,
+ UBool uselower)
+{
+ int32_t i;
+ int32_t length = 0;
+ uint8_t *ptrIdx = (uint8_t *)&value;
+
+#if U_IS_BIG_ENDIAN
+ for (i = 0; i < (int32_t)sizeof(void *); i++)
+#else
+ for (i = (int32_t)sizeof(void *)-1; i >= 0 ; i--)
+#endif
+ {
+ uint8_t byteVal = ptrIdx[i];
+ uint16_t firstNibble = (uint16_t)(byteVal>>4);
+ uint16_t secondNibble = (uint16_t)(byteVal&0xF);
+ if (uselower) {
+ buffer[length++]=TO_LC_DIGIT(firstNibble);
+ buffer[length++]=TO_LC_DIGIT(secondNibble);
+ }
+ else {
+ buffer[length++]=TO_UC_DIGIT(firstNibble);
+ buffer[length++]=TO_UC_DIGIT(secondNibble);
+ }
+ }
+
+ *len = length;
+}
+
+int64_t
+ufmt_uto64(const char16_t *buffer,
+ int32_t *len,
+ int8_t radix)
+{
+ const char16_t *limit;
+ int32_t count;
+ uint64_t result;
+
+
+ /* initialize parameters */
+ limit = buffer + *len;
+ count = 0;
+ result = 0;
+
+ /* iterate through buffer */
+ while(ufmt_isdigit(*buffer, radix) && buffer < limit) {
+
+ /* read the next digit */
+ result *= radix;
+ result += ufmt_digitvalue(*buffer++);
+
+ /* increment our count */
+ ++count;
+ }
+
+ *len = count;
+ return static_cast<int64_t>(result);
+}
+
+#define NIBBLE_PER_BYTE 2
+void *
+ufmt_utop(const char16_t *buffer,
+ int32_t *len)
+{
+ int32_t count, resultIdx, incVal, offset;
+ /* This union allows the pointer to be written as an array. */
+ union {
+ void *ptr;
+ uint8_t bytes[sizeof(void*)];
+ } result;
+
+ /* initialize variables */
+ count = 0;
+ offset = 0;
+ result.ptr = nullptr;
+
+ /* Skip the leading zeros */
+ while(buffer[count] == DIGIT_0 || u_isspace(buffer[count])) {
+ count++;
+ offset++;
+ }
+
+ /* iterate through buffer, stop when you hit the end */
+ while(count < *len && ufmt_isdigit(buffer[count], 16)) {
+ /* increment the count consumed */
+ ++count;
+ }
+
+ /* detect overflow */
+ if (count - offset > (int32_t)(sizeof(void*)*NIBBLE_PER_BYTE)) {
+ offset = count - (int32_t)(sizeof(void*)*NIBBLE_PER_BYTE);
+ }
+
+ /* Initialize the direction of the input */
+#if U_IS_BIG_ENDIAN
+ incVal = -1;
+ resultIdx = (int32_t)(sizeof(void*) - 1);
+#else
+ incVal = 1;
+ resultIdx = 0;
+#endif
+ /* Write how much was consumed. */
+ *len = count;
+ while(--count >= offset) {
+ /* Get the first nibble of the byte */
+ uint8_t byte = (uint8_t)ufmt_digitvalue(buffer[count]);
+
+ if (count > offset) {
+ /* Get the second nibble of the byte when available */
+ byte = (uint8_t)(byte + (ufmt_digitvalue(buffer[--count]) << 4));
+ }
+ /* Write the byte into the array */
+ result.bytes[resultIdx] = byte;
+ resultIdx += incVal;
+ }
+
+ return result.ptr;
+}
+
+char16_t*
+ufmt_defaultCPToUnicode(const char *s, int32_t sSize,
+ char16_t *target, int32_t tSize)
+{
+ char16_t *alias;
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *defConverter = u_getDefaultConverter(&status);
+
+ if(U_FAILURE(status) || defConverter == 0)
+ return 0;
+
+ if(sSize <= 0) {
+ sSize = static_cast<int32_t>(uprv_strlen(s)) + 1;
+ }
+
+ /* perform the conversion in one swoop */
+ if(target != 0) {
+
+ alias = target;
+ ucnv_toUnicode(defConverter, &alias, alias + tSize, &s, s + sSize - 1,
+ nullptr, true, &status);
+
+
+ /* add the null terminator */
+ *alias = 0x0000;
+ }
+
+ u_releaseDefaultConverter(defConverter);
+
+ return target;
+}
+
+
+#endif