LCOV - code coverage report
Current view: top level - clients/examples/C - bincopydata.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 134 157 85.4 %
Date: 2021-09-14 19:48:19 Functions: 17 18 94.4 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "bincopydata.h"
      10             : 
      11             : #ifdef _MSC_VER
      12             : #include <io.h>
      13             : #include <fcntl.h>
      14             : #endif
      15             : 
      16             : static char *exe_name = "<to_be_filled_in>";
      17             : 
      18             : static void
      19           4 : gen_tinyints(FILE *f, bool byteswap, long nrecs)
      20             : {
      21     4000004 :         for (long i = 0; i < nrecs; i++) {
      22     4000000 :                 uint8_t v = (uint8_t)i;
      23             :                 (void)byteswap;
      24     4000000 :                 fwrite(&v, sizeof(v), 1, f);
      25             :         }
      26           4 : }
      27             : 
      28             : static void
      29           8 : gen_smallints(FILE *f, bool byteswap, long nrecs)
      30             : {
      31     4000056 :         for (long i = 0; i < nrecs; i++) {
      32     4000048 :                 uint16_t v = (uint16_t)i;
      33     4000048 :                 if (byteswap) {
      34             :                         copy_binary_convert16(&v);
      35             :                 }
      36     4000048 :                 fwrite(&v, sizeof(v), 1, f);
      37             :         }
      38           8 : }
      39             : 
      40             : static void
      41           4 : gen_bigints(FILE *f, bool byteswap, long nrecs)
      42             : {
      43     4000004 :         for (long i = 0; i < nrecs; i++) {
      44     4000000 :                 uint64_t v = (uint64_t)i;
      45     4000000 :                 if (byteswap) {
      46             :                         copy_binary_convert64(&v);
      47             :                 }
      48     4000000 :                 fwrite(&v, sizeof(v), 1, f);
      49             :         }
      50           4 : }
      51             : 
      52             : #ifdef HAVE_HGE
      53             : static void
      54           1 : gen_hugeints(FILE *f, bool byteswap, long nrecs)
      55             : {
      56     1000001 :         for (long i = 0; i < nrecs; i++) {
      57     1000000 :                 uhge v = (uhge)i;
      58     1000000 :                 if (byteswap) {
      59             :                         copy_binary_convert128(&v);
      60             :                 }
      61     1000000 :                 fwrite(&v, sizeof(v), 1, f);
      62             :         }
      63           1 : }
      64             : #endif
      65             : 
      66             : static void
      67           4 : gen_ints(FILE *f, bool byteswap, long nrecs)
      68             : {
      69           4 :         assert((uintmax_t)nrecs <= (uintmax_t) UINT32_MAX);
      70           4 :         uint32_t n = (uint32_t) nrecs;
      71     4000004 :         for (uint32_t i = 0; i < n; i++) {
      72     4000000 :                 uint32_t v = i;
      73     4000000 :                 if (byteswap) {
      74     1000000 :                         copy_binary_convert32(&v);
      75             :                 }
      76     4000000 :                 fwrite(&v, sizeof(v), 1, f);
      77             :         }
      78           4 : }
      79             : 
      80             : static void
      81           1 : gen_more_ints(FILE *f, bool byteswap, long nrecs)
      82             : {
      83           1 :         assert((uintmax_t)nrecs <= (uintmax_t) UINT32_MAX);
      84           1 :         uint32_t n = (uint32_t) nrecs;
      85     1000001 :         for (uint32_t i = 0; i < n; i++) {
      86     1000000 :                 uint32_t v = i + 1;
      87     1000000 :                 if (byteswap) {
      88           0 :                         copy_binary_convert32(&v);
      89             :                 }
      90     1000000 :                 fwrite(&v, sizeof(v), 1, f);
      91             :         }
      92           1 : }
      93             : 
      94             : static void
      95           1 : gen_null_ints(FILE *f, bool byteswap, long nrecs)
      96             : {
      97           1 :         assert((uintmax_t)nrecs <= (uintmax_t) UINT32_MAX);
      98           1 :         uint32_t n = (uint32_t) nrecs;
      99             :         uint32_t nil = 0x80000000;
     100     1000001 :         for (uint32_t i = 0; i < n; i++) {
     101     1000000 :                 uint32_t v = i % 2 == 0 ? nil : i;
     102     1000000 :                 if (byteswap) {
     103           0 :                         copy_binary_convert32(&v);
     104             :                 }
     105     1000000 :                 fwrite(&v, sizeof(v), 1, f);
     106             :         }
     107           1 : }
     108             : 
     109             : static void
     110           1 : gen_bools(FILE *f, bool byteswap, long nrecs)
     111             : {
     112     1000001 :         for (long i = 0; i < nrecs; i++) {
     113     1000000 :                 char b = i % 2;
     114             :                 (void)byteswap;
     115     1000000 :                 fwrite(&b, sizeof(b), 1, f);
     116             :         }
     117           1 : }
     118             : 
     119             : static void
     120           8 : gen_floats(FILE *f, bool byteswap, long nrecs)
     121             : {
     122             :         // Assume for now that the raw bits are portable enough
     123             : 
     124     4000056 :         for (long i = 0; i < nrecs; i++) {
     125     4000048 :                 float fl = (float)i;
     126     4000048 :                 fl += 0.5;
     127     4000048 :                 if (byteswap)
     128     1000012 :                         copy_binary_convert32(&fl);
     129     4000048 :                 fwrite(&fl, sizeof(fl), 1, f);
     130             :         }
     131           8 : }
     132             : 
     133             : static void
     134           8 : gen_doubles(FILE *f, bool byteswap, long nrecs)
     135             : {
     136             :         // Assume for now that the raw bits are portable enough
     137             : 
     138     4000056 :         for (long i = 0; i < nrecs; i++) {
     139     4000048 :                 double fl = (double)i;
     140     4000048 :                 fl += 0.5;
     141     4000048 :                 if (byteswap)
     142             :                         copy_binary_convert64(&fl);
     143     4000048 :                 fwrite(&fl, sizeof(fl), 1, f);
     144             :         }
     145           8 : }
     146             : 
     147             : static void
     148           1 : gen_strings(FILE *f, bool byteswap, long nrecs)
     149             : {
     150             :         (void)byteswap;
     151     1000001 :         for (long i = 0; i < nrecs; i++) {
     152     1000000 :                 fprintf(f, "int%ld", i);
     153     1000000 :                 fputc(0, f);
     154             :         }
     155           1 : }
     156             : 
     157             : static void
     158           1 : gen_large_strings(FILE *f, bool byteswap, long nrecs)
     159             : {
     160             :         size_t n = 280000;
     161           1 :         char *buf = malloc(n);
     162           1 :         memset(buf, 'a', n);
     163     1000001 :         for (long i = 0; i < nrecs; i++) {
     164     1000000 :                 fprintf(f, "int%06ld", i);
     165     1000000 :                 if (i % 10000 == 0)
     166         100 :                         fwrite(buf, n, 1, f);
     167     1000000 :                 fputc(0, f);
     168             :         }
     169           1 :         free(buf);
     170             :         (void)byteswap;
     171           1 : }
     172             : 
     173             : static void
     174           1 : gen_broken_strings(FILE *f, bool byteswap, long nrecs)
     175             : {
     176             :         // "bröken"
     177           1 :         char utf8[] =   {0x62, 0x72,   0xc3, 0xb6,   0x6b, 0x65, 0x6e, 0x00};
     178           1 :         char latin1[] = {0x62, 0x72,   0xf6,         0x6b, 0x65, 0x6e, 0x00};
     179             : 
     180             :         (void)byteswap;
     181     1000001 :         for (long i = 0; i < nrecs; i++) {
     182     1000000 :                 if (i == 123456)
     183           1 :                         fwrite(latin1, sizeof(latin1), 1, f);
     184             :                 else
     185      999999 :                         fwrite(utf8, sizeof(utf8), 1, f);
     186             :         }
     187           1 : }
     188             : 
     189             : static void
     190           1 : gen_newline_strings(FILE *f, bool byteswap, long nrecs)
     191             : {
     192             :         (void)byteswap;
     193     1000001 :         for (long i = 0; i < nrecs; i++) {
     194     1000000 :                 fprintf(f, "RN\r\nR\r%ld", i);
     195     1000000 :                 fputc(0, f);
     196             :         }
     197           1 : }
     198             : 
     199             : static void
     200           1 : gen_null_strings(FILE *f, bool byteswap, long nrecs)
     201             : {
     202             :         (void)byteswap;
     203     1000001 :         for (long i = 0; i < nrecs; i++) {
     204     1000000 :                 if (i % 2 == 0)
     205      500000 :                         fputc(0x80, f);
     206             :                 else
     207      500000 :                         fputs("banana", f);
     208     1000000 :                 fputc(0, f);
     209             :         }
     210           1 : }
     211             : 
     212             : static void
     213           1 : gen_json(FILE *f, bool byteswap, long nrecs)
     214             : {
     215             :         (void)byteswap;
     216     1000001 :         for (long i = 0; i < nrecs; i++) {
     217     1000000 :                 if (i % 100 == 99) {
     218       10000 :                         fputc('\x80', f);
     219             :                 } else {
     220      990000 :                         fprintf(f, "{\"id\": %ld, \"msg\":\n\"int%ld\"}", i, i);
     221             :                 }
     222     1000000 :                 fputc('\0', f);
     223             :         }
     224           1 : }
     225             : 
     226             : static struct gen {
     227             :         char *name;
     228             :         void (*gen)(FILE *f, bool byteswap, long nrecs);
     229             : } generators[] = {
     230             :         { "ints", gen_ints },
     231             :         { "more_ints", gen_more_ints },
     232             :         { "null_ints", gen_null_ints },
     233             :         { "bools", gen_bools },
     234             :         { "floats", gen_floats },
     235             :         { "doubles", gen_doubles },
     236             :         { "tinyints", gen_tinyints },
     237             :         { "smallints", gen_smallints },
     238             :         { "bigints", gen_bigints },
     239             : #ifdef HAVE_HGE
     240             :         { "hugeints", gen_hugeints },
     241             : #endif
     242             :         //
     243             :         { "strings", gen_strings },
     244             :         { "large_strings", gen_large_strings },
     245             :         { "broken_strings", gen_broken_strings },
     246             :         { "newline_strings", gen_newline_strings },
     247             :         { "null_strings", gen_null_strings },
     248             :         //
     249             :         { "timestamps", gen_timestamps },
     250             :         { "timestamp_times", gen_timestamp_times },
     251             :         { "timestamp_dates", gen_timestamp_dates },
     252             :         { "timestamp_ms", gen_timestamp_ms },
     253             :         { "timestamp_seconds", gen_timestamp_seconds },
     254             :         { "timestamp_minutes", gen_timestamp_minutes },
     255             :         { "timestamp_hours", gen_timestamp_hours },
     256             :         { "timestamp_days", gen_timestamp_days },
     257             :         { "timestamp_months", gen_timestamp_months },
     258             :         { "timestamp_years", gen_timestamp_years },
     259             : 
     260             :         { "json_objects", gen_json },
     261             : 
     262             :         { "binary_uuids", gen_bin_uuids },
     263             :         { "text_uuids", gen_text_uuids },
     264             : 
     265             :         { NULL, NULL },
     266             : };
     267             : 
     268             : _Noreturn static void croak(int status, const char *msg, ...)
     269             :         __attribute__((__format__(__printf__, 2, 3)));
     270             : 
     271             : /* Format the message and write it to stderr. Then exit with the given status.
     272             :  * If status is 1, include USAGE in the message.
     273             :  * Otherwise, if errno is set, include the error message.
     274             :  */
     275             : static void
     276           0 : croak(int status, const char *ctx, ...)
     277             : {
     278             :         va_list ap;
     279             : 
     280           0 :         fprintf(stderr, "Error: ");
     281           0 :         if (ctx != NULL) {
     282           0 :                 fprintf(stderr, " ");
     283           0 :                 va_start(ap, ctx);
     284           0 :                 vfprintf(stderr, ctx, ap);
     285           0 :                 va_end(ap);
     286             :         }
     287           0 :         fprintf(stderr, "\n");
     288           0 :         if (errno) {
     289           0 :                 fprintf(stderr, "Possibly due to: %s\n", strerror(errno));
     290           0 :         } else if (status == 1) {
     291           0 :                 fprintf(stderr, "USAGE: %s TYPE NRECS DESTFILE\n", exe_name);
     292           0 :                 fprintf(stderr, "TYPE:\n");
     293           0 :                 for (struct gen *g = generators; g->name != NULL; g++) {
     294           0 :                         fprintf(stderr, "  - %s\n", g->name);
     295             :                 }
     296             :         }
     297           0 :         exit(status);
     298             : }
     299             : 
     300             : int
     301          58 : main(int argc, char *argv[])
     302             : {
     303          58 :         exe_name = argv[0];
     304             :         void (*gen)(FILE*, bool, long);
     305             :         long nrecs;
     306             :         FILE *dest;
     307             :         bool byteswap = false;
     308             :         bool i_am_little_endian =
     309             : #ifdef WORDS_BIGENDIAN
     310             :                 false
     311             : #else
     312             :                 true
     313             : #endif
     314             :         ;
     315             :         bool i_am_big_endian = !i_am_little_endian;
     316             : 
     317          58 :         char **args = &argv[1];
     318          58 :         char **args_end = &argv[argc];
     319             : 
     320          85 :         while (args < args_end && **args == '-') {
     321          27 :                 char *arg = *args++;
     322          27 :                 if (strcmp(arg, "--native-endian") == 0)
     323             :                         byteswap = false;
     324          18 :                 else if (strcmp(arg, "--big-endian") == 0)
     325             :                         byteswap = i_am_little_endian;
     326           9 :                 else if (strcmp(arg, "--little-endian") == 0)
     327             :                         byteswap = i_am_big_endian;
     328             :                 else
     329           0 :                         croak(1, "Unexpected argument: %s", arg);
     330             :         }
     331             : 
     332          58 :         if (args_end - args != 3)
     333           0 :                 croak(1, "Unexpected number of arguments");
     334             : 
     335             :         gen = NULL;
     336         590 :         for (struct gen *g = generators; g->name; g++) {
     337         590 :                 if (strcmp(g->name, args[0]) == 0) {
     338          58 :                         gen = g->gen;
     339          58 :                         break;
     340             :                 }
     341             :         }
     342          58 :         if (gen == NULL)
     343           0 :                 croak(1, "Unknown TYPE: %s", args[0]);
     344             : 
     345             :         char *end;
     346          58 :         nrecs = strtol(args[1], &end, 10);
     347          58 :         if (*end != '\0')
     348           0 :                 croak(1, "NRECS must be an integer, not '%s'", args[1]);
     349             : 
     350          58 :         char *destfilename = args[2];
     351          58 :         if (strcmp(destfilename, "-") == 0) {
     352             : #ifdef _MSC_VER
     353             :                 _setmode(1, O_BINARY);
     354             : #endif
     355          12 :                 dest = stdout;
     356             :         } else {
     357          46 :                 dest = fopen(destfilename, "wb");
     358             :         }
     359             : 
     360          58 :         if (dest == NULL)
     361           0 :                 croak(2, "Cannot open '%s' for writing", args[2]);
     362             : 
     363          58 :         gen(dest, byteswap, nrecs);
     364             : 
     365          58 :         fclose(dest);
     366             : 
     367             :         return 0;
     368             : }

Generated by: LCOV version 1.14