NITFPRIV(nitf_Pair*) basicIncrement(nitf_TREEnumerator* it, nitf_Error* error) { /* get the next value, and increment the cursor */ nitf_TRECursor* cursor = it ? (nitf_TRECursor*)it->data : NULL; nitf_Pair* data; if (!cursor || !nitf_TRECursor_iterate(cursor, error)) { nitf_Error_initf(error, NITF_CTXT, NITF_ERR_INVALID_OBJECT, "Invalid cursor, or error iterating..."); return NULL; } if (!nitf_TRE_exists(cursor->tre, cursor->tag_str)) goto CATCH_ERROR; data = nitf_HashTable_find(((nitf_TREPrivateData*)cursor->tre->priv)->hash, cursor->tag_str); if (!data) goto CATCH_ERROR; return data; CATCH_ERROR: nitf_Error_initf(error, NITF_CTXT, NITF_ERR_INVALID_OBJECT, "Couldnt retrieve tag [%s]", cursor->tag_str); return NULL; }
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; }
NITFAPI(int) nitf_TRECursor_iterate(nitf_TRECursor * tre_cursor, nitf_Error * error) { nitf_TREDescription *dptr; int *stack; /* used for in conjuction with the stacks */ int index; /* used for in conjuction with the stacks */ int loopCount = 0; /* tells how many times to loop */ int loop_rtni = 0; /* used for temp storage */ int loop_idxi = 0; /* used for temp storage */ int numIfs = 0; /* used to keep track of nested Ifs */ int numLoops = 0; /* used to keep track of nested Loops */ int done = 0; /* flag used for special cases */ char idx_str[10][10]; /* used for keeping track of indexes */ if (!tre_cursor->loop || !tre_cursor->loop_idx || !tre_cursor->loop_rtn) { /* not initialized */ nitf_Error_init(error, "Unhandled TRE Value data type", NITF_CTXT, NITF_ERR_INVALID_PARAMETER); return NITF_FAILURE; } /* count how many descriptions there are */ dptr = ((nitf_TREPrivateData*)tre_cursor->tre->priv)->description; while (!done) { done = 1; /* set the flag */ /* iterate the index */ tre_cursor->index++; if (tre_cursor->index < tre_cursor->numItems) { memset(tre_cursor->tag_str, 0, TAG_BUF_LEN); tre_cursor->prev_ptr = tre_cursor->desc_ptr; tre_cursor->desc_ptr = &dptr[tre_cursor->index]; /* if already in a loop, prepare the array of values */ if (tre_cursor->looping) { stack = tre_cursor->loop_idx->st; /* assert, because we only prepare for 10 */ assert(tre_cursor->looping <= 10); for (index = 0; index < tre_cursor->looping; index++) { NITF_SNPRINTF(idx_str[index], TAG_BUF_LEN, "[%d]", stack[index]); } } /* check if it is an actual item now */ /* ASCII string */ if ((tre_cursor->desc_ptr->data_type == NITF_BCS_A) || /* ASCII number */ (tre_cursor->desc_ptr->data_type == NITF_BCS_N) || /* raw bytes */ (tre_cursor->desc_ptr->data_type == NITF_BINARY)) { NITF_SNPRINTF(tre_cursor->tag_str, TAG_BUF_LEN, "%s", tre_cursor->desc_ptr->tag); /* check if data is part of an array */ if (tre_cursor->looping) { stack = tre_cursor->loop_idx->st; for (index = 0; index < tre_cursor->looping; index++) { char entry[64]; NITF_SNPRINTF(entry, 64, "[%d]", stack[index]); strcat(tre_cursor->tag_str, entry); } } /* check to see if we don't know the length */ if (tre_cursor->desc_ptr->data_count == NITF_TRE_CONDITIONAL_LENGTH) { /* compute it from the function given */ if (tre_cursor->desc_ptr->special) { /* evaluate the special string as a postfix expression */ tre_cursor->length = nitf_TRECursor_evaluatePostfix( tre_cursor->tre, idx_str, tre_cursor->looping, tre_cursor->desc_ptr->special, error); if (tre_cursor->length < 0) { /* error! */ nitf_Error_print(error, stderr, "TRE expression error:"); return NITF_FAILURE; } } else { /* should we return failure here? */ /* for now, just set the length to 0, which forces an iteration... */ tre_cursor->length = 0; } if (tre_cursor->length == 0) { return nitf_TRECursor_iterate(tre_cursor, error); } } else { /* just set the length that was in the TREDescription */ tre_cursor->length = tre_cursor->desc_ptr->data_count; } } /* NITF_LOOP, NITF_IF, etc. */ else if ((tre_cursor->desc_ptr->data_type >= NITF_LOOP) && (tre_cursor->desc_ptr->data_type < NITF_END)) { done = 0; /* set the flag */ /* start of a loop */ if (tre_cursor->desc_ptr->data_type == NITF_LOOP) { loopCount = nitf_TRECursor_evalLoops(tre_cursor->tre, tre_cursor->desc_ptr, idx_str, tre_cursor->looping, error); if (loopCount > 0) { tre_cursor->looping++; /* record loopcount in @loop stack */ nitf_IntStack_push(tre_cursor->loop, loopCount, error); /* record i in @loop_rtn stack */ nitf_IntStack_push(tre_cursor->loop_rtn, tre_cursor->index, error); /* record a 0 in @loop_idx stack */ nitf_IntStack_push(tre_cursor->loop_idx, 0, error); } else { numLoops = 1; /* skip until we see the matching ENDLOOP */ while (numLoops && (++tre_cursor->index < tre_cursor->numItems)) { tre_cursor->desc_ptr = &dptr[tre_cursor->index]; if (tre_cursor->desc_ptr->data_type == NITF_LOOP) numLoops++; else if (tre_cursor->desc_ptr->data_type == NITF_ENDLOOP) numLoops--; } } } /* end of a loop */ else if (tre_cursor->desc_ptr->data_type == NITF_ENDLOOP) { /* retrieve loopcount from @loop stack */ loopCount = nitf_IntStack_pop(tre_cursor->loop, error); /* retrieve loop_rtn from @loop_rtn stack */ loop_rtni = nitf_IntStack_pop(tre_cursor->loop_rtn, error); /* retrieve loop_idx from @loop_idx stack */ loop_idxi = nitf_IntStack_pop(tre_cursor->loop_idx, error); if (--loopCount > 0) { /* record loopcount in @loop stack */ nitf_IntStack_push(tre_cursor->loop, loopCount, error); /* record i in @loop_rtn stack */ nitf_IntStack_push(tre_cursor->loop_rtn, loop_rtni, error); /* record idx in @loop_idx stack */ nitf_IntStack_push(tre_cursor->loop_idx, ++loop_idxi, error); /* jump to the start of the loop */ tre_cursor->index = loop_rtni; } else { --tre_cursor->looping; } } /* an if clause */ else if (tre_cursor->desc_ptr->data_type == NITF_IF) { if (!nitf_TRECursor_evalIf (tre_cursor->tre, tre_cursor->desc_ptr, idx_str, tre_cursor->looping, error)) { numIfs = 1; /* skip until we see the matching ENDIF */ while (numIfs && (++tre_cursor->index < tre_cursor->numItems)) { tre_cursor->desc_ptr = &dptr[tre_cursor->index]; if (tre_cursor->desc_ptr->data_type == NITF_IF) numIfs++; else if (tre_cursor->desc_ptr->data_type == NITF_ENDIF) numIfs--; } } } } else { nitf_Error_init(error, "Unhandled TRE Value data type", NITF_CTXT, NITF_ERR_INVALID_PARAMETER); return NITF_FAILURE; } } else { /* should return FALSE instead. signifies we are DONE iterating! */ return NITF_FAILURE; } } return NITF_SUCCESS; }