diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index b94f7103c..2b51be648 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -21,7 +21,9 @@ hb_aat_layout_has_tracking
hb-blob hb_blob_create +hb_blob_create_or_fail hb_blob_create_from_file +hb_blob_create_from_file_or_fail hb_blob_create_sub_blob hb_blob_copy_writable_or_fail hb_blob_destroy diff --git a/docs/usermanual-getting-started.xml b/docs/usermanual-getting-started.xml index e0df4a553..b73c4b076 100644 --- a/docs/usermanual-getting-started.xml +++ b/docs/usermanual-getting-started.xml @@ -241,7 +241,7 @@ - hb_blob_t *blob = hb_blob_create_from_file(filename); + hb_blob_t *blob = hb_blob_create_from_file(filename); /* or hb_blob_create_from_file_or_fail() */ hb_face_t *face = hb_face_create(blob, 0); hb_font_t *font = hb_font_create(face); diff --git a/perf/perf-draw.hh b/perf/perf-draw.hh index efca854a2..12581bc0d 100644 --- a/perf/perf-draw.hh +++ b/perf/perf-draw.hh @@ -58,8 +58,8 @@ static void draw (benchmark::State &state, const char *font_path, bool is_var, b hb_font_t *font; unsigned num_glyphs; { - hb_blob_t *blob = hb_blob_create_from_file (font_path); - assert (hb_blob_get_length (blob)); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (font_path); + assert (blob); hb_face_t *face = hb_face_create (blob, 0); hb_blob_destroy (blob); num_glyphs = hb_face_get_glyph_count (face); diff --git a/perf/perf-extents.hh b/perf/perf-extents.hh index 836fefe8f..c7bc84c92 100644 --- a/perf/perf-extents.hh +++ b/perf/perf-extents.hh @@ -13,8 +13,8 @@ static void extents (benchmark::State &state, const char *font_path, bool is_var hb_font_t *font; unsigned num_glyphs; { - hb_blob_t *blob = hb_blob_create_from_file (font_path); - assert (hb_blob_get_length (blob)); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (font_path); + assert (blob); hb_face_t *face = hb_face_create (blob, 0); hb_blob_destroy (blob); num_glyphs = hb_face_get_glyph_count (face); diff --git a/perf/perf-shaping.hh b/perf/perf-shaping.hh index 73efd0a7e..85ee19b77 100644 --- a/perf/perf-shaping.hh +++ b/perf/perf-shaping.hh @@ -8,18 +8,18 @@ static void shape (benchmark::State &state, const char *text_path, { hb_font_t *font; { - hb_blob_t *blob = hb_blob_create_from_file (font_path); - assert (hb_blob_get_length (blob)); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (font_path); + assert (blob); hb_face_t *face = hb_face_create (blob, 0); hb_blob_destroy (blob); font = hb_font_create (face); hb_face_destroy (face); } - hb_blob_t *text_blob = hb_blob_create_from_file (text_path); + hb_blob_t *text_blob = hb_blob_create_from_file_or_fail (text_path); + assert (text_blob); unsigned text_length; const char *text = hb_blob_get_data (text_blob, &text_length); - assert (text_length); hb_buffer_t *buf = hb_buffer_create (); for (auto _ : state) diff --git a/src/hb-blob.cc b/src/hb-blob.cc index 71b1b1fc4..4924eba75 100644 --- a/src/hb-blob.cc +++ b/src/hb-blob.cc @@ -71,15 +71,49 @@ hb_blob_create (const char *data, hb_memory_mode_t mode, void *user_data, hb_destroy_func_t destroy) +{ + if (!length) + return hb_blob_get_empty (); + + hb_blob_t *blob = hb_blob_create_or_fail (data, length, mode, + user_data, destroy); + return likely (blob) ? blob : hb_blob_get_empty (); +} + +/** + * hb_blob_create_or_fail: (skip) + * @data: Pointer to blob data. + * @length: Length of @data in bytes. + * @mode: Memory mode for @data. + * @user_data: Data parameter to pass to @destroy. + * @destroy: (nullable): Callback to call when @data is not needed anymore. + * + * Creates a new "blob" object wrapping @data. The @mode parameter is used + * to negotiate ownership and lifecycle of @data. + * + * Note that this function returns a freshly-allocated empty blob even if @length + * is zero. This is in contrast to hb_blob_create(), which returns the singleton + * empty blob (as returned by hb_blob_get_empty()) if @length is zero. + * + * Return value: New blob, or %NULL if failed. Destroy with hb_blob_destroy(). + * + * Since: REPLACEME + **/ +hb_blob_t * +hb_blob_create_or_fail (const char *data, + unsigned int length, + hb_memory_mode_t mode, + void *user_data, + hb_destroy_func_t destroy) { hb_blob_t *blob; - if (!length || - length >= 1u << 31 || - !(blob = hb_object_create ())) { + if (length >= 1u << 31 || + !(blob = hb_object_create ())) + { if (destroy) destroy (user_data); - return hb_blob_get_empty (); + return nullptr; } blob->data = data; @@ -91,9 +125,10 @@ hb_blob_create (const char *data, if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { blob->mode = HB_MEMORY_MODE_READONLY; - if (!blob->try_make_writable ()) { + if (!blob->try_make_writable ()) + { hb_blob_destroy (blob); - return hb_blob_get_empty (); + return nullptr; } } @@ -561,12 +596,32 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file) * Creates a new blob containing the data from the * specified binary font file. * - * Returns: An #hb_blob_t pointer with the content of the file + * Returns: An #hb_blob_t pointer with the content of the file, + * or hb_blob_get_empty() if failed. * * Since: 1.7.7 **/ hb_blob_t * hb_blob_create_from_file (const char *file_name) +{ + hb_blob_t *blob = hb_blob_create_from_file_or_fail (file_name); + return likely (blob) ? blob : hb_blob_get_empty (); +} + +/** + * hb_blob_create_from_file_or_fail: + * @file_name: A font filename + * + * Creates a new blob containing the data from the + * specified binary font file. + * + * Returns: An #hb_blob_t pointer with the content of the file, + * or %NULL if failed. + * + * Since: REPLACEME + **/ +hb_blob_t * +hb_blob_create_from_file_or_fail (const char *file_name) { /* Adopted from glib's gmappedfile.c with Matthias Clasen and Allison Lortie permission but changed a lot to suit our need. */ @@ -601,9 +656,9 @@ hb_blob_create_from_file (const char *file_name) close (fd); - return hb_blob_create (file->contents, file->length, - HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, - (hb_destroy_func_t) _hb_mapped_file_destroy); + return hb_blob_create_or_fail (file->contents, file->length, + HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, + (hb_destroy_func_t) _hb_mapped_file_destroy); fail: close (fd); @@ -661,9 +716,9 @@ fail_without_close: if (unlikely (!file->contents)) goto fail; CloseHandle (fd); - return hb_blob_create (file->contents, file->length, - HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, - (hb_destroy_func_t) _hb_mapped_file_destroy); + return hb_blob_create_or_fail (file->contents, file->length, + HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, + (hb_destroy_func_t) _hb_mapped_file_destroy); fail: CloseHandle (fd); @@ -676,7 +731,7 @@ fail_without_close: It's used as a fallback for systems without mmap or to read from pipes */ unsigned long len = 0, allocated = BUFSIZ * 16; char *data = (char *) malloc (allocated); - if (unlikely (!data)) return hb_blob_get_empty (); + if (unlikely (!data)) return nullptr; FILE *fp = fopen (file_name, "rb"); if (unlikely (!fp)) goto fread_fail_without_close; @@ -706,13 +761,13 @@ fail_without_close: } fclose (fp); - return hb_blob_create (data, len, HB_MEMORY_MODE_WRITABLE, data, - (hb_destroy_func_t) free); + return hb_blob_create_or_fail (data, len, HB_MEMORY_MODE_WRITABLE, data, + (hb_destroy_func_t) free); fread_fail: fclose (fp); fread_fail_without_close: free (data); - return hb_blob_get_empty (); + return nullptr; } #endif /* !HB_NO_OPEN */ diff --git a/src/hb-blob.h b/src/hb-blob.h index 86f12788d..203f9e19d 100644 --- a/src/hb-blob.h +++ b/src/hb-blob.h @@ -90,9 +90,19 @@ hb_blob_create (const char *data, void *user_data, hb_destroy_func_t destroy); +HB_EXTERN hb_blob_t * +hb_blob_create_or_fail (const char *data, + unsigned int length, + hb_memory_mode_t mode, + void *user_data, + hb_destroy_func_t destroy); + HB_EXTERN hb_blob_t * hb_blob_create_from_file (const char *file_name); +HB_EXTERN hb_blob_t * +hb_blob_create_from_file_or_fail (const char *file_name); + /* Always creates with MEMORY_MODE_READONLY. * Even if the parent blob is writable, we don't * want the user of the sub-blob to be able to diff --git a/src/main.cc b/src/main.cc index e898e6e4b..1ab013cd3 100644 --- a/src/main.cc +++ b/src/main.cc @@ -33,12 +33,13 @@ #include "hb.h" #include "hb-ot.h" -#include -#include -#include +#include +#include +#include +#include #ifdef HB_NO_OPEN -#define hb_blob_create_from_file(x) hb_blob_get_empty () +#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty () #endif #if !defined(HB_NO_COLOR) && !defined(HB_NO_DRAW) && defined(HB_EXPERIMENTAL_API) @@ -505,7 +506,8 @@ main (int argc, char **argv) exit (1); } - hb_blob_t *blob = hb_blob_create_from_file (argv[1]); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]); + assert (blob); printf ("Opened font file %s: %d bytes long\n", argv[1], hb_blob_get_length (blob)); #ifndef MAIN_CC_NO_PRIVATE_API print_layout_info_using_private_api (blob); diff --git a/src/test-buffer-serialize.cc b/src/test-buffer-serialize.cc index 4a3d4bc10..8d5a69427 100644 --- a/src/test-buffer-serialize.cc +++ b/src/test-buffer-serialize.cc @@ -33,7 +33,7 @@ #endif #ifdef HB_NO_OPEN -#define hb_blob_create_from_file(x) hb_blob_get_empty () +#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty () #endif int @@ -48,7 +48,8 @@ main (int argc, char **argv) exit (1); } - hb_blob_t *blob = hb_blob_create_from_file (argv[1]); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]); + assert (blob); hb_face_t *face = hb_face_create (blob, 0 /* first face */); hb_blob_destroy (blob); blob = nullptr; diff --git a/src/test-gpos-size-params.cc b/src/test-gpos-size-params.cc index 549f5ae06..b96381ddc 100644 --- a/src/test-gpos-size-params.cc +++ b/src/test-gpos-size-params.cc @@ -30,7 +30,7 @@ #include "hb-ot.h" #ifdef HB_NO_OPEN -#define hb_blob_create_from_file(x) hb_blob_get_empty () +#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty () #endif int @@ -42,7 +42,8 @@ main (int argc, char **argv) } /* Create the face */ - hb_blob_t *blob = hb_blob_create_from_file (argv[1]); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]); + assert (blob); hb_face_t *face = hb_face_create (blob, 0 /* first face */); hb_blob_destroy (blob); blob = nullptr; diff --git a/src/test-gsub-would-substitute.cc b/src/test-gsub-would-substitute.cc index 508217dde..87123030e 100644 --- a/src/test-gsub-would-substitute.cc +++ b/src/test-gsub-would-substitute.cc @@ -34,7 +34,7 @@ #endif #ifdef HB_NO_OPEN -#define hb_blob_create_from_file(x) hb_blob_get_empty () +#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty () #endif int @@ -46,7 +46,8 @@ main (int argc, char **argv) } /* Create the face */ - hb_blob_t *blob = hb_blob_create_from_file (argv[1]); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]); + assert (blob); hb_face_t *face = hb_face_create (blob, 0 /* first face */); hb_blob_destroy (blob); blob = nullptr; diff --git a/src/test-ot-glyphname.cc b/src/test-ot-glyphname.cc index b2d4b3bcf..50d023166 100644 --- a/src/test-ot-glyphname.cc +++ b/src/test-ot-glyphname.cc @@ -28,7 +28,7 @@ #include "hb-ot.h" #ifdef HB_NO_OPEN -#define hb_blob_create_from_file(x) hb_blob_get_empty () +#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty () #endif int @@ -39,7 +39,8 @@ main (int argc, char **argv) exit (1); } - hb_blob_t *blob = hb_blob_create_from_file (argv[1]); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]); + assert (blob); hb_face_t *face = hb_face_create (blob, 0 /* first face */); hb_font_t *font = hb_font_create (face); hb_blob_destroy (blob); diff --git a/src/test-ot-meta.cc b/src/test-ot-meta.cc index f7a755cd5..7cf69dbcc 100644 --- a/src/test-ot-meta.cc +++ b/src/test-ot-meta.cc @@ -26,7 +26,7 @@ #include "hb-ot.h" #ifdef HB_NO_OPEN -#define hb_blob_create_from_file(x) hb_blob_get_empty () +#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty () #endif int @@ -37,7 +37,8 @@ main (int argc, char **argv) exit (1); } - hb_blob_t *blob = hb_blob_create_from_file (argv[1]); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]); + assert (blob); hb_face_t *face = hb_face_create (blob, 0 /* first face */); hb_blob_destroy (blob); blob = nullptr; diff --git a/src/test-ot-name.cc b/src/test-ot-name.cc index f331161fa..bfa654a7c 100644 --- a/src/test-ot-name.cc +++ b/src/test-ot-name.cc @@ -28,7 +28,7 @@ #include "hb-ot.h" #ifdef HB_NO_OPEN -#define hb_blob_create_from_file(x) hb_blob_get_empty () +#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty () #endif int @@ -39,7 +39,8 @@ main (int argc, char **argv) exit (1); } - hb_blob_t *blob = hb_blob_create_from_file (argv[1]); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]); + assert (blob); hb_face_t *face = hb_face_create (blob, 0 /* first face */); hb_blob_destroy (blob); blob = nullptr; diff --git a/src/test.cc b/src/test.cc index 347b71d38..d848cf106 100644 --- a/src/test.cc +++ b/src/test.cc @@ -31,7 +31,7 @@ #endif #ifdef HB_NO_OPEN -#define hb_blob_create_from_file(x) hb_blob_get_empty () +#define hb_blob_create_from_file_or_fail(x) hb_blob_get_empty () #endif int @@ -42,7 +42,8 @@ main (int argc, char **argv) exit (1); } - hb_blob_t *blob = hb_blob_create_from_file (argv[1]); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]); + assert (blob); printf ("Opened font file %s: %u bytes long\n", argv[1], hb_blob_get_length (blob)); /* Create the face */ diff --git a/test/api/hb-test.h b/test/api/hb-test.h index c5eb87086..7390e57a7 100644 --- a/test/api/hb-test.h +++ b/test/api/hb-test.h @@ -296,9 +296,9 @@ hb_test_open_font_file (const char *font_path) char *path = g_strdup (font_path); #endif - hb_blob_t *blob = hb_blob_create_from_file (path); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (path); hb_face_t *face; - if (hb_blob_get_length (blob) == 0) + if (!blob) g_error ("Font %s not found.", path); face = hb_face_create (blob, 0); diff --git a/test/fuzzing/main.cc b/test/fuzzing/main.cc index 9e892ebe1..3024eb574 100644 --- a/test/fuzzing/main.cc +++ b/test/fuzzing/main.cc @@ -1,16 +1,18 @@ #include "hb-fuzzer.hh" -#include +#include +#include int main (int argc, char **argv) { for (int i = 1; i < argc; i++) { - hb_blob_t *blob = hb_blob_create_from_file (argv[i]); + hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[i]); + assert (blob); - unsigned int len; + unsigned len = 0; const char *font_data = hb_blob_get_data (blob, &len); - printf ("%s%s\n", argv[i], len ? "" : " (note: not found or was empty)"); + printf ("%s (%u bytes)\n", argv[i], len); LLVMFuzzerTestOneInput ((const uint8_t *) font_data, len); diff --git a/util/options.cc b/util/options.cc index da2495025..42d3c6cc7 100644 --- a/util/options.cc +++ b/util/options.cc @@ -696,10 +696,10 @@ font_options_t::get_font () const #endif } - blob = hb_blob_create_from_file (font_path); + blob = hb_blob_create_from_file_or_fail (font_path); - if (blob == hb_blob_get_empty ()) - fail (false, "Couldn't read or find %s, or it was empty.", font_path); + if (!blob) + fail (false, "%s: Failed reading file", font_path); /* Create the face */ hb_face_t *face = hb_face_create (blob, face_index);