123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- // © 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
|