sprintf.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. // © 2016 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. /*
  4. ******************************************************************************
  5. *
  6. * Copyright (C) 2001-2014, International Business Machines
  7. * Corporation and others. All Rights Reserved.
  8. *
  9. ******************************************************************************
  10. *
  11. * File sprintf.c
  12. *
  13. * Modification History:
  14. *
  15. * Date Name Description
  16. * 02/08/2001 george Creation. Copied from uprintf.c
  17. * 03/27/2002 Mark Schneckloth Many fixes regarding alignment, null termination
  18. * (mschneckloth@atomz.com) and other various problems.
  19. * 08/07/2003 george Reunify printf implementations
  20. *******************************************************************************
  21. */
  22. #include "unicode/utypes.h"
  23. #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_CONVERSION
  24. #include "unicode/ustdio.h"
  25. #include "unicode/ustring.h"
  26. #include "unicode/putil.h"
  27. #include "uprintf.h"
  28. #include "locbund.h"
  29. #include "cmemory.h"
  30. #include <ctype.h>
  31. /* u_minstrncpy copies the minimum number of code units of (count or output->available) */
  32. static int32_t
  33. u_sprintf_write(void *context,
  34. const char16_t *str,
  35. int32_t count)
  36. {
  37. u_localized_print_string *output = (u_localized_print_string *)context;
  38. /* just calculating buffer size */
  39. if (output->str == nullptr) {
  40. return count;
  41. }
  42. int32_t size = ufmt_min(count, output->available);
  43. u_strncpy(output->str + (output->len - output->available), str, size);
  44. output->available -= size;
  45. return size;
  46. }
  47. static int32_t
  48. u_sprintf_pad_and_justify(void *context,
  49. const u_printf_spec_info *info,
  50. const char16_t *result,
  51. int32_t resultLen)
  52. {
  53. u_localized_print_string *output = (u_localized_print_string *)context;
  54. int32_t written = 0;
  55. int32_t lengthOfResult = resultLen;
  56. /* just calculating buffer size */
  57. if (output->str == nullptr &&
  58. info->fWidth != -1 && resultLen < info->fWidth) {
  59. return info->fWidth;
  60. }
  61. resultLen = ufmt_min(resultLen, output->available);
  62. /* pad and justify, if needed */
  63. if(info->fWidth != -1 && resultLen < info->fWidth) {
  64. int32_t paddingLeft = info->fWidth - resultLen;
  65. int32_t outputPos = output->len - output->available;
  66. if (paddingLeft + resultLen > output->available) {
  67. paddingLeft = output->available - resultLen;
  68. if (paddingLeft < 0) {
  69. paddingLeft = 0;
  70. }
  71. /* paddingLeft = output->available - resultLen;*/
  72. }
  73. written += paddingLeft;
  74. /* left justify */
  75. if(info->fLeft) {
  76. written += u_sprintf_write(output, result, resultLen);
  77. u_memset(&output->str[outputPos + resultLen], info->fPadChar, paddingLeft);
  78. output->available -= paddingLeft;
  79. }
  80. /* right justify */
  81. else {
  82. u_memset(&output->str[outputPos], info->fPadChar, paddingLeft);
  83. output->available -= paddingLeft;
  84. written += u_sprintf_write(output, result, resultLen);
  85. }
  86. }
  87. /* just write the formatted output */
  88. else {
  89. written = u_sprintf_write(output, result, resultLen);
  90. }
  91. if (written >= 0 && lengthOfResult > written) {
  92. return lengthOfResult;
  93. }
  94. return written;
  95. }
  96. U_CAPI int32_t U_EXPORT2
  97. u_sprintf(char16_t *buffer,
  98. const char *patternSpecification,
  99. ... )
  100. {
  101. va_list ap;
  102. int32_t written;
  103. va_start(ap, patternSpecification);
  104. written = u_vsnprintf(buffer, INT32_MAX, patternSpecification, ap);
  105. va_end(ap);
  106. return written;
  107. }
  108. U_CAPI int32_t U_EXPORT2
  109. u_sprintf_u(char16_t *buffer,
  110. const char16_t *patternSpecification,
  111. ... )
  112. {
  113. va_list ap;
  114. int32_t written;
  115. va_start(ap, patternSpecification);
  116. written = u_vsnprintf_u(buffer, INT32_MAX, patternSpecification, ap);
  117. va_end(ap);
  118. return written;
  119. }
  120. U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
  121. u_vsprintf(char16_t *buffer,
  122. const char *patternSpecification,
  123. va_list ap)
  124. {
  125. return u_vsnprintf(buffer, INT32_MAX, patternSpecification, ap);
  126. }
  127. U_CAPI int32_t U_EXPORT2
  128. u_snprintf(char16_t *buffer,
  129. int32_t count,
  130. const char *patternSpecification,
  131. ... )
  132. {
  133. va_list ap;
  134. int32_t written;
  135. va_start(ap, patternSpecification);
  136. written = u_vsnprintf(buffer, count, patternSpecification, ap);
  137. va_end(ap);
  138. return written;
  139. }
  140. U_CAPI int32_t U_EXPORT2
  141. u_snprintf_u(char16_t *buffer,
  142. int32_t count,
  143. const char16_t *patternSpecification,
  144. ... )
  145. {
  146. va_list ap;
  147. int32_t written;
  148. va_start(ap, patternSpecification);
  149. written = u_vsnprintf_u(buffer, count, patternSpecification, ap);
  150. va_end(ap);
  151. return written;
  152. }
  153. U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
  154. u_vsnprintf(char16_t *buffer,
  155. int32_t count,
  156. const char *patternSpecification,
  157. va_list ap)
  158. {
  159. int32_t written;
  160. char16_t *pattern;
  161. char16_t patBuffer[UFMT_DEFAULT_BUFFER_SIZE];
  162. int32_t size = (int32_t)strlen(patternSpecification) + 1;
  163. /* convert from the default codepage to Unicode */
  164. if (size >= (int32_t)MAX_UCHAR_BUFFER_SIZE(patBuffer)) {
  165. pattern = (char16_t *)uprv_malloc(size * sizeof(char16_t));
  166. if (pattern == nullptr) {
  167. return 0;
  168. }
  169. }
  170. else {
  171. pattern = patBuffer;
  172. }
  173. u_charsToUChars(patternSpecification, pattern, size);
  174. /* do the work */
  175. written = u_vsnprintf_u(buffer, count, pattern, ap);
  176. /* clean up */
  177. if (pattern != patBuffer) {
  178. uprv_free(pattern);
  179. }
  180. return written;
  181. }
  182. U_CAPI int32_t U_EXPORT2
  183. u_vsprintf_u(char16_t *buffer,
  184. const char16_t *patternSpecification,
  185. va_list ap)
  186. {
  187. return u_vsnprintf_u(buffer, INT32_MAX, patternSpecification, ap);
  188. }
  189. static const u_printf_stream_handler g_sprintf_stream_handler = {
  190. u_sprintf_write,
  191. u_sprintf_pad_and_justify
  192. };
  193. U_CAPI int32_t U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
  194. u_vsnprintf_u(char16_t *buffer,
  195. int32_t count,
  196. const char16_t *patternSpecification,
  197. va_list ap)
  198. {
  199. int32_t written = 0; /* haven't written anything yet */
  200. int32_t result = 0; /* test the return value of u_printf_parse */
  201. u_localized_print_string outStr;
  202. if (count < 0) {
  203. count = INT32_MAX;
  204. }
  205. outStr.str = buffer;
  206. outStr.len = count;
  207. outStr.available = count;
  208. if (u_locbund_init(&outStr.fBundle, "en_US_POSIX") == nullptr) {
  209. return 0;
  210. }
  211. /* parse and print the whole format string */
  212. result = u_printf_parse(&g_sprintf_stream_handler, patternSpecification, &outStr, &outStr, &outStr.fBundle, &written, ap);
  213. /* Terminate the buffer, if there's room. */
  214. if (outStr.available > 0) {
  215. buffer[outStr.len - outStr.available] = 0x0000;
  216. }
  217. /* Release the cloned bundle, if we cloned it. */
  218. u_locbund_close(&outStr.fBundle);
  219. /* parsing error */
  220. if (result < 0) {
  221. return result;
  222. }
  223. /* return # of UChars written */
  224. return written;
  225. }
  226. #endif /* #if !UCONFIG_NO_FORMATTING */