/* * Returns a new upstream filter. * * Arguments: * upFilter Pointer to pointer to returned upstream filter. Must * not be NULL. Set on and only on success. * Returns: * NULL Success. * else Failure error object. */ ErrorObj* upFilter_new( UpFilter** const upFilter) { ErrorObj* errObj; size_t nbytes = sizeof(UpFilter); UpFilter* const filt = (UpFilter*)malloc(nbytes); if (NULL == filt) { errObj = ERR_NEW2(0, NULL, "Couldn't allocate %lu-bytes: %s", (unsigned long)nbytes, strerror(errno)); } else { StringBuf* const strBuf = strBuf_new(132); if (NULL == strBuf) { errObj = ERR_NEW(0, NULL, strBuf_strerror(strBuf)); free(filt); } else { filt->strBuf = strBuf; filt->head = NULL; filt->stringOutOfDate = 1; filt->count = 0; *upFilter = filt; errObj = NULL; /* success */ } } /* "filt" allocated */ return errObj; }
/** * Sets an LDM product-identifier from a GRIB message. * * Not Atomic, * Idempotent, * Thread-safe * * @param[out] ident Product-identifier buffer. * @param[in] identSize Size of product-identifier buffer in bytes. * @param[in] decoded Decoded GRIB message. * @param[in] wmoHead WMO header associated with the GRIB message. * @retval 0 Success. \c *ident is set. * @retval 1 GRIB message has no data. * @retval 3 System error. */ static int setIdent( char* const ident, const size_t identSize, DecodedGrib2Msg* const decoded, const char* const wmoHead) { const size_t numFields = g2d_getNumFields(decoded); int status; if (0 == numFields) { log_add("GRIB message has no fields"); status = 1; } else { StringBuf* const prods = strBuf_new(127); /* initially empty */ if (NULL == prods) { log_add_syserr("Couldn't allocate string-buffer for products"); log_flush_error(); status = 3; } else { Gribmsg gribMsg; Geminfo gemInfo; int modelId; status = appendParameterNames(prods, decoded, &gribMsg, &gemInfo); if (0 == status) { status = getModelId(decoded, &modelId); if (0 == status) composeIdent(ident, identSize, decoded, &gribMsg, &gemInfo, prods, wmoHead, modelId); } strBuf_free(prods); } /* "prods" allocated */ } /* numFields > 0 */ return status; }
/** * Returns a new instance of a child-map. * * @retval NULL Failure. \c log_start() called. * @retval !NULL Pointer to a new instance. */ ChildMap* cm_new(void) { ChildMap* map = (ChildMap*)malloc(sizeof(ChildMap)); if (NULL == map) { LOG_SERROR0("Couldn't allocate new child-map"); } else { map->root = NULL; map->count = 0; map->buf = strBuf_new(132); if (NULL == map->buf) { LOG_SERROR0("Couldn't allocate command-line buffer"); free(map); map = NULL; } } return map; }
/** * Generates an LDM product-identifier from a GRIB edition 2 message. * * Atomic, * Idempotent, * Not thread-safe * * @param[in] data Pointer to the GRIB message. * @param[in] sz Length of the GRIB message in bytes. * @param[in] wmohead Pointer to the associated WMO header string. * @param[out] ident Pointer to a buffer to receive the LDM * product-identifier. * @param[in] identSize Size of the \c ident buffer in bytes. * @retval 0 Success. \c ident is set and NUL-terminated. * @retval 1 Invalid GRIB message. * @retval 2 GRIB message isn't edition 2. * @retval 3 System error. */ int grib2name ( char* const data, const size_t sz, const char* const wmohead, char* const ident, const size_t identSize) { #if USE_GRIB2_DECODER int status; DecodedGrib2Msg* decoded; if (status = g2d_new(&decoded, (unsigned char*)data, sz)) { log_add("Couldn't decode GRIB message"); status = G2D_INVALID == status ? 1 : G2D_NOT_2 ? 2 : 3; } else { if (status = setIdent(ident, identSize, decoded, wmohead)) { log_add("Couldn't set LDM product-identifier"); status = 1; } g2d_free(decoded); } /* "decoded" allocated */ return status; #else static StringBuf* paramNames; /* Buffer for parameter name(s) */ int iField; /* GRIB-2 field index */ int status; /* Function return code */ g2int listsec0[3]; /* GRIB-2 section 0 parameters */ g2int listsec1[13]; /* GRIB-2 section 1 parameters */ g2int numlocal; /* Number of GRIB section 2-s */ int model_id; /* ID of model */ int grid_id; /* ID of grid */ char fdats[80]; /* No idea */ char levelstmp[80]; /* Level? */ Gribmsg g2Msg; /* GRIB-2 message structure */ if (paramNames) { strBuf_clear(paramNames); } else { paramNames = strBuf_new(127); if (NULL == paramNames) { log_add("Couldn't allocate buffer for parameter name(s)"); return 3; } } g2Msg.cgrib2 = (unsigned char*)data; g2Msg.mlength = sz; g2Msg.gfld = NULL; g2Msg.field_tot = 0; if ((status = g2_info(g2Msg.cgrib2, g2Msg.mlength, listsec0, listsec1, &(g2Msg.field_tot), &numlocal)) != 0) return (2 == status) ? 2 : 1; if (g2Msg.field_tot <= 0) { log_add("GRIB-2 message has no data fields"); return 1; } for (iField = 0; iField < g2Msg.field_tot; iField++) { static char g2tables[5][LLMXLN]; /* GRIB tables */ static char* tbllist[5] = {g2tables[0], g2tables[1], g2tables[2], g2tables[3], g2tables[4]}; /* Addresses of GRIB tables */ Geminfo gemInfo; /* GEMPAK structure */ int const lastField = iField == g2Msg.field_tot - 1; status = g2_getfld(g2Msg.cgrib2, g2Msg.mlength, iField+1, 0, 0, &g2Msg.gfld); if (status) { log_add("Invalid GRIB-2 message: g2_getfld() status=%d", status); return (2 == status) ? 2 : 1; } /* "g2Msg.gfld" is allocated */ /* Initialize strings in Geminfo structure */ (void)memset(gemInfo.cproj, 0, sizeof(gemInfo.cproj)); (void)memset(gemInfo.parm, 0, sizeof(gemInfo.parm)); (void)memset(gemInfo.gdattm1, 0, sizeof(gemInfo.gdattm1)); (void)memset(gemInfo.gdattm2, 0, sizeof(gemInfo.gdattm2)); /* * In the original code, the last field determined the model ID. */ if (lastField) model_id = g2Msg.gfld->ipdtmpl[4]; /* * This assignment to "grid_id" isn't under the above "lastField" * conditional because "decode_g2gnum()" might have side-effects upon * which "gb2_2gem()" depends. */ grid_id = (g2Msg.gfld->griddef == 0) ? decode_g2gnum(g2Msg.gfld) : g2Msg.gfld->griddef; gb2_2gem(&g2Msg, &gemInfo, tbllist, &status); if (status) { log_add("Couldn't decode GRIB2 message. WMO header=\"%s\"", wmohead); log_flush_error(); if (lastField) { (void)strcpy(fdats, "FHRS"); /* safe */ (void)strcpy(levelstmp, "LVL"); /* safe */ } } else { char g2name[13]; /**< Name of product/parameter */ int ilen; /**< Length of resulting string */ (void)strcpy(g2name, gemInfo.parm); /* both 13 bytes */ cst_rmbl(g2name, g2name, &ilen, &status); if (iField) strBuf_appendString(paramNames, ";"); strBuf_appendString(paramNames, g2name); cst_rxbl(gemInfo.unit, gemInfo.unit, &ilen, &status); if (ilen == 0) (void)strcpy(gemInfo.unit, "-"); /* safe */ cst_rmbl(gemInfo.gdattm1, gemInfo.gdattm1, &ilen, &status); cst_rmbl(gemInfo.gdattm2, gemInfo.gdattm2, &ilen, &status); /* * In the original code, the last field determined the following * parameters. */ if (lastField) { static char strBuf[5]; /* Holds 4-char string */ static char* strptr = strBuf; /* For "cst_itoc()" */ if (ilen > 0) (void)snprintf(fdats, sizeof(fdats), "%s-%s", gemInfo.gdattm1, gemInfo.gdattm2); else (void)snprintf(fdats, sizeof(fdats), "%s", gemInfo.gdattm1); for (ilen = 1; ilen > 0; cst_rmst(fdats, "/", &ilen, fdats, &status)); cst_itoc(&gemInfo.vcord, 1, &strptr, &status); if (gemInfo.level[1] == -1) (void)snprintf(levelstmp, sizeof(levelstmp), "%d %s %s", gemInfo.level[0], gemInfo.unit, strptr); else (void)snprintf(levelstmp, sizeof(levelstmp), "%d-%d %s %s", gemInfo.level[0], gemInfo.level[1], gemInfo.unit, strptr); } } g2_free(g2Msg.gfld); g2Msg.gfld = NULL; } /* * See if the WMO header can be used for grid 0 products */ if ((grid_id == 0) && (strlen(wmohead) > 11) && (wmohead[7] == 'K') && (wmohead[8] == 'W')) { int wmoGridId = wmo_to_gridid(&wmohead[0], &wmohead[2]); if (wmoGridId > 0) grid_id = wmoGridId; } (void)snprintf(ident, identSize, "grib2/%s/%s/#%03d/%s/%s/%s", s_pds_center((int)listsec1[0], (int)listsec1[1]), s_pds_model((int)listsec1[0], model_id), grid_id, fdats, strBuf_toString(paramNames), levelstmp); return 0; #endif }