Beispiel #1
0
        /// <summary>
        /// Creates an item from header data.
        /// </summary>
        /// <param name="id">The item id.</param>
        /// <param name="header">The header data.</param>
        /// <param name="dataSourceList">The item list to use as the item data source.</param>
        /// <returns>A new <see cref="NefsItem"/>.</returns>
        public static NefsItem CreateFromHeader(NefsItemId id, NefsHeader header, NefsItemList dataSourceList)
        {
            var p1 = header.Part1.EntriesById[id];
            var p2 = header.Part2.EntriesById[id];

            // Check if part 6 exists
            NefsHeaderPart6Entry p6 = null;

            if (header.Part6.EntriesById.ContainsKey(id))
            {
                p6 = header.Part6.EntriesById[id];
            }

            // Determine type
            var type = p2.Data0x0c_ExtractedSize.Value == 0 ? NefsItemType.Directory : NefsItemType.File;

            // Find parent
            var parentId = header.GetItemDirectoryId(id);

            // Offset and size
            var dataOffset    = p1.Data0x00_OffsetToData.Value;
            var extractedSize = p2.Data0x0c_ExtractedSize.Value;

            // Data source
            INefsDataSource dataSource;

            if (type == NefsItemType.Directory)
            {
                // Item is a directory
                dataSource = new NefsEmptyDataSource();
            }
            else if (p1.IndexIntoPart4 == 0xFFFFFFFFU)
            {
                // Item is not compressed
                var size = new NefsItemSize(extractedSize);
                dataSource = new NefsItemListDataSource(dataSourceList, dataOffset, size);
            }
            else
            {
                // Item is compressed
                var p4   = header.Part4.EntriesByIndex[p1.IndexIntoPart4];
                var size = new NefsItemSize(extractedSize, p4.ChunkSizes);
                dataSource = new NefsItemListDataSource(dataSourceList, dataOffset, size);
            }

            // File name and path
            var fileName = header.GetItemFileName(id);

            // Gather unknown metadata
            var unknown = new NefsItemUnknownData
            {
                Part6Unknown0x00 = p6?.Byte0 ?? 0,
                Part6Unknown0x01 = p6?.Byte1 ?? 0,
                Part6Unknown0x02 = p6?.Byte2 ?? 0,
                Part6Unknown0x03 = p6?.Byte3 ?? 0,
            };

            // Create item
            return(new NefsItem(id, fileName, parentId, type, dataSource, unknown));
        }
Beispiel #2
0
        /// <summary>
        /// Gets the id of the first child for an item. If the item has no children, the item's id
        /// is returned. The first child id is based on the children being sorted by id, not file name.
        /// </summary>
        /// <param name="id">The id of the item.</param>
        /// <returns>The first child id.</returns>
        public NefsItemId GetItemFirstChildId(NefsItemId id)
        {
            // First child id is based on children items being sorted by id, NOT by file name
            var item = this.itemsById[id];

            return(item.Children.Count > 0 ? item.Children.OrderBy(i => i.Value.Item.Id).First().Value.Item.Id : id);
        }
Beispiel #3
0
        /// <summary>
        /// Gets the directory id for an item. If the item is in the root directory, the directory
        /// id will equal the item's id.
        /// </summary>
        /// <param name="id">The item id.</param>
        /// <returns>The directory id.</returns>
        public NefsItemId GetItemDirectoryId(NefsItemId id)
        {
            var item = this.itemsById[id];

            if (item.Parent == null)
            {
                return(id);
            }

            return(item.Parent.Item.Id);
        }
Beispiel #4
0
        /// <summary>
        /// Gets the id of the next item in the same directory as the specified item. If the
        /// specified item is that last item in the directory, the sibling id is equal to the item's
        /// id. Sibling id is based on directory structure with the children sorted by id, not file name.
        /// </summary>
        /// <param name="id">The id of the item to get the sibling for.</param>
        /// <returns>The sibling id.</returns>
        public NefsItemId GetItemSiblingId(NefsItemId id)
        {
            // Sibling id is based on children items being sorted by id, NOT by file name
            var item       = this.itemsById[id];
            var parentList = item.Parent?.Children.OrderBy(i => i.Value.Item.Id).Select(i => i.Value.Item.Id).ToList()
                             ?? this.rootItems.OrderBy(i => i.Value.Item.Id).Select(i => i.Value.Item.Id).ToList();
            var itemIndex = parentList.IndexOf(item.Item.Id);

            if (itemIndex == parentList.Count - 1)
            {
                // This is the last item in the directory
                return(id);
            }

            // Return id of next item in directory
            return(parentList[itemIndex + 1]);
        }
Beispiel #5
0
        /// <summary>
        /// Gets the file path of the item within the archive.
        /// </summary>
        /// <param name="id">The item id.</param>
        /// <returns>The item's file path within the archive.</returns>
        public string GetItemFilePath(NefsItemId id)
        {
            var path = this.GetItemFileName(id);

            var dirId     = this.GetItemDirectoryId(id);
            var prevDirId = id;

            while (dirId != prevDirId)
            {
                var dirName = this.GetItemFileName(dirId);
                path = Path.Combine(dirName, path);

                prevDirId = dirId;
                dirId     = this.GetItemDirectoryId(dirId);
            }

            return(path);
        }
