diff options
Diffstat (limited to 'src/tai64nfrac.c')
-rw-r--r-- | src/tai64nfrac.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/tai64nfrac.c b/src/tai64nfrac.c new file mode 100644 index 0000000..f3db977 --- /dev/null +++ b/src/tai64nfrac.c @@ -0,0 +1,85 @@ +#include "buffer.h" +#include "stralloc.h" +#include "exit.h" +#include "readwrite.h" +#include "open.h" +#include "scan.h" +#include "fmt.h" +#include "getln.h" + +#define TAI64NLEN 24 + +/** @file tai64nfrac + @brief Read a TAI64N external format timestamp from stdin and + write fractional seconds since epoch (TAI, not UTC) to stdout. + Return the characters after the timestamp. + */ + +char outbuf[64]; +buffer bo = BUFFER_INIT(write,1,outbuf,sizeof(outbuf)); + +static void outs(char *s) +{ + if (buffer_puts(&bo,s) == -1) _exit(1); + if (buffer_flush(&bo) == -1) _exit(1); +} + +static void outi(int i) +{ + char num[FMT_ULONG]; + + if (buffer_put(&bo,num,fmt_ulong(num,(unsigned long) i)) == -1) _exit(1); + if (buffer_flush(&bo) == -1) _exit(1); +} + +char inbuf[1024]; +buffer bi = BUFFER_INIT(read,0,inbuf,sizeof(inbuf)); + +int main(void) +{ + int c; + int i; + int match; + unsigned long u; + unsigned long seconds; + unsigned long nanoseconds; + stralloc line = {0}; + +/* Read from stdin */ + + buffer_init(&bi,read,0,inbuf,sizeof(inbuf)); + + for (;;) { + if (getln(&bi,&line,&match,'\n') != 0) _exit(1); + if (!match) break; + if (!stralloc_0(&line)) _exit(1); + + seconds = 0; + nanoseconds = 0; + + if (line.s[0] == '@') { /* tai64 timestamp */ + for (i = 1; i <= TAI64NLEN; i++) { + c = (int)line.s[i]; + u = c - '0'; + if (u >= 10) { + u = c - 'a'; + if (u >= 6) break; + u += 10; + } + seconds <<= 4; + seconds += nanoseconds >> 28; + nanoseconds &= 0xfffffff; + nanoseconds <<= 4; + nanoseconds += u; + } + seconds -= 4611686018427387914ULL; + seconds = seconds > 0 ? seconds : 0; + outi(seconds); outs("."); outi(nanoseconds); outs(line.s + i); outs("\n"); + } else { + outs("tai64nfrac: fatal: Wrong TAI64N input format."); outs("\n"); + _exit(1); + } + } + + _exit(0); +} |