58 if (base->
seek(base, -4, SEEK_END) < 13) {
67 if (base->
seek(base, -5, SEEK_END) < 0 || base->
read(base, &flags, 1) != 1) {
71 bool has_checksums = (flags & 0x80);
83 uint32_t expected_frame_length = frames_num * (has_checksums ? 12 : 8) + 9;
86 off64_t frame_start_ofs = 8 + expected_frame_length;
89 off64_t seek_frame_start = base->
seek(base, -frame_start_ofs, SEEK_END);
90 if (seek_frame_start < frames_num * 8) {
98 uint32_t frame_length;
99 if (!
zstd_read_u32(base, &frame_length) || frame_length != expected_frame_length) {
103 zstd->
seek.frames_num = frames_num;
107 size_t compressed_ofs = 0;
108 size_t uncompressed_ofs = 0;
109 for (
int i = 0;
i < frames_num;
i++) {
110 uint32_t compressed_size, uncompressed_size;
114 if (has_checksums && base->
seek(base, 4, SEEK_CUR) < 0) {
117 zstd->
seek.compressed_ofs[
i] = compressed_ofs;
118 zstd->
seek.uncompressed_ofs[
i] = uncompressed_ofs;
119 compressed_ofs += compressed_size;
120 uncompressed_ofs += uncompressed_size;
122 zstd->
seek.compressed_ofs[frames_num] = compressed_ofs;
123 zstd->
seek.uncompressed_ofs[frames_num] = uncompressed_ofs;
126 if (seek_frame_start != compressed_ofs || base->
seek(base, seek_frame_start, SEEK_SET) < 0) {
129 memset(&zstd->
seek, 0,
sizeof(zstd->
seek));
133 zstd->
seek.cached_frame = -1;
164 if (zstd->
seek.cached_frame == frame) {
166 return zstd->
seek.cached_content;
172 size_t compressed_size = zstd->
seek.compressed_ofs[frame + 1] - zstd->
seek.compressed_ofs[frame];
173 size_t uncompressed_size = zstd->
seek.uncompressed_ofs[frame + 1] -
174 zstd->
seek.uncompressed_ofs[frame];
178 if (zstd->
base->
seek(zstd->
base, zstd->
seek.compressed_ofs[frame], SEEK_SET) < 0 ||
179 zstd->
base->
read(zstd->
base, compressed_data, compressed_size) < compressed_size)
186 size_t res = ZSTD_decompressDCtx(
187 zstd->
ctx, uncompressed_data, uncompressed_size, compressed_data, compressed_size);
189 if (ZSTD_isError(res) || res < uncompressed_size) {
194 zstd->
seek.cached_frame = frame;
195 zstd->
seek.cached_content = uncompressed_data;
196 return uncompressed_data;
212 if (framedata ==
nullptr) {
217 size_t frame_end_offset = std::min(zstd->
seek.uncompressed_ofs[frame + 1], end_offset);
218 size_t frame_read_len = frame_end_offset - zstd->
reader.
offset;
220 size_t offset_in_frame = zstd->
reader.
offset - zstd->
seek.uncompressed_ofs[frame];
221 memcpy((
char *)buffer + read_len, framedata + offset_in_frame, frame_read_len);
222 read_len += frame_read_len;