Ejemplo n.º 1
0
 /// <summary>
 /// Reads the value of the specified type from the buffer.
 /// </summary>
 /// <param name="value">The OUT variable to store the UINT value in.</param>
 /// <exception cref="System.ArgumentException"/>
 /// <exception cref="System.ArgumentNullException"/>
 /// <exception cref="System.ArgumentOutOfRangeException"/>
 public void Read(out uint value)
 {
     value    = BitConverter.ToUInt32(memory, iterator);
     iterator = (iterator + (int)BufferTypeSize.Int32 + fastAlign) & fastAlignNot;
 }
Ejemplo n.º 2
0
        public virtual ResStringPool ReadResStringPool(ResStringPool_header header)
        {
            var pool = new ResStringPool
            {
                Header     = header,
                StringData = new List <string>(),
                StyleData  = new List <List <ResStringPool_span> >()
            };

            // Offsets of the string data, relative to header.StringStart
            var stringIndices = new List <uint>();

            for (int i = 0; i < header.StringCount; i++)
            {
                stringIndices.Add(ReadUInt32());
            }

            // Offset of the style data, relative to header.StylesStart
            var styleIndices = new List <uint>();

            for (int i = 0; i < header.StyleCount; i++)
            {
                styleIndices.Add(ReadUInt32());
            }

            // Keep track of how many bytes are left, to prevent us
            // from reading invalid data.
            long bytesLeft = header.Header.Size;

            bytesLeft -= header.Header.HeaderSize;
            bytesLeft -= 4 * header.StringCount;
            bytesLeft -= 4 * header.StyleCount;

            // Fetch the block which contains the string. If a styles section is
            // present, the strings block ends there; otherwise, it runs to the end
            // of this entry.
            uint stringsEnd = header.StyleCount > 0 ? header.StylesStart : header.Header.Size;

            byte[] rawStringData = ReadBytes((int)stringsEnd - (int)header.StringStart);

            bytesLeft -= rawStringData.Length;

            bool isUtf8 = (header.Flags & StringPoolFlags.UTF8_FLAG) == StringPoolFlags.UTF8_FLAG;

            foreach (uint startingIndex in stringIndices)
            {
                // The starting index specifies where the string starts.
                // We can now read the string in either UTF8 or UTF16 format.
                uint pos = startingIndex;
                if (isUtf8)
                {
                    uint   charLen = Helper.DecodeLengthUtf8(rawStringData, ref pos);
                    uint   byteLen = Helper.DecodeLengthUtf8(rawStringData, ref pos);
                    string item    = Encoding.UTF8.GetString(rawStringData, (int)pos, (int)byteLen);
                    if (item.Length != charLen)
                    {
#if !CORECLR
                        Debug.WriteLine("Warning: UTF-8 string length ({0}) not matching specified length ({1}).",
                                        item.Length, charLen);
#endif
                    }
                    pool.StringData.Add(item);
                }
                else
                {
                    uint   charLen = Helper.DecodeLengthUtf16(rawStringData, ref pos);
                    uint   byteLen = charLen * 2;
                    string item    = Encoding.Unicode.GetString(rawStringData, (int)pos, (int)byteLen);
                    pool.StringData.Add(item);
                }
            }

            // If styles are present, we should read them, too.
            if (header.StyleCount > 0)
            {
                byte[] rawStyleData = ReadBytes((int)header.Header.Size - (int)header.StylesStart);

                foreach (uint startingIndex in styleIndices)
                {
                    // At startingIndex, there are N entries defining the individual tags (b, i,...)
                    // that style the string at index i
                    // They are terminated by a value with value END (0xFFFFFFFF)
                    List <ResStringPool_span> styleData = new List <ResStringPool_span>();

                    int pos = (int)startingIndex;

                    while (true)
                    {
                        var index     = BitConverter.ToUInt32(rawStyleData, pos);
                        var firstChar = BitConverter.ToUInt32(rawStyleData, pos + 4);
                        var lastChar  = BitConverter.ToUInt32(rawStringData, pos + 8);

                        var span = new ResStringPool_span
                        {
                            Name = new ResStringPool_ref()
                            {
                                Index = index == 0xFFFFFFFFu ? (uint?)null : index
                            },
                            FirstChar = firstChar,
                            LastChar  = lastChar,
                        };

                        styleData.Add(span);
                        if (span.IsEnd)
                        {
                            break;
                        }

                        pos += 12;
                    }

                    pool.StyleData.Add(styleData);
                }

                bytesLeft -= rawStyleData.Length;
            }

            // Make sure we didn't go out of bounds.
            if (bytesLeft < 0)
            {
                throw new InvalidDataException("The length of the content exceeds the ResStringPool block boundary.");
            }
            if (bytesLeft > 0)
            {
                // Padding: data is always aligned to 4 bytes.
#if !CORECLR
                Debug.WriteLine("Warning: Garbage at the end of the StringPool block. Padding?");
#endif
                ReadBytes((int)bytesLeft);
            }

            return(pool);
        }