NITFPRIV(NITF_BOOL) basicHasNext(nitf_TREEnumerator** it) { nitf_TRECursor* cursor = it && *it ? (nitf_TRECursor*)(*it)->data : NULL; if (cursor && nitf_TRECursor_isDone(cursor)) { nitf_TRECursor_cleanup(cursor); NITF_FREE(cursor); NITF_FREE(*it); *it = NULL; return NITF_FAILURE; /* maybe 0 is better */ } return cursor != NULL ? NITF_SUCCESS : NITF_FAILURE; }
NITFAPI(NITF_BOOL) nitf_TRECursor_isDone(nitf_TRECursor * tre_cursor) { nitf_Error error; int isDone = (tre_cursor->desc_ptr == tre_cursor->end_ptr); /* check if the passed in cursor is not at the beginning */ if (!isDone && tre_cursor->index >= 0) { nitf_TRECursor dolly = nitf_TRECursor_clone(tre_cursor, &error); /* if iterate returns 0, we are done */ isDone = !nitf_TRECursor_iterate(&dolly, &error); isDone = isDone || (dolly.desc_ptr == dolly.end_ptr); nitf_TRECursor_cleanup(&dolly); } return isDone; }
NITFAPI(int) nitf_TREUtils_computeLength(nitf_TRE * tre) { int length = 0; int tempLength; nitf_Error error; nitf_Pair *pair; /* temp nitf_Pair */ nitf_Field *field; /* temp nitf_Field */ nitf_TRECursor cursor; /* get out if TRE is null */ if (!tre) return -1; cursor = nitf_TRECursor_begin(tre); while (!nitf_TRECursor_isDone(&cursor)) { if (nitf_TRECursor_iterate(&cursor, &error) == NITF_SUCCESS) { tempLength = cursor.length; if (tempLength == NITF_TRE_GOBBLE) { /* we don't have any other way to know the length of this * field, other than to see if the field is in the hash * and use the length defined when it was created. * Otherwise, we don't add any length. */ tempLength = 0; pair = nitf_HashTable_find( ((nitf_TREPrivateData*)tre->priv)->hash, cursor.tag_str); if (pair) { field = (nitf_Field *) pair->data; if (field) tempLength = field->length; } } length += tempLength; } } nitf_TRECursor_cleanup(&cursor); return length; }
NITFAPI(NITF_BOOL) nitf_TREUtils_isSane(nitf_TRE * tre) { int status = 1; nitf_Error error; nitf_TRECursor cursor; /* get out if TRE is null */ if (!tre) return NITF_FAILURE; cursor = nitf_TRECursor_begin(tre); while (!nitf_TRECursor_isDone(&cursor) && status) { if (nitf_TRECursor_iterate(&cursor, &error) == NITF_SUCCESS) if (!nitf_TRE_exists(tre, cursor.tag_str)) status = !status; } nitf_TRECursor_cleanup(&cursor); return status; }
NITFAPI(int) nitf_TREUtils_print(nitf_TRE * tre, nitf_Error * error) { nitf_Pair *pair; /* temp pair */ int status = NITF_SUCCESS; nitf_TRECursor cursor; /* get out if TRE is null */ if (!tre) { nitf_Error_init(error, "print -> invalid tre object", NITF_CTXT, NITF_ERR_INVALID_PARAMETER); return NITF_FAILURE; } cursor = nitf_TRECursor_begin(tre); while (!nitf_TRECursor_isDone(&cursor) && (status == NITF_SUCCESS)) { if ((status = nitf_TRECursor_iterate(&cursor, error)) == NITF_SUCCESS) { pair = nitf_HashTable_find( ((nitf_TREPrivateData*)tre->priv)->hash, cursor.tag_str); if (!pair || !pair->data) { nitf_Error_initf(error, NITF_CTXT, NITF_ERR_UNK, "Unable to find tag, '%s', in TRE hash for TRE '%s'", cursor.tag_str, tre->tag); status = NITF_FAILURE; } else { printf("%s (%s) = [", cursor.desc_ptr->label == NULL ? "null" : cursor.desc_ptr->label, cursor.tag_str); nitf_Field_print((nitf_Field *) pair->data); printf("]\n"); } } } nitf_TRECursor_cleanup(&cursor); return status; }
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; }
NITFAPI(char *) nitf_TREUtils_getRawData(nitf_TRE * tre, nitf_Uint32* treLength, nitf_Error * error) { int status = 1; int offset = 0; nitf_Uint32 length; int tempLength; /* data buffer - Caller must free this */ char *data = NULL; /* temp data buffer */ char *tempBuf = NULL; /* temp nitf_Pair */ nitf_Pair *pair; /* temp nitf_Field */ nitf_Field *field; /* the cursor */ nitf_TRECursor cursor; /* get actual length of TRE */ length = nitf_TREUtils_computeLength(tre); *treLength = length; if (length <= 0) { nitf_Error_init(error, "TRE has invalid length", NITF_CTXT, NITF_ERR_INVALID_OBJECT); return NULL; } /* allocate the memory - this does not get freed in this function */ 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); cursor = nitf_TRECursor_begin(tre); while (!nitf_TRECursor_isDone(&cursor) && status && offset < length) { if (nitf_TRECursor_iterate(&cursor, error) == NITF_SUCCESS) { pair = nitf_HashTable_find(((nitf_TREPrivateData*)tre->priv)->hash, cursor.tag_str); if (pair && pair->data) { tempLength = cursor.length; if (tempLength == NITF_TRE_GOBBLE) { tempLength = length - offset; } field = (nitf_Field *) pair->data; /* get the raw data */ tempBuf = NITF_MALLOC(tempLength); if (!tempBuf) { nitf_Error_init(error, NITF_STRERROR(NITF_ERRNO), NITF_CTXT, NITF_ERR_MEMORY); goto CATCH_ERROR; } /* get the data as raw buf */ nitf_Field_get(field, (NITF_DATA *) tempBuf, NITF_CONV_RAW, tempLength, error); /* first, check to see if we need to swap bytes */ if (field->type == NITF_BINARY) { if (tempLength == NITF_INT16_SZ) { nitf_Int16 int16 = (nitf_Int16)NITF_HTONS(*((nitf_Int16 *) tempBuf)); memcpy(tempBuf, (char*)&int16, tempLength); } else if (tempLength == NITF_INT32_SZ) { nitf_Int32 int32 = (nitf_Int32)NITF_HTONL(*((nitf_Int32 *) tempBuf)); memcpy(tempBuf, (char*)&int32, tempLength); } else { /* TODO what to do??? 8 bit is ok, but what about 64? */ /* for now, just let it go through... */ } } /* now, memcpy the data */ memcpy(data + offset, tempBuf, tempLength); offset += tempLength; /* free the buf */ NITF_FREE(tempBuf); } else { nitf_Error_init(error, "Failed due to missing TRE field(s)", NITF_CTXT, NITF_ERR_INVALID_OBJECT); goto CATCH_ERROR; } } } nitf_TRECursor_cleanup(&cursor); return data; /* deal with errors here */ CATCH_ERROR: if (data) NITF_FREE(data); return NULL; }
/* 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; }