4#include "Stroika/Foundation/StroikaPreComp.h"
11#if qStroika_HasComponent_LZMA
14#include <lzma/7zCrc.h>
18#if qStroika_HasComponent_LZMA && defined(_MSC_VER)
20#pragma comment(lib, "lzma.lib")
25using namespace Stroika::Foundation::DataExchange::Archive;
26using namespace Stroika::Foundation::Streams;
30#if qStroika_HasComponent_LZMA
35 ::CrcGenerateTable ();
40class _7z::Reader::Rep_ :
public Reader::_IRep {
43 static void* Alloc_ (
void* ,
size_t size)
46 return new byte[size];
48 static void Free_ (
void* ,
void* address)
50 delete[]
reinterpret_cast<byte*
> (address);
54 mutable ISzAlloc fAllocImp_{};
55 mutable ISzAlloc fAllocTempImp_{};
57 struct MyISeekInStream : ISeekInStream {
65 static SRes Stream_Read_ (
void* pp,
void* buf,
size_t* size)
67 MyISeekInStream* pThis = (MyISeekInStream*)pp;
68 size_t sz = pThis->fInStream_.ReadBlocking (span{
reinterpret_cast<byte*
> (buf), *size}).size ();
73 static SRes Stream_Seek_ (
void* pp, Int64* pos, ESzSeek origin)
75 MyISeekInStream* pThis = (MyISeekInStream*)pp;
78 *pos = pThis->fInStream_.Seek (*pos);
81 *pos = pThis->fInStream_.Seek (eFromCurrent, *pos);
84 *pos = pThis->fInStream_.Seek (eFromEnd, *pos);
88 return SZ_ERROR_UNSUPPORTED;
93 MyISeekInStream fInSeekStream_;
94 mutable CLookToRead fLookStream_{};
100 fAllocImp_ = ISzAlloc{Alloc_, Free_};
101 fAllocTempImp_ = ISzAlloc{Alloc_, Free_};
103 ::SzArEx_Init (&fDB_);
105 ::LookToRead_CreateVTable (&fLookStream_,
false);
106 fLookStream_.realStream = &fInSeekStream_;
109 if ((ret = ::SzArEx_Open (&fDB_, &fLookStream_.s, &fAllocImp_, &fAllocTempImp_)) != SZ_OK) {
116 ::SzArEx_Free (&fDB_, &fAllocImp_);
118 virtual Set<String> GetContainedFiles ()
const override
121 for (
unsigned int i = 0; i < fDB_.NumFiles; ++i) {
122 if (not SzArEx_IsDir (&fDB_, i)) {
123 size_t nameLen = ::SzArEx_GetFileNameUtf16 (&fDB_, i,
nullptr);
127 StackBuffer<char16_t> fileName{Memory::eUninitialized, nameLen};
128 [[maybe_unused]]
size_t z = ::SzArEx_GetFileNameUtf16 (&fDB_, i,
reinterpret_cast<UInt16*
> (&fileName[0]));
136 UInt32 idx = GetIdx_ (fileName);
142 UInt32 blockIndex = 0xFFFFFFFF;
143 size_t outBufferSize = 0;
146 size_t outSizeProcessed{};
148 [[maybe_unused]]
auto&& cleanup = Execution::Finally ([&outBuffer,
this] ()
noexcept { IAlloc_Free (&fAllocImp_, outBuffer); });
151 if ((ret = ::SzArEx_Extract (&fDB_, &fLookStream_.s, idx, &blockIndex,
reinterpret_cast<uint8_t**
> (&outBuffer), &outBufferSize,
152 &offset, &outSizeProcessed, &fAllocImp_, &fAllocTempImp_)) != SZ_OK) {
155 return Memory::BLOB (outBuffer + offset, outBuffer + offset + outSizeProcessed);
157 UInt32 GetIdx_ (
const String& fn)
const
160 for (UInt32 i = 0; i < fDB_.NumFiles; ++i) {
161 if (not SzArEx_IsDir (&fDB_, i)) {
162 size_t nameLen = SzArEx_GetFileNameUtf16 (&fDB_, i,
nullptr);
166 StackBuffer<char16_t> fileName{Memory::eUninitialized, nameLen};
167 [[maybe_unused]]
size_t z = ::SzArEx_GetFileNameUtf16 (&fDB_, i,
reinterpret_cast<UInt16*
> (&fileName[0]));
168 if (
String{&fileName[0]} == fn) {
173 return static_cast<UInt32
> (-1);
178 : DataExchange::Archive::
Reader{make_shared<Rep_> (in)}
#define AssertNotReached()
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
nonvirtual void Add(ArgByValueType< value_type > item)
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...