internal static DBDirectoryEntry ReadFrom(BinaryReader reader, DBEntryAttributes attributes, StringBuilder stringBuilder)
        {
            var entry = new DBDirectoryEntry
            {
                Attributes          = attributes,
                DataLength          = reader.ReadUInt32(),
                DirectoryNameLength = reader.ReadByte(),
                DirectoryName       = reader.ReadNullTerminatedUtf16String(stringBuilder),
                ModificationTime    = (DBDWord)reader.ReadUInt32(),
                CreationTime        = (DBDWord)reader.ReadUInt32(),
                LastAccessedDate    = (DBDWord)reader.ReadUInt32(),
            };

            return(entry);
        }
        internal static DBFileEntry ReadFrom(BinaryReader reader, DBEntryAttributes attributes, StringBuilder stringBuilder)
        {
            var entry = new DBFileEntry
            {
                Attributes         = attributes,
                FileNameLength     = reader.ReadByte(),
                FileExtensionIndex = reader.ReadByte(),
                FileName           = reader.ReadNullTerminatedUtf16String(stringBuilder),
            };

            var fileSizeLo = reader.ReadUInt32();

            var fileSizeHi = (ulong)reader.ReadUInt16();

            entry.FileSize = fileSizeHi << 32 | fileSizeLo;

            entry.ModificationTime = (DBDWord)reader.ReadUInt32();

            entry.CreationTime = (DBDWord)reader.ReadUInt32();

            entry.LastAccessedDate = (DBDWord)reader.ReadUInt32();

            return(entry);
        }
        /// <summary>
        /// Read the next entry.
        /// </summary>
        /// <returns>The read DBEntry if any; null otherwise.</returns>
        public DBEntry Read()
        {
            switch (state)
            {
            case ReaderState.EndOfFile:
            {
                return(null);
            }

            case ReaderState.ReadHeaderNext:
            {
                LastReadEntry = Header = DBHeader.ReadFrom(binaryReader, strBuilder);

                state = ReaderState.ReadRootDirectoryNext;

                return(LastReadEntry);
            }

            case ReaderState.ReadRootDirectoryNext:
            {
                positionBeforeReadRootDirectory = inputStream.Position;

                LastReadEntry = currentRootDirectory = DBRootDirectoryEntry.ReadFrom(binaryReader, strBuilder);

                if (currentRootDirectory == null)
                {
                    state = ReaderState.EndOfFile;
                    return(null);
                }

                currentPathStack.Push(currentPath = currentRootDirectory.Path);

                currentRootDirectory.FullName = currentPath;

                state = ReaderState.ReadFileOrDirectoryNext;

                return(LastReadEntry);
            }

            case ReaderState.ReadFileOrDirectoryNext:
            {
                typeAndAttributes = (DBEntryAttributes)binaryReader.ReadByte();

                if (typeAndAttributes != 0 || depth > 0)
                {
                    if (typeAndAttributes.HasFlag(DBEntryAttributes.Directory))
                    {
                        positionBeforeReadDirectory = inputStream.Position;

                        var directoryEntry = DBDirectoryEntry.ReadFrom(binaryReader, typeAndAttributes, strBuilder);

                        currentPath += (depth == 0 ? string.Empty : @"\") + directoryEntry.DirectoryName;

                        directoryEntry.ParentDirectory = depth == 0 ? null : dirStack.Peek();
                        directoryEntry.RootDirectory   = currentRootDirectory;
                        directoryEntry.FullName        = currentPath;

                        depth++;

                        dirStack.Push(directoryEntry);

                        return(LastReadEntry = directoryEntry);
                    }

                    if (typeAndAttributes != 0)
                    {
                        var fileEntry = DBFileEntry.ReadFrom(binaryReader, typeAndAttributes, strBuilder);

                        fileEntry.ParentDirectory = depth == 0 ? null : dirStack.Peek();
                        fileEntry.RootDirectory   = currentRootDirectory;
                        fileEntry.FullName        = currentPath + (depth == 0 ? string.Empty : @"\") + fileEntry.FileName;

                        return(LastReadEntry = fileEntry);
                    }

                    depth--;
                    var poppedDir = dirStack.Pop();

                    currentPath = poppedDir.ParentDirectory?.FullName ?? poppedDir.RootDirectory?.FullName ?? string.Empty;

                    return(Read());
                }

                var nullByte = binaryReader.ReadByte();     // normally its a dword byte but we should already have read a zero byte before

                if (nullByte != 0)
                {
                    throw new ArchiveException($"Was expecting to read a final null-byte, read {nullByte} instead.");
                }

                currentPathStack.Pop();

                state = ReaderState.ReadRootDirectoryNext;

                return(Read());
            }
            }

            LastReadEntry = null;
            return(null);
        }