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