Beispiel #1
0
/* pass in a negative number for bandNum if you don't want a band in the name */
char *makeBandName(const char *rootFile, const char* segment, int segmentNum, int bandNum)
{
    char *file = (char *) NITF_MALLOC(NITF_MAX_PATH);
    int pos;

    /* find end slash */
    for (pos = strlen(rootFile) - 1;
            pos && rootFile[pos] != '\\' && rootFile[pos] != '/'; pos--);

    if (bandNum >= 0)
        NITF_SNPRINTF(file, NITF_MAX_PATH,
                      "%s__%s_%d_band_%d", &rootFile[pos + 1],
                      segment, segmentNum, bandNum);
    else
        NITF_SNPRINTF(file, NITF_MAX_PATH, "%s__%s_%d", &rootFile[pos + 1],
                      segment, segmentNum);
    /* remove decimals */
    for (pos = strlen(file) - 1; pos; pos--)
    {
        if (file[pos] == '.')
        {
            file[pos] = '_';
        }
    }
    strcat(file, ".man");
    printf("File: %s\n", file);
    return file;
}
Beispiel #2
0
/* We may want to rethink this function a bit.
 * The NITF spec. has many fields with a BINARY_INTEGER type
 * This could mean that the field contains 3 8-bit binary integers
 * For that example, the length of the field is 3, which isn't an integer size
 * Thus, that wouldn't work here if we just assumed BINARY_INTEGER has ONE integer in the field
 */
