/src/S2OPC/src/Common/helpers/sopc_buffer.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Licensed to Systerel under one or more contributor license |
3 | | * agreements. See the NOTICE file distributed with this work |
4 | | * for additional information regarding copyright ownership. |
5 | | * Systerel licenses this file to you under the Apache |
6 | | * License, Version 2.0 (the "License"); you may not use this |
7 | | * file except in compliance with the License. You may obtain |
8 | | * a copy of the License at |
9 | | * |
10 | | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | | * |
12 | | * Unless required by applicable law or agreed to in writing, |
13 | | * software distributed under the License is distributed on an |
14 | | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
15 | | * KIND, either express or implied. See the License for the |
16 | | * specific language governing permissions and limitations |
17 | | * under the License. |
18 | | */ |
19 | | |
20 | | #include <math.h> |
21 | | #include <stdio.h> |
22 | | #include <string.h> |
23 | | |
24 | | #include <inttypes.h> |
25 | | #include "sopc_assert.h" |
26 | | #include "sopc_buffer.h" |
27 | | #include "sopc_common_constants.h" |
28 | | #include "sopc_macros.h" |
29 | | #include "sopc_mem_alloc.h" |
30 | | |
31 | | /* 2^32 = 4294967296 maximum number you could represent plus \0 at the end */ |
32 | 0 | #define SOPC_MAX_LENGTH_UINT32_TO_STRING 11 |
33 | | |
34 | | /* 2^31 = 2147483648 maximum number you could represent plus \0 at the end plus '-'*/ |
35 | 0 | #define SOPC_MAX_LENGTH_INT32_TO_STRING 12 |
36 | | |
37 | | /* A MINIMUM of 4 is required ! (or problems such as infinite management appear.) */ |
38 | 0 | #define SOPC_PRECISION_PRINTING_FLOAT_NUMBERS 10 |
39 | | |
40 | | static SOPC_ReturnStatus SOPC_Buffer_Init(SOPC_Buffer* buffer, uint32_t initial_size, uint32_t maximum_size) |
41 | 12.3k | { |
42 | 12.3k | if (buffer == NULL || initial_size <= 0 || initial_size > maximum_size) |
43 | 0 | { |
44 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
45 | 0 | } |
46 | | |
47 | 12.3k | buffer->data = SOPC_Calloc((size_t) initial_size, sizeof(uint8_t)); |
48 | 12.3k | if (NULL == buffer->data) |
49 | 0 | { |
50 | 0 | return SOPC_STATUS_OUT_OF_MEMORY; |
51 | 0 | } |
52 | | |
53 | 12.3k | buffer->position = 0; |
54 | 12.3k | buffer->length = 0; |
55 | 12.3k | buffer->initial_size = initial_size; |
56 | 12.3k | buffer->current_size = initial_size; |
57 | 12.3k | buffer->maximum_size = maximum_size; |
58 | | |
59 | 12.3k | return SOPC_STATUS_OK; |
60 | 12.3k | } |
61 | | |
62 | | SOPC_Buffer* SOPC_Buffer_Create(uint32_t size) |
63 | 4.62k | { |
64 | 4.62k | SOPC_Buffer* buf = NULL; |
65 | 4.62k | if (size > 0) |
66 | 4.62k | { |
67 | 4.62k | buf = SOPC_Malloc(sizeof(SOPC_Buffer)); |
68 | 4.62k | if (buf != NULL) |
69 | 4.62k | { |
70 | 4.62k | SOPC_ReturnStatus status = SOPC_Buffer_Init(buf, size, size); |
71 | 4.62k | if (status != SOPC_STATUS_OK) |
72 | 0 | { |
73 | 0 | SOPC_Buffer_Delete(buf); |
74 | 0 | buf = NULL; |
75 | 0 | } |
76 | 4.62k | } |
77 | 4.62k | } |
78 | 4.62k | return buf; |
79 | 4.62k | } |
80 | | |
81 | | SOPC_Buffer* SOPC_Buffer_CreateResizable(uint32_t initial_size, uint32_t maximum_size) |
82 | 7.69k | { |
83 | 7.69k | SOPC_Buffer* buf = NULL; |
84 | 7.69k | if (initial_size > 0) |
85 | 7.69k | { |
86 | 7.69k | buf = SOPC_Calloc(1, sizeof(SOPC_Buffer)); |
87 | 7.69k | if (buf != NULL) |
88 | 7.69k | { |
89 | 7.69k | SOPC_ReturnStatus status = SOPC_Buffer_Init(buf, initial_size, maximum_size); |
90 | 7.69k | if (status != SOPC_STATUS_OK) |
91 | 0 | { |
92 | 0 | SOPC_Buffer_Delete(buf); |
93 | 0 | buf = NULL; |
94 | 0 | } |
95 | 7.69k | } |
96 | 7.69k | } |
97 | 7.69k | return buf; |
98 | 7.69k | } |
99 | | |
100 | | SOPC_Buffer* SOPC_Buffer_Attach(uint8_t* data, uint32_t size) |
101 | 6.54k | { |
102 | 6.54k | SOPC_Buffer* b = SOPC_Calloc(1, sizeof(SOPC_Buffer)); |
103 | | |
104 | 6.54k | if (b == NULL) |
105 | 0 | { |
106 | 0 | return NULL; |
107 | 0 | } |
108 | | |
109 | 6.54k | b->data = data; |
110 | 6.54k | b->length = size; |
111 | 6.54k | b->initial_size = size; |
112 | 6.54k | b->current_size = size; |
113 | 6.54k | b->maximum_size = size; |
114 | | |
115 | 6.54k | return b; |
116 | 6.54k | } |
117 | | |
118 | | void SOPC_Buffer_Clear(SOPC_Buffer* buffer) |
119 | 12.3k | { |
120 | 12.3k | if (buffer != NULL) |
121 | 12.3k | { |
122 | 12.3k | if (buffer->data != NULL) |
123 | 12.3k | { |
124 | 12.3k | SOPC_Free(buffer->data); |
125 | 12.3k | buffer->data = NULL; |
126 | 12.3k | } |
127 | 12.3k | } |
128 | 12.3k | } |
129 | | |
130 | | void SOPC_Buffer_Delete(SOPC_Buffer* buffer) |
131 | 16.9k | { |
132 | 16.9k | if (buffer != NULL) |
133 | 12.3k | { |
134 | 12.3k | SOPC_Buffer_Clear(buffer); |
135 | 12.3k | SOPC_Free(buffer); |
136 | 12.3k | } |
137 | 16.9k | } |
138 | | |
139 | | void SOPC_Buffer_Reset(SOPC_Buffer* buffer) |
140 | 0 | { |
141 | 0 | if (buffer != NULL && buffer->data != NULL) |
142 | 0 | { |
143 | 0 | buffer->position = 0; |
144 | 0 | buffer->length = 0; |
145 | 0 | memset(buffer->data, 0, buffer->current_size); |
146 | 0 | } |
147 | 0 | } |
148 | | |
149 | | SOPC_ReturnStatus SOPC_Buffer_ResetAfterPosition(SOPC_Buffer* buffer, uint32_t position) |
150 | 0 | { |
151 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_INVALID_PARAMETERS; |
152 | 0 | if (buffer != NULL && buffer->data != NULL && position <= buffer->length) |
153 | 0 | { |
154 | 0 | status = SOPC_STATUS_OK; |
155 | 0 | buffer->position = position; |
156 | 0 | buffer->length = position; |
157 | 0 | memset(&(buffer->data[buffer->position]), 0, buffer->current_size - buffer->position); |
158 | 0 | } |
159 | 0 | return status; |
160 | 0 | } |
161 | | |
162 | | SOPC_ReturnStatus SOPC_Buffer_GetPosition(SOPC_Buffer* buffer, uint32_t* position) |
163 | 7.34k | { |
164 | 7.34k | SOPC_ReturnStatus status = SOPC_STATUS_INVALID_PARAMETERS; |
165 | 7.34k | if (NULL != buffer && NULL != position) |
166 | 7.34k | { |
167 | 7.34k | status = SOPC_STATUS_OK; |
168 | 7.34k | *position = buffer->position; |
169 | 7.34k | } |
170 | | |
171 | 7.34k | return status; |
172 | 7.34k | } |
173 | | |
174 | | SOPC_ReturnStatus SOPC_Buffer_SetPosition(SOPC_Buffer* buffer, uint32_t position) |
175 | 292k | { |
176 | 292k | SOPC_ReturnStatus status = SOPC_STATUS_INVALID_PARAMETERS; |
177 | 292k | if (buffer != NULL && buffer->data != NULL && buffer->length >= position) |
178 | 292k | { |
179 | 292k | status = SOPC_STATUS_OK; |
180 | 292k | buffer->position = position; |
181 | 292k | } |
182 | 292k | return status; |
183 | 292k | } |
184 | | |
185 | | SOPC_ReturnStatus SOPC_Buffer_SetDataLength(SOPC_Buffer* buffer, uint32_t length) |
186 | 0 | { |
187 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_INVALID_PARAMETERS; |
188 | 0 | uint8_t* data = NULL; |
189 | 0 | if (buffer != NULL && buffer->data != NULL && buffer->current_size >= length && buffer->position <= length) |
190 | 0 | { |
191 | 0 | status = SOPC_STATUS_OK; |
192 | 0 | if (buffer->length > length) |
193 | 0 | { |
194 | 0 | data = &(buffer->data[length]); |
195 | | // Reset unused bytes to 0 |
196 | 0 | memset(data, 0, buffer->length - length); |
197 | 0 | } |
198 | 0 | buffer->length = length; |
199 | 0 | } |
200 | 0 | return status; |
201 | 0 | } |
202 | | |
203 | | /** |
204 | | * \brief Check the size of buffer can contains \p totalNbBytes. |
205 | | * If it does not and the buffer is resizable: |
206 | | * - (if \p exactResize == false) Compute new size to be the first multiple of initial_size |
207 | | * that contains \p totalNbBytes or maximum_size if greater than maximum_size |
208 | | * - Resize the buffer to the new size |
209 | | * |
210 | | * \return true if buffer is large enough to contains \p totalNbBytes (with or without resize operation), |
211 | | * false otherwise |
212 | | */ |
213 | | static bool SOPC_Buffer_CheckSizeAndResize(SOPC_Buffer* buffer, uint32_t totalNbBytes, bool exactResize) |
214 | 14.9M | { |
215 | 14.9M | SOPC_ASSERT(buffer != NULL); |
216 | 14.9M | if (totalNbBytes <= buffer->current_size) |
217 | 14.9M | { |
218 | | // Enough bytes available in current buffer allocated bytes |
219 | 14.9M | return true; |
220 | 14.9M | } |
221 | 197 | else if (totalNbBytes <= buffer->maximum_size) |
222 | 197 | { |
223 | | // Enough bytes available if buffer is resized |
224 | 197 | uint8_t* newData = NULL; |
225 | 197 | uint32_t newSize = 0; |
226 | 197 | if (exactResize) |
227 | 0 | { |
228 | | // Use the exact number of bytes necessary |
229 | 0 | newSize = totalNbBytes; |
230 | 0 | } |
231 | 197 | else |
232 | 197 | { |
233 | | // Search the first multiple of initial_size which contains totalNbBytes |
234 | 197 | uint32_t requiredSteps = totalNbBytes / buffer->initial_size; |
235 | 197 | if (totalNbBytes % buffer->initial_size != 0) |
236 | 196 | { |
237 | 196 | requiredSteps++; |
238 | 196 | } |
239 | 197 | if (requiredSteps > buffer->maximum_size / buffer->initial_size) |
240 | 0 | { |
241 | | // The first multiple found is greater than maximum_size => use maximum_size |
242 | 0 | newSize = buffer->maximum_size; |
243 | 0 | } |
244 | 197 | else |
245 | 197 | { |
246 | | // Resize to the multiple of initial_size which contains totalNbBytes |
247 | 197 | newSize = requiredSteps * buffer->initial_size; |
248 | 197 | } |
249 | 197 | } |
250 | | // Resize buffer with computed size |
251 | 197 | newData = SOPC_Realloc(buffer->data, (size_t) buffer->current_size, (size_t) newSize); |
252 | 197 | if (NULL != newData) |
253 | 197 | { |
254 | 197 | buffer->data = newData; |
255 | 197 | buffer->current_size = newSize; |
256 | | |
257 | 197 | return true; |
258 | 197 | } |
259 | 197 | } |
260 | 0 | return false; |
261 | 14.9M | } |
262 | | |
263 | | SOPC_ReturnStatus SOPC_Buffer_Write(SOPC_Buffer* buffer, const uint8_t* data_src, uint32_t count) |
264 | 14.9M | { |
265 | 14.9M | SOPC_ReturnStatus status = SOPC_STATUS_NOK; |
266 | 14.9M | if (NULL == data_src || NULL == buffer || NULL == buffer->data) |
267 | 0 | { |
268 | 0 | status = SOPC_STATUS_INVALID_PARAMETERS; |
269 | 0 | } |
270 | 14.9M | else |
271 | 14.9M | { |
272 | 14.9M | if (SOPC_Buffer_CheckSizeAndResize(buffer, buffer->position + count, false)) |
273 | 14.9M | { |
274 | 14.9M | if (memcpy(&(buffer->data[buffer->position]), data_src, count) == &(buffer->data[buffer->position])) |
275 | 14.9M | { |
276 | 14.9M | buffer->position = buffer->position + count; |
277 | | // In case we write in existing buffer position: does not change length |
278 | 14.9M | if (buffer->position > buffer->length) |
279 | 14.8M | { |
280 | 14.8M | buffer->length = buffer->position; |
281 | 14.8M | } |
282 | 14.9M | status = SOPC_STATUS_OK; |
283 | 14.9M | } |
284 | 0 | else |
285 | 0 | { |
286 | 0 | status = SOPC_STATUS_INVALID_STATE; |
287 | 0 | } |
288 | 14.9M | } |
289 | 0 | else |
290 | 0 | { |
291 | 0 | status = SOPC_STATUS_OUT_OF_MEMORY; |
292 | 0 | } |
293 | 14.9M | } |
294 | 14.9M | return status; |
295 | 14.9M | } |
296 | | |
297 | | SOPC_ReturnStatus SOPC_Buffer_Read(uint8_t* data_dest, SOPC_Buffer* buffer, uint32_t count) |
298 | 21.7M | { |
299 | 21.7M | SOPC_ReturnStatus status = SOPC_STATUS_INVALID_PARAMETERS; |
300 | 21.7M | if (buffer != NULL && buffer->data != NULL) |
301 | 21.7M | { |
302 | 21.7M | if (buffer->position + count <= buffer->length) |
303 | 21.7M | { |
304 | 21.7M | if (NULL == data_dest || memcpy(data_dest, &(buffer->data[buffer->position]), count) == data_dest) |
305 | 21.7M | { |
306 | 21.7M | buffer->position = buffer->position + count; |
307 | 21.7M | status = SOPC_STATUS_OK; |
308 | 21.7M | } |
309 | 0 | else |
310 | 0 | { |
311 | 0 | status = SOPC_STATUS_INVALID_STATE; |
312 | 0 | } |
313 | 21.7M | } |
314 | 9.59k | else |
315 | 9.59k | { |
316 | 9.59k | status = SOPC_STATUS_OUT_OF_MEMORY; |
317 | 9.59k | } |
318 | 21.7M | } |
319 | 21.7M | return status; |
320 | 21.7M | } |
321 | | |
322 | | SOPC_ReturnStatus SOPC_Buffer_CopyWithLength(SOPC_Buffer* dest, SOPC_Buffer* src, uint32_t limitedLength) |
323 | 0 | { |
324 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_INVALID_PARAMETERS; |
325 | 0 | if (dest != NULL && src != NULL && dest->data != NULL && src->data != NULL && src->length >= limitedLength && |
326 | 0 | src->position <= limitedLength) |
327 | 0 | { |
328 | 0 | SOPC_ASSERT(src->position <= src->length); |
329 | | |
330 | 0 | if (SOPC_Buffer_CheckSizeAndResize(dest, limitedLength, true)) |
331 | 0 | { |
332 | 0 | memcpy(dest->data, src->data, limitedLength); |
333 | 0 | status = SOPC_Buffer_SetPosition(dest, 0); |
334 | |
|
335 | 0 | if (SOPC_STATUS_OK == status) |
336 | 0 | { |
337 | 0 | status = SOPC_Buffer_SetDataLength(dest, limitedLength); |
338 | 0 | } |
339 | 0 | if (SOPC_STATUS_OK == status) |
340 | 0 | { |
341 | 0 | status = SOPC_Buffer_SetPosition(dest, src->position); |
342 | 0 | } |
343 | 0 | } |
344 | 0 | else |
345 | 0 | { |
346 | 0 | status = SOPC_STATUS_OUT_OF_MEMORY; |
347 | 0 | } |
348 | 0 | } |
349 | 0 | return status; |
350 | 0 | } |
351 | | |
352 | | SOPC_ReturnStatus SOPC_Buffer_Copy(SOPC_Buffer* dest, SOPC_Buffer* src) |
353 | 0 | { |
354 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_INVALID_PARAMETERS; |
355 | 0 | if (src != NULL) |
356 | 0 | { |
357 | 0 | status = SOPC_Buffer_CopyWithLength(dest, src, src->length); |
358 | 0 | } |
359 | |
|
360 | 0 | return status; |
361 | 0 | } |
362 | | |
363 | | uint32_t SOPC_Buffer_Remaining(SOPC_Buffer* buffer) |
364 | 27.8k | { |
365 | 27.8k | SOPC_ASSERT(buffer != NULL); |
366 | 27.8k | return buffer->length - buffer->position; |
367 | 27.8k | } |
368 | | |
369 | | int64_t SOPC_Buffer_ReadFrom(SOPC_Buffer* buffer, SOPC_Buffer* src, uint32_t n) |
370 | 7.90k | { |
371 | 7.90k | if (NULL == buffer || NULL == src || (buffer->current_size - buffer->length) < n) |
372 | 0 | { |
373 | 0 | return -1; |
374 | 0 | } |
375 | | |
376 | 7.90k | uint32_t available = src->length - src->position; |
377 | | |
378 | 7.90k | if (available < n) |
379 | 104 | { |
380 | 104 | n = available; |
381 | 104 | } |
382 | | |
383 | 7.90k | memcpy(buffer->data + buffer->length, src->data + src->position, n * sizeof(uint8_t)); |
384 | 7.90k | buffer->length += n; |
385 | 7.90k | src->position += n; |
386 | 7.90k | return (int64_t) n; |
387 | 7.90k | } |
388 | | |
389 | | #if SOPC_HAS_FILESYSTEM |
390 | | static long get_file_size(FILE* fd) |
391 | 0 | { |
392 | 0 | if (fseek(fd, 0, SEEK_END) == -1) |
393 | 0 | { |
394 | 0 | return -1; |
395 | 0 | } |
396 | | |
397 | 0 | long sz = ftell(fd); |
398 | |
|
399 | 0 | if (sz == -1) |
400 | 0 | { |
401 | 0 | return -1; |
402 | 0 | } |
403 | | |
404 | 0 | if (fseek(fd, 0, SEEK_SET) == -1) |
405 | 0 | { |
406 | 0 | return -1; |
407 | 0 | } |
408 | | |
409 | 0 | return sz; |
410 | 0 | } |
411 | | |
412 | | static bool read_file(FILE* fd, char* data, size_t len) |
413 | 0 | { |
414 | 0 | size_t read = 0; |
415 | |
|
416 | 0 | while (true) |
417 | 0 | { |
418 | 0 | size_t res = fread(data + read, sizeof(char), len - read, fd); |
419 | |
|
420 | 0 | if (res == 0) |
421 | 0 | { |
422 | 0 | break; |
423 | 0 | } |
424 | | |
425 | 0 | read += res; |
426 | 0 | } |
427 | |
|
428 | 0 | return ferror(fd) == 0; |
429 | 0 | } |
430 | | |
431 | | SOPC_ReturnStatus SOPC_Buffer_ReadFile(const char* path, SOPC_Buffer** buf) |
432 | 0 | { |
433 | 0 | FILE* fd = fopen(path, "rb"); |
434 | |
|
435 | 0 | if (fd == NULL) |
436 | 0 | { |
437 | 0 | return SOPC_STATUS_NOK; |
438 | 0 | } |
439 | | |
440 | 0 | long size = get_file_size(fd); |
441 | |
|
442 | 0 | if ((-1 == size || 0 == size || |
443 | 0 | ((unsigned long) size) > UINT32_MAX)) // check future cast into uint32_t and size_t allowed |
444 | 0 | { |
445 | 0 | fclose(fd); |
446 | 0 | return SOPC_STATUS_NOK; |
447 | 0 | } |
448 | | |
449 | 0 | SOPC_Buffer* buffer = SOPC_Buffer_Create((uint32_t) size); |
450 | |
|
451 | 0 | if (buffer == NULL) |
452 | 0 | { |
453 | 0 | fclose(fd); |
454 | 0 | return SOPC_STATUS_OUT_OF_MEMORY; |
455 | 0 | } |
456 | | |
457 | 0 | bool ok = read_file(fd, (char*) buffer->data, (size_t) size); |
458 | 0 | fclose(fd); |
459 | |
|
460 | 0 | if (!ok) |
461 | 0 | { |
462 | 0 | SOPC_Buffer_Delete(buffer); |
463 | 0 | return SOPC_STATUS_NOK; |
464 | 0 | } |
465 | | |
466 | 0 | buffer->length = buffer->current_size; |
467 | 0 | *buf = buffer; |
468 | 0 | return SOPC_STATUS_OK; |
469 | 0 | } |
470 | | #else |
471 | | SOPC_ReturnStatus SOPC_Buffer_ReadFile(const char* path, SOPC_Buffer** buf) |
472 | | { |
473 | | SOPC_UNUSED_ARG(path); |
474 | | SOPC_UNUSED_ARG(buf); |
475 | | return SOPC_STATUS_NOT_SUPPORTED; |
476 | | } |
477 | | |
478 | | #endif // SOPC_HAS_FILESYSTEM |
479 | | |
480 | | SOPC_ReturnStatus SOPC_Buffer_PrintU32(SOPC_Buffer* buf, const uint32_t value) |
481 | 0 | { |
482 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_NOK; |
483 | 0 | char buffer[SOPC_MAX_LENGTH_UINT32_TO_STRING]; |
484 | 0 | int res = snprintf(buffer, SOPC_MAX_LENGTH_UINT32_TO_STRING, "%" PRIu32, value); |
485 | 0 | if (res > 0 && res < SOPC_MAX_LENGTH_UINT32_TO_STRING) |
486 | 0 | { |
487 | 0 | status = SOPC_Buffer_Write(buf, (const uint8_t*) buffer, (uint32_t) strlen(buffer)); |
488 | 0 | } |
489 | 0 | return status; |
490 | 0 | } |
491 | | |
492 | | SOPC_ReturnStatus SOPC_Buffer_PrintI32(SOPC_Buffer* buf, const int32_t value) |
493 | 0 | { |
494 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_NOK; |
495 | 0 | char buffer[SOPC_MAX_LENGTH_INT32_TO_STRING]; |
496 | 0 | int res = snprintf(buffer, SOPC_MAX_LENGTH_INT32_TO_STRING, "%" PRIi32, value); |
497 | 0 | if (res > 0 && res < SOPC_MAX_LENGTH_INT32_TO_STRING) |
498 | 0 | { |
499 | 0 | status = SOPC_Buffer_Write(buf, (const uint8_t*) buffer, (uint32_t) strlen(buffer)); |
500 | 0 | } |
501 | 0 | return status; |
502 | 0 | } |
503 | | |
504 | | SOPC_ReturnStatus SOPC_Buffer_PrintFloatDouble(SOPC_Buffer* buf, const double value) |
505 | 0 | { |
506 | 0 | static const char* infinity_str_json_format = "\"Infinity\""; |
507 | 0 | static const char* infinity_str_minus_json_format = "\"-Infinity\""; |
508 | 0 | static const char* nan_str_json_format = "\"NaN\""; |
509 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_NOK; |
510 | 0 | char buffer[SOPC_PRECISION_PRINTING_FLOAT_NUMBERS + 8]; // (decimal + '-.e+ddd' + '\0') |
511 | | |
512 | | /* Check if value is a special number */ |
513 | | // If it's a NaN |
514 | 0 | if (isnan(value)) |
515 | 0 | { |
516 | 0 | status = SOPC_Buffer_Write(buf, (const uint8_t*) nan_str_json_format, (uint32_t) strlen(nan_str_json_format)); |
517 | 0 | } |
518 | | // If it's a +Inf |
519 | 0 | else if (1 == isinf(value)) |
520 | 0 | { |
521 | 0 | status = SOPC_Buffer_Write(buf, (const uint8_t*) infinity_str_json_format, |
522 | 0 | (uint32_t) strlen(infinity_str_json_format)); |
523 | 0 | } |
524 | | // If it's a -Inf |
525 | 0 | else if (-1 == isinf(value)) |
526 | 0 | { |
527 | 0 | status = SOPC_Buffer_Write(buf, (const uint8_t*) infinity_str_minus_json_format, |
528 | 0 | (uint32_t) strlen(infinity_str_minus_json_format)); |
529 | 0 | } |
530 | | // Else, it's a normal decimal number |
531 | 0 | else |
532 | 0 | { |
533 | 0 | int res = snprintf(buffer, SOPC_PRECISION_PRINTING_FLOAT_NUMBERS + 8, "%.*g", |
534 | 0 | SOPC_PRECISION_PRINTING_FLOAT_NUMBERS, value); |
535 | 0 | if (res > 0 && res < SOPC_PRECISION_PRINTING_FLOAT_NUMBERS + 8) |
536 | 0 | { |
537 | 0 | status = SOPC_Buffer_Write(buf, (const uint8_t*) buffer, (uint32_t) strlen(buffer)); |
538 | 0 | } |
539 | 0 | } |
540 | |
|
541 | 0 | return status; |
542 | 0 | } |
543 | | |
544 | | SOPC_ReturnStatus SOPC_Buffer_PrintCString(SOPC_Buffer* buf, const char* value) |
545 | 0 | { |
546 | 0 | if (NULL == value) |
547 | 0 | { |
548 | 0 | value = "<null>"; |
549 | 0 | } |
550 | 0 | return SOPC_Buffer_Write(buf, (const uint8_t*) value, (uint32_t) strlen(value)); |
551 | 0 | } |