Esempio n. 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);
        }
Esempio n. 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));
        }
Esempio n. 3
0
        /// <summary>
        /// Sets the value.
        /// </summary>
        /// <param name="sField">The field.</param>
        /// <param name="indexValue">The index value.</param>
        /// <param name="data">The data.</param>
        /// <param name="dataOffset">The data offset.</param>
        /// <param name="dataSize">The data size.</param>
        /// <param name="reqType">The req type.</param>
        /// <param name="value">The value.</param>
        /// <exception cref="HfaPointerInsertNotSupportedException">Attempting to insert a pointer is not supported.</exception>
        /// <exception cref="HfaEnumerationNotFoundException">Occurs if the specified value is not a valid member of the enumeration for this field.</exception>
        public void SetInstValue(string sField, int indexValue, byte[] data, long dataOffset, int dataSize, char reqType, object value)
        {
            // If this field contains a pointer, then we wil adjust the data offset relative to it.
            // This updates the offset info, but doesn't change the first four bytes.
            if (Pointer != '\0')
            {
                int nCount;
                if (NumBytes > -1)
                {
                    nCount = ItemCount;
                }
                else if (reqType == 's' && (ItemType == 'c' || ItemType == 'C'))
                {
                    // Either a string or a character array
                    nCount = 0;
                    IEnumerable <char> strVal = value as IEnumerable <char>;
                    if (strVal != null)
                    {
                        nCount = strVal.Count() + 1;
                    }
                }
                else
                {
                    nCount = indexValue + 1;
                }

                uint nOffset = (uint)nCount;
                Array.Copy(Hfa.LittleEndian(nOffset), 0, data, dataOffset + 4, 4);
                dataOffset += 8;
                dataSize   -= 8;
            }

            // Pointers to char or uchar arrays requested as strings are handled as a special case
            if ((ItemType == 'c' || ItemType == 'C') && reqType == 's')
            {
                int nBytesToCopy = NumBytes;
                var strVal       = (value as IEnumerable <char>)?.ToArray();
                if (strVal != null)
                {
                    nBytesToCopy = strVal.Length;
                }
                if (NumBytes == -1 && strVal != null)
                {
                    nBytesToCopy = strVal.Length;
                }

                // Force a blank erase to remove previous characters
                byte[] blank = new byte[nBytesToCopy];
                Array.Copy(blank, 0, data, dataOffset, nBytesToCopy);
                if (strVal != null)
                {
                    ASCIIEncoding ascii    = new ASCIIEncoding();
                    string        str      = new string(strVal);
                    byte[]        charData = ascii.GetBytes(str);
                    Array.Copy(charData, 0, data, dataOffset, charData.Length);
                }

                return;
            }

            // Translate the passed type into different representations
            int    nIntValue;
            double dfDoubleValue;

            if (reqType == 's')
            {
                nIntValue     = int.Parse((string)value);
                dfDoubleValue = double.Parse((string)value);
            }
            else if (reqType == 'd')
            {
                dfDoubleValue = (double)value;
                nIntValue     = Convert.ToInt32((double)value);
            }
            else if (reqType == 'i')
            {
                dfDoubleValue = Convert.ToDouble((int)value);
                nIntValue     = (int)value;
            }
            else if (reqType == 'p')
            {
                throw new HfaPointerInsertNotSupportedException();
            }
            else
            {
                return;
            }

            // Handle by type
            switch (ItemType)
            {
            case 'c':     // Char64
            case 'C':     // Char128
                if (reqType == 's')
                {
                    // handled earlier as special case,
                }
                else
                {
                    data[dataOffset + nIntValue] = (byte)nIntValue;
                }

                break;

            case 'e':     // enums are stored as ushort
            case 's':
                // little s  = ushort type
                if (ItemType == 'e' && reqType == 's')
                {
                    nIntValue = EnumNames.IndexOf((string)value);
                    if (nIntValue == -1)
                    {
                        throw new HfaEnumerationNotFoundException((string)value);
                    }
                }

                // Each enumeration is stored as a 2-bit unsigned short entry.
                ushort num = (ushort)nIntValue;
                Array.Copy(Hfa.LittleEndian(num), 0, data, dataOffset + (2 * indexValue), 2);
                break;

            case 'S':
                // signed short
                Array.Copy(Hfa.LittleEndian((short)nIntValue), 0, data, dataOffset + (indexValue * 2), 2);
                break;

            case 't':
            case 'l':
                Array.Copy(Hfa.LittleEndian((uint)nIntValue), 0, data, dataOffset + (indexValue * 4), 4);
                break;

            case 'L':
                // Int32
                Array.Copy(Hfa.LittleEndian(nIntValue), 0, data, dataOffset + (indexValue * 4), 4);
                break;

            case 'f':
                // Float (32 bit)
                float dfNumber = Convert.ToSingle(dfDoubleValue);
                Array.Copy(Hfa.LittleEndian(dfNumber), 0, data, dataOffset + (indexValue * 4), 4);
                break;

            case 'd':
                // Double (float 64)
                Array.Copy(Hfa.LittleEndian(dfDoubleValue), 0, data, dataOffset + (8 * indexValue), 8);
                break;

            case 'o':
                // object
                if (ItemObjectType == null)
                {
                    break;
                }

                int nExtraOffset = 0;

                if (ItemObjectType.NumBytes > 0)
                {
                    nExtraOffset = ItemObjectType.NumBytes * indexValue;
                }
                else
                {
                    for (int iIndexCounter = 0; iIndexCounter < indexValue; iIndexCounter++)
                    {
                        nExtraOffset += ItemObjectType.GetInstBytes(data, dataOffset + nExtraOffset);
                    }
                }

                if (!string.IsNullOrEmpty(sField))
                {
                    ItemObjectType.SetInstValue(sField, data, dataOffset + nExtraOffset, dataSize - nExtraOffset, reqType, value);
                }

                break;

            default: throw new ArgumentException();
            }
        }
Esempio n. 4
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);
            }
        }
Esempio n. 5
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");
            }
        }