1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2005,2008 Oracle. All rights reserved. 5 * 6 * $Id: util.c,v 1.23 2008/01/08 20:58:23 bostic Exp $ 7 */ 8 9#include "csv.h" 10#include "csv_local.h" 11#include "csv_extern.h" 12 13/* 14 * entry_print -- 15 * Display the primary database's data item. 16 */ 17int 18entry_print(void *data, size_t len, u_int32_t field_count) 19{ 20 u_int32_t a, *offset; 21 u_int i; 22 char *raw; 23 24 memcpy(&a, data, sizeof(u_int32_t)); 25 printf("\tversion: %lu\n", (u_long)a); 26 27 offset = (u_int32_t *)data + 1; 28 if (field_count == 0) { 29 memcpy(&a, offset++, sizeof(u_int32_t)); 30 printf("\tcolumn map: %lu fields: {%.*s}\n", (u_long)a, 31 (int)(len - 2 * sizeof(u_int32_t)), 32 (u_int8_t *)data + 2 * sizeof(u_int32_t)); 33 } else { 34 raw = (char *)(offset + (field_count + 1)); 35 for (i = 0; i < field_count; ++i) { 36 memcpy(&a, &offset[i], sizeof(u_int32_t)); 37 len = OFFSET_LEN(offset, i); 38 printf("\toffset %4lu: len %4lu: {%.*s}\n", 39 (u_long)offset[i], 40 (u_long)len, (int)len, raw + a); 41 } 42 } 43 44 return (0); 45} 46 47/* 48 * strtod_err -- 49 * strtod(3) with error checking. 50 */ 51int 52strtod_err(char *input, double *valp) 53{ 54 double val; 55 char *end; 56 57 /* 58 * strtoul requires setting errno to detect errors. 59 */ 60 errno = 0; 61 val = strtod(input, &end); 62 if (errno == ERANGE) { 63 dbenv->err(dbenv, ERANGE, "%s", input); 64 return (1); 65 } 66 if (input[0] == '\0' || 67 (end[0] != '\0' && end[0] != '\n' && !isspace(end[0]))) { 68 dbenv->errx(dbenv, 69 "%s: invalid floating point argument", input); 70 return (1); 71 } 72 73 *valp = val; 74 return (0); 75} 76 77/* 78 * strtoul_err -- 79 * strtoul(3) with error checking. 80 */ 81int 82strtoul_err(char *input, u_long *valp) 83{ 84 u_long val; 85 char *end; 86 87 /* 88 * strtoul requires setting errno to detect errors. 89 */ 90 errno = 0; 91 val = strtoul(input, &end, 10); 92 if (errno == ERANGE) { 93 dbenv->err(dbenv, ERANGE, "%s", input); 94 return (1); 95 } 96 if (input[0] == '\0' || 97 (end[0] != '\0' && end[0] != '\n' && !isspace(end[0]))) { 98 dbenv->errx(dbenv, "%s: invalid unsigned long argument", input); 99 return (1); 100 } 101 102 *valp = val; 103 return (0); 104} 105 106int 107secondary_callback(DB *db_arg, const DBT *key, const DBT *data, DBT *result) 108{ 109 DbField *f; 110 DbRecord record; 111 void *faddr, *addr; 112 113 /* Populate the field. */ 114 if (DbRecord_init(key, data, &record) != 0) 115 return (-1); 116 117 f = db_arg->app_private; 118 faddr = (u_int8_t *)&record + f->offset; 119 120 /* 121 * If necessary, copy the field into separate memory. 122 * Set up the result DBT. 123 */ 124 switch (f->type) { 125 case STRING: 126 result->data = *(char **)faddr; 127 result->size = strlen(*(char **)faddr) + 1; 128 break; 129 case DOUBLE: 130 if ((addr = malloc(sizeof(double))) == NULL) 131 return (-1); 132 result->data = addr; 133 result->size = sizeof(double); 134 result->flags = DB_DBT_APPMALLOC; 135 memcpy(addr, faddr, sizeof(double)); 136 break; 137 case UNSIGNED_LONG: 138 if ((addr = malloc(sizeof(u_long))) == NULL) 139 return (-1); 140 result->data = addr; 141 result->size = sizeof(u_long); 142 result->flags = DB_DBT_APPMALLOC; 143 memcpy(addr, faddr, sizeof(u_long)); 144 break; 145 default: 146 case NOTSET: 147 abort(); 148 /* NOTREACHED */ 149 } 150 151 return (0); 152} 153 154/* 155 * compare_double -- 156 * Compare two keys. 157 */ 158int 159compare_double(DB *db_arg, const DBT *a_arg, const DBT *b_arg) 160{ 161 double a, b; 162 163 db_arg = db_arg; /* Quiet compiler. */ 164 165 memcpy(&a, a_arg->data, sizeof(double)); 166 memcpy(&b, b_arg->data, sizeof(double)); 167 return (a > b ? 1 : ((a < b) ? -1 : 0)); 168} 169 170/* 171 * compare_ulong -- 172 * Compare two keys. 173 */ 174int 175compare_ulong(DB *db_arg, const DBT *a_arg, const DBT *b_arg) 176{ 177 u_long a, b; 178 179 db_arg = db_arg; /* Quiet compiler. */ 180 181 memcpy(&a, a_arg->data, sizeof(u_long)); 182 memcpy(&b, b_arg->data, sizeof(u_long)); 183 return (a > b ? 1 : ((a < b) ? -1 : 0)); 184} 185 186/* 187 * field_cmp_double -- 188 * Compare two double. 189 */ 190int 191field_cmp_double(void *a, void *b, OPERATOR op) 192{ 193 switch (op) { 194 case GT: 195 return (*(double *)a > *(double *)b); 196 case GTEQ: 197 return (*(double *)a >= *(double *)b); 198 case LT: 199 return (*(double *)a < *(double *)b); 200 case LTEQ: 201 return (*(double *)a <= *(double *)b); 202 case NEQ: 203 return (*(double *)a != *(double *)b); 204 case EQ: 205 return (*(double *)a == *(double *)b); 206 case WC: 207 case NWC: 208 break; 209 } 210 211 abort(); 212 /* NOTREACHED */ 213} 214 215/* 216 * field_cmp_re -- 217 * Compare against regular expression. 218 */ 219int 220field_cmp_re(void *a, void *b, OPERATOR op) 221{ 222 op = op; /* Quiet compiler. */ 223 224 switch (op) { 225#ifdef HAVE_WILDCARD_SUPPORT 226 case WC: 227 return (regexec(b, *(char **)a, 0, NULL, 0) == 0); 228 case NWC: 229 return (regexec(b, *(char **)a, 0, NULL, 0) != 0); 230#else 231 case WC: 232 case NWC: 233 a = a; 234 b = b; /* Quiet compiler. */ 235 /* FALLTHROUGH */ 236#endif 237 case GT: 238 case GTEQ: 239 case LT: 240 case LTEQ: 241 case NEQ: 242 case EQ: 243 break; 244 } 245 246 abort(); 247 /* NOTREACHED */ 248} 249 250/* 251 * field_cmp_string -- 252 * Compare two strings. 253 */ 254int 255field_cmp_string(void *a, void *b, OPERATOR op) 256{ 257 int v; 258 259 v = strcasecmp(*(char **)a, b); 260 switch (op) { 261 case GT: 262 return (v > 0 ? 1 : 0); 263 case GTEQ: 264 return (v >= 0 ? 1 : 0); 265 case LT: 266 return (v < 0 ? 1 : 0); 267 case LTEQ: 268 return (v <= 0 ? 1 : 0); 269 case NEQ: 270 return (v ? 1 : 0); 271 case EQ: 272 return (v ? 0 : 1); 273 case WC: 274 case NWC: 275 break; 276 } 277 278 abort(); 279 /* NOTREACHED */ 280} 281 282/* 283 * field_cmp_ulong -- 284 * Compare two ulongs. 285 */ 286int 287field_cmp_ulong(void *a, void *b, OPERATOR op) 288{ 289 switch (op) { 290 case GT: 291 return (*(u_long *)a > *(u_long *)b); 292 case GTEQ: 293 return (*(u_long *)a >= *(u_long *)b); 294 case LT: 295 return (*(u_long *)a < *(u_long *)b); 296 case LTEQ: 297 return (*(u_long *)a <= *(u_long *)b); 298 case NEQ: 299 return (*(u_long *)a != *(u_long *)b); 300 case EQ: 301 return (*(u_long *)a == *(u_long *)b); 302 case WC: 303 case NWC: 304 break; 305 } 306 307 abort(); 308 /* NOTREACHED */ 309} 310