summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.win32.md13
-rw-r--r--docs/reference/gio/gio-docs.xml4
-rw-r--r--docs/reference/glib/glib-docs.xml4
-rw-r--r--docs/reference/gobject/gobject-docs.xml4
-rw-r--r--docs/reference/gobject/tut_gobject.xml2
-rw-r--r--docs/reference/gobject/tut_gtype.xml16
-rw-r--r--docs/reference/gobject/tut_howto.xml2
-rw-r--r--fuzzing/fuzz_utf8_normalize.c48
-rw-r--r--fuzzing/meson.build1
-rw-r--r--gio/gappinfo.c35
-rw-r--r--gio/gdbusconnection.c46
-rw-r--r--gio/gdbusprivate.c82
-rw-r--r--gio/gio-tool-info.c2
-rw-r--r--gio/gioenums.h3
-rw-r--r--gio/glocalfile.c37
-rw-r--r--gio/gsocket.c89
-rw-r--r--gio/gtestdbus.c2
-rw-r--r--gio/inotify/inotify-kernel.c15
-rw-r--r--gio/meson.build2
-rw-r--r--gio/tests/appmonitor.c100
-rw-r--r--gio/tests/file.c85
-rw-r--r--gio/tests/gdbus-example-proxy-subclass.c102
-rw-r--r--gio/tests/meson.build2
-rw-r--r--glib/gbacktrace.c4
-rw-r--r--glib/gdatetime.c142
-rw-r--r--glib/glib-unix.c20
-rw-r--r--glib/glib-unixprivate.h56
-rw-r--r--glib/gmarkup.c5
-rw-r--r--glib/gunicode.h2
-rw-r--r--glib/gwakeup.c2
-rw-r--r--glib/meson.build4
-rw-r--r--glib/msvc_recommended_pragmas.h (renamed from msvc_recommended_pragmas.h)0
-rw-r--r--glib/tests/NormalizationTest.txt92
-rw-r--r--glib/tests/mainloop.c5
-rw-r--r--glib/tests/markup-example.c168
-rw-r--r--glib/tests/meson.build1
-rw-r--r--glib/tests/unicode.c52
-rw-r--r--gmodule/meson.build6
-rw-r--r--gobject/gsignal.c26
-rw-r--r--gobject/gtype.h45
-rw-r--r--gobject/tests/signals.c5
-rw-r--r--gobject/tests/type-flags.c37
-rw-r--r--meson.build25
43 files changed, 1012 insertions, 381 deletions
diff --git a/README.win32.md b/README.win32.md
index 65f9e78e7..7f11e571e 100644
--- a/README.win32.md
+++ b/README.win32.md
@@ -30,17 +30,16 @@ On Windows setting up a correct build environment is very similar to typing
The following preprocessor macros are to be used for conditional
compilation related to Win32 in GLib-using code:
-- `G_OS_WIN32` is defined when compiling for native Win32, without
- any POSIX emulation, other than to the extent provided by the
- bundled Microsoft C library.
+- `G_OS_WIN32` and `G_PLATFORM_WIN32` are defined when compiling for native
+ Win32, without any POSIX emulation, other than to the extent provided by
+ the bundled Microsoft C library. Either can be used to check when
+ conditionally compiling GLib-using code for Win32.
- `G_WITH_CYGWIN` is defined if compiling for the Cygwin
environment. Note that `G_OS_WIN32` is *not* defined in that case, as
Cygwin is supposed to behave like Unix. `G_OS_UNIX` *is* defined by a GLib
- for Cygwin.
-
-- `G_PLATFORM_WIN32` is defined when either `G_OS_WIN32` or `G_WITH_CYGWIN`
- is defined.
+ for Cygwin, but `G_PLATFORM_WIN32` is *no longer* defined by GLib for
+ Cygwin.
These macros are defined in `glibconfig.h`, and are thus available in
all source files that include `<glib.h>`.
diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml
index b3dd9f0c9..e80a678d1 100644
--- a/docs/reference/gio/gio-docs.xml
+++ b/docs/reference/gio/gio-docs.xml
@@ -408,6 +408,10 @@
<title>Index of new symbols in 2.76</title>
<xi:include href="xml/api-index-2.76.xml"><xi:fallback /></xi:include>
</index>
+ <index id="api-index-2-78" role="2.78">
+ <title>Index of new symbols in 2.78</title>
+ <xi:include href="xml/api-index-2.78.xml"><xi:fallback /></xi:include>
+ </index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
diff --git a/docs/reference/glib/glib-docs.xml b/docs/reference/glib/glib-docs.xml
index e378fd956..2b88abd74 100644
--- a/docs/reference/glib/glib-docs.xml
+++ b/docs/reference/glib/glib-docs.xml
@@ -305,6 +305,10 @@
<title>Index of new symbols in 2.76</title>
<xi:include href="xml/api-index-2.76.xml"><xi:fallback /></xi:include>
</index>
+ <index id="api-index-2-78" role="2.78">
+ <title>Index of new symbols in 2.78</title>
+ <xi:include href="xml/api-index-2.78.xml"><xi:fallback /></xi:include>
+ </index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
diff --git a/docs/reference/gobject/gobject-docs.xml b/docs/reference/gobject/gobject-docs.xml
index ed32c3e97..eecabf933 100644
--- a/docs/reference/gobject/gobject-docs.xml
+++ b/docs/reference/gobject/gobject-docs.xml
@@ -226,6 +226,10 @@
<title>Index of new symbols in 2.76</title>
<xi:include href="xml/api-index-2.76.xml"><xi:fallback /></xi:include>
</index>
+ <index id="api-index-2-78" role="2.78">
+ <title>Index of new symbols in 2.78</title>
+ <xi:include href="xml/api-index-2.78.xml"><xi:fallback /></xi:include>
+ </index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
diff --git a/docs/reference/gobject/tut_gobject.xml b/docs/reference/gobject/tut_gobject.xml
index 7a2ecc77e..7754fec1e 100644
--- a/docs/reference/gobject/tut_gobject.xml
+++ b/docs/reference/gobject/tut_gobject.xml
@@ -294,7 +294,7 @@ ViewerFile *file = g_object_new (VIEWER_TYPE_FILE, NULL);
memory will be freed or returned to the object pool for this type.
Once the object has been freed, if it was the last instance of the type, the type's class
will be destroyed as described in <xref linkend="gtype-instantiatable-classed"/> and
- <xref linkend="gtype-non-instantiatable-classed"/>.
+ <xref linkend="gtype-non-instantiatable-non-classed"/>.
</para>
<para>
diff --git a/docs/reference/gobject/tut_gtype.xml b/docs/reference/gobject/tut_gtype.xml
index ee042889d..c2d51b9a5 100644
--- a/docs/reference/gobject/tut_gtype.xml
+++ b/docs/reference/gobject/tut_gtype.xml
@@ -599,7 +599,7 @@ B *b;
<row>
<!--entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry-->
<entry>interface initialization, see
- <xref linkend="gtype-non-instantiatable-classed-init"/></entry>
+ <xref linkend="gtype-non-instantiatable-non-classed-init"/></entry>
<entry></entry>
</row>
<row>
@@ -610,7 +610,7 @@ B *b;
<row>
<entry morerows="2">Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry>
<entry>interface destruction, see
- <xref linkend="gtype-non-instantiatable-classed-dest"/></entry>
+ <xref linkend="gtype-non-instantiatable-non-classed-dest"/></entry>
<entry></entry>
</row>
<row>
@@ -633,8 +633,8 @@ B *b;
</sect1>
- <sect1 id="gtype-non-instantiatable-classed">
- <title>Non-instantiatable classed types: interfaces</title>
+ <sect1 id="gtype-non-instantiatable-non-classed">
+ <title>Non-instantiatable non-classed types: interfaces</title>
<para>
This section covers the theory behind interfaces. See
@@ -649,7 +649,7 @@ B *b;
be seen as a playback interface. Once you know what they do, you can
control your CD player, MP3 player or anything that uses these symbols.
To declare an interface you have to register a non-instantiatable
- classed type which derives from
+ non-classed type which derives from
<link linkend="GTypeInterface"><type>GTypeInterface</type></link>. The following piece of code declares such an interface.
<informalexample><programlisting>
#define VIEWER_TYPE_EDITABLE viewer_editable_get_type ()
@@ -792,7 +792,7 @@ struct _GInterfaceInfo
</programlisting></informalexample>
</para>
- <sect2 id="gtype-non-instantiatable-classed-init">
+ <sect2 id="gtype-non-instantiatable-non-classed-init">
<title>Interface Initialization</title>
<para>
@@ -937,7 +937,7 @@ viewer_editable_default_init (ViewerEditableInterface *iface)
</sect2>
- <sect2 id="gtype-non-instantiatable-classed-dest">
+ <sect2 id="gtype-non-instantiatable-non-classed-dest">
<title>Interface Destruction</title>
<para>
@@ -955,7 +955,7 @@ viewer_editable_default_init (ViewerEditableInterface *iface)
<para>
Again, it is important to understand, as in
- <xref linkend="gtype-non-instantiatable-classed-init"/>,
+ <xref linkend="gtype-non-instantiatable-non-classed-init"/>,
that both <function>interface_finalize</function> and <function>base_finalize</function>
are invoked exactly once for the destruction of each implementation of an interface. Thus,
if you were to use one of these functions, you would need to use a static integer variable
diff --git a/docs/reference/gobject/tut_howto.xml b/docs/reference/gobject/tut_howto.xml
index 4ed178cec..9bff49b56 100644
--- a/docs/reference/gobject/tut_howto.xml
+++ b/docs/reference/gobject/tut_howto.xml
@@ -854,7 +854,7 @@ b_method_to_call (B *obj, gint some_param)
<para>
The theory behind how GObject interfaces work is given in
- <xref linkend="gtype-non-instantiatable-classed"/>; this section covers how to
+ <xref linkend="gtype-non-instantiatable-non-classed"/>; this section covers how to
define and implement an interface.
</para>
diff --git a/fuzzing/fuzz_utf8_normalize.c b/fuzzing/fuzz_utf8_normalize.c
new file mode 100644
index 000000000..2075fe504
--- /dev/null
+++ b/fuzzing/fuzz_utf8_normalize.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2023 Todd Carson
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "fuzz.h"
+
+int
+LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
+{
+ char *bounded, *terminated, *buf;
+
+ fuzz_set_logging_func ();
+
+ buf = g_malloc (size + 1);
+ memcpy (buf, data, size);
+ buf[size] = '\0';
+
+ terminated = g_utf8_normalize (buf, -1, G_NORMALIZE_ALL);
+ g_free (buf);
+
+ bounded = g_utf8_normalize ((const char *) data, size, G_NORMALIZE_ALL);
+
+ if (terminated && bounded)
+ {
+ g_assert (strcmp (terminated, bounded) == 0);
+ g_free (terminated);
+ g_free (bounded);
+ }
+ else
+ g_assert (!(terminated || bounded));
+
+ return 0;
+}
diff --git a/fuzzing/meson.build b/fuzzing/meson.build
index cd1e4c762..24d9d2554 100644
--- a/fuzzing/meson.build
+++ b/fuzzing/meson.build
@@ -33,6 +33,7 @@ fuzz_targets = [
'fuzz_uri_escape',
'fuzz_uri_parse',
'fuzz_uri_parse_params',
+ 'fuzz_utf8_normalize',
'fuzz_utf8_validate',
'fuzz_uuid_string_is_valid',
'fuzz_variant_binary',
diff --git a/gio/gappinfo.c b/gio/gappinfo.c
index 2a8ca8481..42feb9d7c 100644
--- a/gio/gappinfo.c
+++ b/gio/gappinfo.c
@@ -1658,19 +1658,34 @@ g_app_launch_context_launch_failed (GAppLaunchContext *context,
* @short_description: Monitor application information for changes
*
* #GAppInfoMonitor is a very simple object used for monitoring the app
- * info database for changes (ie: newly installed or removed
- * applications).
+ * info database for changes (newly installed or removed applications).
*
* Call g_app_info_monitor_get() to get a #GAppInfoMonitor and connect
- * to the "changed" signal.
+ * to the #GAppInfoMonitor::changed signal. The signal will be emitted once when
+ * the app info database changes, and will not be emitted again until after the
+ * next call to g_app_info_get_all() or another `g_app_info_*()` function. This
+ * is because monitoring the app info database for changes is expensive.
+ *
+ * The following functions will re-arm the #GAppInfoMonitor::changed signal so
+ * it can be emitted again:
+ * - g_app_info_get_all()
+ * - g_app_info_get_all_for_type()
+ * - g_app_info_get_default_for_type()
+ * - g_app_info_get_fallback_for_type()
+ * - g_app_info_get_recommended_for_type()
+ * - g_desktop_app_info_get_implementations()
+ * - g_desktop_app_info_new()
+ * - g_desktop_app_info_new_from_filename()
+ * - g_desktop_app_info_new_from_keyfile()
+ * - g_desktop_app_info_search()
*
* In the usual case, applications should try to make note of the change
* (doing things like invalidating caches) but not act on it. In
* particular, applications should avoid making calls to #GAppInfo APIs
* in response to the change signal, deferring these until the time that
- * the data is actually required. The exception to this case is when
+ * the updated data is actually required. The exception to this case is when
* application information is actually being displayed on the screen
- * (eg: during a search or when the list of all applications is shown).
+ * (for example, during a search or when the list of all applications is shown).
* The reason for this is that changes to the list of installed
* applications often come in groups (like during system updates) and
* rescanning the list on every change is pointless and expensive.
@@ -1728,8 +1743,10 @@ g_app_info_monitor_class_init (GAppInfoMonitorClass *class)
/**
* GAppInfoMonitor::changed:
*
- * Signal emitted when the app info database for changes (ie: newly installed
- * or removed applications).
+ * Signal emitted when the app info database changes, when applications are
+ * installed or removed.
+ *
+ * Since: 2.40
**/
g_app_info_monitor_changed_signal = g_signal_new (I_("changed"), G_TYPE_APP_INFO_MONITOR, G_SIGNAL_RUN_FIRST,
0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
@@ -1747,6 +1764,10 @@ g_app_info_monitor_class_init (GAppInfoMonitorClass *class)
* thread-default main context whenever the list of installed
* applications (as reported by g_app_info_get_all()) may have changed.
*
+ * The #GAppInfoMonitor::changed signal will only be emitted once until
+ * g_app_info_get_all() (or another `g_app_info_*()` function) is called. Doing
+ * so will re-arm the signal ready to notify about the next change.
+ *
* You must only call g_object_unref() on the return value from under
* the same main context as you created it.
*
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
index ccca4e98c..65ece54b2 100644
--- a/gio/gdbusconnection.c
+++ b/gio/gdbusconnection.c
@@ -409,7 +409,7 @@ struct _GDBusConnection
GDBusConnectionFlags flags;
/* Map used for managing method replies, protected by @lock */
- GHashTable *map_method_serial_to_task; /* guint32 -> GTask* */
+ GHashTable *map_method_serial_to_task; /* guint32 -> owned GTask* */
/* Maps used for managing signal subscription, protected by @lock */
GHashTable *map_rule_to_signal_data; /* match rule (gchar*) -> SignalData */
@@ -1061,7 +1061,7 @@ g_dbus_connection_init (GDBusConnection *connection)
g_mutex_init (&connection->lock);
g_mutex_init (&connection->init_lock);
- connection->map_method_serial_to_task = g_hash_table_new (g_direct_hash, g_direct_equal);
+ connection->map_method_serial_to_task = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
connection->map_rule_to_signal_data = g_hash_table_new (g_str_hash,
g_str_equal);
@@ -1752,7 +1752,7 @@ typedef struct
gulong cancellable_handler_id;
GSource *cancelled_idle_source; /* (owned) (nullable) */
- GSource *timeout_source;
+ GSource *timeout_source; /* (owned) (nullable) */
gboolean delivered;
} SendMessageData;
@@ -1761,6 +1761,7 @@ typedef struct
static void
send_message_data_free (SendMessageData *data)
{
+ /* These should already have been cleared by send_message_with_reply_cleanup(). */
g_assert (data->timeout_source == NULL);
g_assert (data->cancellable_handler_id == 0);
@@ -1769,7 +1770,7 @@ send_message_data_free (SendMessageData *data)
/* ---------------------------------------------------------------------------------------------------- */
-/* can be called from any thread with lock held; @task is (transfer full) */
+/* can be called from any thread with lock held; @task is (transfer none) */
static void
send_message_with_reply_cleanup (GTask *task, gboolean remove)
{
@@ -1785,7 +1786,7 @@ send_message_with_reply_cleanup (GTask *task, gboolean remove)
if (data->timeout_source != NULL)
{
g_source_destroy (data->timeout_source);
- data->timeout_source = NULL;
+ g_clear_pointer (&data->timeout_source, g_source_unref);
}
if (data->cancellable_handler_id > 0)
{
@@ -1804,13 +1805,11 @@ send_message_with_reply_cleanup (GTask *task, gboolean remove)
GUINT_TO_POINTER (data->serial));
g_warn_if_fail (removed);
}
-
- g_object_unref (task);
}
/* ---------------------------------------------------------------------------------------------------- */
-/* Called from GDBus worker thread with lock held; @task is (transfer full). */
+/* Called from GDBus worker thread with lock held; @task is (transfer none). */
static void
send_message_data_deliver_reply_unlocked (GTask *task,
GDBusMessage *reply)
@@ -1828,7 +1827,7 @@ send_message_data_deliver_reply_unlocked (GTask *task,
;
}
-/* Called from a user thread, lock is not held */
+/* Called from a user thread, lock is not held; @task is (transfer none) */
static void
send_message_data_deliver_error (GTask *task,
GQuark domain,
@@ -1845,7 +1844,10 @@ send_message_data_deliver_error (GTask *task,
return;
}
+ /* Hold a ref on @task as send_message_with_reply_cleanup() will remove it
+ * from the task map and could end up dropping the last reference */
g_object_ref (task);
+
send_message_with_reply_cleanup (task, TRUE);
CONNECTION_UNLOCK (connection);
@@ -1855,7 +1857,7 @@ send_message_data_deliver_error (GTask *task,
/* ---------------------------------------------------------------------------------------------------- */
-/* Called from a user thread, lock is not held; @task is (transfer full) */
+/* Called from a user thread, lock is not held; @task is (transfer none) */
static gboolean
send_message_with_reply_cancelled_idle_cb (gpointer user_data)
{
@@ -1887,7 +1889,7 @@ send_message_with_reply_cancelled_cb (GCancellable *cancellable,
/* ---------------------------------------------------------------------------------------------------- */
-/* Called from a user thread, lock is not held; @task is (transfer full) */
+/* Called from a user thread, lock is not held; @task is (transfer none) */
static gboolean
send_message_with_reply_timeout_cb (gpointer user_data)
{
@@ -1895,7 +1897,7 @@ send_message_with_reply_timeout_cb (gpointer user_data)
send_message_data_deliver_error (task, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
_("Timeout was reached"));
- return FALSE;
+ return G_SOURCE_REMOVE;
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -1956,7 +1958,6 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection *connect
g_source_set_static_name (data->timeout_source, "[gio] send_message_with_reply_unlocked");
g_task_attach_source (task, data->timeout_source,
(GSourceFunc) send_message_with_reply_timeout_cb);
- g_source_unref (data->timeout_source);
}
g_hash_table_insert (connection->map_method_serial_to_task,
@@ -2397,7 +2398,8 @@ on_worker_message_about_to_be_sent (GDBusWorker *worker,
return message;
}
-/* called with connection lock held, in GDBusWorker thread */
+/* called with connection lock held, in GDBusWorker thread
+ * @key, @value and @user_data are (transfer none) */
static gboolean
cancel_method_on_close (gpointer key, gpointer value, gpointer user_data)
{
@@ -3749,7 +3751,7 @@ g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
typedef struct
{
SignalSubscriber *subscriber; /* (owned) */
- GDBusMessage *message;
+ GDBusMessage *message; /* (owned) */
GDBusConnection *connection;
const gchar *sender; /* (nullable) for peer-to-peer connections */
const gchar *path;
@@ -3813,7 +3815,7 @@ emit_signal_instance_in_idle_cb (gpointer data)
static void
signal_instance_free (SignalInstance *signal_instance)
{
- g_object_unref (signal_instance->message);
+ g_clear_object (&signal_instance->message);
g_object_unref (signal_instance->connection);
signal_subscriber_unref (signal_instance->subscriber);
g_free (signal_instance);
@@ -4225,7 +4227,7 @@ has_object_been_unregistered (GDBusConnection *connection,
typedef struct
{
GDBusConnection *connection;
- GDBusMessage *message;
+ GDBusMessage *message; /* (owned) */
gpointer user_data;
const gchar *property_name;
const GDBusInterfaceVTable *vtable;
@@ -4239,7 +4241,7 @@ static void
property_data_free (PropertyData *data)
{
g_object_unref (data->connection);
- g_object_unref (data->message);
+ g_clear_object (&data->message);
g_free (data);
}
@@ -4581,7 +4583,7 @@ handle_getset_property (GDBusConnection *connection,
typedef struct
{
GDBusConnection *connection;
- GDBusMessage *message;
+ GDBusMessage *message; /* (owned) */
gpointer user_data;
const GDBusInterfaceVTable *vtable;
GDBusInterfaceInfo *interface_info;
@@ -4590,10 +4592,10 @@ typedef struct
} PropertyGetAllData;
static void
-property_get_all_data_free (PropertyData *data)
+property_get_all_data_free (PropertyGetAllData *data)
{
g_object_unref (data->connection);
- g_object_unref (data->message);
+ g_clear_object (&data->message);
g_free (data);
}
@@ -6821,7 +6823,7 @@ typedef struct
static void
subtree_deferred_data_free (SubtreeDeferredData *data)
{
- g_object_unref (data->message);
+ g_clear_object (&data->message);
exported_subtree_unref (data->es);
g_free (data);
}
diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c
index 762afcee4..2c9238c63 100644
--- a/gio/gdbusprivate.c
+++ b/gio/gdbusprivate.c
@@ -889,21 +889,25 @@ _g_dbus_worker_do_initial_read (gpointer data)
struct _MessageToWriteData
{
GDBusWorker *worker;
- GDBusMessage *message;
+ GDBusMessage *message; /* (owned) */
gchar *blob;
gsize blob_size;
gsize total_written;
- GTask *task;
+ GTask *task; /* (owned) and (nullable) before writing starts and after g_task_return_*() is called */
};
static void
message_to_write_data_free (MessageToWriteData *data)
{
_g_dbus_worker_unref (data->worker);
- if (data->message)
- g_object_unref (data->message);
+ g_clear_object (&data->message);
g_free (data->blob);
+
+ /* The task must either not have been created, or have been created, returned
+ * and finalised by now. */
+ g_assert (data->task == NULL);
+
g_slice_free (MessageToWriteData, data);
}
@@ -915,21 +919,22 @@ static void write_message_continue_writing (MessageToWriteData *data);
*
* write-lock is not held on entry
* output_pending is PENDING_WRITE on entry
+ * @user_data is (transfer full)
*/
static void
write_message_async_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
- MessageToWriteData *data = user_data;
- GTask *task;
+ MessageToWriteData *data = g_steal_pointer (&user_data);
gssize bytes_written;
GError *error;
- /* Note: we can't access data->task after calling g_task_return_* () because the
- * callback can free @data and we're not completing in idle. So use a copy of the pointer.
- */
- task = data->task;
+ /* The ownership of @data is a bit odd in this function: itโ€™s (transfer full)
+ * when the function is called, but the code paths which call g_task_return_*()
+ * on @data->task will indirectly cause it to be freed, because @data is
+ * always guaranteed to be the user_data in the #GTask. So thatโ€™s why it looks
+ * like @data is not always freed on every code path in this function. */
error = NULL;
bytes_written = g_output_stream_write_finish (G_OUTPUT_STREAM (source_object),
@@ -937,8 +942,9 @@ write_message_async_cb (GObject *source_object,
&error);
if (bytes_written == -1)
{
+ GTask *task = g_steal_pointer (&data->task);
g_task_return_error (task, error);
- g_object_unref (task);
+ g_clear_object (&task);
goto out;
}
g_assert (bytes_written > 0); /* zero is never returned */
@@ -949,12 +955,13 @@ write_message_async_cb (GObject *source_object,
g_assert (data->total_written <= data->blob_size);
if (data->total_written == data->blob_size)
{
+ GTask *task = g_steal_pointer (&data->task);
g_task_return_boolean (task, TRUE);
- g_object_unref (task);
+ g_clear_object (&task);
goto out;
}
- write_message_continue_writing (data);
+ write_message_continue_writing (g_steal_pointer (&data));
out:
;
@@ -971,9 +978,9 @@ on_socket_ready (GSocket *socket,
GIOCondition condition,
gpointer user_data)
{
- MessageToWriteData *data = user_data;
- write_message_continue_writing (data);
- return FALSE; /* remove source */
+ MessageToWriteData *data = g_steal_pointer (&user_data);
+ write_message_continue_writing (g_steal_pointer (&data));
+ return G_SOURCE_REMOVE;
}
#endif
@@ -981,22 +988,21 @@ on_socket_ready (GSocket *socket,
*
* write-lock is not held on entry
* output_pending is PENDING_WRITE on entry
+ * @data is (transfer full)
*/
static void
write_message_continue_writing (MessageToWriteData *data)
{
GOutputStream *ostream;
#ifdef G_OS_UNIX
- GTask *task;
GUnixFDList *fd_list;
#endif
-#ifdef G_OS_UNIX
- /* Note: we can't access data->task after calling g_task_return_* () because the
- * callback can free @data and we're not completing in idle. So use a copy of the pointer.
- */
- task = data->task;
-#endif
+ /* The ownership of @data is a bit odd in this function: itโ€™s (transfer full)
+ * when the function is called, but the code paths which call g_task_return_*()
+ * on @data->task will indirectly cause it to be freed, because @data is
+ * always guaranteed to be the user_data in the #GTask. So thatโ€™s why it looks
+ * like @data is not always freed on every code path in this function. */
ostream = g_io_stream_get_output_stream (data->worker->stream);
#ifdef G_OS_UNIX
@@ -1025,11 +1031,12 @@ write_message_continue_writing (MessageToWriteData *data)
{
if (!(data->worker->capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING))
{
+ GTask *task = g_steal_pointer (&data->task);
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_FAILED,
"Tried sending a file descriptor but remote peer does not support this capability");
- g_object_unref (task);
+ g_clear_object (&task);
goto out;
}
control_message = g_unix_fd_message_new_with_fd_list (fd_list);
@@ -1059,16 +1066,20 @@ write_message_continue_writing (MessageToWriteData *data)
data->worker->cancellable);
g_source_set_callback (source,
(GSourceFunc) on_socket_ready,
- data,
+ g_steal_pointer (&data),
NULL); /* GDestroyNotify */
g_source_attach (source, g_main_context_get_thread_default ());
g_source_unref (source);
g_error_free (error);
goto out;
}
- g_task_return_error (task, error);
- g_object_unref (task);
- goto out;
+ else
+ {
+ GTask *task = g_steal_pointer (&data->task);
+ g_task_return_error (task, error);
+ g_clear_object (&task);
+ goto out;
+ }
}
g_assert (bytes_written > 0); /* zero is never returned */
@@ -1078,12 +1089,13 @@ write_message_continue_writing (MessageToWriteData *data)
g_assert (data->total_written <= data->blob_size);
if (data->total_written == data->blob_size)
{
+ GTask *task = g_steal_pointer (&data->task);
g_task_return_boolean (task, TRUE);
- g_object_unref (task);
+ g_clear_object (&task);
goto out;
}
- write_message_continue_writing (data);
+ write_message_continue_writing (g_steal_pointer (&data));
}
#endif
else
@@ -1094,12 +1106,13 @@ write_message_continue_writing (MessageToWriteData *data)
/* We were trying to write byte 0 of the message, which needs
* the fd list to be attached to it, but this connection doesn't
* support doing that. */
+ GTask *task = g_steal_pointer (&data->task);
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_FAILED,
"Tried sending a file descriptor on unsupported stream of type %s",
g_type_name (G_TYPE_FROM_INSTANCE (ostream)));
- g_object_unref (task);
+ g_clear_object (&task);
goto out;
}
#endif
@@ -1110,7 +1123,7 @@ write_message_continue_writing (MessageToWriteData *data)
G_PRIORITY_DEFAULT,
data->worker->cancellable,
write_message_async_cb,
- data);
+ data); /* steal @data */
}
#ifdef G_OS_UNIX
out:
@@ -1133,7 +1146,7 @@ write_message_async (GDBusWorker *worker,
g_task_set_source_tag (data->task, write_message_async);
g_task_set_name (data->task, "[gio] D-Bus write message");
data->total_written = 0;
- write_message_continue_writing (data);
+ write_message_continue_writing (g_steal_pointer (&data));
}
/* called in private thread shared by all GDBusConnection instances (with write-lock held) */
@@ -1322,6 +1335,7 @@ prepare_flush_unlocked (GDBusWorker *worker)
*
* write-lock is not held on entry
* output_pending is PENDING_WRITE on entry
+ * @user_data is (transfer full)
*/
static void
write_message_cb (GObject *source_object,
@@ -1540,7 +1554,7 @@ continue_writing (GDBusWorker *worker)
write_message_async (worker,
data,
write_message_cb,
- data);
+ data); /* takes ownership of @data as user_data */
}
}
diff --git a/gio/gio-tool-info.c b/gio/gio-tool-info.c
index 749bd2d13..59568ae7a 100644
--- a/gio/gio-tool-info.c
+++ b/gio/gio-tool-info.c
@@ -173,7 +173,7 @@ show_info (GFile *file, GFileInfo *info)
{
/* Translators: This is a noun and represents and attribute of a file */
flatten = flatten_string (name);
- g_print (_("display name: %s\n"), flatten);
+ g_print (_("edit name: %s\n"), flatten);
g_free (flatten);
}
diff --git a/gio/gioenums.h b/gio/gioenums.h
index 7fd74a43e..c820cd36d 100644
--- a/gio/gioenums.h
+++ b/gio/gioenums.h
@@ -224,6 +224,9 @@ typedef enum {
* sizes. Normally, the block-size is used, if available, as this is a
* more accurate representation of disk space used.
* Compare with `du --apparent-size`.
+ * Since GLib 2.78. and similarly to `du` since GNU Coreutils 9.2, this will
+ * ignore the sizes of file types other than regular files and links, as the
+ * sizes of other file types are not specified in a standard way.
* @G_FILE_MEASURE_NO_XDEV: Do not cross mount point boundaries.
* Compare with `du -x`.
*
diff --git a/gio/glocalfile.c b/gio/glocalfile.c
index 67d4b99fb..dbb56902d 100644
--- a/gio/glocalfile.c
+++ b/gio/glocalfile.c
@@ -86,6 +86,9 @@
#define FILE_READ_ONLY_VOLUME 0x00080000
#endif
+#ifndef S_ISREG
+#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
+#endif
#ifndef S_ISDIR
#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
#endif
@@ -2777,6 +2780,39 @@ g_local_file_measure_size_of_contents (gint fd,
MeasureState *state,
GError **error);
+/*
+ * _g_stat_is_size_usable:
+ * @buf: a #GLocalFileStat.
+ *
+ * Checks if the file type is such that the `st_size` field of `struct stat` is
+ * well-defined by POSIX.
+ * (see https://pubs.opengroup.org/onlinepubs/009696799/basedefs/sys/stat.h.html)
+ *
+ * This behaviour is aligned with `du` from GNU Coreutils 9.2+
+ * (see https://lists.gnu.org/archive/html/bug-coreutils/2023-03/msg00007.html)
+ * and makes apparent size sums well-defined; formerly, they depended on the
+ * implementation, and could differ across filesystems.
+ *
+ * Returns: %TRUE if the size field is well-defined, %FALSE otherwise.
+ **/
+inline static gboolean
+_g_stat_is_size_usable (const GLocalFileStat *buf)
+{
+#ifndef HAVE_STATX
+ /* Memory objects are defined by POSIX, but are not supported by statx nor Windows */
+#ifdef S_TYPEISSHM
+ if (S_TYPEISSHM (buf))
+ return TRUE;
+#endif
+#ifdef S_TYPEISTMO
+ if (S_TYPEISTMO (buf))
+ return TRUE;
+#endif
+#endif
+
+ return S_ISREG (_g_stat_mode (buf)) || S_ISLNK (_g_stat_mode (buf));
+}
+
static gboolean
g_local_file_measure_size_of_file (gint parent_fd,
GSList *name,
@@ -2836,6 +2872,7 @@ g_local_file_measure_size_of_file (gint parent_fd,
state->disk_usage += _g_stat_blocks (&buf) * G_GUINT64_CONSTANT (512);
else
#endif
+ if (_g_stat_is_size_usable (&buf))
state->disk_usage += _g_stat_size (&buf);
if (S_ISDIR (_g_stat_mode (&buf)))
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 50ef42f83..d25591a17 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -587,7 +587,38 @@ g_socket_details_from_fd (GSocket *socket)
socket_strerror (errsv));
}
-/* Wrapper around socket() that is shared with gnetworkmonitornetlink.c */
+static void
+socket_set_nonblock (int fd)
+{
+#ifndef G_OS_WIN32
+ GError *error = NULL;
+#else
+ gulong arg;
+#endif
+
+ /* Always use native nonblocking sockets, as Windows sets sockets to
+ * nonblocking automatically in certain operations. This way we make
+ * things work the same on all platforms.
+ */
+#ifndef G_OS_WIN32
+ if (!g_unix_set_fd_nonblocking (fd, TRUE, &error))
+ {
+ g_warning ("Error setting socket to nonblocking mode: %s", error->message);
+ g_clear_error (&error);
+ }
+#else
+ arg = TRUE;
+
+ if (ioctlsocket (fd, FIONBIO, &arg) == SOCKET_ERROR)
+ {
+ int errsv = get_socket_errno ();
+ g_warning ("Error setting socket status flags: %s", socket_strerror (errsv));
+ }
+#endif
+}
+
+/* Wrapper around socket() that is shared with gnetworkmonitornetlink.c.
+ * It always sets SOCK_CLOEXEC | SOCK_NONBLOCK. */
gint
g_socket (gint domain,
gint type,
@@ -596,13 +627,13 @@ g_socket (gint domain,
{
int fd, errsv;
-#ifdef SOCK_CLOEXEC
- fd = socket (domain, type | SOCK_CLOEXEC, protocol);
+#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
+ fd = socket (domain, type | SOCK_CLOEXEC | SOCK_NONBLOCK, protocol);
errsv = errno;
if (fd != -1)
return fd;
- /* It's possible that libc has SOCK_CLOEXEC but the kernel does not */
+ /* It's possible that libc has SOCK_CLOEXEC and/or SOCK_NONBLOCK but the kernel does not */
if (fd < 0 && (errsv == EINVAL || errsv == EPROTOTYPE))
#endif
fd = socket (domain, type, protocol);
@@ -644,9 +675,13 @@ g_socket (gint domain,
}
#endif
+ /* Ensure the socket is non-blocking. */
+ socket_set_nonblock (fd);
+
return fd;
}
+/* Returned socket has SOCK_CLOEXEC | SOCK_NONBLOCK set. */
static gint
g_socket_create_socket (GSocketFamily family,
GSocketType type,
@@ -696,44 +731,22 @@ g_socket_constructed (GObject *object)
GSocket *socket = G_SOCKET (object);
if (socket->priv->fd >= 0)
- /* create socket->priv info from the fd */
- g_socket_details_from_fd (socket);
-
+ {
+ /* create socket->priv info from the fd and ensure itโ€™s non-blocking */
+ g_socket_details_from_fd (socket);
+ socket_set_nonblock (socket->priv->fd);
+ }
else
- /* create the fd from socket->priv info */
- socket->priv->fd = g_socket_create_socket (socket->priv->family,
- socket->priv->type,
- socket->priv->protocol,
- &socket->priv->construct_error);
+ {
+ /* create the fd from socket->priv info; this sets it non-blocking by construction */
+ socket->priv->fd = g_socket_create_socket (socket->priv->family,
+ socket->priv->type,
+ socket->priv->protocol,
+ &socket->priv->construct_error);
+ }
if (socket->priv->fd != -1)
{
-#ifndef G_OS_WIN32
- GError *error = NULL;
-#else
- gulong arg;
-#endif
-
- /* Always use native nonblocking sockets, as Windows sets sockets to
- * nonblocking automatically in certain operations. This way we make
- * things work the same on all platforms.
- */
-#ifndef G_OS_WIN32
- if (!g_unix_set_fd_nonblocking (socket->priv->fd, TRUE, &error))
- {
- g_warning ("Error setting socket nonblocking: %s", error->message);
- g_clear_error (&error);
- }
-#else
- arg = TRUE;
-
- if (ioctlsocket (socket->priv->fd, FIONBIO, &arg) == SOCKET_ERROR)
- {
- int errsv = get_socket_errno ();
- g_warning ("Error setting socket status flags: %s", socket_strerror (errsv));
- }
-#endif
-
#ifdef SO_NOSIGPIPE
/* See note about SIGPIPE below. */
g_socket_set_option (socket, SOL_SOCKET, SO_NOSIGPIPE, TRUE, NULL);
diff --git a/gio/gtestdbus.c b/gio/gtestdbus.c
index 34cead176..8c5de3355 100644
--- a/gio/gtestdbus.c
+++ b/gio/gtestdbus.c
@@ -249,7 +249,7 @@ watcher_init (void)
gint pipe_fds[2];
/* fork a child to clean up when we are killed */
- if (!g_unix_open_pipe_internal (pipe_fds, TRUE))
+ if (!g_unix_open_pipe_internal (pipe_fds, TRUE, FALSE))
{
errsv = errno;
g_warning ("pipe() failed: %s", g_strerror (errsv));
diff --git a/gio/inotify/inotify-kernel.c b/gio/inotify/inotify-kernel.c
index 92d61fc31..7733d398e 100644
--- a/gio/inotify/inotify-kernel.c
+++ b/gio/inotify/inotify-kernel.c
@@ -377,6 +377,7 @@ ik_source_new (gboolean (* callback) (ik_event_t *event))
};
InotifyKernelSource *iks;
GSource *source;
+ gboolean should_set_nonblock = FALSE;
source = g_source_new (&source_funcs, sizeof (InotifyKernelSource));
iks = (InotifyKernelSource *) source;
@@ -384,17 +385,23 @@ ik_source_new (gboolean (* callback) (ik_event_t *event))
g_source_set_static_name (source, "inotify kernel source");
iks->unmatched_moves = g_hash_table_new (NULL, NULL);
- iks->fd = inotify_init1 (IN_CLOEXEC);
+ iks->fd = inotify_init1 (IN_CLOEXEC | IN_NONBLOCK);
if (iks->fd < 0)
- iks->fd = inotify_init ();
+ {
+ should_set_nonblock = TRUE;
+ iks->fd = inotify_init ();
+ }
if (iks->fd >= 0)
{
GError *error = NULL;
- g_unix_set_fd_nonblocking (iks->fd, TRUE, &error);
- g_assert_no_error (error);
+ if (should_set_nonblock)
+ {
+ g_unix_set_fd_nonblocking (iks->fd, TRUE, &error);
+ g_assert_no_error (error);
+ }
iks->fd_tag = g_source_add_unix_fd (source, iks->fd, G_IO_IN);
}
diff --git a/gio/meson.build b/gio/meson.build
index 462606f3b..396ca2f4c 100644
--- a/gio/meson.build
+++ b/gio/meson.build
@@ -930,7 +930,7 @@ endif
# Dependencies used by executables below
have_libelf = false
-libelf = dependency('libelf', version : '>= 0.8.12', required : get_option ('libelf'))
+libelf = dependency('libelf', version : '>= 0.8.12', required : false)
if libelf.found()
have_libelf = true
else
diff --git a/gio/tests/appmonitor.c b/gio/tests/appmonitor.c
index 9db8c4dea..c1d68b889 100644
--- a/gio/tests/appmonitor.c
+++ b/gio/tests/appmonitor.c
@@ -1,6 +1,31 @@
+/* GLib testing framework examples and tests
+ *
+ * Copyright ยฉ 2013 Red Hat, Inc.
+ * Copyright ยฉ 2015, 2017, 2018 Endless Mobile, Inc.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
#include <gio/gio.h>
#include <gstdio.h>
+#ifdef G_OS_UNIX
+#include <gio/gdesktopappinfo.h>
+#endif
+
typedef struct
{
gchar *applications_dir;
@@ -24,6 +49,7 @@ teardown (Fixture *fixture,
g_clear_pointer (&fixture->applications_dir, g_free);
}
+#ifdef G_OS_UNIX
static gboolean
create_app (gpointer data)
{
@@ -50,73 +76,95 @@ delete_app (gpointer data)
g_remove (path);
}
-static gboolean changed_fired;
-
static void
-changed_cb (GAppInfoMonitor *monitor, GMainLoop *loop)
+changed_cb (GAppInfoMonitor *monitor,
+ gpointer user_data)
{
- changed_fired = TRUE;
- g_main_loop_quit (loop);
+ gboolean *changed_fired = user_data;
+
+ *changed_fired = TRUE;
+ g_main_context_wakeup (g_main_context_get_thread_default ());
}
static gboolean
-quit_loop (gpointer data)
+timeout_cb (gpointer user_data)
{
- GMainLoop *loop = data;
+ gboolean *timed_out = user_data;
- if (g_main_loop_is_running (loop))
- g_main_loop_quit (loop);
+ g_assert (!timed_out);
+ *timed_out = TRUE;
+ g_main_context_wakeup (g_main_context_get_thread_default ());
return G_SOURCE_REMOVE;
}
+#endif /* G_OS_UNIX */
static void
test_app_monitor (Fixture *fixture,
gconstpointer user_data)
{
+#ifdef G_OS_UNIX
gchar *app_path;
GAppInfoMonitor *monitor;
- GMainLoop *loop;
-
-#ifdef G_OS_WIN32
- g_test_skip (".desktop monitor on win32");
- return;
-#endif
+ GMainContext *context = NULL; /* use the global default main context */
+ GSource *timeout_source = NULL;
+ GDesktopAppInfo *app = NULL;
+ gboolean changed_fired = FALSE;
+ gboolean timed_out = FALSE;
app_path = g_build_filename (fixture->applications_dir, "app.desktop", NULL);
/* FIXME: this shouldn't be required */
g_list_free_full (g_app_info_get_all (), g_object_unref);
+ /* Create an app monitor and check that its ::changed signal is emitted when
+ * a new app is installed. */
monitor = g_app_info_monitor_get ();
- loop = g_main_loop_new (NULL, FALSE);
- g_signal_connect (monitor, "changed", G_CALLBACK (changed_cb), loop);
+ g_signal_connect (monitor, "changed", G_CALLBACK (changed_cb), &changed_fired);
g_idle_add (create_app, app_path);
- g_timeout_add_seconds (3, quit_loop, loop);
+ timeout_source = g_timeout_source_new_seconds (3);
+ g_source_set_callback (timeout_source, timeout_cb, &timed_out, NULL);
+ g_source_attach (timeout_source, NULL);
+
+ while (!changed_fired && !timed_out)
+ g_main_context_iteration (context, TRUE);
- g_main_loop_run (loop);
- g_assert (changed_fired);
+ g_assert_true (changed_fired);
changed_fired = FALSE;
- /* FIXME: this shouldn't be required */
- g_list_free_full (g_app_info_get_all (), g_object_unref);
+ g_source_destroy (timeout_source);
+ g_clear_pointer (&timeout_source, g_source_unref);
+
+ /* Check that the app is now queryable. This has the side-effect of re-arming
+ * the #GAppInfoMonitor::changed signal for the next part of the test. */
+ app = g_desktop_app_info_new ("app.desktop");
+ g_assert_nonnull (app);
+ g_clear_object (&app);
- g_timeout_add_seconds (3, quit_loop, loop);
+ /* Now check that ::changed is emitted when an app is uninstalled. */
+ timeout_source = g_timeout_source_new_seconds (3);
+ g_source_set_callback (timeout_source, timeout_cb, &timed_out, NULL);
+ g_source_attach (timeout_source, NULL);
delete_app (app_path);
- g_main_loop_run (loop);
+ while (!changed_fired && !timed_out)
+ g_main_context_iteration (context, TRUE);
- g_assert (changed_fired);
+ g_assert_true (changed_fired);
- g_main_loop_unref (loop);
+ g_source_destroy (timeout_source);
+ g_clear_pointer (&timeout_source, g_source_unref);
g_remove (app_path);
g_object_unref (monitor);
g_free (app_path);
+#else /* if !G_OS_UNIX */
+ g_test_skip (".desktop monitor on win32");
+#endif /* !G_OS_UNIX */
}
int
diff --git a/gio/tests/file.c b/gio/tests/file.c
index d16eda5c0..ad2f945f9 100644
--- a/gio/tests/file.c
+++ b/gio/tests/file.c
@@ -2515,75 +2515,10 @@ test_copy_preserve_mode (void)
#endif
}
-static gchar *
-splice_to_string (GInputStream *stream,
- GError **error)
-{
- GMemoryOutputStream *buffer = NULL;
- char *ret = NULL;
-
- buffer = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
- if (g_output_stream_splice ((GOutputStream*)buffer, stream, 0, NULL, error) < 0)
- goto out;
-
- if (!g_output_stream_write ((GOutputStream*)buffer, "\0", 1, NULL, error))
- goto out;
-
- if (!g_output_stream_close ((GOutputStream*)buffer, NULL, error))
- goto out;
-
- ret = g_memory_output_stream_steal_data (buffer);
- out:
- g_clear_object (&buffer);
- return ret;
-}
-
-static gboolean
-get_size_from_du (const gchar *path, guint64 *size)
-{
- GSubprocess *du;
- gboolean ok;
- gchar *result;
- gchar *endptr;
- GError *error = NULL;
- gchar *du_path = NULL;
-
-#ifndef __APPLE__
- du_path = g_find_program_in_path ("du");
-#endif
-
- /* If we canโ€™t find du, donโ€™t try and run the test. */
- if (du_path == NULL)
- return FALSE;
-
- g_free (du_path);
-
- du = g_subprocess_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE,
- &error,
- "du", "--bytes", "-s", path, NULL);
- g_assert_no_error (error);
-
- result = splice_to_string (g_subprocess_get_stdout_pipe (du), &error);
- g_assert_no_error (error);
-
- *size = g_ascii_strtoll (result, &endptr, 10);
-
- g_subprocess_wait (du, NULL, &error);
- g_assert_no_error (error);
-
- ok = g_subprocess_get_successful (du);
-
- g_object_unref (du);
- g_free (result);
-
- return ok;
-}
-
static void
test_measure (void)
{
GFile *file;
- guint64 size;
guint64 num_bytes;
guint64 num_dirs;
guint64 num_files;
@@ -2594,12 +2529,6 @@ test_measure (void)
path = g_test_build_filename (G_TEST_DIST, "desktop-files", NULL);
file = g_file_new_for_path (path);
- if (!get_size_from_du (path, &size))
- {
- g_test_message ("du not found or fail to run, skipping byte measurement");
- size = 0;
- }
-
ok = g_file_measure_disk_usage (file,
G_FILE_MEASURE_APPARENT_SIZE,
NULL,
@@ -2612,8 +2541,7 @@ test_measure (void)
g_assert_true (ok);
g_assert_no_error (error);
- if (size > 0)
- g_assert_cmpuint (num_bytes, ==, size);
+ g_assert_cmpuint (num_bytes, ==, 74478);
g_assert_cmpuint (num_dirs, ==, 6);
g_assert_cmpuint (num_files, ==, 32);
@@ -2665,8 +2593,7 @@ measure_done (GObject *source,
g_assert_true (ok);
g_assert_no_error (error);
- if (data->expected_bytes > 0)
- g_assert_cmpuint (data->expected_bytes, ==, num_bytes);
+ g_assert_cmpuint (data->expected_bytes, ==, num_bytes);
g_assert_cmpuint (data->expected_dirs, ==, num_dirs);
g_assert_cmpuint (data->expected_files, ==, num_files);
@@ -2695,15 +2622,9 @@ test_measure_async (void)
path = g_test_build_filename (G_TEST_DIST, "desktop-files", NULL);
file = g_file_new_for_path (path);
-
- if (!get_size_from_du (path, &data->expected_bytes))
- {
- g_test_message ("du not found or fail to run, skipping byte measurement");
- data->expected_bytes = 0;
- }
-
g_free (path);
+ data->expected_bytes = 74478;
data->expected_dirs = 6;
data->expected_files = 32;
diff --git a/gio/tests/gdbus-example-proxy-subclass.c b/gio/tests/gdbus-example-proxy-subclass.c
index 05314ba2a..91b377c48 100644
--- a/gio/tests/gdbus-example-proxy-subclass.c
+++ b/gio/tests/gdbus-example-proxy-subclass.c
@@ -340,9 +340,111 @@ accounts_user_frobnicate_finish (AccountsUser *user,
}
/* ---------------------------------------------------------------------------------------------------- */
+/* Example usage of the AccountsUser type */
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+print_user (AccountsUser *user)
+{
+ g_print (" user-name = `%s'\n", accounts_user_get_user_name (user));
+ g_print (" real-name = `%s'\n", accounts_user_get_real_name (user));
+ g_print (" automatic-login = %s\n", accounts_user_get_automatic_login (user) ? "true" : "false");
+}
+
+static void
+on_changed (AccountsUser *user,
+ gpointer user_data)
+{
+ g_print ("+++ Received the AccountsUser::changed signal\n");
+ print_user (user);
+}
+
+static void
+on_notify (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ AccountsUser *user = ACCOUNTS_USER (object);
+ g_print ("+++ Received the GObject::notify signal for property `%s'\n",
+ pspec->name);
+ print_user (user);
+}
+
+static void
+on_accounts_proxy_available (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ GObject *user_object;
+ AccountsUser *user;
+
+ user_object = g_async_initable_new_finish (G_ASYNC_INITABLE (object),
+ result,
+ &error);
+ if (!user_object)
+ {
+ g_error ("Failed to create proxy: %s", error->message);
+ g_clear_error (&error);
+ return;
+ }
+ user = ACCOUNTS_USER (user_object);
+
+ g_print ("+++ Acquired proxy for user\n");
+ print_user (user);
+
+ g_signal_connect (user,
+ "notify",
+ G_CALLBACK (on_notify),
+ NULL);
+ g_signal_connect (user,
+ "changed",
+ G_CALLBACK (on_changed),
+ NULL);
+}
+
+static void
+on_accounts_appeared (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ g_async_initable_new_async (ACCOUNTS_TYPE_USER, 0, NULL,
+ on_accounts_proxy_available,
+ "g-flags", 0,
+ "g-interface-info", NULL,
+ "g-unique-bus-name", name_owner,
+ "g-connection", connection,
+ "g-object-path", "/org/freedesktop/Accounts/User500",
+ "g-interface-name", "org.freedesktop.Accounts.User");
+}
+
+static void
+on_accounts_vanished (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
gint
main (gint argc, gchar *argv[])
{
+ guint watcher_id;
+ GMainLoop *loop;
+
+ watcher_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
+ "org.freedesktop.Accounts",
+ G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+ on_accounts_appeared,
+ on_accounts_vanished,
+ NULL, NULL);
+
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+ g_bus_unwatch_name (watcher_id);
+
return 0;
}
diff --git a/gio/tests/meson.build b/gio/tests/meson.build
index 2631b1285..2f312e056 100644
--- a/gio/tests/meson.build
+++ b/gio/tests/meson.build
@@ -767,7 +767,7 @@ if not meson.is_cross_build()
resource_plugin += shared_module('resourceplugin',
sources: ['resourceplugin.c', plugin_resources_c],
- link_args : export_dynamic_ldflags,
+ c_args : export_dynamic_cflags,
dependencies : common_gio_tests_deps,
install_dir : installed_tests_execdir,
install_tag : 'tests',
diff --git a/glib/gbacktrace.c b/glib/gbacktrace.c
index b708b1636..0f81502e5 100644
--- a/glib/gbacktrace.c
+++ b/glib/gbacktrace.c
@@ -398,8 +398,8 @@ stack_trace (const char * const *args)
stack_trace_done = FALSE;
signal (SIGCHLD, stack_trace_sigchld);
- if (!g_unix_open_pipe_internal (in_fd, TRUE) ||
- !g_unix_open_pipe_internal (out_fd, TRUE))
+ if (!g_unix_open_pipe_internal (in_fd, TRUE, FALSE) ||
+ !g_unix_open_pipe_internal (out_fd, TRUE, FALSE))
{
perror ("unable to open pipe");
_exit (0);
diff --git a/glib/gdatetime.c b/glib/gdatetime.c
index a9c472e55..2640e3b24 100644
--- a/glib/gdatetime.c
+++ b/glib/gdatetime.c
@@ -3340,103 +3340,103 @@ g_date_time_format_utf8 (GDateTime *datetime,
* Creates a newly allocated string representing the requested @format.
*
* The format strings understood by this function are a subset of the
- * strftime() format language as specified by C99. The \%D, \%U and \%W
- * conversions are not supported, nor is the 'E' modifier. The GNU
- * extensions \%k, \%l, \%s and \%P are supported, however, as are the
- * '0', '_' and '-' modifiers. The Python extension \%f is also supported.
+ * `strftime()` format language as specified by C99. The `%D`, `%U` and `%W`
+ * conversions are not supported, nor is the `E` modifier. The GNU
+ * extensions `%k`, `%l`, `%s` and `%P` are supported, however, as are the
+ * `0`, `_` and `-` modifiers. The Python extension `%f` is also supported.
*
- * In contrast to strftime(), this function always produces a UTF-8
+ * In contrast to `strftime()`, this function always produces a UTF-8
* string, regardless of the current locale. Note that the rendering of
- * many formats is locale-dependent and may not match the strftime()
+ * many formats is locale-dependent and may not match the `strftime()`
* output exactly.
*
* The following format specifiers are supported:
*
- * - \%a: the abbreviated weekday name according to the current locale
- * - \%A: the full weekday name according to the current locale
- * - \%b: the abbreviated month name according to the current locale
- * - \%B: the full month name according to the current locale
- * - \%c: the preferred date and time representation for the current locale
- * - \%C: the century number (year/100) as a 2-digit integer (00-99)
- * - \%d: the day of the month as a decimal number (range 01 to 31)
- * - \%e: the day of the month as a decimal number (range 1 to 31);
- * single digits are preceded by a figure space
- * - \%F: equivalent to `%Y-%m-%d` (the ISO 8601 date format)
- * - \%g: the last two digits of the ISO 8601 week-based year as a
- * decimal number (00-99). This works well with \%V and \%u.
- * - \%G: the ISO 8601 week-based year as a decimal number. This works
- * well with \%V and \%u.
- * - \%h: equivalent to \%b
- * - \%H: the hour as a decimal number using a 24-hour clock (range 00 to 23)
- * - \%I: the hour as a decimal number using a 12-hour clock (range 01 to 12)
- * - \%j: the day of the year as a decimal number (range 001 to 366)
- * - \%k: the hour (24-hour clock) as a decimal number (range 0 to 23);
- * single digits are preceded by a figure space
- * - \%l: the hour (12-hour clock) as a decimal number (range 1 to 12);
- * single digits are preceded by a figure space
- * - \%m: the month as a decimal number (range 01 to 12)
- * - \%M: the minute as a decimal number (range 00 to 59)
- * - \%f: the microsecond as a decimal number (range 000000 to 999999)
- * - \%p: either "AM" or "PM" according to the given time value, or the
+ * - `%a`: the abbreviated weekday name according to the current locale
+ * - `%A`: the full weekday name according to the current locale
+ * - `%b`: the abbreviated month name according to the current locale
+ * - `%B`: the full month name according to the current locale
+ * - `%c`: the preferred date and time representation for the current locale
+ * - `%C`: the century number (year/100) as a 2-digit integer (00-99)
+ * - `%d`: the day of the month as a decimal number (range 01 to 31)
+ * - `%e`: the day of the month as a decimal number (range 1 to 31);
+ * single digits are preceded by a figure space (U+2007)
+ * - `%F`: equivalent to `%Y-%m-%d` (the ISO 8601 date format)
+ * - `%g`: the last two digits of the ISO 8601 week-based year as a
+ * decimal number (00-99). This works well with `%V` and `%u`.
+ * - `%G`: the ISO 8601 week-based year as a decimal number. This works
+ * well with `%V` and `%u`.
+ * - `%h`: equivalent to `%b`
+ * - `%H`: the hour as a decimal number using a 24-hour clock (range 00 to 23)
+ * - `%I`: the hour as a decimal number using a 12-hour clock (range 01 to 12)
+ * - `%j`: the day of the year as a decimal number (range 001 to 366)
+ * - `%k`: the hour (24-hour clock) as a decimal number (range 0 to 23);
+ * single digits are preceded by a figure space (U+2007)
+ * - `%l`: the hour (12-hour clock) as a decimal number (range 1 to 12);
+ * single digits are preceded by a figure space (U+2007)
+ * - `%m`: the month as a decimal number (range 01 to 12)
+ * - `%M`: the minute as a decimal number (range 00 to 59)
+ * - `%f`: the microsecond as a decimal number (range 000000 to 999999)
+ * - `%p`: either โ€˜AMโ€™ or โ€˜PMโ€™ according to the given time value, or the
* corresponding strings for the current locale. Noon is treated as
- * "PM" and midnight as "AM". Use of this format specifier is discouraged, as
- * many locales have no concept of AM/PM formatting. Use \%c or \%X instead.
- * - \%P: like \%p but lowercase: "am" or "pm" or a corresponding string for
+ * โ€˜PMโ€™ and midnight as โ€˜AMโ€™. Use of this format specifier is discouraged, as
+ * many locales have no concept of AM/PM formatting. Use `%c` or `%X` instead.
+ * - `%P`: like `%p` but lowercase: โ€˜amโ€™ or โ€˜pmโ€™ or a corresponding string for
* the current locale. Use of this format specifier is discouraged, as
- * many locales have no concept of AM/PM formatting. Use \%c or \%X instead.
- * - \%r: the time in a.m. or p.m. notation. Use of this format specifier is
- * discouraged, as many locales have no concept of AM/PM formatting. Use \%c
- * or \%X instead.
- * - \%R: the time in 24-hour notation (\%H:\%M)
- * - \%s: the number of seconds since the Epoch, that is, since 1970-01-01
+ * many locales have no concept of AM/PM formatting. Use `%c` or `%X` instead.
+ * - `%r`: the time in a.m. or p.m. notation. Use of this format specifier is
+ * discouraged, as many locales have no concept of AM/PM formatting. Use `%c`
+ * or `%X` instead.
+ * - `%R`: the time in 24-hour notation (`%H:%M`)
+ * - `%s`: the number of seconds since the Epoch, that is, since 1970-01-01
* 00:00:00 UTC
- * - \%S: the second as a decimal number (range 00 to 60)
- * - \%t: a tab character
- * - \%T: the time in 24-hour notation with seconds (\%H:\%M:\%S)
- * - \%u: the ISO 8601 standard day of the week as a decimal, range 1 to 7,
- * Monday being 1. This works well with \%G and \%V.
- * - \%V: the ISO 8601 standard week number of the current year as a decimal
+ * - `%S`: the second as a decimal number (range 00 to 60)
+ * - `%t`: a tab character
+ * - `%T`: the time in 24-hour notation with seconds (`%H:%M:%S`)
+ * - `%u`: the ISO 8601 standard day of the week as a decimal, range 1 to 7,
+ * Monday being 1. This works well with `%G` and `%V`.
+ * - `%V`: the ISO 8601 standard week number of the current year as a decimal
* number, range 01 to 53, where week 1 is the first week that has at
* least 4 days in the new year. See g_date_time_get_week_of_year().
- * This works well with \%G and \%u.
- * - \%w: the day of the week as a decimal, range 0 to 6, Sunday being 0.
- * This is not the ISO 8601 standard format -- use \%u instead.
- * - \%x: the preferred date representation for the current locale without
+ * This works well with `%G` and `%u`.
+ * - `%w`: the day of the week as a decimal, range 0 to 6, Sunday being 0.
+ * This is not the ISO 8601 standard format โ€” use `%u` instead.
+ * - `%x`: the preferred date representation for the current locale without
* the time
- * - \%X: the preferred time representation for the current locale without
+ * - `%X`: the preferred time representation for the current locale without
* the date
- * - \%y: the year as a decimal number without the century
- * - \%Y: the year as a decimal number including the century
- * - \%z: the time zone as an offset from UTC (+hhmm)
- * - \%:z: the time zone as an offset from UTC (+hh:mm).
- * This is a gnulib strftime() extension. Since: 2.38
- * - \%::z: the time zone as an offset from UTC (+hh:mm:ss). This is a
- * gnulib strftime() extension. Since: 2.38
- * - \%:::z: the time zone as an offset from UTC, with : to necessary
- * precision (e.g., -04, +05:30). This is a gnulib strftime() extension. Since: 2.38
- * - \%Z: the time zone or name or abbreviation
- * - \%\%: a literal \% character
+ * - `%y`: the year as a decimal number without the century
+ * - `%Y`: the year as a decimal number including the century
+ * - `%z`: the time zone as an offset from UTC (`+hhmm`)
+ * - `%:z`: the time zone as an offset from UTC (`+hh:mm`).
+ * This is a gnulib `strftime()` extension. Since: 2.38
+ * - `%::z`: the time zone as an offset from UTC (`+hh:mm:ss`). This is a
+ * gnulib `strftime()` extension. Since: 2.38
+ * - `%:::z`: the time zone as an offset from UTC, with `:` to necessary
+ * precision (e.g., `-04`, `+05:30`). This is a gnulib `strftime()` extension. Since: 2.38
+ * - `%Z`: the time zone or name or abbreviation
+ * - `%%`: a literal `%` character
*
* Some conversion specifications can be modified by preceding the
* conversion specifier by one or more modifier characters. The
* following modifiers are supported for many of the numeric
* conversions:
*
- * - O: Use alternative numeric symbols, if the current locale supports those.
- * - _: Pad a numeric result with spaces. This overrides the default padding
+ * - `O`: Use alternative numeric symbols, if the current locale supports those.
+ * - `_`: Pad a numeric result with spaces. This overrides the default padding
* for the specifier.
- * - -: Do not pad a numeric result. This overrides the default padding
+ * - `-`: Do not pad a numeric result. This overrides the default padding
* for the specifier.
- * - 0: Pad a numeric result with zeros. This overrides the default padding
+ * - `0`: Pad a numeric result with zeros. This overrides the default padding
* for the specifier.
*
- * Additionally, when O is used with B, b, or h, it produces the alternative
+ * Additionally, when `O` is used with `B`, `b`, or `h`, it produces the alternative
* form of a month name. The alternative form should be used when the month
* name is used without a day number (e.g., standalone). It is required in
* some languages (Baltic, Slavic, Greek, and more) due to their grammatical
- * rules. For other languages there is no difference. \%OB is a GNU and BSD
- * strftime() extension expected to be added to the future POSIX specification,
- * \%Ob and \%Oh are GNU strftime() extensions. Since: 2.56
+ * rules. For other languages there is no difference. `%OB` is a GNU and BSD
+ * `strftime()` extension expected to be added to the future POSIX specification,
+ * `%Ob` and `%Oh` are GNU `strftime()` extensions. Since: 2.56
*
* Returns: (transfer full) (nullable): a newly allocated string formatted to
* the requested format or %NULL in the case that there was an error (such
diff --git a/glib/glib-unix.c b/glib/glib-unix.c
index 1c9f12599..ef0d1fbfb 100644
--- a/glib/glib-unix.c
+++ b/glib/glib-unix.c
@@ -74,11 +74,16 @@ g_unix_set_error_from_errno (GError **error,
*
* Similar to the UNIX pipe() call, but on modern systems like Linux
* uses the pipe2() system call, which atomically creates a pipe with
- * the configured flags. The only supported flag currently is
- * %FD_CLOEXEC. If for example you want to configure %O_NONBLOCK, that
- * must still be done separately with fcntl().
+ * the configured flags.
*
- * This function does not take %O_CLOEXEC, it takes %FD_CLOEXEC as if
+ * As of GLib 2.78, the supported flags are `FD_CLOEXEC` and `O_NONBLOCK`. Prior
+ * to GLib 2.78, only `FD_CLOEXEC` was supported โ€” if you wanted to configure
+ * `O_NONBLOCK` then that had to be done separately with `fcntl()`.
+ *
+ * It is a programmer error to call this function with unsupported flags, and a
+ * critical warning will be raised.
+ *
+ * This function does not take `O_CLOEXEC`, it takes `FD_CLOEXEC` as if
* for fcntl(); these are different on Linux/glibc.
*
* Returns: %TRUE on success, %FALSE if not (and errno will be set).
@@ -90,11 +95,12 @@ g_unix_open_pipe (int *fds,
int flags,
GError **error)
{
- /* We only support FD_CLOEXEC */
- g_return_val_if_fail ((flags & (FD_CLOEXEC)) == flags, FALSE);
+ /* We only support FD_CLOEXEC and O_NONBLOCK */
+ g_return_val_if_fail ((flags & (FD_CLOEXEC | O_NONBLOCK)) == flags, FALSE);
if (!g_unix_open_pipe_internal (fds,
- (flags & FD_CLOEXEC) != 0))
+ (flags & FD_CLOEXEC) != 0,
+ (flags & O_NONBLOCK) != 0))
return g_unix_set_error_from_errno (error, errno);
return TRUE;
diff --git a/glib/glib-unixprivate.h b/glib/glib-unixprivate.h
index d4c64bd1e..fa13fe861 100644
--- a/glib/glib-unixprivate.h
+++ b/glib/glib-unixprivate.h
@@ -41,15 +41,22 @@ G_BEGIN_DECLS
static inline gboolean
g_unix_open_pipe_internal (int *fds,
- gboolean close_on_exec)
+ gboolean close_on_exec,
+ gboolean nonblock)
{
#ifdef HAVE_PIPE2
do
{
int ecode;
+ int flags = 0;
+
+ if (close_on_exec)
+ flags |= O_CLOEXEC;
+ if (nonblock)
+ flags |= O_NONBLOCK;
/* Atomic */
- ecode = pipe2 (fds, close_on_exec ? O_CLOEXEC : 0);
+ ecode = pipe2 (fds, flags);
if (ecode == -1 && errno != ENOSYS)
return FALSE;
else if (ecode == 0)
@@ -62,21 +69,44 @@ g_unix_open_pipe_internal (int *fds,
if (pipe (fds) == -1)
return FALSE;
- if (!close_on_exec)
- return TRUE;
+ if (close_on_exec)
+ {
+ if (fcntl (fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
+ fcntl (fds[1], F_SETFD, FD_CLOEXEC) == -1)
+ {
+ int saved_errno = errno;
+
+ close (fds[0]);
+ close (fds[1]);
+ fds[0] = -1;
+ fds[1] = -1;
+
+ errno = saved_errno;
+ return FALSE;
+ }
+ }
- if (fcntl (fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
- fcntl (fds[1], F_SETFD, FD_CLOEXEC) == -1)
+ if (nonblock)
{
- int saved_errno = errno;
+#ifdef O_NONBLOCK
+ int flags = O_NONBLOCK;
+#else
+ int flags = O_NDELAY;
+#endif
+
+ if (fcntl (fds[0], F_SETFL, flags) == -1 ||
+ fcntl (fds[1], F_SETFL, flags) == -1)
+ {
+ int saved_errno = errno;
- close (fds[0]);
- close (fds[1]);
- fds[0] = -1;
- fds[1] = -1;
+ close (fds[0]);
+ close (fds[1]);
+ fds[0] = -1;
+ fds[1] = -1;
- errno = saved_errno;
- return FALSE;
+ errno = saved_errno;
+ return FALSE;
+ }
}
return TRUE;
diff --git a/glib/gmarkup.c b/glib/gmarkup.c
index 0c2a9bece..9422abde4 100644
--- a/glib/gmarkup.c
+++ b/glib/gmarkup.c
@@ -85,6 +85,11 @@
* - Character references
*
* - Sections marked as CDATA
+
+ * ## An example parser # {#example}
+ *
+ * Here is an example for a markup parser:
+ * [markup-example.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/glib/tests/markup-example.c)
*/
G_DEFINE_QUARK (g-markup-error-quark, g_markup_error)
diff --git a/glib/gunicode.h b/glib/gunicode.h
index 63117ea28..38e29b84f 100644
--- a/glib/gunicode.h
+++ b/glib/gunicode.h
@@ -210,7 +210,7 @@ typedef enum
* Since new unicode versions may add new types here, applications should be ready
* to handle unknown values. They may be regarded as %G_UNICODE_BREAK_UNKNOWN.
*
- * See [Unicode Line Breaking Algorithm](http://www.unicode.org/unicode/reports/tr14/).
+ * See [Unicode Line Breaking Algorithm](https://www.unicode.org/reports/tr14/).
*/
typedef enum
{
diff --git a/glib/gwakeup.c b/glib/gwakeup.c
index 24d85b669..a3283a3ff 100644
--- a/glib/gwakeup.c
+++ b/glib/gwakeup.c
@@ -160,7 +160,7 @@ g_wakeup_new (void)
/* for any failure, try a pipe instead */
#endif
- if (!g_unix_open_pipe (wakeup->fds, FD_CLOEXEC, &error))
+ if (!g_unix_open_pipe (wakeup->fds, FD_CLOEXEC | O_NONBLOCK, &error))
g_error ("Creating pipes for GWakeup: %s", error->message);
if (!g_unix_set_fd_nonblocking (wakeup->fds[0], TRUE, &error) ||
diff --git a/glib/meson.build b/glib/meson.build
index da76fc005..744275649 100644
--- a/glib/meson.build
+++ b/glib/meson.build
@@ -150,6 +150,10 @@ glib_headers = files(
)
install_headers(glib_headers, install_dir : glib_includedir)
+if host_system == 'windows'
+ install_headers([ 'msvc_recommended_pragmas.h' ], install_dir : glib_includedir)
+endif
+
# Expose as variable to be used by gobject-introspection
# when it includes GLib as a subproject
glib_unix_h = files('glib-unix.h')
diff --git a/msvc_recommended_pragmas.h b/glib/msvc_recommended_pragmas.h
index 051a02ae4..051a02ae4 100644
--- a/msvc_recommended_pragmas.h
+++ b/glib/msvc_recommended_pragmas.h
diff --git a/glib/tests/NormalizationTest.txt b/glib/tests/NormalizationTest.txt
index 302c35f37..e75b4801c 100644
--- a/glib/tests/NormalizationTest.txt
+++ b/glib/tests/NormalizationTest.txt
@@ -1,11 +1,11 @@
-# NormalizationTest-14.0.0.txt
-# Date: 2021-05-28, 21:49:12 GMT
-# ยฉ 2021 Unicodeยฎ, Inc.
+# NormalizationTest-15.0.0.txt
+# Date: 2022-04-02, 01:29:09 GMT
+# ยฉ 2022 Unicodeยฎ, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
-# For terms of use, see http://www.unicode.org/terms_of_use.html
+# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Unicode Character Database
-# For documentation, see http://www.unicode.org/reports/tr44/
+# For documentation, see https://www.unicode.org/reports/tr44/
#
# Normalization Test Suite
# Format:
@@ -16208,6 +16208,68 @@ FFEE;FFEE;FFEE;25CB;25CB; # (๏ฟฎ; ๏ฟฎ; ๏ฟฎ; โ—‹; โ—‹; ) HALFWIDTH WHITE CIRCLE
1D7FD;1D7FD;1D7FD;0037;0037; # (๐Ÿฝ; ๐Ÿฝ; ๐Ÿฝ; 7; 7; ) MATHEMATICAL MONOSPACE DIGIT SEVEN
1D7FE;1D7FE;1D7FE;0038;0038; # (๐Ÿพ; ๐Ÿพ; ๐Ÿพ; 8; 8; ) MATHEMATICAL MONOSPACE DIGIT EIGHT
1D7FF;1D7FF;1D7FF;0039;0039; # (๐Ÿฟ; ๐Ÿฟ; ๐Ÿฟ; 9; 9; ) MATHEMATICAL MONOSPACE DIGIT NINE
+1E030;1E030;1E030;0430;0430; # (๐ž€ฐ; ๐ž€ฐ; ๐ž€ฐ; ะฐ; ะฐ; ) MODIFIER LETTER CYRILLIC SMALL A
+1E031;1E031;1E031;0431;0431; # (๐ž€ฑ; ๐ž€ฑ; ๐ž€ฑ; ะฑ; ะฑ; ) MODIFIER LETTER CYRILLIC SMALL BE
+1E032;1E032;1E032;0432;0432; # (๐ž€ฒ; ๐ž€ฒ; ๐ž€ฒ; ะฒ; ะฒ; ) MODIFIER LETTER CYRILLIC SMALL VE
+1E033;1E033;1E033;0433;0433; # (๐ž€ณ; ๐ž€ณ; ๐ž€ณ; ะณ; ะณ; ) MODIFIER LETTER CYRILLIC SMALL GHE
+1E034;1E034;1E034;0434;0434; # (๐ž€ด; ๐ž€ด; ๐ž€ด; ะด; ะด; ) MODIFIER LETTER CYRILLIC SMALL DE
+1E035;1E035;1E035;0435;0435; # (๐ž€ต; ๐ž€ต; ๐ž€ต; ะต; ะต; ) MODIFIER LETTER CYRILLIC SMALL IE
+1E036;1E036;1E036;0436;0436; # (๐ž€ถ; ๐ž€ถ; ๐ž€ถ; ะถ; ะถ; ) MODIFIER LETTER CYRILLIC SMALL ZHE
+1E037;1E037;1E037;0437;0437; # (๐ž€ท; ๐ž€ท; ๐ž€ท; ะท; ะท; ) MODIFIER LETTER CYRILLIC SMALL ZE
+1E038;1E038;1E038;0438;0438; # (๐ž€ธ; ๐ž€ธ; ๐ž€ธ; ะธ; ะธ; ) MODIFIER LETTER CYRILLIC SMALL I
+1E039;1E039;1E039;043A;043A; # (๐ž€น; ๐ž€น; ๐ž€น; ะบ; ะบ; ) MODIFIER LETTER CYRILLIC SMALL KA
+1E03A;1E03A;1E03A;043B;043B; # (๐ž€บ; ๐ž€บ; ๐ž€บ; ะป; ะป; ) MODIFIER LETTER CYRILLIC SMALL EL
+1E03B;1E03B;1E03B;043C;043C; # (๐ž€ป; ๐ž€ป; ๐ž€ป; ะผ; ะผ; ) MODIFIER LETTER CYRILLIC SMALL EM
+1E03C;1E03C;1E03C;043E;043E; # (๐ž€ผ; ๐ž€ผ; ๐ž€ผ; ะพ; ะพ; ) MODIFIER LETTER CYRILLIC SMALL O
+1E03D;1E03D;1E03D;043F;043F; # (๐ž€ฝ; ๐ž€ฝ; ๐ž€ฝ; ะฟ; ะฟ; ) MODIFIER LETTER CYRILLIC SMALL PE
+1E03E;1E03E;1E03E;0440;0440; # (๐ž€พ; ๐ž€พ; ๐ž€พ; ั€; ั€; ) MODIFIER LETTER CYRILLIC SMALL ER
+1E03F;1E03F;1E03F;0441;0441; # (๐ž€ฟ; ๐ž€ฟ; ๐ž€ฟ; ั; ั; ) MODIFIER LETTER CYRILLIC SMALL ES
+1E040;1E040;1E040;0442;0442; # (๐ž€; ๐ž€; ๐ž€; ั‚; ั‚; ) MODIFIER LETTER CYRILLIC SMALL TE
+1E041;1E041;1E041;0443;0443; # (๐ž; ๐ž; ๐ž; ัƒ; ัƒ; ) MODIFIER LETTER CYRILLIC SMALL U
+1E042;1E042;1E042;0444;0444; # (๐ž‚; ๐ž‚; ๐ž‚; ั„; ั„; ) MODIFIER LETTER CYRILLIC SMALL EF
+1E043;1E043;1E043;0445;0445; # (๐žƒ; ๐žƒ; ๐žƒ; ั…; ั…; ) MODIFIER LETTER CYRILLIC SMALL HA
+1E044;1E044;1E044;0446;0446; # (๐ž„; ๐ž„; ๐ž„; ั†; ั†; ) MODIFIER LETTER CYRILLIC SMALL TSE
+1E045;1E045;1E045;0447;0447; # (๐ž…; ๐ž…; ๐ž…; ั‡; ั‡; ) MODIFIER LETTER CYRILLIC SMALL CHE
+1E046;1E046;1E046;0448;0448; # (๐ž†; ๐ž†; ๐ž†; ัˆ; ัˆ; ) MODIFIER LETTER CYRILLIC SMALL SHA
+1E047;1E047;1E047;044B;044B; # (๐ž‡; ๐ž‡; ๐ž‡; ั‹; ั‹; ) MODIFIER LETTER CYRILLIC SMALL YERU
+1E048;1E048;1E048;044D;044D; # (๐žˆ; ๐žˆ; ๐žˆ; ั; ั; ) MODIFIER LETTER CYRILLIC SMALL E
+1E049;1E049;1E049;044E;044E; # (๐ž‰; ๐ž‰; ๐ž‰; ัŽ; ัŽ; ) MODIFIER LETTER CYRILLIC SMALL YU
+1E04A;1E04A;1E04A;A689;A689; # (๐žŠ; ๐žŠ; ๐žŠ; ๊š‰; ๊š‰; ) MODIFIER LETTER CYRILLIC SMALL DZZE
+1E04B;1E04B;1E04B;04D9;04D9; # (๐ž‹; ๐ž‹; ๐ž‹; ำ™; ำ™; ) MODIFIER LETTER CYRILLIC SMALL SCHWA
+1E04C;1E04C;1E04C;0456;0456; # (๐žŒ; ๐žŒ; ๐žŒ; ั–; ั–; ) MODIFIER LETTER CYRILLIC SMALL BYELORUSSIAN-UKRAINIAN I
+1E04D;1E04D;1E04D;0458;0458; # (๐ž; ๐ž; ๐ž; ั˜; ั˜; ) MODIFIER LETTER CYRILLIC SMALL JE
+1E04E;1E04E;1E04E;04E9;04E9; # (๐žŽ; ๐žŽ; ๐žŽ; ำฉ; ำฉ; ) MODIFIER LETTER CYRILLIC SMALL BARRED O
+1E04F;1E04F;1E04F;04AF;04AF; # (๐ž; ๐ž; ๐ž; าฏ; าฏ; ) MODIFIER LETTER CYRILLIC SMALL STRAIGHT U
+1E050;1E050;1E050;04CF;04CF; # (๐ž; ๐ž; ๐ž; ำ; ำ; ) MODIFIER LETTER CYRILLIC SMALL PALOCHKA
+1E051;1E051;1E051;0430;0430; # (๐ž‘; ๐ž‘; ๐ž‘; ะฐ; ะฐ; ) CYRILLIC SUBSCRIPT SMALL LETTER A
+1E052;1E052;1E052;0431;0431; # (๐ž’; ๐ž’; ๐ž’; ะฑ; ะฑ; ) CYRILLIC SUBSCRIPT SMALL LETTER BE
+1E053;1E053;1E053;0432;0432; # (๐ž“; ๐ž“; ๐ž“; ะฒ; ะฒ; ) CYRILLIC SUBSCRIPT SMALL LETTER VE
+1E054;1E054;1E054;0433;0433; # (๐ž”; ๐ž”; ๐ž”; ะณ; ะณ; ) CYRILLIC SUBSCRIPT SMALL LETTER GHE
+1E055;1E055;1E055;0434;0434; # (๐ž•; ๐ž•; ๐ž•; ะด; ะด; ) CYRILLIC SUBSCRIPT SMALL LETTER DE
+1E056;1E056;1E056;0435;0435; # (๐ž–; ๐ž–; ๐ž–; ะต; ะต; ) CYRILLIC SUBSCRIPT SMALL LETTER IE
+1E057;1E057;1E057;0436;0436; # (๐ž—; ๐ž—; ๐ž—; ะถ; ะถ; ) CYRILLIC SUBSCRIPT SMALL LETTER ZHE
+1E058;1E058;1E058;0437;0437; # (๐ž˜; ๐ž˜; ๐ž˜; ะท; ะท; ) CYRILLIC SUBSCRIPT SMALL LETTER ZE
+1E059;1E059;1E059;0438;0438; # (๐ž™; ๐ž™; ๐ž™; ะธ; ะธ; ) CYRILLIC SUBSCRIPT SMALL LETTER I
+1E05A;1E05A;1E05A;043A;043A; # (๐žš; ๐žš; ๐žš; ะบ; ะบ; ) CYRILLIC SUBSCRIPT SMALL LETTER KA
+1E05B;1E05B;1E05B;043B;043B; # (๐ž›; ๐ž›; ๐ž›; ะป; ะป; ) CYRILLIC SUBSCRIPT SMALL LETTER EL
+1E05C;1E05C;1E05C;043E;043E; # (๐žœ; ๐žœ; ๐žœ; ะพ; ะพ; ) CYRILLIC SUBSCRIPT SMALL LETTER O
+1E05D;1E05D;1E05D;043F;043F; # (๐ž; ๐ž; ๐ž; ะฟ; ะฟ; ) CYRILLIC SUBSCRIPT SMALL LETTER PE
+1E05E;1E05E;1E05E;0441;0441; # (๐žž; ๐žž; ๐žž; ั; ั; ) CYRILLIC SUBSCRIPT SMALL LETTER ES
+1E05F;1E05F;1E05F;0443;0443; # (๐žŸ; ๐žŸ; ๐žŸ; ัƒ; ัƒ; ) CYRILLIC SUBSCRIPT SMALL LETTER U
+1E060;1E060;1E060;0444;0444; # (๐ž ; ๐ž ; ๐ž ; ั„; ั„; ) CYRILLIC SUBSCRIPT SMALL LETTER EF
+1E061;1E061;1E061;0445;0445; # (๐žก; ๐žก; ๐žก; ั…; ั…; ) CYRILLIC SUBSCRIPT SMALL LETTER HA
+1E062;1E062;1E062;0446;0446; # (๐žข; ๐žข; ๐žข; ั†; ั†; ) CYRILLIC SUBSCRIPT SMALL LETTER TSE
+1E063;1E063;1E063;0447;0447; # (๐žฃ; ๐žฃ; ๐žฃ; ั‡; ั‡; ) CYRILLIC SUBSCRIPT SMALL LETTER CHE
+1E064;1E064;1E064;0448;0448; # (๐žค; ๐žค; ๐žค; ัˆ; ัˆ; ) CYRILLIC SUBSCRIPT SMALL LETTER SHA
+1E065;1E065;1E065;044A;044A; # (๐žฅ; ๐žฅ; ๐žฅ; ัŠ; ัŠ; ) CYRILLIC SUBSCRIPT SMALL LETTER HARD SIGN
+1E066;1E066;1E066;044B;044B; # (๐žฆ; ๐žฆ; ๐žฆ; ั‹; ั‹; ) CYRILLIC SUBSCRIPT SMALL LETTER YERU
+1E067;1E067;1E067;0491;0491; # (๐žง; ๐žง; ๐žง; า‘; า‘; ) CYRILLIC SUBSCRIPT SMALL LETTER GHE WITH UPTURN
+1E068;1E068;1E068;0456;0456; # (๐žจ; ๐žจ; ๐žจ; ั–; ั–; ) CYRILLIC SUBSCRIPT SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+1E069;1E069;1E069;0455;0455; # (๐žฉ; ๐žฉ; ๐žฉ; ั•; ั•; ) CYRILLIC SUBSCRIPT SMALL LETTER DZE
+1E06A;1E06A;1E06A;045F;045F; # (๐žช; ๐žช; ๐žช; ัŸ; ัŸ; ) CYRILLIC SUBSCRIPT SMALL LETTER DZHE
+1E06B;1E06B;1E06B;04AB;04AB; # (๐žซ; ๐žซ; ๐žซ; าซ; าซ; ) MODIFIER LETTER CYRILLIC SMALL ES WITH DESCENDER
+1E06C;1E06C;1E06C;A651;A651; # (๐žฌ; ๐žฌ; ๐žฌ; ๊™‘; ๊™‘; ) MODIFIER LETTER CYRILLIC SMALL YERU WITH BACK YER
+1E06D;1E06D;1E06D;04B1;04B1; # (๐žญ; ๐žญ; ๐žญ; าฑ; าฑ; ) MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE
1EE00;1EE00;1EE00;0627;0627; # (๐žธ€; ๐žธ€; ๐žธ€; ุง; ุง; ) ARABIC MATHEMATICAL ALEF
1EE01;1EE01;1EE01;0628;0628; # (๐žธ; ๐žธ; ๐žธ; ุจ; ุจ; ) ARABIC MATHEMATICAL BEH
1EE02;1EE02;1EE02;062C;062C; # (๐žธ‚; ๐žธ‚; ๐žธ‚; ุฌ; ุฌ; ) ARABIC MATHEMATICAL JEEM
@@ -18496,6 +18558,12 @@ FFEE;FFEE;FFEE;25CB;25CB; # (๏ฟฎ; ๏ฟฎ; ๏ฟฎ; โ—‹; โ—‹; ) HALFWIDTH WHITE CIRCLE
0061 10EAB 0315 0300 05AE 0062;0061 05AE 10EAB 0300 0315 0062;0061 05AE 10EAB 0300 0315 0062;0061 05AE 10EAB 0300 0315 0062;0061 05AE 10EAB 0300 0315 0062; # (aโ—Œ๐บซโ—Œฬ•โ—Œฬ€โ—Œึฎb; aโ—Œึฎโ—Œ๐บซโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐บซโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐บซโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐บซโ—Œฬ€โ—Œฬ•b; ) LATIN SMALL LETTER A, YEZIDI COMBINING HAMZA MARK, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 10EAC 0062;00E0 05AE 10EAC 0315 0062;0061 05AE 0300 10EAC 0315 0062;00E0 05AE 10EAC 0315 0062;0061 05AE 0300 10EAC 0315 0062; # (aโ—Œฬ•โ—Œฬ€โ—Œึฎโ—Œ๐บฌb; ร โ—Œึฎโ—Œ๐บฌโ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐บฌโ—Œฬ•b; ร โ—Œึฎโ—Œ๐บฌโ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐บฌโ—Œฬ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, YEZIDI COMBINING MADDA MARK, LATIN SMALL LETTER B
0061 10EAC 0315 0300 05AE 0062;0061 05AE 10EAC 0300 0315 0062;0061 05AE 10EAC 0300 0315 0062;0061 05AE 10EAC 0300 0315 0062;0061 05AE 10EAC 0300 0315 0062; # (aโ—Œ๐บฌโ—Œฬ•โ—Œฬ€โ—Œึฎb; aโ—Œึฎโ—Œ๐บฌโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐บฌโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐บฌโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐บฌโ—Œฬ€โ—Œฬ•b; ) LATIN SMALL LETTER A, YEZIDI COMBINING MADDA MARK, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10EFD 0062;0061 1DFA 0316 10EFD 059A 0062;0061 1DFA 0316 10EFD 059A 0062;0061 1DFA 0316 10EFD 059A 0062;0061 1DFA 0316 10EFD 059A 0062; # (aโ—Œึšโ—Œฬ–โ—Œแทบโ—Œ๐ปฝb; aโ—Œแทบโ—Œฬ–โ—Œ๐ปฝโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ปฝโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ปฝโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ปฝโ—Œึšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC SMALL LOW WORD SAKTA, LATIN SMALL LETTER B
+0061 10EFD 059A 0316 1DFA 0062;0061 1DFA 10EFD 0316 059A 0062;0061 1DFA 10EFD 0316 059A 0062;0061 1DFA 10EFD 0316 059A 0062;0061 1DFA 10EFD 0316 059A 0062; # (aโ—Œ๐ปฝโ—Œึšโ—Œฬ–โ—Œแทบb; aโ—Œแทบโ—Œ๐ปฝโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ปฝโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ปฝโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ปฝโ—Œฬ–โ—Œึšb; ) LATIN SMALL LETTER A, ARABIC SMALL LOW WORD SAKTA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10EFE 0062;0061 1DFA 0316 10EFE 059A 0062;0061 1DFA 0316 10EFE 059A 0062;0061 1DFA 0316 10EFE 059A 0062;0061 1DFA 0316 10EFE 059A 0062; # (aโ—Œึšโ—Œฬ–โ—Œแทบโ—Œ๐ปพb; aโ—Œแทบโ—Œฬ–โ—Œ๐ปพโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ปพโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ปพโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ปพโ—Œึšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC SMALL LOW WORD QASR, LATIN SMALL LETTER B
+0061 10EFE 059A 0316 1DFA 0062;0061 1DFA 10EFE 0316 059A 0062;0061 1DFA 10EFE 0316 059A 0062;0061 1DFA 10EFE 0316 059A 0062;0061 1DFA 10EFE 0316 059A 0062; # (aโ—Œ๐ปพโ—Œึšโ—Œฬ–โ—Œแทบb; aโ—Œแทบโ—Œ๐ปพโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ปพโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ปพโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ปพโ—Œฬ–โ—Œึšb; ) LATIN SMALL LETTER A, ARABIC SMALL LOW WORD QASR, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10EFF 0062;0061 1DFA 0316 10EFF 059A 0062;0061 1DFA 0316 10EFF 059A 0062;0061 1DFA 0316 10EFF 059A 0062;0061 1DFA 0316 10EFF 059A 0062; # (aโ—Œึšโ—Œฬ–โ—Œแทบโ—Œ๐ปฟb; aโ—Œแทบโ—Œฬ–โ—Œ๐ปฟโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ปฟโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ปฟโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ปฟโ—Œึšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC SMALL LOW WORD MADDA, LATIN SMALL LETTER B
+0061 10EFF 059A 0316 1DFA 0062;0061 1DFA 10EFF 0316 059A 0062;0061 1DFA 10EFF 0316 059A 0062;0061 1DFA 10EFF 0316 059A 0062;0061 1DFA 10EFF 0316 059A 0062; # (aโ—Œ๐ปฟโ—Œึšโ—Œฬ–โ—Œแทบb; aโ—Œแทบโ—Œ๐ปฟโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ปฟโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ปฟโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ปฟโ—Œฬ–โ—Œึšb; ) LATIN SMALL LETTER A, ARABIC SMALL LOW WORD MADDA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 059A 0316 1DFA 10F46 0062;0061 1DFA 0316 10F46 059A 0062;0061 1DFA 0316 10F46 059A 0062;0061 1DFA 0316 10F46 059A 0062;0061 1DFA 0316 10F46 059A 0062; # (aโ—Œึšโ—Œฬ–โ—Œแทบโ—Œ๐ฝ†b; aโ—Œแทบโ—Œฬ–โ—Œ๐ฝ†โ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ฝ†โ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ฝ†โ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ฝ†โ—Œึšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SOGDIAN COMBINING DOT BELOW, LATIN SMALL LETTER B
0061 10F46 059A 0316 1DFA 0062;0061 1DFA 10F46 0316 059A 0062;0061 1DFA 10F46 0316 059A 0062;0061 1DFA 10F46 0316 059A 0062;0061 1DFA 10F46 0316 059A 0062; # (aโ—Œ๐ฝ†โ—Œึšโ—Œฬ–โ—Œแทบb; aโ—Œแทบโ—Œ๐ฝ†โ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ฝ†โ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ฝ†โ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ฝ†โ—Œฬ–โ—Œึšb; ) LATIN SMALL LETTER A, SOGDIAN COMBINING DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 059A 0316 1DFA 10F47 0062;0061 1DFA 0316 10F47 059A 0062;0061 1DFA 0316 10F47 059A 0062;0061 1DFA 0316 10F47 059A 0062;0061 1DFA 0316 10F47 059A 0062; # (aโ—Œึšโ—Œฬ–โ—Œแทบโ—Œ๐ฝ‡b; aโ—Œแทบโ—Œฬ–โ—Œ๐ฝ‡โ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ฝ‡โ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ฝ‡โ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ฝ‡โ—Œึšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SOGDIAN COMBINING TWO DOTS BELOW, LATIN SMALL LETTER B
@@ -18640,6 +18708,10 @@ FFEE;FFEE;FFEE;25CB;25CB; # (๏ฟฎ; ๏ฟฎ; ๏ฟฎ; โ—‹; โ—‹; ) HALFWIDTH WHITE CIRCLE
0061 11D45 05B0 094D 3099 0062;0061 3099 11D45 094D 05B0 0062;0061 3099 11D45 094D 05B0 0062;0061 3099 11D45 094D 05B0 0062;0061 3099 11D45 094D 05B0 0062; # (aโ—Œ๐‘ต…โ—Œึฐโ—Œเฅโ—Œใ‚™b; aโ—Œใ‚™โ—Œ๐‘ต…โ—Œเฅโ—Œึฐb; aโ—Œใ‚™โ—Œ๐‘ต…โ—Œเฅโ—Œึฐb; aโ—Œใ‚™โ—Œ๐‘ต…โ—Œเฅโ—Œึฐb; aโ—Œใ‚™โ—Œ๐‘ต…โ—Œเฅโ—Œึฐb; ) LATIN SMALL LETTER A, MASARAM GONDI VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 05B0 094D 3099 11D97 0062;0061 3099 094D 11D97 05B0 0062;0061 3099 094D 11D97 05B0 0062;0061 3099 094D 11D97 05B0 0062;0061 3099 094D 11D97 05B0 0062; # (aโ—Œึฐโ—Œเฅโ—Œใ‚™โ—Œ๐‘ถ—b; aโ—Œใ‚™โ—Œเฅโ—Œ๐‘ถ—โ—Œึฐb; aโ—Œใ‚™โ—Œเฅโ—Œ๐‘ถ—โ—Œึฐb; aโ—Œใ‚™โ—Œเฅโ—Œ๐‘ถ—โ—Œึฐb; aโ—Œใ‚™โ—Œเฅโ—Œ๐‘ถ—โ—Œึฐb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, GUNJALA GONDI VIRAMA, LATIN SMALL LETTER B
0061 11D97 05B0 094D 3099 0062;0061 3099 11D97 094D 05B0 0062;0061 3099 11D97 094D 05B0 0062;0061 3099 11D97 094D 05B0 0062;0061 3099 11D97 094D 05B0 0062; # (aโ—Œ๐‘ถ—โ—Œึฐโ—Œเฅโ—Œใ‚™b; aโ—Œใ‚™โ—Œ๐‘ถ—โ—Œเฅโ—Œึฐb; aโ—Œใ‚™โ—Œ๐‘ถ—โ—Œเฅโ—Œึฐb; aโ—Œใ‚™โ—Œ๐‘ถ—โ—Œเฅโ—Œึฐb; aโ—Œใ‚™โ—Œ๐‘ถ—โ—Œเฅโ—Œึฐb; ) LATIN SMALL LETTER A, GUNJALA GONDI VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 05B0 094D 3099 11F41 0062;0061 3099 094D 11F41 05B0 0062;0061 3099 094D 11F41 05B0 0062;0061 3099 094D 11F41 05B0 0062;0061 3099 094D 11F41 05B0 0062; # (aโ—Œึฐโ—Œเฅโ—Œใ‚™๐‘ฝb; aโ—Œใ‚™โ—Œเฅ๐‘ฝโ—Œึฐb; aโ—Œใ‚™โ—Œเฅ๐‘ฝโ—Œึฐb; aโ—Œใ‚™โ—Œเฅ๐‘ฝโ—Œึฐb; aโ—Œใ‚™โ—Œเฅ๐‘ฝโ—Œึฐb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, KAWI SIGN KILLER, LATIN SMALL LETTER B
+0061 11F41 05B0 094D 3099 0062;0061 3099 11F41 094D 05B0 0062;0061 3099 11F41 094D 05B0 0062;0061 3099 11F41 094D 05B0 0062;0061 3099 11F41 094D 05B0 0062; # (a๐‘ฝโ—Œึฐโ—Œเฅโ—Œใ‚™b; aโ—Œใ‚™๐‘ฝโ—Œเฅโ—Œึฐb; aโ—Œใ‚™๐‘ฝโ—Œเฅโ—Œึฐb; aโ—Œใ‚™๐‘ฝโ—Œเฅโ—Œึฐb; aโ—Œใ‚™๐‘ฝโ—Œเฅโ—Œึฐb; ) LATIN SMALL LETTER A, KAWI SIGN KILLER, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 05B0 094D 3099 11F42 0062;0061 3099 094D 11F42 05B0 0062;0061 3099 094D 11F42 05B0 0062;0061 3099 094D 11F42 05B0 0062;0061 3099 094D 11F42 05B0 0062; # (aโ—Œึฐโ—Œเฅโ—Œใ‚™โ—Œ๐‘ฝ‚b; aโ—Œใ‚™โ—Œเฅโ—Œ๐‘ฝ‚โ—Œึฐb; aโ—Œใ‚™โ—Œเฅโ—Œ๐‘ฝ‚โ—Œึฐb; aโ—Œใ‚™โ—Œเฅโ—Œ๐‘ฝ‚โ—Œึฐb; aโ—Œใ‚™โ—Œเฅโ—Œ๐‘ฝ‚โ—Œึฐb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, KAWI CONJOINER, LATIN SMALL LETTER B
+0061 11F42 05B0 094D 3099 0062;0061 3099 11F42 094D 05B0 0062;0061 3099 11F42 094D 05B0 0062;0061 3099 11F42 094D 05B0 0062;0061 3099 11F42 094D 05B0 0062; # (aโ—Œ๐‘ฝ‚โ—Œึฐโ—Œเฅโ—Œใ‚™b; aโ—Œใ‚™โ—Œ๐‘ฝ‚โ—Œเฅโ—Œึฐb; aโ—Œใ‚™โ—Œ๐‘ฝ‚โ—Œเฅโ—Œึฐb; aโ—Œใ‚™โ—Œ๐‘ฝ‚โ—Œเฅโ—Œึฐb; aโ—Œใ‚™โ—Œ๐‘ฝ‚โ—Œเฅโ—Œึฐb; ) LATIN SMALL LETTER A, KAWI CONJOINER, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 16FF0 0334 16AF0 0062;0061 0334 16AF0 16FF0 0062;0061 0334 16AF0 16FF0 0062;0061 0334 16AF0 16FF0 0062;0061 0334 16AF0 16FF0 0062; # (a๐–ฟฐโ—Œฬดโ—Œ๐–ซฐb; aโ—Œฬดโ—Œ๐–ซฐ๐–ฟฐb; aโ—Œฬดโ—Œ๐–ซฐ๐–ฟฐb; aโ—Œฬดโ—Œ๐–ซฐ๐–ฟฐb; aโ—Œฬดโ—Œ๐–ซฐ๐–ฟฐb; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, BASSA VAH COMBINING HIGH TONE, LATIN SMALL LETTER B
0061 16AF0 16FF0 0334 0062;0061 16AF0 0334 16FF0 0062;0061 16AF0 0334 16FF0 0062;0061 16AF0 0334 16FF0 0062;0061 16AF0 0334 16FF0 0062; # (aโ—Œ๐–ซฐ๐–ฟฐโ—Œฬดb; aโ—Œ๐–ซฐโ—Œฬด๐–ฟฐb; aโ—Œ๐–ซฐโ—Œฬด๐–ฟฐb; aโ—Œ๐–ซฐโ—Œฬด๐–ฟฐb; aโ—Œ๐–ซฐโ—Œฬด๐–ฟฐb; ) LATIN SMALL LETTER A, BASSA VAH COMBINING HIGH TONE, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 16FF0 0334 16AF1 0062;0061 0334 16AF1 16FF0 0062;0061 0334 16AF1 16FF0 0062;0061 0334 16AF1 16FF0 0062;0061 0334 16AF1 16FF0 0062; # (a๐–ฟฐโ—Œฬดโ—Œ๐–ซฑb; aโ—Œฬดโ—Œ๐–ซฑ๐–ฟฐb; aโ—Œฬดโ—Œ๐–ซฑ๐–ฟฐb; aโ—Œฬดโ—Œ๐–ซฑ๐–ฟฐb; aโ—Œฬดโ—Œ๐–ซฑ๐–ฟฐb; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, BASSA VAH COMBINING LOW TONE, LATIN SMALL LETTER B
@@ -18812,6 +18884,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (๏ฟฎ; ๏ฟฎ; ๏ฟฎ; โ—‹; โ—‹; ) HALFWIDTH WHITE CIRCLE
0061 1E029 0315 0300 05AE 0062;0061 05AE 1E029 0300 0315 0062;0061 05AE 1E029 0300 0315 0062;0061 05AE 1E029 0300 0315 0062;0061 05AE 1E029 0300 0315 0062; # (aโ—Œ๐ž€ฉโ—Œฬ•โ—Œฬ€โ—Œึฎb; aโ—Œึฎโ—Œ๐ž€ฉโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž€ฉโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž€ฉโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž€ฉโ—Œฬ€โ—Œฬ•b; ) LATIN SMALL LETTER A, COMBINING GLAGOLITIC LETTER IOTATED BIG YUS, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1E02A 0062;00E0 05AE 1E02A 0315 0062;0061 05AE 0300 1E02A 0315 0062;00E0 05AE 1E02A 0315 0062;0061 05AE 0300 1E02A 0315 0062; # (aโ—Œฬ•โ—Œฬ€โ—Œึฎโ—Œ๐ž€ชb; ร โ—Œึฎโ—Œ๐ž€ชโ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐ž€ชโ—Œฬ•b; ร โ—Œึฎโ—Œ๐ž€ชโ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐ž€ชโ—Œฬ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING GLAGOLITIC LETTER FITA, LATIN SMALL LETTER B
0061 1E02A 0315 0300 05AE 0062;0061 05AE 1E02A 0300 0315 0062;0061 05AE 1E02A 0300 0315 0062;0061 05AE 1E02A 0300 0315 0062;0061 05AE 1E02A 0300 0315 0062; # (aโ—Œ๐ž€ชโ—Œฬ•โ—Œฬ€โ—Œึฎb; aโ—Œึฎโ—Œ๐ž€ชโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž€ชโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž€ชโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž€ชโ—Œฬ€โ—Œฬ•b; ) LATIN SMALL LETTER A, COMBINING GLAGOLITIC LETTER FITA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1E08F 0062;00E0 05AE 1E08F 0315 0062;0061 05AE 0300 1E08F 0315 0062;00E0 05AE 1E08F 0315 0062;0061 05AE 0300 1E08F 0315 0062; # (aโ—Œฬ•โ—Œฬ€โ—Œึฎโ—Œ๐ž‚b; ร โ—Œึฎโ—Œ๐ž‚โ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐ž‚โ—Œฬ•b; ร โ—Œึฎโ—Œ๐ž‚โ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐ž‚โ—Œฬ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I, LATIN SMALL LETTER B
+0061 1E08F 0315 0300 05AE 0062;0061 05AE 1E08F 0300 0315 0062;0061 05AE 1E08F 0300 0315 0062;0061 05AE 1E08F 0300 0315 0062;0061 05AE 1E08F 0300 0315 0062; # (aโ—Œ๐ž‚โ—Œฬ•โ—Œฬ€โ—Œึฎb; aโ—Œึฎโ—Œ๐ž‚โ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž‚โ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž‚โ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž‚โ—Œฬ€โ—Œฬ•b; ) LATIN SMALL LETTER A, COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1E130 0062;00E0 05AE 1E130 0315 0062;0061 05AE 0300 1E130 0315 0062;00E0 05AE 1E130 0315 0062;0061 05AE 0300 1E130 0315 0062; # (aโ—Œฬ•โ—Œฬ€โ—Œึฎโ—Œ๐ž„ฐb; ร โ—Œึฎโ—Œ๐ž„ฐโ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐ž„ฐโ—Œฬ•b; ร โ—Œึฎโ—Œ๐ž„ฐโ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐ž„ฐโ—Œฬ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, NYIAKENG PUACHUE HMONG TONE-B, LATIN SMALL LETTER B
0061 1E130 0315 0300 05AE 0062;0061 05AE 1E130 0300 0315 0062;0061 05AE 1E130 0300 0315 0062;0061 05AE 1E130 0300 0315 0062;0061 05AE 1E130 0300 0315 0062; # (aโ—Œ๐ž„ฐโ—Œฬ•โ—Œฬ€โ—Œึฎb; aโ—Œึฎโ—Œ๐ž„ฐโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž„ฐโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž„ฐโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž„ฐโ—Œฬ€โ—Œฬ•b; ) LATIN SMALL LETTER A, NYIAKENG PUACHUE HMONG TONE-B, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1E131 0062;00E0 05AE 1E131 0315 0062;0061 05AE 0300 1E131 0315 0062;00E0 05AE 1E131 0315 0062;0061 05AE 0300 1E131 0315 0062; # (aโ—Œฬ•โ—Œฬ€โ—Œึฎโ—Œ๐ž„ฑb; ร โ—Œึฎโ—Œ๐ž„ฑโ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐ž„ฑโ—Œฬ•b; ร โ—Œึฎโ—Œ๐ž„ฑโ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐ž„ฑโ—Œฬ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, NYIAKENG PUACHUE HMONG TONE-M, LATIN SMALL LETTER B
@@ -18836,6 +18910,14 @@ FFEE;FFEE;FFEE;25CB;25CB; # (๏ฟฎ; ๏ฟฎ; ๏ฟฎ; โ—‹; โ—‹; ) HALFWIDTH WHITE CIRCLE
0061 1E2EE 0315 0300 05AE 0062;0061 05AE 1E2EE 0300 0315 0062;0061 05AE 1E2EE 0300 0315 0062;0061 05AE 1E2EE 0300 0315 0062;0061 05AE 1E2EE 0300 0315 0062; # (aโ—Œ๐ž‹ฎโ—Œฬ•โ—Œฬ€โ—Œึฎb; aโ—Œึฎโ—Œ๐ž‹ฎโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž‹ฎโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž‹ฎโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž‹ฎโ—Œฬ€โ—Œฬ•b; ) LATIN SMALL LETTER A, WANCHO TONE KOI, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1E2EF 0062;00E0 05AE 1E2EF 0315 0062;0061 05AE 0300 1E2EF 0315 0062;00E0 05AE 1E2EF 0315 0062;0061 05AE 0300 1E2EF 0315 0062; # (aโ—Œฬ•โ—Œฬ€โ—Œึฎโ—Œ๐ž‹ฏb; ร โ—Œึฎโ—Œ๐ž‹ฏโ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐ž‹ฏโ—Œฬ•b; ร โ—Œึฎโ—Œ๐ž‹ฏโ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐ž‹ฏโ—Œฬ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, WANCHO TONE KOINI, LATIN SMALL LETTER B
0061 1E2EF 0315 0300 05AE 0062;0061 05AE 1E2EF 0300 0315 0062;0061 05AE 1E2EF 0300 0315 0062;0061 05AE 1E2EF 0300 0315 0062;0061 05AE 1E2EF 0300 0315 0062; # (aโ—Œ๐ž‹ฏโ—Œฬ•โ—Œฬ€โ—Œึฎb; aโ—Œึฎโ—Œ๐ž‹ฏโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž‹ฏโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž‹ฏโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž‹ฏโ—Œฬ€โ—Œฬ•b; ) LATIN SMALL LETTER A, WANCHO TONE KOINI, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 035C 0315 0300 1E4EC 0062;00E0 0315 1E4EC 035C 0062;0061 0300 0315 1E4EC 035C 0062;00E0 0315 1E4EC 035C 0062;0061 0300 0315 1E4EC 035C 0062; # (aโ—Œอœโ—Œฬ•โ—Œฬ€โ—Œ๐ž“ฌb; ร โ—Œฬ•โ—Œ๐ž“ฌโ—Œอœb; aโ—Œฬ€โ—Œฬ•โ—Œ๐ž“ฌโ—Œอœb; ร โ—Œฬ•โ—Œ๐ž“ฌโ—Œอœb; aโ—Œฬ€โ—Œฬ•โ—Œ๐ž“ฌโ—Œอœb; ) LATIN SMALL LETTER A, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, NAG MUNDARI SIGN MUHOR, LATIN SMALL LETTER B
+0061 1E4EC 035C 0315 0300 0062;00E0 1E4EC 0315 035C 0062;0061 0300 1E4EC 0315 035C 0062;00E0 1E4EC 0315 035C 0062;0061 0300 1E4EC 0315 035C 0062; # (aโ—Œ๐ž“ฌโ—Œอœโ—Œฬ•โ—Œฬ€b; ร โ—Œ๐ž“ฌโ—Œฬ•โ—Œอœb; aโ—Œฬ€โ—Œ๐ž“ฌโ—Œฬ•โ—Œอœb; ร โ—Œ๐ž“ฌโ—Œฬ•โ—Œอœb; aโ—Œฬ€โ—Œ๐ž“ฌโ—Œฬ•โ—Œอœb; ) LATIN SMALL LETTER A, NAG MUNDARI SIGN MUHOR, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, LATIN SMALL LETTER B
+0061 035C 0315 0300 1E4ED 0062;00E0 0315 1E4ED 035C 0062;0061 0300 0315 1E4ED 035C 0062;00E0 0315 1E4ED 035C 0062;0061 0300 0315 1E4ED 035C 0062; # (aโ—Œอœโ—Œฬ•โ—Œฬ€โ—Œ๐ž“ญb; ร โ—Œฬ•โ—Œ๐ž“ญโ—Œอœb; aโ—Œฬ€โ—Œฬ•โ—Œ๐ž“ญโ—Œอœb; ร โ—Œฬ•โ—Œ๐ž“ญโ—Œอœb; aโ—Œฬ€โ—Œฬ•โ—Œ๐ž“ญโ—Œอœb; ) LATIN SMALL LETTER A, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, NAG MUNDARI SIGN TOYOR, LATIN SMALL LETTER B
+0061 1E4ED 035C 0315 0300 0062;00E0 1E4ED 0315 035C 0062;0061 0300 1E4ED 0315 035C 0062;00E0 1E4ED 0315 035C 0062;0061 0300 1E4ED 0315 035C 0062; # (aโ—Œ๐ž“ญโ—Œอœโ—Œฬ•โ—Œฬ€b; ร โ—Œ๐ž“ญโ—Œฬ•โ—Œอœb; aโ—Œฬ€โ—Œ๐ž“ญโ—Œฬ•โ—Œอœb; ร โ—Œ๐ž“ญโ—Œฬ•โ—Œอœb; aโ—Œฬ€โ—Œ๐ž“ญโ—Œฬ•โ—Œอœb; ) LATIN SMALL LETTER A, NAG MUNDARI SIGN TOYOR, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1E4EE 0062;0061 1DFA 0316 1E4EE 059A 0062;0061 1DFA 0316 1E4EE 059A 0062;0061 1DFA 0316 1E4EE 059A 0062;0061 1DFA 0316 1E4EE 059A 0062; # (aโ—Œึšโ—Œฬ–โ—Œแทบโ—Œ๐ž“ฎb; aโ—Œแทบโ—Œฬ–โ—Œ๐ž“ฎโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ž“ฎโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ž“ฎโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐ž“ฎโ—Œึšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, NAG MUNDARI SIGN IKIR, LATIN SMALL LETTER B
+0061 1E4EE 059A 0316 1DFA 0062;0061 1DFA 1E4EE 0316 059A 0062;0061 1DFA 1E4EE 0316 059A 0062;0061 1DFA 1E4EE 0316 059A 0062;0061 1DFA 1E4EE 0316 059A 0062; # (aโ—Œ๐ž“ฎโ—Œึšโ—Œฬ–โ—Œแทบb; aโ—Œแทบโ—Œ๐ž“ฎโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ž“ฎโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ž“ฎโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐ž“ฎโ—Œฬ–โ—Œึšb; ) LATIN SMALL LETTER A, NAG MUNDARI SIGN IKIR, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1E4EF 0062;00E0 05AE 1E4EF 0315 0062;0061 05AE 0300 1E4EF 0315 0062;00E0 05AE 1E4EF 0315 0062;0061 05AE 0300 1E4EF 0315 0062; # (aโ—Œฬ•โ—Œฬ€โ—Œึฎโ—Œ๐ž“ฏb; ร โ—Œึฎโ—Œ๐ž“ฏโ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐ž“ฏโ—Œฬ•b; ร โ—Œึฎโ—Œ๐ž“ฏโ—Œฬ•b; aโ—Œึฎโ—Œฬ€โ—Œ๐ž“ฏโ—Œฬ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, NAG MUNDARI SIGN SUTUH, LATIN SMALL LETTER B
+0061 1E4EF 0315 0300 05AE 0062;0061 05AE 1E4EF 0300 0315 0062;0061 05AE 1E4EF 0300 0315 0062;0061 05AE 1E4EF 0300 0315 0062;0061 05AE 1E4EF 0300 0315 0062; # (aโ—Œ๐ž“ฏโ—Œฬ•โ—Œฬ€โ—Œึฎb; aโ—Œึฎโ—Œ๐ž“ฏโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž“ฏโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž“ฏโ—Œฬ€โ—Œฬ•b; aโ—Œึฎโ—Œ๐ž“ฏโ—Œฬ€โ—Œฬ•b; ) LATIN SMALL LETTER A, NAG MUNDARI SIGN SUTUH, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 059A 0316 1DFA 1E8D0 0062;0061 1DFA 0316 1E8D0 059A 0062;0061 1DFA 0316 1E8D0 059A 0062;0061 1DFA 0316 1E8D0 059A 0062;0061 1DFA 0316 1E8D0 059A 0062; # (aโ—Œึšโ—Œฬ–โ—Œแทบโ—Œ๐žฃb; aโ—Œแทบโ—Œฬ–โ—Œ๐žฃโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐žฃโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐žฃโ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐žฃโ—Œึšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MENDE KIKAKUI COMBINING NUMBER TEENS, LATIN SMALL LETTER B
0061 1E8D0 059A 0316 1DFA 0062;0061 1DFA 1E8D0 0316 059A 0062;0061 1DFA 1E8D0 0316 059A 0062;0061 1DFA 1E8D0 0316 059A 0062;0061 1DFA 1E8D0 0316 059A 0062; # (aโ—Œ๐žฃโ—Œึšโ—Œฬ–โ—Œแทบb; aโ—Œแทบโ—Œ๐žฃโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐žฃโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐žฃโ—Œฬ–โ—Œึšb; aโ—Œแทบโ—Œ๐žฃโ—Œฬ–โ—Œึšb; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER TEENS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 059A 0316 1DFA 1E8D1 0062;0061 1DFA 0316 1E8D1 059A 0062;0061 1DFA 0316 1E8D1 059A 0062;0061 1DFA 0316 1E8D1 059A 0062;0061 1DFA 0316 1E8D1 059A 0062; # (aโ—Œึšโ—Œฬ–โ—Œแทบโ—Œ๐žฃ‘b; aโ—Œแทบโ—Œฬ–โ—Œ๐žฃ‘โ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐žฃ‘โ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐žฃ‘โ—Œึšb; aโ—Œแทบโ—Œฬ–โ—Œ๐žฃ‘โ—Œึšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MENDE KIKAKUI COMBINING NUMBER TENS, LATIN SMALL LETTER B
diff --git a/glib/tests/mainloop.c b/glib/tests/mainloop.c
index 9904da833..4c63df168 100644
--- a/glib/tests/mainloop.c
+++ b/glib/tests/mainloop.c
@@ -1702,10 +1702,6 @@ threadf (gpointer data)
static void
test_mainloop_wait (void)
{
-#ifdef _GLIB_ADDRESS_SANITIZER
- (void) threadf;
- g_test_incomplete ("FIXME: Leaks a GMainLoop, see glib#2307");
-#else
GMainContext *context;
GThread *t1, *t2;
@@ -1718,7 +1714,6 @@ test_mainloop_wait (void)
g_thread_join (t2);
g_main_context_unref (context);
-#endif
}
#endif
diff --git a/glib/tests/markup-example.c b/glib/tests/markup-example.c
new file mode 100644
index 000000000..63e1a481c
--- /dev/null
+++ b/glib/tests/markup-example.c
@@ -0,0 +1,168 @@
+/* Copyright (C) 2008 Luc Pionchon
+ * Copyright (C) 2012 David King
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+
+static void foo_parser_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error);
+static void foo_parser_end_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error);
+static void foo_parser_characters (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error);
+static void foo_parser_passthrough (GMarkupParseContext *context,
+ const gchar *passthrough_text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error);
+static void foo_parser_error (GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data);
+
+/*
+ * Parser
+ */
+static const GMarkupParser foo_xml_parser = {
+ foo_parser_start_element,
+ foo_parser_end_element,
+ foo_parser_characters,
+ foo_parser_passthrough,
+ foo_parser_error
+};
+
+/*
+ * Called for opening tags like <foo bar="baz">
+ */
+static void
+foo_parser_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ g_print ("element: <%s>\n", element_name);
+
+ for (gsize i = 0; attribute_names[i]; i++)
+ {
+ g_print ("attribute: %s = \"%s\"\n", attribute_names[i],
+ attribute_values[i]);
+ }
+}
+
+/*
+ * Called for closing tags like </foo>
+ */
+static void
+foo_parser_end_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ g_print ("element: </%s>\n", element_name);
+}
+
+/*
+ * Called for character data. Text is not nul-terminated
+ */
+static void
+foo_parser_characters (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ g_print ("text: [%s]\n", text);
+}
+
+/*
+ * Called for strings that should be re-saved verbatim in this same
+ * position, but are not otherwise interpretable. At the moment this
+ * includes comments and processing instructions. Text is not
+ * nul-terminated.
+ */
+static void
+foo_parser_passthrough (GMarkupParseContext *context,
+ const gchar *passthrough_text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ g_print ("passthrough: %s\n", passthrough_text);
+}
+
+/*
+ * Called when any parsing method encounters an error. The GError should not be
+ * freed.
+ */
+static void
+foo_parser_error (GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data)
+{
+ g_printerr ("ERROR: %s\n", error->message);
+}
+
+int
+main (void)
+{
+ GMarkupParseContext *context;
+ gboolean success = FALSE;
+ glong len;
+
+ /*
+ * Example XML for the parser.
+ */
+ const gchar foo_xml_example[] =
+ "<foo bar='baz' bir='boz'>"
+ " <bar>bar text 1</bar> "
+ " <bar>bar text 2</bar> "
+ " foo text "
+ "<!-- nothing --> "
+ "</foo> ";
+
+ len = g_utf8_strlen (foo_xml_example, -1);
+ g_print ("Parsing: %s\n", foo_xml_example);
+ g_print ("(%ld UTF-8 characters)\n", len);
+
+ context = g_markup_parse_context_new (&foo_xml_parser, G_MARKUP_DEFAULT_FLAGS, NULL, NULL);
+
+ success = g_markup_parse_context_parse (context, foo_xml_example, len, NULL);
+
+ g_markup_parse_context_free (context);
+
+ if (success)
+ {
+ g_print ("DONE\n");
+ return 0;
+ }
+ else
+ {
+ g_printerr ("ERROR\n");
+ return 1;
+ }
+}
diff --git a/glib/tests/meson.build b/glib/tests/meson.build
index a90051076..72a6ff92b 100644
--- a/glib/tests/meson.build
+++ b/glib/tests/meson.build
@@ -281,6 +281,7 @@ endif
test_extra_programs = {
'assert-msg-test' : {},
+ 'markup-example' : {'install' : false},
'spawn-path-search-helper' : {},
'spawn-test-helper' : {},
'testing-helper' : {},
diff --git a/glib/tests/unicode.c b/glib/tests/unicode.c
index d4955c6d1..5d66977c2 100644
--- a/glib/tests/unicode.c
+++ b/glib/tests/unicode.c
@@ -459,6 +459,10 @@ test_strup (void)
/* Tricky, comparing two unicode strings with an ASCII function */
g_assert_cmpstr (str_up, ==, "AAZZ09X;\003E\357\274\241\357\274\241");
g_free (str_up);
+
+ str_up = g_utf8_strup ("", 0);
+ g_assert_cmpstr (str_up, ==, "");
+ g_free (str_up);
}
/* Test that g_utf8_strdown() returns the correct value for various
@@ -484,6 +488,10 @@ test_strdown (void)
/* Tricky, comparing two unicode strings with an ASCII function */
g_assert_cmpstr (str_down, ==, "aazz09x;\003\007\357\275\201\357\275\201");
g_free (str_down);
+
+ str_down = g_utf8_strdown ("", 0);
+ g_assert_cmpstr (str_down, ==, "");
+ g_free (str_down);
}
/* Test that g_utf8_strup() and g_utf8_strdown() return the correct
@@ -576,6 +584,10 @@ test_casefold (void)
/* Tricky, comparing two unicode strings with an ASCII function */
g_assert_cmpstr (str_casefold, ==, "aazz09x;\357\275\201\357\275\201");
g_free (str_casefold);
+
+ str_casefold = g_utf8_casefold ("", 0);
+ g_assert_cmpstr (str_casefold, ==, "");
+ g_free (str_casefold);
}
static void
@@ -1889,6 +1901,45 @@ test_iso15924 (void)
#undef PACK
}
+static void
+test_normalize (void)
+{
+ guint i;
+ typedef struct
+ {
+ const gchar *str;
+ const gchar *nfd;
+ const gchar *nfc;
+ const gchar *nfkd;
+ const gchar *nfkc;
+ } Test;
+ Test tests[] = {
+ { "ร„ffin", "A\u0308ffin", "ร„ffin", "A\u0308ffin", "ร„ffin" },
+ { "ร„\uFB03n", "A\u0308\uFB03n", "ร„\uFB03n", "A\u0308ffin", "ร„ffin" },
+ { "Henry IV", "Henry IV", "Henry IV", "Henry IV", "Henry IV" },
+ { "Henry \u2163", "Henry \u2163", "Henry \u2163", "Henry IV", "Henry IV" },
+ { "non-utf\x88", NULL, NULL, NULL, NULL },
+ { "", "", "", "", "" },
+ };
+
+#define TEST(str, mode, expected) \
+ { \
+ gchar *normalized = g_utf8_normalize (str, -1, mode); \
+ g_assert_cmpstr (normalized, ==, expected); \
+ g_free (normalized); \
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (tests); i++)
+ {
+ TEST (tests[i].str, G_NORMALIZE_NFD, tests[i].nfd);
+ TEST (tests[i].str, G_NORMALIZE_NFC, tests[i].nfc);
+ TEST (tests[i].str, G_NORMALIZE_NFKD, tests[i].nfkd);
+ TEST (tests[i].str, G_NORMALIZE_NFKC, tests[i].nfkc);
+ }
+
+#undef TEST
+}
+
int
main (int argc,
char *argv[])
@@ -1933,6 +1984,7 @@ main (int argc,
g_test_add_func ("/unicode/xdigit", test_xdigit);
g_test_add_func ("/unicode/xdigit-value", test_xdigit_value);
g_test_add_func ("/unicode/zero-width", test_zerowidth);
+ g_test_add_func ("/unicode/normalize", test_normalize);
return g_test_run();
}
diff --git a/gmodule/meson.build b/gmodule/meson.build
index 4b0778e70..237992fcc 100644
--- a/gmodule/meson.build
+++ b/gmodule/meson.build
@@ -115,22 +115,24 @@ pkg.generate(libgmodule,
description : 'Dynamic module loader for GLib',
)
-pkg.generate(libraries : [libgmodule, export_dynamic_ldflags],
+pkg.generate(libraries : [libgmodule],
requires : ['glib-2.0'],
version : glib_version,
variables : [supported_var],
install_dir : glib_pkgconfigreldir,
filebase : 'gmodule-export-2.0',
+ extra_cflags : export_dynamic_cflags,
name : 'GModule',
description : 'Dynamic module loader for GLib',
)
-pkg.generate(libraries : [libgmodule, export_dynamic_ldflags],
+pkg.generate(libraries : [libgmodule],
requires : ['glib-2.0'],
version : glib_version,
variables : [supported_var],
install_dir : glib_pkgconfigreldir,
filebase : 'gmodule-2.0',
+ extra_cflags : export_dynamic_cflags,
name : 'GModule',
description : 'Dynamic module loader for GLib',
)
diff --git a/gobject/gsignal.c b/gobject/gsignal.c
index dd1c6b50d..bf3e9c66e 100644
--- a/gobject/gsignal.c
+++ b/gobject/gsignal.c
@@ -2946,8 +2946,11 @@ signal_handlers_foreach_matched_unlocked_R (gpointer instance,
* @data: (nullable) (closure closure): The closure data of the handlers' closures.
*
* Blocks all handlers on an instance that match a certain selection criteria.
- * The criteria mask is passed as an OR-ed combination of #GSignalMatchType
- * flags, and the criteria values are passed as arguments.
+ *
+ * The criteria mask is passed as a combination of #GSignalMatchType flags, and
+ * the criteria values are passed as arguments. A handler must match on all
+ * flags set in @mask to be blocked (i.e. the match is conjunctive).
+ *
* Passing at least one of the %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC
* or %G_SIGNAL_MATCH_DATA match flags is required for successful matches.
* If no handlers were found, 0 is returned, the number of blocked handlers
@@ -2994,8 +2997,12 @@ g_signal_handlers_block_matched (gpointer instance,
* @data: (nullable) (closure closure): The closure data of the handlers' closures.
*
* Unblocks all handlers on an instance that match a certain selection
- * criteria. The criteria mask is passed as an OR-ed combination of
- * #GSignalMatchType flags, and the criteria values are passed as arguments.
+ * criteria.
+ *
+ * The criteria mask is passed as a combination of #GSignalMatchType flags, and
+ * the criteria values are passed as arguments. A handler must match on all
+ * flags set in @mask to be unblocked (i.e. the match is conjunctive).
+ *
* Passing at least one of the %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC
* or %G_SIGNAL_MATCH_DATA match flags is required for successful matches.
* If no handlers were found, 0 is returned, the number of unblocked handlers
@@ -3043,10 +3050,13 @@ g_signal_handlers_unblock_matched (gpointer instance,
* @data: (nullable) (closure closure): The closure data of the handlers' closures.
*
* Disconnects all handlers on an instance that match a certain
- * selection criteria. The criteria mask is passed as an OR-ed
- * combination of #GSignalMatchType flags, and the criteria values are
- * passed as arguments. Passing at least one of the
- * %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC or
+ * selection criteria.
+ *
+ * The criteria mask is passed as a combination of #GSignalMatchType flags, and
+ * the criteria values are passed as arguments. A handler must match on all
+ * flags set in @mask to be disconnected (i.e. the match is conjunctive).
+ *
+ * Passing at least one of the %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC or
* %G_SIGNAL_MATCH_DATA match flags is required for successful
* matches. If no handlers were found, 0 is returned, the number of
* disconnected handlers otherwise.
diff --git a/gobject/gtype.h b/gobject/gtype.h
index cba70185e..b68af22ca 100644
--- a/gobject/gtype.h
+++ b/gobject/gtype.h
@@ -268,7 +268,7 @@ G_BEGIN_DECLS
*
* Checks if @type is a fundamental type.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE is @type is fundamental
*/
#define G_TYPE_IS_FUNDAMENTAL(type) ((type) <= G_TYPE_FUNDAMENTAL_MAX)
/**
@@ -279,7 +279,7 @@ G_BEGIN_DECLS
* inherited) from another type (this holds true for all non-fundamental
* types).
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @type is derived
*/
#define G_TYPE_IS_DERIVED(type) ((type) > G_TYPE_FUNDAMENTAL_MAX)
/**
@@ -295,7 +295,7 @@ G_BEGIN_DECLS
* with the difference that GType interfaces are not derivable (but see
* g_type_interface_add_prerequisite() for an alternative).
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @type is an interface
*/
#define G_TYPE_IS_INTERFACE(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_INTERFACE)
/**
@@ -304,7 +304,16 @@ G_BEGIN_DECLS
*
* Checks if @type is a classed type.
*
- * Returns: %TRUE on success
+ * A classed type has an associated #GTypeClass which can be derived to store
+ * class-wide virtual function pointers and data for all instances of the type.
+ * This allows for subclassing. All #GObjects are classed; none of the scalar
+ * fundamental types built into GLib are classed.
+ *
+ * Interfaces are not classed: while their #GTypeInterface struct could be
+ * considered similar to #GTypeClass, and classes can derive interfaces,
+ * #GTypeInterface doesnโ€™t allow for subclassing.
+ *
+ * Returns: %TRUE if @type is classed
*/
#define G_TYPE_IS_CLASSED(type) (g_type_test_flags ((type), G_TYPE_FLAG_CLASSED))
/**
@@ -314,7 +323,7 @@ G_BEGIN_DECLS
* Checks if @type can be instantiated. Instantiation is the
* process of creating an instance (object) of this type.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @type is instantiatable
*/
#define G_TYPE_IS_INSTANTIATABLE(type) (g_type_test_flags ((type), G_TYPE_FLAG_INSTANTIATABLE))
/**
@@ -324,7 +333,7 @@ G_BEGIN_DECLS
* Checks if @type is a derivable type. A derivable type can
* be used as the base class of a flat (single-level) class hierarchy.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @type is derivable
*/
#define G_TYPE_IS_DERIVABLE(type) (g_type_test_flags ((type), G_TYPE_FLAG_DERIVABLE))
/**
@@ -334,7 +343,7 @@ G_BEGIN_DECLS
* Checks if @type is a deep derivable type. A deep derivable type
* can be used as the base class of a deep (multi-level) class hierarchy.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @type is deep derivable
*/
#define G_TYPE_IS_DEEP_DERIVABLE(type) (g_type_test_flags ((type), G_TYPE_FLAG_DEEP_DERIVABLE))
/**
@@ -345,7 +354,7 @@ G_BEGIN_DECLS
* instantiated and is normally used as an abstract base class for
* derived classes.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @type is abstract
*/
#define G_TYPE_IS_ABSTRACT(type) (g_type_test_flags ((type), G_TYPE_FLAG_ABSTRACT))
/**
@@ -356,7 +365,7 @@ G_BEGIN_DECLS
* a value table, but can't be used for g_value_init() and is normally used as
* an abstract base type for derived value types.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @type is an abstract value type
*/
#define G_TYPE_IS_VALUE_ABSTRACT(type) (g_type_test_flags ((type), G_TYPE_FLAG_VALUE_ABSTRACT))
/**
@@ -365,7 +374,7 @@ G_BEGIN_DECLS
*
* Checks if @type is a value type and can be used with g_value_init().
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @type is a value type
*/
#define G_TYPE_IS_VALUE_TYPE(type) (g_type_check_is_value_type (type))
/**
@@ -374,7 +383,7 @@ G_BEGIN_DECLS
*
* Checks if @type has a #GTypeValueTable.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @type has a value table
*/
#define G_TYPE_HAS_VALUE_TABLE(type) (g_type_value_table_peek (type) != NULL)
/**
@@ -384,7 +393,7 @@ G_BEGIN_DECLS
* Checks if @type is a final type. A final type cannot be derived any
* further.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @type is final
*
* Since: 2.70
*/
@@ -497,7 +506,7 @@ struct _GTypeQuery
*
* This macro should only be used in type implementations.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @instance is valid
*/
#define G_TYPE_CHECK_INSTANCE(instance) (_G_TYPE_CHI ((GTypeInstance*) (instance)))
/**
@@ -525,7 +534,7 @@ struct _GTypeQuery
*
* This macro should only be used in type implementations.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @instance is an instance of @g_type
*/
#define G_TYPE_CHECK_INSTANCE_TYPE(instance, g_type) (_G_TYPE_CIT ((instance), (g_type)))
/**
@@ -538,7 +547,7 @@ struct _GTypeQuery
*
* This macro should only be used in type implementations.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @instance is an instance of @g_type
*/
#define G_TYPE_CHECK_INSTANCE_FUNDAMENTAL_TYPE(instance, g_type) (_G_TYPE_CIFT ((instance), (g_type)))
/**
@@ -594,7 +603,7 @@ struct _GTypeQuery
*
* This macro should only be used in type implementations.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @g_class is a class structure of @g_type
*/
#define G_TYPE_CHECK_CLASS_TYPE(g_class, g_type) (_G_TYPE_CCT ((g_class), (g_type)))
/**
@@ -606,7 +615,7 @@ struct _GTypeQuery
*
* This macro should only be used in type implementations.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @value is initialized
*/
#define G_TYPE_CHECK_VALUE(value) (_G_TYPE_CHV ((value)))
/**
@@ -619,7 +628,7 @@ struct _GTypeQuery
*
* This macro should only be used in type implementations.
*
- * Returns: %TRUE on success
+ * Returns: %TRUE if @value has been initialized to hold values of type @g_type
*/
#define G_TYPE_CHECK_VALUE_TYPE(value, g_type) (_G_TYPE_CVH ((value), (g_type)))
/**
diff --git a/gobject/tests/signals.c b/gobject/tests/signals.c
index 1c7085244..bc0306082 100644
--- a/gobject/tests/signals.c
+++ b/gobject/tests/signals.c
@@ -1487,6 +1487,11 @@ test_block_handler (void)
g_signal_handlers_unblock_matched (test2, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, test_handler, NULL);
+ /* Match types are conjunctive */
+ g_assert_cmpuint (g_signal_handlers_block_matched (test1, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, test_handler, "will not match"), ==, 0);
+ g_assert_cmpuint (g_signal_handlers_block_matched (test1, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, test_handler, &count1), ==, 1);
+ g_assert_cmpuint (g_signal_handlers_unblock_matched (test1, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, test_handler, &count1), ==, 1);
+
g_object_unref (test1);
g_object_unref (test2);
}
diff --git a/gobject/tests/type-flags.c b/gobject/tests/type-flags.c
index 653cb9b01..bb67f8c03 100644
--- a/gobject/tests/type-flags.c
+++ b/gobject/tests/type-flags.c
@@ -3,6 +3,42 @@
#include <glib-object.h>
+typedef struct
+{
+ GTypeInterface g_iface;
+} TestInterfaceInterface;
+
+GType test_interface_get_type (void);
+#define TEST_TYPE_INTERFACE test_interface_get_type ()
+G_DEFINE_INTERFACE (TestInterface, test_interface, G_TYPE_INVALID)
+
+static void
+test_interface_default_init (TestInterfaceInterface *iface)
+{
+}
+
+static void
+test_type_flags_interface (void)
+{
+ g_assert_false (G_TYPE_IS_ABSTRACT (TEST_TYPE_INTERFACE));
+ g_assert_false (g_type_test_flags (TEST_TYPE_INTERFACE, G_TYPE_FLAG_ABSTRACT));
+
+ g_assert_false (G_TYPE_IS_CLASSED (TEST_TYPE_INTERFACE));
+ g_assert_false (g_type_test_flags (TEST_TYPE_INTERFACE, G_TYPE_FLAG_CLASSED));
+
+ g_assert_false (G_TYPE_IS_DEEP_DERIVABLE (TEST_TYPE_INTERFACE));
+ g_assert_false (g_type_test_flags (TEST_TYPE_INTERFACE, G_TYPE_FLAG_DEEP_DERIVABLE));
+
+ g_assert_true (G_TYPE_IS_DERIVABLE (TEST_TYPE_INTERFACE));
+ g_assert_true (g_type_test_flags (TEST_TYPE_INTERFACE, G_TYPE_FLAG_DERIVABLE));
+
+ g_assert_false (G_TYPE_IS_FINAL (TEST_TYPE_INTERFACE));
+ g_assert_false (g_type_test_flags (TEST_TYPE_INTERFACE, G_TYPE_FLAG_FINAL));
+
+ g_assert_false (G_TYPE_IS_INSTANTIATABLE (TEST_TYPE_INTERFACE));
+ g_assert_false (g_type_test_flags (TEST_TYPE_INTERFACE, G_TYPE_FLAG_INSTANTIATABLE));
+}
+
#define TEST_TYPE_FINAL (test_final_get_type())
G_DECLARE_FINAL_TYPE (TestFinal, test_final, TEST, FINAL, GObject)
@@ -201,6 +237,7 @@ main (int argc, char *argv[])
g_setenv ("G_ENABLE_DIAGNOSTIC", "1", TRUE);
+ g_test_add_func ("/type/flags/interface", test_type_flags_interface);
g_test_add_func ("/type/flags/final", test_type_flags_final);
g_test_add_func ("/type/flags/final/instance-check", test_type_flags_final_instance_check);
g_test_add_func ("/type/flags/deprecated", test_type_flags_deprecated);
diff --git a/meson.build b/meson.build
index 0cbc9689f..62334cea4 100644
--- a/meson.build
+++ b/meson.build
@@ -1,5 +1,5 @@
project('glib', 'c',
- version : '2.76.1',
+ version : '2.77.0',
# NOTE: See the policy in docs/meson-version.md before changing the Meson dependency
meson_version : '>= 0.60.0',
default_options : [
@@ -37,7 +37,7 @@ cc_can_run = meson.can_run_host_binaries()
if cc.get_argument_syntax() == 'msvc'
# Ignore several spurious warnings for things glib does very commonly
# (also for clang-cl)
- add_project_arguments('/FImsvc_recommended_pragmas.h',language : 'c')
+ add_project_arguments('/FIglib/msvc_recommended_pragmas.h', language : 'c')
endif
if cc.get_id() == 'msvc'
@@ -2089,6 +2089,7 @@ libz_dep = dependency('zlib')
# FIXME: glib-gettext.m4 has much more checks to detect broken/uncompatible
# implementations. This could be extended if issues are found in some platforms.
libintl_deps = []
+libintl_prefix = '#include <libintl.h>'
libintl = dependency('intl', required: false, allow_fallback: false)
if libintl.found()
# libintl supports different threading APIs, which may not
@@ -2100,11 +2101,11 @@ if libintl.found()
#
# Meson's builtin dependency lookup as of 0.60.0 doesn't check for
# pthread, so we do this manually here.
- if cc.has_function('ngettext', dependencies : libintl)
+ if cc.has_function('ngettext', dependencies : libintl, prefix: libintl_prefix)
libintl_deps += [libintl]
else
libintl_pthread = cc.find_library('pthread', required : false)
- if libintl_pthread.found() and cc.has_function('ngettext', dependencies : [libintl, libintl_pthread])
+ if libintl_pthread.found() and cc.has_function('ngettext', dependencies : [libintl, libintl_pthread], prefix: libintl_prefix)
libintl_deps += [libintl, libintl_pthread]
else
libintl = disabler()
@@ -2113,7 +2114,7 @@ if libintl.found()
endif
if libintl.found()
- have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset', dependencies: libintl_deps)
+ have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset', dependencies: libintl_deps, prefix: libintl_prefix)
else
libintl = dependency('intl', allow_fallback: true)
assert(libintl.type_name() == 'internal')
@@ -2304,15 +2305,15 @@ if host_system == 'windows'
# Autotools explicitly removed --Wl,--export-all-symbols from windows builds,
# with no explanation. Do the same here for now but this could be revisited if
# if causes issues.
- export_dynamic_ldflags = []
+ export_dynamic_cflags = []
elif host_system == 'cygwin'
- export_dynamic_ldflags = ['-Wl,--export-all-symbols']
+ export_dynamic_cflags = ['-Wl,--export-all-symbols']
elif host_system in ['darwin', 'ios']
- export_dynamic_ldflags = []
+ export_dynamic_cflags = []
elif host_system == 'sunos'
- export_dynamic_ldflags = []
+ export_dynamic_cflags = []
else
- export_dynamic_ldflags = ['-Wl,--export-dynamic']
+ export_dynamic_cflags = ['-Wl,--export-dynamic']
endif
win32_cflags = []
@@ -2420,10 +2421,6 @@ endif
configure_file(output : 'config.h', configuration : glib_conf)
-if host_system == 'windows'
- install_headers([ 'msvc_recommended_pragmas.h' ], install_dir : glib_includedir)
-endif
-
if get_option('man')
xsltproc = find_program('xsltproc', required : true)
xsltproc_command = [