|
| 1 | +/* Copyright (C) 2020 Chris Piker <chris-piker@uiowa.edu> |
| 2 | + * |
| 3 | + * This file is part of libdas2, the Core Das2 C Library. |
| 4 | + * |
| 5 | + * Libdas2 is free software; you can redistribute it and/or modify it under |
| 6 | + * the terms of the GNU Lesser General Public License version 2.1 as published |
| 7 | + * by the Free Software Foundation. |
| 8 | + * |
| 9 | + * Libdas2 is distributed in the hope that it will be useful, but WITHOUT ANY |
| 10 | + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 11 | + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
| 12 | + * more details. |
| 13 | + * |
| 14 | + * You should have received a copy of the GNU Lesser General Public License |
| 15 | + * version 2.1 along with libdas2; if not, see <http://www.gnu.org/licenses/>. |
| 16 | + */ |
| 17 | + |
| 18 | +#define _POSIX_C_SOURCE 200112L |
| 19 | + |
| 20 | +#include <stdio.h> |
| 21 | +#include <stdlib.h> |
| 22 | +#include <stdbool.h> |
| 23 | +#include <string.h> |
| 24 | +#include <locale.h> |
| 25 | +#include <limits.h> |
| 26 | + |
| 27 | +#ifndef _WIN32 |
| 28 | +#include <unistd.h> |
| 29 | +#endif |
| 30 | + |
| 31 | +#include <das2/core.h> |
| 32 | + |
| 33 | +/* State ******************************************************************** */ |
| 34 | + |
| 35 | +int g_nTimeWidth = 24; /* default to 'time24' */ |
| 36 | +const char* g_sTimeFmt = NULL; |
| 37 | + |
| 38 | +int g_n8ByteWidth = 17; /* default to 'ascii17' for 8-byte floats */ |
| 39 | +int g_n4ByteWidth = 14; /* default to 'ascii14' for 4-byte floats */ |
| 40 | +char g_sSep[12] = {';', '\0'}; |
| 41 | + |
| 42 | +/* Help ********************************************************************* */ |
| 43 | + |
| 44 | +void prnHelp(FILE* pOut) |
| 45 | +{ |
| 46 | + fprintf(pOut, |
| 47 | +"SYNOPSIS:\n" |
| 48 | +" das2_csv - Export a das2 stream to a delimited text format\n" |
| 49 | +"\n" |
| 50 | +"USAGE:\n" |
| 51 | +" das2_csv [-r DIGITS] [-s SUBSEC] [-d DELIM]\n" |
| 52 | +"\n" |
| 53 | +"DESCRIPTION\n" |
| 54 | +" das2_csv is a filter. It reads a das2 stream on standard input and writes\n" |
| 55 | +" a text delimited stream suitable for use in comman spreadsheet programs to\n" |
| 56 | +" standard output.\n" |
| 57 | +"\n" |
| 58 | +" Each das2 packet header encountered in the das2 stream is collapsed to a\n" |
| 59 | +" single text header row. Since the stream may contain any number of packet\n" |
| 60 | +" headers, the output may contain any number of header rows. Users of the\n" |
| 61 | +" output CSV data should be on the look out for this condition if it would\n" |
| 62 | +" adversely impact thier downstream software.\n" |
| 63 | +"\n" |
| 64 | +" By default the field delimiter character is a ';' (semicolon).\n" |
| 65 | +"\n" |
| 66 | +" By default 32-bit floating points numbers are written with 7 significant\n" |
| 67 | +" digits in the mantissa and 2 digits in the exponent. Any 64-bit floats\n" |
| 68 | +" encontered in the input stream are written with 17 significant digits in\n" |
| 69 | +" the mantissa and 2 digits in the exponent. Binary time values are written\n" |
| 70 | +" as ISO-8601 timestamps with microsecond resolution, i.e. the pattern\n" |
| 71 | +" yyyy-mm-ddThh:mm:ss.ssssss\n" |
| 72 | +"\n" |
| 73 | +" All output values are rounded normally instead of truncating fractions.\n" |
| 74 | +"\n" |
| 75 | +" All output text is encoded as UTF-8.\n" |
| 76 | +"\n" |
| 77 | +"OPTIONS:\n" |
| 78 | +"\n" |
| 79 | +" -h,--help\n" |
| 80 | +" Print this help text\n" |
| 81 | +"\n" |
| 82 | +" -d DELIM Change the default text delimiter from ';' (semicolon) to some\n" |
| 83 | +" other UTF-8 character.\n" |
| 84 | +"\n" |
| 85 | +" -r DIGITS Set the number of significant digits for general output. The\n" |
| 86 | +" minimum resolution is 2 significant digits.\n" |
| 87 | +"\n" |
| 88 | +" -s SUBSEC Set the sub-second resolution. Output N digits of sub-second\n" |
| 89 | +" resolution. The minimum value is 0, thus time values are\n" |
| 90 | +" are always output to at least seconds resolution.\n" |
| 91 | +"\n" |
| 92 | +"AUTHORS:\n" |
| 93 | +" chris-piker@uiowa.edu\n" |
| 94 | +"\n" |
| 95 | +"SEE ALSO:\n" |
| 96 | +" das2_ascii, das2_binary, das2_hapi\n" |
| 97 | +"\n" |
| 98 | +" and the das 2 ICD @ http://das2.org for an introduction to the das 2 system.\n" |
| 99 | +"\n"); |
| 100 | +} |
| 101 | + |
| 102 | +/* Headers ****************************************************************** */ |
| 103 | + |
| 104 | +DasErrCode OnPktHdr(StreamDesc* pSdIn, PktDesc* pPdIn, void* vpSep) |
| 105 | +{ |
| 106 | + /* For each plane, print a header */ |
| 107 | + for |
| 108 | + |
| 109 | +} |
| 110 | + |
| 111 | +/* Data ********************************************************************* */ |
| 112 | + |
| 113 | +DasErrCode onPktData(PktDesc* pPdIn, void* vpSep) |
| 114 | +{ |
| 115 | + |
| 116 | +} |
| 117 | + |
| 118 | + |
| 119 | +/* Exceptions *************************************************************** */ |
| 120 | + |
| 121 | +DasErrCode onException(OobExcept* pExcept, void* vpSep) |
| 122 | +{ |
| 123 | + /* Can't do much here but quit with log message */ |
| 124 | + fprintf(stderr, "Stream Exception: %s, %s\n", pExcept->sType, pExcept->sMsg); |
| 125 | + |
| 126 | + return DAS_OKAY; |
| 127 | +} |
| 128 | + |
| 129 | +/* Main ********************************************************************* */ |
| 130 | + |
| 131 | +int main( int argc, char *argv[]) { |
| 132 | + |
| 133 | + int i = 0; |
| 134 | + int status = 0; |
| 135 | + int nGenRes = 7; |
| 136 | + int nSecRes = 3; |
| 137 | + char sTimeFmt[64] = {'\0'}; |
| 138 | + |
| 139 | + /* Exit on errors, log info messages and above */ |
| 140 | + das_init(argv[0], DASERR_DIS_EXIT, 0, DASLOG_INFO, NULL); |
| 141 | + |
| 142 | + for(i = 1; i < argc; i++){ |
| 143 | + if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0 ){ |
| 144 | + prnHelp(); |
| 145 | + return 0; |
| 146 | + } |
| 147 | + |
| 148 | + if(strcmp(argv[i], "-r") == 0){ |
| 149 | + i++; |
| 150 | + if(i >= argc){ |
| 151 | + fprintf(stderr, "ERROR: Resolution parameter missing after -r\n"); |
| 152 | + return 13; |
| 153 | + } |
| 154 | + nGenRes = atoi(argv[i]); |
| 155 | + if(nGenRes < 2 || nGenRes > 18){ |
| 156 | + fprintf(stderr, "ERROR: Can't format to %d significant digits, " |
| 157 | + "Supported range is only 2 to 18 significant digits.\n", |
| 158 | + nGenRes); |
| 159 | + return 13; |
| 160 | + } |
| 161 | + continue; |
| 162 | + } |
| 163 | + |
| 164 | + if(strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0){ |
| 165 | + printf("$TODO: Find a git auto substitution method$\n"); |
| 166 | + return 0; |
| 167 | + } |
| 168 | + |
| 169 | + if(strcmp(argv[i], "-s") == 0){ |
| 170 | + i++; |
| 171 | + if(i >= argc){ |
| 172 | + fprintf(stderr, "ERROR: Sub-seconds resolution parameter missing after -s\n"); |
| 173 | + return 13; |
| 174 | + } |
| 175 | + nSecRes = atoi(argv[i]); |
| 176 | + if(nSecRes < 0 || nSecRes > 9){ |
| 177 | + fprintf(stderr, "ERROR: Only 0 to 9 sub-seconds digits supported " |
| 178 | + "don't know how to handle %d sub-second digits.", nSecRes); |
| 179 | + return 13; |
| 180 | + } |
| 181 | + continue; |
| 182 | + } |
| 183 | + |
| 184 | + if(strcmp(argv[i], "-d") == 0){ |
| 185 | + for(int j = 0; (j < strlen(argv[i])) && (j < 11); ++j) |
| 186 | + sSep[j] = argv[i][j]; |
| 187 | + continue; |
| 188 | + } |
| 189 | + |
| 190 | + fprintf(stderr, "ERROR: unknown parameter '%s'\n", argv[i]); |
| 191 | + return 13; |
| 192 | + } |
| 193 | + |
| 194 | + if(nGenRes != 7){ |
| 195 | + g_n4ByteWidth = nGenRes + 7; |
| 196 | + g_n8ByteWidth = nGenRes + 7; |
| 197 | + } |
| 198 | + |
| 199 | + if(nSecRes != 3){ |
| 200 | + if(nSecRes == 0) |
| 201 | + g_nTimeWidth = 20; |
| 202 | + else |
| 203 | + g_nTimeWidth = 21 + nSecRes; |
| 204 | + |
| 205 | + sprintf(sTimeFmt, "%%04d-%%02d-%%02dT%%02d:%%02d:%%0%d.%df", |
| 206 | + nSecRes + 3, nSecRes); |
| 207 | + g_sTimeFmt = sTimeFmt; |
| 208 | + } |
| 209 | + |
| 210 | + StreamHandler* pSh = new_StreamHandler(NULL); |
| 211 | + |
| 212 | + pSh->streamDescHandler = NULL; |
| 213 | + pSh->pktDescHandler = OnPktHdr; |
| 214 | + pSh->pktDataHandler = onPktData; |
| 215 | + pSh->exceptionHandler = onException; |
| 216 | + pSh->commentHandler = NULL; |
| 217 | + pSh->closeHandler = onClose; |
| 218 | + |
| 219 | + DasIO* pIn = new_DasIO_cfile("Standard Input", stdin, "r"); |
| 220 | + DasIO_addProcessor(pIn, pSh); |
| 221 | + |
| 222 | + int nRet = DasIO_readAll(pIn); |
| 223 | + return nRet; |
| 224 | +} |
0 commit comments