-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathformat.c
117 lines (97 loc) · 3.39 KB
/
format.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*******************************************************************************
* File: format.c
* Created: 2020-05-05
*
* Authors:
* Tyler Matijevich
*
* License:
* This file format.c is part of the IecString project
* released under the MIT license agreement.
******************************************************************************/
#include "main.h"
/* Format string with runtime data */
int32_t IecStringFormat(char *destination, uint32_t size, char *source,
IecStringFormatType *values)
{
/* Gaurd null pointers */
if (!destination || !source || !values)
{
/* Copy if no values */
IecStringCopy(destination, size, source);
return IECSTRING_ERROR_NULL;
}
/* Check for zero size */
if (!size)
return IECSTRING_ERROR_SIZE_ZERO;
/* Check if source overlaps destination size */
if (destination <= source && source < destination + size)
return IECSTRING_ERROR_OVERLAP;
/* Check if destination overlaps source length */
if (source <= destination && destination <= source + strlen(source))
return IECSTRING_ERROR_OVERLAP;
/* Local variables */
int count_bool = 0, count_float = 0, count_int = 0, count_string = 0;
uint32_t bytes_remaining = size;
size_t length;
int32_t status = 0;
/* Format each character from source */
while (*source && bytes_remaining > 1)
{
/* Directly copy source character if it is not a specifier */
if (*source != '%')
{
*destination++ = *source++;
bytes_remaining--;
continue;
}
/* Force string length of zero if nothing is written */
*destination = '\0';
status = 0;
switch (*(++source))
{
case 'b':
if (count_bool > IECSTRING_FORMAT_INDEX)
break;
status = IecStringCopy(destination, bytes_remaining,
values->b[count_bool++] ? "TRUE" : "FALSE");
break;
/* LREAL/double casted to REAL/float */
case 'r':
case 'f':
if (count_float > IECSTRING_FORMAT_INDEX)
break;
status = IecStringFloat(destination, bytes_remaining,
(float)values->f[count_float++], 0, 6, IECSTRING_FLAG_NONE);
break;
/* Integer/decimal */
case 'i':
case 'd':
if (count_int > IECSTRING_FORMAT_INDEX)
break;
status = IecStringDecimal(destination, bytes_remaining,
values->i[count_int++], 0, IECSTRING_FLAG_NONE);
break;
case 's':
if (count_string > IECSTRING_FORMAT_INDEX)
break;
status = IecStringCopy(destination, bytes_remaining,
values->s[count_string++]);
break;
case '%':
*destination = '%';
*(destination + 1) = '\0';
break;
}
length = strlen(destination);
destination += length;
bytes_remaining -= length;
source++;
}
/* Add null terminator */
*destination = '\0';
/* Truncated if source characters remain and destination is full
or function returns a status */
return IECSTRING_WARNING_TRUNCATE *
((*source && bytes_remaining <= 1) || status);
}