diff --git a/src/fdb5/api/fdb_c.cc b/src/fdb5/api/fdb_c.cc index 9c2fa3363..79aa7fc84 100644 --- a/src/fdb5/api/fdb_c.cc +++ b/src/fdb5/api/fdb_c.cc @@ -14,6 +14,8 @@ #include "eckit/runtime/Main.h" #include "metkit/mars/MarsRequest.h" +#include "metkit/mars/MarsExpension.h" +#include "eckit/utils/Tokenizer.h" #include "fdb5/fdb5_version.h" #include "fdb5/api/FDB.h" @@ -45,11 +47,27 @@ struct fdb_request_t { fdb_request_t(std::string str) { request_ = metkit::mars::MarsRequest(str); } + size_t values(const char* name, char** values[]) { + std::string n(name); + std::vector vv = request_.values(name); + + *values = new char*[vv.size()]; + for (size_t i = 0; i < vv.size(); i++) { + (*values)[i] = new char[vv[i].size()+1]; + strncpy((*values)[i], vv[i].c_str(), vv[i].size()); + (*values)[i][vv[i].size()] = '\0'; + } + return vv.size(); + } void values(const char* name, const char* values[], int numValues) { std::string n(name); std::vector vv; + Tokenizer parse("/"); + for (int i=0; i result; + parse(values[i], result); + vv.insert(std::end(vv), std::begin(result), std::end(result)); } request_.values(n, vv); } @@ -58,6 +76,12 @@ struct fdb_request_t { req->request_ = metkit::mars::MarsRequest::parse(str); return req; } + void expand() { + bool inherit = false; + bool strict = true; + metkit::mars::MarsExpension expand(inherit, strict); + request_ = expand.expand(request_); + } const metkit::mars::MarsRequest request() const { return request_; } private: metkit::mars::MarsRequest request_; @@ -403,6 +427,18 @@ int fdb_request_add(fdb_request_t* req, const char* param, const char* values[], req->values(param, values, numValues); }); } +int fdb_request_get(fdb_request_t* req, const char* param, char** values[], size_t* numValues) { + return wrapApiFunction([req, param, values, numValues] { + ASSERT(req); + ASSERT(param); + *numValues = req->values(param, values); + }); +} +int fdb_expand_request(fdb_request_t* req) { + return wrapApiFunction([req]{ + req->expand(); + }); +} int fdb_delete_request(fdb_request_t* req) { return wrapApiFunction([req]{ ASSERT(req); diff --git a/src/fdb5/api/fdb_c.h b/src/fdb5/api/fdb_c.h index dc725a757..e3371c61a 100644 --- a/src/fdb5/api/fdb_c.h +++ b/src/fdb5/api/fdb_c.h @@ -139,6 +139,21 @@ int fdb_new_request(fdb_request_t** req); */ int fdb_request_add(fdb_request_t* req, const char* param, const char* values[], int numValues); +/** Get the Metadata values associated to a Request metadata + * \param req Request instance + * \param param Metadata name + * \param values Metadata values + * \param numValues number of metadata values + * \returns Return code (#FdbErrorValues) + */ +int fdb_request_get(fdb_request_t* req, const char* param, char** values[], size_t* numValues); + +/** Expand a Request + * \param req Request instance + * \returns Return code (#FdbErrorValues) + */ +int fdb_expand_request(fdb_request_t* req); + /** Deallocates Request object and associated resources. * \param req Request instance * \returns Return code (#FdbErrorValues) diff --git a/tests/fdb/api/test_fdb_c.cc b/tests/fdb/api/test_fdb_c.cc index cda453e04..57c1f486c 100644 --- a/tests/fdb/api/test_fdb_c.cc +++ b/tests/fdb/api/test_fdb_c.cc @@ -449,6 +449,94 @@ CASE( "fdb_c - retrieve" ) { } +CASE( "fdb_c - expand" ) { + + fdb_handle_t* fdb; + fdb_new_handle(&fdb); + fdb_request_t* request; + fdb_new_request(&request); + fdb_request_add1(request, "domain", "g"); + fdb_request_add1(request, "stream", "oper"); + fdb_request_add1(request, "levtype", "pl"); + fdb_request_add1(request, "levelist", "300"); + const char* dates[] = {"20191110", "to", "20191111"}; + fdb_request_add(request, "date", dates, 3); + fdb_request_add1(request, "time", "0000"); + fdb_request_add1(request, "step", "0"); + fdb_request_add1(request, "param", "138"); + fdb_request_add1(request, "class", "rd"); + fdb_request_add1(request, "type", "an"); + fdb_request_add1(request, "expver", "xxxx"); + + char buf[1000]; + char grib[4]; + long read = 0; + long size; + fdb_datareader_t* dr; + fdb_new_datareader(&dr); + EXPECT_EQUAL(fdb_retrieve(fdb, request, dr), FDB_ERROR_GENERAL_EXCEPTION); + + EXPECT_EQUAL(fdb_expand_request(request), FDB_SUCCESS); + + size_t numValues; + char** values; + + fdb_request_get(request, "date", &values, &numValues); + EXPECT_EQUAL(numValues, 2); + EXPECT_EQUAL(0, strncmp(values[0], "20191110", 8)); + EXPECT_EQUAL(0, strncmp(values[1], "20191111", 8)); + delete values[0]; + delete values[1]; + delete values; + + EXPECT(fdb_retrieve(fdb, request, dr) == FDB_SUCCESS); + fdb_datareader_open(dr, &size); + EXPECT_NOT_EQUAL(0, size); + fdb_datareader_read(dr, grib, 4, &read); + EXPECT_EQUAL(4, read); + EXPECT_EQUAL(0, strncmp(grib, "GRIB", 4)); + fdb_datareader_tell(dr, &read); + EXPECT_EQUAL(4, read); + fdb_datareader_seek(dr, 3); + fdb_datareader_tell(dr, &read); + EXPECT_EQUAL(3, read); + fdb_datareader_skip(dr, 3); + fdb_datareader_tell(dr, &read); + EXPECT_EQUAL(6, read); + fdb_datareader_read(dr, buf, 1000, &read); + EXPECT_EQUAL(1000, read); + fdb_datareader_tell(dr, &read); + EXPECT_EQUAL(1006, read); + fdb_delete_datareader(dr); + + fdb_request_add1(request, "date", "20191110/to/20191115/by/2"); + + fdb_request_get(request, "date", &values, &numValues); + EXPECT_EQUAL(numValues, 5); + EXPECT_EQUAL(0, strncmp(values[0], "20191110", 8)); + EXPECT_EQUAL(0, strncmp(values[1], "to", 2)); + EXPECT_EQUAL(0, strncmp(values[2], "20191115", 8)); + EXPECT_EQUAL(0, strncmp(values[3], "by", 2)); + EXPECT_EQUAL(0, strncmp(values[4], "2", 1)); + for (size_t i = 0; iregistry()); -// std::cout << key.valuesToString() << std::endl; EXPECT(key.canonicalValue("date") == t(now.yyyymmdd())); EXPECT(key.valuesToString() == "od:0001:oper:ofb:"+t(now.yyyymmdd())+":0000:MHS:3001");