gguf : avoid too many file size calls (#19919)
This commit is contained in:
+47
-30
@@ -228,13 +228,41 @@ struct gguf_context {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct gguf_reader {
|
struct gguf_reader {
|
||||||
FILE * file;
|
gguf_reader(FILE * file) : file(file) {
|
||||||
|
// read the remaining bytes once and update on each read
|
||||||
|
nbytes_remain = file_remain(file);
|
||||||
|
}
|
||||||
|
|
||||||
gguf_reader(FILE * file) : file(file) {}
|
// helper for remaining bytes in a file
|
||||||
|
static uint64_t file_remain(FILE * file) {
|
||||||
|
const int64_t cur = gguf_ftell(file);
|
||||||
|
if (cur < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (gguf_fseek(file, 0, SEEK_END) != 0) {
|
||||||
|
gguf_fseek(file, cur, SEEK_SET);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const int64_t end = gguf_ftell(file);
|
||||||
|
if (end < 0) {
|
||||||
|
gguf_fseek(file, cur, SEEK_SET);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
gguf_fseek(file, cur, SEEK_SET);
|
||||||
|
return static_cast<uint64_t>(end - cur);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool read(T & dst) const {
|
bool read(T & dst) const {
|
||||||
return fread(&dst, 1, sizeof(dst), file) == sizeof(dst);
|
const size_t size = sizeof(dst);
|
||||||
|
if (nbytes_remain < size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const size_t nread = fread(&dst, 1, size, file);
|
||||||
|
nbytes_remain -= nread;
|
||||||
|
return nread == size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -242,20 +270,19 @@ struct gguf_reader {
|
|||||||
if (n > GGUF_MAX_ARRAY_ELEMENTS) {
|
if (n > GGUF_MAX_ARRAY_ELEMENTS) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const uint64_t nbytes = nbytes_remain();
|
|
||||||
if constexpr (std::is_same<T, std::string>::value) {
|
if constexpr (std::is_same<T, std::string>::value) {
|
||||||
// strings are prefixed with their length, so we need to account for that
|
// strings are prefixed with their length, so we need to account for that
|
||||||
if (n > SIZE_MAX / sizeof(uint64_t)) {
|
if (n > SIZE_MAX / sizeof(uint64_t)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (nbytes < n * sizeof(uint64_t)) {
|
if (nbytes_remain < n * sizeof(uint64_t)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (n > SIZE_MAX / sizeof(T)) {
|
if (n > SIZE_MAX / sizeof(T)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (nbytes < n * sizeof(T)) {
|
if (nbytes_remain < n * sizeof(T)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,39 +339,29 @@ struct gguf_reader {
|
|||||||
GGML_LOG_ERROR("%s: string length %" PRIu64 " exceeds maximum %" PRIu64 "\n", __func__, size, (uint64_t) GGUF_MAX_STRING_LENGTH);
|
GGML_LOG_ERROR("%s: string length %" PRIu64 " exceeds maximum %" PRIu64 "\n", __func__, size, (uint64_t) GGUF_MAX_STRING_LENGTH);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const uint64_t nbytes = nbytes_remain();
|
if (size > nbytes_remain) {
|
||||||
if (size > nbytes) {
|
GGML_LOG_ERROR("%s: string length %" PRIu64 " exceeds remaining file size %" PRIu64 " bytes\n", __func__, size, nbytes_remain);
|
||||||
GGML_LOG_ERROR("%s: string length %" PRIu64 " exceeds remaining file size %" PRIu64 " bytes\n", __func__, size, nbytes);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
dst.resize(static_cast<size_t>(size));
|
dst.resize(static_cast<size_t>(size));
|
||||||
return fread(dst.data(), 1, dst.length(), file) == dst.length();
|
const size_t nread = fread(dst.data(), 1, size, file);
|
||||||
|
nbytes_remain -= nread;
|
||||||
|
return nread == size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read(void * dst, const size_t size) const {
|
bool read(void * dst, const size_t size) const {
|
||||||
return fread(dst, 1, size, file) == size;
|
if (size > nbytes_remain) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const size_t nread = fread(dst, 1, size, file);
|
||||||
|
nbytes_remain -= nread;
|
||||||
|
return nread == size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remaining bytes in the file
|
private:
|
||||||
uint64_t nbytes_remain() const {
|
FILE * file;
|
||||||
const int64_t cur = gguf_ftell(file);
|
|
||||||
if (cur < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (gguf_fseek(file, 0, SEEK_END) != 0) {
|
|
||||||
gguf_fseek(file, cur, SEEK_SET);
|
|
||||||
|
|
||||||
return 0;
|
mutable uint64_t nbytes_remain;
|
||||||
}
|
|
||||||
const int64_t end = gguf_ftell(file);
|
|
||||||
if (end < 0) {
|
|
||||||
gguf_fseek(file, cur, SEEK_SET);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
gguf_fseek(file, cur, SEEK_SET);
|
|
||||||
return static_cast<uint64_t>(end - cur);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gguf_context * gguf_init_empty(void) {
|
struct gguf_context * gguf_init_empty(void) {
|
||||||
|
|||||||
Reference in New Issue
Block a user