Пример #1
0
        /// <summary>
        /// Scans through the array and estimates the byte size of the field in this case.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="dataOffset">The data offset.</param>
        /// <returns>The byte size of the field.</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);
        }
Пример #2
0
        /// <summary>
        /// Gets the count for a particular instance of a field. This will normally be
        /// the built in value, but for variable fields, this is extracted from the
        /// data itself.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="dataOffset">The data offset.</param>
        /// <returns>The count for a particular instance of a field.</returns>
        public int GetInstCount(byte[] data, long dataOffset)
        {
            if (Pointer == '\0')
            {
                return(ItemCount);
            }

            if (ItemType == 'b')
            {
                int numRows    = Hfa.ReadInt32(data, dataOffset + 8);
                int numColumns = Hfa.ReadInt32(data, dataOffset + 12);
                return(numRows * numColumns);
            }

            return(Hfa.ReadInt32(data, dataOffset));
        }
Пример #3
0
        /// <summary>
        /// Extracts the value.
        /// </summary>
        /// <param name="pszField">The psz field.</param>
        /// <param name="nIndexValue">The index value.</param>
        /// <param name="data">The data.</param>
        /// <param name="dataOffset">The offset to start from.</param>
        /// <param name="nDataSize">The data size.</param>
        /// <param name="reqType">The req type.</param>
        /// <param name="pReqReturn">The req return.</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>True, if the value could be extracted.</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:
                    float 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);
            }
        }
Пример #4
0
        /// <summary>
        /// Dumps the fields value.
        /// </summary>
        /// <param name="fpOut">The output stream.</param>
        /// <param name="data">The data.</param>
        /// <param name="dataOffset">The offset to start from.</param>
        /// <param name="dataSize">The data size.</param>
        /// <param name="prefix">The 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(MaxEntryReport, 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 > MaxEntryReport)
            {
                sw.Write(prefix + " ... remaining instances omitted ...\n");
            }

            if (nEntries == 0)
            {
                sw.Write(prefix + FieldName + " = (no values)\n");
            }
        }