summaryrefslogtreecommitdiff
path: root/src/tai64nfrac.c
blob: f3db9770927ffc38bb1abb643d00d7398a643396 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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);
}