csvtofsv.c - csvtofsv - Convert CSV to FSV (`fs' (0x1c) as FS and `rs' (0x1e) as RS)
 (HTM) hg clone https://bitbucket.org/iamleot/csvtofsv
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
       csvtofsv.c
       ---
            1 /*-
            2  * Copyright (c) 2019 Leonardo Taccari
            3  * All rights reserved.
            4  *
            5  * Redistribution and use in source and binary forms, with or without
            6  * modification, are permitted provided that the following conditions
            7  * are met:
            8  *
            9  * 1. Redistributions of source code must retain the above copyright
           10  *    notice, this list of conditions and the following disclaimer.
           11  * 2. Redistributions in binary form must reproduce the above copyright
           12  *    notice, this list of conditions and the following disclaimer in the
           13  *    documentation and/or other materials provided with the distribution.
           14  *
           15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
           16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
           17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
           18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
           19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
           20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
           21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
           22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
           23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
           24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
           25  * POSSIBILITY OF SUCH DAMAGE.
           26  */
           27 
           28 
           29 #include <stdbool.h>
           30 #include <stdio.h>
           31 
           32 
           33 #define FS      034
           34 #define RS      036
           35 
           36 
           37 /*
           38  * Convert a CSV from stdin to FSV with `fs' ASCII char (0x1c) as field
           39  * separator and `rs' ASCII char (0x1e) as record separator.
           40  */
           41 int
           42 main(int argc, char *argv[])
           43 {
           44         int c, nc, pc;
           45         bool first, quoted;
           46 
           47         first = true;
           48         quoted = false;
           49         pc = '\0';
           50         while ((c = getchar()) != EOF) {
           51                 pc = c;
           52                 switch (c) {
           53                 case '"':
           54                         if (first) {
           55                                 quoted = true;
           56                                 first = false;
           57                         } else if (!quoted) {
           58                                 /*
           59                                  * RFC 4180 says: `Fields containing [...]
           60                                  * double quotes [...] should be enclosed in
           61                                  * double-quotes.'.  This violates that by
           62                                  * printing alone `"' as-is.
           63                                  */
           64                                 putchar(c);
           65                         } else if ((nc = getchar()) != EOF) {
           66                                 pc = nc;
           67                                 if (nc == '"') {
           68                                         putchar('"');
           69                                 } else if (nc == ',') {
           70                                         putchar(FS);
           71                                         first = true;
           72                                         quoted = false;
           73                                 } else if ((nc == '\n') ||
           74                                           ((nc == '\r') &&
           75                                               ((nc = getchar()) == '\n'))) {
           76                                         pc = nc;
           77                                         putchar(RS);
           78                                         first = true;
           79                                         quoted = false;
           80                                 } else {
           81                                         ungetc(nc, stdin);
           82                                 }
           83                         }
           84                         break;
           85                 case ',':
           86                         if (quoted) {
           87                                 putchar(',');
           88                         } else {
           89                                 putchar(FS);
           90                                 first = true;
           91                         }
           92                         break;
           93                 case '\n':
           94                         if (quoted) {
           95                                 putchar('\n');
           96                         } else {
           97                                 putchar(RS);
           98                                 first = true;
           99                         }
          100                         break;
          101                 case '\r':
          102                         /* ignore */
          103                         break;
          104                 case FS:
          105                         fprintf(stderr, "FS character found, stopping.\n");
          106                         return 1;
          107                         break; /* NOTREACHED */
          108                 case RS:
          109                         fprintf(stderr, "RS character found, stopping.\n");
          110                         return 1;
          111                         break; /* NOTREACHED */
          112                 default:
          113                         putchar(c);
          114                         break;
          115                 }
          116         }
          117 
          118         if (pc != '\0' && pc != '\n')
          119                 putchar(RS);
          120 
          121         return 0;
          122 }