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