internal void GetDataByteArray(FileFormat.EntryType entryType, uint entryIndex, uint numEntries, ref byte[][] dataOut)
        {
            Chapter chapter = GetChapter(entryType);

            if (entryIndex + numEntries > chapter.GetNumEntries())
            {
                throw new IOException("Invalid entry index or number of entries.");
            }

            if (numEntries > dataOut.Length)
            {
                throw new IOException("Not enough space in dataOut array.");
            }

            uint  blockIndex       = chapter.GetBlockIndex();
            ulong startBlockOffset = chapter.GetBlockOffsetForEntryIndex(entryIndex);
            ulong offset           = startBlockOffset;

            for (uint i = 0; i < numEntries; ++i)
            {
                uint entrySize = chapter.GetSizeForEntryIndex(entryIndex + i);

                dataOut[i] = new byte[entrySize];
                m_Blocks[blockIndex].GetData(offset, entrySize, ref dataOut[i], m_Reader);

                offset += entrySize;
            }
        }
        public void GetDataArray <T>(FileFormat.EntryType entryType, uint entryIndex, uint numEntries, ref T[] dataOut, GetItem <T> getItemFunc)
        {
            Chapter chapter = GetChapter(entryType);

            if (entryIndex + numEntries > chapter.GetNumEntries())
            {
                throw new IOException("Invalid entry indices");
            }

            if (numEntries > dataOut.Length)
            {
                throw new IOException("Not enough space in dataOut array");
            }

            uint  blockIndex       = chapter.GetBlockIndex();
            ulong startBlockOffset = chapter.GetBlockOffsetForEntryIndex(entryIndex);
            ulong endBlockOffset   = chapter.GetBlockOffsetForEntryIndex(entryIndex + numEntries);
            uint  dataSize         = (uint)(endBlockOffset - startBlockOffset);

            byte[] data = GetDataCache(dataSize);

            m_Blocks[blockIndex].GetData(startBlockOffset, dataSize, ref data, m_Reader);

            uint dataIndex = 0;

            for (uint i = 0; i < numEntries; i++)
            {
                uint entrySize = chapter.GetSizeForEntryIndex(entryIndex + i);
                dataOut[i] = getItemFunc(data, dataIndex, entrySize);
                dataIndex += entrySize;
            }
        }
 public void WriteEntry(FileFormat.EntryType entryType, string data)
 {
     if (data == null)
     {
         throw new NullReferenceException();
     }
     Internal_WriteEntryString(data, (int)entryType);
 }
        public void WriteEntry <T>(FileFormat.EntryType entryType, T data) where T : struct
        {
            GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);

            try
            {
                IntPtr rawDataPtr = handle.AddrOfPinnedObject();
                int    dataSize   = UnsafeUtility.SizeOf <T>();
                Internal_WriteEntryData(rawDataPtr, dataSize, (int)entryType);
            }
            finally
            {
                handle.Free();
            }
        }
        internal Chapter GetChapter(FileFormat.EntryType entryType)
        {
            if ((uint)entryType >= m_Chapters.Length)
            {
                throw new IOException("Invalid entry type");
            }

            Chapter chapter = m_Chapters[(uint)entryType];

            if (chapter == null)
            {
                throw new IOException("Attempted to read from empty chapter");
            }

            return(chapter);
        }
        public uint GetNumEntries(FileFormat.EntryType entryType)
        {
            if ((uint)entryType >= m_Chapters.Length)
            {
                throw new IOException("Invalid entry type");
            }

            Chapter chapter = m_Chapters[(uint)entryType];

            if (chapter == null)
            {
                return(0);
            }

            return(chapter.GetNumEntries());
        }
        public void WriteEntryArray <T>(FileFormat.EntryType entryType, T[] data) where T : struct
        {
            GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);

            try
            {
                IntPtr rawDataPtr  = handle.AddrOfPinnedObject();
                int    dataSize    = Marshal.SizeOf(typeof(T));
                int    numElements = data.Length;
                Internal_WriteEntryDataArray(rawDataPtr, dataSize, numElements, (int)entryType);
            }
            finally
            {
                handle.Free();
            }
        }
        public T GetDataSingle <T>(FileFormat.EntryType entryType, GetItem <T> getItemFunc)
        {
            Chapter chapter = GetChapter(entryType);

            if (!(chapter is SingleValueChapter))
            {
                throw new IOException("Chapter is not a single value chapter");
            }

            uint  blockIndex  = chapter.GetBlockIndex();
            ulong blockOffset = chapter.GetBlockOffsetForEntryIndex(0);
            uint  dataSize    = chapter.GetSizeForEntryIndex(0);

            byte[] data = GetDataCache(dataSize);

            m_Blocks[blockIndex].GetData(blockOffset, dataSize, ref data, m_Reader);

            return(getItemFunc(data, 0, dataSize));
        }
        public void GetDataArray <T>(FileFormat.EntryType entryType, uint entryIndex, uint numEntries, ref T[] dataOut, GetItem <T> getItemFunc)
        {
            Chapter chapter = GetChapter(entryType);

            if (entryIndex + numEntries > chapter.GetNumEntries())
            {
                throw new IOException("Invalid entry index or number of entries.");
            }

            if (numEntries > dataOut.Length)
            {
                throw new IOException("Not enough space in dataOut array.");
            }

            uint  blockIndex       = chapter.GetBlockIndex();
            ulong startBlockOffset = chapter.GetBlockOffsetForEntryIndex(entryIndex);

            byte[] data = GetDataCache(m_CacheDataCapacity);

            uint  i      = 0;
            ulong offset = startBlockOffset;

            while (i < numEntries)
            {
                uint cacheMemory = 0;

                uint element = i;

                while (element < numEntries)
                {
                    uint entrySize = chapter.GetSizeForEntryIndex(entryIndex + element);

                    if (entrySize > m_CacheDataCapacity)
                    {
                        if (cacheMemory > 0)
                        {
                            break; // first process what is in the cache
                        }

                        // When the cache is empty process big entry
                        data = GetDataCache(entrySize);
                    }

                    if (cacheMemory + entrySize > m_CacheDataCapacity)
                    {
                        break;
                    }

                    cacheMemory += entrySize;
                    element++;
                }

                m_Blocks[blockIndex].GetData(offset, cacheMemory, ref data, m_Reader);

                uint dataOffset = 0;

                while (i < element)
                {
                    uint entrySize = chapter.GetSizeForEntryIndex(entryIndex + i);
                    dataOut[i]  = getItemFunc(data, dataOffset, entrySize);
                    dataOffset += entrySize;
                    i++;
                }

                offset += cacheMemory;
            }
        }
 public void WriteEntry(FileFormat.EntryType entryType, string data)
 {
     Internal_WriteEntryString(data, (int)entryType);
 }