CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData ) { int iBlock; if( LoadBlockInfo() != CE_None ) return CE_Failure; iBlock = nXBlock + nYBlock * nBlocksPerRow; /* -------------------------------------------------------------------- */ /* If the block isn't valid, or is compressed we just return */ /* all zeros, and an indication of failure. */ /* -------------------------------------------------------------------- */ if( !(panBlockFlag[iBlock] & (BFLG_VALID|BFLG_COMPRESSED)) ) { int nBytes; nBytes = HFAGetDataTypeBits(nDataType)*nBlockXSize*nBlockYSize/8; while( nBytes > 0 ) ((GByte *) pData)[--nBytes] = 0; return( CE_Failure ); } /* -------------------------------------------------------------------- */ /* Otherwise we really read the data. */ /* -------------------------------------------------------------------- */ if( VSIFSeek( psInfo->fp, panBlockStart[iBlock], SEEK_SET ) != 0 ) return CE_Failure; if( VSIFRead( pData, panBlockSize[iBlock], 1, psInfo->fp ) == 0 ) return CE_Failure; /* -------------------------------------------------------------------- */ /* Byte swap to local byte order if required. It appears that */ /* raster data is always stored in Intel byte order in Imagine */ /* files. */ /* -------------------------------------------------------------------- */ #ifdef CPL_MSB if( HFAGetDataTypeBits(nDataType) == 16 ) { int ii; for( ii = 0; ii < nBlockXSize*nBlockYSize; ii++ ) { unsigned char *pabyData = (unsigned char *) pData; int nTemp; nTemp = pabyData[ii*2]; pabyData[ii*2] = pabyData[ii*2+1]; pabyData[ii*2+1] = nTemp; } } #endif /* def CPL_MSB */ return( CE_None ); }
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 ); }
HFACompress::HFACompress( void *pData, GUInt32 nBlockSize, int nDataType ) { m_pData = pData; m_nDataType = nDataType; m_nDataTypeNumBits = HFAGetDataTypeBits( m_nDataType ); m_nBlockSize = nBlockSize; m_nBlockCount = (nBlockSize * 8) / m_nDataTypeNumBits; /* Allocate some memory for the count and values - probably too big */ /* About right for worst case scenario tho */ m_pCounts = (GByte*)VSIMalloc( m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32) ); m_nSizeCounts = 0; m_pValues = (GByte*)VSIMalloc( m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32) ); m_nSizeValues = 0; m_nMin = 0; m_nNumRuns = 0; m_nNumBits = 0; }
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 ); }