/// <summary> /// Gets the bitcount of a single member of the specified data type. /// </summary> /// <param name="dataType">The data type to get the byte count of</param> /// <returns>An integer that represents the bit count of the specified type</returns> public static int GetBitCount(this HfaEPT dataType) { switch (dataType) { case HfaEPT.U1: return 1; case HfaEPT.U2: return 2; case HfaEPT.U4: return 4; case HfaEPT.U8: case HfaEPT.S8: return 8; case HfaEPT.U16: case HfaEPT.S16: return 16; case HfaEPT.U32: case HfaEPT.S32: case HfaEPT.Single: return 32; case HfaEPT.Double: case HfaEPT.Char64: return 64; case HfaEPT.Char128: return 128; } return 0; }
/// <summary> /// Scans through the array and estimates the byte size of the field in this case. /// </summary> /// <param name="data"></param> /// <param name="dataOffset"></param> /// <returns></returns> public int GetInstBytes(byte[] data, long dataOffset) { int nCount; int nInstBytes = 0; long offset = dataOffset; // Hard sized fields just return their constant size if (NumBytes > -1) { return(NumBytes); } // Pointers have a 4 byte integer count and a 4 byte uint offset if (_pointer != '\0') { nCount = Hfa.ReadInt32(data, offset); offset += 8; nInstBytes += 8; } else { // Anything other than a pointer only can have one item. nCount = 1; } if (_itemType == 'b' && nCount != 0) { // BASEDATA int nRows = Hfa.ReadInt32(data, offset); offset += 4; int nColumns = Hfa.ReadInt32(data, offset); offset += 4; HfaEPT baseItemType = (HfaEPT)Hfa.ReadInt16(data, offset); nInstBytes += 12; nInstBytes += ((baseItemType.GetBitCount() + 7) / 8) * nRows * nColumns; } else if (_itemObjectType == null) { nInstBytes += nCount * HfaDictionary.GetItemSize(_itemType); } else { for (int i = 0; i < nCount; i++) { nInstBytes += _itemObjectType.GetInstBytes(data, offset + nInstBytes); } } return(nInstBytes); }
/// <summary> /// Gets the bitcount of a single member of the specified data type. /// </summary> /// <param name="dataType">The data type to get the byte count of</param> /// <returns>An integer that represents the bit count of the specified type</returns> public static int GetBitCount(this HfaEPT dataType) { switch (dataType) { case HfaEPT.U1: return(1); case HfaEPT.U2: return(2); case HfaEPT.U4: return(4); case HfaEPT.U8: case HfaEPT.S8: return(8); case HfaEPT.U16: case HfaEPT.S16: return(16); case HfaEPT.U32: case HfaEPT.S32: case HfaEPT.Single: return(32); case HfaEPT.Double: case HfaEPT.Char64: return(64); case HfaEPT.Char128: return(128); } return(0); }
/// <summary> /// /// </summary> /// <param name="pszField"></param> /// <param name="nIndexValue"></param> /// <param name="data"></param> /// <param name="dataOffset"></param> /// <param name="nDataSize"></param> /// <param name="reqType"></param> /// <param name="pReqReturn"></param> /// <param name="extraOffset">This is used in the case of 'object' pointers where the indexed object is further in the data block.</param> /// <returns></returns> /// <exception cref="HfaInvalidCountException">Occurs if the count is less than zero for the header of a block of base data</exception> public bool ExtractInstValue(string pszField, int nIndexValue, byte[] data, long dataOffset, int nDataSize, char reqType, out object pReqReturn, out int extraOffset) { extraOffset = 0; pReqReturn = null; string returnString = null; int nIntRet = 0; double dfDoubleRet = 0.0; // it doesn't appear like remove this line will have side effects. //int size = GetInstBytes(data, dataOffset); int nInstItemCount = GetInstCount(data, dataOffset); byte[] rawData = null; long offset = dataOffset; // Check the index value is valid. Eventually this will have to account for variable fields. if (nIndexValue < 0 || nIndexValue >= nInstItemCount) { return(false); } // if this field contains a pointer then we will adjust the data offset relative to it. if (_pointer != '\0') { long nOffset = Hfa.ReadUInt32(data, dataOffset + 4); if (nOffset != (uint)(dataOffset + 8)) { // It seems there was originally an exception that would have gone here. // Original exception would have been pszFieldname.pszField points at nOffset, not nDataOffset +8 as expected. } offset += 8; dataOffset += 8; nDataSize -= 8; } // pointers to chara or uchar arrays are read as strings and then handled as a special case. if ((_itemType == 'c' || _itemType == 'C') && reqType == 's') { // Ok, nasty, the original code simply "pointed" to the byte data at this point and cast the pointer. // We probably need to cycle through until we reach the null character. List <char> chars = new List <char>(); while ((char)data[offset] != '\0') { chars.Add((char)data[offset]); offset++; dataOffset++; } pReqReturn = new String(chars.ToArray()); } switch (_itemType) { case 'c': case 'C': nIntRet = data[dataOffset + nIndexValue]; dfDoubleRet = nIntRet; break; case 'e': case 's': { int nNumber = Hfa.ReadUInt16(data, dataOffset + nIndexValue * 2); nIntRet = nNumber; dfDoubleRet = nIntRet; if (_itemType == 'e' && nIntRet >= 0 && nIntRet < _enumNames.Count()) { returnString = _enumNames[nIntRet]; } } break; case 'S': { short nNumber = Hfa.ReadInt16(data, dataOffset + nIndexValue * 2); nIntRet = nNumber; dfDoubleRet = nNumber; } break; case 't': case 'l': { long nNumber = Hfa.ReadUInt32(data, dataOffset + nIndexValue * 2); nIntRet = (int)nNumber; dfDoubleRet = nNumber; } break; case 'L': { int nNumber = Hfa.ReadInt32(data, dataOffset + nIndexValue * 2); nIntRet = nNumber; dfDoubleRet = nNumber; } break; case 'f': { float fNumber = Hfa.ReadSingle(data, dataOffset + nIndexValue * 4); dfDoubleRet = fNumber; nIntRet = Convert.ToInt32(fNumber); } break; case 'd': { dfDoubleRet = Hfa.ReadDouble(data, dataOffset + nInstItemCount * 8); nIntRet = Convert.ToInt32(dfDoubleRet); } break; case 'b': // BASE DATA { int nRows = Hfa.ReadInt32(data, dataOffset); int nColumns = Hfa.ReadInt32(data, dataOffset + 4); if (nIndexValue < 0 || nIndexValue >= nRows * nColumns) { return(false); } HfaEPT type = (HfaEPT)Hfa.ReadUInt16(data, dataOffset + 8); // Ignore the 2 byte objecttype value dataOffset += 12; if (nRows < 0 || nColumns < 0) { throw new HfaInvalidCountException(nRows, nColumns); } switch (type) { case HfaEPT.U8: dfDoubleRet = data[dataOffset + nIndexValue]; nIntRet = data[offset + nIndexValue]; break; case HfaEPT.S16: short tShort = Hfa.ReadInt16(data, dataOffset + nIndexValue * 2); dfDoubleRet = tShort; nIntRet = tShort; break; case HfaEPT.U16: int tUShort = Hfa.ReadUInt16(data, dataOffset + nIndexValue * 2); dfDoubleRet = tUShort; nIntRet = tUShort; break; case HfaEPT.Single: Single tSingle = Hfa.ReadSingle(data, dataOffset + nIndexValue * 4); dfDoubleRet = tSingle; nIntRet = Convert.ToInt32(tSingle); break; case HfaEPT.Double: dfDoubleRet = Hfa.ReadDouble(data, dataOffset + nIndexValue * 8); nIntRet = Convert.ToInt32(dfDoubleRet); break; default: pReqReturn = null; return(false); } } break; case 'o': if (_itemObjectType != null) { if (_itemObjectType.NumBytes > 0) { extraOffset = _itemObjectType.NumBytes * nIndexValue; } else { for (int iIndexCounter = 0; iIndexCounter < nIndexValue; iIndexCounter++) { extraOffset += _itemObjectType.GetInstBytes(data, dataOffset + extraOffset); } } int len = _itemObjectType.GetInstBytes(data, dataOffset + extraOffset); rawData = new byte[len]; Array.Copy(data, dataOffset + extraOffset, rawData, 0, len); if (!string.IsNullOrEmpty(pszField)) { return (_itemObjectType.ExtractInstValue(pszField, rawData, 0, rawData.Length, reqType, out pReqReturn)); } } break; default: return(false); } // Handle appropriate representations switch (reqType) { case 's': { if (returnString == null) { returnString = nIntRet.ToString(); } pReqReturn = returnString; return(true); } case 'd': pReqReturn = dfDoubleRet; return(true); case 'i': pReqReturn = nIntRet; return(true); case 'p': pReqReturn = rawData; return(true); default: return(false); } }
/// <summary> /// /// </summary> /// <param name="fpOut"></param> /// <param name="data"></param> /// <param name="dataOffset"></param> /// <param name="dataSize"></param> /// <param name="prefix"></param> public void DumpInstValue(Stream fpOut, byte[] data, long dataOffset, int dataSize, string prefix) { StreamWriter sw = new StreamWriter(fpOut); int extraOffset; int nEntries = GetInstCount(data, dataOffset); // Special case for arrays of characters or uchars which are printed as a string if ((_itemType == 'c' || _itemType == 'C') && nEntries > 0) { object value; if (ExtractInstValue(null, 0, data, dataOffset, dataSize, 's', out value, out extraOffset)) { sw.WriteLine(prefix + _fieldName + " = '" + (string)value + "'"); } else { sw.WriteLine(prefix + _fieldName + " = (access failed)"); } } for (int iEntry = 0; iEntry < Math.Min(MAX_ENTRY_REPORT, nEntries); iEntry++) { sw.Write(prefix + _fieldName); if (nEntries > 1) { sw.Write("[" + iEntry + "]"); } sw.Write(" = "); object value; switch (_itemType) { case 'f': case 'd': if (ExtractInstValue(null, iEntry, data, dataOffset, dataSize, 'd', out value, out extraOffset)) { sw.Write(value + "\n"); } else { sw.Write("(access failed)\n"); } break; case 'b': int nRows = Hfa.ReadInt32(data, dataOffset + 8); int nColumns = Hfa.ReadInt32(data, dataOffset + 12); HfaEPT type = Hfa.ReadType(data, dataOffset + 16); sw.Write(nRows + "x" + nColumns + " basedata of type " + type); break; case 'e': if (ExtractInstValue(null, iEntry, data, dataOffset, dataSize, 's', out value, out extraOffset)) { sw.Write((string)value); } else { sw.Write("(accessfailed)"); } break; case 'o': if (!ExtractInstValue(null, iEntry, data, dataOffset, dataSize, 'p', out value, out extraOffset)) { sw.WriteLine("(access failed)"); } else { // the pointer logic here is death! Originally the pointer address was used // nByteOffset = ((GByte*) val) - pabyData; // This doesn't work in a safe context. sw.Write("\n"); string szLongFieldName = prefix; if (prefix.Length > 256) { szLongFieldName = prefix.Substring(0, 256); } _itemObjectType.DumpInstValue(fpOut, data, dataOffset + extraOffset, dataSize - extraOffset, szLongFieldName); } break; default: if (ExtractInstValue(null, iEntry, data, dataOffset, dataSize, 'i', out value, out extraOffset)) { sw.WriteLine(value); } else { sw.WriteLine("(access failed)\n"); } break; } } if (nEntries > MAX_ENTRY_REPORT) { sw.Write(prefix + " ... remaining instances omitted ...\n"); } if (nEntries == 0) { sw.Write(prefix + _fieldName + " = (no values)\n"); } }