void * data;
};
-static size_t gguf_type_size(enum gguf_type type) {
+size_t gguf_type_size(enum gguf_type type) {
GGML_ASSERT(0 <= type && type < GGUF_TYPE_COUNT);
return GGUF_TYPE_SIZE[type];
}
return ctx;
}
-struct gguf_context * gguf_init_from_file(const char * fname, struct gguf_init_params params) {
- FILE * file = ggml_fopen(fname, "rb");
- if (!file) {
- fprintf(stderr, "%s: failed to open '%s': '%s'\n", __func__, fname, strerror(errno));
- return NULL;
- }
-
+struct gguf_context * gguf_init_from_file_impl(FILE * file, struct gguf_init_params params) {
// offset from start of file
size_t offset = 0;
for (uint32_t i = 0; i < sizeof(magic); i++) {
if (magic[i] != GGUF_MAGIC[i]) {
fprintf(stderr, "%s: invalid magic characters '%c%c%c%c'\n", __func__, magic[0], magic[1], magic[2], magic[3]);
- fclose(file);
return NULL;
}
}
struct gguf_context * ctx = calloc(1, sizeof(struct gguf_context));
if (!ctx) {
fprintf(stderr, "%s: failed to allocate memory for context\n", __func__);
- fclose(file);
return NULL;
}
if (ctx->header.version == 1) {
fprintf(stderr, "%s: GGUFv1 is no longer supported. please use a more up-to-date version\n", __func__);
- fclose(file);
gguf_free(ctx);
return NULL;
}
if (!ok) {
fprintf(stderr, "%s: failed to read header\n", __func__);
- fclose(file);
gguf_free(ctx);
return NULL;
}
{
const uint64_t n_kv = ctx->header.n_kv;
- ctx->kv = calloc(n_kv, sizeof(struct gguf_kv));
- if (!ctx->kv) {
- fprintf(stderr, "%s: failed to allocate memory for kv pairs\n", __func__);
- fclose(file);
- gguf_free(ctx);
- return NULL;
+ if (n_kv > 0) {
+ ctx->kv = calloc(n_kv, sizeof(struct gguf_kv));
+ if (!ctx->kv) {
+ fprintf(stderr, "%s: failed to allocate memory for kv pairs\n", __func__);
+ gguf_free(ctx);
+ return NULL;
+ }
}
for (uint64_t i = 0; i < n_kv; ++i) {
// prevent from integer overflow in the malloc below
if (kv->value.arr.n >= SIZE_MAX/gguf_type_size(kv->value.arr.type)) {
fprintf(stderr, "%s: array size is too large (%" PRIu64 ")\n", __func__, kv->value.arr.n);
- fclose(file);
gguf_free(ctx);
return NULL;
}
kv->value.arr.data = calloc(kv->value.arr.n, gguf_type_size(kv->value.arr.type));
if (!kv->value.arr.data) {
fprintf(stderr, "%s: failed to allocate memory for array\n", __func__);
- fclose(file);
gguf_free(ctx);
return NULL;
}
// prevent from integer overflow in the malloc below
if (kv->value.arr.n >= SIZE_MAX/sizeof(struct gguf_str)) {
fprintf(stderr, "%s: array size is too large (%" PRIu64 ")\n", __func__, kv->value.arr.n);
- fclose(file);
gguf_free(ctx);
return NULL;
}
kv->value.arr.data = calloc(kv->value.arr.n, sizeof(struct gguf_str));
if (!kv->value.arr.data) {
fprintf(stderr, "%s: failed to allocate memory for array\n", __func__);
- fclose(file);
gguf_free(ctx);
return NULL;
}
if (!ok) {
fprintf(stderr, "%s: failed to read key-value pairs\n", __func__);
- fclose(file);
gguf_free(ctx);
return NULL;
}
ctx->infos = calloc(ctx->header.n_tensors, sizeof(struct gguf_tensor_info));
if (!ctx->infos) {
fprintf(stderr, "%s: failed to allocate memory for tensor infos\n", __func__);
- fclose(file);
gguf_free(ctx);
return NULL;
}
if (!ok) {
fprintf(stderr, "%s: failed to read tensor info\n", __func__);
- fclose(file);
gguf_free(ctx);
return NULL;
}
// this tensor type support have been removed:
fprintf(stderr, "%s: tensor '%s' of type %d: %s\n",
__func__, info->name.data, (int) info->type, ggml_type_name(info->type));
- fclose(file);
gguf_free(ctx);
return NULL;
}
if (ne % ggml_blck_size(info->type) != 0) {
fprintf(stderr, "%s: tensor '%s' of type %d (%s) number of elements (%" PRId64 ") is not a multiple of block size (%" PRId64 ")\n",
__func__, info->name.data, (int) info->type, ggml_type_name(info->type), ne, ggml_blck_size(info->type));
- fclose(file);
gguf_free(ctx);
return NULL;
}
*params.ctx = ggml_init(pdata);
if (*params.ctx == NULL) {
fprintf(stderr, "%s: failed to initialize context\n", __func__);
- fclose(file);
gguf_free(ctx);
return NULL;
}
if (!ok) {
fprintf(stderr, "%s: failed to read tensor data\n", __func__);
- fclose(file);
ggml_free(ctx_data);
gguf_free(ctx);
return NULL;
if (!ok) {
fprintf(stderr, "%s: failed to read the tensor data\n", __func__);
- fclose(file);
ggml_free(ctx_data);
gguf_free(ctx);
return NULL;
ggml_set_no_alloc(ctx_data, params.no_alloc);
}
- fclose(file);
-
return ctx;
}
+struct gguf_context * gguf_init_from_file(const char * fname, struct gguf_init_params params) {
+ FILE * file = ggml_fopen(fname, "rb");
+ if (!file) {
+ fprintf(stderr, "%s: failed to open '%s': '%s'\n", __func__, fname, strerror(errno));
+ return NULL;
+ }
+
+ struct gguf_context * result = gguf_init_from_file_impl(file, params);
+ fclose(file);
+ return result;
+}
+
void gguf_free(struct gguf_context * ctx) {
if (ctx == NULL) {
return;
// fwrite(val, sizeof(char), size, file);
//}
-struct gguf_buf {
- void * data;
- size_t size;
- size_t offset;
-};
-
-static struct gguf_buf gguf_buf_init(size_t size) {
+struct gguf_buf gguf_buf_init(size_t size) {
struct gguf_buf buf = {
/*buf.data =*/ size == 0 ? NULL : GGML_CALLOC(1, size),
/*buf.size =*/ size,
return buf;
}
-static void gguf_buf_free(struct gguf_buf buf) {
+void gguf_buf_free(struct gguf_buf buf) {
if (buf.data) {
GGML_FREE(buf.data);
}
buf->offset += el_size;
}
-static void gguf_write_to_buf(const struct gguf_context * ctx, struct gguf_buf * buf, bool only_meta) {
+void gguf_write_to_buf(const struct gguf_context * ctx, struct gguf_buf * buf, bool only_meta) {
// write header
gguf_bwrite_el(buf, &ctx->header.magic, sizeof(ctx->header.magic));
gguf_bwrite_el(buf, &ctx->header.version, sizeof(ctx->header.version));