1 /*
2 Copyright (C) 2016-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5
6 /*
7 WARNING: This file was generated by the dkct program (see
8 http://dktools.sourceforge.net/ for details).
9 Changes you make here will be lost if dkct is run again!
10 You should modify the original source and run dkct on it.
11 Original source: dk4c8dbl.ctr
12 */
13
14 /** @file dk4c8dbl.c The dk4c8dbl module.
15 */
16
17
18 #include "dk4conf.h"
19 #include <libdk4base/dk4types.h>
20 #include <libdk4c/dk4c8dbl.h>
21
22 #if DK4_HAVE_STRING_H
23 #include <string.h>
24 #endif
25
26 #if DK4_HAVE_STDLIB_H
27 #include <stdlib.h>
28 #endif
29
30 #include <libdk4maio8d/dk4mao8dbl.h>
31 #include <libdk4maio8d/dk4mai8ddi.h>
32 #include <libdk4base/dk4str8.h>
33
34 #if DK4_HAVE_ASSERT_H
35 #ifndef ASSERT_H_INCLUDED
36 #include <assert.h>
37 #define ASSERT_H_INCLUDED 1
38 #endif
39 #endif
40
41
42
43
44
45
46 /** Write character to stream or file.
47 @param dptr Destination for write operations.
48 @param dtp Type of dptr: 0=FILE, 1=dk4_stream_t.
49 @param c Character to write.
50 @param erp Error report, may be NULL.
51 @return 1 on success, 0 on error.
52
53 Error codes:
54 - DK4_E_INVALID_ARGUMENTS<br>
55 if strm is NULL or not opened for writing,
56 - DK4_E_WRITE_FAILED<br>
57 if writing one ore multiple bytes to the stream failed,
58 - DK4_E_FLUSH_FAILED<br>
59 if flusing data downwards failed.
60 */
61 static
62 int
dk4c8dbl_i_byte_to_void(void * dptr,int dtp,char c,dk4_er_t * erp)63 dk4c8dbl_i_byte_to_void(
64 void *dptr,
65 int dtp,
66 char c,
67 dk4_er_t *erp
68 )
69 {
70 int back;
71 #if DK4_USE_ASSERT
72 assert(NULL != dptr);
73 #endif
74 switch (dtp) {
75 case 1: {
76 back = dk4stream_write_byte((dk4_stream_t*)dptr, c, erp);
77 } break;
78 default: {
79 if (EOF != fputc(c, (FILE *)dptr)) {
80 back = 1;
81 }
82 else {
83 back = 0;
84 dk4error_set_simple_error_code(erp, DK4_E_WRITE_FAILED);
85 }
86 } break;
87 }
88 return back;
89 }
90
91
92
93 static
94 void
dk4c8dbl_i_cut_trailing_zeroes(char * str)95 dk4c8dbl_i_cut_trailing_zeroes(char *str)
96 {
97 char *cutpos = NULL;
98
99 #if DK4_USE_ASSERT
100 assert(NULL != str);
101 #endif
102 while ('\0' != *str) {
103 if ('0' == *str) {
104 if (NULL == cutpos) {
105 cutpos = str;
106 }
107 }
108 else {
109 cutpos = NULL;
110 }
111 str++;
112 }
113 if (NULL != cutpos) {
114 *cutpos = '\0';
115 }
116
117 }
118
119
120
121 /** Write double value to stream or file, avoid scientific notation.
122 @param dptr Destination for write operations.
123 @param dtp Type of dptr: 0=FILE, 1=dk4_stream_t.
124 @param str String representation of double.
125 @param erp Error report, may be NULL.
126 @return 1 on success, 0 on error.
127
128 Error codes:
129 - DK4_E_INVALID_ARGUMENTS<br>
130 if dptr is NULL,
131 - DK4_E_BUFFER_TOO_SMALL<br>
132 if the internal destination buffer is too small to store the string,
133 - DK4_E_WRITE_FAILED<br>
134 if writing one ore multiple bytes to the stream failed,
135 - DK4_E_FLUSH_FAILED<br>
136 if flushing data downwards failed.
137 */
138 static
139 int
dk4c8dbl_i_str_to_void(void * dptr,int dtp,char * str,dk4_er_t * erp)140 dk4c8dbl_i_str_to_void(
141 void *dptr,
142 int dtp,
143 char *str,
144 dk4_er_t *erp
145 )
146 {
147 char *eptr; /* Position of 'e' */
148 char *ddptr; /* Position of decimal dot */
149 char *p1; /* Traverse string */
150 const char *endptr = NULL; /* End of processed data exponent */
151 dk4_im_t expo = (dk4_im_t)0L; /* Exponent value */
152 size_t dotpos; /* Position of decimal dot */
153 int isneg = 0; /* Flag: Negative number */
154 int back = 0; /* Function result */
155 int res; /* Conversion result */
156
157 /*
158 Check for scientific notation
159 */
160 #if DK4_USE_ASSERT
161 assert(NULL != dptr);
162 assert(NULL != str);
163 #endif
164 eptr = strchr(str, 'e');
165 if (NULL == eptr) { eptr = strchr(str, 'E'); }
166 if (NULL != eptr) {
167 /*
168 Scientific notation found, analyse string first
169 -----------------------------------------------
170 */
171 /*
172 Check for negative value (unary minus)
173 */
174 if ('-' == *str) {
175 isneg = 1;
176 str++;
177 }
178 /*
179 Retrieve exponent value
180 */
181 *(eptr++) = '\0';
182 res = dk4ma_input_c8_dec_dk4_im_t( &expo, eptr, &endptr, 1, erp);
183 if (0 == res) {
184 expo = (dk4_im_t)0L;
185 }
186
187 /*
188 Find position of decimal dot and convert string digit sequence
189 */
190 ddptr = strchr(str, '.');
191 if (NULL != ddptr) {
192 *ddptr = '\0';
193 dotpos = strlen(str);
194 dk4str8_cpy_to_left(ddptr, &(ddptr[1]));
195 dk4c8dbl_i_cut_trailing_zeroes(&(ddptr[1]));
196 }
197 else {
198 dotpos = strlen(str);
199 }
200 /*
201 Calculate real position of decimal dot.
202 */
203 expo += (dk4_im_t)dotpos;
204 /*
205 Remove leading zeroes
206 */
207 while (('0' == *str) && ('\0' != str[1])) {
208 str++;
209 expo--;
210 }
211 /*
212 Now write the number
213 --------------------
214 */
215 back = 1;
216 /*
217 Write unary minus for negative numbers
218 */
219 if (0 != isneg) {
220 if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '-', erp)) {
221 back = 0;
222 }
223 }
224 if ((dk4_im_t)0L >= expo) {
225 /*
226 Decimal dot is before first digit in string
227 */
228 if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '0', erp)) {
229 back = 0;
230 }
231 if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '.', erp)) {
232 back = 0;
233 }
234 while ((dk4_im_t)0L > expo++) {
235 if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '0', erp)) {
236 back = 0;
237 }
238 }
239 p1 = str;
240 while ('\0' != *p1) {
241 if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, *(p1++), erp)) {
242 back = 0;
243 }
244 }
245 }
246 else {
247 /*
248 Decimal dot is in string or after string
249 */
250 p1 = str;
251 while ('\0' != *p1) {
252 if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, *p1, erp)) {
253 back = 0;
254 }
255 expo--;
256 p1++;
257 if ((dk4_im_t)0L == expo) {
258 if ('\0' != *p1) {
259 if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '.', erp)) {
260 back = 0;
261 }
262 }
263 }
264 }
265 while ((dk4_im_t)0L < expo--) {
266 if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '0', erp)) {
267 back = 0;
268 }
269 }
270 }
271 }
272 else {
273 /*
274 No exponent, can ship out string as is
275 --------------------------------------
276 */
277 /*
278 Remove leading zeroes
279 */
280 while (('0' == *str) && ('\0' != str[1])) {
281 str++;
282 }
283 /*
284 Remove trailing zeroes
285 */
286 ddptr = strchr(str, '.');
287 if (NULL != ddptr) {
288 ddptr++;
289 ddptr++;
290 dk4c8dbl_i_cut_trailing_zeroes(ddptr);
291
292 }
293 /*
294 Write output
295 */
296 back = 1;
297 p1 = str;
298 if ('.' == *str) {
299 if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '0', erp)) {
300 back = 0;
301 }
302 }
303 while ('\0' != *p1) {
304 if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, *(p1++), erp)) {
305 back = 0;
306 }
307 }
308 }
309
310 return back;
311 }
312
313
314
315 /** Write double value to stream or file, avoid scientific notation.
316 @param dptr Destination for write operations.
317 @param dtp Type of dptr: 0=FILE, 1=dk4_stream_t.
318 @param v Value to write.
319 @param exact Flag: Exact representation.
320 @param minim Flag: Minimize an exact representation.
321 @param erp Error report, may be NULL.
322 @return 1 on success, 0 on error.
323
324 Error codes:
325 - DK4_E_INVALID_ARGUMENTS<br>
326 if dptr is NULL,
327 - DK4_E_BUFFER_TOO_SMALL<br>
328 if the internal destination buffer is too small to store the string,
329 - DK4_E_WRITE_FAILED<br>
330 if writing one ore multiple bytes to the stream failed,
331 - DK4_E_FLUSH_FAILED<br>
332 if flushing data downwards failed.
333 */
334 static
335 int
dk4c8dbl_i_double_to_void(void * dptr,int dtp,double v,int exact,int minim,dk4_er_t * erp)336 dk4c8dbl_i_double_to_void(
337 void *dptr,
338 int dtp,
339 double v,
340 int exact,
341 int minim,
342 dk4_er_t *erp
343 )
344 {
345 char buf[16*sizeof(double)];
346 size_t szbuf = sizeof(buf);
347 int res = 0;
348 int back = 0;
349 #if DK4_USE_ASSERT
350 assert(NULL != dptr);
351 #endif
352 if (NULL != dptr) {
353 res = dk4ma_write_c8_double(buf, szbuf, v, exact, minim, erp);
354 if (0 != res) {
355 back = dk4c8dbl_i_str_to_void(dptr, dtp, buf, erp);
356 }
357 }
358 else {
359 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
360 }
361 return back;
362 }
363
364
365
366 int
367
dk4c8dbl_double_to_stream(dk4_stream_t * strm,double v,int exact,int minim,dk4_er_t * erp)368 dk4c8dbl_double_to_stream(
369 dk4_stream_t *strm,
370 double v,
371 int exact,
372 int minim,
373 dk4_er_t *erp
374 )
375 {
376 #if DK4_USE_ASSERT
377 assert(NULL != strm);
378 #endif
379 return (dk4c8dbl_i_double_to_void((void *)strm, 1, v, exact, minim, erp));
380 }
381
382
383
384 int
385
dk4c8dbl_double_to_file(FILE * fipo,double v,int exact,int minim,dk4_er_t * erp)386 dk4c8dbl_double_to_file(
387 FILE *fipo,
388 double v,
389 int exact,
390 int minim,
391 dk4_er_t *erp
392 )
393 {
394 #if DK4_USE_ASSERT
395 assert(NULL != fipo);
396 #endif
397 return (dk4c8dbl_i_double_to_void((void *)fipo, 0, v, exact, minim, erp));
398 }
399
400
401
402 int
403
dk4c8dbl_str_double_to_file(FILE * fipo,const char * str,dk4_er_t * erp)404 dk4c8dbl_str_double_to_file(
405 FILE *fipo,
406 const char *str,
407 dk4_er_t *erp
408 )
409 {
410 char buf[16*sizeof(double)];
411 int back = 0;
412 #if DK4_USE_ASSERT
413 assert(NULL != fipo);
414 assert(NULL != str);
415 #endif
416 if ((NULL != fipo) && (NULL != str)) {
417 if (strlen(str) < sizeof(buf)) {
418 strcpy(buf, str);
419 back = dk4c8dbl_i_str_to_void((void *)fipo, 0, buf, erp);
420 }
421 else {
422 dk4error_set_simple_error_code(erp, DK4_E_SYNTAX);
423 }
424 }
425 else {
426 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
427 }
428 return back;
429 }
430
431
432
433 /* vim: set ai sw=4 ts=4 : */
434