diff --git a/glib/gstring.h b/glib/gstring.h index ef219a62a..b82123198 100644 --- a/glib/gstring.h +++ b/glib/gstring.h @@ -34,6 +34,7 @@ #include #include #include +#include #include /* for G_CAN_INLINE */ #include @@ -182,7 +183,9 @@ g_string_append_c_inline (GString *gstring, g_string_insert_c (gstring, -1, c); return gstring; } -#define g_string_append_c(gstr,c) g_string_append_c_inline (gstr, c) + +#define g_string_append_c(gstr,c) \ + g_string_append_c_inline (gstr, c) G_ALWAYS_INLINE static inline GString * @@ -190,6 +193,12 @@ g_string_append_len_inline (GString *gstring, const char *val, gssize len) { + if G_UNLIKELY (gstring == NULL) + return g_string_append_len (gstring, val, len); + + if G_UNLIKELY (val == NULL) + return (len != 0) ? g_string_append_len (gstring, val, len) : gstring; + if (len < 0) len = strlen (val); @@ -207,7 +216,9 @@ g_string_append_len_inline (GString *gstring, else return g_string_insert_len (gstring, -1, val, len); } -#define g_string_append_len(gstr,val,len) g_string_append_len_inline (gstr, val, len) + +#define g_string_append_len(gstr, val, len) \ + g_string_append_len_inline (gstr, val, len) G_ALWAYS_INLINE static inline GString * @@ -219,13 +230,24 @@ g_string_truncate_inline (GString *gstring, return gstring; } -#define g_string_truncate(gstr,len) g_string_truncate_inline (gstr, len) +#define g_string_truncate(gstr, len) \ + g_string_truncate_inline (gstr, len) #if G_GNUC_CHECK_VERSION (2, 0) -#define g_string_append(gstr,val) g_string_append_len (gstr, val, __builtin_constant_p (val) ? (gssize) strlen (val) : (gssize) -1) +#define g_string_append(gstr, val) \ + (__builtin_constant_p (val) ? \ + G_GNUC_EXTENSION ({ \ + const char * const __val = (val); \ + g_string_append_len (gstr, __val, \ + G_LIKELY (__val != NULL) ? \ + (gssize) strlen (_G_STR_NONNULL (__val)) \ + : (gssize) -1); \ + }) \ + : \ + g_string_append_len (gstr, val, (gssize) -1)) -#endif +#endif /* G_GNUC_CHECK_VERSION (2, 0) */ #endif /* G_CAN_INLINE */ diff --git a/glib/tests/cxx.cpp b/glib/tests/cxx.cpp index f7129bcf7..6e4727f2a 100644 --- a/glib/tests/cxx.cpp +++ b/glib/tests/cxx.cpp @@ -321,6 +321,106 @@ test_str_equal (void) g_free (str_b); } + +static void +test_string_append (void) +{ + GString *string; + char *tmp; + int i; + + tmp = g_strdup ("more"); + + /* append */ + string = g_string_new ("firsthalf"); + g_string_append (string, "last"); + (g_string_append) (string, "half"); + + g_assert_cmpstr (string->str, ==, "firsthalflasthalf"); + + i = 0; + g_string_append (string, &tmp[i++]); + (g_string_append) (string, &tmp[i++]); + g_assert_true (i == 2); + g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreore"); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*string != NULL*failed*"); + g_assert_null (g_string_append (NULL, NULL)); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*string != NULL*failed*"); + g_assert_null ((g_string_append) (NULL, NULL)); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*val != NULL*failed*"); + g_assert_true (g_string_append (string, NULL) == string); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*val != NULL*failed*"); + g_assert_true ((g_string_append) (string, NULL) == string); + g_test_assert_expected_messages (); + + g_string_free (string, TRUE); + + /* append_len */ + string = g_string_new ("firsthalf"); + g_string_append_len (string, "lasthalfjunkjunk", strlen ("last")); + (g_string_append_len) (string, "halfjunkjunk", strlen ("half")); + g_string_append_len (string, "more", -1); + (g_string_append_len) (string, "ore", -1); + + g_assert_true (g_string_append_len (string, NULL, 0) == string); + g_assert_true ((g_string_append_len) (string, NULL, 0) == string); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*string != NULL*failed*"); + g_assert_null (g_string_append_len (NULL, NULL, -1)); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*string != NULL*failed*"); + g_assert_null ((g_string_append_len) (NULL, NULL, -1)); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*val != NULL*failed*"); + g_assert_true (g_string_append_len (string, NULL, -1) == string); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*val != NULL*failed*"); + g_assert_true ((g_string_append_len) (string, NULL, -1) == string); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*val != NULL*failed*"); + g_assert_true (g_string_append_len (string, NULL, 1) == string); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*val != NULL*failed*"); + g_assert_true ((g_string_append_len) (string, NULL, 1) == string); + g_test_assert_expected_messages (); + + g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreore"); + + char c = 'A'; + g_string_append_c (string, c++); + (g_string_append_c) (string, c++); + g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreoreAB"); + + i = string->len; + g_string_truncate (string, --i); + (g_string_truncate) (string, --i); + g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreore"); + + g_string_free (string, TRUE); +} + int main (int argc, char *argv[]) { @@ -344,6 +444,7 @@ main (int argc, char *argv[]) g_test_add_func ("/C++/clear-pointer", test_clear_pointer); g_test_add_func ("/C++/steal-pointer", test_steal_pointer); g_test_add_func ("/C++/str-equal", test_str_equal); + g_test_add_func ("/C++/string-append", test_string_append); return g_test_run (); } diff --git a/glib/tests/string.c b/glib/tests/string.c index 92138c0ba..46c3d7b8a 100644 --- a/glib/tests/string.c +++ b/glib/tests/string.c @@ -225,6 +225,26 @@ test_string_append (void) g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreore"); + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*string != NULL*failed*"); + g_assert_null (g_string_append (NULL, NULL)); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*string != NULL*failed*"); + g_assert_null ((g_string_append) (NULL, NULL)); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*val != NULL*failed*"); + g_assert_true (g_string_append (string, NULL) == string); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*val != NULL*failed*"); + g_assert_true ((g_string_append) (string, NULL) == string); + g_test_assert_expected_messages (); + g_string_free (string, TRUE); g_free (tmp); @@ -235,6 +255,39 @@ test_string_append (void) g_string_append_len (string, "more", -1); (g_string_append_len) (string, "ore", -1); + g_assert_true (g_string_append_len (string, NULL, 0) == string); + g_assert_true ((g_string_append_len) (string, NULL, 0) == string); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*string != NULL*failed*"); + g_assert_null (g_string_append_len (NULL, NULL, -1)); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*string != NULL*failed*"); + g_assert_null ((g_string_append_len) (NULL, NULL, -1)); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*val != NULL*failed*"); + g_assert_true (g_string_append_len (string, NULL, -1) == string); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*val != NULL*failed*"); + g_assert_true ((g_string_append_len) (string, NULL, -1) == string); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*val != NULL*failed*"); + g_assert_true (g_string_append_len (string, NULL, 1) == string); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*val != NULL*failed*"); + g_assert_true ((g_string_append_len) (string, NULL, 1) == string); + g_test_assert_expected_messages (); + g_assert_cmpstr (string->str, ==, "firsthalflasthalfmoreore"); g_string_free (string, TRUE); }