NITFPRIV(NITF_BOOL) fromIntToString(nitf_Field * field, char *outValue,
                                    size_t length, nitf_Error * error)
{
    char buffer[256];
    size_t actualLength = 0;
    /*  These are all two-step processes 1) get native int 2) NITF_SNPRINTF */
    switch (field->length)
    {
        case 2:
        {
            nitf_Int16 int16;
            if (!toInt16(field, &int16, error))
                goto CATCH_ERROR;
            actualLength = NITF_SNPRINTF(buffer, 256, "%d", int16);
        }
        break;
        case 4:
        {
            nitf_Int32 int32;
            if (!toInt32(field, &int32, error))
                goto CATCH_ERROR;
            actualLength = NITF_SNPRINTF(buffer, 256, "%ld", (long) int32);
        }
        break;
        case 8:
        {
            nitf_Int64 int64;
            if (!toInt64(field, &int64, error))
                goto CATCH_ERROR;
            actualLength = NITF_SNPRINTF(buffer, 256, "%lld", int64);
        }
        break;
        default:
        {
            /* otherwise, it must not be an integer value */
            return fromStringToString(field, outValue, length, error);
        }
    }
    if (actualLength > length)
    {
        nitf_Error_initf(error, NITF_CTXT, NITF_ERR_INVALID_PARAMETER,
                         "Out value too small [%d] size required",
                         strlen(buffer));
        return NITF_FAILURE;
    }
    strcpy(outValue, buffer);
    return NITF_SUCCESS;

CATCH_ERROR:
    return NITF_FAILURE;
}
Beispiel #3
0
NITFPRIV(const char **) doInit(nitf_DLL * dll,
                               const char *prefix,
                               nitf_Error * error)
{
    NITF_PLUGIN_INIT_FUNCTION init;
    const char **ident;

    char name[NITF_MAX_PATH];
    memset(name, 0, NITF_MAX_PATH);
    NITF_SNPRINTF(name, NITF_MAX_PATH, "%s%s", prefix, NITF_PLUGIN_INIT_SUFFIX);
    init = (NITF_PLUGIN_INIT_FUNCTION) nitf_DLL_retrieve(dll, name, error);
    if (!init)
    {
        nitf_Error_print(error, stdout, "Invalid init hook in DSO");
        return NULL;
    }

    /*  Else, call it  */

    ident = (*init)(error);
    if (!ident)
    {
        nitf_Error_initf(error,
                         NITF_CTXT,
                         NITF_ERR_INVALID_OBJECT,
                         "The plugin [%s] is not retrievable", prefix);
        return NULL;
    }
    return ident;
}
Beispiel #4
0
NITFPRIV(NITF_BOOL) insertCreator(nitf_DLL* dso, 
                                  nitf_HashTable* hash,
                                  const char* ident,
                                  const char* suffix,
                                  nitf_Error* error)
{
    /*  We are trying to find tre_main  */
    NITF_DLL_FUNCTION_PTR dsoMain = NULL;

    /*  Get the name of the handler  */
    char name[NITF_MAX_PATH];
    char* p = NULL;

    if (!nitf_DLL_isValid(dso))
    {
        nitf_Error_initf(error,
                         NITF_CTXT,
                         NITF_ERR_INVALID_PARAMETER,
                         "DSO is not valid for [%s]",
                         ident);

    }

    memset(name, 0, NITF_MAX_PATH);
    NITF_SNPRINTF(name, NITF_MAX_PATH, "%s%s", ident, suffix);

    nitf_Utils_replace(name, ' ', '_');

    /*  No error has occurred (yet)  */
#if NITF_DEBUG_PLUGIN_REG
    printf("Loading function [%s] in dso at [%p]\n", name, dso);
#endif

    /*  Retrieve the main  */
    dsoMain = nitf_DLL_retrieve(dso, name, error);

    if (!dsoMain)
    {
        /*  If it didnt work, we are done  */
        return NITF_FAILURE;
    }

#if NITF_DEBUG_PLUGIN_REG
    if (nitf_HashTable_exists(hash, ident))
    {
        printf("Warning, overriding [%s] hook", ident);
        
    }
#endif
    
    return nitf_HashTable_insert(hash, ident, dsoMain, error);

}
Beispiel #5
0
NITFAPI(NITF_BOOL) nitf_Field_setInt64(nitf_Field * field,
                                       nitf_Int64 number,
                                       nitf_Error * error)
{
    char numberBuffer[20];      /* Holds converted number */
    nitf_Uint32 numberLen;      /* Length of converted number string */

    /*  Check the field type */

    if (field->type == NITF_BINARY)
    {
        nitf_Error_init(error, "Integer set for binary field ",
                        NITF_CTXT, NITF_ERR_INVALID_PARAMETER);
        return (NITF_FAILURE);
    }

    /*  Convert thte number to a string */

    NITF_SNPRINTF(numberBuffer, 20, "%lld", number);
    numberLen = strlen(numberBuffer);

    /* if it's resizable and a different length, we resize */
    if (field->resizable && numberLen != field->length)
    {
        if (!nitf_Field_resizeField(field, numberLen, error))
            return NITF_FAILURE;
    }

    if (numberLen > field->length)
    {
        nitf_Error_init(error, "Value for BCS_N field is too long",
                        NITF_CTXT, NITF_ERR_INVALID_PARAMETER);
        return (NITF_FAILURE);
    }

    /*  Transfer and pad result */

    if (field->type == NITF_BCS_N)
        copyAndFillZeros(field, numberBuffer, numberLen, error);
    else
        copyAndFillSpaces(field, numberBuffer, numberLen, error);

    return (NITF_SUCCESS);
}
Beispiel #6
0
NITFAPI(nitf_TRECursor) nitf_TRECursor_begin(nitf_TRE * tre)
{
    nitf_Error error;
    nitf_TRECursor tre_cursor;
    nitf_TREDescription *dptr;

    tre_cursor.loop = nitf_IntStack_construct(&error);
    tre_cursor.loop_idx = nitf_IntStack_construct(&error);
    tre_cursor.loop_rtn = nitf_IntStack_construct(&error);
    tre_cursor.numItems = 0;
    tre_cursor.index = 0;
    tre_cursor.looping = 0;
    /* init the pointers */
    tre_cursor.end_ptr = NULL;
    tre_cursor.prev_ptr = NULL;
    tre_cursor.desc_ptr = NULL;

    if (tre)
    {
        /* set the start index */
        tre_cursor.index = -1;
        /* count how many descriptions there are */
		dptr = ((nitf_TREPrivateData*)tre->priv)->description;

        while (dptr && (dptr->data_type != NITF_END))
        {
            tre_cursor.numItems++;
            dptr++;
        }
        tre_cursor.end_ptr = dptr;
        memset(tre_cursor.tag_str, 0, TAG_BUF_LEN);
		NITF_SNPRINTF(tre_cursor.tag_str, TAG_BUF_LEN, "%s",
		        ((nitf_TREPrivateData*)tre->priv)->description->tag);
        tre_cursor.tre = tre;
    }

    return tre_cursor;
}
Beispiel #7
0
/*
 *  Take a buffer of memory that we read out of a NITF segment
 *  and write it one of two-ways.
 *
 *  For non RGB 24-bit true-color data, write each band separately.
 *  This demonstrates the typical, non-accelerated, generic read.
 *
 *  For 24-bit true-color, if its band interleaved by pixel (mode 'P')
 *  demonstrate accelerated mode, and read without de-interleaving pixels,
 *  then write it to one big image as is.
 *
 */
