1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2014-2020. All rights reserved.
3 * Licensed under Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 * Description: By defining corresponding macro for ANSI string and including "output.inl",
12 * this file generates real underlying function used by printf family API.
13 * Author: lishunda
14 * Create: 2014-02-25
15 */
16
17 #define SECUREC_FORMAT_OUTPUT_INPUT 1
18
19 #ifdef SECUREC_FOR_WCHAR
20 #undef SECUREC_FOR_WCHAR
21 #endif
22
23 #include "secureprintoutput.h"
24 #if SECUREC_WARP_OUTPUT
25 #define SECUREC_FORMAT_FLAG_TABLE_SIZE 128
SecSkipKnownFlags(const char * format)26 SECUREC_INLINE const char *SecSkipKnownFlags(const char *format)
27 {
28 static const unsigned char flagTable[SECUREC_FORMAT_FLAG_TABLE_SIZE] = {
29 /*
30 * Known flag is "0123456789 +-#hlLwZzjqt*I$"
31 */
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00,
35 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
39 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
40 };
41 const char *fmt = format;
42 while (*fmt != '\0') {
43 char fmtChar = *fmt;
44 if ((unsigned char)fmtChar > 0x7f) { /* 0x7f is upper limit of format char value */
45 break;
46 }
47 if (flagTable[(unsigned char)fmtChar] == 0) {
48 break;
49 }
50 ++fmt;
51 }
52 return fmt;
53 }
54
SecFormatContainN(const char * format)55 SECUREC_INLINE int SecFormatContainN(const char *format)
56 {
57 const char *fmt = format;
58 while (*fmt != '\0') {
59 ++fmt;
60 /* Skip normal char */
61 if (*(fmt - 1) != '%') {
62 continue;
63 }
64 /* Meet %% */
65 if (*fmt == '%') {
66 ++fmt; /* Point to the character after the %. Correct handling %%xx */
67 continue;
68 }
69 /* Now parse %..., fmt point to the character after the % */
70 fmt = SecSkipKnownFlags(fmt);
71 if (*fmt == 'n') {
72 return 1;
73 }
74 }
75 return 0;
76 }
77 /*
78 * Multi character formatted output implementation, the count include \0 character, must be greater than zero
79 */
SecVsnprintfImpl(char * string,size_t count,const char * format,va_list argList)80 int SecVsnprintfImpl(char *string, size_t count, const char *format, va_list argList)
81 {
82 int retVal;
83 if (SecFormatContainN(format) != 0) {
84 string[0] = '\0';
85 return -1;
86 }
87 retVal = vsnprintf(string, count, format, argList);
88 if (retVal >= (int)count) { /* The size_t to int is ok, count max is SECUREC_STRING_MAX_LEN */
89 /* The buffer was too small; we return truncation */
90 string[count - 1] = '\0';
91 return SECUREC_PRINTF_TRUNCATE;
92 }
93 if (retVal < 0) {
94 string[0] = '\0'; /* Empty the dest strDest */
95 return -1;
96 }
97 return retVal;
98 }
99 #else
100 #if SECUREC_IN_KERNEL
101 #include <linux/ctype.h>
102 #endif
103
104 #ifndef EOF
105 #define EOF (-1)
106 #endif
107
108 #include "output.inl"
109
110 /*
111 * Multi character formatted output implementation
112 */
SecVsnprintfImpl(char * string,size_t count,const char * format,va_list argList)113 int SecVsnprintfImpl(char *string, size_t count, const char *format, va_list argList)
114 {
115 SecPrintfStream str;
116 int retVal;
117
118 str.count = (int)count; /* The count include \0 character, must be greater than zero */
119 str.cur = string;
120
121 retVal = SecOutputS(&str, format, argList);
122 if (retVal >= 0) {
123 if (SecPutZeroChar(&str) == 0) {
124 return retVal;
125 }
126 }
127 if (str.count < 0) {
128 /* The buffer was too small, then truncate */
129 string[count - 1] = '\0';
130 return SECUREC_PRINTF_TRUNCATE;
131 }
132 string[0] = '\0'; /* Empty the dest string */
133 return -1;
134 }
135
136 /*
137 * Write a wide character
138 */
SecWriteMultiChar(char ch,int num,SecPrintfStream * f,int * pnumwritten)139 SECUREC_INLINE void SecWriteMultiChar(char ch, int num, SecPrintfStream *f, int *pnumwritten)
140 {
141 int count;
142 for (count = num; count > 0; --count) {
143 --f->count; /* f -> count may be negative,indicating insufficient space */
144 if (f->count < 0) {
145 *pnumwritten = -1;
146 return;
147 }
148 *(f->cur) = ch;
149 ++f->cur;
150 *pnumwritten = *pnumwritten + 1;
151 }
152 }
153
154 /*
155 * Write string function, where this function is called, make sure that len is greater than 0
156 */
SecWriteString(const char * string,int len,SecPrintfStream * f,int * pnumwritten)157 SECUREC_INLINE void SecWriteString(const char *string, int len, SecPrintfStream *f, int *pnumwritten)
158 {
159 const char *str = string;
160 int count;
161 for (count = len; count > 0; --count) {
162 --f->count; /* f -> count may be negative,indicating insufficient space */
163 if (f->count < 0) {
164 *pnumwritten = -1;
165 return;
166 }
167 *(f->cur) = *str;
168 ++f->cur;
169 ++str;
170 }
171 *pnumwritten = *pnumwritten + (int)(size_t)(str - string);
172 }
173 #endif
174
175