int HFAField::GetInstCount( GByte * pabyData, int nDataSize ) { if( chPointer == '\0' ) return nItemCount; else if( chItemType == 'b' ) { GInt32 nRows, nColumns; if( nDataSize < 20 ) return 0; memcpy( &nRows, pabyData+8, 4 ); HFAStandard( 4, &nRows ); memcpy( &nColumns, pabyData+12, 4 ); HFAStandard( 4, &nColumns ); return nRows * nColumns; } else { GInt32 nCount; if( nDataSize < 4 ) return 0; memcpy( &nCount, pabyData, 4 ); HFAStandard( 4, &nCount ); return nCount; } }
int HFAField::GetInstBytes( GByte *pabyData, int nDataSize ) { int nCount; int nInstBytes = 0; if( nBytes > -1 ) return nBytes; if( chPointer != '\0' ) { memcpy( &nCount, pabyData, 4 ); HFAStandard( 4, &nCount ); pabyData += 8; nInstBytes += 8; } else nCount = 1; if( chItemType == 'b' && nCount != 0 ) // BASEDATA { GInt32 nRows, nColumns; GInt16 nBaseItemType; memcpy( &nRows, pabyData, 4 ); HFAStandard( 4, &nRows ); memcpy( &nColumns, pabyData+4, 4 ); HFAStandard( 4, &nColumns ); memcpy( &nBaseItemType, pabyData+8, 2 ); HFAStandard( 2, &nBaseItemType ); nInstBytes += 12; nInstBytes += ((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows * nColumns; } else if( poItemObjectType == NULL ) { nInstBytes += nCount * HFADictionary::GetItemSize(chItemType); } else { int i; for( i = 0; i < nCount; i++ ) { int nThisBytes; nThisBytes = poItemObjectType->GetInstBytes( pabyData, nDataSize - nInstBytes ); nInstBytes += nThisBytes; pabyData += nThisBytes; } } return( nInstBytes ); }
CPLErr HFABand::GetPCT( int * pnColors, double **ppadfRed, double **ppadfGreen, double **ppadfBlue ) { *pnColors = 0; *ppadfRed = NULL; *ppadfGreen = NULL; *ppadfBlue = NULL; /* -------------------------------------------------------------------- */ /* If we haven't already tried to load the colors, do so now. */ /* -------------------------------------------------------------------- */ if( nPCTColors == -1 ) { HFAEntry *poColumnEntry; int i, iColumn; nPCTColors = 0; poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Red"); if( poColumnEntry == NULL ) return( CE_Failure ); nPCTColors = poColumnEntry->GetIntField( "numRows" ); for( iColumn = 0; iColumn < 3; iColumn++ ) { apadfPCT[iColumn] = (double *)CPLMalloc(sizeof(double)*nPCTColors); if( iColumn == 0 ) poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Red"); else if( iColumn == 1 ) poColumnEntry= poNode->GetNamedChild("Descriptor_Table.Green"); else if( iColumn == 2 ) poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Blue"); VSIFSeek( psInfo->fp, poColumnEntry->GetIntField("columnDataPtr"), SEEK_SET ); VSIFRead( apadfPCT[iColumn], sizeof(double), nPCTColors, psInfo->fp); for( i = 0; i < nPCTColors; i++ ) HFAStandard( 8, apadfPCT[iColumn] + i ); } } /* -------------------------------------------------------------------- */ /* Return the values. */ /* -------------------------------------------------------------------- */ if( nPCTColors == 0 ) return( CE_Failure ); *pnColors = nPCTColors; *ppadfRed = apadfPCT[0]; *ppadfGreen = apadfPCT[1]; *ppadfBlue = apadfPCT[2]; return( CE_None ); }
HFAEntry::HFAEntry( HFAInfo_t * psHFAIn, GUInt32 nPos, HFAEntry * poParentIn, HFAEntry * poPrevIn ) { psHFA = psHFAIn; nFilePos = nPos; poParent = poParentIn; poPrev = poPrevIn; /* -------------------------------------------------------------------- */ /* Initialize fields to null values in case there is a read */ /* error, so the entry will be in a harmless state. */ /* -------------------------------------------------------------------- */ poNext = poChild = NULL; nDataPos = nDataSize = 0; nNextPos = nChildPos = 0; szName[0] = szType[0] = '\0'; pabyData = NULL; poType = NULL; /* -------------------------------------------------------------------- */ /* Read the entry information from the file. */ /* -------------------------------------------------------------------- */ GInt32 anEntryNums[6]; int i; if( VSIFSeek( psHFA->fp, nFilePos, SEEK_SET ) == -1 || VSIFRead( anEntryNums, sizeof(GInt32), 6, psHFA->fp ) < 1 ) { CPLError( CE_Failure, CPLE_FileIO, "VSIFRead() failed in HFAEntry()." ); return; } for( i = 0; i < 6; i++ ) HFAStandard( 4, anEntryNums + i ); nNextPos = anEntryNums[0]; nChildPos = anEntryNums[3]; nDataPos = anEntryNums[4]; nDataSize = anEntryNums[5]; /* -------------------------------------------------------------------- */ /* Read the name, and type. */ /* -------------------------------------------------------------------- */ if( VSIFRead( szName, 1, 64, psHFA->fp ) < 1 || VSIFRead( szType, 1, 32, psHFA->fp ) < 1 ) { CPLError( CE_Failure, CPLE_FileIO, "VSIFRead() failed in HFAEntry()." ); return; } }
HFAEntry* HFAEntry::New( HFAInfo_t * psHFAIn, GUInt32 nPos, HFAEntry * poParentIn, HFAEntry * poPrevIn ) { HFAEntry* poEntry = new HFAEntry; poEntry->psHFA = psHFAIn; poEntry->nFilePos = nPos; poEntry->poParent = poParentIn; poEntry->poPrev = poPrevIn; /* -------------------------------------------------------------------- */ /* Read the entry information from the file. */ /* -------------------------------------------------------------------- */ GInt32 anEntryNums[6] = {}; if( VSIFSeekL( poEntry->psHFA->fp, poEntry->nFilePos, SEEK_SET ) == -1 || VSIFReadL( anEntryNums, sizeof(GInt32), 6, poEntry->psHFA->fp ) < 1 ) { CPLError( CE_Failure, CPLE_FileIO, "VSIFReadL(%p,6*4) @ %d failed in HFAEntry().\n%s", poEntry->psHFA->fp, poEntry->nFilePos, VSIStrerror( errno ) ); delete poEntry; return NULL; } for( int i = 0; i < 6; i++ ) HFAStandard( 4, anEntryNums + i ); poEntry->nNextPos = anEntryNums[0]; poEntry->nChildPos = anEntryNums[3]; poEntry->nDataPos = anEntryNums[4]; poEntry->nDataSize = anEntryNums[5]; /* -------------------------------------------------------------------- */ /* Read the name, and type. */ /* -------------------------------------------------------------------- */ if( VSIFReadL( poEntry->szName, 1, 64, poEntry->psHFA->fp ) < 1 || VSIFReadL( poEntry->szType, 1, 32, poEntry->psHFA->fp ) < 1 ) { poEntry->szName[sizeof(poEntry->szName)-1] = '\0'; poEntry->szType[sizeof(poEntry->szType)-1] = '\0'; CPLError( CE_Failure, CPLE_FileIO, "VSIFReadL() failed in HFAEntry()." ); delete poEntry; return NULL; } poEntry->szName[sizeof(poEntry->szName)-1] = '\0'; poEntry->szType[sizeof(poEntry->szType)-1] = '\0'; return poEntry; }
int HFAField::GetInstCount( GByte * pabyData ) { if( chPointer == '\0' ) return nItemCount; else { GInt32 nCount; memcpy( &nCount, pabyData, 4 ); HFAStandard( 4, &nCount ); return nCount; } }
int HFAField::GetInstBytes( GByte * pabyData ) { int nCount; int nInstBytes = 0; if( nBytes > -1 ) return nBytes; if( chPointer != '\0' ) { memcpy( &nCount, pabyData, 4 ); HFAStandard( 4, &nCount ); pabyData += 8; nInstBytes += 8; } else nCount = 1; if( poItemObjectType == NULL ) { nInstBytes += nCount * HFADictionary::GetItemSize(chItemType); } else { int i; for( i = 0; i < nCount; i++ ) { int nThisBytes; nThisBytes = poItemObjectType->GetInstBytes( pabyData ); nInstBytes += nThisBytes; pabyData += nThisBytes; } } return( nInstBytes ); }
int HFAField::ExtractInstValue( const char * pszField, int nIndexValue, GByte *pabyData, GUInt32 nDataOffset, int nDataSize, char chReqType, void *pReqReturn, int *pnRemainingDataSize ) { char *pszStringRet = NULL; int nIntRet = 0; double dfDoubleRet = 0.0; int nInstItemCount = GetInstCount( pabyData, nDataSize ); GByte *pabyRawData = NULL; if (pnRemainingDataSize) *pnRemainingDataSize = -1; /* -------------------------------------------------------------------- */ /* Check the index value is valid. */ /* */ /* Eventually this will have to account for variable fields. */ /* -------------------------------------------------------------------- */ if( nIndexValue < 0 || nIndexValue >= nInstItemCount ) { if( chItemType == 'b' && nIndexValue >= -3 && nIndexValue < 0 ) /* ok - special index values */; else return FALSE; } /* -------------------------------------------------------------------- */ /* If this field contains a pointer, then we will adjust the */ /* data offset relative to it. */ /* -------------------------------------------------------------------- */ if( chPointer != '\0' ) { GUInt32 nOffset; if (nDataSize < 8) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &nOffset, pabyData+4, 4 ); HFAStandard( 4, &nOffset ); if( nOffset != (GUInt32) (nDataOffset + 8) ) { #ifdef notdef CPLError( CE_Warning, CPLE_AppDefined, "%s.%s points at %d, not %d as expected\n", pszFieldName, pszField ? pszField : "", nOffset, nDataOffset+8 ); #endif } pabyData += 8; nDataOffset += 8; nDataSize -= 8; } /* -------------------------------------------------------------------- */ /* pointers to char or uchar arrays requested as strings are */ /* handled as a special case. */ /* -------------------------------------------------------------------- */ if( (chItemType == 'c' || chItemType == 'C') && chReqType == 's' ) { *((GByte **)pReqReturn) = pabyData; if (pnRemainingDataSize) *pnRemainingDataSize = nDataSize; return( pabyData != NULL ); } /* -------------------------------------------------------------------- */ /* Handle by type. */ /* -------------------------------------------------------------------- */ switch( chItemType ) { case 'c': case 'C': if (nIndexValue >= nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } nIntRet = pabyData[nIndexValue]; dfDoubleRet = nIntRet; break; case 'e': case 's': { unsigned short nNumber; if (nIndexValue*2 + 2 > nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &nNumber, pabyData + nIndexValue*2, 2 ); HFAStandard( 2, &nNumber ); nIntRet = nNumber; dfDoubleRet = nIntRet; if( chItemType == 'e' && nIntRet >= 0 && nIntRet < CSLCount(papszEnumNames) ) { pszStringRet = papszEnumNames[nIntRet]; } } break; case 'S': { short nNumber; if (nIndexValue*2 + 2 > nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &nNumber, pabyData + nIndexValue*2, 2 ); HFAStandard( 2, &nNumber ); nIntRet = nNumber; dfDoubleRet = nIntRet; } break; case 't': case 'l': { GUInt32 nNumber; if (nIndexValue*4 + 4 > nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &nNumber, pabyData + nIndexValue*4, 4 ); HFAStandard( 4, &nNumber ); nIntRet = nNumber; dfDoubleRet = nIntRet; } break; case 'L': { GInt32 nNumber; if (nIndexValue*4 + 4 > nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &nNumber, pabyData + nIndexValue*4, 4 ); HFAStandard( 4, &nNumber ); nIntRet = nNumber; dfDoubleRet = nIntRet; } break; case 'f': { float fNumber; if (nIndexValue*4 + 4 > nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &fNumber, pabyData + nIndexValue*4, 4 ); HFAStandard( 4, &fNumber ); dfDoubleRet = fNumber; nIntRet = (int) fNumber; } break; case 'd': { double dfNumber; if (nIndexValue*8 + 8 > nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &dfNumber, pabyData + nIndexValue*8, 8 ); HFAStandard( 8, &dfNumber ); dfDoubleRet = dfNumber; nIntRet = (int) dfNumber; } break; case 'b': { GInt32 nRows, nColumns; GInt16 nBaseItemType; if( nDataSize < 12 ) return FALSE; memcpy( &nRows, pabyData, 4 ); HFAStandard( 4, &nRows ); memcpy( &nColumns, pabyData+4, 4 ); HFAStandard( 4, &nColumns ); memcpy( &nBaseItemType, pabyData+8, 2 ); HFAStandard( 2, &nBaseItemType ); // We ignore the 2 byte objecttype value. if( nIndexValue < -3 || nIndexValue >= nRows * nColumns ) return FALSE; pabyData += 12; nDataSize -= 12; if( nIndexValue == -3 ) { dfDoubleRet = nIntRet = nBaseItemType; } else if( nIndexValue == -2 ) { dfDoubleRet = nIntRet = nColumns; } else if( nIndexValue == -1 ) { dfDoubleRet = nIntRet = nRows; } else if( nBaseItemType == EPT_u8 ) { if (nIndexValue >= nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } dfDoubleRet = pabyData[nIndexValue]; nIntRet = pabyData[nIndexValue]; } else if( nBaseItemType == EPT_s8 ) { if (nIndexValue >= nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } dfDoubleRet = ((signed char *)pabyData)[nIndexValue]; nIntRet = ((signed char *)pabyData)[nIndexValue]; } else if( nBaseItemType == EPT_s16 ) { GInt16 nValue; if (nIndexValue*2 + 2 > nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &nValue, pabyData + 2*nIndexValue, 2 ); HFAStandard( 2, &nValue ); dfDoubleRet = nValue; nIntRet = nValue; } else if( nBaseItemType == EPT_u16 ) { GUInt16 nValue; if (nIndexValue*2 + 2 > nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &nValue, pabyData + 2*nIndexValue, 2 ); HFAStandard( 2, &nValue ); dfDoubleRet = nValue; nIntRet = nValue; } else if( nBaseItemType == EPT_s32 ) { GInt32 nValue; if (nIndexValue*4 + 4 > nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &nValue, pabyData + 4*nIndexValue, 4 ); HFAStandard( 4, &nValue ); dfDoubleRet = nValue; nIntRet = nValue; } else if( nBaseItemType == EPT_u32 ) { GUInt32 nValue; if (nIndexValue*4 + 4 > nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &nValue, pabyData + 4*nIndexValue, 4 ); HFAStandard( 4, &nValue ); dfDoubleRet = nValue; nIntRet = nValue; } else if( nBaseItemType == EPT_f32 ) { float fValue; if (nIndexValue*4 + 4 > nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &fValue, pabyData + 4*nIndexValue, 4 ); HFAStandard( 4, &fValue ); dfDoubleRet = fValue; nIntRet = (int) fValue; } else if( nBaseItemType == EPT_f64 ) { double dfValue; if (nIndexValue*8 + 8 > nDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return FALSE; } memcpy( &dfValue, pabyData+8*nIndexValue, 8 ); HFAStandard( 8, &dfValue ); dfDoubleRet = dfValue; nIntRet = (int) dfValue; } else { CPLError(CE_Failure, CPLE_AppDefined, "Unknown base item type : %d", nBaseItemType); return FALSE; } } break; case 'o': if( poItemObjectType != NULL ) { int nExtraOffset = 0; int iIndexCounter; if( poItemObjectType->nBytes > 0 ) { if (nIndexValue != 0 && poItemObjectType->nBytes > INT_MAX / nIndexValue) return CE_Failure; nExtraOffset = poItemObjectType->nBytes * nIndexValue; } else { for( iIndexCounter = 0; iIndexCounter < nIndexValue && nExtraOffset < nDataSize; iIndexCounter++ ) { int nInc = poItemObjectType->GetInstBytes(pabyData + nExtraOffset, nDataSize - nExtraOffset); if (nInc < 0 || nExtraOffset > INT_MAX - nInc) { CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value"); return CE_Failure; } nExtraOffset += nInc; } } if (nExtraOffset >= nDataSize) return CE_Failure; pabyRawData = pabyData + nExtraOffset; if( pszField != NULL && strlen(pszField) > 0 ) { return( poItemObjectType-> ExtractInstValue( pszField, pabyRawData, nDataOffset + nExtraOffset, nDataSize - nExtraOffset, chReqType, pReqReturn, pnRemainingDataSize ) ); } } break; default: return FALSE; break; } /* -------------------------------------------------------------------- */ /* Return the appropriate representation. */ /* -------------------------------------------------------------------- */ if( chReqType == 's' ) { if( pszStringRet == NULL ) { /* HFAEntry:: BuildEntryFromMIFObject() expects to have always */ /* 8 bytes before the data. In normal situations, it should */ /* not go here, but that can happen if the file is corrupted */ /* so reserve the first 8 bytes before the string to contain null bytes */ memset(szNumberString, 0, 8); sprintf( szNumberString + 8, "%.14g", dfDoubleRet ); pszStringRet = szNumberString + 8; } *((char **) pReqReturn) = pszStringRet; return( TRUE ); } else if( chReqType == 'd' ) { *((double *)pReqReturn) = dfDoubleRet; return( TRUE ); } else if( chReqType == 'i' ) { *((int *) pReqReturn) = nIntRet; return( TRUE ); } else if( chReqType == 'p' ) { *((GByte **) pReqReturn) = pabyRawData; return( TRUE ); } else { CPLAssert( FALSE ); return FALSE; } }
CPLErr HFAField::SetInstValue( const char * pszField, int nIndexValue, GByte *pabyData, GUInt32 nDataOffset, int nDataSize, char chReqType, void *pValue ) { /* -------------------------------------------------------------------- */ /* If this field contains a pointer, then we will adjust the */ /* data offset relative to it. */ /* -------------------------------------------------------------------- */ if( chPointer != '\0' ) { GUInt32 nCount; GUInt32 nOffset; /* set the count for fixed sized arrays */ if( nBytes > -1 ) nCount = nItemCount; // The count returned for BASEDATA's are the contents, // but here we really want to mark it as one BASEDATA instance // (see #2144) if( chItemType == 'b' ) nCount = 1; /* Set the size from string length */ else if( chReqType == 's' && (chItemType == 'c' || chItemType == 'C')) { if( pValue == NULL ) nCount = 0; else nCount = strlen((char *) pValue) + 1; } /* set size based on index ... assumes in-order setting of array */ else nCount = nIndexValue+1; if( (int) nCount + 8 > nDataSize ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to extend field %s in node past end of data,\n" "not currently supported.", pszField ); return CE_Failure; } // we will update the object count iff we are writing beyond the end memcpy( &nOffset, pabyData, 4 ); HFAStandard( 4, &nOffset ); if( nOffset < nCount ) { nOffset = nCount; HFAStandard( 4, &nOffset ); memcpy( pabyData, &nOffset, 4 ); } if( pValue == NULL ) nOffset = 0; else nOffset = nDataOffset + 8; HFAStandard( 4, &nOffset ); memcpy( pabyData+4, &nOffset, 4 ); pabyData += 8; nDataOffset += 8; nDataSize -= 8; } /* -------------------------------------------------------------------- */ /* pointers to char or uchar arrays requested as strings are */ /* handled as a special case. */ /* -------------------------------------------------------------------- */ if( (chItemType == 'c' || chItemType == 'C') && chReqType == 's' ) { int nBytesToCopy; if( nBytes == -1 ) { if( pValue == NULL ) nBytesToCopy = 0; else nBytesToCopy = strlen((char *) pValue) + 1; } else nBytesToCopy = nBytes; if( nBytesToCopy > nDataSize ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to extend field %s in node past end of data,\n" "not currently supported.", pszField ); return CE_Failure; } memset( pabyData, 0, nBytesToCopy ); if( pValue != NULL ) strncpy( (char *) pabyData, (char *) pValue, nBytesToCopy ); return CE_None; } /* -------------------------------------------------------------------- */ /* Translate the passed type into different representations. */ /* -------------------------------------------------------------------- */ int nIntValue; double dfDoubleValue; if( chReqType == 's' ) { nIntValue = atoi((char *) pValue); dfDoubleValue = atof((char *) pValue); } else if( chReqType == 'd' ) { dfDoubleValue = *((double *) pValue); nIntValue = (int) dfDoubleValue; } else if( chReqType == 'i' ) { dfDoubleValue = *((int *) pValue); nIntValue = *((int *) pValue); } else if( chReqType == 'p' ) { CPLError( CE_Failure, CPLE_NotSupported, "HFAField::SetInstValue() not supported yet for pointer values." ); return CE_Failure; } else { CPLAssert( FALSE ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Handle by type. */ /* -------------------------------------------------------------------- */ switch( chItemType ) { case 'c': case 'C': if( nIndexValue + 1 > nDataSize ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to extend field %s in node past end of data,\n" "not currently supported.", pszField ); return CE_Failure; } if( chReqType == 's' ) pabyData[nIndexValue] = ((char *) pValue)[0]; else pabyData[nIndexValue] = (char) nIntValue; break; case 'e': case 's': { if( chItemType == 'e' && chReqType == 's' ) { nIntValue = CSLFindString( papszEnumNames, (char *) pValue ); if( nIntValue == -1 ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to set enumerated field with unknown" " value `%s'.", (char *) pValue ); return CE_Failure; } } unsigned short nNumber = (unsigned short) nIntValue; if( nIndexValue*2 + 2 > nDataSize ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to extend field %s in node past end of data,\n" "not currently supported.", pszField ); return CE_Failure; } HFAStandard( 2, &nNumber ); memcpy( pabyData + nIndexValue*2, &nNumber, 2 ); } break; case 'S': { short nNumber; if( nIndexValue*2 + 2 > nDataSize ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to extend field %s in node past end of data,\n" "not currently supported.", pszField ); return CE_Failure; } nNumber = (short) nIntValue; HFAStandard( 2, &nNumber ); memcpy( pabyData + nIndexValue*2, &nNumber, 2 ); } break; case 't': case 'l': { GUInt32 nNumber = nIntValue; if( nIndexValue*4 + 4 > nDataSize ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to extend field %s in node past end of data,\n" "not currently supported.", pszField ); return CE_Failure; } HFAStandard( 4, &nNumber ); memcpy( pabyData + nIndexValue*4, &nNumber, 4 ); } break; case 'L': { GInt32 nNumber = nIntValue; if( nIndexValue*4 + 4 > nDataSize ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to extend field %s in node past end of data,\n" "not currently supported.", pszField ); return CE_Failure; } HFAStandard( 4, &nNumber ); memcpy( pabyData + nIndexValue*4, &nNumber, 4 ); } break; case 'f': { float fNumber = (float) dfDoubleValue; if( nIndexValue*4 + 4 > nDataSize ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to extend field %s in node past end of data,\n" "not currently supported.", pszField ); return CE_Failure; } HFAStandard( 4, &fNumber ); memcpy( pabyData + nIndexValue*4, &fNumber, 4 ); } break; case 'd': { double dfNumber = dfDoubleValue; if( nIndexValue*8 + 8 > nDataSize ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to extend field %s in node past end of data,\n" "not currently supported.", pszField ); return CE_Failure; } HFAStandard( 8, &dfNumber ); memcpy( pabyData + nIndexValue*8, &dfNumber, 8 ); } break; case 'b': { GInt32 nRows = 1; GInt32 nColumns = 1; GInt16 nBaseItemType; // Extract existing rows, columns, and datatype. memcpy( &nRows, pabyData, 4 ); HFAStandard( 4, &nRows ); memcpy( &nColumns, pabyData+4, 4 ); HFAStandard( 4, &nColumns ); memcpy( &nBaseItemType, pabyData+8, 2 ); HFAStandard( 2, &nBaseItemType ); // Are we using special index values to update the rows, columnrs // or type? if( nIndexValue == -3 ) nBaseItemType = nIntValue; else if( nIndexValue == -2 ) nColumns = nIntValue; else if( nIndexValue == -1 ) nRows = nIntValue; if( nIndexValue < -3 || nIndexValue >= nRows * nColumns ) return CE_Failure; // Write back the rows, columns and basedatatype. HFAStandard( 4, &nRows ); memcpy( pabyData, &nRows, 4 ); HFAStandard( 4, &nColumns ); memcpy( pabyData+4, &nColumns, 4 ); HFAStandard( 2, &nBaseItemType ); memcpy ( pabyData + 8, &nBaseItemType, 2 ); HFAStandard( 2, &nBaseItemType ); // swap back for our use. // We ignore the 2 byte objecttype value. nDataSize -= 12; if( nIndexValue >= 0 ) { if( (nIndexValue+1) * (HFAGetDataTypeBits(nBaseItemType)/8) > nDataSize ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to extend field %s in node past end of data,\n" "not currently supported.", pszField ); return CE_Failure; } if( nBaseItemType == EPT_f64 ) { double dfNumber = dfDoubleValue; HFAStandard( 8, &dfNumber ); memcpy( pabyData + 12 + nIndexValue * 8, &dfNumber, 8 ); } else { CPLError( CE_Failure, CPLE_AppDefined, "Setting basedata field %s with type %s not currently supported.", pszField, HFAGetDataTypeName( nBaseItemType ) ); return CE_Failure; } } } break; case 'o': if( poItemObjectType != NULL ) { int nExtraOffset = 0; int iIndexCounter; if( poItemObjectType->nBytes > 0 ) { if (nIndexValue != 0 && poItemObjectType->nBytes > INT_MAX / nIndexValue) return CE_Failure; nExtraOffset = poItemObjectType->nBytes * nIndexValue; } else { for( iIndexCounter = 0; iIndexCounter < nIndexValue && nExtraOffset < nDataSize; iIndexCounter++ ) { int nInc = poItemObjectType->GetInstBytes(pabyData + nExtraOffset, nDataSize - nExtraOffset); if (nInc < 0 || nExtraOffset > INT_MAX - nInc) { CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value"); return CE_Failure; } nExtraOffset += nInc; } } if (nExtraOffset >= nDataSize) return CE_Failure; if( pszField != NULL && strlen(pszField) > 0 ) { return( poItemObjectType-> SetInstValue( pszField, pabyData + nExtraOffset, nDataOffset + nExtraOffset, nDataSize - nExtraOffset, chReqType, pValue ) ); } else { CPLAssert( FALSE ); return CE_Failure; } } break; default: CPLAssert( FALSE ); return CE_Failure; break; } return CE_None; }
int HFAField::GetInstBytes( GByte *pabyData, int nDataSize ) { int nCount; int nInstBytes = 0; if( nBytes > -1 ) return nBytes; if( chPointer != '\0' ) { if (nDataSize < 4) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return -1; } memcpy( &nCount, pabyData, 4 ); HFAStandard( 4, &nCount ); pabyData += 8; nInstBytes += 8; } else nCount = 1; if( chItemType == 'b' && nCount != 0 ) // BASEDATA { if (nDataSize - nInstBytes < 4+4+2) { CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small"); return -1; } GInt32 nRows, nColumns; GInt16 nBaseItemType; memcpy( &nRows, pabyData, 4 ); HFAStandard( 4, &nRows ); memcpy( &nColumns, pabyData+4, 4 ); HFAStandard( 4, &nColumns ); memcpy( &nBaseItemType, pabyData+8, 2 ); HFAStandard( 2, &nBaseItemType ); nInstBytes += 12; if (nRows < 0 || nColumns < 0) return -1; if (nColumns != 0 && nRows > INT_MAX / nColumns) return -1; if (nColumns != 0 && ((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows > INT_MAX / nColumns) return -1; if (((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows * nColumns > INT_MAX - nInstBytes) return -1; nInstBytes += ((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows * nColumns; } else if( poItemObjectType == NULL ) { if (nCount != 0 && HFADictionary::GetItemSize(chItemType) > INT_MAX / nCount) return -1; nInstBytes += nCount * HFADictionary::GetItemSize(chItemType); } else { int i; for( i = 0; i < nCount && nInstBytes < nDataSize && nInstBytes >= 0; i++ ) { int nThisBytes; nThisBytes = poItemObjectType->GetInstBytes( pabyData, nDataSize - nInstBytes ); if (nThisBytes < 0 || nInstBytes > INT_MAX - nThisBytes) { CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value"); return -1; } nInstBytes += nThisBytes; pabyData += nThisBytes; } } return( nInstBytes ); }
HFAHandle HFAOpen( const char * pszFilename, const char * pszAccess ) { FILE *fp; char szHeader[16]; HFAInfo_t *psInfo; GUInt32 nHeaderPos; HFAEntry *poNode; /* -------------------------------------------------------------------- */ /* Open the file. */ /* -------------------------------------------------------------------- */ if( EQUAL(pszAccess,"r") || EQUAL(pszAccess,"rb" ) ) fp = VSIFOpen( pszFilename, "rb" ); else fp = VSIFOpen( pszFilename, "r+b" ); /* should this be changed to use some sort of CPLFOpen() which will set the error? */ if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "File open of %s failed.", pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Read and verify the header. */ /* -------------------------------------------------------------------- */ if( VSIFRead( szHeader, 16, 1, fp ) < 1 ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to read 16 byte header failed for\n%s.", pszFilename ); return NULL; } if( !EQUALN(szHeader,"EHFA_HEADER_TAG",15) ) { CPLError( CE_Failure, CPLE_AppDefined, "File %s is not an Imagine HFA file ... header wrong.", pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Create the HFAInfo_t */ /* -------------------------------------------------------------------- */ psInfo = (HFAInfo_t *) CPLCalloc(sizeof(HFAInfo_t),1); psInfo->fp = fp; /* -------------------------------------------------------------------- */ /* Where is the header? */ /* -------------------------------------------------------------------- */ VSIFRead( &nHeaderPos, sizeof(GInt32), 1, fp ); HFAStandard( 4, &nHeaderPos ); /* -------------------------------------------------------------------- */ /* Read the header. */ /* -------------------------------------------------------------------- */ VSIFSeek( fp, nHeaderPos, SEEK_SET ); VSIFRead( &(psInfo->nVersion), sizeof(GInt32), 1, fp ); HFAStandard( 4, &(psInfo->nVersion) ); VSIFRead( szHeader, 4, 1, fp ); /* skip freeList */ VSIFRead( &(psInfo->nRootPos), sizeof(GInt32), 1, fp ); HFAStandard( 4, &(psInfo->nRootPos) ); VSIFRead( &(psInfo->nEntryHeaderLength), sizeof(GInt16), 1, fp ); HFAStandard( 2, &(psInfo->nEntryHeaderLength) ); VSIFRead( &(psInfo->nDictionaryPos), sizeof(GInt32), 1, fp ); HFAStandard( 4, &(psInfo->nDictionaryPos) ); /* -------------------------------------------------------------------- */ /* Instantiate the root entry. */ /* -------------------------------------------------------------------- */ psInfo->poRoot = new HFAEntry( psInfo, psInfo->nRootPos, NULL, NULL ); /* -------------------------------------------------------------------- */ /* Read the dictionary */ /* -------------------------------------------------------------------- */ psInfo->pszDictionary = HFAGetDictionary( psInfo ); psInfo->poDictionary = new HFADictionary( psInfo->pszDictionary ); /* -------------------------------------------------------------------- */ /* Find the first band node. */ /* -------------------------------------------------------------------- */ psInfo->nBands = 0; poNode = psInfo->poRoot->GetChild(); while( poNode != NULL ) { if( EQUAL(poNode->GetType(),"Eimg_Layer") ) { if( psInfo->nBands == 0 ) { psInfo->nXSize = poNode->GetIntField("width"); psInfo->nYSize = poNode->GetIntField("height"); } else if( poNode->GetIntField("width") != psInfo->nXSize || poNode->GetIntField("height") != psInfo->nYSize ) { CPLAssert( FALSE ); continue; } psInfo->papoBand = (HFABand **) CPLRealloc(psInfo->papoBand, sizeof(HFABand *) * (psInfo->nBands+1)); psInfo->papoBand[psInfo->nBands] = new HFABand( psInfo, poNode ); psInfo->nBands++; } poNode = poNode->GetNext(); } return psInfo; }
void *HFAField::ExtractInstValue( const char * pszField, int nIndexValue, GByte *pabyData, int nDataOffset, int nDataSize, char chReqType ) { char *pszStringRet = NULL; static int nIntRet = 0; static double dfDoubleRet = 0.0; int nInstItemCount = GetInstCount( pabyData ); GByte *pabyRawData = NULL; /* -------------------------------------------------------------------- */ /* Check the index value is valid. */ /* */ /* Eventually this will have to account for variable fields. */ /* -------------------------------------------------------------------- */ if( nIndexValue < 0 || nIndexValue >= nInstItemCount ) return NULL; /* -------------------------------------------------------------------- */ /* If this field contains a pointer, then we will adjust the */ /* data offset relative to it. */ /* -------------------------------------------------------------------- */ if( chPointer != '\0' ) { GUInt32 nOffset; memcpy( &nOffset, pabyData+4, 4 ); HFAStandard( 4, &nOffset ); if( nOffset != (GUInt32) (nDataOffset + 8) ) { #ifdef notdef CPLError( CE_Warning, CPLE_AppDefined, "%s.%s points at %d, not %d as expected\n", pszFieldName, pszField ? pszField : "", nOffset, nDataOffset+8 ); #endif } pabyData += 8; nDataOffset += 8; nDataSize -= 8; } /* -------------------------------------------------------------------- */ /* pointers to char or uchar arrays requested as strings are */ /* handled as a special case. */ /* -------------------------------------------------------------------- */ if( (chItemType == 'c' || chItemType == 'C') && chReqType == 's' ) return( pabyData ); /* -------------------------------------------------------------------- */ /* Handle by type. */ /* -------------------------------------------------------------------- */ switch( chItemType ) { case 'c': case 'C': nIntRet = pabyData[nIndexValue]; dfDoubleRet = nIntRet; break; case 'e': case 's': { unsigned short nNumber; memcpy( &nNumber, pabyData + nIndexValue*2, 2 ); HFAStandard( 2, &nNumber ); nIntRet = nNumber; dfDoubleRet = nIntRet; if( chItemType == 'e' && nIntRet >= 0 && nIntRet < CSLCount(papszEnumNames) ) { pszStringRet = papszEnumNames[nIntRet]; } } break; case 'S': { short nNumber; memcpy( &nNumber, pabyData + nIndexValue*2, 2 ); HFAStandard( 2, &nNumber ); nIntRet = nNumber; dfDoubleRet = nIntRet; } break; case 't': case 'l': { GUInt32 nNumber; memcpy( &nNumber, pabyData + nIndexValue*4, 4 ); HFAStandard( 4, &nNumber ); nIntRet = nNumber; dfDoubleRet = nIntRet; } break; case 'L': { GInt32 nNumber; memcpy( &nNumber, pabyData + nIndexValue*4, 4 ); HFAStandard( 4, &nNumber ); nIntRet = nNumber; dfDoubleRet = nIntRet; } break; case 'f': { float fNumber; memcpy( &fNumber, pabyData + nIndexValue*4, 4 ); HFAStandard( 4, &fNumber ); dfDoubleRet = fNumber; nIntRet = (int) fNumber; } break; case 'd': { double dfNumber; memcpy( &dfNumber, pabyData + nIndexValue*8, 8 ); HFAStandard( 8, &dfNumber ); dfDoubleRet = dfNumber; nIntRet = (int) dfNumber; } break; case 'o': if( poItemObjectType != NULL ) { int nExtraOffset = 0; int iIndexCounter; if( poItemObjectType->nBytes > 0 ) { nExtraOffset = poItemObjectType->nBytes * nIndexValue; } else { for( iIndexCounter = 0; iIndexCounter < nIndexValue; iIndexCounter++ ) { nExtraOffset += poItemObjectType->GetInstBytes(pabyData+nExtraOffset); } } pabyRawData = pabyData + nExtraOffset; if( pszField != NULL && strlen(pszField) > 0 ) { return( poItemObjectType-> ExtractInstValue( pszField, pabyRawData, nDataOffset + nExtraOffset, nDataSize - nExtraOffset, chReqType ) ); } } break; default: return NULL; break; } /* -------------------------------------------------------------------- */ /* Return the appropriate representation. */ /* -------------------------------------------------------------------- */ if( chReqType == 's' ) { if( pszStringRet == NULL ) { static char szNumber[28]; sprintf( szNumber, "%d", nIntRet ); pszStringRet = szNumber; } return( pszStringRet ); } else if( chReqType == 'd' ) return( &dfDoubleRet ); else if( chReqType == 'i' ) return( &nIntRet ); else if( chReqType == 'p' ) return( pabyRawData ); else { CPLAssert( FALSE ); return NULL; } }
CPLErr HFAEntry::FlushToDisk() { CPLErr eErr = CE_None; /* -------------------------------------------------------------------- */ /* If we are the root node, call SetPosition() on the whole */ /* tree to ensure that all entries have an allocated position. */ /* -------------------------------------------------------------------- */ if( poParent == NULL ) SetPosition(); /* ==================================================================== */ /* Only write this node out if it is dirty. */ /* ==================================================================== */ if( bDirty ) { /* -------------------------------------------------------------------- */ /* Ensure we know where the relative entries are located. */ /* -------------------------------------------------------------------- */ if( poNext != NULL ) nNextPos = poNext->nFilePos; if( poChild != NULL ) nChildPos = poChild->nFilePos; /* -------------------------------------------------------------------- */ /* Write the Ehfa_Entry fields. */ /* -------------------------------------------------------------------- */ GUInt32 nLong; //VSIFFlushL( psHFA->fp ); if( VSIFSeekL( psHFA->fp, nFilePos, SEEK_SET ) != 0 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to seek to %d for writing, out of disk space?", nFilePos ); return CE_Failure; } nLong = nNextPos; HFAStandard( 4, &nLong ); VSIFWriteL( &nLong, 4, 1, psHFA->fp ); if( poPrev != NULL ) nLong = poPrev->nFilePos; else nLong = 0; HFAStandard( 4, &nLong ); VSIFWriteL( &nLong, 4, 1, psHFA->fp ); if( poParent != NULL ) nLong = poParent->nFilePos; else nLong = 0; HFAStandard( 4, &nLong ); VSIFWriteL( &nLong, 4, 1, psHFA->fp ); nLong = nChildPos; HFAStandard( 4, &nLong ); VSIFWriteL( &nLong, 4, 1, psHFA->fp ); nLong = nDataPos; HFAStandard( 4, &nLong ); VSIFWriteL( &nLong, 4, 1, psHFA->fp ); nLong = nDataSize; HFAStandard( 4, &nLong ); VSIFWriteL( &nLong, 4, 1, psHFA->fp ); VSIFWriteL( szName, 1, 64, psHFA->fp ); VSIFWriteL( szType, 1, 32, psHFA->fp ); nLong = 0; /* Should we keep the time, or set it more reasonably? */ if( VSIFWriteL( &nLong, 4, 1, psHFA->fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to write HFAEntry %s(%s), out of disk space?", szName, szType ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Write out the data. */ /* -------------------------------------------------------------------- */ //VSIFFlushL( psHFA->fp ); if( nDataSize > 0 && pabyData != NULL ) { if( VSIFSeekL( psHFA->fp, nDataPos, SEEK_SET ) != 0 || VSIFWriteL( pabyData, nDataSize, 1, psHFA->fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to write %d bytes HFAEntry %s(%s) data,\n" "out of disk space?", nDataSize, szName, szType ); return CE_Failure; } } //VSIFFlushL( psHFA->fp ); } /* -------------------------------------------------------------------- */ /* Process all the children of this node */ /* -------------------------------------------------------------------- */ for( HFAEntry *poThisChild = poChild; poThisChild != NULL; poThisChild = poThisChild->poNext ) { eErr = poThisChild->FlushToDisk(); if( eErr != CE_None ) return eErr; } bDirty = FALSE; return CE_None; }
HFAEntry* HFAEntry::BuildEntryFromMIFObject( HFAEntry *poContainer, const char *pszMIFObjectPath ) { const char* pszField; CPLString osFieldName; osFieldName.Printf("%s.%s", pszMIFObjectPath, "MIFDictionary" ); pszField = poContainer->GetStringField( osFieldName.c_str() ); if (pszField == NULL) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s entry", osFieldName.c_str()); return NULL; } CPLString osDictionnary = pszField; osFieldName.Printf("%s.%s", pszMIFObjectPath, "type.string" ); pszField = poContainer->GetStringField( osFieldName.c_str() ); if (pszField == NULL) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s entry", osFieldName.c_str()); return NULL; } CPLString osType = pszField; osFieldName.Printf("%s.%s", pszMIFObjectPath, "MIFObject" ); int nRemainingDataSize = 0; pszField = poContainer->GetStringField( osFieldName.c_str(), NULL, &nRemainingDataSize ); if (pszField == NULL) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s entry", osFieldName.c_str()); return NULL; } GInt32 nMIFObjectSize; // we rudely look before the field data to get at the pointer/size info memcpy( &nMIFObjectSize, pszField-8, 4 ); HFAStandard( 4, &nMIFObjectSize ); if (nMIFObjectSize <= 0) { CPLError(CE_Failure, CPLE_AppDefined, "Invalid MIF object size (%d)", nMIFObjectSize); return NULL; } // check that we won't copy more bytes than available in the buffer if (nMIFObjectSize > nRemainingDataSize) { CPLError(CE_Failure, CPLE_AppDefined, "Invalid MIF object size (%d > %d)", nMIFObjectSize, nRemainingDataSize); return NULL; } GByte* pabyData = (GByte *) VSIMalloc(nMIFObjectSize); if (pabyData == NULL) return NULL; memcpy( pabyData, pszField, nMIFObjectSize ); return new HFAEntry(poContainer, pszMIFObjectPath, osDictionnary, osType, nMIFObjectSize, pabyData); }
HFAEntry::HFAEntry( HFAEntry * poContainer, const char *pszMIFObjectPath ) { /* -------------------------------------------------------------------- */ /* Initialize Entry */ /* -------------------------------------------------------------------- */ nFilePos = 0; poParent = poPrev = poNext = poChild = NULL; bIsMIFObject = TRUE; nDataPos = nDataSize = 0; nNextPos = nChildPos = 0; memset( szName, 0, 64 ); pabyData = NULL; poType = NULL; /* -------------------------------------------------------------------- */ /* Create a dummy HFAInfo_t. */ /* -------------------------------------------------------------------- */ psHFA = (HFAInfo_t *) CPLCalloc(sizeof(HFAInfo_t),1); psHFA->eAccess = HFA_ReadOnly; psHFA->bTreeDirty = FALSE; psHFA->poRoot = this; psHFA->poDictionary = new HFADictionary( poContainer->GetStringField( CPLString().Printf("%s.%s", pszMIFObjectPath, "MIFDictionary" ) ) ); /* -------------------------------------------------------------------- */ /* Work out the type for this MIFObject. */ /* -------------------------------------------------------------------- */ memset( szType, 0, 32 ); strncpy( szType, poContainer->GetStringField( CPLString().Printf("%s.%s", pszMIFObjectPath, "type.string") ), 32 ); poType = psHFA->poDictionary->FindType( szType ); /* -------------------------------------------------------------------- */ /* Find the desired field. */ /* -------------------------------------------------------------------- */ GInt32 nMIFObjectSize; const GByte *pabyRawData = (const GByte *) poContainer->GetStringField( CPLString().Printf("%s.%s", pszMIFObjectPath, "MIFObject" ) ); // we rudely look before the field data to get at the pointer/size info memcpy( &nMIFObjectSize, pabyRawData-8, 4 ); HFAStandard( 4, &nMIFObjectSize ); nDataSize = nMIFObjectSize; pabyData = (GByte *) VSIMalloc(nDataSize); memcpy( pabyData, pabyRawData, nDataSize ); }
int HFAField::ExtractInstValue( const char * pszField, int nIndexValue, GByte *pabyData, GUInt32 nDataOffset, int nDataSize, char chReqType, void *pReqReturn ) { char *pszStringRet = NULL; int nIntRet = 0; double dfDoubleRet = 0.0; int nInstItemCount = GetInstCount( pabyData, nDataSize ); GByte *pabyRawData = NULL; /* -------------------------------------------------------------------- */ /* Check the index value is valid. */ /* */ /* Eventually this will have to account for variable fields. */ /* -------------------------------------------------------------------- */ if( nIndexValue < 0 || nIndexValue >= nInstItemCount ) { if( chItemType == 'b' && nIndexValue >= -3 && nIndexValue < 0 ) /* ok - special index values */; else return FALSE; } /* -------------------------------------------------------------------- */ /* If this field contains a pointer, then we will adjust the */ /* data offset relative to it. */ /* -------------------------------------------------------------------- */ if( chPointer != '\0' ) { GUInt32 nOffset; memcpy( &nOffset, pabyData+4, 4 ); HFAStandard( 4, &nOffset ); if( nOffset != (GUInt32) (nDataOffset + 8) ) { #ifdef notdef CPLError( CE_Warning, CPLE_AppDefined, "%s.%s points at %d, not %d as expected\n", pszFieldName, pszField ? pszField : "", nOffset, nDataOffset+8 ); #endif } pabyData += 8; nDataOffset += 8; nDataSize -= 8; } /* -------------------------------------------------------------------- */ /* pointers to char or uchar arrays requested as strings are */ /* handled as a special case. */ /* -------------------------------------------------------------------- */ if( (chItemType == 'c' || chItemType == 'C') && chReqType == 's' ) { *((GByte **)pReqReturn) = pabyData; return( pabyData != NULL ); } /* -------------------------------------------------------------------- */ /* Handle by type. */ /* -------------------------------------------------------------------- */ switch( chItemType ) { case 'c': case 'C': nIntRet = pabyData[nIndexValue]; dfDoubleRet = nIntRet; break; case 'e': case 's': { unsigned short nNumber; memcpy( &nNumber, pabyData + nIndexValue*2, 2 ); HFAStandard( 2, &nNumber ); nIntRet = nNumber; dfDoubleRet = nIntRet; if( chItemType == 'e' && nIntRet >= 0 && nIntRet < CSLCount(papszEnumNames) ) { pszStringRet = papszEnumNames[nIntRet]; } } break; case 'S': { short nNumber; memcpy( &nNumber, pabyData + nIndexValue*2, 2 ); HFAStandard( 2, &nNumber ); nIntRet = nNumber; dfDoubleRet = nIntRet; } break; case 't': case 'l': { GUInt32 nNumber; memcpy( &nNumber, pabyData + nIndexValue*4, 4 ); HFAStandard( 4, &nNumber ); nIntRet = nNumber; dfDoubleRet = nIntRet; } break; case 'L': { GInt32 nNumber; memcpy( &nNumber, pabyData + nIndexValue*4, 4 ); HFAStandard( 4, &nNumber ); nIntRet = nNumber; dfDoubleRet = nIntRet; } break; case 'f': { float fNumber; memcpy( &fNumber, pabyData + nIndexValue*4, 4 ); HFAStandard( 4, &fNumber ); dfDoubleRet = fNumber; nIntRet = (int) fNumber; } break; case 'd': { double dfNumber; memcpy( &dfNumber, pabyData + nIndexValue*8, 8 ); HFAStandard( 8, &dfNumber ); dfDoubleRet = dfNumber; nIntRet = (int) dfNumber; } break; case 'b': { GInt32 nRows, nColumns; GInt16 nBaseItemType; if( nDataSize < 12 ) return FALSE; memcpy( &nRows, pabyData, 4 ); HFAStandard( 4, &nRows ); memcpy( &nColumns, pabyData+4, 4 ); HFAStandard( 4, &nColumns ); memcpy( &nBaseItemType, pabyData+8, 2 ); HFAStandard( 2, &nBaseItemType ); // We ignore the 2 byte objecttype value. if( nIndexValue < -3 || nIndexValue >= nRows * nColumns ) return FALSE; pabyData += 12; if( nIndexValue == -3 ) { dfDoubleRet = nIntRet = nBaseItemType; } else if( nIndexValue == -2 ) { dfDoubleRet = nIntRet = nColumns; } else if( nIndexValue == -1 ) { dfDoubleRet = nIntRet = nRows; } else if( nBaseItemType == EPT_u8 ) { dfDoubleRet = pabyData[nIndexValue]; nIntRet = pabyData[nIndexValue]; } else if( nBaseItemType == EPT_s16 ) { GInt16 nValue; memcpy( &nValue, pabyData + 2*nIndexValue, 2 ); HFAStandard( 2, &nValue ); dfDoubleRet = nValue; nIntRet = nValue; } else if( nBaseItemType == EPT_u16 ) { GUInt16 nValue; memcpy( &nValue, pabyData + 2*nIndexValue, 2 ); HFAStandard( 2, &nValue ); dfDoubleRet = nValue; nIntRet = nValue; } else if( nBaseItemType == EPT_s32 ) { GInt32 nValue; memcpy( &nValue, pabyData + 4*nIndexValue, 4 ); HFAStandard( 4, &nValue ); dfDoubleRet = nValue; nIntRet = nValue; } else if( nBaseItemType == EPT_u32 ) { GUInt32 nValue; memcpy( &nValue, pabyData + 4*nIndexValue, 4 ); HFAStandard( 4, &nValue ); dfDoubleRet = nValue; nIntRet = nValue; } else if( nBaseItemType == EPT_f32 ) { float fValue; memcpy( &fValue, pabyData + 4*nIndexValue, 4 ); HFAStandard( 4, &fValue ); dfDoubleRet = fValue; nIntRet = (int) fValue; } else if( nBaseItemType == EPT_f64 ) { double dfValue; memcpy( &dfValue, pabyData+8*nIndexValue, 8 ); HFAStandard( 8, &dfValue ); dfDoubleRet = dfValue; nIntRet = (int) dfValue; } else { CPLAssert( FALSE ); return FALSE; } } break; case 'o': if( poItemObjectType != NULL ) { int nExtraOffset = 0; int iIndexCounter; if( poItemObjectType->nBytes > 0 ) { nExtraOffset = poItemObjectType->nBytes * nIndexValue; } else { for( iIndexCounter = 0; iIndexCounter < nIndexValue; iIndexCounter++ ) { nExtraOffset += poItemObjectType->GetInstBytes(pabyData + nExtraOffset, nDataSize - nExtraOffset); } } pabyRawData = pabyData + nExtraOffset; if( pszField != NULL && strlen(pszField) > 0 ) { return( poItemObjectType-> ExtractInstValue( pszField, pabyRawData, nDataOffset + nExtraOffset, nDataSize - nExtraOffset, chReqType, pReqReturn ) ); } } break; default: return FALSE; break; } /* -------------------------------------------------------------------- */ /* Return the appropriate representation. */ /* -------------------------------------------------------------------- */ if( chReqType == 's' ) { if( pszStringRet == NULL ) { sprintf( szNumberString, "%.14g", dfDoubleRet ); pszStringRet = szNumberString; } *((char **) pReqReturn) = pszStringRet; return( TRUE ); } else if( chReqType == 'd' ) { *((double *)pReqReturn) = dfDoubleRet; return( TRUE ); } else if( chReqType == 'i' ) { *((int *) pReqReturn) = nIntRet; return( TRUE ); } else if( chReqType == 'p' ) { *((GByte **) pReqReturn) = pabyRawData; return( TRUE ); } else { CPLAssert( FALSE ); return FALSE; } }