[HarfBuzz] harfbuzz-ng: Branch 'master' - 20 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Thu Apr 28 16:45:12 PDT 2011
TODO | 4
src/hb-blob.cc | 59 ++-
src/hb-blob.h | 12
src/hb-buffer-private.hh | 2
src/hb-buffer.cc | 82 +++--
src/hb-buffer.h | 10
src/hb-common.h | 11
src/hb-font.cc | 84 ++++-
src/hb-font.h | 47 ++-
src/hb-object-private.hh | 140 +++++++--
src/hb-open-type-private.hh | 2
src/hb-ot-layout-gsub-private.hh | 2
src/hb-private.hh | 143 ++++++++-
src/hb-unicode.cc | 25 +
src/hb-unicode.h | 12
test/Makefile.am | 1
test/hb-test.h | 155 +++++++++-
test/test-buffer.c | 593 ++++++++++++++++++++++++++++++++++++---
test/test-common.c | 14
test/test-unicode.c | 32 +-
20 files changed, 1240 insertions(+), 190 deletions(-)
New commits:
commit 13db3d40bfc09c68f9761a71435b1840b9d34099
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 19:44:45 2011 -0400
[test/buffer] Add UTF-16 tests
diff --git a/test/test-buffer.c b/test/test-buffer.c
index ba7f15e..f9dabe6 100644
--- a/test/test-buffer.c
+++ b/test/test-buffer.c
@@ -633,6 +633,46 @@ test_buffer_utf8_validity (gconstpointer user_data)
}
+typedef struct {
+ const uint16_t utf16[8];
+ const uint32_t codepoints[8];
+} utf16_test_t;
+
+/* note: we skip the first and last item from utf16 when adding to buffer */
+static const utf16_test_t utf16_tests[] = {
+ {{0x41, 0x004D, 0x0430, 0x4E8C, 0xD800, 0xDF02, 0x61} , {0x004D, 0x0430, 0x4E8C, 0x10302}},
+ {{0x41, 0xD800, 0xDF02, 0x61}, {0x10302}},
+ {{0x41, 0xD800, 0xDF02}, {-1}},
+ {{0x41, 0x61, 0xD800, 0xDF02}, {0x61, -1}},
+ {{0x41, 0xD800, 0x61, 0xDF02}, {-1, 0x61}},
+ {{0x41, 0x61}, {}}
+};
+
+static void
+test_buffer_utf16 (gconstpointer user_data)
+{
+ const utf16_test_t *test = user_data;
+ hb_buffer_t *b;
+ hb_glyph_info_t *glyphs;
+ unsigned int u_len, chars, i, len;
+
+ for (u_len = 0; test->utf16[u_len]; u_len++)
+ ;
+ for (chars = 0; test->codepoints[chars]; chars++)
+ ;
+
+ b = hb_buffer_create (0);
+ hb_buffer_add_utf16 (b, test->utf16, u_len, 1, u_len - 2);
+
+ glyphs = hb_buffer_get_glyph_infos (b, &len);
+ g_assert_cmpint (len, ==, chars);
+ for (i = 0; i < chars; i++)
+ g_assert_cmphex (glyphs[i].codepoint, ==, test->codepoints[i]);
+
+ hb_buffer_destroy (b);
+}
+
+
int
main (int argc, char **argv)
{
@@ -658,7 +698,6 @@ main (int argc, char **argv)
hb_test_add_data_flavor (&utf8_tests[i], flavor, test_buffer_utf8);
g_free (flavor);
}
-
for (i = 0; i < G_N_ELEMENTS (utf8_validity_tests); i++)
{
char *flavor = g_strdup_printf ("%d", i);
@@ -666,7 +705,12 @@ main (int argc, char **argv)
g_free (flavor);
}
- /* XXX test invalid UTF-16 text input */
+ for (i = 0; i < G_N_ELEMENTS (utf16_tests); i++)
+ {
+ char *flavor = g_strdup_printf ("%d", i);
+ hb_test_add_data_flavor (&utf16_tests[i], flavor, test_buffer_utf16);
+ g_free (flavor);
+ }
return hb_test_run();
}
commit 243673d601588a6f704ceafbff5dd5cdf66c47b7
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 19:37:51 2011 -0400
[test/buffer] Add more extensive UTF-8 test data from glib
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index c3e9be0..1e49c7a 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -624,7 +624,7 @@ hb_utf8_next (const uint8_t *text,
uint8_t c = *text;
unsigned int mask, len;
- /* TODO check for overlong sequences? also: optimize? */
+ /* TODO check for overlong sequences? */
UTF8_COMPUTE (c, mask, len);
if (unlikely (!len || (unsigned int) (end - text) < len)) {
diff --git a/test/test-buffer.c b/test/test-buffer.c
index e0a582c..ba7f15e 100644
--- a/test/test-buffer.c
+++ b/test/test-buffer.c
@@ -33,20 +33,6 @@ static const char utf8[10] = "ab\360\240\200\200defg";
static const uint16_t utf16[8] = {'a', 'b', 0xD840, 0xDC00, 'd', 'e', 'f', 'g'};
static const uint32_t utf32[7] = {'a', 'b', 0x20000, 'd', 'e', 'f', 'g'};
-typedef struct {
- const char utf8[8];
- const uint32_t codepoints[8];
-} utf8_test_t;
-
-
-/* note: we skip the first and last byte when adding to buffer */
-static const utf8_test_t utf8_tests[] = {
- {"a\303\207", {-1}},
- {"a\303\207b", {0xC7}},
- {"ab\303cd", {'b', -1, 'c'}}
-};
-
-
typedef enum {
BUFFER_EMPTY,
@@ -330,6 +316,20 @@ test_buffer_allocation (fixture_t *fixture, gconstpointer user_data)
g_assert (hb_buffer_allocation_successful (fixture->b));
}
+
+typedef struct {
+ const char utf8[8];
+ const uint32_t codepoints[8];
+} utf8_test_t;
+
+/* note: we skip the first and last byte when adding to buffer */
+static const utf8_test_t utf8_tests[] = {
+ {"a\303\207", {-1}},
+ {"a\303\207b", {0xC7}},
+ {"ab\303cd", {'b', -1, 'c'}},
+ {"ab\303\302\301cd", {'b', -1, -1, -1, 'c'}}
+};
+
static void
test_buffer_utf8 (gconstpointer user_data)
{
@@ -354,6 +354,285 @@ test_buffer_utf8 (gconstpointer user_data)
}
+
+/* Following test table is adapted from glib/glib/tests/utf8-validate.c
+ * with relicensing permission from Matthias Clasen. */
+
+typedef struct {
+ const char *text;
+ int max_len;
+ unsigned int offset;
+ gboolean valid;
+} utf8_validity_test_t;
+
+static const utf8_validity_test_t utf8_validity_tests[] = {
+ /* some tests to check max_len handling */
+ /* length 1 */
+ { "abcde", -1, 5, TRUE },
+ { "abcde", 3, 3, TRUE },
+ { "abcde", 5, 5, TRUE },
+ /* length 2 */
+ { "\xc2\xa9\xc2\xa9\xc2\xa9", -1, 6, TRUE },
+ { "\xc2\xa9\xc2\xa9\xc2\xa9", 1, 0, FALSE },
+ { "\xc2\xa9\xc2\xa9\xc2\xa9", 2, 2, TRUE },
+ { "\xc2\xa9\xc2\xa9\xc2\xa9", 3, 2, FALSE },
+ { "\xc2\xa9\xc2\xa9\xc2\xa9", 4, 4, TRUE },
+ { "\xc2\xa9\xc2\xa9\xc2\xa9", 5, 4, FALSE },
+ { "\xc2\xa9\xc2\xa9\xc2\xa9", 6, 6, TRUE },
+ /* length 3 */
+ { "\xe2\x89\xa0\xe2\x89\xa0", -1, 6, TRUE },
+ { "\xe2\x89\xa0\xe2\x89\xa0", 1, 0, FALSE },
+ { "\xe2\x89\xa0\xe2\x89\xa0", 2, 0, FALSE },
+ { "\xe2\x89\xa0\xe2\x89\xa0", 3, 3, TRUE },
+ { "\xe2\x89\xa0\xe2\x89\xa0", 4, 3, FALSE },
+ { "\xe2\x89\xa0\xe2\x89\xa0", 5, 3, FALSE },
+ { "\xe2\x89\xa0\xe2\x89\xa0", 6, 6, TRUE },
+
+ /* examples from http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt */
+ /* greek 'kosme' */
+ { "\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5", -1, 11, TRUE },
+ /* first sequence of each length */
+ { "\x00", -1, 0, TRUE },
+ { "\xc2\x80", -1, 2, TRUE },
+ { "\xe0\xa0\x80", -1, 3, TRUE },
+ { "\xf0\x90\x80\x80", -1, 4, TRUE },
+ { "\xf8\x88\x80\x80\x80", -1, 0, FALSE },
+ { "\xfc\x84\x80\x80\x80\x80", -1, 0, FALSE },
+ /* last sequence of each length */
+ { "\x7f", -1, 1, TRUE },
+ { "\xdf\xbf", -1, 2, TRUE },
+ { "\xef\xbf\xbf", -1, 0, TRUE },
+ { "\xf7\xbf\xbf\xbf", -1, 0, TRUE },
+ { "\xfb\xbf\xbf\xbf\xbf", -1, 0, FALSE },
+ { "\xfd\xbf\xbf\xbf\xbf\xbf", -1, 0, FALSE },
+ /* other boundary conditions */
+ { "\xed\x9f\xbf", -1, 3, TRUE },
+ { "\xee\x80\x80", -1, 3, TRUE },
+ { "\xef\xbf\xbd", -1, 3, TRUE },
+ { "\xf4\x8f\xbf\xbf", -1, 0, TRUE },
+ /* malformed sequences */
+ /* continuation bytes */
+ { "\x80", -1, 0, FALSE },
+ { "\xbf", -1, 0, FALSE },
+ { "\x80\xbf", -1, 0, FALSE },
+ { "\x80\xbf\x80", -1, 0, FALSE },
+ { "\x80\xbf\x80\xbf", -1, 0, FALSE },
+ { "\x80\xbf\x80\xbf\x80", -1, 0, FALSE },
+ { "\x80\xbf\x80\xbf\x80\xbf", -1, 0, FALSE },
+ { "\x80\xbf\x80\xbf\x80\xbf\x80", -1, 0, FALSE },
+
+ /* all possible continuation byte */
+ { "\x80", -1, 0, FALSE },
+ { "\x81", -1, 0, FALSE },
+ { "\x82", -1, 0, FALSE },
+ { "\x83", -1, 0, FALSE },
+ { "\x84", -1, 0, FALSE },
+ { "\x85", -1, 0, FALSE },
+ { "\x86", -1, 0, FALSE },
+ { "\x87", -1, 0, FALSE },
+ { "\x88", -1, 0, FALSE },
+ { "\x89", -1, 0, FALSE },
+ { "\x8a", -1, 0, FALSE },
+ { "\x8b", -1, 0, FALSE },
+ { "\x8c", -1, 0, FALSE },
+ { "\x8d", -1, 0, FALSE },
+ { "\x8e", -1, 0, FALSE },
+ { "\x8f", -1, 0, FALSE },
+ { "\x90", -1, 0, FALSE },
+ { "\x91", -1, 0, FALSE },
+ { "\x92", -1, 0, FALSE },
+ { "\x93", -1, 0, FALSE },
+ { "\x94", -1, 0, FALSE },
+ { "\x95", -1, 0, FALSE },
+ { "\x96", -1, 0, FALSE },
+ { "\x97", -1, 0, FALSE },
+ { "\x98", -1, 0, FALSE },
+ { "\x99", -1, 0, FALSE },
+ { "\x9a", -1, 0, FALSE },
+ { "\x9b", -1, 0, FALSE },
+ { "\x9c", -1, 0, FALSE },
+ { "\x9d", -1, 0, FALSE },
+ { "\x9e", -1, 0, FALSE },
+ { "\x9f", -1, 0, FALSE },
+ { "\xa0", -1, 0, FALSE },
+ { "\xa1", -1, 0, FALSE },
+ { "\xa2", -1, 0, FALSE },
+ { "\xa3", -1, 0, FALSE },
+ { "\xa4", -1, 0, FALSE },
+ { "\xa5", -1, 0, FALSE },
+ { "\xa6", -1, 0, FALSE },
+ { "\xa7", -1, 0, FALSE },
+ { "\xa8", -1, 0, FALSE },
+ { "\xa9", -1, 0, FALSE },
+ { "\xaa", -1, 0, FALSE },
+ { "\xab", -1, 0, FALSE },
+ { "\xac", -1, 0, FALSE },
+ { "\xad", -1, 0, FALSE },
+ { "\xae", -1, 0, FALSE },
+ { "\xaf", -1, 0, FALSE },
+ { "\xb0", -1, 0, FALSE },
+ { "\xb1", -1, 0, FALSE },
+ { "\xb2", -1, 0, FALSE },
+ { "\xb3", -1, 0, FALSE },
+ { "\xb4", -1, 0, FALSE },
+ { "\xb5", -1, 0, FALSE },
+ { "\xb6", -1, 0, FALSE },
+ { "\xb7", -1, 0, FALSE },
+ { "\xb8", -1, 0, FALSE },
+ { "\xb9", -1, 0, FALSE },
+ { "\xba", -1, 0, FALSE },
+ { "\xbb", -1, 0, FALSE },
+ { "\xbc", -1, 0, FALSE },
+ { "\xbd", -1, 0, FALSE },
+ { "\xbe", -1, 0, FALSE },
+ { "\xbf", -1, 0, FALSE },
+ /* lone start characters */
+ { "\xc0\x20", -1, 0, FALSE },
+ { "\xc1\x20", -1, 0, FALSE },
+ { "\xc2\x20", -1, 0, FALSE },
+ { "\xc3\x20", -1, 0, FALSE },
+ { "\xc4\x20", -1, 0, FALSE },
+ { "\xc5\x20", -1, 0, FALSE },
+ { "\xc6\x20", -1, 0, FALSE },
+ { "\xc7\x20", -1, 0, FALSE },
+ { "\xc8\x20", -1, 0, FALSE },
+ { "\xc9\x20", -1, 0, FALSE },
+ { "\xca\x20", -1, 0, FALSE },
+ { "\xcb\x20", -1, 0, FALSE },
+ { "\xcc\x20", -1, 0, FALSE },
+ { "\xcd\x20", -1, 0, FALSE },
+ { "\xce\x20", -1, 0, FALSE },
+ { "\xcf\x20", -1, 0, FALSE },
+ { "\xd0\x20", -1, 0, FALSE },
+ { "\xd1\x20", -1, 0, FALSE },
+ { "\xd2\x20", -1, 0, FALSE },
+ { "\xd3\x20", -1, 0, FALSE },
+ { "\xd4\x20", -1, 0, FALSE },
+ { "\xd5\x20", -1, 0, FALSE },
+ { "\xd6\x20", -1, 0, FALSE },
+ { "\xd7\x20", -1, 0, FALSE },
+ { "\xd8\x20", -1, 0, FALSE },
+ { "\xd9\x20", -1, 0, FALSE },
+ { "\xda\x20", -1, 0, FALSE },
+ { "\xdb\x20", -1, 0, FALSE },
+ { "\xdc\x20", -1, 0, FALSE },
+ { "\xdd\x20", -1, 0, FALSE },
+ { "\xde\x20", -1, 0, FALSE },
+ { "\xdf\x20", -1, 0, FALSE },
+ { "\xe0\x20", -1, 0, FALSE },
+ { "\xe1\x20", -1, 0, FALSE },
+ { "\xe2\x20", -1, 0, FALSE },
+ { "\xe3\x20", -1, 0, FALSE },
+ { "\xe4\x20", -1, 0, FALSE },
+ { "\xe5\x20", -1, 0, FALSE },
+ { "\xe6\x20", -1, 0, FALSE },
+ { "\xe7\x20", -1, 0, FALSE },
+ { "\xe8\x20", -1, 0, FALSE },
+ { "\xe9\x20", -1, 0, FALSE },
+ { "\xea\x20", -1, 0, FALSE },
+ { "\xeb\x20", -1, 0, FALSE },
+ { "\xec\x20", -1, 0, FALSE },
+ { "\xed\x20", -1, 0, FALSE },
+ { "\xee\x20", -1, 0, FALSE },
+ { "\xef\x20", -1, 0, FALSE },
+ { "\xf0\x20", -1, 0, FALSE },
+ { "\xf1\x20", -1, 0, FALSE },
+ { "\xf2\x20", -1, 0, FALSE },
+ { "\xf3\x20", -1, 0, FALSE },
+ { "\xf4\x20", -1, 0, FALSE },
+ { "\xf5\x20", -1, 0, FALSE },
+ { "\xf6\x20", -1, 0, FALSE },
+ { "\xf7\x20", -1, 0, FALSE },
+ { "\xf8\x20", -1, 0, FALSE },
+ { "\xf9\x20", -1, 0, FALSE },
+ { "\xfa\x20", -1, 0, FALSE },
+ { "\xfb\x20", -1, 0, FALSE },
+ { "\xfc\x20", -1, 0, FALSE },
+ { "\xfd\x20", -1, 0, FALSE },
+ /* missing continuation bytes */
+ { "\x20\xc0", -1, 1, FALSE },
+ { "\x20\xe0\x80", -1, 1, FALSE },
+ { "\x20\xf0\x80\x80", -1, 1, FALSE },
+ { "\x20\xf8\x80\x80\x80", -1, 1, FALSE },
+ { "\x20\xfc\x80\x80\x80\x80", -1, 1, FALSE },
+ { "\x20\xdf", -1, 1, FALSE },
+ { "\x20\xef\xbf", -1, 1, FALSE },
+ { "\x20\xf7\xbf\xbf", -1, 1, FALSE },
+ { "\x20\xfb\xbf\xbf\xbf", -1, 1, FALSE },
+ { "\x20\xfd\xbf\xbf\xbf\xbf", -1, 1, FALSE },
+ /* impossible bytes */
+ { "\x20\xfe\x20", -1, 1, FALSE },
+ { "\x20\xff\x20", -1, 1, FALSE },
+#if 0
+ /* XXX fix these, or document that we don't detect them? */
+ /* overlong sequences */
+ { "\x20\xc0\xaf\x20", -1, 1, FALSE },
+ { "\x20\xe0\x80\xaf\x20", -1, 1, FALSE },
+ { "\x20\xf0\x80\x80\xaf\x20", -1, 1, FALSE },
+ { "\x20\xf8\x80\x80\x80\xaf\x20", -1, 1, FALSE },
+ { "\x20\xfc\x80\x80\x80\x80\xaf\x20", -1, 1, FALSE },
+ { "\x20\xc1\xbf\x20", -1, 1, FALSE },
+ { "\x20\xe0\x9f\xbf\x20", -1, 1, FALSE },
+ { "\x20\xf0\x8f\xbf\xbf\x20", -1, 1, FALSE },
+ { "\x20\xf8\x87\xbf\xbf\xbf\x20", -1, 1, FALSE },
+ { "\x20\xfc\x83\xbf\xbf\xbf\xbf\x20", -1, 1, FALSE },
+ { "\x20\xc0\x80\x20", -1, 1, FALSE },
+ { "\x20\xe0\x80\x80\x20", -1, 1, FALSE },
+ { "\x20\xf0\x80\x80\x80\x20", -1, 1, FALSE },
+ { "\x20\xf8\x80\x80\x80\x80\x20", -1, 1, FALSE },
+ { "\x20\xfc\x80\x80\x80\x80\x80\x20", -1, 1, FALSE },
+ /* illegal code positions */
+ { "\x20\xed\xa0\x80\x20", -1, 1, FALSE },
+ { "\x20\xed\xad\xbf\x20", -1, 1, FALSE },
+ { "\x20\xed\xae\x80\x20", -1, 1, FALSE },
+ { "\x20\xed\xaf\xbf\x20", -1, 1, FALSE },
+ { "\x20\xed\xb0\x80\x20", -1, 1, FALSE },
+ { "\x20\xed\xbe\x80\x20", -1, 1, FALSE },
+ { "\x20\xed\xbf\xbf\x20", -1, 1, FALSE },
+ { "\x20\xed\xa0\x80\xed\xb0\x80\x20", -1, 1, FALSE },
+ { "\x20\xed\xa0\x80\xed\xbf\xbf\x20", -1, 1, FALSE },
+ { "\x20\xed\xad\xbf\xed\xb0\x80\x20", -1, 1, FALSE },
+ { "\x20\xed\xad\xbf\xed\xbf\xbf\x20", -1, 1, FALSE },
+ { "\x20\xed\xae\x80\xed\xb0\x80\x20", -1, 1, FALSE },
+ { "\x20\xed\xae\x80\xed\xbf\xbf\x20", -1, 1, FALSE },
+ { "\x20\xed\xaf\xbf\xed\xb0\x80\x20", -1, 1, FALSE },
+ { "\x20\xed\xaf\xbf\xed\xbf\xbf\x20", -1, 1, FALSE },
+ { "\x20\xef\xbf\xbe\x20", -1, 1, FALSE },
+ { "\x20\xef\xbf\xbf\x20", -1, 1, FALSE },
+#endif
+ { "", -1, 0, TRUE }
+};
+
+static void
+test_buffer_utf8_validity (gconstpointer user_data)
+{
+ const utf8_validity_test_t *test = user_data;
+ hb_buffer_t *b;
+ hb_glyph_info_t *glyphs;
+ unsigned int text_bytes, segment_bytes, i, len;
+
+ text_bytes = strlen (test->text);
+ if (test->max_len == -1)
+ segment_bytes = text_bytes;
+ else
+ segment_bytes = test->max_len;
+
+ b = hb_buffer_create (0);
+ hb_buffer_add_utf8 (b, test->text, text_bytes, 0, segment_bytes);
+
+ glyphs = hb_buffer_get_glyph_infos (b, &len);
+ for (i = 0; i < len; i++)
+ if (glyphs[i].codepoint == (hb_codepoint_t) -1)
+ break;
+
+ g_assert (test->valid ? i == len : i < len);
+ if (!test->valid)
+ g_assert (glyphs[i].cluster == test->offset);
+
+ hb_buffer_destroy (b);
+}
+
+
int
main (int argc, char **argv)
{
@@ -379,7 +658,15 @@ main (int argc, char **argv)
hb_test_add_data_flavor (&utf8_tests[i], flavor, test_buffer_utf8);
g_free (flavor);
}
- /* XXX test invalid UTF-8 / UTF-16 text input (also overlong sequences) */
+
+ for (i = 0; i < G_N_ELEMENTS (utf8_validity_tests); i++)
+ {
+ char *flavor = g_strdup_printf ("%d", i);
+ hb_test_add_data_flavor (&utf8_validity_tests[i], flavor, test_buffer_utf8_validity);
+ g_free (flavor);
+ }
+
+ /* XXX test invalid UTF-16 text input */
return hb_test_run();
}
commit dfec67f958482e5c3bb01e06b08694cd4ded6f66
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 18:34:42 2011 -0400
[test/buffer] Add initial utf-8 tests
diff --git a/test/hb-test.h b/test/hb-test.h
index 44c9405..81aba66 100644
--- a/test/hb-test.h
+++ b/test/hb-test.h
@@ -140,7 +140,30 @@ hb_test_add_func_flavor (const char *test_path,
hb_test_add_func (path, test_func);
g_free (path);
}
-#define hb_test_add_flavor(Func, Flavor) hb_test_add_func (#Func, Flavor, Func)
+#define hb_test_add_flavor(Flavor, Func) hb_test_add_func (#Func, Flavor, Func)
+
+static inline void
+hb_test_add_data_func (const char *test_path,
+ gconstpointer test_data,
+ GTestDataFunc test_func)
+{
+ char *normal_path = hb_test_normalize_path (test_path);
+ g_test_add_data_func (normal_path, test_data, test_func);
+ g_free (normal_path);
+}
+#define hb_test_add_data(Func, UserData) hb_test_add_data_func (#Func, UserData, Func)
+
+static inline void
+hb_test_add_data_func_flavor (const char *test_path,
+ const char *flavor,
+ gconstpointer test_data,
+ GTestDataFunc test_func)
+{
+ char *path = g_strdup_printf ("%s/%s", test_path, flavor);
+ hb_test_add_data_func (path, test_data, test_func);
+ g_free (path);
+}
+#define hb_test_add_data_flavor(UserData, Flavor, Func) hb_test_add_data_func_flavor (#Func, Flavor, UserData, Func)
static inline void
diff --git a/test/test-buffer.c b/test/test-buffer.c
index 1499550..e0a582c 100644
--- a/test/test-buffer.c
+++ b/test/test-buffer.c
@@ -33,6 +33,21 @@ static const char utf8[10] = "ab\360\240\200\200defg";
static const uint16_t utf16[8] = {'a', 'b', 0xD840, 0xDC00, 'd', 'e', 'f', 'g'};
static const uint32_t utf32[7] = {'a', 'b', 0x20000, 'd', 'e', 'f', 'g'};
+typedef struct {
+ const char utf8[8];
+ const uint32_t codepoints[8];
+} utf8_test_t;
+
+
+/* note: we skip the first and last byte when adding to buffer */
+static const utf8_test_t utf8_tests[] = {
+ {"a\303\207", {-1}},
+ {"a\303\207b", {0xC7}},
+ {"ab\303cd", {'b', -1, 'c'}}
+};
+
+
+
typedef enum {
BUFFER_EMPTY,
BUFFER_ONE_BY_ONE,
@@ -315,11 +330,34 @@ test_buffer_allocation (fixture_t *fixture, gconstpointer user_data)
g_assert (hb_buffer_allocation_successful (fixture->b));
}
+static void
+test_buffer_utf8 (gconstpointer user_data)
+{
+ const utf8_test_t *test = user_data;
+ hb_buffer_t *b;
+ hb_glyph_info_t *glyphs;
+ unsigned int bytes, chars, i, len;
+
+ bytes = strlen (test->utf8);
+ for (chars = 0; test->codepoints[chars]; chars++)
+ ;
+
+ b = hb_buffer_create (0);
+ hb_buffer_add_utf8 (b, test->utf8, bytes, 1, bytes - 2);
+
+ glyphs = hb_buffer_get_glyph_infos (b, &len);
+ g_assert_cmpint (len, ==, chars);
+ for (i = 0; i < chars; i++)
+ g_assert_cmphex (glyphs[i].codepoint, ==, test->codepoints[i]);
+
+ hb_buffer_destroy (b);
+}
+
int
main (int argc, char **argv)
{
- int i;
+ unsigned int i;
hb_test_init (&argc, &argv);
@@ -335,6 +373,12 @@ main (int argc, char **argv)
hb_test_add_fixture (fixture, GINT_TO_POINTER (BUFFER_EMPTY), test_buffer_allocation);
+ for (i = 0; i < G_N_ELEMENTS (utf8_tests); i++)
+ {
+ char *flavor = g_strdup_printf ("%d", i);
+ hb_test_add_data_flavor (&utf8_tests[i], flavor, test_buffer_utf8);
+ g_free (flavor);
+ }
/* XXX test invalid UTF-8 / UTF-16 text input (also overlong sequences) */
return hb_test_run();
commit aafe395ab550d3ba2fabc69155662e87d45e74a8
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 17:10:44 2011 -0400
Add test suite infrastructure
Wraps around glib for convenience and ease of use.
diff --git a/test/Makefile.am b/test/Makefile.am
index e4fdb20..e48708b 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -7,6 +7,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/ $(GLIB_CFLAGS)
LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS)
check_PROGRAMS = $(TEST_PROGS)
+noinst_PROGRAMS = $(TEST_PROGS)
TEST_PROGS += \
test-buffer \
diff --git a/test/hb-test.h b/test/hb-test.h
index 2c04642..44c9405 100644
--- a/test/hb-test.h
+++ b/test/hb-test.h
@@ -27,12 +27,10 @@
#ifndef HB_TEST_H
#define HB_TEST_H
-#include <hb.h>
#include <hb-glib.h>
-#include <glib.h>
-
#include <stdlib.h>
+#include <string.h>
HB_BEGIN_DECLS
@@ -40,6 +38,30 @@ HB_BEGIN_DECLS
#undef G_DISABLE_ASSERT
+/* Misc */
+
+/* This is too ugly to be public API, but quite handy. */
+#define HB_TAG_CHAR4(s) (HB_TAG(((const char *) s)[0], \
+ ((const char *) s)[1], \
+ ((const char *) s)[2], \
+ ((const char *) s)[3]))
+
+
+/* Helpers */
+
+static inline void
+hb_test_init (int *argc, char ***argv)
+{
+ g_test_init (argc, argv, NULL);
+}
+
+static inline int
+hb_test_run (void)
+{
+ return g_test_run ();
+}
+
+
/* Bugzilla helpers */
static inline void
@@ -78,13 +100,105 @@ hb_test_bug_redhat (unsigned int number)
}
-/* Misc */
+/* Wrap glib test functions to simplify. Should have been in glib already. */
+
+/* Drops the "test_" prefix and converts '_' to '/'.
+ * Essentially builds test path from function name. */
+static inline char *
+hb_test_normalize_path (const char *path)
+{
+ char *s, *p;
+
+ g_assert (0 == strncmp (path, "test_", 5));
+ path += 4;
+
+ s = g_strdup (path);
+ for (p = s; *p; p++)
+ if (*p == '_')
+ *p = '/';
+
+ return s;
+}
+
+
+static inline void
+hb_test_add_func (const char *test_path,
+ GTestFunc test_func)
+{
+ char *normal_path = hb_test_normalize_path (test_path);
+ g_test_add_func (normal_path, test_func);
+ g_free (normal_path);
+}
+#define hb_test_add(Func) hb_test_add_func (#Func, Func)
+
+static inline void
+hb_test_add_func_flavor (const char *test_path,
+ const char *flavor,
+ GTestFunc test_func)
+{
+ char *path = g_strdup_printf ("%s/%s", test_path, flavor);
+ hb_test_add_func (path, test_func);
+ g_free (path);
+}
+#define hb_test_add_flavor(Func, Flavor) hb_test_add_func (#Func, Flavor, Func)
+
+
+static inline void
+hb_test_add_vtable (const char *test_path,
+ gsize data_size,
+ gconstpointer test_data,
+ GTestFixtureFunc data_setup,
+ GTestFixtureFunc data_test,
+ GTestFixtureFunc data_teardown)
+{
+ char *normal_path = hb_test_normalize_path (test_path);
+ g_test_add_vtable (normal_path, data_size, test_data, data_setup, data_test, data_teardown);
+ g_free (normal_path);
+}
+#define hb_test_add_fixture(FixturePrefix, UserData, Func) \
+G_STMT_START { \
+ typedef G_PASTE (FixturePrefix, _t) Fixture; \
+ void (*add_vtable) (const char*, gsize, gconstpointer, \
+ void (*) (Fixture*, gconstpointer), \
+ void (*) (Fixture*, gconstpointer), \
+ void (*) (Fixture*, gconstpointer)) \
+ = (void (*) (const gchar *, gsize, gconstpointer, \
+ void (*) (Fixture*, gconstpointer), \
+ void (*) (Fixture*, gconstpointer), \
+ void (*) (Fixture*, gconstpointer))) hb_test_add_vtable; \
+ add_vtable (#Func, sizeof (G_PASTE (FixturePrefix, _t)), UserData, \
+ G_PASTE (FixturePrefix, _init), Func, G_PASTE (FixturePrefix, _finish)); \
+} G_STMT_END
+
+static inline void
+hb_test_add_vtable_flavor (const char *test_path,
+ const char *flavor,
+ gsize data_size,
+ gconstpointer test_data,
+ GTestFixtureFunc data_setup,
+ GTestFixtureFunc data_test,
+ GTestFixtureFunc data_teardown)
+{
+ char *path = g_strdup_printf ("%s/%s", test_path, flavor);
+ hb_test_add_vtable (path, data_size, test_data, data_setup, data_test, data_teardown);
+ g_free (path);
+}
+#define hb_test_add_fixture_flavor(FixturePrefix, UserData, Flavor, Func) \
+G_STMT_START { \
+ typedef G_PASTE (FixturePrefix, _t) Fixture; \
+ void (*add_vtable) (const char*, const char *, gsize, gconstpointer, \
+ void (*) (Fixture*, gconstpointer), \
+ void (*) (Fixture*, gconstpointer), \
+ void (*) (Fixture*, gconstpointer)) \
+ = (void (*) (const gchar *, const char *, gsize, gconstpointer, \
+ void (*) (Fixture*, gconstpointer), \
+ void (*) (Fixture*, gconstpointer), \
+ void (*) (Fixture*, gconstpointer))) hb_test_add_vtable_flavor; \
+ add_vtable (#Func, Flavor, sizeof (G_PASTE (FixturePrefix, _t)), UserData, \
+ G_PASTE (FixturePrefix, _init), Func, G_PASTE (FixturePrefix, _finish)); \
+} G_STMT_END
+
-/* This is too ugly to be public API, but quite handy. */
-#define HB_TAG_CHAR4(s) (HB_TAG(((const char *) s)[0], \
- ((const char *) s)[1], \
- ((const char *) s)[2], \
- ((const char *) s)[3]))
HB_END_DECLS
#endif /* HB_TEST_H */
diff --git a/test/test-buffer.c b/test/test-buffer.c
index 7da4c92..1499550 100644
--- a/test/test-buffer.c
+++ b/test/test-buffer.c
@@ -89,7 +89,7 @@ fixture_init (fixture_t *fixture, gconstpointer user_data)
}
static void
-fixture_fini (fixture_t *fixture, gconstpointer user_data)
+fixture_finish (fixture_t *fixture, gconstpointer user_data)
{
hb_buffer_destroy (fixture->b);
}
@@ -321,24 +321,21 @@ main (int argc, char **argv)
{
int i;
- g_test_init (&argc, &argv, NULL);
-
- for (i = 0; i < BUFFER_NUM_TYPES; i++) {
-#define TEST_ADD(path, func) \
- G_STMT_START { \
- char *s = g_strdup_printf ("%s/%s", path, buffer_names[i]); \
- g_test_add (s, fixture_t, GINT_TO_POINTER (i), fixture_init, func, fixture_fini); \
- g_free (s); \
- } G_STMT_END
- TEST_ADD ("/buffer/properties", test_buffer_properties);
- TEST_ADD ("/buffer/contents", test_buffer_contents);
- TEST_ADD ("/buffer/positions", test_buffer_positions);
-#undef TEST_ADD
+ hb_test_init (&argc, &argv);
+
+ for (i = 0; i < BUFFER_NUM_TYPES; i++)
+ {
+ const void *buffer_type = GINT_TO_POINTER (i);
+ const char *buffer_name = buffer_names[i];
+
+ hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_properties);
+ hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_contents);
+ hb_test_add_fixture_flavor (fixture, buffer_type, buffer_name, test_buffer_positions);
}
- g_test_add ("/buffer/allocation", fixture_t, GINT_TO_POINTER (BUFFER_EMPTY), fixture_init, test_buffer_allocation, fixture_fini);
+ hb_test_add_fixture (fixture, GINT_TO_POINTER (BUFFER_EMPTY), test_buffer_allocation);
/* XXX test invalid UTF-8 / UTF-16 text input (also overlong sequences) */
- return g_test_run();
+ return hb_test_run();
}
diff --git a/test/test-common.c b/test/test-common.c
index d232740..31661f0 100644
--- a/test/test-common.c
+++ b/test/test-common.c
@@ -173,13 +173,13 @@ test_types_language (void)
int
main (int argc, char **argv)
{
- g_test_init (&argc, &argv, NULL);
+ hb_test_init (&argc, &argv);
- g_test_add_func ("/types/int", test_types_int);
- g_test_add_func ("/types/direction", test_types_direction);
- g_test_add_func ("/types/tag", test_types_tag);
- g_test_add_func ("/types/script", test_types_script);
- g_test_add_func ("/types/language", test_types_language);
+ hb_test_add (test_types_int);
+ hb_test_add (test_types_direction);
+ hb_test_add (test_types_tag);
+ hb_test_add (test_types_script);
+ hb_test_add (test_types_language);
- return g_test_run();
+ return hb_test_run();
}
diff --git a/test/test-unicode.c b/test/test-unicode.c
index c696341..30a89be 100644
--- a/test/test-unicode.c
+++ b/test/test-unicode.c
@@ -29,7 +29,7 @@
/* This file tests the unicode virtual functions interface */
static void
-test_nil (void)
+test_unicode_nil (void)
{
hb_unicode_funcs_t *uf = hb_unicode_funcs_create (NULL);
@@ -39,7 +39,7 @@ test_nil (void)
}
static void
-test_glib (void)
+test_unicode_glib (void)
{
hb_unicode_funcs_t *uf = hb_glib_get_unicode_funcs ();
@@ -47,7 +47,7 @@ test_glib (void)
}
static void
-test_default (void)
+test_unicode_default (void)
{
hb_unicode_funcs_t *uf = hb_unicode_funcs_get_default ();
@@ -85,7 +85,7 @@ simple_get_script (hb_unicode_funcs_t *ufuncs,
}
static void
-test_custom (void)
+test_unicode_custom (void)
{
hb_unicode_funcs_t *uf = hb_unicode_funcs_create (NULL);
@@ -120,7 +120,7 @@ a_is_for_arabic_get_script (hb_unicode_funcs_t *ufuncs,
}
static void
-test_subclassing_nil (void)
+test_unicode_subclassing_nil (void)
{
hb_unicode_funcs_t *uf, *aa;
@@ -143,7 +143,7 @@ test_subclassing_nil (void)
}
static void
-test_subclassing_glib (void)
+test_unicode_subclassing_glib (void)
{
hb_unicode_funcs_t *uf, *aa;
@@ -163,7 +163,7 @@ test_subclassing_glib (void)
}
static void
-test_subclassing_deep (void)
+test_unicode_subclassing_deep (void)
{
hb_unicode_funcs_t *uf, *aa;
@@ -195,18 +195,18 @@ test_subclassing_deep (void)
int
main (int argc, char **argv)
{
- g_test_init (&argc, &argv, NULL);
+ hb_test_init (&argc, &argv);
- g_test_add_func ("/unicode/nil", test_nil);
- g_test_add_func ("/unicode/glib", test_glib);
- g_test_add_func ("/unicode/default", test_default);
- g_test_add_func ("/unicode/custom", test_custom);
- g_test_add_func ("/unicode/subclassing/nil", test_subclassing_nil);
- g_test_add_func ("/unicode/subclassing/glib", test_subclassing_glib);
- g_test_add_func ("/unicode/subclassing/deep", test_subclassing_deep);
+ hb_test_add (test_unicode_nil);
+ hb_test_add (test_unicode_glib);
+ hb_test_add (test_unicode_default);
+ hb_test_add (test_unicode_custom);
+ hb_test_add (test_unicode_subclassing_nil);
+ hb_test_add (test_unicode_subclassing_glib);
+ hb_test_add (test_unicode_subclassing_deep);
/* XXX test all methods for their defaults and various (glib, icu, default) implementations. */
/* XXX test glib & icu two-way script conversion */
- return g_test_run ();
+ return hb_test_run ();
}
commit c7ffe2ad5f6e97e26d14e2cc0d4098af8f5f36d0
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 16:03:29 2011 -0400
[API Remove hb_font_funcs_copy()
Will be adding font_funcs subclassing instead.
diff --git a/src/hb-font.cc b/src/hb-font.cc
index b067901..5e4d379 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -141,19 +141,6 @@ hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
}
-hb_font_funcs_t *
-hb_font_funcs_copy (hb_font_funcs_t *other_ffuncs)
-{
- hb_font_funcs_t *ffuncs;
-
- if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
- return &_hb_font_funcs_nil;
-
- ffuncs->v = other_ffuncs->v;
-
- return ffuncs;
-}
-
void
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
{
diff --git a/src/hb-font.h b/src/hb-font.h
index 9c69470..c26ab01 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -105,9 +105,6 @@ hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
hb_user_data_key_t *key);
-hb_font_funcs_t *
-hb_font_funcs_copy (hb_font_funcs_t *ffuncs);
-
void
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs);
commit 30f34d08d445722320db711c3ddf41e66225752c
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 16:02:40 2011 -0400
[TODO] Remove finished items
diff --git a/TODO b/TODO
index d8d4d56..e95dd4f 100644
--- a/TODO
+++ b/TODO
@@ -14,8 +14,6 @@ API issues to fix before 1.0:
- Figure out how many .so objects, how to link, etc
-- User-data support ala cairo
-
- Real subclassing support for vfunc vectors
- Add hb-cairo glue
diff --git a/src/hb-font.h b/src/hb-font.h
index f018a8b..9c69470 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -70,16 +70,6 @@ hb_face_get_user_data (hb_face_t *face,
hb_user_data_key_t *key);
-/* XXX
- *
- * I have two major concerns about this API as it is right now:
- *
- * - Jonathan Kew convinced me to make it return NULL if table not found (280af1bd),
- * however, that is WRONG IMO. The API should not differentiate between a non-existing
- * table vs a zero-length table vs a very short table. It only leads to implementations
- * that check for non-NULL and assume that they've got a usable table going on... This
- * actually happened with Firefox.
- */
hb_blob_t *
hb_face_reference_table (hb_face_t *face,
hb_tag_t tag);
commit 080a0eb7d82d7195be72c16ece6e0a3ffed636b6
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 16:01:01 2011 -0400
Add _hb_unsigned_int_mul_overflows
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 13d0040..c3e9be0 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -77,19 +77,16 @@ _hb_buffer_enlarge (hb_buffer_t *buffer, unsigned int size)
unsigned int new_allocated = buffer->allocated;
hb_glyph_position_t *new_pos = NULL;
hb_glyph_info_t *new_info = NULL;
- bool overflows = FALSE;
bool separate_out = buffer->out_info != buffer->info;
- overflows = size >= ((unsigned int) -1) / sizeof (buffer->info[0]);
- if (unlikely (overflows))
+ if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (buffer->info[0]))))
goto done;
while (size > new_allocated)
new_allocated += (new_allocated >> 1) + 32;
ASSERT_STATIC (sizeof (buffer->info[0]) == sizeof (buffer->pos[0]));
- overflows = new_allocated >= ((unsigned int) -1) / sizeof (buffer->info[0]);
- if (unlikely (overflows))
+ if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (buffer->info[0]))))
goto done;
new_pos = (hb_glyph_position_t *) realloc (buffer->pos, new_allocated * sizeof (buffer->pos[0]));
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 5810cc3..af8274d 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -231,7 +231,7 @@ struct hb_sanitize_context_t
inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
{
const char *p = (const char *) base;
- bool overflows = record_size > 0 && len >= ((unsigned int) -1) / record_size;
+ bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
(void) (HB_DEBUG_SANITIZE && (int) this->debug_depth < (int) HB_DEBUG_SANITIZE &&
fprintf (stderr, "SANITIZE(%p) %-*d-> array [%p..%p] (%d*%d=%ld bytes) in [%p..%p] -> %s\n",
diff --git a/src/hb-ot-layout-gsub-private.hh b/src/hb-ot-layout-gsub-private.hh
index 4bf4441..1bd5984 100644
--- a/src/hb-ot-layout-gsub-private.hh
+++ b/src/hb-ot-layout-gsub-private.hh
@@ -409,7 +409,7 @@ struct Ligature
inline uint16_t allocate_lig_id (hb_buffer_t *buffer) const {
uint16_t lig_id = buffer->next_serial ();
- if (unlikely (!lig_id)) lig_id = buffer->next_serial (); /* in case of overflows */
+ if (unlikely (!lig_id)) lig_id = buffer->next_serial (); /* in case of overflow */
return lig_id;
}
diff --git a/src/hb-private.hh b/src/hb-private.hh
index ca37084..b91595d 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -210,6 +210,13 @@ _hb_ctz (unsigned int number)
#endif
}
+static inline bool
+_hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
+{
+ return (size > 0) && (count >= ((unsigned int) -1) / size);
+}
+
+
/* Type of bsearch() / qsort() compare function */
typedef int (*hb_compare_func_t) (const void *, const void *);
@@ -297,7 +304,7 @@ struct hb_static_array_t {
array = new_array;
}
} else {
- bool overflows = (new_allocated < allocated) || (new_allocated >= ((unsigned int) -1) / sizeof (Type));
+ bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
if (unlikely (overflows))
new_array = NULL;
else
commit 1d39d6e42b3d7628512d675a84a831a0f58624eb
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 15:54:16 2011 -0400
Desable possibly lethal test on 64-bit machines
diff --git a/test/test-buffer.c b/test/test-buffer.c
index 61a1b48..7da4c92 100644
--- a/test/test-buffer.c
+++ b/test/test-buffer.c
@@ -304,9 +304,12 @@ test_buffer_allocation (fixture_t *fixture, gconstpointer user_data)
g_assert (hb_buffer_allocation_successful (fixture->b));
/* technically, this one can actually pass on 64bit machines, but
- * I'm doubtful that any malloc allows 4GB allocations at a time. */
- g_assert (!hb_buffer_pre_allocate (fixture->b, ((unsigned int) -1) / 20 - 1));
- g_assert (!hb_buffer_allocation_successful (fixture->b));
+ * I'm doubtful that any malloc allows 4GB allocations at a time.
+ * But let's only enable it on a 32-bit machine. */
+ if (sizeof (long) == 4) {
+ g_assert (!hb_buffer_pre_allocate (fixture->b, ((unsigned int) -1) / 20 - 1));
+ g_assert (!hb_buffer_allocation_successful (fixture->b));
+ }
hb_buffer_reset (fixture->b);
g_assert (hb_buffer_allocation_successful (fixture->b));
commit 3264042873fd639f3ef8ff0acfad777a0a9f3355
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 14:24:16 2011 -0400
[test/buffer] Test pre_allocate() and allocation_successful()
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 7dfe83a..13d0040 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -80,7 +80,8 @@ _hb_buffer_enlarge (hb_buffer_t *buffer, unsigned int size)
bool overflows = FALSE;
bool separate_out = buffer->out_info != buffer->info;
- if (unlikely (size > ((unsigned int)-1) / 2))
+ overflows = size >= ((unsigned int) -1) / sizeof (buffer->info[0]);
+ if (unlikely (overflows))
goto done;
while (size > new_allocated)
diff --git a/test/test-buffer.c b/test/test-buffer.c
index b79f955..61a1b48 100644
--- a/test/test-buffer.c
+++ b/test/test-buffer.c
@@ -281,10 +281,35 @@ test_buffer_allocation (fixture_t *fixture, gconstpointer user_data)
g_assert (hb_buffer_pre_allocate (fixture->b, 100));
g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
+ g_assert (hb_buffer_allocation_successful (fixture->b));
/* lets try a huge allocation, make sure it fails */
g_assert (!hb_buffer_pre_allocate (fixture->b, (unsigned int) -1));
g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
+ g_assert (!hb_buffer_allocation_successful (fixture->b));
+
+ /* small one again */
+ g_assert (hb_buffer_pre_allocate (fixture->b, 50));
+ g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
+ g_assert (!hb_buffer_allocation_successful (fixture->b));
+
+ hb_buffer_reset (fixture->b);
+ g_assert (hb_buffer_allocation_successful (fixture->b));
+
+ /* all allocation and size */
+ g_assert (!hb_buffer_pre_allocate (fixture->b, ((unsigned int) -1) / 20 + 1));
+ g_assert (!hb_buffer_allocation_successful (fixture->b));
+
+ hb_buffer_reset (fixture->b);
+ g_assert (hb_buffer_allocation_successful (fixture->b));
+
+ /* technically, this one can actually pass on 64bit machines, but
+ * I'm doubtful that any malloc allows 4GB allocations at a time. */
+ g_assert (!hb_buffer_pre_allocate (fixture->b, ((unsigned int) -1) / 20 - 1));
+ g_assert (!hb_buffer_allocation_successful (fixture->b));
+
+ hb_buffer_reset (fixture->b);
+ g_assert (hb_buffer_allocation_successful (fixture->b));
}
@@ -311,7 +336,6 @@ main (int argc, char **argv)
g_test_add ("/buffer/allocation", fixture_t, GINT_TO_POINTER (BUFFER_EMPTY), fixture_init, test_buffer_allocation, fixture_fini);
/* XXX test invalid UTF-8 / UTF-16 text input (also overlong sequences) */
- /* XXX test pre_allocate(), allocation_successful(), and memory management */
return g_test_run();
}
commit 123aa04f7b3241d6e43de2d472c4a1cbdb250ac7
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 12:58:28 2011 -0400
Fix possible but improbable overflow in hb_array_t
diff --git a/src/hb-private.hh b/src/hb-private.hh
index ce09d18..ca37084 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -297,7 +297,7 @@ struct hb_static_array_t {
array = new_array;
}
} else {
- bool overflows = new_allocated >= ((unsigned int) -1) / sizeof (Type);
+ bool overflows = (new_allocated < allocated) || (new_allocated >= ((unsigned int) -1) / sizeof (Type));
if (unlikely (overflows))
new_array = NULL;
else
commit e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 12:56:49 2011 -0400
[buffer] More error handling
Should be all set now.
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index 6954f96..7c298b0 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -95,9 +95,9 @@ struct _hb_buffer_t {
/* Buffer contents */
+ bool in_error; /* Allocation failed */
bool have_output; /* Whether we have an output buffer going on */
bool have_positions; /* Whether we have positions */
- bool in_error; /* Allocation failed */
unsigned int i; /* Cursor into ->info and ->pos arrays */
unsigned int len; /* Length of ->info and ->pos arrays */
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 98ddd96..7dfe83a 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -43,6 +43,10 @@ static hb_buffer_t _hb_buffer_nil = {
HB_SCRIPT_INVALID,
NULL,
},
+
+ TRUE, /* in_error */
+ TRUE, /* have_output */
+ TRUE /* have_positions */
};
/* Here is how the buffer works internally:
@@ -71,26 +75,26 @@ _hb_buffer_enlarge (hb_buffer_t *buffer, unsigned int size)
return FALSE;
unsigned int new_allocated = buffer->allocated;
- hb_glyph_position_t *new_pos;
- hb_glyph_info_t *new_info;
- bool separate_out;
+ hb_glyph_position_t *new_pos = NULL;
+ hb_glyph_info_t *new_info = NULL;
+ bool overflows = FALSE;
+ bool separate_out = buffer->out_info != buffer->info;
- separate_out = buffer->out_info != buffer->info;
+ if (unlikely (size > ((unsigned int)-1) / 2))
+ goto done;
while (size > new_allocated)
new_allocated += (new_allocated >> 1) + 32;
ASSERT_STATIC (sizeof (buffer->info[0]) == sizeof (buffer->pos[0]));
- bool overflows = new_allocated >= ((unsigned int) -1) / sizeof (buffer->info[0]);
+ overflows = new_allocated >= ((unsigned int) -1) / sizeof (buffer->info[0]);
+ if (unlikely (overflows))
+ goto done;
- if (unlikely (overflows)) {
- new_pos = NULL;
- new_info = NULL;
- } else {
- new_pos = (hb_glyph_position_t *) realloc (buffer->pos, new_allocated * sizeof (buffer->pos[0]));
- new_info = (hb_glyph_info_t *) realloc (buffer->info, new_allocated * sizeof (buffer->info[0]));
- }
+ new_pos = (hb_glyph_position_t *) realloc (buffer->pos, new_allocated * sizeof (buffer->pos[0]));
+ new_info = (hb_glyph_info_t *) realloc (buffer->info, new_allocated * sizeof (buffer->info[0]));
+done:
if (unlikely (!new_pos || !new_info))
buffer->in_error = TRUE;
@@ -116,7 +120,7 @@ _hb_buffer_ensure (hb_buffer_t *buffer, unsigned int size)
static inline hb_bool_t
_hb_buffer_ensure_separate (hb_buffer_t *buffer, unsigned int size)
{
- if (unlikely (!_hb_buffer_ensure (buffer, size))) return FALSE;
+ if (unlikely (!size || !_hb_buffer_ensure (buffer, size))) return FALSE;
if (buffer->out_info == buffer->info)
{
@@ -188,8 +192,11 @@ void
hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
hb_unicode_funcs_t *unicode)
{
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
+
if (!unicode)
- unicode = &_hb_unicode_funcs_default;
+ unicode = _hb_buffer_nil.unicode;
hb_unicode_funcs_reference (unicode);
hb_unicode_funcs_destroy (buffer->unicode);
@@ -207,6 +214,9 @@ hb_buffer_set_direction (hb_buffer_t *buffer,
hb_direction_t direction)
{
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
+
buffer->props.direction = direction;
}
@@ -220,6 +230,9 @@ void
hb_buffer_set_script (hb_buffer_t *buffer,
hb_script_t script)
{
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
+
buffer->props.script = script;
}
@@ -233,6 +246,9 @@ void
hb_buffer_set_language (hb_buffer_t *buffer,
hb_language_t language)
{
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
+
buffer->props.language = language;
}
@@ -246,14 +262,17 @@ hb_buffer_get_language (hb_buffer_t *buffer)
void
hb_buffer_reset (hb_buffer_t *buffer)
{
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
+
hb_unicode_funcs_destroy (buffer->unicode);
buffer->unicode = _hb_buffer_nil.unicode;
buffer->props = _hb_buffer_nil.props;
+ buffer->in_error = FALSE;
buffer->have_output = FALSE;
buffer->have_positions = FALSE;
- buffer->in_error = FALSE;
buffer->i = 0;
buffer->len = 0;
@@ -301,6 +320,9 @@ hb_buffer_add (hb_buffer_t *buffer,
void
_hb_buffer_clear_output (hb_buffer_t *buffer)
{
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
+
buffer->have_output = TRUE;
buffer->have_positions = FALSE;
@@ -311,6 +333,9 @@ _hb_buffer_clear_output (hb_buffer_t *buffer)
void
_hb_buffer_clear_positions (hb_buffer_t *buffer)
{
+ if (unlikely (hb_object_is_inert (buffer)))
+ return;
+
buffer->have_output = FALSE;
buffer->have_positions = TRUE;
@@ -320,12 +345,10 @@ _hb_buffer_clear_positions (hb_buffer_t *buffer)
void
_hb_buffer_swap (hb_buffer_t *buffer)
{
- unsigned int tmp;
+ if (unlikely (buffer->in_error)) return;
assert (buffer->have_output);
- if (unlikely (buffer->in_error)) return;
-
if (buffer->out_info != buffer->info)
{
hb_glyph_info_t *tmp_string;
@@ -335,6 +358,7 @@ _hb_buffer_swap (hb_buffer_t *buffer)
buffer->pos = (hb_glyph_position_t *) buffer->out_info;
}
+ unsigned int tmp;
tmp = buffer->len;
buffer->len = buffer->out_len;
buffer->out_len = tmp;
commit 15c57e04bf05026ef424f8ae912d2f379301bf93
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 12:28:54 2011 -0400
[test/buffer] Add test pre_alloc(); hangs in the buffer code right now
Because the following loop overflows:
while (size > new_allocated)
new_allocated += (new_allocated >> 1) + 32;
diff --git a/test/test-buffer.c b/test/test-buffer.c
index 2f811f5..b79f955 100644
--- a/test/test-buffer.c
+++ b/test/test-buffer.c
@@ -53,10 +53,10 @@ static const char *buffer_names[] = {
typedef struct
{
hb_buffer_t *b;
-} Fixture;
+} fixture_t;
static void
-fixture_init (Fixture *fixture, gconstpointer user_data)
+fixture_init (fixture_t *fixture, gconstpointer user_data)
{
unsigned int i;
@@ -89,14 +89,14 @@ fixture_init (Fixture *fixture, gconstpointer user_data)
}
static void
-fixture_fini (Fixture *fixture, gconstpointer user_data)
+fixture_fini (fixture_t *fixture, gconstpointer user_data)
{
hb_buffer_destroy (fixture->b);
}
static void
-test_buffer_properties (Fixture *fixture, gconstpointer user_data)
+test_buffer_properties (fixture_t *fixture, gconstpointer user_data)
{
hb_unicode_funcs_t *ufuncs;
@@ -135,7 +135,7 @@ test_buffer_properties (Fixture *fixture, gconstpointer user_data)
}
static void
-test_buffer_contents (Fixture *fixture, gconstpointer user_data)
+test_buffer_contents (fixture_t *fixture, gconstpointer user_data)
{
unsigned int i, len, len2;
buffer_type_t buffer_type = GPOINTER_TO_INT (user_data);
@@ -241,6 +241,9 @@ test_buffer_contents (Fixture *fixture, gconstpointer user_data)
g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+ g_assert (hb_buffer_allocation_successful (fixture->b));
+
+
/* test reset clears content */
hb_buffer_reset (fixture->b);
@@ -248,7 +251,7 @@ test_buffer_contents (Fixture *fixture, gconstpointer user_data)
}
static void
-test_buffer_positions (Fixture *fixture, gconstpointer user_data)
+test_buffer_positions (fixture_t *fixture, gconstpointer user_data)
{
unsigned int i, len, len2;
hb_glyph_position_t *positions;
@@ -271,6 +274,20 @@ test_buffer_positions (Fixture *fixture, gconstpointer user_data)
g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
}
+static void
+test_buffer_allocation (fixture_t *fixture, gconstpointer user_data)
+{
+ g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
+
+ g_assert (hb_buffer_pre_allocate (fixture->b, 100));
+ g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
+
+ /* lets try a huge allocation, make sure it fails */
+ g_assert (!hb_buffer_pre_allocate (fixture->b, (unsigned int) -1));
+ g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
+}
+
+
int
main (int argc, char **argv)
{
@@ -282,7 +299,7 @@ main (int argc, char **argv)
#define TEST_ADD(path, func) \
G_STMT_START { \
char *s = g_strdup_printf ("%s/%s", path, buffer_names[i]); \
- g_test_add (s, Fixture, GINT_TO_POINTER (i), fixture_init, func, fixture_fini); \
+ g_test_add (s, fixture_t, GINT_TO_POINTER (i), fixture_init, func, fixture_fini); \
g_free (s); \
} G_STMT_END
TEST_ADD ("/buffer/properties", test_buffer_properties);
@@ -291,6 +308,8 @@ main (int argc, char **argv)
#undef TEST_ADD
}
+ g_test_add ("/buffer/allocation", fixture_t, GINT_TO_POINTER (BUFFER_EMPTY), fixture_init, test_buffer_allocation, fixture_fini);
+
/* XXX test invalid UTF-8 / UTF-16 text input (also overlong sequences) */
/* XXX test pre_allocate(), allocation_successful(), and memory management */
commit 1e5527e2d60ed3b4a5adf62b258415ec3aef41fb
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 12:15:24 2011 -0400
[test/buffer] Test reset(), set_length(), and set/get_unicode_data()
diff --git a/test/test-buffer.c b/test/test-buffer.c
index 75e9a8c..2f811f5 100644
--- a/test/test-buffer.c
+++ b/test/test-buffer.c
@@ -98,12 +98,22 @@ fixture_fini (Fixture *fixture, gconstpointer user_data)
static void
test_buffer_properties (Fixture *fixture, gconstpointer user_data)
{
- /* TODO check unicode_funcs */
+ hb_unicode_funcs_t *ufuncs;
+ /* test default properties */
+
+ g_assert (hb_buffer_get_unicode_funcs (fixture->b) == hb_unicode_funcs_get_default ());
g_assert (hb_buffer_get_direction (fixture->b) == HB_DIRECTION_INVALID);
g_assert (hb_buffer_get_script (fixture->b) == HB_SCRIPT_INVALID);
g_assert (hb_buffer_get_language (fixture->b) == NULL);
+
+ /* test property changes are retained */
+ ufuncs = hb_unicode_funcs_create (NULL);
+ hb_buffer_set_unicode_funcs (fixture->b, ufuncs);
+ hb_unicode_funcs_destroy (ufuncs);
+ g_assert (hb_buffer_get_unicode_funcs (fixture->b) == ufuncs);
+
hb_buffer_set_direction (fixture->b, HB_DIRECTION_RTL);
g_assert (hb_buffer_get_direction (fixture->b) == HB_DIRECTION_RTL);
@@ -112,12 +122,22 @@ test_buffer_properties (Fixture *fixture, gconstpointer user_data)
hb_buffer_set_language (fixture->b, hb_language_from_string ("fa"));
g_assert (hb_buffer_get_language (fixture->b) == hb_language_from_string ("Fa"));
+
+
+ /* test reset clears properties */
+
+ hb_buffer_reset (fixture->b);
+
+ g_assert (hb_buffer_get_unicode_funcs (fixture->b) == hb_unicode_funcs_get_default ());
+ g_assert (hb_buffer_get_direction (fixture->b) == HB_DIRECTION_INVALID);
+ g_assert (hb_buffer_get_script (fixture->b) == HB_SCRIPT_INVALID);
+ g_assert (hb_buffer_get_language (fixture->b) == NULL);
}
static void
test_buffer_contents (Fixture *fixture, gconstpointer user_data)
{
- unsigned int i, len;
+ unsigned int i, len, len2;
buffer_type_t buffer_type = GPOINTER_TO_INT (user_data);
hb_glyph_info_t *glyphs;
@@ -126,7 +146,10 @@ test_buffer_contents (Fixture *fixture, gconstpointer user_data)
return;
}
- glyphs = hb_buffer_get_glyph_infos (fixture->b, &len);
+ len = hb_buffer_get_length (fixture->b);
+ glyphs = hb_buffer_get_glyph_infos (fixture->b, NULL); /* test NULL */
+ glyphs = hb_buffer_get_glyph_infos (fixture->b, &len2);
+ g_assert_cmpint (len, ==, len2);
g_assert_cmpint (len, ==, 5);
for (i = 0; i < len; i++) {
@@ -198,16 +221,43 @@ test_buffer_contents (Fixture *fixture, gconstpointer user_data)
hb_buffer_reverse_clusters (fixture->b);
for (i = 0; i < len; i++)
g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+
+
+ /* test setting length */
+
+ /* enlarge */
+ g_assert (hb_buffer_set_length (fixture->b, 10));
+ glyphs = hb_buffer_get_glyph_infos (fixture->b, NULL);
+ g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 10);
+ for (i = 0; i < 5; i++)
+ g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+ for (i = 5; i < 10; i++)
+ g_assert_cmphex (glyphs[i].codepoint, ==, 0);
+ /* shrink */
+ g_assert (hb_buffer_set_length (fixture->b, 3));
+ glyphs = hb_buffer_get_glyph_infos (fixture->b, NULL);
+ g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 3);
+ for (i = 0; i < 3; i++)
+ g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+
+
+ /* test reset clears content */
+
+ hb_buffer_reset (fixture->b);
+ g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
}
static void
test_buffer_positions (Fixture *fixture, gconstpointer user_data)
{
- unsigned int i, len;
+ unsigned int i, len, len2;
hb_glyph_position_t *positions;
/* Without shaping, positions should all be zero */
- positions = hb_buffer_get_glyph_positions (fixture->b, &len);
+ len = hb_buffer_get_length (fixture->b);
+ positions = hb_buffer_get_glyph_positions (fixture->b, NULL); /* test NULL */
+ positions = hb_buffer_get_glyph_positions (fixture->b, &len2);
+ g_assert_cmpint (len, ==, len2);
for (i = 0; i < len; i++) {
g_assert_cmpint (0, ==, positions[i].x_advance);
g_assert_cmpint (0, ==, positions[i].y_advance);
@@ -215,6 +265,10 @@ test_buffer_positions (Fixture *fixture, gconstpointer user_data)
g_assert_cmpint (0, ==, positions[i].y_offset);
g_assert_cmpint (0, ==, positions[i].var.i32);
}
+
+ /* test reset clears content */
+ hb_buffer_reset (fixture->b);
+ g_assert_cmpint (hb_buffer_get_length (fixture->b), ==, 0);
}
int
@@ -239,8 +293,6 @@ main (int argc, char **argv)
/* XXX test invalid UTF-8 / UTF-16 text input (also overlong sequences) */
/* XXX test pre_allocate(), allocation_successful(), and memory management */
- /* XXX test buffer reset */
- /* XXX test buffer set length */
return g_test_run();
}
commit db126b5448ec802285cf2b6f0e7da412d02dfb28
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Apr 28 11:56:29 2011 -0400
[test/buffer] Test reverse() and reverse_clusters()
diff --git a/test/test-buffer.c b/test/test-buffer.c
index ab7f204..75e9a8c 100644
--- a/test/test-buffer.c
+++ b/test/test-buffer.c
@@ -130,6 +130,12 @@ test_buffer_contents (Fixture *fixture, gconstpointer user_data)
g_assert_cmpint (len, ==, 5);
for (i = 0; i < len; i++) {
+ g_assert_cmphex (glyphs[i].mask, ==, 1);
+ g_assert_cmphex (glyphs[i].var1.u32, ==, 0);
+ g_assert_cmphex (glyphs[i].var2.u32, ==, 0);
+ }
+
+ for (i = 0; i < len; i++) {
unsigned int cluster;
cluster = 1+i;
if (i >= 2) {
@@ -140,10 +146,58 @@ test_buffer_contents (Fixture *fixture, gconstpointer user_data)
}
g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
g_assert_cmphex (glyphs[i].cluster, ==, cluster);
- g_assert_cmphex (glyphs[i].mask, ==, 1);
- g_assert_cmphex (glyphs[i].var1.u32, ==, 0);
- g_assert_cmphex (glyphs[i].var2.u32, ==, 0);
}
+
+ /* reverse, test, and reverse back */
+
+ hb_buffer_reverse (fixture->b);
+ for (i = 0; i < len; i++)
+ g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
+
+ hb_buffer_reverse (fixture->b);
+ for (i = 0; i < len; i++)
+ g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+
+ /* reverse_clusters works same as reverse for now since each codepoint is
+ * in its own cluster */
+
+ hb_buffer_reverse_clusters (fixture->b);
+ for (i = 0; i < len; i++)
+ g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
+
+ hb_buffer_reverse_clusters (fixture->b);
+ for (i = 0; i < len; i++)
+ g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+
+ /* now form a cluster and test again */
+ glyphs[2].cluster = glyphs[1].cluster;
+
+ /* reverse, test, and reverse back */
+
+ hb_buffer_reverse (fixture->b);
+ for (i = 0; i < len; i++)
+ g_assert_cmphex (glyphs[i].codepoint, ==, utf32[len-i]);
+
+ hb_buffer_reverse (fixture->b);
+ for (i = 0; i < len; i++)
+ g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
+
+ /* reverse_clusters twice still should return the original string,
+ * but when applied once, the 1-2 cluster should be retained. */
+
+ hb_buffer_reverse_clusters (fixture->b);
+ for (i = 0; i < len; i++) {
+ unsigned int j = len-1-i;
+ if (j == 1)
+ j = 2;
+ else if (j == 2)
+ j = 1;
+ g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+j]);
+ }
+
+ hb_buffer_reverse_clusters (fixture->b);
+ for (i = 0; i < len; i++)
+ g_assert_cmphex (glyphs[i].codepoint, ==, utf32[1+i]);
}
static void
@@ -184,7 +238,6 @@ main (int argc, char **argv)
}
/* XXX test invalid UTF-8 / UTF-16 text input (also overlong sequences) */
- /* XXX test reverse() and reverse_clusters() */
/* XXX test pre_allocate(), allocation_successful(), and memory management */
/* XXX test buffer reset */
/* XXX test buffer set length */
commit 5fa849b77d49da2212825ebb1bea9145713b8449
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Apr 27 21:46:01 2011 -0400
[API] Add _set/get_user_data() for all objects
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 435d37b..83a75f6 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -162,6 +162,23 @@ hb_blob_destroy (hb_blob_t *blob)
free (blob);
}
+hb_bool_t
+hb_blob_set_user_data (hb_blob_t *blob,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy)
+{
+ return hb_object_set_user_data (blob, key, data, destroy);
+}
+
+void *
+hb_blob_get_user_data (hb_blob_t *blob,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (blob, key);
+}
+
+
unsigned int
hb_blob_get_length (hb_blob_t *blob)
{
diff --git a/src/hb-blob.h b/src/hb-blob.h
index 76ea80d..d698ee2 100644
--- a/src/hb-blob.h
+++ b/src/hb-blob.h
@@ -62,6 +62,18 @@ hb_blob_reference (hb_blob_t *blob);
void
hb_blob_destroy (hb_blob_t *blob);
+hb_bool_t
+hb_blob_set_user_data (hb_blob_t *blob,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy);
+
+
+void *
+hb_blob_get_user_data (hb_blob_t *blob,
+ hb_user_data_key_t *key);
+
+
unsigned int
hb_blob_get_length (hb_blob_t *blob);
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 2ae29ca..98ddd96 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -167,6 +167,22 @@ hb_buffer_destroy (hb_buffer_t *buffer)
free (buffer);
}
+hb_bool_t
+hb_buffer_set_user_data (hb_buffer_t *buffer,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy)
+{
+ return hb_object_set_user_data (buffer, key, data, destroy);
+}
+
+void *
+hb_buffer_get_user_data (hb_buffer_t *buffer,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (buffer, key);
+}
+
void
hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index e7ef087..47a2123 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -68,6 +68,16 @@ hb_buffer_reference (hb_buffer_t *buffer);
void
hb_buffer_destroy (hb_buffer_t *buffer);
+hb_bool_t
+hb_buffer_set_user_data (hb_buffer_t *buffer,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy);
+
+void *
+hb_buffer_get_user_data (hb_buffer_t *buffer,
+ hb_user_data_key_t *key);
+
void
hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 5506480..b067901 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -124,6 +124,23 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
free (ffuncs);
}
+hb_bool_t
+hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy)
+{
+ return hb_object_set_user_data (ffuncs, key, data, destroy);
+}
+
+void *
+hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (ffuncs, key);
+}
+
+
hb_font_funcs_t *
hb_font_funcs_copy (hb_font_funcs_t *other_ffuncs)
{
@@ -408,6 +425,23 @@ hb_face_destroy (hb_face_t *face)
free (face);
}
+hb_bool_t
+hb_face_set_user_data (hb_face_t *face,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy)
+{
+ return hb_object_set_user_data (face, key, data, destroy);
+}
+
+void *
+hb_face_get_user_data (hb_face_t *face,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (face, key);
+}
+
+
hb_blob_t *
hb_face_reference_table (hb_face_t *face,
hb_tag_t tag)
@@ -480,6 +514,23 @@ hb_font_destroy (hb_font_t *font)
free (font);
}
+hb_bool_t
+hb_font_set_user_data (hb_font_t *font,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy)
+{
+ return hb_object_set_user_data (font, key, data, destroy);
+}
+
+void *
+hb_font_get_user_data (hb_font_t *font,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (font, key);
+}
+
+
void
hb_font_set_funcs (hb_font_t *font,
hb_font_funcs_t *klass,
diff --git a/src/hb-font.h b/src/hb-font.h
index e349591..f018a8b 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -58,6 +58,18 @@ hb_face_reference (hb_face_t *face);
void
hb_face_destroy (hb_face_t *face);
+hb_bool_t
+hb_face_set_user_data (hb_face_t *face,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy);
+
+
+void *
+hb_face_get_user_data (hb_face_t *face,
+ hb_user_data_key_t *key);
+
+
/* XXX
*
* I have two major concerns about this API as it is right now:
@@ -91,6 +103,18 @@ hb_font_funcs_reference (hb_font_funcs_t *ffuncs);
void
hb_font_funcs_destroy (hb_font_funcs_t *ffuncs);
+hb_bool_t
+hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy);
+
+
+void *
+hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key);
+
+
hb_font_funcs_t *
hb_font_funcs_copy (hb_font_funcs_t *ffuncs);
@@ -203,6 +227,18 @@ hb_font_reference (hb_font_t *font);
void
hb_font_destroy (hb_font_t *font);
+hb_bool_t
+hb_font_set_user_data (hb_font_t *font,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy);
+
+
+void *
+hb_font_get_user_data (hb_font_t *font,
+ hb_user_data_key_t *key);
+
+
void
hb_font_set_funcs (hb_font_t *font,
hb_font_funcs_t *klass,
diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc
index 9922955..0486be3 100644
--- a/src/hb-unicode.cc
+++ b/src/hb-unicode.cc
@@ -155,6 +155,23 @@ hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
free (ufuncs);
}
+hb_bool_t
+hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy)
+{
+ return hb_object_set_user_data (ufuncs, key, data, destroy);
+}
+
+void *
+hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (ufuncs, key);
+}
+
+
void
hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
{
diff --git a/src/hb-unicode.h b/src/hb-unicode.h
index d558c22..a46431b 100644
--- a/src/hb-unicode.h
+++ b/src/hb-unicode.h
@@ -59,6 +59,18 @@ hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs);
void
hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs);
+hb_bool_t
+hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy);
+
+
+void *
+hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key);
+
+
void
hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs);
commit 852e08ec8fbfbce1d50e571d0bb0b52ef4d4cc58
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Apr 27 21:45:51 2011 -0400
Move code around
diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index 7bc6b46..d124758 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -44,134 +44,28 @@ HB_BEGIN_DECLS
#endif
-/* user_data */
-
-HB_END_DECLS
-
-
-template <typename Type, unsigned int StaticSize>
-struct hb_static_array_t {
-
- unsigned int len;
- unsigned int allocated;
- Type *array;
- Type static_array[StaticSize];
-
- void finish (void) { for (unsigned i = 0; i < len; i++) array[i].finish (); }
-
- inline Type& operator [] (unsigned int i)
- {
- return array[i];
- }
-
- inline Type *push (void)
- {
- if (!array) {
- array = static_array;
- allocated = ARRAY_LENGTH (static_array);
- }
- if (likely (len < allocated))
- return &array[len++];
- /* Need to reallocate */
- unsigned int new_allocated = allocated + (allocated >> 1) + 8;
- Type *new_array;
- if (array == static_array) {
- new_array = (Type *) calloc (new_allocated, sizeof (Type));
- if (new_array) {
- memcpy (new_array, array, len * sizeof (Type));
- array = new_array;
- }
- } else {
- bool overflows = new_allocated >= ((unsigned int) -1) / sizeof (Type);
- if (unlikely (overflows))
- new_array = NULL;
- else
- new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
- if (new_array) {
- free (array);
- array = new_array;
- }
- }
- if ((len < allocated))
- return &array[len++];
- else
- return NULL;
- }
-
- inline void pop (void)
- {
- len--;
- /* TODO: shrink array if needed */
- }
-};
-
-template <typename Type>
-struct hb_array_t : hb_static_array_t<Type, 2> {};
-
-
-template <typename Key, typename Value>
-struct hb_map_t
-{
- struct item_t {
- Key key;
- /* unsigned int hash; */
- Value value;
-
- void finish (void) { value.finish (); }
- };
+/* reference_count */
- hb_array_t <item_t> items;
-
- private:
-
- inline item_t *find (Key key) {
- if (unlikely (!key)) return NULL;
- for (unsigned int i = 0; i < items.len; i++)
- if (key == items[i].key)
- return &items[i];
- return NULL;
- }
-
- public:
+typedef struct {
+ hb_atomic_int_t ref_count;
- inline bool set (Key key,
- Value &value)
- {
- if (unlikely (!key)) return NULL;
- item_t *item;
- item = find (key);
- if (item)
- item->finish ();
- else
- item = items.push ();
- if (unlikely (!item)) return false;
- item->key = key;
- item->value = value;
- return true;
- }
+#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1)
+#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE}
- inline void unset (Key &key)
- {
- item_t *item;
- item = find (key);
- if (!item) return;
+ inline void init (int v) { ref_count = v; /* non-atomic is fine */ }
+ inline int inc (void) { return hb_atomic_int_fetch_and_add (ref_count, 1); }
+ inline int dec (void) { return hb_atomic_int_fetch_and_add (ref_count, -1); }
+ inline void set (int v) { hb_atomic_int_set (ref_count, v); }
- item->finish ();
- items[items.len - 1] = *item;
- items.pop ();
- }
+ inline int get (void) const { return hb_atomic_int_get (ref_count); }
+ inline bool is_invalid (void) const { return get () == HB_REFERENCE_COUNT_INVALID_VALUE; }
- inline Value *get (Key key)
- {
- item_t *item = find (key);
- return item ? &item->value : NULL;
- }
+} hb_reference_count_t;
- void finish (void) { items.finish (); }
-};
+/* user_data */
-HB_BEGIN_DECLS
+/* XXX make this thread-safe, somehow! */
typedef struct {
void *data;
@@ -204,6 +98,7 @@ struct hb_user_data_array_t {
};
+/* object_header */
typedef struct _hb_object_header_t hb_object_header_t;
@@ -273,6 +168,9 @@ struct _hb_object_header_t {
HB_END_DECLS
+
+/* object */
+
template <typename Type>
static inline void hb_object_trace (const Type *obj, const char *function)
{
@@ -303,6 +201,21 @@ static inline bool hb_object_destroy (Type *obj)
hb_object_trace (obj, HB_FUNC);
return obj->header.destroy ();
}
+template <typename Type>
+static inline bool hb_object_set_user_data (Type *obj,
+ hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy)
+{
+ return obj->header.set_user_data (key, data, destroy);
+}
+
+template <typename Type>
+static inline void *hb_object_get_user_data (Type *obj,
+ hb_user_data_key_t *key)
+{
+ return obj->header.get_user_data (key);
+}
HB_BEGIN_DECLS
diff --git a/src/hb-private.hh b/src/hb-private.hh
index fc06e70..ce09d18 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -258,23 +258,135 @@ typedef volatile int hb_mutex_t;
#endif
-/* A reference count */
+HB_END_DECLS
+
+
+/* arrays and maps */
+
+
+template <typename Type, unsigned int StaticSize>
+struct hb_static_array_t {
+
+ unsigned int len;
+ unsigned int allocated;
+ Type *array;
+ Type static_array[StaticSize];
+
+ void finish (void) { for (unsigned i = 0; i < len; i++) array[i].finish (); }
+
+ inline Type& operator [] (unsigned int i)
+ {
+ return array[i];
+ }
+
+ inline Type *push (void)
+ {
+ if (!array) {
+ array = static_array;
+ allocated = ARRAY_LENGTH (static_array);
+ }
+ if (likely (len < allocated))
+ return &array[len++];
+ /* Need to reallocate */
+ unsigned int new_allocated = allocated + (allocated >> 1) + 8;
+ Type *new_array;
+ if (array == static_array) {
+ new_array = (Type *) calloc (new_allocated, sizeof (Type));
+ if (new_array) {
+ memcpy (new_array, array, len * sizeof (Type));
+ array = new_array;
+ }
+ } else {
+ bool overflows = new_allocated >= ((unsigned int) -1) / sizeof (Type);
+ if (unlikely (overflows))
+ new_array = NULL;
+ else
+ new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
+ if (new_array) {
+ free (array);
+ array = new_array;
+ }
+ }
+ if ((len < allocated))
+ return &array[len++];
+ else
+ return NULL;
+ }
+
+ inline void pop (void)
+ {
+ len--;
+ /* TODO: shrink array if needed */
+ }
+};
+
+template <typename Type>
+struct hb_array_t : hb_static_array_t<Type, 2> {};
-typedef struct {
- hb_atomic_int_t ref_count;
-#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1)
-#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE}
+template <typename Key, typename Value>
+struct hb_map_t
+{
+ struct item_t {
+ Key key;
+ /* unsigned int hash; */
+ Value value;
+
+ void finish (void) { value.finish (); }
+ };
+
+ hb_array_t <item_t> items;
+
+ private:
+
+ inline item_t *find (Key key) {
+ if (unlikely (!key)) return NULL;
+ for (unsigned int i = 0; i < items.len; i++)
+ if (key == items[i].key)
+ return &items[i];
+ return NULL;
+ }
+
+ public:
+
+ inline bool set (Key key,
+ Value &value)
+ {
+ if (unlikely (!key)) return NULL;
+ item_t *item;
+ item = find (key);
+ if (item)
+ item->finish ();
+ else
+ item = items.push ();
+ if (unlikely (!item)) return false;
+ item->key = key;
+ item->value = value;
+ return true;
+ }
+
+ inline void unset (Key &key)
+ {
+ item_t *item;
+ item = find (key);
+ if (!item) return;
- inline void init (int v) { ref_count = v; /* non-atomic is fine */ }
- inline int inc (void) { return hb_atomic_int_fetch_and_add (ref_count, 1); }
- inline int dec (void) { return hb_atomic_int_fetch_and_add (ref_count, -1); }
- inline void set (int v) { hb_atomic_int_set (ref_count, v); }
+ item->finish ();
+ items[items.len - 1] = *item;
+ items.pop ();
+ }
- inline int get (void) const { return hb_atomic_int_get (ref_count); }
- inline bool is_invalid (void) const { return get () == HB_REFERENCE_COUNT_INVALID_VALUE; }
+ inline Value *get (Key key)
+ {
+ item_t *item = find (key);
+ return item ? &item->value : NULL;
+ }
-} hb_reference_count_t;
+ void finish (void) { items.finish (); }
+};
+
+
+HB_BEGIN_DECLS
/* Big-endian handling */
commit 29c67d3f70b081766a6c01353980f457f38aeb12
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Apr 27 21:22:32 2011 -0400
Add initial implementation of user_data to objects
diff --git a/src/hb-common.h b/src/hb-common.h
index e6f5f2b..74030f4 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -68,8 +68,6 @@ typedef union _hb_var_int_t {
int8_t i8[4];
} hb_var_int_t;
-typedef void (*hb_destroy_func_t) (void *user_data);
-
/* hb_tag_t */
@@ -287,6 +285,15 @@ hb_direction_t
hb_script_get_horizontal_direction (hb_script_t script);
+/* User data */
+
+typedef struct _hb_user_data_key_t {
+ char unused;
+} hb_user_data_key_t;
+
+typedef void (*hb_destroy_func_t) (void *user_data);
+
+
HB_END_DECLS
#endif /* HB_COMMON_H */
diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index 8fbddd4..7bc6b46 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -44,10 +44,172 @@ HB_BEGIN_DECLS
#endif
+/* user_data */
+
+HB_END_DECLS
+
+
+template <typename Type, unsigned int StaticSize>
+struct hb_static_array_t {
+
+ unsigned int len;
+ unsigned int allocated;
+ Type *array;
+ Type static_array[StaticSize];
+
+ void finish (void) { for (unsigned i = 0; i < len; i++) array[i].finish (); }
+
+ inline Type& operator [] (unsigned int i)
+ {
+ return array[i];
+ }
+
+ inline Type *push (void)
+ {
+ if (!array) {
+ array = static_array;
+ allocated = ARRAY_LENGTH (static_array);
+ }
+ if (likely (len < allocated))
+ return &array[len++];
+ /* Need to reallocate */
+ unsigned int new_allocated = allocated + (allocated >> 1) + 8;
+ Type *new_array;
+ if (array == static_array) {
+ new_array = (Type *) calloc (new_allocated, sizeof (Type));
+ if (new_array) {
+ memcpy (new_array, array, len * sizeof (Type));
+ array = new_array;
+ }
+ } else {
+ bool overflows = new_allocated >= ((unsigned int) -1) / sizeof (Type);
+ if (unlikely (overflows))
+ new_array = NULL;
+ else
+ new_array = (Type *) realloc (array, new_allocated * sizeof (Type));
+ if (new_array) {
+ free (array);
+ array = new_array;
+ }
+ }
+ if ((len < allocated))
+ return &array[len++];
+ else
+ return NULL;
+ }
+
+ inline void pop (void)
+ {
+ len--;
+ /* TODO: shrink array if needed */
+ }
+};
+
+template <typename Type>
+struct hb_array_t : hb_static_array_t<Type, 2> {};
+
+
+template <typename Key, typename Value>
+struct hb_map_t
+{
+ struct item_t {
+ Key key;
+ /* unsigned int hash; */
+ Value value;
+
+ void finish (void) { value.finish (); }
+ };
+
+ hb_array_t <item_t> items;
+
+ private:
+
+ inline item_t *find (Key key) {
+ if (unlikely (!key)) return NULL;
+ for (unsigned int i = 0; i < items.len; i++)
+ if (key == items[i].key)
+ return &items[i];
+ return NULL;
+ }
+
+ public:
+
+ inline bool set (Key key,
+ Value &value)
+ {
+ if (unlikely (!key)) return NULL;
+ item_t *item;
+ item = find (key);
+ if (item)
+ item->finish ();
+ else
+ item = items.push ();
+ if (unlikely (!item)) return false;
+ item->key = key;
+ item->value = value;
+ return true;
+ }
+
+ inline void unset (Key &key)
+ {
+ item_t *item;
+ item = find (key);
+ if (!item) return;
+
+ item->finish ();
+ items[items.len - 1] = *item;
+ items.pop ();
+ }
+
+ inline Value *get (Key key)
+ {
+ item_t *item = find (key);
+ return item ? &item->value : NULL;
+ }
+
+ void finish (void) { items.finish (); }
+};
+
+
+HB_BEGIN_DECLS
+
+typedef struct {
+ void *data;
+ hb_destroy_func_t destroy;
+
+ void finish (void) { if (destroy) destroy (data); }
+} hb_user_data_t;
+
+struct hb_user_data_array_t {
+
+ hb_map_t<hb_user_data_key_t *, hb_user_data_t> map;
+
+ inline bool set (hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy)
+ {
+ if (!data && !destroy) {
+ map.unset (key);
+ return true;
+ }
+ hb_user_data_t user_data = {data, destroy};
+ return map.set (key, user_data);
+ }
+
+ inline void *get (hb_user_data_key_t *key) {
+ return map.get (key);
+ }
+
+ void finish (void) { map.finish (); }
+};
+
+
+
typedef struct _hb_object_header_t hb_object_header_t;
struct _hb_object_header_t {
hb_reference_count_t ref_count;
+ hb_user_data_array_t user_data;
#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INVALID}
@@ -64,7 +226,9 @@ struct _hb_object_header_t {
ref_count.init (1);
}
- inline bool is_inert (void) const { return unlikely (ref_count.is_invalid ()); }
+ inline bool is_inert (void) const {
+ return unlikely (ref_count.is_invalid ());
+ }
inline void reference (void) {
if (unlikely (!this || this->is_inert ()))
@@ -75,7 +239,25 @@ struct _hb_object_header_t {
inline bool destroy (void) {
if (unlikely (!this || this->is_inert ()))
return false;
- return ref_count.dec () == 1;
+ if (ref_count.dec () != 1)
+ return false;
+
+ user_data.finish ();
+
+ return true;
+ }
+
+ inline bool set_user_data (hb_user_data_key_t *key,
+ void * data,
+ hb_destroy_func_t destroy) {
+ if (unlikely (!this || this->is_inert ()))
+ return false;
+
+ return user_data.set (key, data, destroy);
+ }
+
+ inline void *get_user_data (hb_user_data_key_t *key) {
+ return user_data.get (key);
}
inline void trace (const char *function) const {
commit 47e71d9661946a4ffb96026bf1d697d788414ab5
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Apr 27 16:38:03 2011 -0400
[object] Remove unnecessary use of macros
diff --git a/TODO b/TODO
index 941a8c8..d8d4d56 100644
--- a/TODO
+++ b/TODO
@@ -9,8 +9,6 @@ General fixes:
- Remove fixed-size feature/lookup arrays in hb-ot-map
-- Use templates instead of macros for objects?
-
API issues to fix before 1.0:
============================
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 7d1925f..435d37b 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -87,7 +87,7 @@ hb_blob_create (const char *data,
{
hb_blob_t *blob;
- if (!length || !HB_OBJECT_DO_CREATE (hb_blob_t, blob)) {
+ if (!length || !(blob = hb_object_create<hb_blob_t> ())) {
if (destroy)
destroy (user_data);
return &_hb_blob_nil;
@@ -122,7 +122,7 @@ hb_blob_create_sub_blob (hb_blob_t *parent,
hb_blob_t *blob;
const char *pdata;
- if (!length || offset >= parent->length || !HB_OBJECT_DO_CREATE (hb_blob_t, blob))
+ if (!length || offset >= parent->length || !(blob = hb_object_create<hb_blob_t> ()))
return &_hb_blob_nil;
pdata = hb_blob_lock (parent);
@@ -149,13 +149,13 @@ hb_blob_create_empty (void)
hb_blob_t *
hb_blob_reference (hb_blob_t *blob)
{
- HB_OBJECT_DO_REFERENCE (blob);
+ return hb_object_reference (blob);
}
void
hb_blob_destroy (hb_blob_t *blob)
{
- HB_OBJECT_DO_DESTROY (blob);
+ if (!hb_object_destroy (blob)) return;
_hb_blob_destroy_user_data (blob);
@@ -171,7 +171,7 @@ hb_blob_get_length (hb_blob_t *blob)
const char *
hb_blob_lock (hb_blob_t *blob)
{
- if (HB_OBJECT_IS_INERT (blob))
+ if (hb_object_is_inert (blob))
return NULL;
hb_mutex_lock (blob->lock);
@@ -190,7 +190,7 @@ hb_blob_lock (hb_blob_t *blob)
void
hb_blob_unlock (hb_blob_t *blob)
{
- if (HB_OBJECT_IS_INERT (blob))
+ if (hb_object_is_inert (blob))
return;
hb_mutex_lock (blob->lock);
@@ -210,7 +210,7 @@ hb_blob_is_writable (hb_blob_t *blob)
{
hb_memory_mode_t mode;
- if (HB_OBJECT_IS_INERT (blob))
+ if (hb_object_is_inert (blob))
return FALSE;
hb_mutex_lock (blob->lock);
@@ -292,7 +292,7 @@ hb_blob_try_writable_inplace (hb_blob_t *blob)
{
hb_memory_mode_t mode;
- if (HB_OBJECT_IS_INERT (blob))
+ if (hb_object_is_inert (blob))
return FALSE;
hb_mutex_lock (blob->lock);
@@ -312,7 +312,7 @@ hb_blob_try_writable (hb_blob_t *blob)
{
hb_memory_mode_t mode;
- if (HB_OBJECT_IS_INERT (blob))
+ if (hb_object_is_inert (blob))
return FALSE;
hb_mutex_lock (blob->lock);
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 5468270..2ae29ca 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -137,7 +137,7 @@ hb_buffer_create (unsigned int pre_alloc_size)
{
hb_buffer_t *buffer;
- if (!HB_OBJECT_DO_CREATE (hb_buffer_t, buffer))
+ if (!(buffer = hb_object_create<hb_buffer_t> ()))
return &_hb_buffer_nil;
if (pre_alloc_size)
@@ -151,13 +151,13 @@ hb_buffer_create (unsigned int pre_alloc_size)
hb_buffer_t *
hb_buffer_reference (hb_buffer_t *buffer)
{
- HB_OBJECT_DO_REFERENCE (buffer);
+ return hb_object_reference (buffer);
}
void
hb_buffer_destroy (hb_buffer_t *buffer)
{
- HB_OBJECT_DO_DESTROY (buffer);
+ if (!hb_object_destroy (buffer)) return;
hb_unicode_funcs_destroy (buffer->unicode);
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 149ca19..5506480 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -102,7 +102,7 @@ hb_font_funcs_create (void)
{
hb_font_funcs_t *ffuncs;
- if (!HB_OBJECT_DO_CREATE (hb_font_funcs_t, ffuncs))
+ if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
return &_hb_font_funcs_nil;
ffuncs->v = _hb_font_funcs_nil.v;
@@ -113,13 +113,13 @@ hb_font_funcs_create (void)
hb_font_funcs_t *
hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
{
- HB_OBJECT_DO_REFERENCE (ffuncs);
+ return hb_object_reference (ffuncs);
}
void
hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
{
- HB_OBJECT_DO_DESTROY (ffuncs);
+ if (!hb_object_destroy (ffuncs)) return;
free (ffuncs);
}
@@ -129,7 +129,7 @@ hb_font_funcs_copy (hb_font_funcs_t *other_ffuncs)
{
hb_font_funcs_t *ffuncs;
- if (!HB_OBJECT_DO_CREATE (hb_font_funcs_t, ffuncs))
+ if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
return &_hb_font_funcs_nil;
ffuncs->v = other_ffuncs->v;
@@ -140,7 +140,7 @@ hb_font_funcs_copy (hb_font_funcs_t *other_ffuncs)
void
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
{
- if (HB_OBJECT_IS_INERT (ffuncs))
+ if (hb_object_is_inert (ffuncs))
return;
ffuncs->immutable = TRUE;
@@ -308,7 +308,7 @@ hb_face_create_for_tables (hb_get_table_func_t get_table,
{
hb_face_t *face;
- if (!HB_OBJECT_DO_CREATE (hb_face_t, face)) {
+ if (!(face = hb_object_create<hb_face_t> ())) {
if (destroy)
destroy (user_data);
return &_hb_face_nil;
@@ -389,13 +389,13 @@ hb_face_create_for_data (hb_blob_t *blob,
hb_face_t *
hb_face_reference (hb_face_t *face)
{
- HB_OBJECT_DO_REFERENCE (face);
+ return hb_object_reference (face);
}
void
hb_face_destroy (hb_face_t *face)
{
- HB_OBJECT_DO_DESTROY (face);
+ if (!hb_object_destroy (face)) return;
_hb_ot_layout_free (face->ot_layout);
@@ -454,7 +454,7 @@ hb_font_create (void)
{
hb_font_t *font;
- if (!HB_OBJECT_DO_CREATE (hb_font_t, font))
+ if (!(font = hb_object_create<hb_font_t> ()))
return &_hb_font_nil;
font->klass = &_hb_font_funcs_nil;
@@ -465,13 +465,13 @@ hb_font_create (void)
hb_font_t *
hb_font_reference (hb_font_t *font)
{
- HB_OBJECT_DO_REFERENCE (font);
+ return hb_object_reference (font);
}
void
hb_font_destroy (hb_font_t *font)
{
- HB_OBJECT_DO_DESTROY (font);
+ if (!hb_object_destroy (font)) return;
hb_font_funcs_destroy (font->klass);
if (font->destroy)
@@ -486,7 +486,7 @@ hb_font_set_funcs (hb_font_t *font,
void *user_data,
hb_destroy_func_t destroy)
{
- if (HB_OBJECT_IS_INERT (font))
+ if (hb_object_is_inert (font))
return;
if (font->destroy)
@@ -514,7 +514,7 @@ hb_font_unset_funcs (hb_font_t *font,
*user_data = font->user_data;
*destroy = font->destroy;
- if (HB_OBJECT_IS_INERT (font))
+ if (hb_object_is_inert (font))
return;
font->klass = NULL;
@@ -527,7 +527,7 @@ hb_font_set_scale (hb_font_t *font,
int x_scale,
int y_scale)
{
- if (HB_OBJECT_IS_INERT (font))
+ if (hb_object_is_inert (font))
return;
font->x_scale = x_scale;
@@ -548,7 +548,7 @@ hb_font_set_ppem (hb_font_t *font,
unsigned int x_ppem,
unsigned int y_ppem)
{
- if (HB_OBJECT_IS_INERT (font))
+ if (hb_object_is_inert (font))
return;
font->x_ppem = x_ppem;
diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index c3cdeb5..8fbddd4 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -123,18 +123,9 @@ static inline bool hb_object_destroy (Type *obj)
}
-
HB_BEGIN_DECLS
-/* Object allocation and lifecycle manamgement macros */
-
-#define HB_OBJECT_DO_CREATE(Type, obj) likely (obj = hb_object_create<Type> ())
-#define HB_OBJECT_IS_INERT(obj) hb_object_is_inert (obj)
-#define HB_OBJECT_DO_REFERENCE(obj) return hb_object_reference (obj)
-#define HB_OBJECT_DO_DESTROY(obj) if (!hb_object_destroy (obj)) return
-
-
HB_END_DECLS
#endif /* HB_OBJECT_PRIVATE_HH */
diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc
index b756461..9922955 100644
--- a/src/hb-unicode.cc
+++ b/src/hb-unicode.cc
@@ -107,7 +107,7 @@ hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
{
hb_unicode_funcs_t *ufuncs;
- if (!HB_OBJECT_DO_CREATE (hb_unicode_funcs_t, ufuncs))
+ if (!(ufuncs = hb_object_create<hb_unicode_funcs_t> ()))
return &_hb_unicode_funcs_nil;
if (parent != NULL)
@@ -133,13 +133,13 @@ hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
hb_unicode_funcs_t *
hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs)
{
- HB_OBJECT_DO_REFERENCE (ufuncs);
+ return hb_object_reference (ufuncs);
}
void
hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
{
- HB_OBJECT_DO_DESTROY (ufuncs);
+ if (!hb_object_destroy (ufuncs)) return;
#define DESTROY(name) if (ufuncs->destroy.name) ufuncs->destroy.name (ufuncs->user_data.name)
DESTROY (combining_class);
@@ -158,7 +158,7 @@ hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
void
hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
{
- if (HB_OBJECT_IS_INERT (ufuncs))
+ if (hb_object_is_inert (ufuncs))
return;
ufuncs->immutable = TRUE;
commit 8be1420f8fd0e5c53282245d6830efbee5c7409d
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Apr 27 16:14:04 2011 -0400
[blob] Use HB_FUNC instead of __FUNCTION__
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 6e9f40f..7d1925f 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -177,7 +177,7 @@ hb_blob_lock (hb_blob_t *blob)
hb_mutex_lock (blob->lock);
(void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s (%d) -> %p\n", blob, __FUNCTION__,
+ fprintf (stderr, "%p %s (%d) -> %p\n", blob, HB_FUNC,
blob->lock_count, blob->data));
blob->lock_count++;
@@ -196,7 +196,7 @@ hb_blob_unlock (hb_blob_t *blob)
hb_mutex_lock (blob->lock);
(void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s (%d) -> %p\n", blob, __FUNCTION__,
+ fprintf (stderr, "%p %s (%d) -> %p\n", blob, HB_FUNC,
blob->lock_count, blob->data));
assert (blob->lock_count > 0);
@@ -240,28 +240,28 @@ _try_make_writable_inplace_unix_locked (hb_blob_t *blob)
if ((uintptr_t) -1L == pagesize) {
(void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: failed to get pagesize: %s\n", blob, __FUNCTION__, strerror (errno)));
+ fprintf (stderr, "%p %s: failed to get pagesize: %s\n", blob, HB_FUNC, strerror (errno)));
return FALSE;
}
(void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: pagesize is %lu\n", blob, __FUNCTION__, (unsigned long) pagesize));
+ fprintf (stderr, "%p %s: pagesize is %lu\n", blob, HB_FUNC, (unsigned long) pagesize));
mask = ~(pagesize-1);
addr = (const char *) (((uintptr_t) blob->data) & mask);
length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask) - addr;
(void) (HB_DEBUG_BLOB &&
fprintf (stderr, "%p %s: calling mprotect on [%p..%p] (%lu bytes)\n",
- blob, __FUNCTION__,
+ blob, HB_FUNC,
addr, addr+length, (unsigned long) length));
if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) {
(void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: %s\n", blob, __FUNCTION__, strerror (errno)));
+ fprintf (stderr, "%p %s: %s\n", blob, HB_FUNC, strerror (errno)));
return FALSE;
}
(void) (HB_DEBUG_BLOB &&
fprintf (stderr, "%p %s: successfully made [%p..%p] (%lu bytes) writable\n",
- blob, __FUNCTION__,
+ blob, HB_FUNC,
addr, addr+length, (unsigned long) length));
return TRUE;
#else
@@ -273,15 +273,15 @@ static void
try_writable_inplace_locked (hb_blob_t *blob)
{
(void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: making writable\n", blob, __FUNCTION__));
+ fprintf (stderr, "%p %s: making writable\n", blob, HB_FUNC));
if (_try_make_writable_inplace_unix_locked (blob)) {
(void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: making writable -> succeeded\n", blob, __FUNCTION__));
+ fprintf (stderr, "%p %s: making writable -> succeeded\n", blob, HB_FUNC));
blob->mode = HB_MEMORY_MODE_WRITABLE;
} else {
(void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: making writable -> FAILED\n", blob, __FUNCTION__));
+ fprintf (stderr, "%p %s: making writable -> FAILED\n", blob, HB_FUNC));
/* Failed to make writable inplace, mark that */
blob->mode = HB_MEMORY_MODE_READONLY;
}
@@ -325,7 +325,7 @@ hb_blob_try_writable (hb_blob_t *blob)
char *new_data;
(void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s (%d) -> %p\n", blob, __FUNCTION__,
+ fprintf (stderr, "%p %s (%d) -> %p\n", blob, HB_FUNC,
blob->lock_count, blob->data));
if (blob->lock_count)
@@ -334,7 +334,7 @@ hb_blob_try_writable (hb_blob_t *blob)
new_data = (char *) malloc (blob->length);
if (new_data) {
(void) (HB_DEBUG_BLOB &&
- fprintf (stderr, "%p %s: dupped successfully -> %p\n", blob, __FUNCTION__, blob->data));
+ fprintf (stderr, "%p %s: dupped successfully -> %p\n", blob, HB_FUNC, blob->data));
memcpy (new_data, blob->data, blob->length);
_hb_blob_destroy_user_data (blob);
blob->mode = HB_MEMORY_MODE_WRITABLE;
commit ae008b90cfc2028e878100f78b21d70f923a6044
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Apr 27 16:12:12 2011 -0400
[object] Add tracing support back in
diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index 8142bd4..c3cdeb5 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -91,21 +91,37 @@ struct _hb_object_header_t {
HB_END_DECLS
-
template <typename Type>
-static inline Type *hb_object_create () { return (Type *) hb_object_header_t::create (sizeof (Type)); }
-
+static inline void hb_object_trace (const Type *obj, const char *function)
+{
+ obj->header.trace (function);
+}
template <typename Type>
-static inline bool hb_object_is_inert (const Type *obj) { return unlikely (obj->header.is_inert()); }
-
+static inline Type *hb_object_create ()
+{
+ Type *obj = (Type *) hb_object_header_t::create (sizeof (Type));
+ hb_object_trace (obj, HB_FUNC);
+ return obj;
+}
template <typename Type>
-static inline Type *hb_object_reference (Type *obj) { obj->header.reference (); return obj; }
-
+static inline bool hb_object_is_inert (const Type *obj)
+{
+ return unlikely (obj->header.is_inert());
+}
template <typename Type>
-static inline bool hb_object_destroy (Type *obj) { return obj->header.destroy (); }
-
+static inline Type *hb_object_reference (Type *obj)
+{
+ hb_object_trace (obj, HB_FUNC);
+ obj->header.reference ();
+ return obj;
+}
template <typename Type>
-static inline void hb_object_trace (const Type *obj) { obj->header.trace (__FUNCTION__); }
+static inline bool hb_object_destroy (Type *obj)
+{
+ hb_object_trace (obj, HB_FUNC);
+ return obj->header.destroy ();
+}
+
HB_BEGIN_DECLS
@@ -113,8 +129,6 @@ HB_BEGIN_DECLS
/* Object allocation and lifecycle manamgement macros */
-/* XXX Trace objects. Got removed in refactoring */
-#define HB_TRACE_OBJECT(obj) hb_object_trace (obj)
#define HB_OBJECT_DO_CREATE(Type, obj) likely (obj = hb_object_create<Type> ())
#define HB_OBJECT_IS_INERT(obj) hb_object_is_inert (obj)
#define HB_OBJECT_DO_REFERENCE(obj) return hb_object_reference (obj)
More information about the HarfBuzz
mailing list