@@ -216,14 +216,79 @@ struct gguf_context {
216
216
void * data = nullptr ;
217
217
};
218
218
219
- struct gguf_reader {
219
+ struct gguf_bytes_reader {
220
+ // / @brief Reads up to `count` objects into the array `buffer`.
221
+ // / The position of the underlying stream implementation is advanced
222
+ // / by the number of characters read.
223
+ // /
224
+ // / @note If an error occurs, the resulting value of the underlying stream
225
+ // / position indicator is indeterminate.
226
+ virtual size_t read (void * buffer, size_t size, size_t count) = 0;
227
+
228
+ // / @brief Seeks to a position aligned to the given alignment boundary.
229
+ // / @return The current position after alignment, or 0 on error.
230
+ virtual size_t align (size_t alignment) = 0;
231
+
232
+ virtual ~gguf_bytes_reader () = 0 ;
233
+ };
234
+
235
+ gguf_bytes_reader::~gguf_bytes_reader () {}
236
+
237
+ struct gguf_bytes_buffer_reader : public gguf_bytes_reader {
238
+ gguf_bytes_buffer_reader (std::basic_streambuf<uint8_t > & streambuf) : streambuf(streambuf), offset(0 ) {}
239
+
240
+ ~gguf_bytes_buffer_reader () {}
241
+
242
+ size_t read (void * buffer, size_t size, size_t count) override {
243
+ size_t total_size = size * count;
244
+ auto bytes_read = streambuf.sgetn (static_cast <uint8_t *>(buffer), total_size);
245
+ offset += bytes_read;
246
+ return bytes_read;
247
+ }
248
+
249
+ size_t align (size_t alignment) override {
250
+ size_t new_offset = GGML_PAD (offset, alignment);
251
+ size_t seek_offset = new_offset - offset;
252
+
253
+ auto result = streambuf.pubseekoff (seek_offset, std::ios_base::cur);
254
+ if (result == std::streampos (-1 )) {
255
+ return 0 ;
256
+ }
257
+ offset = new_offset;
258
+ return offset;
259
+ }
260
+
261
+ private:
262
+ std::basic_streambuf<uint8_t > & streambuf;
263
+ size_t offset;
264
+ };
265
+
266
+ struct gguf_bytes_file_reader : public gguf_bytes_reader {
267
+ gguf_bytes_file_reader (FILE * file) : file(file) {}
268
+
269
+ ~gguf_bytes_file_reader () {}
270
+
271
+ size_t read (void * buffer, size_t size, size_t count) override { return fread (buffer, 1 , size * count, file); }
272
+
273
+ size_t align (size_t alignment) override {
274
+ if (fseek (file, GGML_PAD (ftell (file), alignment), SEEK_SET) != 0 ) {
275
+ return 0 ;
276
+ }
277
+ return ftell (file);
278
+ }
279
+
280
+ private:
220
281
FILE * file;
282
+ };
221
283
222
- gguf_reader (FILE * file) : file(file) {}
284
+ struct gguf_reader {
285
+ gguf_bytes_reader& bytes_reader;
286
+
287
+ gguf_reader (gguf_bytes_reader& bytes_reader) : bytes_reader(bytes_reader) {}
223
288
224
289
template <typename T>
225
290
bool read (T & dst) const {
226
- return fread (&dst, 1 , sizeof (dst), file ) == sizeof (dst);
291
+ return bytes_reader. read (&dst, 1 , sizeof (dst)) == sizeof (dst);
227
292
}
228
293
229
294
template <typename T>
@@ -278,11 +343,11 @@ struct gguf_reader {
278
343
return false ;
279
344
}
280
345
dst.resize (size);
281
- return fread (dst.data (), 1 , dst.length (), file ) == dst.length ();
346
+ return bytes_reader. read (dst.data (), 1 , dst.length ()) == dst.length ();
282
347
}
283
348
284
349
bool read (void * dst, const size_t size) const {
285
- return fread (dst, 1 , size, file ) == size;
350
+ return bytes_reader. read (dst, 1 , size) == size;
286
351
}
287
352
};
288
353
@@ -316,8 +381,8 @@ bool gguf_read_emplace_helper(const struct gguf_reader & gr, std::vector<struct
316
381
return true ;
317
382
}
318
383
319
- struct gguf_context * gguf_init_from_file_impl (FILE * file, struct gguf_init_params params) {
320
- const struct gguf_reader gr (file);
384
+ namespace {
385
+ struct gguf_context * gguf_init_from_reader_impl ( const struct gguf_reader & gr, struct gguf_init_params params) {
321
386
struct gguf_context * ctx = new gguf_context;
322
387
323
388
bool ok = true ;
@@ -606,15 +671,14 @@ struct gguf_context * gguf_init_from_file_impl(FILE * file, struct gguf_init_par
606
671
GGML_ASSERT (int64_t (ctx->info .size ()) == n_tensors);
607
672
608
673
// we require the data section to be aligned, so take into account any padding
609
- if (fseek (file, GGML_PAD (ftell (file), ctx->alignment ), SEEK_SET) != 0 ) {
610
- GGML_LOG_ERROR (" %s: failed to seek to beginning of data section\n " , __func__);
674
+ // store the current file offset - this is where the data section starts
675
+ ctx->offset = gr.bytes_reader .align (ctx->alignment );
676
+ if (ctx->offset == 0 ) {
677
+ GGML_LOG_ERROR (" %s: failed to align data section\n " , __func__);
611
678
gguf_free (ctx);
612
679
return nullptr ;
613
680
}
614
681
615
- // store the current file offset - this is where the data section starts
616
- ctx->offset = ftell (file);
617
-
618
682
// compute the total size of the data section, taking into account the alignment
619
683
{
620
684
ctx->size = 0 ;
@@ -718,6 +782,13 @@ struct gguf_context * gguf_init_from_file_impl(FILE * file, struct gguf_init_par
718
782
719
783
return ctx;
720
784
}
785
+ }
786
+
787
+ struct gguf_context * gguf_init_from_file_impl (FILE * file, struct gguf_init_params params) {
788
+ gguf_bytes_file_reader bytes_reader (file);
789
+ gguf_reader reader (bytes_reader);
790
+ return gguf_init_from_reader_impl (reader, params);
791
+ }
721
792
722
793
struct gguf_context * gguf_init_from_file (const char * fname, struct gguf_init_params params) {
723
794
FILE * file = ggml_fopen (fname, " rb" );
@@ -732,6 +803,14 @@ struct gguf_context * gguf_init_from_file(const char * fname, struct gguf_init_p
732
803
return result;
733
804
}
734
805
806
+ #ifdef __cplusplus
807
+ struct gguf_context * gguf_init_from_buffer (std::basic_streambuf<uint8_t > & streambuf, struct gguf_init_params params) {
808
+ gguf_bytes_buffer_reader bytes_reader (streambuf);
809
+ gguf_reader reader (bytes_reader);
810
+ return gguf_init_from_reader_impl (reader, params);
811
+ }
812
+ #endif
813
+
735
814
void gguf_free (struct gguf_context * ctx) {
736
815
if (ctx == nullptr ) {
737
816
return ;
0 commit comments