Graphviz 14.1.2~dev.20251217.0236
Loading...
Searching...
No Matches
sfcvt.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include <limits.h>
12#include <sfio/sfhdr.h>
13#include <stdio.h>
14#include <string.h>
15
16/* Convert a floating point value to ASCII
17**
18** Written by Kiem-Phong Vo
19*/
20
21static char *Inf = "Inf", *Zero = "0";
22#define SF_INTPART (SF_IDIGITS/2)
23#define SF_INFINITE ((_Sfi = 3), Inf)
24#define SF_ZERO ((_Sfi = 1), Zero)
25
33char *_sfcvt(void * dv, int n_digit, int *decpt, int *sign, int format)
34{
35 char *sp;
36 long n, v;
37 char *ep, *buf, *endsp;
38 static char Buf[SF_MAXDIGITS];
39
40 *sign = *decpt = 0;
41 {
42 double dval = *(double *)dv;
43
44 if (dval == 0.)
45 return SF_ZERO;
46 else if ((*sign = dval < 0.)) /* assignment = */
47 dval = -dval;
48
49 n = 0;
50 if (dval >= (double)LONG_MAX) { /* scale to a small enough number to fit an int */
51 v = SF_MAXEXP10 - 1;
52 do {
53 if (dval < _Sfpos10[v])
54 v -= 1;
55 else {
56 dval *= _Sfneg10[v];
57 if ((n += 1 << v) >= SF_IDIGITS)
58 return SF_INFINITE;
59 }
60 } while (dval >= (double)LONG_MAX);
61 }
62 *decpt = (int) n;
63
64 buf = sp = Buf + SF_INTPART;
65 if ((v = (int) dval) != 0) { /* translate the integer part */
66 dval -= (double) v;
67
68 n = snprintf(Buf, sizeof(Buf), "%ld", v);
69 memmove(Buf + SF_INTPART - n, Buf, n);
70
71 if ((*decpt += (int) n) >= SF_IDIGITS)
72 return SF_INFINITE;
73 buf = Buf + SF_INTPART - n;
74 sp = Buf + SF_INTPART;
75 } else
76 n = 0;
77
78 /* remaining number of digits to compute; add 1 for later rounding */
79 n = (((format & SFFMT_EFORMAT)
80 || *decpt <= 0) ? 1 : *decpt + 1) - n;
81 if (n_digit > 0)
82 n += n_digit;
83
84 if ((ep = sp + n) > (endsp = Buf + (SF_MAXDIGITS - 2)))
85 ep = endsp;
86 if (sp > ep)
87 sp = ep;
88 else {
89 if ((format & SFFMT_EFORMAT) && *decpt == 0 && dval > 0.) {
90 double d;
91 while ((int) (d = dval * 10.) == 0) {
92 dval = d;
93 *decpt -= 1;
94 }
95 }
96
97 while (sp < ep) { /* generate fractional digits */
98 if (dval <= 0.) { /* fill with 0's */
99 do {
100 *sp++ = '0';
101 } while (sp < ep);
102 goto done;
103 } else if ((n = (int) (dval *= 10.)) < 10) {
104 *sp++ = (char) ('0' + n);
105 dval -= n;
106 } else { /* n == 10 */
107 do {
108 *sp++ = '9';
109 } while (sp < ep);
110 }
111 }
112 }
113 }
114
115 if (ep <= buf)
116 ep = buf + 1;
117 else if (ep < endsp) { /* round the last digit */
118 *--sp += 5;
119 while (*sp > '9') {
120 *sp = '0';
121 if (sp > buf)
122 *--sp += 1;
123 else { /* next power of 10 */
124 *sp = '1';
125 *decpt += 1;
126 if (!(format & SFFMT_EFORMAT)) { /* add one more 0 for %f precision */
127 ep[-1] = '0';
128 ep += 1;
129 }
130 }
131 }
132 }
133
134 done:
135 *--ep = '\0';
136 _Sfi = ep - buf;
137 return buf;
138}
GVIO_API const char * format
Definition gvio.h:51
static int sign(double v)
Definition legal.c:43
#define SF_INTPART
Definition sfcvt.c:22
#define SF_INFINITE
Definition sfcvt.c:23
#define SF_ZERO
Definition sfcvt.c:24
char * _sfcvt(void *dv, int n_digit, int *decpt, int *sign, int format)
Definition sfcvt.c:33
static char * Zero
Definition sfcvt.c:21
static char * Inf
Definition sfcvt.c:21
ssize_t _Sfi
Definition sfextern.c:21
#define SF_MAXDIGITS
Definition sfhdr.h:122
#define SF_IDIGITS
Definition sfhdr.h:121
#define _Sfpos10
Definition sfhdr.h:125
#define SFFMT_EFORMAT
Definition sfhdr.h:101
#define _Sfneg10
Definition sfhdr.h:126
#define SF_MAXEXP10
Definition sfhdr.h:119