/* * This file is part of matrix-glib-sdk * * matrix-glib-sdk 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 3 of the License, or (at your option) any later version. * * matrix-glib-sdk 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 matrix-glib-sdk. If not, see * . */ #include #include "matrix-c-compacts.h" #include "matrix-types.h" static JsonNode * matrix_json_compact_get_json_node_impl(MatrixJsonCompact *matrix_json_compact, GError **error); /** * MatrixJsonCompactClass: * @finalize: instance finalization function. Should chain up to the @finalize method of the * parent class * @get_json_node: instance method to get the JSON node described by the instance * * Class structure for #MatrixJsonCompact. */ static void matrix_json_compact_class_init(MatrixJsonCompactClass *klass) { ((MatrixJsonCompactClass *)klass)->get_json_node = matrix_json_compact_get_json_node_impl; } MatrixJsonCompact * matrix_json_compact_construct(GType object_type) { MatrixJsonCompact *ret = (MatrixJsonCompact *)g_type_create_instance(object_type); ret->refcount = 1; return ret; } static void matrix_json_compact_init(MatrixJsonCompact *matrix_json_compact) {} /** * matrix_json_compact_ref: * @json_compact: a #MatrixJsonCompact object * * Increment reference count on @json_compact. * * Returns: (transfer full): @json_compact */ MatrixJsonCompact * matrix_json_compact_ref(MatrixJsonCompact *matrix_json_compact) { g_return_val_if_fail(matrix_json_compact != NULL, NULL); ++(matrix_json_compact->refcount); return matrix_json_compact; } static void matrix_json_compact_free(MatrixJsonCompact *matrix_json_compact) { g_return_if_fail(matrix_json_compact != NULL); g_free(matrix_json_compact); } /** * matrix_json_compact_unref: * @json_compact: (transfer full): a #MatrixJsonCompact object * * Decrement reference count on @json_compact. * * If reference count reaches 0, the object is disposed. */ void matrix_json_compact_unref(MatrixJsonCompact *matrix_json_compact) { g_return_if_fail(matrix_json_compact != NULL); if (--(matrix_json_compact->refcount) == 0) { matrix_json_compact_free(matrix_json_compact); } } static JsonNode * matrix_json_compact_get_json_node_impl(MatrixJsonCompact *matrix_json_compact, GError **error) { g_critical("Type `%s' does not implement abstract method `matrix_json_compact_get_json_node'", g_type_name(G_TYPE_FROM_INSTANCE(matrix_json_compact))); return NULL; } /** * matrix_json_compact_get_json_node: * @json_compact: a #MatrixJsonCompact object * @error: a #GError, or %NULL to ignore errors * * Export the contents of @json_compact as a #JsonNode object. * * Subclasses must implement this method. * * Returns: (transfer full): a #JsonNode */ JsonNode * matrix_json_compact_get_json_node(MatrixJsonCompact *matrix_json_compact, GError **error) { g_return_val_if_fail(matrix_json_compact != NULL, NULL); return MATRIX_JSON_COMPACT_GET_CLASS(matrix_json_compact)->get_json_node(matrix_json_compact, error); } /** * matrix_json_compact_get_json_data: * @json_compact: a #MatrixJsonCompact object * @datalen: (nullable): a place to hold the length of the result, or %NULL to ignore * @error: (nullable): a #GError, or %NULL to ignore errors * * Export the contents of the @json_compact as a stringified JSON object. If @datalen is * not %NULL, the length of the resulting string is stored there. * * This function calls matrix_json_compact_get_json_node() internally. If any error happens * during the export, it is stored in @error. * * The returned string is owned by the caller and must be freed. * * Returns: (transfer full): a stringified JSON object */ gchar * matrix_json_compact_get_json_data(MatrixJsonCompact *matrix_json_compact, gsize *datalen, GError **error) { gchar* result = NULL; JsonGenerator* generator = NULL; JsonNode* node = NULL; gsize result_len; GError * inner_error = NULL; g_return_val_if_fail(matrix_json_compact != NULL, NULL); node = matrix_json_compact_get_json_node(matrix_json_compact, &inner_error); if (inner_error != NULL) { g_object_unref(generator); g_propagate_error (error, inner_error); return NULL; } generator = json_generator_new (); json_generator_set_root (generator, node); result = json_generator_to_data (generator, &result_len); json_node_free(node); g_object_unref(generator); if (datalen) { *datalen = result_len; } return result; } static void matrix_value_json_compact_init(GValue *value) { value->data[0].v_pointer = NULL; } static void matrix_value_json_compact_free_value(GValue *value) { matrix_json_compact_unref(value->data[0].v_pointer); } static void matrix_value_json_compact_copy_value(const GValue *src_value, GValue *dest_value) { dest_value->data[0].v_pointer = matrix_json_compact_ref(src_value->data[0].v_pointer); } static gpointer matrix_value_json_compact_peek_pointer(const GValue *value) { return value->data[0].v_pointer; } static gchar * matrix_value_json_compact_collect_value(GValue *value, guint n_collect_values, GTypeCValue *collect_values, guint collect_flags) { if (collect_values[0].v_pointer) { MatrixJsonCompact *object = collect_values[0].v_pointer; if (object->parent_instance.g_class == NULL) { return g_strconcat("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME(value), "'", NULL); } else if (!g_value_type_compatible(G_TYPE_FROM_INSTANCE(object), G_VALUE_TYPE(value))) { return g_strconcat("invalid object type `", g_type_name(G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME(value), "'", NULL); } value->data[0].v_pointer = matrix_json_compact_ref(object); } else { value->data[0].v_pointer = NULL; } return NULL; } static gchar * matrix_value_json_compact_lcopy_value(const GValue *value, guint n_collect_values, GTypeCValue *collect_values, guint collect_flags) { MatrixJsonCompact **object_p = collect_values[0].v_pointer; if (!object_p) { return g_strdup_printf("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME(value)); } if (!value->data[0].v_pointer) { *object_p = NULL; } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { *object_p = value->data[0].v_pointer; } else { *object_p = matrix_json_compact_ref (value->data[0].v_pointer); } return NULL; } /** * MatrixJsonCompact: * * Abstract parent for classes that can be saved to JSON but don’t need full #GObject * functionality. */ GType matrix_json_compact_get_type(void) { static volatile gsize matrix_json_compact_type_id__volatile = 0; if (g_once_init_enter(&matrix_json_compact_type_id__volatile)) { static const GTypeValueTable g_define_type_value_table = { matrix_value_json_compact_init, matrix_value_json_compact_free_value, matrix_value_json_compact_copy_value, matrix_value_json_compact_peek_pointer, "p", matrix_value_json_compact_collect_value, "p", matrix_value_json_compact_lcopy_value }; static const GTypeInfo g_define_type_info = { sizeof(MatrixJsonCompactClass), (GBaseInitFunc)NULL, (GBaseFinalizeFunc)NULL, (GClassInitFunc)matrix_json_compact_class_init, (GClassFinalizeFunc)NULL, NULL, sizeof(MatrixJsonCompact), 0, (GInstanceInitFunc)matrix_json_compact_init, &g_define_type_value_table }; static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; GType matrix_json_compact_type_id; matrix_json_compact_type_id = g_type_register_fundamental(g_type_fundamental_next(), "MatrixJsonCompact", &g_define_type_info, &g_define_type_fundamental_info, G_TYPE_FLAG_ABSTRACT); g_once_init_leave(&matrix_json_compact_type_id__volatile, matrix_json_compact_type_id); } return matrix_json_compact_type_id__volatile; } typedef struct { guint64 _limit; gchar **_types; guint _types_len; gchar **_excluded_types; guint _excluded_types_len; gchar **_senders; guint _senders_len; gchar **_excluded_senders; guint _excluded_senders_len; gchar **_rooms; guint _rooms_len; gchar **_excluded_rooms; guint _excluded_rooms_len; } MatrixFilterRulesPrivate; /** * MatrixFilterRules: * * Class to hold filtering rules. */ G_DEFINE_TYPE_WITH_PRIVATE(MatrixFilterRules, matrix_filter_rules, MATRIX_TYPE_JSON_COMPACT) /* * STR_ARRAY_TO_JSON: * @PRIV: (not nullable): a variable that holds a #MatrixFilterRulesPrivate struct * @BUILDER: (not nullable): A #JsonBuilder object to use for array building. It must have an * object opened with json_builder_begin_object() * @NAME: (not nullable) (transfer none): the name of the array within the opened object * * Creates a new array with @NAME in the currently open object of @BUILDER. To do so, it will * use the field of the same name from @PRIV. */ #define STR_ARRAY_TO_JSON(PRIV, BUILDER, NAME) \ if ((PRIV)->_ ## NAME ## _len != 0) { \ guint i; \ \ json_builder_set_member_name((BUILDER), #NAME); \ json_builder_begin_array((BUILDER)); \ \ for (i = 0; i < (PRIV)->_ ## NAME ## _len; i++) { \ json_builder_add_string_value((BUILDER), (PRIV)->_ ## NAME [i]); \ }; \ \ json_builder_end_array((BUILDER)); \ } \ \ if ((PRIV)->_excluded_ ## NAME ## _len != 0) { \ guint i; \ \ json_builder_set_member_name((BUILDER), "not_" #NAME); \ json_builder_begin_array((BUILDER)); \ \ for (i = 0; i < (PRIV)->_excluded_ ## NAME ## _len; i++) { \ json_builder_add_string_value((BUILDER), (PRIV)->_excluded_ ## NAME [i]); \ }; \ \ json_builder_end_array((BUILDER)); \ } static JsonNode * matrix_filter_rules_get_json_node(MatrixJsonCompact *matrix_json_compact, GError **error) { MatrixFilterRules *matrix_filter_rules; MatrixFilterRulesPrivate *priv; g_return_val_if_fail(matrix_json_compact != NULL, NULL); matrix_filter_rules = (MatrixFilterRules *)matrix_json_compact; priv = matrix_filter_rules_get_instance_private(matrix_filter_rules); JsonNode* result = NULL; JsonBuilder* builder = NULL; builder = json_builder_new (); json_builder_begin_object (builder); json_builder_set_member_name (builder, "limit"); json_builder_add_int_value (builder, (gint64)priv->_limit); STR_ARRAY_TO_JSON(priv, builder, rooms); STR_ARRAY_TO_JSON(priv, builder, senders); STR_ARRAY_TO_JSON(priv, builder, types); json_builder_end_object(builder); result = json_builder_get_root (builder); g_object_unref(builder); return result; } #undef STR_ARRAY_TO_JSON /** * matrix_filter_rules_construct: * @object_type: the #GType of the object to construct. This must be derived from * #MatrixJsonCompact. * * Construct a new #MatrixFilterRules object. * * Returns: (transfer full): a new #MatrixFilterRules object */ MatrixFilterRules * matrix_filter_rules_construct(GType object_type) { return (MatrixFilterRules *)matrix_json_compact_construct(object_type); } /** * matrix_filter_rules_new: * * Create a new #MatrixFilterRules object with a reference count of 1. * * Returns: (transfer full): a new #MatrixFilterRules object */ MatrixFilterRules * matrix_filter_rules_new(void) { return matrix_filter_rules_construct(MATRIX_TYPE_FILTER_RULES); } /** * matrix_filter_rules_get_limit: * @filter_rules: a #MatrixFilterRules object * * Get the message count limit defined in @filter_rules. * * Returns: the message count limit */ guint matrix_filter_rules_get_limit(MatrixFilterRules *matrix_filter_rules) { MatrixFilterRulesPrivate *priv; g_return_val_if_fail(matrix_filter_rules != NULL, 0); priv = matrix_filter_rules_get_instance_private(matrix_filter_rules); return priv->_limit; } /** * matrix_filter_rules_set_limit: * @filter_rules: a #MatrixFilterRules object * @limit: the message count limit * * Set the message count limit in @filter_rules. */ void matrix_filter_rules_set_limit(MatrixFilterRules *matrix_filter_rules, guint limit) { MatrixFilterRulesPrivate *priv; g_return_if_fail(matrix_filter_rules != NULL); priv = matrix_filter_rules_get_instance_private(matrix_filter_rules); priv->_limit = limit; } static inline gchar ** copy_str_array(gchar **src, gint n_src) { gchar **dst; if (src == NULL) { return NULL; } dst = g_new0(gchar *, n_src); for (gint i = 0; i < n_src; i++) { dst[i] = g_strdup(src[i]); } return dst; } static inline void free_str_array(gchar **list, gint n_list) { gint i = 0; if (list == NULL) { return; } g_return_if_fail(list != NULL); for (i = 0; i < n_list; i++) { g_free(list[i]); } } /* * STR_ARRAY_GETTER: * @NAME: the name of a string array in #MatrixFilterRulesPrivate * * Create a getter function for @NAME in #MatrixFilterRulesPrivate. */ #define STR_ARRAY_GETTER(NAME) \ gchar ** \ matrix_filter_rules_get_ ## NAME (MatrixFilterRules *matrix_filter_rules, gint *n_ ## NAME) \ { \ MatrixFilterRulesPrivate * priv; \ \ g_return_val_if_fail(matrix_filter_rules != NULL, NULL); \ \ priv = matrix_filter_rules_get_instance_private(matrix_filter_rules); \ \ if (n_ ## NAME != NULL) { \ *n_ ## NAME = priv->_ ## NAME ## _len; \ } \ \ return priv->_ ## NAME; \ } /* * STR_ARRAY_SETTER: * @NAME: the name of a string array in #MatrixFilterRulesPrivate * * Create a setter function for @NAME in #MatrixFilterRulesPrivate */ #define STR_ARRAY_SETTER(NAME) \ void \ matrix_filter_rules_set_ ## NAME (MatrixFilterRules *matrix_filter_rules, gchar ** NAME, gint n_ ## NAME) \ { \ MatrixFilterRulesPrivate * priv; \ \ g_return_if_fail(matrix_filter_rules != NULL); \ \ priv = matrix_filter_rules_get_instance_private(matrix_filter_rules); \ \ free_str_array(priv->_ ## NAME, priv->_ ## NAME ##_len); \ priv->_ ## NAME = copy_str_array(NAME, n_ ## NAME); \ priv->_ ## NAME ## _len = n_ ## NAME; \ } /** * matrix_filter_rules_get_types: * @filter_rules: a #MatrixFilterRules object * @n_types: (nullable): placeholder for the length of the returned list, or %NULL to ignore * * Get the list of message types to be included in the filtered results. * * The returned value is owned by @filter_rules and shouldn’t be freed nor modified. * * Returns: (nullable) (transfer none): a list of message types */ STR_ARRAY_GETTER(types); /** * matrix_filter_rules_set_types: * @filter_rules: a #MatrixFilterRules object * @types: (nullable): a list of message types * @n_types: the number of items in @types * * Set the list of message types to be included in the filtered results. */ STR_ARRAY_SETTER(types); /** * matrix_filter_rules_get_excluded_types: * @filter_rules: a #MatrixFilterRules object * @n_excluded_types: (nullable): placeholder for the length of the returned list, or %NULL to ignore * * Get the list of message types to be excluded in the filtered results. * * The returned value is owned by @filter_rules and shouldn’t be freed nor modified. * * Returns: (transfer none) (nullable): a list of message types to exclude */ STR_ARRAY_GETTER(excluded_types); /** * matrix_filter_rules_set_excluded_types: * @filter_rules: a #MatrixFilterRules object * @excluded_types: (nullable): a list of types to exclude * @n_excluded_types: the number of items in @excluded_types * * Set the list of message types to be excluded in the filtered results. The message types in * this list will be excluded even if they would be explicitly included (ie. set with * matrix_filter_rules_set_types()). */ STR_ARRAY_SETTER(excluded_types) /** * matrix_filter_rules_get_senders: * @filter_rules: a #MatrixFilterRules object * @n_senders: (nullable): placeholder for the length of the returned list, or %NULL to ignore * * Get the list of senders whose messages should to be included in the filtered results. * * The returned value is owned by @filter_rules and shouldn’t be freed nor modified. * * Returns: (transfer none) (nullable): a list of sender Matrix IDs */ STR_ARRAY_GETTER(senders); /** * matrix_filter_rules_set_senders: * @filter_rules: a #MatrixFilterRules object * @senders: (nullable): a list of Matrix IDs * @n_senders: the number of items in @senders * * Set the list of Matrix IDs whose messages should be included in the filtered results. */ STR_ARRAY_SETTER(senders); /** * matrix_filter_rules_get_excluded_senders: * @filter_rules: a #MatrixFilterRules object * @n_excluded_senders: (nullable): placeholder for the length of the returned list, or %NULL * to ignore * * Get the list of sender Matrix IDs to be excluded from the filtered results. * * The returned value is owned by @filter_rules and shouldn’t be freed nor modified. * * Returns: (transfer none) (nullable): a list of Matrix IDs to exclude */ STR_ARRAY_GETTER(excluded_senders); /** * matrix_filter_rules_set_excluded_senders: * @filter_rules: a #MatrixFilterRules object * @excluded_senders: (nullable): a list of Matrix IDs to exclude * @n_excluded_senders: the number of items in @excluded_senders * * Set the list of Matrix IDs whose messages should be excluded from the filtered results. * Messages from Matrix IDs in this list will be excluded even if they would be explicitly * included (ie. set with matrix_filter_rules_set_senders()). */ STR_ARRAY_SETTER(excluded_senders); /** * matrix_filter_rules_get_rooms: * @filter_rules: a #MatrixFilterRules object * @n_rooms: (nullable): placeholder for the length of the returned list, or %NULL to ignore * * Get the list of rooms to be included in the filtered results. * * The returned value is owned by @filter_rules and shouldn’t be freed nor modified. * * Returns: (transfer none) (nullable): a list of rooms */ STR_ARRAY_GETTER(rooms); /** * matrix_filter_rules_set_rooms: * @filter_rules: a #MatrixFilterRules object * @rooms: (nullable): a list of room IDs * @n_rooms: the number of items in @rooms * * Set the list of rooms to be included in the filtered results. */ STR_ARRAY_SETTER(rooms); /** * matrix_filter_rules_get_excluded_rooms: * @filter_rules: a #MatrixFilterRules object * @n_excluded_rooms: (nullable): placeholder for the length of the returned list, or %NULL to ignore * * Get the list of room IDs to be excluded in the filtered results. * * The returned value is owned by @filter_rules and shouldn’t be freed nor modified. * * Returns: (transfer none) (nullable): a list of room IDs to exclude */ STR_ARRAY_GETTER(excluded_rooms); /** * matrix_filter_rules_set_excluded_rooms: * @filter_rules: a #MatrixFilterRules object * @excluded_rooms: (nullable): a list of room IDs to exclude * @n_excluded_rooms: the number of items in @excluded_rooms * * Set the list of room IDs to be excluded from the filtered results. The room IDs in this * list will be excluded even if they would be explicitly included (ie. set with * matrix_filter_rules_set_rooms()). */ STR_ARRAY_SETTER(excluded_rooms); static void matrix_filter_rules_finalize (MatrixJsonCompact *matrix_json_compact) { MatrixFilterRules *matrix_filter_rules; MatrixFilterRulesPrivate *priv; g_return_if_fail(matrix_json_compact != NULL); matrix_filter_rules = MATRIX_FILTER_RULES(matrix_json_compact); priv = matrix_filter_rules_get_instance_private(matrix_filter_rules); priv->_types = (free_str_array(priv->_types, priv->_types_len), NULL); priv->_excluded_types = (free_str_array(priv->_excluded_types, priv->_excluded_types_len), NULL); priv->_senders = (free_str_array(priv->_senders, priv->_senders_len), NULL); priv->_excluded_senders = (free_str_array(priv->_excluded_senders, priv->_excluded_senders_len), NULL); priv->_rooms = (free_str_array(priv->_rooms, priv->_rooms_len), NULL); priv->_excluded_rooms = (free_str_array(priv->_excluded_rooms, priv->_excluded_rooms_len), NULL); MATRIX_JSON_COMPACT_CLASS(matrix_filter_rules_parent_class)->finalize(matrix_json_compact); } static void matrix_filter_rules_class_init(MatrixFilterRulesClass *klass) { ((MatrixJsonCompactClass *)klass)->finalize = matrix_filter_rules_finalize; ((MatrixJsonCompactClass *)klass)->get_json_node = (JsonNode* (*) (MatrixJsonCompact *, GError**)) matrix_filter_rules_get_json_node; } static void matrix_filter_rules_init(MatrixFilterRules *matrix_filter_rules) {}