123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- // © 2016 and later: Unicode, Inc. and others.
- // License & terms of use: http://www.unicode.org/copyright.html
- /*
- ******************************************************************************
- *
- * Copyright (C) 2001-2014, International Business Machines
- * Corporation and others. All Rights Reserved.
- *
- ******************************************************************************
- *
- * File sprintf.c
- *
- * Modification History:
- *
- * Date Name Description
- * 02/08/2001 george Creation. Copied from uprintf.c
- * 03/27/2002 Mark Schneckloth Many fixes regarding alignment, null termination
- * (mschneckloth@atomz.com) and other various problems.
- * 08/07/2003 george Reunify printf implementations
- *******************************************************************************
- */
- #include "unicode/utypes.h"
- #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_CONVERSION
- #include "unicode/ustdio.h"
- #include "unicode/ustring.h"
- #include "unicode/putil.h"
- #include "uprintf.h"
- #include "locbund.h"
- #include "cmemory.h"
- #include <ctype.h>
- /* u_minstrncpy copies the minimum number of code units of (count or output->available) */
- static int32_t
- u_sprintf_write(void *context,
- const char16_t *str,
- int32_t count)
- {
- u_localized_print_string *output = (u_localized_print_string *)context;
- /* just calculating buffer size */
- if (output->str == nullptr) {
- return count;
- }
- int32_t size = ufmt_min(count, output->available);
- u_strncpy(output->str + (output->len - output->available), str, size);
- output->available -= size;
- return size;
- }
- static int32_t
- u_sprintf_pad_and_justify(void *context,
- const u_printf_spec_info *info,
- const char16_t *result,
- int32_t resultLen)
- {
- u_localized_print_string *output = (u_localized_print_string *)context;
- int32_t written = 0;
- int32_t lengthOfResult = resultLen;
- /* just calculating buffer size */
- if (output->str == nullptr &&
- info->fWidth != -1 && resultLen < info->fWidth) {
- return info->fWidth;
- }
- resultLen = ufmt_min(resultLen, output->available);
- /* pad and justify, if needed */
- if(info->fWidth != -1 && resultLen < info->fWidth) {
- int32_t paddingLeft = info->fWidth - resultLen;
- int32_t outputPos = output->len - output->available;
-
- if (paddingLeft + resultLen > output->available) {
- paddingLeft = output->available - resultLen;
- if (paddingLeft < 0) {
- paddingLeft = 0;
- }
- /* paddingLeft = output->available - resultLen;*/
- }
- written += paddingLeft;
- /* left justify */
- if(info->fLeft) {
- written += u_sprintf_write(output, result, resultLen);
- u_memset(&output->str[outputPos + resultLen], info->fPadChar, paddingLeft);
- output->available -= paddingLeft;
- }
- /* right justify */
- else {
- u_memset(&output->str[outputPos], info->fPadChar, paddingLeft);
- output->available -= paddingLeft;
- written += u_sprintf_write(output, result, resultLen);
- }
- }
- /* just write the formatted output */
- else {
- written = u_sprintf_write(output, result, resultLen);
- }
-
- if (written >= 0 && lengthOfResult > written) {
- return lengthOfResult;
- }
- return written;
- }
- U_CAPI int32_t U_EXPORT2
- u_sprintf(char16_t *buffer,
- const char *patternSpecification,
- ... )
- {
- va_list ap;
- int32_t written;
- va_start(ap, patternSpecification);
- written = u_vsnprintf(buffer, INT32_MAX, patternSpecification, ap);
- va_end(ap);
- return written;
- }
- U_CAPI int32_t U_EXPORT2
- u_sprintf_u(char16_t *buffer,
- const char16_t *patternSpecification,
- ... )
- {
- va_list ap;
- int32_t written;
- va_start(ap, patternSpecification);
- written = u_vsnprintf_u(buffer, INT32_MAX, patternSpecification, ap);
- va_end(ap);
- return written;
- }
- U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
- u_vsprintf(char16_t *buffer,
- const char *patternSpecification,
- va_list ap)
- {
- return u_vsnprintf(buffer, INT32_MAX, patternSpecification, ap);
- }
- U_CAPI int32_t U_EXPORT2
- u_snprintf(char16_t *buffer,
- int32_t count,
- const char *patternSpecification,
- ... )
- {
- va_list ap;
- int32_t written;
- va_start(ap, patternSpecification);
- written = u_vsnprintf(buffer, count, patternSpecification, ap);
- va_end(ap);
- return written;
- }
- U_CAPI int32_t U_EXPORT2
- u_snprintf_u(char16_t *buffer,
- int32_t count,
- const char16_t *patternSpecification,
- ... )
- {
- va_list ap;
- int32_t written;
- va_start(ap, patternSpecification);
- written = u_vsnprintf_u(buffer, count, patternSpecification, ap);
- va_end(ap);
- return written;
- }
- U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
- u_vsnprintf(char16_t *buffer,
- int32_t count,
- const char *patternSpecification,
- va_list ap)
- {
- int32_t written;
- char16_t *pattern;
- char16_t patBuffer[UFMT_DEFAULT_BUFFER_SIZE];
- int32_t size = (int32_t)strlen(patternSpecification) + 1;
- /* convert from the default codepage to Unicode */
- if (size >= (int32_t)MAX_UCHAR_BUFFER_SIZE(patBuffer)) {
- pattern = (char16_t *)uprv_malloc(size * sizeof(char16_t));
- if (pattern == nullptr) {
- return 0;
- }
- }
- else {
- pattern = patBuffer;
- }
- u_charsToUChars(patternSpecification, pattern, size);
- /* do the work */
- written = u_vsnprintf_u(buffer, count, pattern, ap);
- /* clean up */
- if (pattern != patBuffer) {
- uprv_free(pattern);
- }
- return written;
- }
- U_CAPI int32_t U_EXPORT2
- u_vsprintf_u(char16_t *buffer,
- const char16_t *patternSpecification,
- va_list ap)
- {
- return u_vsnprintf_u(buffer, INT32_MAX, patternSpecification, ap);
- }
- static const u_printf_stream_handler g_sprintf_stream_handler = {
- u_sprintf_write,
- u_sprintf_pad_and_justify
- };
- U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
- u_vsnprintf_u(char16_t *buffer,
- int32_t count,
- const char16_t *patternSpecification,
- va_list ap)
- {
- int32_t written = 0; /* haven't written anything yet */
- int32_t result = 0; /* test the return value of u_printf_parse */
- u_localized_print_string outStr;
- if (count < 0) {
- count = INT32_MAX;
- }
- outStr.str = buffer;
- outStr.len = count;
- outStr.available = count;
- if (u_locbund_init(&outStr.fBundle, "en_US_POSIX") == nullptr) {
- return 0;
- }
- /* parse and print the whole format string */
- result = u_printf_parse(&g_sprintf_stream_handler, patternSpecification, &outStr, &outStr, &outStr.fBundle, &written, ap);
-
- /* Terminate the buffer, if there's room. */
- if (outStr.available > 0) {
- buffer[outStr.len - outStr.available] = 0x0000;
- }
- /* Release the cloned bundle, if we cloned it. */
- u_locbund_close(&outStr.fBundle);
- /* parsing error */
- if (result < 0) {
- return result;
- }
- /* return # of UChars written */
- return written;
- }
- #endif /* #if !UCONFIG_NO_FORMATTING */
|