1c0b746e5SOllivier Robert /* 2c0b746e5SOllivier Robert * mstolfp - convert an ascii string in milliseconds to an l_fp number 3c0b746e5SOllivier Robert */ 42b15cb3dSCy Schubert #include <config.h> 5c0b746e5SOllivier Robert #include <stdio.h> 6c0b746e5SOllivier Robert #include <ctype.h> 7c0b746e5SOllivier Robert 8c0b746e5SOllivier Robert #include "ntp_fp.h" 9c0b746e5SOllivier Robert #include "ntp_stdlib.h" 10c0b746e5SOllivier Robert 11c0b746e5SOllivier Robert int mstolfp(const char * str,l_fp * lfp)12c0b746e5SOllivier Robertmstolfp( 13c0b746e5SOllivier Robert const char *str, 14c0b746e5SOllivier Robert l_fp *lfp 15c0b746e5SOllivier Robert ) 16c0b746e5SOllivier Robert { 17*a466cc55SCy Schubert int ch, neg = 0; 18*a466cc55SCy Schubert u_int32 q, r; 19c0b746e5SOllivier Robert 20c0b746e5SOllivier Robert /* 21c0b746e5SOllivier Robert * We understand numbers of the form: 22c0b746e5SOllivier Robert * 232d4e511cSCy Schubert * [spaces][-|+][digits][.][digits][spaces|\n|\0] 24c0b746e5SOllivier Robert * 25*a466cc55SCy Schubert * This is kinda hack. We use 'atolfp' to do the basic parsing 26*a466cc55SCy Schubert * (after some initial checks) and then divide the result by 27*a466cc55SCy Schubert * 1000. The original implementation avoided that by 28*a466cc55SCy Schubert * hacking up the input string to move the decimal point, but 29*a466cc55SCy Schubert * that needed string manipulations prone to buffer overruns. 30*a466cc55SCy Schubert * To avoid that trouble we do the conversion first and adjust 31*a466cc55SCy Schubert * the result. 32c0b746e5SOllivier Robert */ 33c0b746e5SOllivier Robert 34*a466cc55SCy Schubert while (isspace(ch = *(const unsigned char*)str)) 35*a466cc55SCy Schubert ++str; 36*a466cc55SCy Schubert 37*a466cc55SCy Schubert switch (ch) { 38*a466cc55SCy Schubert case '-': neg = TRUE; 39*a466cc55SCy Schubert case '+': ++str; 40*a466cc55SCy Schubert default : break; 41c0b746e5SOllivier Robert } 42c0b746e5SOllivier Robert 43*a466cc55SCy Schubert if (!isdigit(ch = *(const unsigned char*)str) && (ch != '.')) 44*a466cc55SCy Schubert return 0; 45*a466cc55SCy Schubert if (!atolfp(str, lfp)) 46c0b746e5SOllivier Robert return 0; 47c0b746e5SOllivier Robert 48*a466cc55SCy Schubert /* now do a chained/overlapping division by 1000 to get from 49*a466cc55SCy Schubert * seconds to msec. 1000 is small enough to go with temporary 50*a466cc55SCy Schubert * 32bit accus for Q and R. 51c0b746e5SOllivier Robert */ 52*a466cc55SCy Schubert q = lfp->l_ui / 1000u; 53*a466cc55SCy Schubert r = lfp->l_ui - (q * 1000u); 54*a466cc55SCy Schubert lfp->l_ui = q; 55c0b746e5SOllivier Robert 56*a466cc55SCy Schubert r = (r << 16) | (lfp->l_uf >> 16); 57*a466cc55SCy Schubert q = r / 1000u; 58*a466cc55SCy Schubert r = ((r - q * 1000) << 16) | (lfp->l_uf & 0x0FFFFu); 59*a466cc55SCy Schubert lfp->l_uf = q << 16; 60*a466cc55SCy Schubert q = r / 1000; 61*a466cc55SCy Schubert lfp->l_uf |= q; 62*a466cc55SCy Schubert r -= q * 1000u; 63c0b746e5SOllivier Robert 64*a466cc55SCy Schubert /* fix sign */ 65*a466cc55SCy Schubert if (neg) 66*a466cc55SCy Schubert L_NEG(lfp); 67*a466cc55SCy Schubert /* round */ 68*a466cc55SCy Schubert if (r >= 500) 69*a466cc55SCy Schubert L_ADDF(lfp, (neg ? -1 : 1)); 70*a466cc55SCy Schubert return 1; 71c0b746e5SOllivier Robert } 72