void writeImage(nitf_ImageSegment * segment,
                char *imageName,
                nitf_ImageReader * deserializer,
                int imageNumber,
                nitf_Uint32 rowSkipFactor,
                nitf_Uint32 columnSkipFactor,
                NITF_BOOL optz,
                nitf_Error * error)
{

    nitf_Uint32 nBits, nBands, xBands, nRows, nColumns;
    size_t subimageSize;
    nitf_SubWindow *subimage;
    unsigned int i;
    int padded;
    nitf_Uint8 **buffer = NULL;
    nitf_Uint32 band;
    nitf_Uint32 *bandList = NULL;

    nitf_DownSampler *pixelSkip;

    /* TODO, replace these macros! */
    NITF_TRY_GET_UINT32(segment->subheader->numBitsPerPixel, &nBits,
                        error);
    NITF_TRY_GET_UINT32(segment->subheader->numImageBands, &nBands, error);
    NITF_TRY_GET_UINT32(segment->subheader->numMultispectralImageBands,
                        &xBands, error);
    nBands += xBands;
    NITF_TRY_GET_UINT32(segment->subheader->numRows, &nRows, error);
    NITF_TRY_GET_UINT32(segment->subheader->numCols, &nColumns, error);
    subimageSize = (nRows / rowSkipFactor) * (nColumns / columnSkipFactor)
                   * NITF_NBPP_TO_BYTES(nBits);

    printf("Image number: %d\n", imageNumber);
    printf("NBANDS -> %d\n"
           "XBANDS -> %d\n"
           "NROWS -> %d\n"
           "NCOLS -> %d\n"
           "PVTYPE -> %.*s\n"
           "NBPP -> %.*s\n"
           "ABPP -> %.*s\n"
           "PJUST -> %.*s\n"
           "IMODE -> %.*s\n"
           "NBPR -> %.*s\n"
           "NBPC -> %.*s\n"
           "NPPBH -> %.*s\n"
           "NPPBV -> %.*s\n"
           "IC -> %.*s\n"
           "COMRAT -> %.*s\n",
           nBands,
           xBands,
           nRows,
           nColumns,
           (int)segment->subheader->pixelValueType->length,
           segment->subheader->pixelValueType->raw,
           (int)segment->subheader->numBitsPerPixel->length,
           segment->subheader->numBitsPerPixel->raw,
           (int)segment->subheader->actualBitsPerPixel->length,
           segment->subheader->actualBitsPerPixel->raw,
           (int)segment->subheader->pixelJustification->length,
           segment->subheader->pixelJustification->raw,
           (int)segment->subheader->imageMode->length,
           segment->subheader->imageMode->raw,
           (int)segment->subheader->numBlocksPerRow->length,
           segment->subheader->numBlocksPerRow->raw,
           (int)segment->subheader->numBlocksPerCol->length,
           segment->subheader->numBlocksPerCol->raw,
           (int)segment->subheader->numPixelsPerHorizBlock->length,
           segment->subheader->numPixelsPerHorizBlock->raw,
           (int)segment->subheader->numPixelsPerVertBlock->length,
           segment->subheader->numPixelsPerVertBlock->raw,
           (int)segment->subheader->imageCompression->length,
           segment->subheader->imageCompression->raw,
           (int)segment->subheader->compressionRate->length,
           segment->subheader->compressionRate->raw);
    

    if (optz)
    {
	/*
         *  There is an accelerated mode for band-interleaved by pixel data.
         *  In that case, we assume that the user doesnt want the data
         *  de-interleaved into separate band buffers.  To make this work
         *  you have to tell us that you want only one band back,
         *  and you have to provide us a singular buffer that is the
         *  actual number of bands x the pixel size.  Then we will
         *  read the window and not de-interleave.
         *  To demonstrate, for RGB24 images, let's we write out the 1 band
	 *  - this will be MUCH faster
	 */
	if (nBands == 3
            && segment->subheader->imageMode->raw[0] == 'P'
            && strncmp("RGB", segment->subheader->imageRepresentation->raw, 3) == 0
            && NITF_NBPP_TO_BYTES(nBits) == 1
            && (strncmp("NC", segment->subheader->imageCompression->raw, 2)
                || strncmp("NM", segment->subheader->imageCompression->raw, 2)))
	{
            subimageSize *= nBands;
            nBands = 1;
            printf("Using accelerated 3-band RGB mode pix-interleaved image\n");
	}


	if (nBands == 2
            && segment->subheader->NITF_IMODE->raw[0] == 'P'
            && NITF_NBPP_TO_BYTES(nBits) == 4
            && segment->subheader->bandInfo[0]->NITF_ISUBCAT->raw[0] == 'I'
            && (strncmp("NC", segment->subheader->NITF_IC->raw, 2)
                || strncmp("NM", segment->subheader->NITF_IC->raw, 2)))
	{
            subimageSize *= nBands;
            nBands = 1;
            printf("Using accelerated 2-band IQ mode pix-interleaved image\n");
	}
    }
    subimage = nitf_SubWindow_construct(error);
    assert(subimage);

    /* 
     *  You need a buffer for each band (unless this is an 
     *  accelerated IQ complex or RGB read, in which case, you
     *  can set the number of bands to 1, and size your buffer
     *  accordingly to receive band-interleaved by pixel data)
     */
    buffer = (nitf_Uint8 **) NITF_MALLOC(nBands * sizeof(nitf_Uint8*));

    /* An iterator for bands */
    band = 0;

    /* 
     *  This tells us what order to give you bands in.  Normally
     *  you just want it in the order of the banding.  For example,
     *  in a non-accelerated band-interleaved by pixel cases, you might
     *  have a band of magnitude and a band of phase.  If you order the
     *  bandList backwards, the phase buffer comes first in the output
     */
    bandList = (nitf_Uint32 *) NITF_MALLOC(sizeof(nitf_Uint32 *) * nBands);

    /* This example reads all rows and cols starting at 0, 0 */
    subimage->startCol = 0;
    subimage->startRow = 0;

    /* Request rows is the full rows dividied by pixel skip (usually 1) */
    subimage->numRows = nRows / rowSkipFactor;

    /* Request columns is the full columns divided by pixel skip (usually 1) */
    subimage->numCols = nColumns / columnSkipFactor;

    /* Construct our pixel skip downsampler (does nothing if skips are 1) */
    pixelSkip = nitf_PixelSkip_construct(rowSkipFactor, 
                                         columnSkipFactor, 
                                         error);
    if (!pixelSkip)
    {
        nitf_Error_print(error, stderr, "Pixel Skip construction failed");
        goto CATCH_ERROR;
    }
    if (!nitf_SubWindow_setDownSampler(subimage, pixelSkip, error))
    {
        nitf_Error_print(error, stderr, "Set down sampler failed");
        goto CATCH_ERROR;
    }

    for (band = 0; band < nBands; band++)
        bandList[band] = band;
    subimage->bandList = bandList;
    subimage->numBands = nBands;

    assert(buffer);
    for (i = 0; i < nBands; i++)
    {
        buffer[i] = (nitf_Uint8 *) NITF_MALLOC(subimageSize);
        assert(buffer[i]);
    }
    if (!nitf_ImageReader_read
            (deserializer, subimage, buffer, &padded, error))
    {
        nitf_Error_print(error, stderr, "Read failed");
        goto CATCH_ERROR;
    }
    for (i = 0; i < nBands; i++)
    {

        nitf_IOHandle toFile;
        char file[NITF_MAX_PATH];
        int pos;

        /* find end slash */
        for (pos = strlen(imageName) - 1;
                pos && imageName[pos] != '\\' && imageName[pos] != '/';
                pos--);

        pos = pos == 0 ? pos : pos + 1;
        NITF_SNPRINTF(file, NITF_MAX_PATH,
                      "%s_%d__%d_%d_%d_band_%d", &imageName[pos],
                      imageNumber, nRows / rowSkipFactor,
                      nColumns / columnSkipFactor, nBits, i);
        /* remove decimals */
        for (pos = strlen(file) - 1; pos; pos--)
            if (file[pos] == '.')
                file[pos] = '_';
        strcat(file, ".out");
        printf("File: %s\n", file);
        toFile = nitf_IOHandle_create(file, NITF_ACCESS_WRITEONLY,
                                      NITF_CREATE, error);
        if (NITF_INVALID_HANDLE(toFile))
        {
            nitf_Error_print(error, stderr,
                             "IO handle creation failed for raw band");
            goto CATCH_ERROR;
        }
        if (!nitf_IOHandle_write(toFile,
                                 (const char *) buffer[i],
                                 subimageSize, error))
        {
            nitf_Error_print(error, stderr, 
                             "IO handle write failed for raw band");
            goto CATCH_ERROR;
        }
        nitf_IOHandle_close(toFile);
    }

    /* free buffers */
    for (i = 0; i < nBands; i++)
        NITF_FREE(buffer[i]);

    NITF_FREE(buffer);
    NITF_FREE(bandList);
    nitf_SubWindow_destruct(&subimage);
    nitf_DownSampler_destruct(&pixelSkip);

    return;

CATCH_ERROR:
    /* free buffers */
    for (i = 0; i < nBands; i++)
        NITF_FREE(buffer[i]);
    NITF_FREE(buffer);
    NITF_FREE(bandList);
    printf("ERROR processing\n");
}
Beispiel #8
0
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);
}
Beispiel #9
0
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;
}