Beispiel #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NefsItem"/> class.
        /// </summary>
        /// <param name="guid">The unique identifier for this item.</param>
        /// <param name="id">The item id.</param>
        /// <param name="fileName">The file name within the archive.</param>
        /// <param name="directoryId">The directory id the item is in.</param>
        /// <param name="dataSource">The data source for the item's data.</param>
        /// <param name="transform">
        /// The transform that is applied to this item's data. Can be null if no transform.
        /// </param>
        /// <param name="attributes">Additional attributes.</param>
        /// <param name="state">The item state.</param>
        public NefsItem(
            Guid guid,
            NefsItemId id,
            string fileName,
            NefsItemId directoryId,
            INefsDataSource dataSource,
            NefsDataTransform transform,
            NefsItemAttributes attributes,
            NefsItemState state = NefsItemState.None)
        {
            this.Guid        = guid;
            this.Id          = id;
            this.DirectoryId = directoryId;
            this.DataSource  = dataSource ?? throw new ArgumentNullException(nameof(dataSource));
            this.State       = state;
            this.Transform   = transform;
            this.Attributes  = attributes;

            // Save file name
            this.FileName = fileName ?? throw new ArgumentNullException(nameof(fileName));
        }
Beispiel #7
0
        /// <summary>
        /// Removes the item with the specified id.
        /// </summary>
        /// <param name="id">The id of the item to remove.</param>
        public void Remove(NefsItemId id)
        {
            if (!this.itemsById.ContainsKey(id))
            {
                return;
            }

            var item = this.itemsById[id];

            this.itemsById.Remove(id);

            // Check if in root
            if (item.Parent == null)
            {
                this.rootItems.Remove(item.Item.FileName);
            }
            else
            {
                // Remove item from parent
                item.Parent?.Children.Remove(item.Item.FileName);
                item.Parent = null;
            }
        }
Beispiel #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NefsItem"/> class.
        /// </summary>
        /// <param name="id">The item id (index).</param>
        /// <param name="fileName">The file name within the archive.</param>
        /// <param name="directoryId">The directory id the item is in.</param>
        /// <param name="type">The type of item.</param>
        /// <param name="dataSource">The data source for the item's data.</param>
        /// <param name="unknownData">Unknown metadata.</param>
        /// <param name="state">The item state.</param>
        public NefsItem(
            NefsItemId id,
            string fileName,
            NefsItemId directoryId,
            NefsItemType type,
            INefsDataSource dataSource,
            NefsItemUnknownData unknownData,
            NefsItemState state = NefsItemState.None)
        {
            this.Id          = id;
            this.DirectoryId = directoryId;
            this.Type        = type;
            this.DataSource  = dataSource ?? throw new ArgumentNullException(nameof(dataSource));
            this.State       = state;

            // Unknown data
            this.Part6Unknown0x00 = unknownData.Part6Unknown0x00;
            this.Part6Unknown0x01 = unknownData.Part6Unknown0x01;
            this.Part6Unknown0x02 = unknownData.Part6Unknown0x02;
            this.Part6Unknown0x03 = unknownData.Part6Unknown0x03;

            // Save file name
            this.FileName = fileName ?? throw new ArgumentNullException(nameof(fileName));
        }
Beispiel #9
0
 /// <summary>
 /// Gets the file name of the item.
 /// </summary>
 /// <param name="id">The item id.</param>
 /// <returns>The item's file name.</returns>
 public string GetItemFileName(NefsItemId id)
 {
     return(this.itemsById[id].Item.FileName);
 }
Beispiel #10
0
 /// <summary>
 /// Gets the item with the specified id. Throws an exception if not found.
 /// </summary>
 /// <param name="id">The id of the item to get.</param>
 /// <returns>The <see cref="NefsItem"/>.</returns>
 public NefsItem GetItem(NefsItemId id)
 {
     return(this.itemsById[id].Item);
 }
Beispiel #11
0
        /// <summary>
        /// Enumerates the children of an item.
        /// </summary>
        /// <param name="id">The item id.</param>
        /// <returns>The items children.</returns>
        public IEnumerable <NefsItem> EnumerateItemChildren(NefsItemId id)
        {
            var item = this.itemsById[id];

            return(item.Children.Values.Select(v => v.Item));
        }
Beispiel #12
0
 /// <summary>
 /// Checks if the item list contains an item with the specified id.
 /// </summary>
 /// <param name="id">The id to check.</param>
 /// <returns>True if the list contains the item id.</returns>
 public bool ContainsKey(NefsItemId id)
 {
     return(this.itemsById.ContainsKey(id));
 }
Beispiel #13
0
 /// <summary>
 /// Gets all items with the specified id. Throws an exception if not found.
 /// </summary>
 /// <param name="id">The id of the items to get.</param>
 /// <returns>The <see cref="NefsItem"/>.</returns>
 public IReadOnlyList <NefsItem> GetItems(NefsItemId id)
 {
     return(this.itemsById[id].Items);
 }