mirror of https://github.com/ecmwf/eccodes.git
934 lines
26 KiB
C++
934 lines
26 KiB
C++
/*
|
|
* (C) Copyright 2005- ECMWF.
|
|
*
|
|
* This software is licensed under the terms of the Apache Licence Version 2.0
|
|
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
|
*
|
|
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
|
|
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
|
*/
|
|
|
|
/*
|
|
*
|
|
* Description: grib database routines
|
|
*
|
|
*/
|
|
#include "grib_api_internal.h"
|
|
#define GRIB_START_ARRAY_SIZE 5000
|
|
#define GRIB_ARRAY_INCREMENT 1000
|
|
|
|
#define SWAP(a, b) \
|
|
temp = (a); \
|
|
(a) = (b); \
|
|
(b) = temp;
|
|
|
|
#define GRIB_ORDER_BY_ASC 1
|
|
#define GRIB_ORDER_BY_DESC -1
|
|
|
|
/* Note: A fast cut-down version of strcmp which does NOT return -1 */
|
|
/* 0 means input strings are equal and 1 means not equal */
|
|
GRIB_INLINE static int grib_inline_strcmp(const char* a, const char* b)
|
|
{
|
|
if (*a != *b)
|
|
return 1;
|
|
while ((*a != 0 && *b != 0) && *(a) == *(b)) {
|
|
a++;
|
|
b++;
|
|
}
|
|
return (*a == 0 && *b == 0) ? 0 : 1;
|
|
}
|
|
|
|
static int grib_db_new_column(grib_db* db, int id, char* key, int type);
|
|
static void grib_db_delete_columns(grib_db* db);
|
|
static int grib_db_columns_resize(grib_db* db, size_t newsize);
|
|
static int grib_db_column_copy_from_handle(grib_handle* h, grib_db* db, int i);
|
|
static grib_db* grib_db_create_from_keys(grib_context* c, char** keys, int nkeys, int* err);
|
|
static void grib_fieldset* grib_db_fieldset_create(grib_db* db, int* err);
|
|
static void grib_db_sort(grib_set* set, int beg, int theEnd);
|
|
static grib_order_by* grib_db_new_order_by(grib_context* c, char* obstr);
|
|
static void grib_db_delete_order_by(grib_context* c, grib_order_by* order_by);
|
|
static int grib_db_resize(grib_db* db, size_t newsize);
|
|
static int grib_db_resize_fields(grib_db* db, size_t newsize);
|
|
|
|
|
|
/* --------------- grib_column functions ------------------*/
|
|
static int grib_db_new_column(grib_db* db, int id, char* key, int type)
|
|
{
|
|
grib_column* column = 0;
|
|
grib_context* c;
|
|
int err = 0;
|
|
|
|
if (!db)
|
|
return GRIB_INVALID_ARGUMENT;
|
|
|
|
c = db->context;
|
|
|
|
db->columns[id].errors = (int*)grib_context_malloc(c,
|
|
sizeof(int) * GRIB_START_ARRAY_SIZE);
|
|
|
|
switch (type) {
|
|
case GRIB_TYPE_LONG:
|
|
db->columns[id].long_values = (long*)grib_context_malloc(c,
|
|
sizeof(long) * GRIB_START_ARRAY_SIZE);
|
|
if (!db->columns[id].long_values) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_db_new_column : Cannot malloc %d bytes",
|
|
sizeof(long) * GRIB_START_ARRAY_SIZE);
|
|
err = GRIB_OUT_OF_MEMORY;
|
|
return err;
|
|
}
|
|
break;
|
|
case GRIB_TYPE_DOUBLE:
|
|
db->columns[id].double_values = (double*)grib_context_malloc(c,
|
|
sizeof(double) * GRIB_START_ARRAY_SIZE);
|
|
if (!db->columns[id].double_values) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_db_new_column : Cannot malloc %d bytes",
|
|
sizeof(double) * GRIB_START_ARRAY_SIZE);
|
|
err = GRIB_OUT_OF_MEMORY;
|
|
return err;
|
|
}
|
|
break;
|
|
case GRIB_TYPE_STRING:
|
|
db->columns[id].string_values = (char**)grib_context_malloc(c,
|
|
sizeof(char*) * GRIB_START_ARRAY_SIZE);
|
|
if (!db->columns[id].string_values) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_db_new_column : Cannot malloc %d bytes",
|
|
sizeof(char*) * GRIB_START_ARRAY_SIZE);
|
|
err = GRIB_OUT_OF_MEMORY;
|
|
return err;
|
|
}
|
|
break;
|
|
default:
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_db_new_column : unknown column type %d", type);
|
|
grib_context_free(c, column);
|
|
return err;
|
|
}
|
|
|
|
db->columns[id].context = c;
|
|
db->columns[id].name = strdup(key);
|
|
db->columns[id].type = type;
|
|
db->columns[id].values_array_size = GRIB_START_ARRAY_SIZE;
|
|
db->columns[id].size = 0;
|
|
return err;
|
|
}
|
|
|
|
static void grib_db_delete_columns(grib_db* db)
|
|
{
|
|
int i = 0;
|
|
grib_context* c;
|
|
|
|
if (!set)
|
|
return;
|
|
c = db->context;
|
|
|
|
for (i = 0; i < db->columns_size; i++) {
|
|
switch (db->columns[i].type) {
|
|
case GRIB_TYPE_LONG:
|
|
grib_context_free(c, db->columns[i].long_values);
|
|
break;
|
|
case GRIB_TYPE_DOUBLE:
|
|
grib_context_free(c, db->columns[i].double_values);
|
|
break;
|
|
case GRIB_TYPE_STRING:
|
|
for (i = 0; i < db->columns[i].size; i++)
|
|
grib_context_free(c, db->columns[i].string_values[i]);
|
|
grib_context_free(c, db->columns[i].string_values);
|
|
break;
|
|
default:
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_db_new_column : unknown column type %d", db->columns[i].type);
|
|
}
|
|
grib_context_free(c, db->columns[i].errors);
|
|
free(db->columns[i].name);
|
|
}
|
|
grib_context_free(c, db->columns);
|
|
}
|
|
|
|
static int grib_db_columns_resize(grib_db* db, size_t newsize)
|
|
{
|
|
double* newdoubles;
|
|
long* newlongs;
|
|
char** newstrings;
|
|
int* newerrors;
|
|
int i = 0;
|
|
grib_context* c;
|
|
|
|
if (!db || !db->columns)
|
|
return GRIB_INVALID_ARGUMENT;
|
|
|
|
c = db->context;
|
|
|
|
if (newsize <= db->columns[0].values_array_size)
|
|
return 0;
|
|
|
|
for (i = 0; i < db->columns_size; i++) {
|
|
switch (db->columns[i].type) {
|
|
case GRIB_TYPE_LONG:
|
|
newlongs = (long*)grib_context_realloc(c, db->columns[i].long_values,
|
|
newsize * sizeof(long));
|
|
if (!newlongs) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_db_columns_resize : Cannot malloc %d bytes", newsize - db->columns[i].values_array_size);
|
|
return GRIB_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
db->columns[i].long_values = newlongs;
|
|
break;
|
|
case GRIB_TYPE_DOUBLE:
|
|
newdoubles = (double*)grib_context_realloc(c, db->columns[i].double_values,
|
|
newsize * sizeof(double));
|
|
if (!newdoubles) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_db_columns_resize : Cannot malloc %d bytes", newsize - db->columns[i].values_array_size);
|
|
return GRIB_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
db->columns[i].double_values = newdoubles;
|
|
break;
|
|
case GRIB_TYPE_STRING:
|
|
newstrings = (char**)grib_context_realloc(c, db->columns[i].string_values,
|
|
newsize * sizeof(char*));
|
|
if (!newstrings) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_db_columns_resize : Cannot malloc %d bytes", newsize - db->columns[i].values_array_size);
|
|
return GRIB_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
db->columns[i].string_values = newstrings;
|
|
break;
|
|
}
|
|
newerrors = (int*)grib_context_realloc(c, db->columns[i].errors, newsize * sizeof(int));
|
|
if (!newerrors) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_db_columns_resize : Cannot malloc %d bytes",
|
|
db->columns[i].errors, newsize * sizeof(int));
|
|
return GRIB_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
db->columns[i].errors = newerrors;
|
|
|
|
db->columns[i].values_array_size = newsize;
|
|
}
|
|
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
static int grib_db_column_copy_from_handle(grib_handle* h, grib_db* db, int i)
|
|
{
|
|
int err = 0;
|
|
long lval = 0;
|
|
double dval = 0;
|
|
char sval[1024];
|
|
size_t slen = 1024;
|
|
if (!db || !h || db->columns[i].type == 0)
|
|
return GRIB_INVALID_ARGUMENT;
|
|
|
|
if (db->columns[i].size >= db->columns[i].values_array_size)
|
|
grib_db_columns_resize(db, db->columns[i].values_array_size + GRIB_ARRAY_INCREMENT);
|
|
|
|
switch (db->columns[i].type) {
|
|
case GRIB_TYPE_LONG:
|
|
err = grib_get_long(h, db->columns[i].name, &lval);
|
|
db->columns[i].long_values[db->columns[i].size] = lval;
|
|
break;
|
|
case GRIB_TYPE_DOUBLE:
|
|
err = grib_get_double(h, db->columns[i].name, &dval);
|
|
db->columns[i].double_values[db->columns[i].size] = dval;
|
|
break;
|
|
case GRIB_TYPE_STRING:
|
|
err = grib_get_string(h, db->columns[i].name, sval, &slen);
|
|
db->columns[i].string_values[db->columns[i].size] = strdup(sval);
|
|
break;
|
|
}
|
|
|
|
db->columns[i].errors[db->columns[i].size] = err;
|
|
db->columns[i].size++;
|
|
|
|
return err;
|
|
}
|
|
|
|
// grib_db* grib_db_new_from_files(grib_context* c, char* filenames[],
|
|
// int nfiles, char** keys, int nkeys, int* err)
|
|
// {
|
|
// int i = 0;
|
|
// int ret = GRIB_SUCCESS;
|
|
// grib_db* db = 0;
|
|
// if (!c) c = grib_context_get_default();
|
|
|
|
// if (((!keys || nkeys == 0)) || !filenames) {
|
|
// *err = GRIB_INVALID_ARGUMENT;
|
|
// return NULL;
|
|
// }
|
|
|
|
// db = grib_db_new_from_file(c, filenames[0], keys, nkeys, err);
|
|
// if (!db || *err != GRIB_SUCCESS)
|
|
// return db;
|
|
|
|
// *err = GRIB_SUCCESS;
|
|
// for (i = 1; i < nfiles; i++) {
|
|
// ret = grib_db_load(db, filenames[i]);
|
|
// if (ret != GRIB_SUCCESS)
|
|
// *err = ret;
|
|
// }
|
|
// return db;
|
|
// }
|
|
|
|
// grib_db* grib_db_new_from_file(grib_context* c, char* filename,
|
|
// char** keys, int nkeys, int* err)
|
|
// {
|
|
// int i = 0;
|
|
// int ret = GRIB_SUCCESS;
|
|
// grib_db* db = 0;
|
|
|
|
// if (!c)
|
|
// c = grib_context_get_default();
|
|
|
|
// if (((!keys || nkeys == 0)) || !filename) {
|
|
// *err = GRIB_INVALID_ARGUMENT;
|
|
// return NULL;
|
|
// }
|
|
|
|
// db = grib_db_create_from_keys(c, keys, nkeys, err);
|
|
// *err = GRIB_SUCCESS;
|
|
// ret = grib_db_load(db, filename);
|
|
// if (ret != GRIB_SUCCESS)
|
|
// *err = ret;
|
|
// return db;
|
|
// }
|
|
|
|
|
|
static grib_db* grib_db_create_from_keys(grib_context* c, char** keys, int nkeys, int* err)
|
|
{
|
|
grib_db* db = 0;
|
|
size_t msize = 0, size = 0;
|
|
int i = 0;
|
|
int type = 0;
|
|
int default_type = GRIB_TYPE_DOUBLE;
|
|
|
|
if (!c)
|
|
c = grib_context_get_default();
|
|
|
|
size = GRIB_START_ARRAY_SIZE;
|
|
|
|
msize = sizeof(grib_db);
|
|
db = (grib_db*)grib_context_malloc(c, msize);
|
|
if (!db) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_db_create : Cannot malloc %d bytes", msize);
|
|
return NULL;
|
|
}
|
|
|
|
db->context = c;
|
|
db->size = 0;
|
|
db->fields_array_size = size;
|
|
db->fields = 0;
|
|
db->columns = 0;
|
|
|
|
db->fields = grib_db_create_fields(db->context, size);
|
|
|
|
db->columns = (grib_column*)grib_context_malloc(c, sizeof(grib_column) * nkeys);
|
|
if (!set->columns) {
|
|
grib_context_log(c, GRIB_LOG_ERROR, "grib_db_new_query: memory allocation error");
|
|
*err = GRIB_OUT_OF_MEMORY;
|
|
return NULL;
|
|
}
|
|
for (i = 0; i < nkeys; i++) {
|
|
char* key = strdup(keys[i]);
|
|
char* p = key;
|
|
while (*p != ':' && *p != '\0')
|
|
p++;
|
|
if (*p == ':') {
|
|
type = grib_type_to_int(*(p + 1));
|
|
*p = '\0';
|
|
}
|
|
else {
|
|
type = default_type;
|
|
}
|
|
*err = grib_db_new_column(db, i, key, type);
|
|
free(key);
|
|
}
|
|
|
|
db->columns_size = nkeys;
|
|
|
|
return db;
|
|
}
|
|
|
|
void grib_db_delete(grib_db* db)
|
|
{
|
|
grib_context* c = 0;
|
|
if (!db)
|
|
return;
|
|
|
|
c = set->context;
|
|
|
|
grib_db_delete_columns(db);
|
|
|
|
grib_db_delete_fields(db);
|
|
|
|
grib_context_free(c, db);
|
|
}
|
|
|
|
grib_query* grib_db_new_query(grib_context* c, const char* where_string,
|
|
const char* order_by_string)
|
|
{
|
|
grib_query* q = 0;
|
|
|
|
if (!c)
|
|
c = grib_context_get_default();
|
|
|
|
q = (grib_query*)grib_context_malloc(c, sizeof(grib_query));
|
|
|
|
q->where_string = 0;
|
|
q->order_by = 0;
|
|
|
|
if (where_string)
|
|
q->where_string = strdup(where_string);
|
|
|
|
if (order_by_string) {
|
|
q->order_by = grib_db_new_order_by(set->context, (char*)order_by_string);
|
|
if ((err = grib_db_set_order_by(set, ob)) != GRIB_SUCCESS)
|
|
return q;
|
|
}
|
|
|
|
return q;
|
|
}
|
|
|
|
grib_fieldset* grib_db_execute(grib_db* db, grib_query* query, int* err)
|
|
{
|
|
grib_fieldset* set = NULL;
|
|
|
|
if (!db) {
|
|
*err = GRIB_INVALID_ARGUMENT;
|
|
return NULL;
|
|
}
|
|
set = grib_db_fieldset_create(db, err);
|
|
if (*err != GRIB_SUCCESS)
|
|
return set;
|
|
|
|
set->query = query;
|
|
|
|
*err = grib_db_apply_where(set, query->where_string);
|
|
if (*err != GRIB_SUCCESS)
|
|
return set;
|
|
|
|
*err = grib_db_apply_order_by(set, query->order_by);
|
|
if (*err != GRIB_SUCCESS)
|
|
return set;
|
|
|
|
return set;
|
|
}
|
|
|
|
static void grib_fieldset* grib_db_fieldset_create(grib_db* db, int* err)
|
|
{
|
|
grib_fieldset* set = (grib_fieldset*)grib_context_malloc(db->context,
|
|
sizeof(grib_fieldset));
|
|
|
|
if (!set) {
|
|
*err = GRIB_OUT_OF_MEMORY;
|
|
return NULL;
|
|
}
|
|
|
|
set->db = db;
|
|
set->context = db->context;
|
|
set->grib_query = NULL;
|
|
set->size = 0;
|
|
set->filter = NULL;
|
|
set->order = NULL;
|
|
|
|
return set;
|
|
}
|
|
|
|
int grib_db_apply_where(grib_fieldset* set)
|
|
{
|
|
int err = GRIB_SUCCESS;
|
|
grib_math* m = 0;
|
|
|
|
if (!set)
|
|
return GRIB_INVALID_ARGUMENT;
|
|
|
|
// m=grib_math_new(set->context,where_string,&err);
|
|
// print_math(m);
|
|
// printf("\n");
|
|
|
|
if (set->filter)
|
|
grib_db_delete_int_array(set->filter);
|
|
set->filter = grib_db_create_int_array(set->context, db->size);
|
|
|
|
if (set->order)
|
|
grib_db_delete_int_array(set->order);
|
|
set->order = grib_db_create_int_array(set->context, db->size);
|
|
|
|
for (i = 0; i < db->size; i++)
|
|
set->filter[i] = i;
|
|
|
|
return err;
|
|
}
|
|
|
|
int grib_db_apply_order_by(grib_fieldset* set)
|
|
{
|
|
int err = 0;
|
|
grib_order_by* ob = NULL;
|
|
|
|
if (!set || !set->query)
|
|
return GRIB_INVALID_ARGUMENT;
|
|
|
|
if (set->query->order_by)
|
|
grib_db_sort(set, 0, set->size - 1);
|
|
|
|
grib_db_rewind(set);
|
|
|
|
return err;
|
|
}
|
|
|
|
// static int grib_fieldset_compare(grib_fieldset* set, int* i, int* j)
|
|
// {
|
|
// int ret = 0;
|
|
// double d = 0;
|
|
// int idkey = 0;
|
|
// grib_order_by* ob = 0;
|
|
// int ii = 0, jj = 0;
|
|
// int *order = 0, *filter = 0;
|
|
|
|
// if (!set || !set->order_by)
|
|
// return GRIB_INVALID_ARGUMENT;
|
|
// ob = set->query->order_by;
|
|
// order = set->order->el;
|
|
// filter = set->filter->el;
|
|
|
|
// ii = *(set->filter->el + *(order + *i));
|
|
// jj = *(set->filter->el + *(order + *j));
|
|
|
|
// while (ob) {
|
|
// idkey = ob->idkey;
|
|
// switch (set->db->columns[idkey].type) {
|
|
// case GRIB_TYPE_STRING:
|
|
// ret = grib_inline_strcmp(set->db->columns[idkey].string_values[ii],
|
|
// set->db->columns[idkey].string_values[jj]);
|
|
// break;
|
|
|
|
// case GRIB_TYPE_DOUBLE:
|
|
// d = set->db->columns[idkey].double_values[ii] -
|
|
// set->db->columns[idkey].double_values[jj];
|
|
// if (d > 0)
|
|
// ret = 1;
|
|
// else if (d == 0)
|
|
// ret = 0;
|
|
// else
|
|
// ret = -1;
|
|
// break;
|
|
|
|
// case GRIB_TYPE_LONG:
|
|
// ret = set->db->columns[idkey].long_values[ii] -
|
|
// set->db->columns[idkey].long_values[jj];
|
|
// break;
|
|
// default:
|
|
// return GRIB_INVALID_TYPE;
|
|
// }
|
|
// if (ret != 0) {
|
|
// ret *= ob->mode;
|
|
// break;
|
|
// }
|
|
// ob = ob->next;
|
|
// }
|
|
|
|
// return ret;
|
|
// }
|
|
|
|
static void grib_db_sort(grib_set* set, int beg, int theEnd)
|
|
{
|
|
double temp;
|
|
int l = 0, r = 0;
|
|
if (theEnd > beg) {
|
|
l = beg + 1;
|
|
r = theEnd;
|
|
while (l < r) {
|
|
if (grib_db_compare(set, &l, &beg) <= 0) {
|
|
l++;
|
|
}
|
|
else if (grib_db_compare(set, &r, &beg) >= 0) {
|
|
r--;
|
|
}
|
|
else {
|
|
SWAP(set->order->el[l], set->order->el[r])
|
|
}
|
|
}
|
|
|
|
if (grib_db_compare(set, &l, &beg) < 0) {
|
|
SWAP(set->order->el[l], set->order->el[beg])
|
|
l--;
|
|
}
|
|
else {
|
|
l--;
|
|
SWAP(set->order->el[l], set->order->el[beg])
|
|
}
|
|
|
|
grib_db_sort(set, beg, l);
|
|
grib_db_sort(set, r, theEnd);
|
|
}
|
|
}
|
|
|
|
static void grib_db_delete_order_by(grib_context* c, grib_order_by* order_by)
|
|
{
|
|
grib_order_by* ob = order_by;
|
|
|
|
if (!c)
|
|
c = grib_context_get_default();
|
|
|
|
while (order_by) {
|
|
if (order_by->key)
|
|
free(order_by->key);
|
|
ob = order_by;
|
|
order_by = order_by->next;
|
|
grib_context_free(c, ob);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static grib_order_by* grib_db_new_order_by(grib_context* c, char* obstr)
|
|
{
|
|
char *t1 = 0, *t2 = 0, *p = 0;
|
|
int id = 0;
|
|
char *z = 0, *zs = 0;
|
|
char* lasts = NULL;
|
|
int mode, mode_default = GRIB_ORDER_BY_ASC;
|
|
grib_order_by *ob, *sob;
|
|
|
|
if (!obstr)
|
|
return NULL;
|
|
|
|
z = strdup(obstr);
|
|
zs = z;
|
|
grib_trim(&z);
|
|
|
|
if (strlen(z) == 0) {
|
|
return 0;
|
|
}
|
|
|
|
ob = (grib_order_by*)grib_context_malloc(c, sizeof(grib_order_by));
|
|
sob = ob;
|
|
ob->key = 0;
|
|
ob->idkey = 0;
|
|
ob->mode = 0;
|
|
ob->next = 0;
|
|
|
|
t1 = strtok_r(z, ",", &lasts);
|
|
|
|
while (t1) {
|
|
grib_trim(&t1);
|
|
t2 = strdup(t1);
|
|
p = t2;
|
|
while (*p != ' ' && *p != '\0')
|
|
p++;
|
|
mode = mode_default;
|
|
if (p != t2) {
|
|
while (*p == ' ')
|
|
p++;
|
|
if (*p != '\0') {
|
|
*(p - 1) = '\0';
|
|
if (!grib_inline_strcmp(p, "asc"))
|
|
mode = GRIB_ORDER_BY_ASC;
|
|
if (!grib_inline_strcmp(p, "desc"))
|
|
mode = GRIB_ORDER_BY_DESC;
|
|
}
|
|
grib_trim(&p);
|
|
}
|
|
grib_trim(&t2);
|
|
id = -1;
|
|
t1 = strtok_r(NULL, ",", &lasts);
|
|
|
|
if (ob->key) {
|
|
ob->next = (grib_order_by*)grib_context_malloc(c, sizeof(grib_order_by));
|
|
ob = ob->next;
|
|
ob->key = 0;
|
|
ob->next = 0;
|
|
}
|
|
ob->mode = mode;
|
|
ob->key = t2;
|
|
ob->idkey = id;
|
|
}
|
|
|
|
free(zs);
|
|
return sob;
|
|
}
|
|
|
|
int grib_db_load(grib_db* db, char* filename)
|
|
{
|
|
int ret = GRIB_SUCCESS;
|
|
int err = 0;
|
|
int i = 0;
|
|
grib_handle* h = 0;
|
|
int nkeys;
|
|
grib_file* file;
|
|
double offset = 0;
|
|
long length = 0;
|
|
grib_context* c = 0;
|
|
|
|
if (!db || !filename)
|
|
return GRIB_INVALID_ARGUMENT;
|
|
c = db->context;
|
|
|
|
nkeys = db->columns_size;
|
|
|
|
file = grib_file_open(filename, "r", &err);
|
|
if (!file || !file->handle)
|
|
return err;
|
|
|
|
while ((h = grib_handle_new_from_file(c, file->handle, &err)) != NULL || ret != GRIB_SUCCESS) {
|
|
if (!h)
|
|
return ret;
|
|
|
|
err = GRIB_SUCCESS;
|
|
for (i = 0; i < db->columns_size; i++) {
|
|
err = grib_db_column_copy_from_handle(h, db, i);
|
|
if (err != GRIB_SUCCESS)
|
|
ret = err;
|
|
}
|
|
if (err == GRIB_SUCCESS || err == GRIB_NOT_FOUND) {
|
|
if (db->fields_array_size < db->columns[0].values_array_size) {
|
|
ret = grib_db_resize(db, db->columns[0].values_array_size);
|
|
if (ret != GRIB_SUCCESS)
|
|
return ret;
|
|
}
|
|
offset = 0;
|
|
ret = grib_get_double(h, "offset", &offset);
|
|
db->fields[db->size] = (grib_field*)grib_context_malloc(c, sizeof(grib_field));
|
|
db->fields[db->size]->file = file;
|
|
file->refcount++;
|
|
db->fields[db->size]->offset = (off_t)offset;
|
|
ret = grib_get_long(h, "totalLength", &length);
|
|
db->fields[db->size]->length = length;
|
|
db->size = set->columns[0].size;
|
|
}
|
|
grib_handle_delete(h);
|
|
}
|
|
if (h)
|
|
grib_handle_delete(h);
|
|
|
|
grib_file_close(file->name, 0, &err);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int grib_db_resize(grib_db* db, size_t newsize)
|
|
{
|
|
int err = 0;
|
|
|
|
err = grib_db_resize_fields(db, newsize);
|
|
if (err != 0)
|
|
return err;
|
|
|
|
set->fields_array_size = newsize;
|
|
|
|
return GRIB_SUCCESS;
|
|
}
|
|
|
|
void grib_db_rewind(grib_fieldset* set)
|
|
{
|
|
if (set)
|
|
set->current = 0;
|
|
}
|
|
|
|
grib_handle* grib_db_next_handle(grib_fieldset* set, int* err)
|
|
{
|
|
grib_handle* h;
|
|
*err = GRIB_SUCCESS;
|
|
h = grib_db_retrieve(set, set->current, err);
|
|
if (*err == GRIB_SUCCESS) {
|
|
set->current++;
|
|
}
|
|
return h;
|
|
}
|
|
|
|
int grib_db_count(grib_fieldset* set)
|
|
{
|
|
return set->size;
|
|
}
|
|
|
|
grib_handle* grib_db_retrieve(grib_fieldset* set, int i, int* err)
|
|
{
|
|
grib_handle* h = 0;
|
|
grib_field* field = 0;
|
|
*err = GRIB_SUCCESS;
|
|
if (!set) {
|
|
*err = GRIB_INVALID_ARGUMENT;
|
|
return NULL;
|
|
}
|
|
if (i >= set->size)
|
|
return NULL;
|
|
|
|
field = set->db->fields[set->filter->el[set->order->el[i]]];
|
|
grib_file_open(field->file->name, "r", err);
|
|
if (*err != GRIB_SUCCESS)
|
|
return NULL;
|
|
|
|
fseeko(field->file->handle, field->offset, SEEK_SET);
|
|
h = grib_handle_new_from_file(set->context, field->file->handle, err);
|
|
if (*err != GRIB_SUCCESS)
|
|
return NULL;
|
|
|
|
grib_file_close(field->file->name, 0, err);
|
|
|
|
return h;
|
|
}
|
|
|
|
static grib_int_array* grib_db_create_int_array(grib_context* c, size_t size)
|
|
{
|
|
grib_int_array* a;
|
|
int i = 0;
|
|
|
|
if (!c)
|
|
c = grib_context_get_default();
|
|
|
|
a = (grib_int_array*)grib_context_malloc(c, sizeof(grib_int_array));
|
|
|
|
if (!a) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_db_create_int_array : Cannot malloc %d bytes",
|
|
sizeof(grib_int_array));
|
|
return NULL;
|
|
}
|
|
|
|
a->el = (int*)grib_context_malloc(c, sizeof(int) * size);
|
|
if (!a->el) {
|
|
grib_context_log(c, GRIB_LOG_ERROR,
|
|
"grib_db_create_int_array : Cannot malloc %d bytes",
|
|
sizeof(int) * size);
|
|
return NULL;
|
|
}
|
|
|
|
a->size = size;
|
|
a->context = c;
|
|
for (i = 0; i < size; i++)
|
|
a->el[i] = i;
|
|
|
|
return a;
|
|
}
|
|
|
|
static int grib_db_resize_int_array(grib_int_array* a, size_t newsize)
|
|
{
|
|
int* el;
|
|
int err = 0;
|
|
if (!a)
|
|
return GRIB_INVALID_ARGUMENT;
|
|
|
|
newsize = newsize * sizeof(int);
|
|
|
|
el = (int*)grib_context_realloc(a->context, a->el, newsize);
|
|
if (!el) {
|
|
grib_context_log(a->context, GRIB_LOG_ERROR,
|
|
"grib_db_resize_int_array : Cannot malloc %d bytes",
|
|
newsize);
|
|
return GRIB_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
a->el = el;
|
|
a->size = newsize;
|
|
return err;
|
|
}
|
|
|
|
static void grib_db_delete_int_array(grib_int_array* f)
|
|
{
|
|
grib_context* c = NULL;
|
|
|
|
if (!f)
|
|
return;
|
|
c = f->context;
|
|
|
|
grib_context_free(c, f->el);
|
|
grib_context_free(c, f);
|
|
}
|
|
|
|
static grib_field** grib_db_create_fields(grib_context* c, size_t size)
|
|
{
|
|
int i = 0;
|
|
grib_field** fields = (grib_field**)grib_context_malloc(c, size * sizeof(grib_field*));
|
|
if (!fields)
|
|
return NULL;
|
|
for (i = 0; i < size; i++)
|
|
fields[i] = 0;
|
|
return fields;
|
|
}
|
|
|
|
static int grib_db_resize_fields(grib_db* db, size_t newsize)
|
|
{
|
|
int err = 0;
|
|
int i;
|
|
grib_field** fields;
|
|
if (!db)
|
|
return GRIB_INVALID_ARGUMENT;
|
|
|
|
fields = (grib_field**)grib_context_realloc(set->context, set->fields, newsize * sizeof(grib_field*));
|
|
if (!fields) {
|
|
grib_context_log(set->context, GRIB_LOG_ERROR,
|
|
"grib_db_resize_fields : Cannot malloc %d bytes",
|
|
newsize * sizeof(grib_field*));
|
|
return GRIB_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
db->fields = fields;
|
|
|
|
for (i = set->fields_array_size; i < newsize; i++)
|
|
db->fields[i] = 0;
|
|
|
|
db->fields_array_size = newsize;
|
|
return err;
|
|
}
|
|
|
|
static void grib_db_delete_fields(grib_fieldset* set)
|
|
{
|
|
int i;
|
|
for (i = 0; i < set->size; i++) {
|
|
if (!set->fields[i])
|
|
continue;
|
|
set->fields[i]->file->refcount--;
|
|
grib_context_free(set->context, set->fields[i]);
|
|
}
|
|
grib_context_free(set->context, set->fields);
|
|
}
|
|
|
|
static void grib_trim(char** x)
|
|
{
|
|
char* p = 0;
|
|
while (**x == ' ')
|
|
(*x)++;
|
|
if (**x == '\0')
|
|
return;
|
|
p = (*x) + strlen(*x) - 1;
|
|
while (*p == ' ') {
|
|
*p = '\0';
|
|
p--;
|
|
}
|
|
if (*p == ' ')
|
|
*p = '\0';
|
|
}
|
|
|
|
static int grib_db_set_order_by(grib_fieldset* set, grib_order_by* ob)
|
|
{
|
|
grib_order_by* next = ob;
|
|
int i = 0;
|
|
|
|
while (next) {
|
|
next->idkey = -1;
|
|
for (i = 0; i < set->columns_size; i++) {
|
|
if (!grib_inline_strcmp(next->key, set->columns[i].name)) {
|
|
next->idkey = i;
|
|
break;
|
|
}
|
|
}
|
|
if (next->idkey == -1) {
|
|
grib_context_log(set->context, GRIB_LOG_ERROR,
|
|
"Unable to apply the order by. Key missing from the fieldset.\n");
|
|
return GRIB_MISSING_KEY;
|
|
}
|
|
next = next->next;
|
|
}
|
|
|
|
set->order_by = ob;
|
|
|
|
return GRIB_SUCCESS;
|
|
}
|