1 /*
2 * (C) Copyright 2005- ECMWF.
3 *
4 * This software is licensed under the terms of the Apache Licence Version 2.0
5 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6 *
7 * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
8 * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
9 */
10
11 /*
12 *
13 * Description: grib database routines
14 *
15 */
16 #include "grib_api_internal.h"
17 #define GRIB_START_ARRAY_SIZE 5000
18 #define GRIB_ARRAY_INCREMENT 1000
19
20 #define SWAP(a, b) \
21 temp = (a); \
22 (a) = (b); \
23 (b) = temp;
24
25 #define GRIB_ORDER_BY_ASC 1
26 #define GRIB_ORDER_BY_DESC -1
27
28 /* Note: A fast cut-down version of strcmp which does NOT return -1 */
29 /* 0 means input strings are equal and 1 means not equal */
grib_inline_strcmp(const char * a,const char * b)30 GRIB_INLINE static int grib_inline_strcmp(const char* a, const char* b)
31 {
32 if (*a != *b)
33 return 1;
34 while ((*a != 0 && *b != 0) && *(a) == *(b)) {
35 a++;
36 b++;
37 }
38 return (*a == 0 && *b == 0) ? 0 : 1;
39 }
40
41 static int grib_db_new_column(grib_db* db, int id, char* key, int type);
42 static void grib_db_delete_columns(grib_db* db);
43 static int grib_db_columns_resize(grib_db* db, size_t newsize);
44 static int grib_db_column_copy_from_handle(grib_handle* h, grib_db* db, int i);
45 static grib_db* grib_db_create_from_keys(grib_context* c, char** keys, int nkeys, int* err);
46 static void grib_fieldset* grib_db_fieldset_create(grib_db* db, int* err);
47 static int grib_fieldset_compare(grib_fieldset* set, int* i, int* j);
48 static void grib_db_sort(grib_set* set, int beg, int theEnd);
49 static grib_order_by* grib_db_new_order_by(grib_context* c, char* obstr);
50 static void grib_db_delete_order_by(grib_context* c, grib_order_by* order_by);
51 static int grib_db_resize(grib_db* db, size_t newsize);
52 static int grib_db_resize_fields(grib_db* db, size_t newsize);
53
54
55 /* --------------- grib_column functions ------------------*/
grib_db_new_column(grib_db * db,int id,char * key,int type)56 static int grib_db_new_column(grib_db* db, int id, char* key, int type)
57 {
58 grib_column* column = 0;
59 grib_context* c;
60 int err = 0;
61
62 if (!db)
63 return GRIB_INVALID_ARGUMENT;
64
65 c = db->context;
66
67 db->columns[id].errors = (int*)grib_context_malloc(c,
68 sizeof(int) * GRIB_START_ARRAY_SIZE);
69
70 switch (type) {
71 case GRIB_TYPE_LONG:
72 db->columns[id].long_values = (long*)grib_context_malloc(c,
73 sizeof(long) * GRIB_START_ARRAY_SIZE);
74 if (!db->columns[id].long_values) {
75 grib_context_log(c, GRIB_LOG_ERROR,
76 "grib_db_new_column : Cannot malloc %d bytes",
77 sizeof(long) * GRIB_START_ARRAY_SIZE);
78 err = GRIB_OUT_OF_MEMORY;
79 return err;
80 }
81 break;
82 case GRIB_TYPE_DOUBLE:
83 db->columns[id].double_values = (double*)grib_context_malloc(c,
84 sizeof(double) * GRIB_START_ARRAY_SIZE);
85 if (!db->columns[id].double_values) {
86 grib_context_log(c, GRIB_LOG_ERROR,
87 "grib_db_new_column : Cannot malloc %d bytes",
88 sizeof(double) * GRIB_START_ARRAY_SIZE);
89 err = GRIB_OUT_OF_MEMORY;
90 return err;
91 }
92 break;
93 case GRIB_TYPE_STRING:
94 db->columns[id].string_values = (char**)grib_context_malloc(c,
95 sizeof(char*) * GRIB_START_ARRAY_SIZE);
96 if (!db->columns[id].string_values) {
97 grib_context_log(c, GRIB_LOG_ERROR,
98 "grib_db_new_column : Cannot malloc %d bytes",
99 sizeof(char*) * GRIB_START_ARRAY_SIZE);
100 err = GRIB_OUT_OF_MEMORY;
101 return err;
102 }
103 break;
104 default:
105 grib_context_log(c, GRIB_LOG_ERROR,
106 "grib_db_new_column : unknown column type %d", type);
107 grib_context_free(c, column);
108 return err;
109 }
110
111 db->columns[id].context = c;
112 db->columns[id].name = strdup(key);
113 db->columns[id].type = type;
114 db->columns[id].values_array_size = GRIB_START_ARRAY_SIZE;
115 db->columns[id].size = 0;
116 return err;
117 }
118
grib_db_delete_columns(grib_db * db)119 static void grib_db_delete_columns(grib_db* db)
120 {
121 int i = 0;
122 grib_context* c;
123
124 if (!set)
125 return;
126 c = db->context;
127
128 for (i = 0; i < db->columns_size; i++) {
129 switch (db->columns[i].type) {
130 case GRIB_TYPE_LONG:
131 grib_context_free(c, db->columns[i].long_values);
132 break;
133 case GRIB_TYPE_DOUBLE:
134 grib_context_free(c, db->columns[i].double_values);
135 break;
136 case GRIB_TYPE_STRING:
137 for (i = 0; i < db->columns[i].size; i++)
138 grib_context_free(c, db->columns[i].string_values[i]);
139 grib_context_free(c, db->columns[i].string_values);
140 break;
141 default:
142 grib_context_log(c, GRIB_LOG_ERROR,
143 "grib_db_new_column : unknown column type %d", db->columns[i].type);
144 }
145 grib_context_free(c, db->columns[i].errors);
146 free(db->columns[i].name);
147 }
148 grib_context_free(c, db->columns);
149 }
150
grib_db_columns_resize(grib_db * db,size_t newsize)151 static int grib_db_columns_resize(grib_db* db, size_t newsize)
152 {
153 double* newdoubles;
154 long* newlongs;
155 char** newstrings;
156 int* newerrors;
157 int i = 0;
158 grib_context* c;
159
160 if (!db || !db->columns)
161 return GRIB_INVALID_ARGUMENT;
162
163 c = db->context;
164
165 if (newsize <= db->columns[0].values_array_size)
166 return 0;
167
168 for (i = 0; i < db->columns_size; i++) {
169 switch (db->columns[i].type) {
170 case GRIB_TYPE_LONG:
171 newlongs = (long*)grib_context_realloc(c, db->columns[i].long_values,
172 newsize * sizeof(long));
173 if (!newlongs) {
174 grib_context_log(c, GRIB_LOG_ERROR,
175 "grib_db_columns_resize : Cannot malloc %d bytes", newsize - db->columns[i].values_array_size);
176 return GRIB_OUT_OF_MEMORY;
177 }
178 else
179 db->columns[i].long_values = newlongs;
180 break;
181 case GRIB_TYPE_DOUBLE:
182 newdoubles = (double*)grib_context_realloc(c, db->columns[i].double_values,
183 newsize * sizeof(double));
184 if (!newdoubles) {
185 grib_context_log(c, GRIB_LOG_ERROR,
186 "grib_db_columns_resize : Cannot malloc %d bytes", newsize - db->columns[i].values_array_size);
187 return GRIB_OUT_OF_MEMORY;
188 }
189 else
190 db->columns[i].double_values = newdoubles;
191 break;
192 case GRIB_TYPE_STRING:
193 newstrings = (char**)grib_context_realloc(c, db->columns[i].string_values,
194 newsize * sizeof(char*));
195 if (!newstrings) {
196 grib_context_log(c, GRIB_LOG_ERROR,
197 "grib_db_columns_resize : Cannot malloc %d bytes", newsize - db->columns[i].values_array_size);
198 return GRIB_OUT_OF_MEMORY;
199 }
200 else
201 db->columns[i].string_values = newstrings;
202 break;
203 }
204 newerrors = (int*)grib_context_realloc(c, db->columns[i].errors, newsize * sizeof(int));
205 if (!newerrors) {
206 grib_context_log(c, GRIB_LOG_ERROR,
207 "grib_db_columns_resize : Cannot malloc %d bytes",
208 db->columns[i].errors, newsize * sizeof(int));
209 return GRIB_OUT_OF_MEMORY;
210 }
211 else
212 db->columns[i].errors = newerrors;
213
214 db->columns[i].values_array_size = newsize;
215 }
216
217 return GRIB_SUCCESS;
218 }
219
grib_db_column_copy_from_handle(grib_handle * h,grib_db * db,int i)220 static int grib_db_column_copy_from_handle(grib_handle* h, grib_db* db, int i)
221 {
222 int err = 0;
223 long lval = 0;
224 double dval = 0;
225 char sval[1024];
226 size_t slen = 1024;
227 if (!db || !h || db->columns[i].type == 0)
228 return GRIB_INVALID_ARGUMENT;
229
230 if (db->columns[i].size >= db->columns[i].values_array_size)
231 grib_db_columns_resize(db, db->columns[i].values_array_size + GRIB_ARRAY_INCREMENT);
232
233 switch (db->columns[i].type) {
234 case GRIB_TYPE_LONG:
235 err = grib_get_long(h, db->columns[i].name, &lval);
236 db->columns[i].long_values[db->columns[i].size] = lval;
237 break;
238 case GRIB_TYPE_DOUBLE:
239 err = grib_get_double(h, db->columns[i].name, &dval);
240 db->columns[i].double_values[db->columns[i].size] = dval;
241 break;
242 case GRIB_TYPE_STRING:
243 err = grib_get_string(h, db->columns[i].name, sval, &slen);
244 db->columns[i].string_values[db->columns[i].size] = strdup(sval);
245 break;
246 }
247
248 db->columns[i].errors[db->columns[i].size] = err;
249 db->columns[i].size++;
250
251 return err;
252 }
253
254 /* --------------- grib_db functions ------------------*/
255 #if 0
256 grib_db* grib_db_new_from_files(grib_context* c, char* filenames[],
257 int nfiles, char** keys, int nkeys, int* err)
258 {
259 int i = 0;
260 int ret = GRIB_SUCCESS;
261
262 grib_db* db = 0;
263
264 if (!c)
265 c = grib_context_get_default();
266
267 if (((!keys || nkeys == 0)) || !filenames) {
268 *err = GRIB_INVALID_ARGUMENT;
269 return NULL;
270 }
271
272 db = grib_db_new_from_file(c, filenames[0], keys, nkeys, err);
273 if (!db || *err != GRIB_SUCCESS)
274 return db;
275
276 *err = GRIB_SUCCESS;
277 for (i = 1; i < nfiles; i++) {
278 ret = grib_db_load(db, filenames[i]);
279 if (ret != GRIB_SUCCESS)
280 *err = ret;
281 }
282
283 return db;
284 }
285
286 grib_db* grib_db_new_from_file(grib_context* c, char* filename,
287 char** keys, int nkeys, int* err)
288 {
289 int i = 0;
290 int ret = GRIB_SUCCESS;
291
292 grib_db* db = 0;
293
294 if (!c)
295 c = grib_context_get_default();
296
297 if (((!keys || nkeys == 0)) || !filename) {
298 *err = GRIB_INVALID_ARGUMENT;
299 return NULL;
300 }
301
302 db = grib_db_create_from_keys(c, keys, nkeys, err);
303
304 *err = GRIB_SUCCESS;
305 ret = grib_db_load(db, filename);
306 if (ret != GRIB_SUCCESS)
307 *err = ret;
308
309 return db;
310 }
311 #endif
312
grib_db_create_from_keys(grib_context * c,char ** keys,int nkeys,int * err)313 static grib_db* grib_db_create_from_keys(grib_context* c, char** keys, int nkeys, int* err)
314 {
315 grib_db* db = 0;
316 size_t msize = 0, size = 0;
317 int i = 0;
318 int type = 0;
319 int default_type = GRIB_TYPE_DOUBLE;
320
321 if (!c)
322 c = grib_context_get_default();
323
324 size = GRIB_START_ARRAY_SIZE;
325
326 msize = sizeof(grib_db);
327 db = (grib_db*)grib_context_malloc(c, msize);
328 if (!db) {
329 grib_context_log(c, GRIB_LOG_ERROR,
330 "grib_db_create : Cannot malloc %d bytes", msize);
331 return NULL;
332 }
333
334 db->context = c;
335 db->size = 0;
336 db->fields_array_size = size;
337 db->fields = 0;
338 db->columns = 0;
339
340 db->fields = grib_db_create_fields(db->context, size);
341
342 db->columns = (grib_column*)grib_context_malloc(c, sizeof(grib_column) * nkeys);
343 if (!set->columns) {
344 grib_context_log(c, GRIB_LOG_ERROR, "grib_db_new_query: memory allocation error");
345 *err = GRIB_OUT_OF_MEMORY;
346 return NULL;
347 }
348 for (i = 0; i < nkeys; i++) {
349 char* key = strdup(keys[i]);
350 char* p = key;
351 while (*p != ':' && *p != '\0')
352 p++;
353 if (*p == ':') {
354 type = grib_type_to_int(*(p + 1));
355 *p = '\0';
356 }
357 else {
358 type = default_type;
359 }
360 *err = grib_db_new_column(db, i, key, type);
361 free(key);
362 }
363
364 db->columns_size = nkeys;
365
366 return db;
367 }
368
grib_db_delete(grib_db * db)369 void grib_db_delete(grib_db* db)
370 {
371 grib_context* c = 0;
372 if (!db)
373 return;
374
375 c = set->context;
376
377 grib_db_delete_columns(db);
378
379 grib_db_delete_fields(db);
380
381 grib_context_free(c, db);
382 }
383
grib_db_new_query(grib_context * c,const char * where_string,const char * order_by_string)384 grib_query* grib_db_new_query(grib_context* c, const char* where_string,
385 const char* order_by_string)
386 {
387 grib_query* q = 0;
388
389 if (!c)
390 c = grib_context_get_default();
391
392 q = (grib_query*)grib_context_malloc(c, sizeof(grib_query));
393
394 q->where_string = 0;
395 q->order_by = 0;
396
397 if (where_string)
398 q->where_string = strdup(where_string);
399
400 if (order_by_string) {
401 q->order_by = grib_db_new_order_by(set->context, (char*)order_by_string);
402 if ((err = grib_db_set_order_by(set, ob)) != GRIB_SUCCESS)
403 return q;
404 }
405
406 return q;
407 }
408
grib_db_execute(grib_db * db,grib_query * query,int * err)409 grib_fieldset* grib_db_execute(grib_db* db, grib_query* query, int* err)
410 {
411 grib_fieldset* set = NULL;
412
413 if (!db) {
414 *err = GRIB_INVALID_ARGUMENT;
415 return NULL;
416 }
417 set = grib_db_fieldset_create(db, err);
418 if (*err != GRIB_SUCCESS)
419 return set;
420
421 set->query = query;
422
423 *err = grib_db_apply_where(set, query->where_string);
424 if (*err != GRIB_SUCCESS)
425 return set;
426
427 *err = grib_db_apply_order_by(set, query->order_by);
428 if (*err != GRIB_SUCCESS)
429 return set;
430
431 return set;
432 }
433
grib_db_fieldset_create(grib_db * db,int * err)434 static void grib_fieldset* grib_db_fieldset_create(grib_db* db, int* err)
435 {
436 grib_fieldset* set = (grib_fieldset*)grib_context_malloc(db->context,
437 sizeof(grib_fieldset));
438
439 if (!set) {
440 *err = GRIB_OUT_OF_MEMORY;
441 return NULL;
442 }
443
444 set->db = db;
445 set->context = db->context;
446 set->grib_query = NULL;
447 set->size = 0;
448 set->filter = NULL;
449 set->order = NULL;
450
451 return set;
452 }
453
grib_db_apply_where(grib_fieldset * set)454 int grib_db_apply_where(grib_fieldset* set)
455 {
456 int err = GRIB_SUCCESS;
457 grib_math* m = 0;
458
459 if (!set)
460 return GRIB_INVALID_ARGUMENT;
461
462 /*
463 m=grib_math_new(set->context,where_string,&err);
464
465 print_math(m);
466 printf("\n");
467 */
468
469 if (set->filter)
470 grib_db_delete_int_array(set->filter);
471 set->filter = grib_db_create_int_array(set->context, db->size);
472
473 if (set->order)
474 grib_db_delete_int_array(set->order);
475 set->order = grib_db_create_int_array(set->context, db->size);
476
477 for (i = 0; i < db->size; i++)
478 set->filter[i] = i;
479
480 return err;
481 }
482
grib_db_apply_order_by(grib_fieldset * set)483 int grib_db_apply_order_by(grib_fieldset* set)
484 {
485 int err = 0;
486 grib_order_by* ob = NULL;
487
488 if (!set || !set->query)
489 return GRIB_INVALID_ARGUMENT;
490
491 if (set->query->order_by)
492 grib_db_sort(set, 0, set->size - 1);
493
494 grib_db_rewind(set);
495
496 return err;
497 }
498
grib_fieldset_compare(grib_fieldset * set,int * i,int * j)499 static int grib_fieldset_compare(grib_fieldset* set, int* i, int* j)
500 {
501 int ret = 0;
502 double d = 0;
503 int idkey = 0;
504 grib_order_by* ob = 0;
505 int ii = 0, jj = 0;
506 int *order = 0, *filter = 0;
507
508 if (!set || !set->order_by)
509 return GRIB_INVALID_ARGUMENT;
510 ob = set->query->order_by;
511 order = set->order->el;
512 filter = set->filter->el;
513
514 ii = *(set->filter->el + *(order + *i));
515 jj = *(set->filter->el + *(order + *j));
516
517 while (ob) {
518 idkey = ob->idkey;
519 switch (set->db->columns[idkey].type) {
520 case GRIB_TYPE_STRING:
521 ret = grib_inline_strcmp(set->db->columns[idkey].string_values[ii],
522 set->db->columns[idkey].string_values[jj]);
523 break;
524
525 case GRIB_TYPE_DOUBLE:
526 d = set->db->columns[idkey].double_values[ii] -
527 set->db->columns[idkey].double_values[jj];
528 if (d > 0)
529 ret = 1;
530 else if (d == 0)
531 ret = 0;
532 else
533 ret = -1;
534 break;
535
536 case GRIB_TYPE_LONG:
537 ret = set->db->columns[idkey].long_values[ii] -
538 set->db->columns[idkey].long_values[jj];
539 break;
540 default:
541 return GRIB_INVALID_TYPE;
542 }
543 if (ret != 0) {
544 ret *= ob->mode;
545 break;
546 }
547 ob = ob->next;
548 }
549
550 return ret;
551 }
552
grib_db_sort(grib_set * set,int beg,int theEnd)553 static void grib_db_sort(grib_set* set, int beg, int theEnd)
554 {
555 double temp;
556 int l = 0, r = 0;
557 if (theEnd > beg) {
558 l = beg + 1;
559 r = theEnd;
560 while (l < r) {
561 if (grib_db_compare(set, &l, &beg) <= 0) {
562 l++;
563 }
564 else if (grib_db_compare(set, &r, &beg) >= 0) {
565 r--;
566 }
567 else {
568 SWAP(set->order->el[l], set->order->el[r])
569 }
570 }
571
572 if (grib_db_compare(set, &l, &beg) < 0) {
573 SWAP(set->order->el[l], set->order->el[beg])
574 l--;
575 }
576 else {
577 l--;
578 SWAP(set->order->el[l], set->order->el[beg])
579 }
580
581 grib_db_sort(set, beg, l);
582 grib_db_sort(set, r, theEnd);
583 }
584 }
585
grib_db_delete_order_by(grib_context * c,grib_order_by * order_by)586 static void grib_db_delete_order_by(grib_context* c, grib_order_by* order_by)
587 {
588 grib_order_by* ob = order_by;
589
590 if (!c)
591 c = grib_context_get_default();
592
593 while (order_by) {
594 if (order_by->key)
595 free(order_by->key);
596 ob = order_by;
597 order_by = order_by->next;
598 grib_context_free(c, ob);
599 }
600
601 return;
602 }
603
grib_db_new_order_by(grib_context * c,char * obstr)604 static grib_order_by* grib_db_new_order_by(grib_context* c, char* obstr)
605 {
606 char *t1 = 0, *t2 = 0, *p = 0;
607 int id = 0;
608 char *z = 0, *zs = 0;
609 int mode, mode_default = GRIB_ORDER_BY_ASC;
610 grib_order_by *ob, *sob;
611
612 if (!obstr)
613 return NULL;
614
615 z = strdup(obstr);
616 zs = z;
617 grib_trim(&z);
618
619 if (strlen(z) == 0) {
620 return 0;
621 }
622
623 ob = (grib_order_by*)grib_context_malloc(c, sizeof(grib_order_by));
624 sob = ob;
625 ob->key = 0;
626 ob->idkey = 0;
627 ob->mode = 0;
628 ob->next = 0;
629
630 if (z)
631 t1 = strtok(z, ",");
632
633 while (t1) {
634 grib_trim(&t1);
635 t2 = strdup(t1);
636 p = t2;
637 while (*p != ' ' && *p != '\0')
638 p++;
639 mode = mode_default;
640 if (p != t2) {
641 while (*p == ' ' && *p != '\0')
642 p++;
643 if (*p != '\0') {
644 *(p - 1) = '\0';
645 if (!grib_inline_strcmp(p, "asc"))
646 mode = GRIB_ORDER_BY_ASC;
647 if (!grib_inline_strcmp(p, "desc"))
648 mode = GRIB_ORDER_BY_DESC;
649 }
650 grib_trim(&p);
651 }
652 grib_trim(&t2);
653 id = -1;
654 t1 = strtok(NULL, ",");
655
656 if (ob->key) {
657 ob->next = (grib_order_by*)grib_context_malloc(c, sizeof(grib_order_by));
658 ob = ob->next;
659 ob->key = 0;
660 ob->next = 0;
661 }
662 ob->mode = mode;
663 ob->key = t2;
664 ob->idkey = id;
665 }
666
667 free(zs);
668 return sob;
669 }
670
grib_db_load(grib_db * db,char * filename)671 int grib_db_load(grib_db* db, char* filename)
672 {
673 int ret = GRIB_SUCCESS;
674 int err = 0;
675 int i = 0;
676 grib_handle* h = 0;
677 int nkeys;
678 grib_file* file;
679 double offset = 0;
680 long length = 0;
681 grib_context* c = 0;
682
683 if (!db || !filename)
684 return GRIB_INVALID_ARGUMENT;
685 c = db->context;
686
687 nkeys = db->columns_size;
688
689 file = grib_file_open(filename, "r", &err);
690 if (!file || !file->handle)
691 return err;
692
693 while ((h = grib_handle_new_from_file(c, file->handle, &err)) != NULL || ret != GRIB_SUCCESS) {
694 if (!h)
695 return ret;
696
697 err = GRIB_SUCCESS;
698 for (i = 0; i < db->columns_size; i++) {
699 err = grib_db_column_copy_from_handle(h, db, i);
700 if (err != GRIB_SUCCESS)
701 ret = err;
702 }
703 if (err == GRIB_SUCCESS || err == GRIB_NOT_FOUND) {
704 if (db->fields_array_size < db->columns[0].values_array_size) {
705 ret = grib_db_resize(db, db->columns[0].values_array_size);
706 if (ret != GRIB_SUCCESS)
707 return ret;
708 }
709 offset = 0;
710 ret = grib_get_double(h, "offset", &offset);
711 db->fields[db->size] = (grib_field*)grib_context_malloc(c, sizeof(grib_field));
712 db->fields[db->size]->file = file;
713 file->refcount++;
714 db->fields[db->size]->offset = (off_t)offset;
715 ret = grib_get_long(h, "totalLength", &length);
716 db->fields[db->size]->length = length;
717 db->size = set->columns[0].size;
718 }
719 grib_handle_delete(h);
720 }
721 if (h)
722 grib_handle_delete(h);
723
724 grib_file_close(file->name, 0, &err);
725
726 return ret;
727 }
728
grib_db_resize(grib_db * db,size_t newsize)729 static int grib_db_resize(grib_db* db, size_t newsize)
730 {
731 int err = 0;
732
733 err = grib_db_resize_fields(db, newsize);
734 if (err != 0)
735 return err;
736
737 set->fields_array_size = newsize;
738
739 return GRIB_SUCCESS;
740 }
741
grib_db_rewind(grib_fieldset * set)742 void grib_db_rewind(grib_fieldset* set)
743 {
744 if (set)
745 set->current = 0;
746 }
747
grib_db_next_handle(grib_fieldset * set,int * err)748 grib_handle* grib_db_next_handle(grib_fieldset* set, int* err)
749 {
750 grib_handle* h;
751 *err = GRIB_SUCCESS;
752 h = grib_db_retrieve(set, set->current, err);
753 if (*err == GRIB_SUCCESS) {
754 set->current++;
755 }
756 return h;
757 }
758
grib_db_count(grib_fieldset * set)759 int grib_db_count(grib_fieldset* set)
760 {
761 return set->size;
762 }
763
grib_db_retrieve(grib_fieldset * set,int i,int * err)764 grib_handle* grib_db_retrieve(grib_fieldset* set, int i, int* err)
765 {
766 grib_handle* h = 0;
767 grib_field* field = 0;
768 *err = GRIB_SUCCESS;
769 if (!set) {
770 *err = GRIB_INVALID_ARGUMENT;
771 return NULL;
772 }
773 if (i >= set->size)
774 return NULL;
775
776 field = set->db->fields[set->filter->el[set->order->el[i]]];
777 grib_file_open(field->file->name, "r", err);
778 if (*err != GRIB_SUCCESS)
779 return NULL;
780
781 fseeko(field->file->handle, field->offset, SEEK_SET);
782 h = grib_handle_new_from_file(set->context, field->file->handle, err);
783 if (*err != GRIB_SUCCESS)
784 return NULL;
785
786 grib_file_close(field->file->name, 0, err);
787
788 return h;
789 }
790
grib_db_create_int_array(grib_context * c,size_t size)791 static grib_int_array* grib_db_create_int_array(grib_context* c, size_t size)
792 {
793 grib_int_array* a;
794 int i = 0;
795
796 if (!c)
797 c = grib_context_get_default();
798
799 a = (grib_int_array*)grib_context_malloc(c, sizeof(grib_int_array));
800
801 if (!a) {
802 grib_context_log(c, GRIB_LOG_ERROR,
803 "grib_db_create_int_array : Cannot malloc %d bytes",
804 sizeof(grib_int_array));
805 return NULL;
806 }
807
808 a->el = (int*)grib_context_malloc(c, sizeof(int) * size);
809 if (!a->el) {
810 grib_context_log(c, GRIB_LOG_ERROR,
811 "grib_db_create_int_array : Cannot malloc %d bytes",
812 sizeof(int) * size);
813 return NULL;
814 }
815
816 a->size = size;
817 a->context = c;
818 for (i = 0; i < size; i++)
819 a->el[i] = i;
820
821 return a;
822 }
823
grib_db_resize_int_array(grib_int_array * a,size_t newsize)824 static int grib_db_resize_int_array(grib_int_array* a, size_t newsize)
825 {
826 int* el;
827 int err = 0;
828 if (!a)
829 return GRIB_INVALID_ARGUMENT;
830
831 newsize = newsize * sizeof(int);
832
833 el = (int*)grib_context_realloc(a->context, a->el, newsize);
834 if (!el) {
835 grib_context_log(a->context, GRIB_LOG_ERROR,
836 "grib_db_resize_int_array : Cannot malloc %d bytes",
837 newsize);
838 return GRIB_OUT_OF_MEMORY;
839 }
840 else
841 a->el = el;
842 a->size = newsize;
843 return err;
844 }
845
grib_db_delete_int_array(grib_int_array * f)846 static void grib_db_delete_int_array(grib_int_array* f)
847 {
848 grib_context* c = NULL;
849
850 if (!f)
851 return;
852 c = f->context;
853
854 grib_context_free(c, f->el);
855 grib_context_free(c, f);
856 }
857
grib_db_create_fields(grib_context * c,size_t size)858 static grib_field** grib_db_create_fields(grib_context* c, size_t size)
859 {
860 int i = 0;
861 grib_field** fields = (grib_field**)grib_context_malloc(c, size * sizeof(grib_field*));
862 if (!fields)
863 return NULL;
864 for (i = 0; i < size; i++)
865 fields[i] = 0;
866 return fields;
867 }
868
grib_db_resize_fields(grib_db * db,size_t newsize)869 static int grib_db_resize_fields(grib_db* db, size_t newsize)
870 {
871 int err = 0;
872 int i;
873 grib_field** fields;
874 if (!db)
875 return GRIB_INVALID_ARGUMENT;
876
877 fields = (grib_field**)grib_context_realloc(set->context, set->fields, newsize * sizeof(grib_field*));
878 if (!fields) {
879 grib_context_log(set->context, GRIB_LOG_ERROR,
880 "grib_db_resize_fields : Cannot malloc %d bytes",
881 newsize * sizeof(grib_field*));
882 return GRIB_OUT_OF_MEMORY;
883 }
884 else
885 db->fields = fields;
886
887 for (i = set->fields_array_size; i < newsize; i++)
888 db->fields[i] = 0;
889
890 db->fields_array_size = newsize;
891 return err;
892 }
893
grib_db_delete_fields(grib_fieldset * set)894 static void grib_db_delete_fields(grib_fieldset* set)
895 {
896 int i;
897 for (i = 0; i < set->size; i++) {
898 if (!set->fields[i])
899 continue;
900 set->fields[i]->file->refcount--;
901 grib_context_free(set->context, set->fields[i]);
902 }
903 grib_context_free(set->context, set->fields);
904 }
905
grib_trim(char ** x)906 static void grib_trim(char** x)
907 {
908 char* p = 0;
909 while (**x == ' ' && **x != '\0')
910 (*x)++;
911 if (**x == '\0')
912 return;
913 p = (*x) + strlen(*x) - 1;
914 while (*p == ' ') {
915 *p = '\0';
916 p--;
917 }
918 if (*p == ' ')
919 *p = '\0';
920 }
921
grib_db_set_order_by(grib_fieldset * set,grib_order_by * ob)922 static int grib_db_set_order_by(grib_fieldset* set, grib_order_by* ob)
923 {
924 grib_order_by* next = ob;
925 int i = 0;
926
927 while (next) {
928 next->idkey = -1;
929 for (i = 0; i < set->columns_size; i++) {
930 if (!grib_inline_strcmp(next->key, set->columns[i].name)) {
931 next->idkey = i;
932 break;
933 }
934 }
935 if (next->idkey == -1) {
936 grib_context_log(set->context, GRIB_LOG_ERROR,
937 "Unable to apply the order by. Key missing from the fieldset.\n");
938 return GRIB_MISSING_KEY;
939 }
940 next = next->next;
941 }
942
943 set->order_by = ob;
944
945 return GRIB_SUCCESS;
946 }
947