00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <ctype.h>
00023 #include <errno.h>
00024 #include <locale.h>
00025 #include <stdlib.h>
00026 #include <lal/Date.h>
00027 #include <lal/LALDatatypes.h>
00028
00029
00030 #include <lal/LALRCSID.h>
00031 NRCSID (STRTOGPSC,"$Id: StrToGPS.c,v 1.18 2008/04/29 01:12:11 kipp Exp $");
00032
00033
00034
00035
00036
00037
00038
00039 static int isbase10(const char *s, int radix)
00040 {
00041 if(*s == radix)
00042 s++;
00043 if(isdigit(*s))
00044 return(1);
00045 return(0);
00046 }
00047
00048
00049 static int isbase16(const char *s, int radix)
00050 {
00051 if(*s == '0') {
00052 s++;
00053 if(*s == 'X' || *s == 'x') {
00054 s++;
00055 if(*s == radix)
00056 s++;
00057 if(isxdigit(*s))
00058 return(1);
00059 }
00060 }
00061 return(0);
00062 }
00063
00064
00065
00066
00067
00068
00069
00070 static int isdecimalexp(const char *s)
00071 {
00072 if(*s == 'E' || *s == 'e') {
00073 s++;
00074 if(*s == '+' || *s == '-')
00075 s++;
00076 if(isdigit(*s))
00077 return(1);
00078 }
00079 return(0);
00080 }
00081
00082
00083 static int isbinaryexp(const char *s)
00084 {
00085 if(*s == 'P' || *s == 'p') {
00086 s++;
00087 if(*s == '+' || *s == '-')
00088 s++;
00089 if(isdigit(*s))
00090 return(1);
00091 }
00092 return(0);
00093 }
00094
00095
00096
00097
00098
00099
00100
00101 int XLALStrToGPS(LIGOTimeGPS *t, const char *nptr, char **endptr)
00102 {
00103 static const char func[] = "XLALStrToGPS";
00104 union { char *s; const char *cs; } pconv;
00105 int olderrno;
00106 int radix;
00107 char *digits;
00108 int len;
00109 int sign;
00110 int base;
00111 int radixpos;
00112 int exppart;
00113
00114
00115 olderrno = errno;
00116 errno = 0;
00117
00118
00119 radix = localeconv()->decimal_point[0];
00120
00121
00122 pconv.cs = nptr;
00123
00124
00125 while(isspace(*(pconv.cs)))
00126 (pconv.cs)++;
00127 if(endptr)
00128 *endptr = pconv.s;
00129
00130
00131 if(*(pconv.cs) == '-') {
00132 sign = -1;
00133 (pconv.cs)++;
00134 } else if(*(pconv.cs) == '+') {
00135 sign = +1;
00136 (pconv.cs)++;
00137 } else
00138 sign = +1;
00139
00140
00141 if(isbase16((pconv.cs), radix)) {
00142 base = 16;
00143 (pconv.cs) += 2;
00144 } else if(isbase10((pconv.cs), radix)) {
00145 base = 10;
00146 } else {
00147
00148 XLALGPSSet(t, 0, 0);
00149 return(0);
00150 }
00151
00152
00153
00154 radixpos = -1;
00155 switch(base) {
00156 case 10:
00157 for(len = 0; 1; len++) {
00158 if(isdigit((pconv.cs)[len]))
00159 continue;
00160 if((pconv.cs)[len] == radix && radixpos < 0) {
00161 radixpos = len;
00162 continue;
00163 }
00164 break;
00165 }
00166 break;
00167
00168 case 16:
00169 for(len = 0; 1; len++) {
00170 if(isxdigit((pconv.cs)[len]))
00171 continue;
00172 if((pconv.cs)[len] == radix && radixpos < 0) {
00173 radixpos = len;
00174 continue;
00175 }
00176 break;
00177 }
00178 break;
00179 }
00180
00181
00182
00183 if(radixpos >= 0) {
00184 digits = malloc(len + 1);
00185 memcpy(digits, (pconv.cs), radixpos);
00186 memcpy(digits + radixpos, (pconv.cs) + radixpos + 1, len - radixpos - 1);
00187 digits[len - 1] = '\0';
00188 (pconv.cs) += len;
00189 len--;
00190 } else {
00191 digits = malloc(len + 2);
00192 memcpy(digits, (pconv.cs), len);
00193 digits[len] = '\0';
00194 radixpos = len;
00195 (pconv.cs) += len;
00196 }
00197
00198
00199
00200 exppart = 1;
00201 switch(base) {
00202 case 10:
00203
00204 if(isdecimalexp((pconv.cs)))
00205 radixpos += strtol((pconv.cs) + 1, &pconv.s, 10);
00206 break;
00207
00208 case 16:
00209
00210 if(isbinaryexp((pconv.cs))) {
00211 exppart = strtol((pconv.cs) + 1, &pconv.s, 10);
00212 radixpos += exppart / 4;
00213 exppart %= 4;
00214 if(exppart < 0) {
00215 radixpos--;
00216 exppart += 4;
00217 }
00218 exppart = 1 << exppart;
00219 }
00220 break;
00221 }
00222
00223
00224 if(endptr)
00225 *endptr = pconv.s;
00226
00227
00228
00229 if(radixpos < 2) {
00230 digits = realloc(digits, len + 2 + (2 - radixpos));
00231 memmove(digits + (2 - radixpos) + 1, digits, len + 1);
00232 memset(digits, '0', (2 - radixpos) + 1);
00233 if(radixpos == 1)
00234 digits[1] = digits[2];
00235 radixpos = 2;
00236 } else if(radixpos > len) {
00237 digits = realloc(digits, radixpos + 2);
00238 memset(digits + len, '0', radixpos - len);
00239 digits[radixpos + 1] = '\0';
00240 } else {
00241 memmove(digits + radixpos + 1, digits + radixpos, len - radixpos + 1);
00242 }
00243 digits[radixpos] = radix;
00244
00245
00246 XLALINT8NSToGPS(t, sign * strtol(digits, NULL, base) * exppart * 1000000000ll);
00247
00248
00249 if(errno != ERANGE) {
00250 switch(base) {
00251 case 10:
00252 break;
00253
00254 case 16:
00255 digits[radixpos - 2] = '0';
00256 digits[radixpos - 1] = 'x';
00257 radixpos -= 2;
00258 break;
00259 }
00260 XLALGPSAdd(t, sign * strtod(digits + radixpos, NULL) * exppart);
00261 }
00262
00263
00264 free(digits);
00265
00266
00267 if(errno == ERANGE)
00268 XLAL_ERROR(func, XLAL_ERANGE);
00269 errno = olderrno;
00270
00271
00272 return(0);
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 char *XLALGPSToStr(char *s, const LIGOTimeGPS *t)
00287 {
00288 static const char func[] = "XLALGPSToStr";
00289 const long billion = 1000000000;
00290
00291 LIGOTimeGPS copy = *t;
00292
00293
00294
00295 if(!s) {
00296
00297
00298
00299 s = XLALMalloc(21 * sizeof(*s));
00300 if(!s)
00301 XLAL_ERROR_NULL(func, XLAL_EFUNC);
00302 }
00303
00304
00305
00306 while(labs(copy.gpsNanoSeconds) > billion) {
00307 if(copy.gpsNanoSeconds < 0) {
00308 copy.gpsSeconds -= 1;
00309 copy.gpsNanoSeconds += billion;
00310 } else {
00311 copy.gpsSeconds += 1;
00312 copy.gpsNanoSeconds -= billion;
00313 }
00314 }
00315
00316
00317
00318
00319 if(copy.gpsSeconds > 0 && copy.gpsNanoSeconds < 0) {
00320 copy.gpsSeconds -= 1;
00321 copy.gpsNanoSeconds += billion;
00322 } else if(copy.gpsSeconds < 0 && copy.gpsNanoSeconds > 0) {
00323 copy.gpsSeconds += 1;
00324 copy.gpsNanoSeconds -= billion;
00325 }
00326
00327
00328
00329 if(copy.gpsSeconds < 0 || copy.gpsNanoSeconds < 0)
00330
00331 sprintf(s, "-%ld.%09ld", labs(copy.gpsSeconds), labs(copy.gpsNanoSeconds));
00332 else
00333
00334 sprintf(s, "%ld.%09ld", (long) copy.gpsSeconds, (long) copy.gpsNanoSeconds);
00335
00336 return s;
00337 }