@@ -20,292 +20,11 @@ limitations under the License.
20
20
// more code.
21
21
22
22
#include " tensorflow/lite/micro/micro_string.h"
23
-
24
- #include < cstdarg>
25
- #include < cstdint>
26
- #include < cstring>
27
-
28
- namespace {
29
-
30
- // Int formats can need up to 10 bytes for the value plus a single byte for the
31
- // sign.
32
- constexpr int kMaxIntCharsNeeded = 10 + 1 ;
33
- // Hex formats can need up to 8 bytes for the value plus two bytes for the "0x".
34
- constexpr int kMaxHexCharsNeeded = 8 + 2 ;
35
-
36
- // Float formats can need up to 7 bytes for the fraction plus 3 bytes for "x2^"
37
- // plus 3 bytes for the exponent and a single sign bit.
38
- constexpr float kMaxFloatCharsNeeded = 7 + 3 + 3 + 1 ;
39
-
40
- // All input buffers to the number conversion functions must be this long.
41
- const int kFastToBufferSize = 48 ;
42
-
43
- // Reverses a zero-terminated string in-place.
44
- char * ReverseStringInPlace (char * start, char * end) {
45
- char * p1 = start;
46
- char * p2 = end - 1 ;
47
- while (p1 < p2) {
48
- char tmp = *p1;
49
- *p1++ = *p2;
50
- *p2-- = tmp;
51
- }
52
- return start;
53
- }
54
-
55
- // Appends a string to a string, in-place. You need to pass in the maximum
56
- // string length as the second argument.
57
- char * StrCatStr (char * main, int main_max_length, const char * to_append) {
58
- char * current = main;
59
- while (*current != 0 ) {
60
- ++current;
61
- }
62
- char * current_end = main + (main_max_length - 1 );
63
- while ((*to_append != 0 ) && (current < current_end)) {
64
- *current = *to_append;
65
- ++current;
66
- ++to_append;
67
- }
68
- *current = 0 ;
69
- return current;
70
- }
71
-
72
- // Populates the provided buffer with an ASCII representation of the number.
73
- char * FastUInt32ToBufferLeft (uint32_t i, char * buffer, int base) {
74
- char * start = buffer;
75
- do {
76
- int32_t digit = i % base;
77
- char character;
78
- if (digit < 10 ) {
79
- character = ' 0' + digit;
80
- } else {
81
- character = ' a' + (digit - 10 );
82
- }
83
- *buffer++ = character;
84
- i /= base;
85
- } while (i > 0 );
86
- *buffer = 0 ;
87
- ReverseStringInPlace (start, buffer);
88
- return buffer;
89
- }
90
-
91
- // Populates the provided buffer with an ASCII representation of the number.
92
- char * FastInt32ToBufferLeft (int32_t i, char * buffer) {
93
- uint32_t u = i;
94
- if (i < 0 ) {
95
- *buffer++ = ' -' ;
96
- u = -u;
97
- }
98
- return FastUInt32ToBufferLeft (u, buffer, 10 );
99
- }
100
-
101
- // Converts a number to a string and appends it to another.
102
- char * StrCatInt32 (char * main, int main_max_length, int32_t number) {
103
- char number_string[kFastToBufferSize ];
104
- FastInt32ToBufferLeft (number, number_string);
105
- return StrCatStr (main, main_max_length, number_string);
106
- }
107
-
108
- // Converts a number to a string and appends it to another.
109
- char * StrCatUInt32 (char * main, int main_max_length, uint32_t number, int base) {
110
- char number_string[kFastToBufferSize ];
111
- FastUInt32ToBufferLeft (number, number_string, base);
112
- return StrCatStr (main, main_max_length, number_string);
113
- }
114
-
115
- // Populates the provided buffer with ASCII representation of the float number.
116
- // Avoids the use of any floating point instructions (since these aren't
117
- // supported on many microcontrollers) and as a consequence prints values with
118
- // power-of-two exponents.
119
- char * FastFloatToBufferLeft (float f, char * buffer) {
120
- char * current = buffer;
121
- char * current_end = buffer + (kFastToBufferSize - 1 );
122
- // Access the bit fields of the floating point value to avoid requiring any
123
- // float instructions. These constants are derived from IEEE 754.
124
- const uint32_t sign_mask = 0x80000000 ;
125
- const uint32_t exponent_mask = 0x7f800000 ;
126
- const int32_t exponent_shift = 23 ;
127
- const int32_t exponent_bias = 127 ;
128
- const uint32_t fraction_mask = 0x007fffff ;
129
- uint32_t u;
130
- memcpy (&u, &f, sizeof (int32_t ));
131
- const int32_t exponent =
132
- ((u & exponent_mask) >> exponent_shift) - exponent_bias;
133
- const uint32_t fraction = (u & fraction_mask);
134
- // Expect ~0x2B1B9D3 for fraction.
135
- if (u & sign_mask) {
136
- *current = ' -' ;
137
- current += 1 ;
138
- }
139
- *current = 0 ;
140
- // These are special cases for infinities and not-a-numbers.
141
- if (exponent == 128 ) {
142
- if (fraction == 0 ) {
143
- current = StrCatStr (current, (current_end - current), " Inf" );
144
- return current;
145
- } else {
146
- current = StrCatStr (current, (current_end - current), " NaN" );
147
- return current;
148
- }
149
- }
150
- // 0x007fffff (8388607) represents 0.99... for the fraction, so to print the
151
- // correct decimal digits we need to scale our value before passing it to the
152
- // conversion function. This scale should be 10000000/8388608 = 1.1920928955.
153
- // We can approximate this using multiply-adds and right-shifts using the
154
- // values in this array. The 1. portion of the number string is printed out
155
- // in a fixed way before the fraction, below.
156
- const int32_t scale_shifts_size = 13 ;
157
- const int8_t scale_shifts[13 ] = {3 , 4 , 8 , 11 , 13 , 14 , 17 ,
158
- 18 , 19 , 20 , 21 , 22 , 23 };
159
- uint32_t scaled_fraction = fraction;
160
- for (int i = 0 ; i < scale_shifts_size; ++i) {
161
- scaled_fraction += (fraction >> scale_shifts[i]);
162
- }
163
- *current = ' 1' ;
164
- current += 1 ;
165
- *current = ' .' ;
166
- current += 1 ;
167
- *current = 0 ;
168
-
169
- // Prepend leading zeros to fill in all 7 bytes of the fraction. Truncate
170
- // zeros off the end of the fraction. Every fractional value takes 7 bytes.
171
- // For example, 2500 would be written into the buffer as 0002500 since it
172
- // represents .00025.
173
- constexpr int kMaxFractionalDigits = 7 ;
174
-
175
- // Abort early if there is not enough space in the buffer.
176
- if (current_end - current <= kMaxFractionalDigits ) {
177
- return current;
178
- }
179
-
180
- // Pre-fill buffer with zeros to ensure zero-truncation works properly.
181
- for (int i = 1 ; i < kMaxFractionalDigits ; i++) {
182
- *(current + i) = ' 0' ;
183
- }
184
-
185
- // Track how large the fraction is to add leading zeros.
186
- char * previous = current;
187
- current = StrCatUInt32 (current, (current_end - current), scaled_fraction, 10 );
188
- int fraction_digits = current - previous;
189
- int leading_zeros = kMaxFractionalDigits - fraction_digits;
190
-
191
- // Overwrite the null terminator from StrCatUInt32 to ensure zero-trunctaion
192
- // works properly.
193
- *current = ' 0' ;
194
-
195
- // Shift fraction values and prepend zeros if necessary.
196
- if (leading_zeros != 0 ) {
197
- for (int i = 0 ; i < fraction_digits; i++) {
198
- current--;
199
- *(current + leading_zeros) = *current;
200
- *current = ' 0' ;
201
- }
202
- current += kMaxFractionalDigits ;
203
- }
204
-
205
- // Truncate trailing zeros for cleaner logs. Ensure we leave at least one
206
- // fractional character for the case when scaled_fraction is 0.
207
- while (*(current - 1 ) == ' 0' && (current - 1 ) > previous) {
208
- current--;
209
- }
210
- *current = 0 ;
211
- current = StrCatStr (current, (current_end - current), " *2^" );
212
- current = StrCatInt32 (current, (current_end - current), exponent);
213
- return current;
214
- }
215
-
216
- int FormatInt32 (char * output, int32_t i) {
217
- return static_cast <int >(FastInt32ToBufferLeft (i, output) - output);
218
- }
219
-
220
- int FormatUInt32 (char * output, uint32_t i) {
221
- return static_cast <int >(FastUInt32ToBufferLeft (i, output, 10 ) - output);
222
- }
223
-
224
- int FormatHex (char * output, uint32_t i) {
225
- return static_cast <int >(FastUInt32ToBufferLeft (i, output, 16 ) - output);
226
- }
227
-
228
- int FormatFloat (char * output, float i) {
229
- return static_cast <int >(FastFloatToBufferLeft (i, output) - output);
230
- }
231
-
232
- } // namespace
23
+ #include < rtthread.h>
233
24
234
25
extern " C" int MicroVsnprintf (char * output, int len, const char * format,
235
26
va_list args) {
236
- int output_index = 0 ;
237
- const char * current = format;
238
- // One extra character must be left for the null terminator.
239
- const int usable_length = len - 1 ;
240
- while (*current != ' \0 ' && output_index < usable_length) {
241
- if (*current == ' %' ) {
242
- current++;
243
- switch (*current) {
244
- case ' d' :
245
- // Cut off log message if format could exceed log buffer length.
246
- if (usable_length - output_index < kMaxIntCharsNeeded ) {
247
- output[output_index++] = ' \0 ' ;
248
- return output_index;
249
- }
250
- output_index +=
251
- FormatInt32 (&output[output_index], va_arg (args, int32_t ));
252
- current++;
253
- break ;
254
- case ' u' :
255
- if (usable_length - output_index < kMaxIntCharsNeeded ) {
256
- output[output_index++] = ' \0 ' ;
257
- return output_index;
258
- }
259
- output_index +=
260
- FormatUInt32 (&output[output_index], va_arg (args, uint32_t ));
261
- current++;
262
- break ;
263
- case ' x' :
264
- if (usable_length - output_index < kMaxHexCharsNeeded ) {
265
- output[output_index++] = ' \0 ' ;
266
- return output_index;
267
- }
268
- output[output_index++] = ' 0' ;
269
- output[output_index++] = ' x' ;
270
- output_index +=
271
- FormatHex (&output[output_index], va_arg (args, uint32_t ));
272
- current++;
273
- break ;
274
- case ' f' :
275
- if (usable_length - output_index < kMaxFloatCharsNeeded ) {
276
- output[output_index++] = ' \0 ' ;
277
- return output_index;
278
- }
279
- output_index +=
280
- FormatFloat (&output[output_index], va_arg (args, double ));
281
- current++;
282
- break ;
283
- case ' %' :
284
- output[output_index++] = *current++;
285
- break ;
286
- case ' c' :
287
- if (usable_length - output_index < 1 ) {
288
- output[output_index++] = ' \0 ' ;
289
- return output_index;
290
- }
291
- output[output_index++] = va_arg (args, int32_t );
292
- current++;
293
- break ;
294
- case ' s' :
295
- char * string = va_arg (args, char *);
296
- int string_idx = 0 ;
297
- while (string_idx + output_index < usable_length &&
298
- string[string_idx] != ' \0 ' ) {
299
- output[output_index++] = string[string_idx++];
300
- }
301
- current++;
302
- }
303
- } else {
304
- output[output_index++] = *current++;
305
- }
306
- }
307
- output[output_index++] = ' \0 ' ;
308
- return output_index;
27
+ return rt_vsnprintf (output, len, format, args);
309
28
}
310
29
311
30
extern " C" int MicroSnprintf (char * output, int len, const char * format, ...) {
0 commit comments