Branch data Line data Source code
1 : : // Copyright 2019-2026 David Robillard <d@drobilla.net>
2 : : // SPDX-License-Identifier: ISC
3 : :
4 : : #include "big_decimal.h"
5 : : #include "result.h"
6 : : #include "write_utils.h"
7 : :
8 : : #include <exess/exess.h>
9 : :
10 : : #include <stdbool.h>
11 : : #include <stdint.h>
12 : : #include <string.h>
13 : :
14 : : static inline ExessVariableResult
15 : 1116 : fixed(const ExessResult result, const size_t write_count)
16 : : {
17 [ + + ]: 1116 : return VRESULT(result.status, result.count, result.status ? 0U : write_count);
18 : : }
19 : :
20 : : static inline ExessVariableResult
21 : 43 : integer(const ExessVariableResult result,
22 : : const void* const value,
23 : : const BigDecimalKind kind,
24 : : const bool equals)
25 : : {
26 : 43 : const BigDecimal* const decimal = (const BigDecimal*)value;
27 : :
28 [ + + ]: 39 : return (!result.status && ((decimal->kind == kind) == equals)
29 : 7 : ? VRESULT(EXESS_OUT_OF_RANGE, result.read_count, 0U)
30 [ + + ]: 82 : : result);
31 : : }
32 : :
33 : : EXESS_NONBLOCKING ExessVariableResult
34 : 1399 : exess_read_value(const ExessDatatype datatype,
35 : : const char* const str,
36 : : const size_t out_size,
37 : : void* const out)
38 : : {
39 : 1399 : ExessVariableResult r = {EXESS_UNSUPPORTED, 0, 0};
40 : :
41 [ + + ]: 1399 : if (out_size < exess_value_sizes[datatype]) {
42 : 1 : return VRESULT(EXESS_NO_SPACE, 0U, 0U);
43 : : }
44 : :
45 [ + + + + : 1398 : switch (datatype) {
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + - ]
46 : 6 : case EXESS_NOTHING:
47 : 6 : break;
48 : 54 : case EXESS_BOOLEAN:
49 : 1392 : return fixed(exess_read_boolean(str, (bool*)out), sizeof(bool));
50 : 150 : case EXESS_DOUBLE:
51 : 150 : return fixed(exess_read_double(str, (double*)out), sizeof(double));
52 : 150 : case EXESS_FLOAT:
53 : 150 : return fixed(exess_read_float(str, (float*)out), sizeof(float));
54 : 58 : case EXESS_LONG:
55 : 58 : return fixed(exess_read_long(str, (int64_t*)out), sizeof(int64_t));
56 : 19 : case EXESS_INT:
57 : 19 : return fixed(exess_read_int(str, (int32_t*)out), sizeof(int32_t));
58 : 15 : case EXESS_SHORT:
59 : 15 : return fixed(exess_read_short(str, (int16_t*)out), sizeof(int16_t));
60 : 15 : case EXESS_BYTE:
61 : 15 : return fixed(exess_read_byte(str, (int8_t*)out), sizeof(int8_t));
62 : 45 : case EXESS_ULONG:
63 : 45 : return fixed(exess_read_ulong(str, (uint64_t*)out), sizeof(uint64_t));
64 : 14 : case EXESS_UINT:
65 : 14 : return fixed(exess_read_uint(str, (uint32_t*)out), sizeof(uint32_t));
66 : 14 : case EXESS_USHORT:
67 : 14 : return fixed(exess_read_ushort(str, (uint16_t*)out), sizeof(uint16_t));
68 : 14 : case EXESS_UBYTE:
69 : 14 : return fixed(exess_read_ubyte(str, (uint8_t*)out), sizeof(uint8_t));
70 : :
71 : 175 : case EXESS_DECIMAL:
72 : 175 : return exess_read_decimal(str, out_size, out);
73 : 8 : case EXESS_INTEGER:
74 : 8 : return exess_read_integer(str, out_size, out);
75 : :
76 : 9 : case EXESS_NON_POSITIVE_INTEGER:
77 : 9 : return integer(
78 : : exess_read_integer(str, out_size, out), out, EXESS_POSITIVE, true);
79 : :
80 : 9 : case EXESS_NEGATIVE_INTEGER:
81 : 9 : return integer(
82 : : exess_read_integer(str, out_size, out), out, EXESS_NEGATIVE, false);
83 : :
84 : 12 : case EXESS_NON_NEGATIVE_INTEGER:
85 : 12 : return integer(
86 : : exess_read_integer(str, out_size, out), out, EXESS_NEGATIVE, true);
87 : :
88 : 13 : case EXESS_POSITIVE_INTEGER:
89 : 13 : return integer(
90 : : exess_read_integer(str, out_size, out), out, EXESS_POSITIVE, false);
91 : :
92 : 118 : case EXESS_DURATION:
93 : 118 : return fixed(exess_read_duration(str, (ExessDuration*)out),
94 : : sizeof(ExessDuration));
95 : :
96 : 5 : case EXESS_YEAR_MONTH_DURATION:
97 : 5 : r = fixed(exess_read_duration(str, (ExessDuration*)out),
98 : : sizeof(ExessDuration));
99 [ + + ]: 4 : return (!r.status && (((const ExessDuration*)out)->seconds ||
100 [ + + ]: 2 : ((const ExessDuration*)out)->nanoseconds))
101 : 3 : ? VRESULT(EXESS_BAD_VALUE, r.read_count, 0U)
102 [ + + ]: 9 : : r;
103 : :
104 : 3 : case EXESS_DAY_TIME_DURATION:
105 : 3 : r = fixed(exess_read_duration(str, (ExessDuration*)out),
106 : : sizeof(ExessDuration));
107 [ + + ]: 2 : return (!r.status && ((const ExessDuration*)out)->months)
108 : 1 : ? VRESULT(EXESS_BAD_VALUE, r.read_count, 0U)
109 [ + + ]: 5 : : r;
110 : :
111 : 139 : case EXESS_DATE_TIME:
112 : 139 : return fixed(exess_read_date_time(str, (ExessDateTime*)out),
113 : : sizeof(ExessDateTime));
114 : :
115 : 3 : case EXESS_DATE_TIME_STAMP:
116 : 3 : r = fixed(exess_read_date_time(str, (ExessDateTime*)out),
117 : : sizeof(ExessDateTime));
118 : 5 : return (!r.status &&
119 [ + + ]: 2 : (((const ExessDateTime*)out)->zone == EXESS_TIMEZONE_LOCAL))
120 : 1 : ? VRESULT(EXESS_BAD_VALUE, r.read_count, 0U)
121 [ + + ]: 5 : : r;
122 : :
123 : 120 : case EXESS_TIME:
124 : 120 : return fixed(exess_read_time(str, (ExessTime*)out), sizeof(ExessTime));
125 : 80 : case EXESS_DATE:
126 : 80 : return fixed(exess_read_date(str, (ExessDate*)out), sizeof(ExessDate));
127 : :
128 : 20 : case EXESS_YEAR_MONTH:
129 : 20 : return fixed(exess_read_year_month(str, (ExessYearMonth*)out),
130 : : sizeof(ExessYearMonth));
131 : 20 : case EXESS_YEAR:
132 : 20 : return fixed(exess_read_year(str, (ExessYear*)out), sizeof(ExessYear));
133 : 20 : case EXESS_MONTH_DAY:
134 : 20 : return fixed(exess_read_month_day(str, (ExessMonthDay*)out),
135 : : sizeof(ExessMonthDay));
136 : 20 : case EXESS_DAY:
137 : 20 : return fixed(exess_read_day(str, (ExessDay*)out), sizeof(ExessDay));
138 : 20 : case EXESS_MONTH:
139 : 20 : return fixed(exess_read_month(str, (ExessMonth*)out), sizeof(ExessMonth));
140 : :
141 : 39 : case EXESS_HEX:
142 : 39 : return exess_read_hex(str, out_size, out);
143 : 11 : case EXESS_BASE64:
144 : 11 : return exess_read_base64(str, out_size, out);
145 : : }
146 : :
147 : 6 : return r;
148 : : }
149 : :
150 : : EXESS_NONBLOCKING ExessResult
151 : 737 : exess_write_value(const ExessDatatype datatype,
152 : : const size_t value_size,
153 : : const void* const value,
154 : : const size_t buf_size,
155 : : char* const buf)
156 : : {
157 [ + + + + : 737 : switch (datatype) {
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ - ]
158 : 1 : case EXESS_NOTHING:
159 : 1 : break;
160 : 23 : case EXESS_BOOLEAN:
161 : 23 : return exess_write_boolean(*(const bool*)value, buf_size, buf);
162 : 19 : case EXESS_DOUBLE:
163 : 19 : return exess_write_double(*(const double*)value, buf_size, buf);
164 : 26 : case EXESS_FLOAT:
165 : 26 : return exess_write_float(*(const float*)value, buf_size, buf);
166 : 96 : case EXESS_LONG:
167 : 96 : return exess_write_long(*(const int64_t*)value, buf_size, buf);
168 : 60 : case EXESS_INT:
169 : 60 : return exess_write_int(*(const int32_t*)value, buf_size, buf);
170 : 60 : case EXESS_SHORT:
171 : 60 : return exess_write_short(*(const int16_t*)value, buf_size, buf);
172 : 61 : case EXESS_BYTE:
173 : 61 : return exess_write_byte(*(const int8_t*)value, buf_size, buf);
174 : 59 : case EXESS_ULONG:
175 : 59 : return exess_write_ulong(*(const uint64_t*)value, buf_size, buf);
176 : 31 : case EXESS_UINT:
177 : 31 : return exess_write_uint(*(const uint32_t*)value, buf_size, buf);
178 : 31 : case EXESS_USHORT:
179 : 31 : return exess_write_ushort(*(const uint16_t*)value, buf_size, buf);
180 : 31 : case EXESS_UBYTE:
181 : 31 : return exess_write_ubyte(*(const uint8_t*)value, buf_size, buf);
182 : 14 : case EXESS_DECIMAL:
183 : 14 : return exess_write_decimal(value_size, value, buf_size, buf);
184 : 95 : case EXESS_INTEGER:
185 : : case EXESS_NON_POSITIVE_INTEGER:
186 : : case EXESS_NEGATIVE_INTEGER:
187 : : case EXESS_NON_NEGATIVE_INTEGER:
188 : : case EXESS_POSITIVE_INTEGER:
189 : 95 : return exess_write_integer(value_size, value, buf_size, buf);
190 : 19 : case EXESS_DURATION:
191 : : case EXESS_YEAR_MONTH_DURATION:
192 : : case EXESS_DAY_TIME_DURATION:
193 : 19 : return exess_write_duration(*(const ExessDuration*)value, buf_size, buf);
194 : 20 : case EXESS_DATE_TIME:
195 : : case EXESS_DATE_TIME_STAMP:
196 : 20 : return exess_write_date_time(*(const ExessDateTime*)value, buf_size, buf);
197 : 21 : case EXESS_TIME:
198 : 21 : return exess_write_time(*(const ExessTime*)value, buf_size, buf);
199 : 17 : case EXESS_DATE:
200 : 17 : return exess_write_date(*(const ExessDate*)value, buf_size, buf);
201 : 9 : case EXESS_YEAR_MONTH:
202 : 9 : return exess_write_year_month(*(const ExessYearMonth*)value, buf_size, buf);
203 : 6 : case EXESS_YEAR:
204 : 6 : return exess_write_year(*(const ExessYear*)value, buf_size, buf);
205 : 9 : case EXESS_MONTH_DAY:
206 : 9 : return exess_write_month_day(*(const ExessMonthDay*)value, buf_size, buf);
207 : 7 : case EXESS_DAY:
208 : 7 : return exess_write_day(*(const ExessDay*)value, buf_size, buf);
209 : 6 : case EXESS_MONTH:
210 : 6 : return exess_write_month(*(const ExessMonth*)value, buf_size, buf);
211 : 9 : case EXESS_HEX:
212 : 9 : return exess_write_hex(value_size, value, buf_size, buf);
213 : 7 : case EXESS_BASE64:
214 : 7 : return exess_write_base64(value_size, value, buf_size, buf);
215 : : }
216 : :
217 : 1 : return end_write(EXESS_BAD_VALUE, buf_size, buf, 0);
218 : : }
|