xref: /freebsd/contrib/ntp/libntp/mstolfp.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
1 /*
2  * mstolfp - convert an ascii string in milliseconds to an l_fp number
3  */
4 #include <stdio.h>
5 #include <ctype.h>
6 
7 #include "ntp_fp.h"
8 #include "ntp_stdlib.h"
9 
10 int
11 mstolfp(
12 	const char *str,
13 	l_fp *lfp
14 	)
15 {
16 	register const char *cp;
17 	register char *bp;
18 	register const char *cpdec;
19 	char buf[100];
20 
21 	/*
22 	 * We understand numbers of the form:
23 	 *
24 	 * [spaces][-][digits][.][digits][spaces|\n|\0]
25 	 *
26 	 * This is one enormous hack.  Since I didn't feel like
27 	 * rewriting the decoding routine for milliseconds, what
28 	 * is essentially done here is to make a copy of the string
29 	 * with the decimal moved over three places so the seconds
30 	 * decoding routine can be used.
31 	 */
32 	bp = buf;
33 	cp = str;
34 	while (isspace((int)*cp))
35 	    cp++;
36 
37 	if (*cp == '-') {
38 		*bp++ = '-';
39 		cp++;
40 	}
41 
42 	if (*cp != '.' && !isdigit((int)*cp))
43 	    return 0;
44 
45 
46 	/*
47 	 * Search forward for the decimal point or the end of the string.
48 	 */
49 	cpdec = cp;
50 	while (isdigit((int)*cpdec))
51 	    cpdec++;
52 
53 	/*
54 	 * Found something.  If we have more than three digits copy the
55 	 * excess over, else insert a leading 0.
56 	 */
57 	if ((cpdec - cp) > 3) {
58 		do {
59 			*bp++ = (char)*cp++;
60 		} while ((cpdec - cp) > 3);
61 	} else {
62 		*bp++ = '0';
63 	}
64 
65 	/*
66 	 * Stick the decimal in.  If we've got less than three digits in
67 	 * front of the millisecond decimal we insert the appropriate number
68 	 * of zeros.
69 	 */
70 	*bp++ = '.';
71 	if ((cpdec - cp) < 3) {
72 		register int i = 3 - (cpdec - cp);
73 
74 		do {
75 			*bp++ = '0';
76 		} while (--i > 0);
77 	}
78 
79 	/*
80 	 * Copy the remainder up to the millisecond decimal.  If cpdec
81 	 * is pointing at a decimal point, copy in the trailing number too.
82 	 */
83 	while (cp < cpdec)
84 	    *bp++ = (char)*cp++;
85 
86 	if (*cp == '.') {
87 		cp++;
88 		while (isdigit((int)*cp))
89 		    *bp++ = (char)*cp++;
90 	}
91 	*bp = '\0';
92 
93 	/*
94 	 * Check to make sure the string is properly terminated.  If
95 	 * so, give the buffer to the decoding routine.
96 	 */
97 	if (*cp != '\0' && !isspace((int)*cp))
98 	    return 0;
99 	return atolfp(buf, lfp);
100 }
101