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