NITFPRIV(NITF_BOOL) defaultSetField(nitf_TRE * tre, const char *tag, NITF_DATA * data, size_t dataLength, nitf_Error * error) { nitf_Field* field = NULL; if (strcmp(tag, NITF_TRE_RAW)) { nitf_Error_initf(error, NITF_CTXT, NITF_ERR_INVALID_PARAMETER, "Invalid param [%s]", tag); return NITF_FAILURE; } field = nitf_Field_construct(dataLength, NITF_BINARY, error); if (!field) return NITF_FAILURE; /* TODO -- likely inefficient, since we end up copying the raw data here */ if (!nitf_Field_setRawData(field, (NITF_DATA *) data, dataLength, error)) return NITF_FAILURE; if (nitf_HashTable_exists(((nitf_TREPrivateData*)tre->priv)->hash, tag)) { nitf_Field* oldValue; nitf_Pair* pair = nitf_HashTable_find( ((nitf_TREPrivateData*)tre->priv)->hash, tag); oldValue = (nitf_Field*)pair->data; nitf_Field_destruct(&oldValue); pair->data = field; return NITF_SUCCESS; } /* reset the lengths in two places */ ((nitf_TREPrivateData*)tre->priv)->length = dataLength; ((nitf_TREPrivateData*)tre->priv)->description[0].data_count = dataLength; return nitf_HashTable_insert(((nitf_TREPrivateData*)tre->priv)->hash, tag, field, error); }
/*! * Clone this object. This is a deep copy operation. * * \param source The source object * \param error An error to populate upon failure * \return A new object that is identical to the old */ NITFAPI(nitf_Field *) nitf_Field_clone(nitf_Field * source, nitf_Error * error) { nitf_Field *field = NULL; if (source) { /* construct new one */ field = nitf_Field_construct(source->length, source->type, error); if (field) { field->resizable = source->resizable; /* set the data */ if (!nitf_Field_setRawData (field, (NITF_DATA *) source->raw, source->length, error)) { nitf_Field_destruct(&field); field = NULL; } } } return field; }
//! set the value void set(NITF_DATA* inval, size_t length) throw(nitf::NITFException) { NITF_BOOL x = nitf_Field_setRawData(getNativeOrThrow(), inval, length, &error); if (!x) throw nitf::NITFException(&error); }
NITFAPI(NITF_BOOL) nitf_TREUtils_fillData(nitf_TRE * tre, const nitf_TREDescription* descrip, nitf_Error * error) { nitf_TRECursor cursor; /* set the description so the cursor can use it */ ((nitf_TREPrivateData*)tre->priv)->description = (nitf_TREDescription*)descrip; /* loop over the description, and add blank fields for the * "normal" fields... any special case fields (loops, conditions) * won't be added here */ cursor = nitf_TRECursor_begin(tre); while (!nitf_TRECursor_isDone(&cursor)) { if (nitf_TRECursor_iterate(&cursor, error)) { nitf_Pair* pair = nitf_HashTable_find( ((nitf_TREPrivateData*)tre->priv)->hash, cursor.tag_str); if (!pair || !pair->data) { nitf_Field* field = NULL; int fieldLength = cursor.length; /* If it is a GOBBLE length, there isn't really a standard * on how long it can be... therefore we'll just throw in * a field of size 1, just to have something... */ if (fieldLength == NITF_TRE_GOBBLE) { fieldLength = 1; } field = nitf_Field_construct(fieldLength, cursor.desc_ptr->data_type, error); /* set the field to be resizable later on */ if (cursor.length == NITF_TRE_GOBBLE) field->resizable = 1; /* special case if BINARY... must set Raw Data */ if (cursor.desc_ptr->data_type == NITF_BINARY) { char* tempBuf = (char *) NITF_MALLOC(fieldLength); if (!tempBuf) { nitf_Field_destruct(&field); nitf_Error_init(error, NITF_STRERROR(NITF_ERRNO), NITF_CTXT, NITF_ERR_MEMORY); goto CATCH_ERROR; } memset(tempBuf, 0, fieldLength); nitf_Field_setRawData(field, (NITF_DATA *) tempBuf, fieldLength, error); } else if (cursor.desc_ptr->data_type == NITF_BCS_N) { /* this will get zero/blank filled by the function */ nitf_Field_setString(field, "0", error); } else { /* this will get zero/blank filled by the function */ nitf_Field_setString(field, " ", error); } /* add to hash if there wasn't an entry yet */ if (!pair) { nitf_HashTable_insert( ((nitf_TREPrivateData*)tre->priv)->hash, cursor.tag_str, field, error); } /* otherwise, just set the data pointer */ else { pair->data = (NITF_DATA *) field; } } } } nitf_TRECursor_cleanup(&cursor); /* no problems */ /* return tre->descrip; */ return NITF_SUCCESS; CATCH_ERROR: return NITF_FAILURE; }
NITFAPI(NITF_BOOL) nitf_TREUtils_setValue(nitf_TRE * tre, const char *tag, NITF_DATA * data, size_t dataLength, nitf_Error * error) { nitf_Pair *pair; nitf_Field *field = NULL; nitf_TRECursor cursor; NITF_BOOL done = 0; NITF_BOOL status = 1; nitf_FieldType type = NITF_BCS_A; /* used temporarily for storing the length */ int length; /* get out if TRE is null */ if (!tre) { nitf_Error_init(error, "setValue -> invalid tre object", NITF_CTXT, NITF_ERR_INVALID_PARAMETER); return NITF_FAILURE; } /* If the field already exists, get it and modify it */ if (nitf_HashTable_exists(((nitf_TREPrivateData*)tre->priv)->hash, tag)) { pair = nitf_HashTable_find( ((nitf_TREPrivateData*)tre->priv)->hash, tag); field = (nitf_Field *) pair->data; if (!field) { nitf_Error_initf(error, NITF_CTXT, NITF_ERR_INVALID_PARAMETER, "setValue -> invalid field object: %s", tag); return NITF_FAILURE; } /* check to see if the data passed in is too large or too small */ if ((dataLength > field->length && !field->resizable) || dataLength < 1) { nitf_Error_initf(error, NITF_CTXT, NITF_ERR_INVALID_PARAMETER, "setValue -> invalid dataLength for field: %s", tag); return NITF_FAILURE; } if (!nitf_Field_setRawData (field, (NITF_DATA *) data, dataLength, error)) { return NITF_FAILURE; } #ifdef NITF_DEBUG fprintf(stdout, "Setting (and filling) Field [%s] to TRE [%s]\n", tag, tre->tag); #endif /* Now we need to fill our data */ if (!nitf_TREUtils_fillData(tre, ((nitf_TREPrivateData*)tre->priv)->description, error)) return NITF_FAILURE; } /* it doesn't exist in the hash yet, so we need to find it */ else { cursor = nitf_TRECursor_begin(tre); while (!nitf_TRECursor_isDone(&cursor) && !done && status) { if (nitf_TRECursor_iterate(&cursor, error) == NITF_SUCCESS) { /* we found it */ if (strcmp(tag, cursor.tag_str) == 0) { if (cursor.desc_ptr->data_type == NITF_BCS_A) { type = NITF_BCS_A; } else if (cursor.desc_ptr->data_type == NITF_BCS_N) { type = NITF_BCS_N; } else if (cursor.desc_ptr->data_type == NITF_BINARY) { type = NITF_BINARY; } else { /* bad type */ nitf_Error_init(error, "setValue -> invalid data type", NITF_CTXT, NITF_ERR_INVALID_PARAMETER); return NITF_FAILURE; } length = cursor.length; /* check to see if we should gobble the rest */ if (length == NITF_TRE_GOBBLE) { length = dataLength; } /* construct the field */ field = nitf_Field_construct(length, type, error); /* now, set the data */ nitf_Field_setRawData(field, (NITF_DATA *) data, dataLength, error); #ifdef NITF_DEBUG fprintf(stdout, "Adding (and filling) Field [%s] to TRE [%s]\n", cursor.tag_str, tre->tag); #endif /* add to the hash */ nitf_HashTable_insert( ((nitf_TREPrivateData*)tre->priv)->hash, cursor.tag_str, field, error); /* Now we need to fill our data */ if (!nitf_TREUtils_fillData(tre, ((nitf_TREPrivateData*)tre->priv)->description, error)) return NITF_FAILURE; done = 1; /* set, so we break out of loop */ } } } /* did we find it? */ if (!done) { nitf_Error_initf(error, NITF_CTXT, NITF_ERR_UNK, "Unable to find tag, '%s', in TRE hash for TRE '%s'", tag, tre->tag); status = 0; } nitf_TRECursor_cleanup(&cursor); } return status; }
NITFAPI(int) nitf_TREUtils_parse(nitf_TRE * tre, char *bufptr, nitf_Error * error) { int status = 1; int iterStatus = NITF_SUCCESS; int offset = 0; int length; nitf_TRECursor cursor; nitf_Field *field = NULL; nitf_TREPrivateData *privData = NULL; /* get out if TRE is null */ if (!tre) { nitf_Error_init(error, "parse -> invalid tre object", NITF_CTXT, NITF_ERR_INVALID_PARAMETER); return NITF_FAILURE; } privData = (nitf_TREPrivateData*)tre->priv; /* flush the hash first, to protect from duplicate entries */ if (privData) { nitf_TREPrivateData_flush(privData, error); } cursor = nitf_TRECursor_begin(tre); while (offset < privData->length && status) { if ((iterStatus = nitf_TRECursor_iterate(&cursor, error)) == NITF_SUCCESS) { length = cursor.length; if (length == NITF_TRE_GOBBLE) { length = privData->length - offset; } /* no need to call setValue, because we already know * it is OK for this one to be in the hash */ /* construct the field */ field = nitf_Field_construct(length, cursor.desc_ptr->data_type, error); if (!field) goto CATCH_ERROR; /* first, check to see if we need to swap bytes */ if (field->type == NITF_BINARY && (length == NITF_INT16_SZ || length == NITF_INT32_SZ)) { if (length == NITF_INT16_SZ) { nitf_Int16 int16 = (nitf_Int16)NITF_NTOHS(*((nitf_Int16 *) (bufptr + offset))); status = nitf_Field_setRawData(field, (NITF_DATA *) & int16, length, error); } else if (length == NITF_INT32_SZ) { nitf_Int32 int32 = (nitf_Int32)NITF_NTOHL(*((nitf_Int32 *) (bufptr + offset))); status = nitf_Field_setRawData(field, (NITF_DATA *) & int32, length, error); } } else { /* check for the other binary lengths ... */ if (field->type == NITF_BINARY) { /* TODO what to do??? 8 bit is ok, but what about 64? */ /* for now, just let it go through... */ } /* now, set the data */ status = nitf_Field_setRawData(field, (NITF_DATA *) (bufptr + offset), length, error); } #ifdef NITF_DEBUG { fprintf(stdout, "Adding Field [%s] to TRE [%s]\n", cursor.tag_str, tre->tag); } #endif /* add to the hash */ nitf_HashTable_insert(((nitf_TREPrivateData*)tre->priv)->hash, cursor.tag_str, field, error); offset += length; } /* otherwise, the iterate function thinks we are done */ else { break; } } nitf_TRECursor_cleanup(&cursor); /* check if we still have more to parse, and throw an error if so */ if (offset < privData->length) { nitf_Error_init(error, "TRE data is longer than it should be", NITF_CTXT, NITF_ERR_INVALID_OBJECT); status = NITF_FAILURE; } return status; /* deal with errors here */ CATCH_ERROR: return NITF_FAILURE; }
NITFPRIV(int) defaultRead(nitf_IOInterface *io, nitf_Uint32 length, nitf_TRE * tre, struct _nitf_Record* record, nitf_Error * error) { nitf_Field *field = NULL; nitf_TREDescription *descr = NULL; char *data = NULL; NITF_BOOL success; if (!tre) { /* set error ??? */ goto CATCH_ERROR; } /* malloc the space for the raw data */ data = (char *) NITF_MALLOC(length + 1); if (!data) { nitf_Error_init(error, NITF_STRERROR(NITF_ERRNO), NITF_CTXT, NITF_ERR_MEMORY); goto CATCH_ERROR; } memset(data, 0, length + 1); descr = (nitf_TREDescription *) NITF_MALLOC(2 * sizeof(nitf_TREDescription)); if (!descr) { nitf_Error_init(error, NITF_STRERROR(NITF_ERRNO), NITF_CTXT, NITF_ERR_MEMORY); goto CATCH_ERROR; } descr[0].data_type = NITF_BINARY; descr[0].data_count = length; descr[0].label = _NITF_DEFAULT_TRE_LABEL; descr[0].tag = NITF_TRE_RAW; descr[1].data_type = NITF_END; descr[1].data_count = 0; descr[1].label = NULL; descr[1].tag = NULL; tre->priv = nitf_TREPrivateData_construct(error); if (!tre->priv) goto CATCH_ERROR; ((nitf_TREPrivateData*)tre->priv)->length = length; ((nitf_TREPrivateData*)tre->priv)->description = descr; /* Read the data extension into the tre */ success = nitf_TREUtils_readField(io, data, (int) length, error); if (!success) goto CATCH_ERROR; field = nitf_Field_construct(length, NITF_BINARY, error); if (field == NULL) { goto CATCH_ERROR; } /* TODO -- likely inefficient, since we end up copying the raw data here */ if (!nitf_Field_setRawData (field, (NITF_DATA *) data, length, error)) { goto CATCH_ERROR; } nitf_HashTable_insert(((nitf_TREPrivateData*)tre->priv)->hash, NITF_TRE_RAW, field, error); NITF_FREE(data); #ifdef NITF_PRINT_TRES printf ("------------------------------------------------------------\n"); printf("[%s] length %d (unknown TRE default handler)\n", tre->tag, length); printf ("------------------------------------------------------------\n"); printf("\n"); #endif return NITF_SUCCESS; /* Handle any errors */ CATCH_ERROR: if (descr) NITF_FREE(descr); if (tre && tre->priv) nitf_TREPrivateData_destruct((nitf_TREPrivateData**)&tre->priv); return NITF_FAILURE; }
/* TODO This is a cut and paste of nitf_TREUtils_parse() with a little bit * of extra logic for determining the appropriate field type for * engineering data. Is there a way to reuse more of the other * parse function? */ NITFPRIV(int) ENGRDA_parse(nitf_TRE * tre, char *bufptr, nitf_Error * error) { int status = 1; int iterStatus = NITF_SUCCESS; int offset = 0; int length; nitf_TRECursor cursor; nitf_Field *field = NULL; nitf_TREPrivateData *privData = NULL; nitf_FieldType prevValueType; nitf_FieldType fieldType; /* get out if TRE is null */ if (!tre) { nitf_Error_init(error, "parse -> invalid tre object", NITF_CTXT, NITF_ERR_INVALID_PARAMETER); return NITF_FAILURE; } privData = (nitf_TREPrivateData*)tre->priv; /* flush the hash first, to protect from duplicate entries */ if (privData) { nitf_TREPrivateData_flush(privData, error); } cursor = nitf_TRECursor_begin(tre); prevValueType = NITF_BINARY; while (offset < privData->length && status) { if ((iterStatus = nitf_TRECursor_iterate(&cursor, error)) == NITF_SUCCESS) { length = cursor.length; if (length == NITF_TRE_GOBBLE) { length = privData->length - offset; } /* no need to call setValue, because we already know * it is OK for this one to be in the hash */ /* for engineering data, the TREDescription specifies the type as * binary but in reality it's based on the value type field. this * will be saved off for us below. it's also critical to set this * correctly so that string types don't get endian swapped. */ fieldType = !strncmp(cursor.tag_str, "ENGDATA", 7) ? prevValueType : cursor.desc_ptr->data_type; /* construct the field */ field = nitf_Field_construct(length, fieldType, error); if (!field) goto CATCH_ERROR; /* first, check to see if we need to swap bytes */ if (field->type == NITF_BINARY && (length == NITF_INT16_SZ || length == NITF_INT32_SZ)) { if (length == NITF_INT16_SZ) { nitf_Int16 int16 = (nitf_Int16)NITF_NTOHS(*((nitf_Int16 *) (bufptr + offset))); status = nitf_Field_setRawData(field, (NITF_DATA *) & int16, length, error); } else if (length == NITF_INT32_SZ) { nitf_Int32 int32 = (nitf_Int32)NITF_NTOHL(*((nitf_Int32 *) (bufptr + offset))); status = nitf_Field_setRawData(field, (NITF_DATA *) & int32, length, error); } } else { /* check for the other binary lengths ... */ if (field->type == NITF_BINARY) { /* TODO what to do??? 8 bit is ok, but what about 64? */ /* for now, just let it go through... */ } /* now, set the data */ status = nitf_Field_setRawData(field, (NITF_DATA *) (bufptr + offset), length, error); } /* when we see the value type, save it off * we'll eventually read this when we get to the engineering data * itself */ if (!strncmp(cursor.tag_str, "ENGTYP", 6) && field->type == NITF_BCS_A && field->length == 1) { prevValueType = (field->raw[0] == 'A') ? NITF_BCS_A : NITF_BINARY; } #ifdef NITF_DEBUG { fprintf(stdout, "Adding Field [%s] to TRE [%s]\n", cursor.tag_str, tre->tag); } #endif /* add to the hash */ nitf_HashTable_insert(((nitf_TREPrivateData*)tre->priv)->hash, cursor.tag_str, field, error); offset += length; } /* otherwise, the iterate function thinks we are done */ else { break; } } nitf_TRECursor_cleanup(&cursor); /* check if we still have more to parse, and throw an error if so */ if (offset < privData->length) { nitf_Error_init(error, "TRE data is longer than it should be", NITF_CTXT, NITF_ERR_INVALID_OBJECT); status = NITF_FAILURE; } return status; /* deal with errors here */ CATCH_ERROR: return NITF_FAILURE; }
NITFAPI(NITF_BOOL) nitf_Field_setReal(nitf_Field * field, const char *type, NITF_BOOL plus, double value, nitf_Error *error) { nitf_Uint32 precision; /* Format precision */ nitf_Uint32 bufferLen; /* Length of buffer */ char *buffer; /* Holds intermediate and final results */ char fmt[64]; /* Format used */ /* Check type */ if ( (strcmp(type, "f") != 0) && (strcmp(type, "e") != 0) && (strcmp(type, "E") != 0)) { nitf_Error_initf(error, NITF_CTXT, NITF_ERR_INVALID_PARAMETER, "Invalid conversion type %s", type); return(NITF_FAILURE); } /* Allocate buffer used to build value */ /* The 64 covers the puncuation and exponent and is overkill */ bufferLen = field->length * 2 + 64; buffer = NITF_MALLOC(bufferLen + 1); if (buffer == NULL) { nitf_Error_init(error, NITF_STRERROR(NITF_ERRNO), NITF_CTXT, NITF_ERR_MEMORY); return(NITF_FAILURE); } /* Try a precision that will be too large and then adjust it based on the length of what you get. This results in a left justified string with the maximum number of decmal places. What you are actually figuring is the number of digits in the whole part of the number. */ precision = field->length; /* Must be too big */ if (plus) NITF_SNPRINTF(fmt, 64, "%%+-1.%dl%s", precision, type); else NITF_SNPRINTF(fmt, 64, "%%-1.%dl%s", precision, type); NITF_SNPRINTF(buffer, bufferLen + 1, fmt, value); bufferLen = strlen(buffer); /* if it's resizable and a different length, we resize */ if (field->resizable && bufferLen != field->length) { if (!nitf_Field_resizeField(field, bufferLen, error)) return NITF_FAILURE; } if (bufferLen > field->length) { if (precision > bufferLen - field->length) precision -= bufferLen - field->length; else precision = 0; if (plus) NITF_SNPRINTF(fmt, 64, "%%+-1.%dl%s", precision, type); else NITF_SNPRINTF(fmt, 64, "%%-1.%dl%s", precision, type); NITF_SNPRINTF(buffer, bufferLen + 1, fmt, value); } if (!nitf_Field_setRawData(field, buffer, field->length, error)) { NITF_FREE(buffer); return(NITF_FAILURE); } NITF_FREE(buffer); return(NITF_SUCCESS); }