Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Please login to access the resource
home:MaxxedSUSE:leap
libglibutil
_service:obs_scm:libglibutil-1714660956.7df665e...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:libglibutil-1714660956.7df665e.obscpio of Package libglibutil
07070100000000000081A40000000000000000000000016633A65C0000020A000000000000000000000000000000000000002A00000000libglibutil-1714660956.7df665e/.gitignore*~ test/libglibutil_test.ncb test/libglibutil_test.opt test/coverage/full.gcov test/coverage/libglibutil.gcov test/coverage/results debian/.debhelper debian/files debian/libglibutil-dev.debhelper.log debian/libglibutil-dev.install debian/libglibutil-dev.substvars debian/libglibutil-dev debian/libglibutil.debhelper.log debian/libglibutil.install debian/libglibutil.postinst.debhelper debian/libglibutil.postrm.debhelper debian/libglibutil.substvars debian/libglibutil debian/tmp documentation.list installroot build RPMS 07070100000001000081A40000000000000000000000016633A65C00000610000000000000000000000000000000000000002700000000libglibutil-1714660956.7df665e/LICENSECopyright (C) 2023-2024 Slava Monich <slava@monich.com> Copyright (C) 2014-2022 Jolla Ltd. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the names of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 07070100000002000081A40000000000000000000000016633A65C00001A90000000000000000000000000000000000000002800000000libglibutil-1714660956.7df665e/Makefile# -*- Mode: makefile-gmake -*- .PHONY: clean all debug release coverage pkgconfig install install-dev test .PHONY: print_debug_lib print_release_lib print_coverage_lib # # Required packages # PKGS = glib-2.0 gobject-2.0 # # Default target # all: debug release pkgconfig # # Directories # SRC_DIR = src INCLUDE_DIR = include BUILD_DIR = build DEBUG_BUILD_DIR = $(BUILD_DIR)/debug RELEASE_BUILD_DIR = $(BUILD_DIR)/release COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage # # Library version # VERSION_FILE = $(INCLUDE_DIR)/gutil_version.h get_version = $(shell grep -E '^ *\#define +GUTIL_VERSION_$1 +[0-9]+$$' $(VERSION_FILE) | sed 's/ */ /g' | cut -d ' ' -f 3) VERSION_MAJOR := $(call get_version,MAJOR) VERSION_MINOR := $(call get_version,MINOR) VERSION_MICRO := $(call get_version,MICRO) # Version for pkg-config PCVERSION := $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_MICRO) # # Library name # NAME = glibutil LIB_NAME = lib$(NAME) LIB_DEV_SYMLINK = $(LIB_NAME).so LIB_SYMLINK1 = $(LIB_DEV_SYMLINK).$(VERSION_MAJOR) LIB_SYMLINK2 = $(LIB_SYMLINK1).$(VERSION_MINOR) LIB_SONAME = $(LIB_SYMLINK1) LIB = $(LIB_SONAME).$(VERSION_MINOR).$(VERSION_MICRO) STATIC_LIB = $(LIB_NAME).a # # Sources # SRC = \ gutil_datapack.c \ gutil_history.c \ gutil_idlepool.c \ gutil_idlequeue.c \ gutil_inotify.c \ gutil_intarray.c \ gutil_ints.c \ gutil_log.c \ gutil_misc.c \ gutil_ring.c \ gutil_strv.c \ gutil_timenotify.c \ gutil_objv.c \ gutil_version.c \ gutil_weakref.c # # Tools and flags # PKG_CONFIG ?= pkg-config CC ?= $(CROSS_COMPILE)gcc STRIP ?= strip LD = $(CC) WARNINGS ?= -Wall -Wsign-compare INCLUDES = -I$(INCLUDE_DIR) BASE_FLAGS = -fPIC FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \ -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32 \ -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_MAX_ALLOWED \ -MMD -MP $(shell $(PKG_CONFIG) --cflags $(PKGS)) FULL_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS) -shared -Wl,-soname,$(LIB_SONAME) \ -Wl,--version-script=$(LIB_NAME).ver LIBS := $(shell $(PKG_CONFIG) --libs $(PKGS)) DEBUG_FLAGS = -g RELEASE_FLAGS = COVERAGE_FLAGS = -g KEEP_SYMBOLS ?= 0 ifneq ($(KEEP_SYMBOLS),0) RELEASE_FLAGS += -g endif DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS) RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS) DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2 COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) -O0 --coverage # # Files # PKGCONFIG = $(BUILD_DIR)/$(LIB_NAME).pc DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o) COVERAGE_OBJS = $(SRC:%.c=$(COVERAGE_BUILD_DIR)/%.o) DEBUG_LIB = $(DEBUG_BUILD_DIR)/$(LIB) RELEASE_LIB = $(RELEASE_BUILD_DIR)/$(LIB) DEBUG_LINK = $(DEBUG_BUILD_DIR)/$(LIB_SYMLINK1) RELEASE_LINK = $(RELEASE_BUILD_DIR)/$(LIB_SYMLINK1) DEBUG_DEV_LINK = $(DEBUG_BUILD_DIR)/$(LIB_DEV_SYMLINK) RELEASE_DEV_LINK = $(RELEASE_BUILD_DIR)/$(LIB_DEV_SYMLINK) DEBUG_STATIC_LIB = $(DEBUG_BUILD_DIR)/$(STATIC_LIB) RELEASE_STATIC_LIB = $(RELEASE_BUILD_DIR)/$(STATIC_LIB) COVERAGE_STATIC_LIB = $(COVERAGE_BUILD_DIR)/$(STATIC_LIB) # # Dependencies # DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d) $(COVERAGE_OBJS:%.o=%.d) ifneq ($(MAKECMDGOALS),clean) ifneq ($(strip $(DEPS)),) -include $(DEPS) endif endif $(PKGCONFIG): | $(BUILD_DIR) $(DEBUG_OBJS) $(DEBUG_LIB) $(DEBUG_STATIC_LIB): | $(DEBUG_BUILD_DIR) $(RELEASE_OBJS) $(RELEASE_LIB) $(RELEASE_STATIC_LIB): | $(RELEASE_BUILD_DIR) $(COVERAGE_OBJS) $(COVERAGE_STATIC_LIB): | $(COVERAGE_BUILD_DIR) # # Rules # debug: $(DEBUG_STATIC_LIB) $(DEBUG_DEV_LINK) release: $(RELEASE_STATIC_LIB) $(RELEASE_DEV_LINK) coverage: $(COVERAGE_STATIC_LIB) pkgconfig: $(PKGCONFIG) print_debug_lib: @echo $(DEBUG_STATIC_LIB) print_release_lib: @echo $(RELEASE_STATIC_LIB) print_coverage_lib: @echo $(COVERAGE_STATIC_LIB) clean: $(MAKE) -C test clean rm -fr test/coverage/results test/coverage/*.gcov rm -f *~ $(SRC_DIR)/*~ $(INCLUDE_DIR)/*~ rm -fr $(BUILD_DIR) RPMS installroot rm -fr debian/tmp debian/libglibutil debian/libglibutil-dev rm -f documentation.list debian/files debian/*.substvars rm -f debian/*.debhelper.log debian/*.debhelper debian/*~ rm -fr debian/*.install test: $(MAKE) -C test test $(BUILD_DIR): mkdir -p $@ $(DEBUG_BUILD_DIR): mkdir -p $@ $(RELEASE_BUILD_DIR): mkdir -p $@ $(COVERAGE_BUILD_DIR): mkdir -p $@ $(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c $(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ $(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c $(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ $(COVERAGE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c $(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ $(DEBUG_LIB): $(DEBUG_OBJS) $(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) -o $@ $(LIBS) $(RELEASE_LIB): $(RELEASE_OBJS) $(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) -o $@ $(LIBS) ifeq ($(KEEP_SYMBOLS),0) $(STRIP) $@ endif $(DEBUG_LINK): $(DEBUG_LIB) ln -sf $(LIB) $@ $(RELEASE_LINK): $(RELEASE_LIB) ln -sf $(LIB) $@ $(DEBUG_DEV_LINK): $(DEBUG_LINK) ln -sf $(LIB_SYMLINK1) $@ $(RELEASE_DEV_LINK): $(RELEASE_LINK) ln -sf $(LIB_SYMLINK1) $@ $(DEBUG_STATIC_LIB): $(DEBUG_OBJS) $(AR) rc $@ $? $(RELEASE_STATIC_LIB): $(RELEASE_OBJS) $(AR) rc $@ $? $(COVERAGE_STATIC_LIB): $(COVERAGE_OBJS) $(AR) rc $@ $? # # LIBDIR usually gets substituted with arch specific dir. # It's relative in deb build and can be whatever in rpm build. # LIBDIR ?= usr/lib ABS_LIBDIR := $(shell echo /$(LIBDIR) | sed -r 's|/+|/|g') $(PKGCONFIG): $(LIB_NAME).pc.in Makefile sed -e 's|@version@|$(PCVERSION)|g' -e 's|@libdir@|$(ABS_LIBDIR)|g' $< > $@ debian/%.install: debian/%.install.in sed 's|@LIBDIR@|$(LIBDIR)|g' $< > $@ # # Install # INSTALL_PERM = 644 INSTALL = install INSTALL_DIRS = $(INSTALL) -d INSTALL_FILES = $(INSTALL) -m $(INSTALL_PERM) INSTALL_LIB_DIR = $(DESTDIR)$(ABS_LIBDIR) INSTALL_INCLUDE_DIR = $(DESTDIR)/usr/include/gutil INSTALL_PKGCONFIG_DIR = $(DESTDIR)$(ABS_LIBDIR)/pkgconfig # # rpm based systems expect libraries to be 755 # deb based systems expect libraries to be 644 # # 755 works for both because dh_fixperms removes execute permissions # from any libraries and other files that don't need it. # install: $(INSTALL_LIB_DIR) $(INSTALL) -m 755 $(RELEASE_LIB) $(INSTALL_LIB_DIR) ln -sf $(LIB) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK2) ln -sf $(LIB_SYMLINK2) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK1) install-dev: install $(INSTALL_INCLUDE_DIR) $(INSTALL_PKGCONFIG_DIR) $(INSTALL_FILES) $(INCLUDE_DIR)/*.h $(INSTALL_INCLUDE_DIR) $(INSTALL_FILES) $(PKGCONFIG) $(INSTALL_PKGCONFIG_DIR) ln -sf $(LIB_SYMLINK1) $(INSTALL_LIB_DIR)/$(LIB_DEV_SYMLINK) $(INSTALL_LIB_DIR): $(INSTALL_DIRS) $@ $(INSTALL_INCLUDE_DIR): $(INSTALL_DIRS) $@ $(INSTALL_PKGCONFIG_DIR): $(INSTALL_DIRS) $@ 07070100000003000081A40000000000000000000000016633A65C0000001B000000000000000000000000000000000000002600000000libglibutil-1714660956.7df665e/READMELibrary of glib utilities. 07070100000004000041ED0000000000000000000000036633A65C00000000000000000000000000000000000000000000002600000000libglibutil-1714660956.7df665e/debian07070100000005000081A40000000000000000000000016633A65C000039D7000000000000000000000000000000000000003000000000libglibutil-1714660956.7df665e/debian/changeloglibglibutil (1.0.79) unstable; urgency=low * Exported gutil_source_remove() and Added gutil_source_clear() -- Slava Monich <slava@monich.com> Thu, 02 May 2024 17:40:30 +0300 libglibutil (1.0.78) unstable; urgency=low * Added gutil_source_remove() * Added gutil_source_clear() -- Slava Monich <slava@monich.com> Thu, 02 May 2024 04:43:18 +0300 libglibutil (1.0.77) unstable; urgency=low * Eliminate defects found by Coverity -- Slava Monich <slava@monich.com> Wed, 10 Apr 2024 04:13:16 +0300 libglibutil (1.0.76) unstable; urgency=low * Added gutil_idle_pool_get_default() * Return the value pushed to the idle pool * Interpret NULL as the default pool when appropriate -- Slava Monich <slava@monich.com> Sun, 28 Jan 2024 02:36:16 +0200 libglibutil (1.0.75) unstable; urgency=low * Cross-compilation tweaks * Compatibility with clang -fsanitize=cfi * Export all and only required symbols -- Slava Monich <slava@monich.com> Fri, 01 Dec 2023 02:01:34 +0200 libglibutil (1.0.74) unstable; urgency=low * Added Added gutil_data_copy_as_variant() -- Slava Monich <slava@monich.com> Sun, 10 Sep 2023 04:11:17 +0300 libglibutil (1.0.73) unstable; urgency=low * Define and use MAKE var instead of explicitly calling make * Added gutil_log_set_timestamp_format() -- Slava Monich <slava@monich.com> Tue, 05 Sep 2023 15:53:55 +0300 libglibutil (1.0.72) unstable; urgency=low * Don't export gutil_time_notify_get_type() * Added gutil_data_new() * Added gutil_data_copy() * Added gutil_objv_new() -- Slava Monich <slava@monich.com> Sun, 20 Aug 2023 02:05:13 +0300 libglibutil (1.0.71) unstable; urgency=low * Added gutil_object_ref() * Added gutil_object_unref() * Added gutil_objv_append() * Added gutil_objv_insert() * Added gutil_ptrv_is_empty() * Added gutil_bin2hex() * Added gutil_data2hex() -- Slava Monich <slava@monich.com> Sun, 18 Jun 2023 14:24:13 +0300 libglibutil (1.0.70) unstable; urgency=low * Added gutil_objv module -- Slava Monich <slava@monich.com> Mon, 29 May 2023 01:35:08 +0300 libglibutil (1.0.69) unstable; urgency=low * Runtime and compile time version detection * Added gutil_datapack module * Require glib 2.32 -- Slava Monich <slava@monich.com> Thu, 06 Apr 2023 02:13:48 +0300 libglibutil (1.0.68) unstable; urgency=low * Added gutil_weakref module * Fixed a few compilation warnings * Packaging tweaks -- Slava Monich <slava@monich.com> Sat, 04 Feb 2023 04:26:45 +0200 libglibutil (1.0.67) unstable; urgency=low * Added gutil_log_dump_bytes() -- Slava Monich <slava.monich@jolla.com> Fri, 15 Jul 2022 03:02:33 +0300 libglibutil (1.0.66) unstable; urgency=low * Bumped debhelper compat level to 7 -- Slava Monich <slava.monich@jolla.com> Fri, 15 Jul 2022 03:02:33 +0300 libglibutil (1.0.65) unstable; urgency=low * Fixed a Musl compatibility issue -- Slava Monich <slava.monich@jolla.com> Thu, 16 Jun 2022 02:12:22 +0300 libglibutil (1.0.64) unstable; urgency=low * Resolved a mysterious parallel build issue -- Slava Monich <slava.monich@jolla.com> Tue, 17 May 2022 03:56:50 +0300 libglibutil (1.0.63) unstable; urgency=low * Added gutil_bytes_has_prefix() * Added gutil_bytes_has_suffix() -- Slava Monich <slava.monich@jolla.com> Sat, 23 Apr 2022 21:24:25 +0300 libglibutil (1.0.62) unstable; urgency=low * Added gutil_strlen0() * Added gutil_strv_find_last() * Added gutil_strv_remove_dups() -- Slava Monich <slava.monich@jolla.com> Sun, 13 Mar 2022 21:59:26 +0200 libglibutil (1.0.61) unstable; urgency=low * Added gutil_strv_remove() -- Slava Monich <slava.monich@jolla.com> Thu, 25 Nov 2021 18:31:18 +0200 libglibutil (1.0.60) unstable; urgency=low * Housekeeping release -- Slava Monich <slava.monich@jolla.com> Mon, 22 Nov 2021 23:37:14 +0200 libglibutil (1.0.58) unstable; urgency=low * Don't check upper bound when setting log level from the envvironment -- Slava Monich <slava.monich@jolla.com> Wed, 17 Nov 2021 13:17:45 +0200 libglibutil (1.0.57) unstable; urgency=low * Fixed unit tests for older 32-bit systems -- Slava Monich <slava.monich@jolla.com> Mon, 08 Nov 2021 02:28:37 +0200 libglibutil (1.0.56) unstable; urgency=low * Added gutil_parse_int64() * Added gutil_parse_uint64() -- Slava Monich <slava.monich@jolla.com> Sun, 03 Oct 2021 20:18:15 +0300 libglibutil (1.0.55) unstable; urgency=low * Added gutil_log_dump() * Added gutil_range_init_with_bytes() * Added gutil_range_has_prefix() * Added gutil_range_skip_prefix() -- Slava Monich <slava.monich@jolla.com> Sun, 23 May 2021 03:33:58 +0300 libglibutil (1.0.54) unstable; urgency=low * Added GUtilRange type * Tweaked interpretation of environment variables -- Slava Monich <slava.monich@jolla.com> Mon, 17 May 2021 16:06:25 +0300 libglibutil (1.0.53) unstable; urgency=low * Optimized gutil_parse_int() * Added gutil_parse_uint() -- Slava Monich <slava.monich@jolla.com> Wed, 05 May 2021 15:30:57 +0300 libglibutil (1.0.52) unstable; urgency=low * Added gutil_memdup() -- Slava Monich <slava.monich@jolla.com> Sun, 18 Apr 2021 17:40:41 +0300 libglibutil (1.0.51) unstable; urgency=low * Initialize default log settings from the environment * Disable timestamps by default * Added gutil_log_tid option * Added gutil_ptrv_free() -- Slava Monich <slava.monich@jolla.com> Thu, 25 Feb 2021 19:36:05 +0200 libglibutil (1.0.50) unstable; urgency=low * Added gutil_ptrv_length() -- Slava Monich <slava.monich@jolla.com> Wed, 28 Oct 2020 17:59:10 +0200 libglibutil (1.0.49) unstable; urgency=low * Added gutil_slice_free() macro -- Slava Monich <slava.monich@jolla.com> Sat, 17 Oct 2020 01:01:25 +0300 libglibutil (1.0.48) unstable; urgency=low * Make library executable on rpm based systems -- Slava Monich <slava.monich@jolla.com> Mon, 31 Aug 2020 00:07:18 +0300 libglibutil (1.0.47) unstable; urgency=low * Added gutil_strv_addv() -- Slava Monich <slava.monich@jolla.com> Tue, 28 Jul 2020 13:56:08 +0300 libglibutil (1.0.46) unstable; urgency=low * Allow STRIP to be defined by the environment -- Slava Monich <slava.monich@jolla.com> Sat, 30 May 2020 00:02:35 +0300 libglibutil (1.0.45) unstable; urgency=low * Support for multiple archs -- Slava Monich <slava.monich@jolla.com> Fri, 22 May 2020 16:11:42 +0300 libglibutil (1.0.44) unstable; urgency=low * Adapted to side-by-side linking * Allow overriding CC for unit tests -- Slava Monich <slava.monich@jolla.com> Tue, 17 Mar 2020 19:01:45 +0200 libglibutil (1.0.43) unstable; urgency=low * Allow specifying per-module logging function * Added default GLogProc2 compatible callbacks -- Slava Monich <slava.monich@jolla.com> Fri, 20 Dec 2019 19:31:32 +0200 libglibutil (1.0.42) unstable; urgency=low * Zero-initialize timespec::tv_nsec * Optimized gutil_strv_equal() -- Slava Monich <slava.monich@jolla.com> Fri, 22 Nov 2019 00:49:13 +0200 libglibutil (1.0.41) unstable; urgency=low * Added gutil_bytes_equal() and gutil_bytes_equal_data() -- Slava Monich <slava.monich@jolla.com> Sun, 10 Nov 2019 17:14:19 +0300 libglibutil (1.0.40) unstable; urgency=low * Added gutil_strv_bsearch() -- Slava Monich <slava.monich@jolla.com> Mon, 16 Sep 2019 02:22:51 +0300 libglibutil (1.0.39) unstable; urgency=low * Allow use of CC defined by build system -- Slava Monich <slava.monich@jolla.com> Tue, 27 Aug 2019 13:19:56 +0300 libglibutil (1.0.38) unstable; urgency=low * Added gutil_data_has_prefix() and gutil_data_has_suffix() -- Slava Monich <slava.monich@jolla.com> Thu, 01 Aug 2019 00:13:32 +0300 libglibutil (1.0.37) unstable; urgency=low * Added gutil_bytes_concat() and gutil_bytes_xor() -- Slava Monich <slava.monich@jolla.com> Tue, 23 Jul 2019 21:17:18 +0300 libglibutil (1.0.36) unstable; urgency=low * Handle empty log prefix as no prefix at all * Don't nullify default log name in gutil_log_set_type() -- Slava Monich <slava.monich@jolla.com> Thu, 13 Jun 2019 18:15:33 +0300 libglibutil (1.0.35) unstable; urgency=low * Added gutil_strv_last() function -- Slava Monich <slava.monich@jolla.com> Wed, 13 Feb 2019 19:56:31 +0300 libglibutil (1.0.34) unstable; urgency=low * Added a few more GUtilIdlePool functions: gutil_idle_pool_destroy gutil_idle_pool_add_bytes gutil_idle_pool_add_bytes_ref -- Slava Monich <slava.monich@jolla.com> Wed, 07 Nov 2018 17:57:52 +0300 libglibutil (1.0.33) unstable; urgency=low * Added GLOG_FLAG_DISABLE flag -- Slava Monich <slava.monich@jolla.com> Sat, 03 Nov 2018 11:47:25 +0300 libglibutil (1.0.32) unstable; urgency=low * Added gutil_idle_pool_add_strv function -- Slava Monich <slava.monich@jolla.com> Sun, 14 Oct 2018 00:47:01 +0300 libglibutil (1.0.31) unstable; urgency=low * Added GUtilData type and functions to work with it: gutil_data_equal gutil_data_from_string gutil_data_from_bytes -- Slava Monich <slava.monich@jolla.com> Sat, 13 Oct 2018 13:17:45 +0300 libglibutil (1.0.30) unstable; urgency=low * Added gutil_parse_int function -- Slava Monich <slava.monich@jolla.com> Fri, 20 Jul 2018 00:06:40 +0300 libglibutil (1.0.29) unstable; urgency=low * Added gutil_hexdump function * Fixed dependencies for pkgconfig target -- Slava Monich <slava.monich@jolla.com> Tue, 13 Mar 2018 19:28:46 +0300 libglibutil (1.0.28) unstable; urgency=low * Added gutil_idle_pool_get function -- Slava Monich <slava.monich@jolla.com> Sun, 25 Feb 2018 19:58:21 +0200 libglibutil (1.0.27) unstable; urgency=low * GUtilIdlePool is not a GObject anymore * Took out glib-object.h from public headers -- Slava Monich <slava.monich@jolla.com> Sun, 25 Feb 2018 13:20:49 +0200 libglibutil (1.0.26) unstable; urgency=low * Optimized GUtilIdleQueue -- Slava Monich <slava.monich@jolla.com> Sat, 25 Nov 2017 02:16:18 +0200 libglibutil (1.0.25) unstable; urgency=low * Allow NULL module in gutil_log_enabled * Added test_log -- Slava Monich <slava.monich@jolla.com> Thu, 19 Oct 2017 19:51:05 +0300 libglibutil (1.0.24) unstable; urgency=low * Added gutil_strv_strip function -- Slava Monich <slava.monich@jolla.com> Sun, 18 Jun 2017 00:27:35 +0300 libglibutil (1.0.23) unstable; urgency=low * Added a few more GUtilIntArray functions gutil_int_array_new_from_vals gutil_int_array_new_from_value gutil_int_array_find gutil_int_array_contains gutil_int_array_remove gutil_int_array_remove_fast gutil_int_array_remove_all gutil_int_array_remove_all_fast -- Slava Monich <slava.monich@jolla.com> Mon, 05 Jun 2017 19:01:12 +0300 libglibutil (1.0.22) unstable; urgency=low * Added GUtilIdleQueue -- Slava Monich <slava.monich@jolla.com> Sun, 23 Apr 2017 18:07:46 +0300 libglibutil (1.0.21) unstable; urgency=low * Added gutil_hex2bin and gutil_hex2bytes functions -- Slava Monich <slava.monich@jolla.com> Fri, 10 Mar 2017 23:36:04 +0200 libglibutil (1.0.20) unstable; urgency=low * Added GUtilIntHistory -- Slava Monich <slava.monich@jolla.com> Thu, 02 Mar 2017 16:58:02 +0200 libglibutil (1.0.19) unstable; urgency=low * Added GUtilIntArray and GUtilInts -- Slava Monich <slava.monich@jolla.com> Thu, 23 Feb 2017 18:37:01 +0200 libglibutil (1.0.18) unstable; urgency=low * Allow strings longer than 512 bytes in gutil_log_syslog -- Slava Monich <slava.monich@jolla.com> Sat, 18 Feb 2017 20:30:23 +0200 libglibutil (1.0.17) unstable; urgency=low * Made unit tests work with glib < 2.36 -- Slava Monich <slava.monich@jolla.com> Fri, 06 Jan 2017 20:07:29 +0300 libglibutil (1.0.16) unstable; urgency=low * Switched to glib test framework -- Slava Monich <slava.monich@jolla.com> Mon, 05 Dec 2016 18:07:41 +0200 libglibutil (1.0.15) unstable; urgency=low * Added gutil_time_notify API -- Slava Monich <slava.monich@jolla.com> Mon, 28 Nov 2016 19:02:36 +0200 libglibutil (1.0.14) unstable; urgency=low * Another check for NULL in gutil_inotify_watch_new * Removed unnecessary checks from gutil_inotify_ref/undef * Added test_inotify -- Slava Monich <slava.monich@jolla.com> Sat, 24 Sep 2016 17:30:39 +0300 libglibutil (1.0.13) unstable; urgency=low * Added gutil_strv_remove_at * Moved common test code into a reusable module * Added test_misc -- Slava Monich <slava.monich@jolla.com> Fri, 23 Sep 2016 17:58:04 +0300 libglibutil (1.0.12) unstable; urgency=low * Cleaned up debian build * Fixed test_idlepool against glib < 2.36 * Added gutil_ring_max_size and gutil_ring_set_max_size * Fixed gutil_ring_flatten behavior with empty ring buffer -- Slava Monich <slava.monich@jolla.com> Wed, 07 Sep 2016 12:43:14 +0300 libglibutil (1.0.11) unstable; urgency=low * Moved GLOG_MODULE_DECL from gutil_log.h to gutil_types.h -- Slava Monich <slava.monich@jolla.com> Sun, 10 Jul 2016 11:46:30 +0300 libglibutil (1.0.10) unstable; urgency=low * Fixed test_idlepool * Added GLOG_FLAG_HIDE_NAME and gutil_log_func2 -- Slava Monich <slava.monich@jolla.com> Fri, 13 May 2016 17:14:37 +0300 libglibutil (1.0.9) unstable; urgency=low * Added gutil_ring_drop and gutil_ring_drop_last functions -- Slava Monich <slava.monich@jolla.com> Sun, 10 Apr 2016 15:20:40 +0300 libglibutil (1.0.8) unstable; urgency=low * Added gutil_ring API -- Slava Monich <slava.monich@jolla.com> Fri, 08 Apr 2016 19:50:38 +0300 libglibutil (1.0.7) unstable; urgency=low * Added gutil_idle_pool API -- Slava Monich <slava.monich@jolla.com> Tue, 29 Mar 2016 17:29:46 +0300 libglibutil (1.0.6) unstable; urgency=low * Added gutil_strv_sort function * Added gutil_inotify_watch API -- Slava Monich <slava.monich@jolla.com> Sat, 05 Mar 2016 01:13:34 +0200 libglibutil (1.0.5) unstable; urgency=low * Fixed a bug gutil_disconnect_handlers -- Slava Monich <slava.monich@jolla.com> Tue, 23 Feb 2016 15:00:19 +0300 libglibutil (1.0.4) unstable; urgency=low * Added gutil_disconnect_handlers function * Compiled on Windows -- Slava Monich <slava.monich@jolla.com> Sat, 20 Feb 2016 22:58:23 +0300 libglibutil (1.0.3) unstable; urgency=low * Added GStrV type -- Slava Monich <slava.monich@jolla.com> Sat, 09 Jan 2016 12:35:58 +0200 libglibutil (1.0.2) unstable; urgency=low * Makefile cleanup * Removed unnecessary CR from the assert message -- Slava Monich <slava.monich@jolla.com> Thu, 24 Dec 2015 00:33:08 +0200 libglibutil (1.0.1) unstable; urgency=low * Use three-digit version for pkg-config -- Slava Monich <slava.monich@jolla.com> Mon, 16 Nov 2015 14:01:15 +0200 libglibutil (1.0.0) unstable; urgency=low * Initial release -- Slava Monich <slava.monich@jolla.com> Sat, 27 Dec 2014 22:36:32 +0200 07070100000006000081A40000000000000000000000016633A65C00000002000000000000000000000000000000000000002D00000000libglibutil-1714660956.7df665e/debian/compat7 07070100000007000081A40000000000000000000000016633A65C000001F0000000000000000000000000000000000000002E00000000libglibutil-1714660956.7df665e/debian/controlSource: libglibutil Section: libs Priority: optional Maintainer: Slava Monich <slava.monich@jolla.com> Build-Depends: debhelper (>= 8.1.3), libglib2.0-dev (>= 2.32) Standards-Version: 3.8.4 Package: libglibutil Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Library of glib utilities Package: libglibutil-dev Section: libdevel Architecture: any Depends: libglibutil (= ${binary:Version}), ${misc:Depends} Description: Development files for libglibutil 07070100000008000081A40000000000000000000000016633A65C00000610000000000000000000000000000000000000003000000000libglibutil-1714660956.7df665e/debian/copyrightCopyright (C) 2023-2024 Slava Monich <slava@monich.com> Copyright (C) 2014-2022 Jolla Ltd. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the names of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 07070100000009000081A40000000000000000000000016633A65C00000092000000000000000000000000000000000000004100000000libglibutil-1714660956.7df665e/debian/libglibutil-dev.install.indebian/tmp/@LIBDIR@/libglibutil.so @LIBDIR@ debian/tmp/@LIBDIR@/pkgconfig/libglibutil.pc @LIBDIR@/pkgconfig debian/tmp/usr/include/* usr/include/ 0707010000000A000081A40000000000000000000000016633A65C0000002E000000000000000000000000000000000000003D00000000libglibutil-1714660956.7df665e/debian/libglibutil.install.indebian/tmp/@LIBDIR@/libglibutil.so.* @LIBDIR@ 0707010000000B000081ED0000000000000000000000016633A65C00000185000000000000000000000000000000000000002C00000000libglibutil-1714660956.7df665e/debian/rules#!/usr/bin/make -f # -*- makefile -*- # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 LIBDIR=usr/lib/$(shell dpkg-architecture -qDEB_HOST_MULTIARCH) override_dh_auto_build: dh_auto_build -- LIBDIR=$(LIBDIR) release pkgconfig debian/libglibutil.install debian/libglibutil-dev.install override_dh_auto_install: dh_auto_install -- LIBDIR=$(LIBDIR) install-dev %: dh $@ 0707010000000C000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000002D00000000libglibutil-1714660956.7df665e/debian/source0707010000000D000081A40000000000000000000000016633A65C0000000D000000000000000000000000000000000000003400000000libglibutil-1714660956.7df665e/debian/source/format3.0 (native) 0707010000000E000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000002700000000libglibutil-1714660956.7df665e/include0707010000000F000081A40000000000000000000000016633A65C000014D5000000000000000000000000000000000000003800000000libglibutil-1714660956.7df665e/include/gutil_datapack.h/* * Copyright (C) 2023 Slava Monich <slava@monich.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_DATAPACK_H #define GUTIL_DATAPACK_H #include "gutil_types.h" /* * Utilities for packing and unpacking simple data types and structures. * * Since 1.0.69 */ G_BEGIN_DECLS /* * Compact 7 bits per byte representation of a signed integer with * redundant sign bits removed. Most significant bit is the continuation * flag. Bit 0x40 in the first (most significant) byte is the sign bit. * Unused bits in the most significant chunk must be filled with the * sign bit. * * For positive numbers it's slightly less efficient than encoding unsigned * numbers because of one extra sign bit (e.g. unsigned number 65 can be * squeezed into a single byte but the signed one takes 2 bytes). * * Examples: * * 33 (0x0000000000000021) => 00100001 (0x21) * -33 (0xffffffffffffffdf) => 01011111 (0x5f) * 65 (0x0000000000000041) => 10000000 01000001 (0x80 0x41) * -65 (0xffffffffffffff3f) => 11111111 00111111 (0xff 0x3f) * 129 (0x0000000000000081) => 10000001 00000001 (0x81 0x01) * -129 (0xffffffffffffff7f) => 11111110 01111110 (0xfe 0x7f) */ guint gutil_signed_mbn_size( gint64 value); guint gutil_signed_mbn_encode( gpointer buf, gint64 value); guint gutil_signed_mbn_encode2( gpointer buf, gint64 value, guint value_size); gboolean gutil_signed_mbn_decode( GUtilRange* in, gint64* out); gboolean gutil_signed_mbn_decode2( const GUtilData* in, gint64* out); /* * Compact 7 bits per byte representation of an unsigned integer with * redundant zero bits removed. Most significant bit is the continuation * flag. Unused bits in the first byte (most significant chunk) must be * filled with zeros. * * Examples: * * 33 (0x0000000000000021) => 00100001 (0x21) * 65 (0x0000000000000041) => 01000001 (0x41) * 129 (0x0000000000000081) => 10000001 00000001 (0x81 0x01) */ guint gutil_unsigned_mbn_size( guint64 value); guint gutil_unsigned_mbn_encode( gpointer buf, guint64 value); guint gutil_unsigned_mbn_encode2( gpointer buf, guint64 value, guint value_size); gboolean gutil_unsigned_mbn_decode( GUtilRange* in, guint64* out); gboolean gutil_unsigned_mbn_decode2( const GUtilData* in, guint64* out); /* * TLV is a convenient and extendible way to pack various kinds of data * into a single memory block. Each entry gets encoded as follows: * * +--- * | T (unsigned MBN) : tag (non-zero) * +--- * | L (unsigned MBN) : length (zero if there's no data) * +--- * | V (L bytes) : tag specific data (optional) * +--- * * To make API even more convenient, these utilities restrict the tag * value to INT_MAX which should be enough in most real life situations. * Also, these utilities assume that tags are non-zero. gutil_tlv_decode() * returns zero ifno TLV can be pulled out of the input data, and the * tags array passed to gutil_tlvs_decode() is zero terminated. */ typedef enum gutil_tlvs_decode_flags { GUTIL_TLVS_DECODE_NO_FLAGS = 0, GUTIL_TLVS_DECODE_FLAG_SKIP_UNKNOWN_TAGS = 0x1 } GUTIL_TLVS_DECODE_FLAGS; guint gutil_tlv_size( guint tag, gsize len); gsize gutil_tlv_encode( gpointer buf, guint tag, const GUtilData* val); guint gutil_tlv_decode( GUtilRange* in, GUtilData* val); #define GUTIL_TLVS_DECODE_ERROR (-1) #define GUTIL_TLVS_DECODE_DUPLICATE_TAG (-2) #define GUTIL_TLVS_DECODE_UNKNOWN_TAG (-3) int gutil_tlvs_decode( const GUtilData* in, const guint* tags, GUtilData* vals, GUTIL_TLVS_DECODE_FLAGS flags); G_END_DECLS #endif /* GUTIL_DATAPACK_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000010000081A40000000000000000000000016633A65C00000DD8000000000000000000000000000000000000003700000000libglibutil-1714660956.7df665e/include/gutil_history.h/* * Copyright (C) 2017 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jolla Ltd nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_HISTORY_H #define GUTIL_HISTORY_H #include "gutil_types.h" G_BEGIN_DECLS /* * A history of values. Keeps track of no more than last X values submitted * within the last Y microseconds. Microsecond precision may sound like a bit * of an overkill but that's what glib functions like g_get_monotonic_time * return. * * Currently it's only useful for calculating the median but the API could * be extended to provide access to the individual samples, if anyone ever * needs that. * * Also, it's calculating median rather than the average taking into account * that samples are not necessarily added to the history at uniform intervals. * If someone needs the straight average, it's easy enough to add API for that * too. * * When you call gutil_int_history_add but the time hasn't changed since the * last gutil_int_history_add call, the last value is replaced (as opposed to * adding a new entry). */ #define GUTIL_HISTORY_SEC ((gint64)(G_USEC_PER_SEC)) typedef gint64 (*GUtilHistoryTimeFunc)(void); GUtilIntHistory* gutil_int_history_new( int max_size, gint64 max_interval); GUtilIntHistory* gutil_int_history_new_full( int max_size, gint64 max_interval, GUtilHistoryTimeFunc time_fn); GUtilIntHistory* gutil_int_history_ref( GUtilIntHistory* history); void gutil_int_history_unref( GUtilIntHistory* history); guint gutil_int_history_size( GUtilIntHistory* history); gint64 gutil_int_history_interval( GUtilIntHistory* history); void gutil_int_history_clear( GUtilIntHistory* history); int gutil_int_history_add( GUtilIntHistory* history, int value); int gutil_int_history_median( GUtilIntHistory* history, int default_value); G_END_DECLS #endif /* GUTIL_HISTORY_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000011000081A40000000000000000000000016633A65C00001085000000000000000000000000000000000000003800000000libglibutil-1714660956.7df665e/include/gutil_idlepool.h/* * Copyright (C) 2016-2024 Slava Monich <slava@monich.com> * Copyright (C) 2016-2018 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_IDLEPOOL_H #define GUTIL_IDLEPOOL_H #include "gutil_types.h" G_BEGIN_DECLS /* * This is a glib equivalent of NSAutoreleasePool. Its purpose is to * temporarily hold a reference, until the next idle callback or until * the pool is drained manually with gutil_idle_pool_drain(). * * Note that the following functions don't add references, they hold * the references which you have created: * * gutil_idle_pool_add_object() * gutil_idle_pool_add_variant() * gutil_idle_pool_add_ptr_array() * gutil_idle_pool_add_bytes() * * The following functions, however, do add the reference and hold it * until the pool is drained: * * gutil_idle_pool_add_object_ref() * gutil_idle_pool_add_variant_ref() * gutil_idle_pool_add_ptr_array_ref() * gutil_idle_pool_add_bytes_ref() */ GUtilIdlePool* gutil_idle_pool_new( void); GUtilIdlePool* gutil_idle_pool_get( GUtilIdlePool** shared); GUtilIdlePool* gutil_idle_pool_get_default( void); /* Since 1.0.76 */ GUtilIdlePool* gutil_idle_pool_ref( GUtilIdlePool* pool); void gutil_idle_pool_unref( GUtilIdlePool* pool); void gutil_idle_pool_destroy( GUtilIdlePool* pool); /* Since 1.0.34 */ void gutil_idle_pool_drain( GUtilIdlePool* pool); gpointer /* Since 1.0.76 */ gutil_idle_pool_add( GUtilIdlePool* pool, gpointer pointer, GDestroyNotify destroy); char** /* Since 1.0.76 */ gutil_idle_pool_add_strv( GUtilIdlePool* pool, char** strv); /* Since 1.0.32 */ gpointer /* Since 1.0.76 */ gutil_idle_pool_add_object( GUtilIdlePool* pool, gpointer object); GVariant* /* Since 1.0.76 */ gutil_idle_pool_add_variant( GUtilIdlePool* pool, GVariant* variant); GPtrArray* /* Since 1.0.76 */ gutil_idle_pool_add_ptr_array( GUtilIdlePool* pool, GPtrArray* array); GBytes* /* Since 1.0.76 */ gutil_idle_pool_add_bytes( GUtilIdlePool* pool, GBytes* bytes); /* Since 1.0.34 */ gpointer /* Since 1.0.76 */ gutil_idle_pool_add_object_ref( GUtilIdlePool* pool, gpointer object); GVariant* /* Since 1.0.76 */ gutil_idle_pool_add_variant_ref( GUtilIdlePool* pool, GVariant* variant); GPtrArray* /* Since 1.0.76 */ gutil_idle_pool_add_ptr_array_ref( GUtilIdlePool* pool, GPtrArray* array); GBytes* /* Since 1.0.76 */ gutil_idle_pool_add_bytes_ref( GUtilIdlePool* pool, GBytes* bytes); /* Since 1.0.34 */ G_END_DECLS #endif /* GUTIL_IDLEPOOL_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000012000081A40000000000000000000000016633A65C00000C1A000000000000000000000000000000000000003900000000libglibutil-1714660956.7df665e/include/gutil_idlequeue.h/* * Copyright (C) 2017 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jolla Ltd nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_IDLEQUEUE_H #define GUTIL_IDLEQUEUE_H #include "gutil_types.h" G_BEGIN_DECLS /* * GUtilIdleQueue allows to queue idle callbacks, tag them, cancel * individual callbacks or all of them. */ typedef gsize GUtilIdleQueueTag; typedef void (*GUtilIdleFunc)( gpointer data); GUtilIdleQueue* gutil_idle_queue_new(void); void gutil_idle_queue_free( GUtilIdleQueue* queue); GUtilIdleQueue* gutil_idle_queue_ref( GUtilIdleQueue* queue); void gutil_idle_queue_unref( GUtilIdleQueue* queue); void gutil_idle_queue_add( GUtilIdleQueue* queue, GUtilIdleFunc run, gpointer data); void gutil_idle_queue_add_full( GUtilIdleQueue* queue, GUtilIdleFunc run, gpointer data, GFreeFunc free); void gutil_idle_queue_add_tag( GUtilIdleQueue* queue, GUtilIdleQueueTag tag, GUtilIdleFunc run, gpointer data); void gutil_idle_queue_add_tag_full( GUtilIdleQueue* queue, GUtilIdleQueueTag tag, GUtilIdleFunc run, gpointer data, GFreeFunc free); gboolean gutil_idle_queue_contains_tag( GUtilIdleQueue* queue, GUtilIdleQueueTag tag); gboolean gutil_idle_queue_cancel_tag( GUtilIdleQueue* queue, GUtilIdleQueueTag tag); void gutil_idle_queue_cancel_all( GUtilIdleQueue* queue); G_END_DECLS #endif /* GUTIL_IDLEQUEUE_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000013000081A40000000000000000000000016633A65C00000B20000000000000000000000000000000000000003700000000libglibutil-1714660956.7df665e/include/gutil_inotify.h/* * Copyright (C) 2014-2018 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jolla Ltd nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_INOTIFY_H #define GUTIL_INOTIFY_H #include "gutil_types.h" G_BEGIN_DECLS typedef struct gutil_inotify_watch_callback GUtilInotifyWatchCallback; typedef void (*GUtilInotifyWatchFunc)( GUtilInotifyWatch* watch, guint mask, guint cookie, const char* name, void* arg); GUtilInotifyWatch* gutil_inotify_watch_new( const char* path, guint32 mask); GUtilInotifyWatch* gutil_inotify_watch_ref( GUtilInotifyWatch* watch); void gutil_inotify_watch_unref( GUtilInotifyWatch* watch); void gutil_inotify_watch_destroy( GUtilInotifyWatch* watch); gulong gutil_inotify_watch_add_handler( GUtilInotifyWatch* watch, GUtilInotifyWatchFunc fn, void* arg); void gutil_inotify_watch_remove_handler( GUtilInotifyWatch* watch, gulong id); GUtilInotifyWatchCallback* gutil_inotify_watch_callback_new( const char* path, guint32 mask, GUtilInotifyWatchFunc fn, void* arg); void gutil_inotify_watch_callback_free( GUtilInotifyWatchCallback* cb); G_END_DECLS #endif /* GUTIL_INOTIFY_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000014000081A40000000000000000000000016633A65C0000103F000000000000000000000000000000000000003800000000libglibutil-1714660956.7df665e/include/gutil_intarray.h/* * Copyright (C) 2017 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jolla Ltd nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_INTARRAY_H #define GUTIL_INTARRAY_H #include "gutil_types.h" G_BEGIN_DECLS /* * This is basically a GArray providing better type safety at compile time. */ struct gutil_int_array { int* data; guint count; }; GUtilIntArray* gutil_int_array_new( void); GUtilIntArray* gutil_int_array_sized_new( guint reserved_count); GUtilIntArray* gutil_int_array_new_from_vals( const int* vals, guint count); GUtilIntArray* gutil_int_array_new_from_value( int value); int* gutil_int_array_free( GUtilIntArray* array, gboolean free_data); GUtilInts* gutil_int_array_free_to_ints( GUtilIntArray* array); GUtilIntArray* gutil_int_array_ref( GUtilIntArray* array); void gutil_int_array_unref( GUtilIntArray* array); GUtilIntArray* gutil_int_array_append( GUtilIntArray* array, int val); GUtilIntArray* gutil_int_array_append_vals( GUtilIntArray* array, const int* vals, guint count); GUtilIntArray* gutil_int_array_prepend( GUtilIntArray* array, int val); GUtilIntArray* gutil_int_array_prepend_vals( GUtilIntArray* array, const int* vals, guint count); GUtilIntArray* gutil_int_array_insert( GUtilIntArray* array, guint pos, int val); GUtilIntArray* gutil_int_array_insert_vals( GUtilIntArray* array, guint pos, const int* vals, guint count); GUtilIntArray* gutil_int_array_set_count( GUtilIntArray* array, guint count); int gutil_int_array_find( GUtilIntArray* array, int value); gboolean gutil_int_array_contains( GUtilIntArray* array, int value); gboolean gutil_int_array_remove( GUtilIntArray* array, int value); gboolean gutil_int_array_remove_fast( GUtilIntArray* array, int value); guint gutil_int_array_remove_all( GUtilIntArray* array, int value); guint gutil_int_array_remove_all_fast( GUtilIntArray* array, int value); GUtilIntArray* gutil_int_array_remove_index( GUtilIntArray* array, guint pos); GUtilIntArray* gutil_int_array_remove_index_fast( GUtilIntArray* array, guint pos); GUtilIntArray* gutil_int_array_remove_range( GUtilIntArray* array, guint pos, guint count); void gutil_int_array_sort_ascending( GUtilIntArray* array); void gutil_int_array_sort_descending( GUtilIntArray* array); G_END_DECLS #endif /* GUTIL_INTARRAY_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000015000081A40000000000000000000000016633A65C00000BF2000000000000000000000000000000000000003400000000libglibutil-1714660956.7df665e/include/gutil_ints.h/* * Copyright (C) 2017 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jolla Ltd nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_INTS_H #define GUTIL_INTS_H #include "gutil_types.h" G_BEGIN_DECLS /* * A read-only non-empty array of ints. NULL is the empty array. * If it's not NULL then it's not empty. */ GUtilInts* gutil_ints_new( const int* data, guint count); GUtilInts* gutil_ints_new_take( int* data, guint count); GUtilInts* gutil_ints_new_static( const int* data, guint count); GUtilInts* gutil_ints_new_with_free_func( const int* data, guint count, GDestroyNotify free_func, gpointer user_data); GUtilInts* gutil_ints_new_from_ints( GUtilInts* ints, guint offset, guint count); GUtilInts* gutil_ints_ref( GUtilInts* ints); void gutil_ints_unref( GUtilInts* ints); int* gutil_ints_unref_to_data( GUtilInts* ints, guint* count); const int* gutil_ints_get_data( GUtilInts* ints, guint* count); guint gutil_ints_get_count( GUtilInts* ints); int gutil_ints_find( GUtilInts* ints, int value); gboolean gutil_ints_contains( GUtilInts* ints, int value); guint gutil_ints_hash( gconstpointer ints); gboolean gutil_ints_equal( gconstpointer a, gconstpointer b); gint gutil_ints_compare( gconstpointer a, gconstpointer b); G_END_DECLS #endif /* GUTIL_INTS_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000016000081A40000000000000000000000016633A65C00003503000000000000000000000000000000000000003300000000libglibutil-1714660956.7df665e/include/gutil_log.h/* * Copyright (C) 2014-2023 Slava Monich <slava@monich.com> * Copyright (C) 2014-2022 Jolla Ltd. * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_LOG_H #define GUTIL_LOG_H #include "gutil_types.h" #include <stdarg.h> G_BEGIN_DECLS /* Log levels */ #define GLOG_LEVEL_ALWAYS (-2) #define GLOG_LEVEL_INHERIT (-1) #define GLOG_LEVEL_NONE (0) #define GLOG_LEVEL_ERR (1) #define GLOG_LEVEL_WARN (2) #define GLOG_LEVEL_INFO (3) #define GLOG_LEVEL_DEBUG (4) #define GLOG_LEVEL_VERBOSE (5) /* Allow these to be redefined */ #ifndef GLOG_LEVEL_MAX # ifdef DEBUG # define GLOG_LEVEL_MAX GLOG_LEVEL_VERBOSE # else # define GLOG_LEVEL_MAX GLOG_LEVEL_DEBUG # endif #endif /* GLOG_LEVEL_MAX */ #ifndef GLOG_LEVEL_DEFAULT # ifdef DEBUG # define GLOG_LEVEL_DEFAULT GLOG_LEVEL_DEBUG # else # define GLOG_LEVEL_DEFAULT GLOG_LEVEL_INFO # endif #endif /* GLOG_LEVEL_DEFAULT */ /* Do we need a separate log level for ASSERTs? */ #ifndef GLOG_LEVEL_ASSERT # ifdef DEBUG # define GLOG_LEVEL_ASSERT GLOG_LEVEL_ERR # else /* No asserts in release build */ # define GLOG_LEVEL_ASSERT (GLOG_LEVEL_MAX+1) # endif #endif /* Logging function prototypes */ #define GUTIL_DEFINE_LOG_FN(fn) void fn(const char* name, int level, \ const char* format, va_list va) #define GUTIL_DEFINE_LOG_FN2(fn) void fn(const GLogModule* module, \ int level, const char* format, va_list va) typedef GUTIL_DEFINE_LOG_FN((*GLogProc)); typedef GUTIL_DEFINE_LOG_FN2((*GLogProc2)); /* Log module */ struct glog_module { const char* name; /* Name (used as prefix) */ const GLogModule* parent; /* Parent log module (optional) */ GLogProc2 log_proc; /* Per-module logging function (1.0.43) */ const int max_level; /* Maximum level defined at compile time */ int level; /* Current log level */ int flags; /* Flags (see below) */ int reserved2; /* Reserved for future expansion */ }; #define GLOG_FLAG_HIDE_NAME (0x01) /* Don't print the module name */ #define GLOG_FLAG_DISABLE (0x02) /* Don't print this log */ /* Command line parsing helper. Option format is [module]:level * where level can be either a number or log level name ("none", err etc.) */ gboolean gutil_log_parse_option( const char* opt, /* String to parse */ GLogModule** modules, /* Known modules */ int count, /* Number of known modules */ GError** error); /* Optional error message */ /* Set log type by name ("syslog", "stdout" or "glib"). This is also * primarily for parsing command line options */ gboolean gutil_log_set_type( const char* type, const char* default_name); const char* gutil_log_get_type( void); /* Generates the string containg description of log levels and list of * log modules. The caller must deallocate the string with g_free */ char* gutil_log_description( GLogModule** modules, /* Known modules */ int count); /* Number of known modules */ /* Logging function */ void gutil_log( const GLogModule* module, /* Calling module (NULL for default) */ int level, /* Message log level */ const char* format, /* Message format */ ...) G_GNUC_PRINTF(3,4); /* Followed by arguments */ void gutil_logv( const GLogModule* module, int level, const char* format, va_list va); /* Check if logging is enabled for the specified log level */ gboolean gutil_log_enabled( const GLogModule* module, int level); void gutil_log_dump( const GLogModule* module, int level, const char* prefix, const void* data, gsize size); /* Since 1.0.55 */ void gutil_log_dump_bytes( const GLogModule* module, int level, const char* prefix, GBytes* bytes); /* Since 1.0.67 */ void gutil_log_set_timestamp_format( const char* f /* see strftime(3) */ ); /* Since 1.0.73 */ /* Known log types */ extern const char GLOG_TYPE_STDOUT[]; extern const char GLOG_TYPE_STDERR[]; extern const char GLOG_TYPE_GLIB[]; extern const char GLOG_TYPE_CUSTOM[]; extern const char GLOG_TYPE_SYSLOG[]; /* Available log handlers */ GUTIL_DEFINE_LOG_FN(gutil_log_stdout); GUTIL_DEFINE_LOG_FN(gutil_log_stderr); GUTIL_DEFINE_LOG_FN(gutil_log_glib); GUTIL_DEFINE_LOG_FN(gutil_log_syslog); GUTIL_DEFINE_LOG_FN2(gutil_log_stdout2); /* Since 1.0.43 */ GUTIL_DEFINE_LOG_FN2(gutil_log_stderr2); /* Since 1.0.43 */ GUTIL_DEFINE_LOG_FN2(gutil_log_glib2); /* Since 1.0.43 */ GUTIL_DEFINE_LOG_FN2(gutil_log_syslog2); /* Since 1.0.43 */ /* Log configuration */ GLOG_MODULE_DECL(gutil_log_default) extern GLogProc gutil_log_func; extern GLogProc2 gutil_log_func2; extern gboolean gutil_log_timestamp; /* Only affects stdout and stderr */ extern gboolean gutil_log_tid; /* Since 1.0.51 */ /* Log module (optional) */ #define GLOG_MODULE_DEFINE_(var,name) \ GLogModule var = {name, NULL, NULL, \ GLOG_LEVEL_MAX, GLOG_LEVEL_INHERIT, 0, 0} #define GLOG_MODULE_DEFINE2_(var,name,parent) \ GLogModule var = {name, &(parent), NULL, \ GLOG_LEVEL_MAX, GLOG_LEVEL_INHERIT, 0, 0} #ifdef GLOG_MODULE_NAME extern GLogModule GLOG_MODULE_NAME; # define GLOG_MODULE_CURRENT (&GLOG_MODULE_NAME) # define GLOG_MODULE_DEFINE(name) \ GLOG_MODULE_DEFINE_(GLOG_MODULE_NAME,name) # define GLOG_MODULE_DEFINE2(name,parent) \ GLOG_MODULE_DEFINE2_(GLOG_MODULE_NAME,name,parent) #else # define GLOG_MODULE_CURRENT NULL #endif /* Logging macros */ #define GLOG_NOTHING ((void)0) #define GLOG_ENABLED(level) gutil_log_enabled(GLOG_MODULE_CURRENT,level) #define GERRMSG(err) (((err) && (err)->message) ? (err)->message : \ "Unknown error") #if !defined(GLOG_VARARGS) && defined(__GNUC__) # define GLOG_VARARGS #endif #ifndef GLOG_VARARGS # define GLOG_VA_FN(x) _gutil_log_##x # define GLOG_VA_NONE(x) G_INLINE_FUNC \ void GLOG_VA_FN(x)(const char* f, ...) {} # define GLOG_VA(x) GLOG_VA_(GLOG_VA_FN(x),x) # define GLOG_VA_(fn,x) G_INLINE_FUNC \ void fn(const char* f, ...) { \ if (f && f[0]) { \ va_list va; va_start(va,f); \ gutil_logv(GLOG_MODULE_CURRENT, GLOG_LEVEL_##x, f, va); \ va_end(va); \ } \ } #endif /* GLOG_VARARGS */ #define GUTIL_LOG_ANY (GLOG_LEVEL_MAX >= GLOG_LEVEL_NONE) #define GUTIL_LOG_ERR (GLOG_LEVEL_MAX >= GLOG_LEVEL_ERR) #define GUTIL_LOG_WARN (GLOG_LEVEL_MAX >= GLOG_LEVEL_WARN) #define GUTIL_LOG_INFO (GLOG_LEVEL_MAX >= GLOG_LEVEL_INFO) #define GUTIL_LOG_DEBUG (GLOG_LEVEL_MAX >= GLOG_LEVEL_DEBUG) #define GUTIL_LOG_VERBOSE (GLOG_LEVEL_MAX >= GLOG_LEVEL_VERBOSE) #define GUTIL_LOG_ASSERT (GLOG_LEVEL_MAX >= GLOG_LEVEL_ASSERT) #if GUTIL_LOG_ASSERT void gutil_log_assert( const GLogModule* module, /* Calling module (NULL for default) */ int level, /* Assert log level */ const char* expr, /* Assert expression */ const char* file, /* File name */ int line); /* Line number */ # define GASSERT(expr) ((expr) ? GLOG_NOTHING : \ gutil_log_assert(GLOG_MODULE_CURRENT, GLOG_LEVEL_ASSERT, \ #expr, __FILE__, __LINE__)) # define GVERIFY(expr) GASSERT(expr) # define GVERIFY_FALSE(expr) GASSERT(!(expr)) # define GVERIFY_EQ(expr,val) GASSERT((expr) == (val)) # define GVERIFY_NE(expr,val) GASSERT((expr) != (val)) # define GVERIFY_GE(expr,val) GASSERT((expr) >= (val)) # define GVERIFY_GT(expr,val) GASSERT((expr) > (val)) # define GVERIFY_LE(expr,val) GASSERT((expr) <= (val)) # define GVERIFY_LT(expr,val) GASSERT((expr) < (val)) #else # define GASSERT(expr) # define GVERIFY(expr) (expr) # define GVERIFY_FALSE(expr) (expr) # define GVERIFY_EQ(expr,val) (expr) # define GVERIFY_NE(expr,val) (expr) # define GVERIFY_GE(expr,val) (expr) # define GVERIFY_GT(expr,val) (expr) # define GVERIFY_LE(expr,val) (expr) # define GVERIFY_LT(expr,val) (expr) #endif #ifdef GLOG_VARARGS # if GUTIL_LOG_ERR # define GERR(f,args...) gutil_log(GLOG_MODULE_CURRENT, \ GLOG_LEVEL_ERR, f, ##args) # define GERR_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \ GLOG_LEVEL_ERR, "%s() " f, __FUNCTION__, ##args) # else # define GERR(f,args...) GLOG_NOTHING # define GERR_(f,args...) GLOG_NOTHING # endif /* GUTIL_LOG_ERR */ #else # define GERR_ GERR # define GERR GLOG_VA_FN(ERR) # if GUTIL_LOG_ERR GLOG_VA(ERR) # else GLOG_VA_NONE(ERR) # endif /* GUTIL_LOG_ERR */ #endif /* GLOG_VARARGS */ #ifdef GLOG_VARARGS # if GUTIL_LOG_WARN # define GWARN(f,args...) gutil_log(GLOG_MODULE_CURRENT, \ GLOG_LEVEL_WARN, f, ##args) # define GWARN_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \ GLOG_LEVEL_WARN, "%s() " f, __FUNCTION__, ##args) # else # define GWARN(f,args...) GLOG_NOTHING # define GWARN_(f,args...) GLOG_NOTHING # endif /* GUTIL_LOGL_WARN */ #else # define GWARN_ GWARN # define GWARN GLOG_VA_FN(WARN) # if GUTIL_LOG_WARN GLOG_VA(WARN) # else GLOG_VA_NONE(WARN) # endif /* GUTIL_LOGL_WARN */ # endif /* GLOG_VARARGS */ #ifdef GLOG_VARARGS # if GUTIL_LOG_INFO # define GINFO(f,args...) gutil_log(GLOG_MODULE_CURRENT, \ GLOG_LEVEL_INFO, f, ##args) # define GINFO_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \ GLOG_LEVEL_INFO, "%s() " f, __FUNCTION__, ##args) # else # define GINFO(f,args...) GLOG_NOTHING # define GINFO_(f,args...) GLOG_NOTHING # endif /* GUTIL_LOG_INFO */ #else # define GINFO_ GINFO # define GINFO GLOG_VA_FN(INFO) # if GUTIL_LOG_INFO GLOG_VA(INFO) # else GLOG_VA_NONE(INFO) # endif /* GUTIL_LOG_INFO */ #endif /* GLOG_VARARGS */ #ifdef GLOG_VARARGS # if GUTIL_LOG_DEBUG # define GDEBUG(f,args...) gutil_log(GLOG_MODULE_CURRENT, \ GLOG_LEVEL_DEBUG, f, ##args) # define GDEBUG_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \ GLOG_LEVEL_DEBUG, "%s() " f, __FUNCTION__, ##args) # define GDEBUG_DUMP(buf,n) gutil_log_dump(GLOG_MODULE_CURRENT, \ GLOG_LEVEL_DEBUG, NULL, buf, n) /* Since 1.0.55 */ # define GDEBUG_DUMP_BYTES(b) gutil_log_dump_bytes(GLOG_MODULE_CURRENT, \ GLOG_LEVEL_DEBUG, NULL, b) /* Since 1.0.67 */ # else # define GDEBUG(f,args...) GLOG_NOTHING # define GDEBUG_(f,args...) GLOG_NOTHING # define GDEBUG_DUMP(buf,n) GLOG_NOTHING /* Since 1.0.55 */ # define GDEBUG_DUMP_BYTES(b) GLOG_NOTHING /* Since 1.0.67 */ # endif /* GUTIL_LOG_DEBUG */ #else # define GDEBUG_ GDEBUG # define GDEBUG GLOG_VA_FN(debug) # if GUTIL_LOG_DEBUG GLOG_VA_(GDEBUG,DEBUG) # else GLOG_VA_NONE_(GDEBUG,DEBUG) # endif /* GUTIL_LOG_DEBUG */ #endif /* GLOG_VARARGS */ #ifdef GLOG_VARARGS # if GUTIL_LOG_VERBOSE # define GVERBOSE(f,args...) gutil_log(GLOG_MODULE_CURRENT, \ GLOG_LEVEL_VERBOSE, f, ##args) # define GVERBOSE_(f,args...) gutil_log(GLOG_MODULE_CURRENT, \ GLOG_LEVEL_VERBOSE, "%s() " f, __FUNCTION__, ##args) # else # define GVERBOSE(f,args...) GLOG_NOTHING # define GVERBOSE_(f,args...) GLOG_NOTHING # endif /* GUTIL_LOG_VERBOSE */ #else # define GVERBOSE_ GVERBOSE # define GVERBOSE GLOG_VA_FN(VERBOSE) # if GUTIL_LOG_VERBOSE GLOG_VA(VERBOSE) # else GLOG_VA_NONE(VERBOSE) # endif /* GUTIL_LOG_VERBOSE */ #endif /* GLOG_VARARGS */ G_END_DECLS #endif /* GUTIL_LOG_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000017000081A40000000000000000000000016633A65C0000090A000000000000000000000000000000000000003600000000libglibutil-1714660956.7df665e/include/gutil_macros.h/* * Copyright (C) 2014-2020 Jolla Ltd. * Copyright (C) 2014-2020 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_MACROS_H #define GUTIL_MACROS_H #include <gutil_types.h> #define G_CAST(address,type,field) \ ((type *)((guint8*)(address) - G_STRUCT_OFFSET(type,field))) #define G_ALIGN2(value) (((value)+1) & ~1) #define G_ALIGN4(value) (((value)+3) & ~3) #define G_ALIGN8(value) (((value)+7) & ~7) #ifdef __GNUC__ # define G_PACKED __attribute__((packed)) #else # define G_PACKED #endif #define gutil_slice_free(x) g_slice_free1(sizeof(*(x)), x) /* Since 1.0.49 */ #endif /* GUTIL_MACROS_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000018000081A40000000000000000000000016633A65C00001530000000000000000000000000000000000000003400000000libglibutil-1714660956.7df665e/include/gutil_misc.h/* * Copyright (C) 2023-2024 Slava Monich <slava@monich.com> * Copyright (C) 2016-2022 Jolla Ltd. * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_MISC_H #define GUTIL_MISC_H #include "gutil_types.h" G_BEGIN_DECLS void gutil_disconnect_handlers( gpointer instance, gulong* ids, int count); void* gutil_object_ref( void* object); /* Since 1.0.71 */ void gutil_object_unref( void* object); /* Since 1.0.71 */ gboolean gutil_source_remove( guint id); /* Since 1.0.78 */ gboolean gutil_source_clear( guint* id); /* Since 1.0.78 */ void* gutil_hex2bin( const char* str, gssize len, void* data); char* gutil_bin2hex( const void* data, gsize len, gboolean upper_case) /* Since 1.0.71 */ G_GNUC_WARN_UNUSED_RESULT; char* gutil_data2hex( const GUtilData* data, gboolean upper_case) /* Since 1.0.71 */ G_GNUC_WARN_UNUSED_RESULT; GBytes* gutil_hex2bytes( const char* str, gssize len); #define GUTIL_HEXDUMP_BUFSIZE (70) #define GUTIL_HEXDUMP_MAXBYTES (16) guint gutil_hexdump( char* buf, const void* data, guint size); /* Since 1.0.29 */ gboolean gutil_parse_int( const char* str, int base, int* value); /* Since 1.0.30 */ gboolean gutil_parse_uint( const char* str, int base, unsigned int* value); /* Since 1.0.53 */ gboolean gutil_parse_int64( const char* str, int base, gint64* value); /* Since 1.0.56 */ gboolean gutil_parse_uint64( const char* str, int base, guint64* value); /* Since 1.0.56 */ gboolean gutil_data_equal( const GUtilData* data1, const GUtilData* data2); /* Since 1.0.31 */ gboolean gutil_data_has_prefix( const GUtilData* data, const GUtilData* prefix); /* Since 1.0.38 */ gboolean gutil_data_has_suffix( const GUtilData* data, const GUtilData* suffix); /* Since 1.0.38 */ const GUtilData* gutil_data_from_string( GUtilData* data, const char* str); /* Since 1.0.31 */ const GUtilData* gutil_data_from_bytes( GUtilData* data, GBytes* bytes); /* Since 1.0.31 */ GUtilData* gutil_data_new( const void* bytes, guint len) /* Since 1.0.72 */ G_GNUC_WARN_UNUSED_RESULT; GUtilData* gutil_data_copy( const GUtilData* data) /* Since 1.0.72 */ G_GNUC_WARN_UNUSED_RESULT; GVariant* gutil_data_copy_as_variant( const GUtilData* data) /* Since 1.0.74 */ G_GNUC_WARN_UNUSED_RESULT; GBytes* gutil_bytes_concat( GBytes* bytes, ...) /* Since 1.0.37 */ G_GNUC_WARN_UNUSED_RESULT G_GNUC_NULL_TERMINATED; GBytes* gutil_bytes_xor( GBytes* bytes1, GBytes* bytes2); /* Since 1.0.37 */ gboolean gutil_bytes_equal( GBytes* bytes, const void* data, gsize size); /* Since 1.0.41 */ gboolean gutil_bytes_equal_data( GBytes* bytes, const GUtilData* data); /* Since 1.0.41 */ gboolean gutil_bytes_has_prefix( GBytes* bytes, const void* data, gsize size); /* Since 1.0.63 */ gboolean gutil_bytes_has_suffix( GBytes* bytes, const void* data, gsize size); /* Since 1.0.63 */ gsize gutil_ptrv_length( const void* ptrv); /* Since 1.0.50 */ gboolean gutil_ptrv_is_empty( const void* ptrv); /* Since 1.0.71 */ void gutil_ptrv_free( void** ptrv); /* Since 1.0.51 */ void* gutil_memdup( const void* ptr, gsize size); /* Since 1.0.52 */ gsize gutil_strlen0( const char* str); /* Since 1.0.62 */ gsize gutil_range_init_with_bytes( GUtilRange* range, GBytes* bytes); /* Since 1.0.55 */ gboolean gutil_range_has_prefix( const GUtilRange* range, const GUtilData* prefix); /* Since 1.0.55 */ gboolean gutil_range_skip_prefix( GUtilRange* range, const GUtilData* prefix); /* Since 1.0.55 */ G_END_DECLS #endif /* GUTIL_MISC_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000019000081A40000000000000000000000016633A65C00000CF0000000000000000000000000000000000000003400000000libglibutil-1714660956.7df665e/include/gutil_objv.h/* * Copyright (C) 2023 Slava Monich <slava@monich.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_OBJV_H #define GUTIL_OBJV_H #include "gutil_types.h" #include <glib-object.h> /* * Operations on NULL-terminated array of references to GObjects. * * Since 1.0.70 */ G_BEGIN_DECLS GObject** gutil_objv_new( GObject* obj, ...) /* Since 1.0.72 */ G_GNUC_WARN_UNUSED_RESULT G_GNUC_NULL_TERMINATED; void gutil_objv_free( GObject** objv); GObject** gutil_objv_copy( GObject* const* objv) G_GNUC_WARN_UNUSED_RESULT; GObject** gutil_objv_add( GObject** objv, GObject* obj) G_GNUC_WARN_UNUSED_RESULT; GObject** gutil_objv_insert( GObject** objv, GObject* obj, gsize pos) /* Since 1.0.71 */ G_GNUC_WARN_UNUSED_RESULT; GObject** gutil_objv_append( GObject** objv, GObject* const* objs) /* Since 1.0.71 */ G_GNUC_WARN_UNUSED_RESULT; GObject** gutil_objv_remove( GObject** objv, GObject* obj, gboolean all) G_GNUC_WARN_UNUSED_RESULT; GObject** gutil_objv_remove_at( GObject** objv, gsize pos) G_GNUC_WARN_UNUSED_RESULT; GObject* gutil_objv_at( GObject* const* objv, gsize pos); gboolean gutil_objv_equal( GObject* const* objv1, GObject* const* objv2); GObject* gutil_objv_first( GObject* const* objv); GObject* gutil_objv_last( GObject* const* objv); gssize gutil_objv_find( GObject* const* objv, GObject* obj); gssize gutil_objv_find_last( GObject* const* objv, GObject* obj); gboolean gutil_objv_contains( GObject* const* objv, GObject* obj); G_END_DECLS #endif /* GUTIL_OBJV_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000001A000081A40000000000000000000000016633A65C00000DF7000000000000000000000000000000000000003400000000libglibutil-1714660956.7df665e/include/gutil_ring.h/* * Copyright (C) 2016-2017 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jolla Ltd nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_RING_H #define GUTIL_RING_H #include "gutil_types.h" G_BEGIN_DECLS /* * GLib-style "first in, first out" ring buffer. * * Note that `get' functions don't invoke the free function on the * elements they remove from the ring buffer. The ring buffer only * frees the elements it removes internally in gutil_ring_clear, * gutil_ring_drop functions and the last gutil_ring_unref. */ #define GUTIL_RING_UNLIMITED_SIZE (-1) GUtilRing* gutil_ring_new(void); GUtilRing* gutil_ring_sized_new( gint reserved_size, gint max_size); GUtilRing* gutil_ring_new_full( gint reserved_size, gint max_size, GDestroyNotify free_func); GUtilRing* gutil_ring_ref( GUtilRing* ring); void gutil_ring_unref( GUtilRing* ring); void gutil_ring_set_free_func( GUtilRing* ring, GDestroyNotify free_func); gint gutil_ring_max_size( GUtilRing* ring); void gutil_ring_set_max_size( GUtilRing* ring, gint max_size); gint gutil_ring_size( GUtilRing* ring); void gutil_ring_clear( GUtilRing* ring); void gutil_ring_compact( GUtilRing* ring); gboolean gutil_ring_reserve( GUtilRing* ring, gint reserved_size); gboolean gutil_ring_can_put( GUtilRing* ring, gint num_elements); gboolean gutil_ring_put( GUtilRing* ring, gpointer data); gboolean gutil_ring_put_front( GUtilRing* ring, gpointer data); gpointer gutil_ring_get( GUtilRing* ring); gpointer gutil_ring_get_last( GUtilRing* ring); gint gutil_ring_drop( GUtilRing* ring, gint count); gint gutil_ring_drop_last( GUtilRing* ring, gint count); gpointer gutil_ring_data_at( GUtilRing* ring, gint pos); gpointer* gutil_ring_flatten( GUtilRing* ring, gint* size); G_END_DECLS #endif /* GUTIL_RING_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000001B000081A40000000000000000000000016633A65C000011F7000000000000000000000000000000000000003400000000libglibutil-1714660956.7df665e/include/gutil_strv.h/* * Copyright (C) 2014-2022 Jolla Ltd. * Copyright (C) 2014-2022 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_STRV_H #define GUTIL_STRV_H #include "gutil_types.h" G_BEGIN_DECLS /** * NULL-tolerant version of g_strv_length */ guint gutil_strv_length( const GStrV* sv); /** * Returns i-th strings in the array, NULL if index is out of bounds. */ const char* gutil_strv_at( const GStrV* sv, guint i); /** * Returns the last string in the array, NULL if there's nothing there. */ const char* gutil_strv_last( const GStrV* sv); /* Since 1.0.35 */ /** * Returns index of the specified string in the string array, * or -1 if the string is not found. */ int gutil_strv_find( const GStrV* sv, const char* s); /** * Returns index of the last occurrence of specified string in the string * array, or -1 if the string is not found. */ int gutil_strv_find_last( const GStrV* sv, const char* s); /* Since 1.0.62 */ /** * Checks if string array contains the specified string. */ gboolean gutil_strv_contains( const GStrV* sv, const char* s); /** * Appends new string to the array. */ GStrV* gutil_strv_add( GStrV* sv, const char* s) G_GNUC_WARN_UNUSED_RESULT; /** * Appends new string(s) to the array. */ GStrV* gutil_strv_addv( GStrV* sv, const char* s, ...) /* Since 1.0.47 */ G_GNUC_WARN_UNUSED_RESULT G_GNUC_NULL_TERMINATED; /** * Removes the string from the specified position in the array. */ GStrV* gutil_strv_remove_at( GStrV* sv, int pos, gboolean free_string) G_GNUC_WARN_UNUSED_RESULT; /** * Removes one or all matching strings from the array and frees them. */ GStrV* gutil_strv_remove( GStrV* sv, const char* s, gboolean remove_all) /* Since 1.0.61 */ G_GNUC_WARN_UNUSED_RESULT; #define gutil_strv_remove_one(sv, s) gutil_strv_remove(sv, s, FALSE) #define gutil_strv_remove_all(sv, s) gutil_strv_remove(sv, s, TRUE) /** * Checks two string arrays for equality. */ gboolean gutil_strv_equal( const GStrV* sv1, const GStrV* sv2); /** * Removes all duplicates from the string array. */ GStrV* gutil_strv_remove_dups( GStrV* sv); /* Since 1.0.62 */ /** * Sorts the string array */ GStrV* gutil_strv_sort( GStrV* sv, gboolean ascending); /** * Binary search in the sorted string array. Returns index of the * specified string in the string array, or -1 if the string is not * found. It's basically a version of gutil_strv_find optimized for * sorted arrays. The string array must be sorted by gutil_strv_sort * with the same 'ascending' argument. */ int gutil_strv_bsearch( GStrV* sv, const char* s, gboolean ascending); /* Since 1.0.40 */ /** * Removes leading and trailing whitespaces from all strings in the vector. */ GStrV* gutil_strv_strip( GStrV* sv); G_END_DECLS #endif /* GUTIL_STRV_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000001C000081A40000000000000000000000016633A65C00000951000000000000000000000000000000000000003A00000000libglibutil-1714660956.7df665e/include/gutil_timenotify.h/* * Copyright (C) 2016-2018 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jolla Ltd nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_TIMENOTIFY_H #define GUTIL_TIMENOTIFY_H #include "gutil_types.h" G_BEGIN_DECLS typedef void (*GUtilTimeNotifyFunc)( GUtilTimeNotify* notify, void* arg); GUtilTimeNotify* gutil_time_notify_new( void); GUtilTimeNotify* gutil_time_notify_ref( GUtilTimeNotify* notify); void gutil_time_notify_unref( GUtilTimeNotify* notify); gulong gutil_time_notify_add_handler( GUtilTimeNotify* notify, GUtilTimeNotifyFunc fn, void* arg); void gutil_time_notify_remove_handler( GUtilTimeNotify* notify, gulong id); G_END_DECLS #endif /* GUTIL_TIMENOTIFY_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000001D000081A40000000000000000000000016633A65C00000A80000000000000000000000000000000000000003500000000libglibutil-1714660956.7df665e/include/gutil_types.h/* * Copyright (C) 2014-2021 Jolla Ltd. * Copyright (C) 2023 Slava Monich <slava@monich.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_TYPES_H #define GUTIL_TYPES_H #include <glib.h> #include <string.h> #include <stdio.h> G_BEGIN_DECLS typedef char* GStrV; typedef struct gutil_idle_pool GUtilIdlePool; typedef struct gutil_idle_queue GUtilIdleQueue; typedef struct gutil_ints GUtilInts; typedef struct gutil_int_array GUtilIntArray; typedef struct gutil_int_history GUtilIntHistory; typedef struct gutil_inotify_watch GUtilInotifyWatch; typedef struct gutil_ring GUtilRing; typedef struct gutil_time_notify GUtilTimeNotify; typedef struct gutil_weakref GUtilWeakRef; /* Since 1.0.68 */ typedef struct gutil_data { const guint8* bytes; gsize size; } GUtilData; typedef struct gutil_range { const guint8* ptr; const guint8* end; } GUtilRange; /* Since 1.0.54 */ #define GLOG_MODULE_DECL(m) extern GLogModule m; typedef struct glog_module GLogModule; G_END_DECLS #endif /* GUTIL_TYPES_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000001E000081A40000000000000000000000016633A65C00000E50000000000000000000000000000000000000003700000000libglibutil-1714660956.7df665e/include/gutil_version.h/* * Copyright (C) 2023-2024 Slava Monich <slava@monich.com> * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_VERSION_H #define GUTIL_VERSION_H #include "gutil_types.h" /* * GUTIL_VERSION_X_Y_Z macros will be added with each release. The fact that * such macro is defined means that you're compiling against libgutil version * X.Y.Z or greater. * * Since 1.0.69 */ G_BEGIN_DECLS #define GUTIL_VERSION_MAJOR 1 #define GUTIL_VERSION_MINOR 0 #define GUTIL_VERSION_MICRO 79 #define GUTIL_VERSION_STRING "1.0.79" extern const guint gutil_version_major; /* GUTIL_VERSION_MAJOR */ extern const guint gutil_version_minor; /* GUTIL_VERSION_MINOR */ extern const guint gutil_version_micro; /* GUTIL_VERSION_MICRO */ /* Version as a single word */ #define GUTIL_VERSION_(v1,v2,v3) \ ((((v1) & 0x7f) << 24) | \ (((v2) & 0xfff) << 12) | \ ((v3) & 0xfff)) #define GUTIL_VERSION_MAJOR_(v) (((v) >> 24) & 0x7f) #define GUTIL_VERSION_MINOR_(v) (((v) >> 12) & 0xfff) #define GUTIL_VERSION_MICRO_(v) (((v) & 0xfff)) /* Current compile time version as a single word */ #define GUTIL_VERSION GUTIL_VERSION_ \ (GUTIL_VERSION_MAJOR, GUTIL_VERSION_MINOR, GUTIL_VERSION_MICRO) /* Runtime version as a single word */ #define gutil_version() GUTIL_VERSION_ \ (gutil_version_major, gutil_version_minor, gutil_version_micro) /* Specific versions */ #define GUTIL_VERSION_1_0_69 GUTIL_VERSION_(1,0,69) #define GUTIL_VERSION_1_0_70 GUTIL_VERSION_(1,0,70) #define GUTIL_VERSION_1_0_71 GUTIL_VERSION_(1,0,71) #define GUTIL_VERSION_1_0_72 GUTIL_VERSION_(1,0,72) #define GUTIL_VERSION_1_0_73 GUTIL_VERSION_(1,0,73) #define GUTIL_VERSION_1_0_74 GUTIL_VERSION_(1,0,74) #define GUTIL_VERSION_1_0_75 GUTIL_VERSION_(1,0,75)) #define GUTIL_VERSION_1_0_76 GUTIL_VERSION_(1,0,76)) #define GUTIL_VERSION_1_0_77 GUTIL_VERSION_(1,0,77)) #define GUTIL_VERSION_1_0_78 GUTIL_VERSION_(1,0,78)) #define GUTIL_VERSION_1_0_79 GUTIL_VERSION_(1,0,79)) G_END_DECLS #endif /* GUTIL_VERSION_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000001F000081A40000000000000000000000016633A65C00000A91000000000000000000000000000000000000003700000000libglibutil-1714660956.7df665e/include/gutil_weakref.h/* * Copyright (C) 2023 Slava Monich <slava@monich.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GUTIL_WEAKREF_H #define GUTIL_WEAKREF_H #include "gutil_types.h" /* * Ref-countable weak reference can be used to avoid calling g_weak_ref_set() * too often because it grabs global weak_locations_lock for exclusive access. * Note that g_weak_ref_set() is also invoked internally by g_weak_ref_init() * and g_weak_ref_clear(). * * g_weak_ref_get() on the other hand only acquires weak_locations_lock * for read-only access which is less of a bottleneck in a multi-threaded * environment. And it's generally significantly simpler and faster than * g_weak_ref_set(). * * Since 1.0.68 */ G_BEGIN_DECLS GUtilWeakRef* gutil_weakref_new( gpointer obj); GUtilWeakRef* gutil_weakref_ref( GUtilWeakRef* ref); void gutil_weakref_unref( GUtilWeakRef* ref); gpointer gutil_weakref_get( GUtilWeakRef* ref); void gutil_weakref_set( GUtilWeakRef* ref, gpointer obj); G_END_DECLS #endif /* GUTIL_WEAKREF_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000020000081A40000000000000000000000016633A65C000000E8000000000000000000000000000000000000003100000000libglibutil-1714660956.7df665e/libglibutil.pc.inname=glibutil libdir=@libdir@ includedir=/usr/include Name: libglibutil Description: Library of glib utilities Version: @version@ Requires.private: glib-2.0 Libs: -L${libdir} -l${name} Cflags: -I${includedir} -I${includedir}/gutil 07070100000021000081A40000000000000000000000016633A65C000017AC000000000000000000000000000000000000002F00000000libglibutil-1714660956.7df665e/libglibutil.ver{ global: GLOG_TYPE_CUSTOM; GLOG_TYPE_GLIB; GLOG_TYPE_STDERR; GLOG_TYPE_STDOUT; GLOG_TYPE_SYSLOG; gutil_bin2hex; gutil_bytes_concat; gutil_bytes_equal; gutil_bytes_equal_data; gutil_bytes_has_prefix; gutil_bytes_has_suffix; gutil_bytes_xor; gutil_data2hex; gutil_data_copy; gutil_data_copy_as_variant; gutil_data_equal; gutil_data_from_bytes; gutil_data_from_string; gutil_data_has_prefix; gutil_data_has_suffix; gutil_data_new; gutil_disconnect_handlers; gutil_hex2bin; gutil_hex2bytes; gutil_hexdump; gutil_idle_pool_add; gutil_idle_pool_add_bytes; gutil_idle_pool_add_bytes_ref; gutil_idle_pool_add_object; gutil_idle_pool_add_object_ref; gutil_idle_pool_add_ptr_array; gutil_idle_pool_add_ptr_array_ref; gutil_idle_pool_add_strv; gutil_idle_pool_add_variant; gutil_idle_pool_add_variant_ref; gutil_idle_pool_destroy; gutil_idle_pool_drain; gutil_idle_pool_get; gutil_idle_pool_get_default; gutil_idle_pool_new; gutil_idle_pool_ref; gutil_idle_pool_unref; gutil_idle_queue_add; gutil_idle_queue_add_full; gutil_idle_queue_add_tag; gutil_idle_queue_add_tag_full; gutil_idle_queue_cancel_all; gutil_idle_queue_cancel_tag; gutil_idle_queue_contains_tag; gutil_idle_queue_free; gutil_idle_queue_new; gutil_idle_queue_ref; gutil_idle_queue_unref; gutil_inotify_watch_add_handler; gutil_inotify_watch_callback_free; gutil_inotify_watch_callback_new; gutil_inotify_watch_destroy; gutil_inotify_watch_new; gutil_inotify_watch_ref; gutil_inotify_watch_remove_handler; gutil_inotify_watch_unref; gutil_int_array_append; gutil_int_array_append_vals; gutil_int_array_contains; gutil_int_array_find; gutil_int_array_free; gutil_int_array_free_to_ints; gutil_int_array_insert; gutil_int_array_insert_vals; gutil_int_array_new; gutil_int_array_new_from_vals; gutil_int_array_new_from_value; gutil_int_array_prepend; gutil_int_array_prepend_vals; gutil_int_array_ref; gutil_int_array_remove; gutil_int_array_remove_all; gutil_int_array_remove_all_fast; gutil_int_array_remove_fast; gutil_int_array_remove_index; gutil_int_array_remove_index_fast; gutil_int_array_remove_range; gutil_int_array_set_count; gutil_int_array_sized_new; gutil_int_array_sort_ascending; gutil_int_array_sort_descending; gutil_int_array_unref; gutil_int_history_add; gutil_int_history_clear; gutil_int_history_interval; gutil_int_history_median; gutil_int_history_new; gutil_int_history_new_full; gutil_int_history_ref; gutil_int_history_size; gutil_int_history_unref; gutil_ints_compare; gutil_ints_contains; gutil_ints_equal; gutil_ints_find; gutil_ints_get_count; gutil_ints_get_data; gutil_ints_hash; gutil_ints_new; gutil_ints_new_from_ints; gutil_ints_new_static; gutil_ints_new_take; gutil_ints_new_with_free_func; gutil_ints_ref; gutil_ints_unref; gutil_ints_unref_to_data; gutil_log; gutil_log_assert; gutil_log_default; gutil_log_description; gutil_log_dump; gutil_log_dump_bytes; gutil_log_enabled; gutil_log_func; gutil_log_func2; gutil_log_get_type; gutil_log_glib; gutil_log_glib2; gutil_log_parse_option; gutil_log_set_timestamp_format; gutil_log_set_type; gutil_log_stderr; gutil_log_stderr2; gutil_log_stdio; gutil_log_stdout; gutil_log_stdout2; gutil_log_syslog; gutil_log_syslog2; gutil_log_tid; gutil_log_timestamp; gutil_logv; gutil_memdup; gutil_object_ref; gutil_object_unref; gutil_objv_add; gutil_objv_append; gutil_objv_at; gutil_objv_contains; gutil_objv_copy; gutil_objv_equal; gutil_objv_find; gutil_objv_find_last; gutil_objv_first; gutil_objv_free; gutil_objv_insert; gutil_objv_last; gutil_objv_new; gutil_objv_remove; gutil_objv_remove_at; gutil_parse_int; gutil_parse_int64; gutil_parse_uint; gutil_parse_uint64; gutil_ptrv_free; gutil_ptrv_is_empty; gutil_ptrv_length; gutil_range_has_prefix; gutil_range_init_with_bytes; gutil_range_skip_prefix; gutil_ring_can_put; gutil_ring_clear; gutil_ring_compact; gutil_ring_data_at; gutil_ring_drop; gutil_ring_drop_last; gutil_ring_flatten; gutil_ring_get; gutil_ring_get_last; gutil_ring_max_size; gutil_ring_new; gutil_ring_new_full; gutil_ring_put; gutil_ring_put_front; gutil_ring_ref; gutil_ring_reserve; gutil_ring_set_free_func; gutil_ring_set_max_size; gutil_ring_size; gutil_ring_sized_new; gutil_ring_unref; gutil_signed_mbn_decode; gutil_signed_mbn_decode2; gutil_signed_mbn_encode; gutil_signed_mbn_encode2; gutil_signed_mbn_size; gutil_source_clear; gutil_source_remove; gutil_strlen0; gutil_strv_add; gutil_strv_addv; gutil_strv_at; gutil_strv_bsearch; gutil_strv_contains; gutil_strv_equal; gutil_strv_find; gutil_strv_find_last; gutil_strv_last; gutil_strv_length; gutil_strv_remove; gutil_strv_remove_at; gutil_strv_remove_dups; gutil_strv_sort; gutil_strv_strip; gutil_time_notify_add_handler; gutil_time_notify_new; gutil_time_notify_ref; gutil_time_notify_remove_handler; gutil_time_notify_unref; gutil_tlv_decode; gutil_tlv_encode; gutil_tlvs_decode; gutil_tlv_size; gutil_unsigned_mbn_decode; gutil_unsigned_mbn_decode2; gutil_unsigned_mbn_encode; gutil_unsigned_mbn_encode2; gutil_unsigned_mbn_size; gutil_version_major; gutil_version_micro; gutil_version_minor; gutil_weakref_get; gutil_weakref_new; gutil_weakref_ref; gutil_weakref_set; gutil_weakref_unref; local: *; }; 07070100000022000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000002300000000libglibutil-1714660956.7df665e/rpm07070100000023000081A40000000000000000000000016633A65C00000558000000000000000000000000000000000000003400000000libglibutil-1714660956.7df665e/rpm/libglibutil.specName: libglibutil Version: 1.0.79 Release: 0 Summary: Library of glib utilities License: BSD URL: https://github.com/sailfishos/libglibutil Source: %{name}-%{version}.tar.bz2 %define glib_version 2.32 BuildRequires: pkgconfig BuildRequires: pkgconfig(glib-2.0) >= %{glib_version} # license macro requires rpm >= 4.11 BuildRequires: pkgconfig(rpm) %define license_support %(pkg-config --exists 'rpm >= 4.11'; echo $?) # make_build macro appeared in rpm 4.12 %{!?make_build: %define make_build make %{_smp_mflags}} Requires: glib2 >= %{glib_version} Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig %description Provides glib utility functions and macros %package devel Summary: Development library for %{name} Requires: %{name} = %{version} Requires: pkgconfig(glib-2.0) >= %{glib_version} %description devel This package contains the development library for %{name}. %prep %setup -q %build %make_build LIBDIR=%{_libdir} KEEP_SYMBOLS=1 release pkgconfig %install make LIBDIR=%{_libdir} DESTDIR=%{buildroot} install-dev %check make -C test test %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %defattr(-,root,root,-) %{_libdir}/%{name}.so.* %if %{license_support} == 0 %license LICENSE %endif %files devel %defattr(-,root,root,-) %dir %{_includedir}/gutil %{_libdir}/pkgconfig/*.pc %{_libdir}/%{name}.so %{_includedir}/gutil/*.h 07070100000024000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000002300000000libglibutil-1714660956.7df665e/src07070100000025000081A40000000000000000000000016633A65C000033E5000000000000000000000000000000000000003400000000libglibutil-1714660956.7df665e/src/gutil_datapack.c/* * Copyright (C) 2023-2024 Slava Monich <slava@monich.com> * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_datapack.h" #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif /* * Compact 7 bits per byte representation of a signed integer with * redundant sign bits removed. Most significant bit is the continuation * flag. Bit 0x40 in the first (most significant) byte is the sign bit. * Unused bits in the most significant chunk must be filled with the * sign bit. * * For positive numbers it's slightly less efficient than encoding unsigned * numbers because of one extra sign bit (e.g. unsigned number 65 can be * squeezed into a single byte but the signed one takes 2 bytes). * * Examples: * * 33 (0x0000000000000021) => 00100001 (0x21) * -33 (0xffffffffffffffdf) => 01011111 (0x5f) * 65 (0x0000000000000041) => 10000000 01000001 (0x80 0x41) * -65 (0xffffffffffffff3f) => 11111111 00111111 (0xff 0x3f) * 129 (0x0000000000000081) => 10000001 00000001 (0x81 0x01) * -129 (0xffffffffffffff7f) => 11111110 01111110 (0xfe 0x7f) */ guint gutil_signed_mbn_size( gint64 value) { guint n = 1, msc = (value & 0x7f); /* Most Significant Chunk */ value >>= 7; if (value < 0) { while (value != -1) { msc = (value & 0x7f); value >>= 7; n++; } if (!(msc & 0x40)) { n++; /* Sign bit didn't fit */ } } else { while (value) { msc = (value & 0x7f); value >>= 7; n++; } if (msc & 0x40) { n++; /* Sign bit didn't fit */ } } return n; } guint gutil_signed_mbn_encode( gpointer buf, gint64 value) { return gutil_signed_mbn_encode2(buf, value, gutil_signed_mbn_size(value)); } guint gutil_signed_mbn_encode2( gpointer buf, gint64 value, guint size) { guchar* ptr = buf; /* Zero or too large size must be a programming error. */ if (size > 0) { guint n = size; ptr[--n] = (guchar)(value & 0x7f); value >>= 7; while (n) { ptr[--n] = (guchar)(value | 0x80); value >>= 7; } if (value < 0) { const guint maxbits = sizeof(value) * 8; /* Special treatment of negative numbers */ if (size * 7 > maxbits) { /* Extend the sign bit */ ptr[0] |= ~((1 << (maxbits - (size - 1) * 7)) - 1); } } } return size; } gboolean gutil_signed_mbn_decode( GUtilRange* in, gint64* out) { if (in->ptr < in->end) { guchar last = in->ptr[0]; if (last & 0x80) { const int maxbits = sizeof(*out) * 8; const guchar msc = last; /* Most Significant Chunk */ int nbits = 7; guint off = 1; guint64 value = (last & 0x7f); while ((in->ptr + off) < in->end && ((last = in->ptr[off++]) & 0x80)) { value = (value << 7) | (last & 0x7f); if ((nbits + 7) <= maxbits) { nbits += 7; } else { /* Too many bytes */ return FALSE; } } if (!(last & 0x80)) { value = (value << 7) | last; if (msc & 0x40) { /* Negative number */ if ((nbits + 7) < maxbits) { /* Extend the sign bit */ if (out) { *out = value | ~((G_GINT64_CONSTANT(1) << (nbits + 7)) - 1); } in->ptr += off; return TRUE; } else { /* Unused bits must be set to 1 */ if ((msc | ((1 << (maxbits - nbits)) - 1)) == 0xff) { if (out) { *out = value; } in->ptr += off; return TRUE; } } } else { /* Positive number, unused bits (if any) must be zeroed */ /* Unused bits must be zeroed */ if ((nbits + 7) < maxbits || (msc & ~((1 << (maxbits - nbits)) - 1)) == 0x80) { if (out) { *out = value; } in->ptr += off; return TRUE; } } } /* Broken sequence */ } else { /* Single byte, very common case */ if (out) { if ((*out = *in->ptr++) & 0x40) { /* Small negative number */ *out |= (G_GINT64_CONSTANT(-1) ^ 0x7f); } } else { in->ptr++; } return TRUE; } } return FALSE; } gboolean gutil_signed_mbn_decode2( const GUtilData* data, gint64* out) { if (data && data->size) { GUtilRange in; gint64 value; in.end = (in.ptr = data->bytes) + data->size; if (gutil_signed_mbn_decode(&in, &value) && in.ptr == in.end) { if (out) { *out = value; } return TRUE; } } return FALSE; } /* * Compact 7 bits per byte representation of an unsigned integer with * redundant zero bits removed. Most significant bit is the continuation * flag. Unused bits in the first byte (most significant chunk) must be * filled with zeros. * * Examples: * * 33 (0x0000000000000021) => 00100001 (0x21) * 65 (0x0000000000000041) => 01000001 (0x41) * 129 (0x0000000000000081) => 10000001 00000001 (0x81 0x01) */ guint gutil_unsigned_mbn_size( guint64 value) { guint n; value >>= 7; for (n = 1; value; n++) { value >>= 7; } return n; } guint gutil_unsigned_mbn_encode( gpointer buf, guint64 value) { return gutil_unsigned_mbn_encode2(buf, value, gutil_unsigned_mbn_size(value)); } guint gutil_unsigned_mbn_encode2( gpointer buf, guint64 value, guint size) { guchar* ptr = buf; /* Zero or too large size must be a programming error. */ if (size > 0) { guint n = size; ptr[--n] = (guchar)(value & 0x7f); value >>= 7; while (n) { ptr[--n] = (guchar)(value | 0x80); value >>= 7; } } return size; } gboolean gutil_unsigned_mbn_decode( GUtilRange* in, guint64* out) { if (in->ptr < in->end) { guchar last = in->ptr[0]; if (last & 0x80) { const int maxbits = sizeof(*out) * 8; const guchar msc = last; /* Most Significant Chunk */ int nbits = 7; guint off = 1; guint64 value = (last & 0x7f); while ((in->ptr + off) < in->end && ((last = in->ptr[off++]) & 0x80)) { value = (value << 7) | (last & 0x7f); if ((nbits + 7) <= maxbits) { nbits += 7; } else { /* Too many bytes */ return FALSE; } } if (!(last & 0x80)) { value = (value << 7) | last; /* Unused bits must be zeroed */ if ((nbits + 7) < maxbits || (msc & ~((1 << (maxbits - nbits)) - 1)) == 0x80) { if (out) { *out = value; } in->ptr += off; return TRUE; } } /* Broken sequence */ } else { /* Single byte, very common case */ if (out) { *out = *in->ptr++; } else { in->ptr++; } return TRUE; } } return FALSE; } gboolean gutil_unsigned_mbn_decode2( const GUtilData* data, guint64* out) { if (data && data->size) { GUtilRange in; guint64 value; in.end = (in.ptr = data->bytes) + data->size; if (gutil_unsigned_mbn_decode(&in, &value) && in.ptr == in.end) { if (out) { *out = value; } return TRUE; } } return FALSE; } /* * TLV is a convenient and extendible way to pack various kinds of data * into a single memory block. Each entry gets encoded as follows: * * +--- * | T (unsigned MBN) : tag (non-zero) * +--- * | L (unsigned MBN) : length (zero if there's no data) * +--- * | V (L bytes) : tag specific data (optional) * +--- * * To make API even more convenient, these utilities restrict the tag * value to INT_MAX which should be enough in most real life situations. * Also, these utilities assume that tags are non-zero. gutil_tlv_decode() * returns zero ifno TLV can be pulled out of the input data, and the * tags array passed to gutil_tlvs_decode() is zero terminated. */ guint gutil_tlv_size( guint tag, gsize len) { return gutil_unsigned_mbn_size(tag) + gutil_unsigned_mbn_size(len) + len; } gsize gutil_tlv_encode( gpointer buf, guint tag, const GUtilData* val) { guchar* ptr = buf; const guint tag_size = gutil_unsigned_mbn_encode(ptr, tag); ptr += tag_size; if (val && val->size) { const guint len_size = gutil_unsigned_mbn_encode(ptr, val->size); memcpy(ptr + len_size, val->bytes, val->size); return tag_size + len_size + val->size; } else { ptr[0] = 0; return tag_size + 1; } } guint gutil_tlv_decode( GUtilRange* in, GUtilData* val) { GUtilRange tmp = *in; guint64 tag, len; if (gutil_unsigned_mbn_decode(&tmp, &tag) && tag <= INT_MAX && gutil_unsigned_mbn_decode(&tmp, &len) && (tmp.end - tmp.ptr) >= (gssize) len) { if (val) { val->bytes = tmp.ptr; val->size = (gsize) len; } in->ptr = tmp.ptr + len; return (guint) tag; } return 0; } int gutil_tlvs_decode( const GUtilData* in, const guint* tags, GUtilData* vals, GUTIL_TLVS_DECODE_FLAGS flags) { /* No more than first 31 tags from the tags array are considered */ const int max_tags = sizeof(int) * 8 - 1; int mask = 0; GUtilRange range; GUtilData val; guint tag; range.end = (range.ptr = in->bytes) + in->size; if (vals) { int n = 0; const guint* tag = tags; /* Clear the output values */ while (*tag++) n++; memset(vals, 0, sizeof(vals[0]) * n); } while ((tag = gutil_tlv_decode(&range, &val)) != 0) { int i, bit = 0; for (i = 0; tags[i] && i < max_tags; i++) { if (tags[i] == tag) { bit = 1 << i; break; } } if (bit) { if (mask & bit) { return GUTIL_TLVS_DECODE_DUPLICATE_TAG; } else { mask |= bit; if (vals) { vals[i] = val; } } } else if (!(flags & GUTIL_TLVS_DECODE_FLAG_SKIP_UNKNOWN_TAGS)) { return GUTIL_TLVS_DECODE_UNKNOWN_TAG; } } return (range.ptr == range.end) ? mask : GUTIL_TLVS_DECODE_ERROR; } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000026000081A40000000000000000000000016633A65C00001AF5000000000000000000000000000000000000003300000000libglibutil-1714660956.7df665e/src/gutil_history.c/* * Copyright (C) 2017-2023 Slava Monich <slava@monich.com> * Copyright (C) 2017 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_history.h" #include "gutil_log.h" #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif #define GUTIL_HISTORY_DEFAULT_TIME_FUNC g_get_monotonic_time typedef struct gutil_int_history_entry { gint64 time; int value; } GUtilIntHistoryEntry; struct gutil_int_history { gint ref_count; GUtilHistoryTimeFunc time; gint64 max_interval; int first; /* Oldest position (inclusive) */ int last; /* Latest position (inclusive) */ int max_size; /* Number of entries */ GUtilIntHistoryEntry entry[1]; }; GUtilIntHistory* gutil_int_history_new( int max_size, gint64 max_interval) { return gutil_int_history_new_full(max_size, max_interval, NULL); } GUtilIntHistory* gutil_int_history_new_full( int max_size, gint64 max_interval, GUtilHistoryTimeFunc fn) { if (max_size > 0 && max_interval > 0) { /* * We don't allow to dynamically change the maximum history size * so we can allocate the whole thing from a single memory block. */ GUtilIntHistory* h = g_malloc0(sizeof(GUtilIntHistory) + (max_size - 1) * sizeof(GUtilIntHistoryEntry)); g_atomic_int_set(&h->ref_count, 1); h->max_size = max_size; h->max_interval = max_interval; h->first = h->last = -1; h->time = fn ? fn : GUTIL_HISTORY_DEFAULT_TIME_FUNC; return h; } return NULL; } GUtilIntHistory* gutil_int_history_ref( GUtilIntHistory* h) { if (G_LIKELY(h)) { GASSERT(h->ref_count > 0); g_atomic_int_inc(&h->ref_count); } return h; } void gutil_int_history_unref( GUtilIntHistory* h) { if (G_LIKELY(h)) { GASSERT(h->ref_count > 0); if (g_atomic_int_dec_and_test(&h->ref_count)) { g_free(h); } } } static gboolean gutil_int_history_flush( GUtilIntHistory* h, const gint64 now) { const gint64 cutoff = now - h->max_interval; if (h->entry[h->last].time >= cutoff) { /* At least the last entry is valid */ while (h->entry[h->first].time < cutoff) { h->first = (h->first + 1) % h->max_size; } return TRUE; } else { /* The last entry has expired */ h->last = h->first = -1; return FALSE; } } guint gutil_int_history_size( GUtilIntHistory* h) { if (G_LIKELY(h) && h->last >= 0) { if (gutil_int_history_flush(h, h->time())) { if (h->first > h->last) { return (h->max_size + h->last - h->first + 1); } else { GASSERT(h->last > h->first); return (h->last - h->first + 1); } } } return 0; } gint64 gutil_int_history_interval( GUtilIntHistory* h) { if (G_LIKELY(h) && h->last >= 0) { const gint64 now = h->time(); if (gutil_int_history_flush(h, now)) { return now - h->entry[h->first].time; } } return 0; } void gutil_int_history_clear( GUtilIntHistory* h) { if (G_LIKELY(h)) { h->last = h->first = -1; } } static int gutil_int_history_median_at( GUtilIntHistory* h, const gint64 now) { /* The caller has already checked that the history is not empty */ if (h->first == h->last) { return h->entry[h->last].value; } else { int pos = h->first; int v = h->entry[pos].value; gint64 t = h->entry[pos].time; gint64 dt = 0; gint64 area = 0; while (pos != h->last) { gint64 t1; int v1; pos = (pos + 1) % h->max_size; t1 = h->entry[pos].time; v1 = h->entry[pos].value; dt += t1 - t; area += (t1 - t)*(v + v1)/2; t = t1; v = v1; } /* Integral area divided by time */ return (int)(area/dt); } } int gutil_int_history_add( GUtilIntHistory* h, int value) { if (G_LIKELY(h)) { gint64 now = h->time(); if (h->last < 0 || !gutil_int_history_flush(h, now)) { h->last = h->first = 0; } else { const gint64 last_time = h->entry[h->last].time; if (now > last_time) { /* Need a new entry */ h->last = (h->last + 1) % h->max_size; if (h->last == h->first) { h->first = (h->first + 1) % h->max_size; } } else if (now < last_time) { /* Time goes back? */ now = last_time; } } h->entry[h->last].time = now; h->entry[h->last].value = value; return gutil_int_history_median_at(h, now); } return 0; } int gutil_int_history_median( GUtilIntHistory* h, int default_value) { if (G_LIKELY(h) && h->last >= 0) { const gint64 now = h->time(); if (gutil_int_history_flush(h, now)) { return gutil_int_history_median_at(h, now); } } return default_value; } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000027000081A40000000000000000000000016633A65C00002866000000000000000000000000000000000000003400000000libglibutil-1714660956.7df665e/src/gutil_idlepool.c/* * Copyright (C) 2016-2024 Slava Monich <slava@monich.com> * Copyright (C) 2016-2020 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include <gutil_idlepool.h> #include <gutil_macros.h> #include <gutil_log.h> #include <glib-object.h> #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif typedef struct gutil_idle_pool_item GUtilIdlePoolItem; struct gutil_idle_pool_item { GUtilIdlePoolItem* next; gpointer pointer; GDestroyNotify destroy; }; struct gutil_idle_pool { gint ref_count; guint idle_id; GThread* thread; GUtilIdlePoolItem* first; GUtilIdlePoolItem* last; GUtilIdlePool** shared; }; GUtilIdlePool* gutil_idle_pool_new() { GUtilIdlePool* self = g_slice_new0(GUtilIdlePool); /* No need to take a ref as we never dereference this pointer */ self->thread = g_thread_self(); g_atomic_int_set(&self->ref_count, 1); return self; } static void gutil_idle_pool_unref_1( gpointer pool) { gutil_idle_pool_unref(pool); } GUtilIdlePool* gutil_idle_pool_get( GUtilIdlePool** shared) { if (shared) { if (*shared) { /* The object already exists */ return *shared; } else { GUtilIdlePool* pool = gutil_idle_pool_new(); pool->shared = shared; /* New shared object will destroy itself if the caller * doesn't reference it. */ gutil_idle_pool_add(pool, pool, gutil_idle_pool_unref_1); *shared = pool; return pool; } } else { return gutil_idle_pool_new(); } } /* * Thread specific GUtilIdlePool gets created on demand and remains alive * until the thread exits or gutil_idle_pool_release_default is called. The * thread should have a GMainContext or else strange things may happen (see * the comments in gutil_idle_pool_idle). */ GUtilIdlePool* gutil_idle_pool_get_default() /* Since 1.0.76 */ { static GPrivate thread_pool = G_PRIVATE_INIT(gutil_idle_pool_unref_1); GUtilIdlePool* pool = g_private_get(&thread_pool); if (!pool) { pool = gutil_idle_pool_new(); g_private_set(&thread_pool, pool); } return pool; } GUtilIdlePool* gutil_idle_pool_ref( GUtilIdlePool* self) { if (G_LIKELY(self)) { GASSERT(self->ref_count > 0); g_atomic_int_inc(&self->ref_count); } return self; } void gutil_idle_pool_unref( GUtilIdlePool* self) { if (G_LIKELY(self)) { GASSERT(self->ref_count > 0); if (g_atomic_int_dec_and_test(&self->ref_count)) { /* Clear pointer to the shared instance */ if (self->shared) *(self->shared) = NULL; gutil_idle_pool_drain(self); gutil_slice_free(self); } } } void gutil_idle_pool_destroy( GUtilIdlePool* self) /* Since 1.0.34 */ { if (G_LIKELY(self)) { gutil_idle_pool_drain(self); gutil_idle_pool_unref(self); } } void gutil_idle_pool_drain( GUtilIdlePool* self) { /* If no pool is specified, use the default one for this thread */ if (!self) { self = gutil_idle_pool_get_default(); } while (self->first) { GUtilIdlePoolItem* items = self->first; GUtilIdlePoolItem* item = items; self->first = self->last = NULL; while (item) { item->destroy(item->pointer); item = item->next; } g_slice_free_chain(GUtilIdlePoolItem, items, next); } if (self->idle_id) { const guint id = self->idle_id; self->idle_id = 0; g_source_remove(id); } } static gboolean gutil_idle_pool_idle( gpointer user_data) { GUtilIdlePool* self = user_data; self->idle_id = 0; /* * gutil_idle_pool_idle may be invoked on a wrong (main) thread if * something is added to a thread specific pool (e.g. the one created * by gutil_idle_pool_get_default) before the thread specific GMainContext * has been pushed to the context stack. In this case we must not touch * the pool because the access to the pool items is not synchronized and * we generally want to destroy items on the same thread which has created * them. Hence the check for the current thread. * * In the worst case (if the thread specific GMainContext never gets * created) this callback will keep getting invoked but the items won't * be actually deallocated until the thread exits. And the pool (together * with the items it contains) may actually end up being destroyed on the * main thread. * * The bottom line is that it's better not to use GUtilIdlePool without * GMainContext. */ if (self->thread == g_thread_self()) { gutil_idle_pool_drain(self); } else { GDEBUG("gutil_idle_pool_idle is invoked on a wrong thread"); } return G_SOURCE_REMOVE; } gpointer /* Return value since 1.0.76 */ gutil_idle_pool_add( GUtilIdlePool* self, gpointer pointer, GDestroyNotify destroy) { if (G_LIKELY(destroy)) { GUtilIdlePoolItem* item = g_slice_new(GUtilIdlePoolItem); item->next = NULL; item->pointer = pointer; item->destroy = destroy; /* If no pool is specified, use the default one for this thread */ if (!self) { self = gutil_idle_pool_get_default(); } if (self->last) { self->last->next = item; } else { GASSERT(!self->first); self->first = item; } self->last = item; if (!self->idle_id) { GSource* src = g_idle_source_new(); GMainContext* context = g_main_context_get_thread_default(); g_source_set_priority(src, G_PRIORITY_DEFAULT_IDLE); g_source_set_callback(src, gutil_idle_pool_idle, gutil_idle_pool_ref(self), gutil_idle_pool_unref_1); self->idle_id = g_source_attach(src, context ? context : g_main_context_default()); g_source_unref(src); } } return pointer; } static void gutil_idle_pool_strv_free( gpointer strv) { g_strfreev(strv); } char** /* Return value since 1.0.76 */ gutil_idle_pool_add_strv( GUtilIdlePool* self, char** strv) /* Since 1.0.32 */ { if (G_LIKELY(strv)) { gutil_idle_pool_add(self, strv, gutil_idle_pool_strv_free); } return strv; } gpointer /* Return value since 1.0.76 */ gutil_idle_pool_add_object( GUtilIdlePool* self, gpointer object) { if (G_LIKELY(object)) { gutil_idle_pool_add(self, G_OBJECT(object), g_object_unref); } return object; } static void gutil_idle_pool_variant_unref( gpointer var) { g_variant_unref(var); } GVariant* /* Returns value since 1.0.76 */ gutil_idle_pool_add_variant( GUtilIdlePool* self, GVariant* variant) { if (G_LIKELY(variant)) { gutil_idle_pool_add(self, variant, gutil_idle_pool_variant_unref); } return variant; } static void gutil_idle_pool_ptr_array_unref( gpointer array) { g_ptr_array_unref(array); } GPtrArray* /* Return value since 1.0.76 */ gutil_idle_pool_add_ptr_array( GUtilIdlePool* self, GPtrArray* array) { if (G_LIKELY(array)) { gutil_idle_pool_add(self, array, gutil_idle_pool_ptr_array_unref); } return array; } static void gutil_idle_pool_bytes_unref( gpointer bytes) { g_bytes_unref(bytes); } GBytes* /* Return value since 1.0.76 */ gutil_idle_pool_add_bytes( GUtilIdlePool* self, GBytes* bytes) /* Since 1.0.34 */ { return G_LIKELY(bytes) ? gutil_idle_pool_add(self, bytes, gutil_idle_pool_bytes_unref) : NULL; } gpointer /* Return value since 1.0.76 */ gutil_idle_pool_add_object_ref( GUtilIdlePool* self, gpointer object) { return G_LIKELY(object) ? gutil_idle_pool_add_object(self, g_object_ref(object)) : NULL; } GVariant* /* Returns value since 1.0.76 */ gutil_idle_pool_add_variant_ref( GUtilIdlePool* self, GVariant* variant) { return G_LIKELY(variant) ? gutil_idle_pool_add_variant(self, g_variant_ref(variant)) : NULL; } GPtrArray* /* Return value since 1.0.76 */ gutil_idle_pool_add_ptr_array_ref( GUtilIdlePool* self, GPtrArray* array) { return G_LIKELY(array) ? gutil_idle_pool_add_ptr_array(self, g_ptr_array_ref(array)) : NULL; } GBytes* /* Return value since 1.0.76 */ gutil_idle_pool_add_bytes_ref( GUtilIdlePool* self, GBytes* bytes) /* Since 1.0.34 */ { return G_LIKELY(bytes) ? gutil_idle_pool_add_bytes(self, g_bytes_ref(bytes)) : NULL; } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000028000081A40000000000000000000000016633A65C00001F52000000000000000000000000000000000000003500000000libglibutil-1714660956.7df665e/src/gutil_idlequeue.c/* * Copyright (C) 2017-2024 Slava Monich <slava@monich.com> * Copyright (C) 2017-2020 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_idlequeue.h" #include "gutil_macros.h" #include "gutil_misc.h" #include "gutil_log.h" #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif typedef struct gutil_idle_queue_item GUtilIdleQueueItem; struct gutil_idle_queue_item { GUtilIdleQueueItem* next; GUtilIdleQueueTag tag; gpointer data; GUtilIdleFunc run; GFreeFunc destroy; gboolean completed; }; struct gutil_idle_queue { gint ref_count; guint source_id; GUtilIdleQueueItem* first; GUtilIdleQueueItem* last; }; static void gutil_idle_queue_item_destroy( GUtilIdleQueueItem* item) { GASSERT(item->completed); if (item->destroy) { item->destroy(item->data); } gutil_slice_free(item); } static gboolean gutil_idle_queue_run( gpointer data) { GUtilIdleQueue* q = data; GUtilIdleQueueItem* item; GUtilIdleQueueItem* done = NULL; /* * Mark all currently existing items as as completed. Callbacks * that we are about to invoke may add more items, those we are * not supposed to run until the next idle loop. Also, note that * callbacks may cancel some of the completed items, that's why * we can't remove them from the list just yet. */ for (item = q->first; item; item = item->next) { item->completed = TRUE; } while ((item = q->first) && item->completed) { /* Remove this one from the list */ q->first = item->next; if (!q->first) { q->last = NULL; } /* Place it to the "done" list */ item->next = done; done = item; /* Invoke the callbacks */ if (item->run) { item->run(item->data); } if (item->destroy) { item->destroy(item->data); } } /* Free the completed items */ g_slice_free_chain(GUtilIdleQueueItem, done, next); if (q->first) { /* New callbacks have been added */ return G_SOURCE_CONTINUE; } else { q->source_id = 0; return G_SOURCE_REMOVE; } } GUtilIdleQueue* gutil_idle_queue_new() { GUtilIdleQueue* q = g_slice_new0(GUtilIdleQueue); g_atomic_int_set(&q->ref_count, 1); return q; } void gutil_idle_queue_free( GUtilIdleQueue* q) { gutil_idle_queue_cancel_all(q); gutil_idle_queue_unref(q); } GUtilIdleQueue* gutil_idle_queue_ref( GUtilIdleQueue* q) { if (G_LIKELY(q)) { GASSERT(q->ref_count > 0); g_atomic_int_inc(&q->ref_count); } return q; } void gutil_idle_queue_unref( GUtilIdleQueue* q) { if (G_LIKELY(q)) { GASSERT(q->ref_count > 0); if (g_atomic_int_dec_and_test(&q->ref_count)) { gutil_idle_queue_cancel_all(q); gutil_slice_free(q); } } } void gutil_idle_queue_add( GUtilIdleQueue* q, GUtilIdleFunc run, gpointer data) { gutil_idle_queue_add_tag_full(q, 0, run, data, NULL); } void gutil_idle_queue_add_full( GUtilIdleQueue* q, GUtilIdleFunc run, gpointer data, GFreeFunc free) { gutil_idle_queue_add_tag_full(q, 0, run, data, free); } void gutil_idle_queue_add_tag( GUtilIdleQueue* q, GUtilIdleQueueTag tag, GUtilIdleFunc run, gpointer data) { gutil_idle_queue_add_tag_full(q, tag, run, data, NULL); } void gutil_idle_queue_add_tag_full( GUtilIdleQueue* q, GUtilIdleQueueTag tag, GUtilIdleFunc run, gpointer data, GFreeFunc destroy) { if (G_LIKELY(q)) { GUtilIdleQueueItem* item = g_slice_new0(GUtilIdleQueueItem); /* Fill the item */ item->tag = tag; item->run = run; item->destroy = destroy; item->data = data; /* Add it to the queue */ if (q->last) { GASSERT(q->first); q->last->next = item; } else { GASSERT(!q->first); q->first = item; } q->last = item; /* Schedule the callback if necessary */ if (!q->source_id) { q->source_id = g_idle_add(gutil_idle_queue_run, q); } } else if (destroy) { destroy(data); } } gboolean gutil_idle_queue_contains_tag( GUtilIdleQueue* q, GUtilIdleQueueTag tag) { if (G_LIKELY(q)) { const GUtilIdleQueueItem* item; for (item = q->first; item; item = item->next) { if (item->tag == tag) { return TRUE; } } } return FALSE; } static void gutil_idle_queue_cancel_first( GUtilIdleQueue* q) { GUtilIdleQueueItem* item = q->first; q->first = item->next; if (!q->first) { q->last = NULL; } gutil_idle_queue_item_destroy(item); } gboolean gutil_idle_queue_cancel_tag( GUtilIdleQueue* q, GUtilIdleQueueTag tag) { if (G_LIKELY(q) && q->first) { GUtilIdleQueueItem* item = q->first; if (item->tag == tag) { item->completed = TRUE; gutil_idle_queue_cancel_first(q); GASSERT(q->source_id); if (!q->first) { gutil_source_clear(&q->source_id); } return TRUE; } else { GUtilIdleQueueItem* prev = item; for (item = item->next; item; prev = item, item = item->next) { if (item->tag == tag) { if (item->next) { prev->next = item->next; } else { GASSERT(q->last == item); prev->next = NULL; q->last = prev; } item->completed = TRUE; gutil_idle_queue_item_destroy(item); return TRUE; } } } } return FALSE; } void gutil_idle_queue_cancel_all( GUtilIdleQueue* q) { if (G_LIKELY(q)) { GUtilIdleQueueItem* item; for (item = q->first; item; item = item->next) { item->completed = TRUE; } while (q->first && q->first->completed) { gutil_idle_queue_cancel_first(q); } if (!q->first) { gutil_source_clear(&q->source_id); } } } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000029000081A40000000000000000000000016633A65C00002E56000000000000000000000000000000000000003300000000libglibutil-1714660956.7df665e/src/gutil_inotify.c/* * Copyright (C) 2014-2023 Slava Monich <slava@monich.com> * Copyright (C) 2014-2018 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include <gutil_inotify.h> #include <gutil_log.h> #include <glib-object.h> #include <sys/inotify.h> #include <unistd.h> #include <errno.h> #ifdef __clang__ #define NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) #else #define NO_SANITIZE_CFI #endif #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif typedef struct gutil_inotify { int ref_count; int fd; GHashTable* watches; GIOChannel* io_channel; guint io_watch_id; gchar buf[sizeof(struct inotify_event) + NAME_MAX + 1]; } GUtilInotify; typedef GObjectClass GUtilInotifyWatchClass; typedef GUtilInotifyWatch GUtilInotifyWatch; struct gutil_inotify_watch { GObject object; GUtilInotify* inotify; GUtilInotifyWatch* parent; guint32 mask; char* path; int wd; }; struct gutil_inotify_watch_callback { GUtilInotifyWatch* watch; gulong id; }; enum gutil_inotify_watch_signal { SIGNAL_WATCH_EVENT, SIGNAL_COUNT }; #define SIGNAL_WATCH_EVENT_NAME "gutil-inotify-watch-event" static guint gutil_inotify_watch_signals[SIGNAL_COUNT] = { 0 }; #define PARENT_TYPE G_TYPE_OBJECT #define PARENT_CLASS gutil_inotify_watch_parent_class #define THIS_TYPE gutil_inotify_watch_get_type() #define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, THIS_TYPE, GUtilInotifyWatch) G_GNUC_INTERNAL GType THIS_TYPE; G_DEFINE_TYPE(GUtilInotifyWatch, gutil_inotify_watch, PARENT_TYPE) /*==========================================================================* * GUtilInotify *==========================================================================*/ static GUtilInotify* gutil_inotify_instance = NULL; static GUtilInotify* gutil_inotify_ref( GUtilInotify* self) { GASSERT(self->ref_count > 0); g_atomic_int_inc(&self->ref_count); return self; } static void gutil_inotify_unref( GUtilInotify* self) { GASSERT(self->ref_count > 0); if (g_atomic_int_dec_and_test(&self->ref_count)) { if (self->io_watch_id) { g_source_remove(self->io_watch_id); } GASSERT(!g_hash_table_size(self->watches)); g_hash_table_destroy(self->watches); g_io_channel_shutdown(self->io_channel, FALSE, NULL); g_io_channel_unref(self->io_channel); close(self->fd); g_free(self); if (gutil_inotify_instance == self) { gutil_inotify_instance = NULL; } } } static gboolean gutil_inotify_read( GUtilInotify* self) { G_GNUC_UNUSED GIOStatus status; gsize nbytes = 0; GError* error = NULL; status = g_io_channel_read_chars(self->io_channel, self->buf, sizeof(self->buf), &nbytes, &error); GASSERT(status == G_IO_STATUS_NORMAL || (status == G_IO_STATUS_ERROR && error)); if (error) { GERR("Inotify read failed: %s", error->message); g_error_free(error); return FALSE; } else { const char* next = self->buf; while (nbytes > 0) { const struct inotify_event* event = (void*)next; const size_t len = sizeof(struct inotify_event) + event->len; const char* path = event->len ? event->name : NULL; GDEBUG("Inotify event 0x%04x for %s", event->mask, path); GASSERT(len <= nbytes); if (len > nbytes) { break; } else { GUtilInotifyWatch* watch = g_hash_table_lookup(self->watches, GINT_TO_POINTER(event->wd)); if (watch) { gutil_inotify_watch_ref(watch); g_signal_emit(watch, gutil_inotify_watch_signals[SIGNAL_WATCH_EVENT], 0, event->mask, event->cookie, path); gutil_inotify_watch_unref(watch); } next += len; nbytes -= len; } } return TRUE; } } static gboolean gutil_inotify_callback( GIOChannel* channel, GIOCondition condition, gpointer user_data) { GUtilInotify* self = user_data; if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) { self->io_watch_id = 0; return G_SOURCE_REMOVE; } else { gboolean ok; gutil_inotify_ref(self); ok = (condition & G_IO_IN) && gutil_inotify_read(self); if (!ok) self->io_watch_id = 0; gutil_inotify_unref(self); return ok; } } static GUtilInotify* gutil_inotify_create( int fd) { GIOChannel* channel = g_io_channel_unix_new(fd); GASSERT(channel); if (channel) { GUtilInotify* inotify = g_new(GUtilInotify, 1); inotify->ref_count = 1; inotify->fd = fd; inotify->io_channel = channel; inotify->watches = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); g_io_channel_set_encoding(channel, NULL, NULL); g_io_channel_set_buffered(channel, FALSE); inotify->io_watch_id = g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR, gutil_inotify_callback, inotify); return inotify; } return NULL; } static GUtilInotify* gutil_inotify_new() { if (gutil_inotify_instance) { gutil_inotify_ref(gutil_inotify_instance); } else { int fd = inotify_init(); if (fd >= 0) { /* GUtilInotify takes ownership of the file descriptor */ gutil_inotify_instance = gutil_inotify_create(fd); if (!gutil_inotify_instance) { close(fd); } } else { GERR("Failed to init inotify: %s", strerror(errno)); } } return gutil_inotify_instance; } static void gutil_inotify_add_watch( GUtilInotify* self, GUtilInotifyWatch* watch) { GASSERT(watch->wd >= 0); g_hash_table_insert(self->watches, GINT_TO_POINTER(watch->wd), watch); } static void gutil_inotify_remove_watch( GUtilInotify* self, GUtilInotifyWatch* watch) { GASSERT(watch->wd >= 0); GVERIFY(g_hash_table_remove(self->watches, GINT_TO_POINTER(watch->wd))); } /*==========================================================================* * GUtilInotifyWatch *==========================================================================*/ GUtilInotifyWatch* gutil_inotify_watch_new( const char* path, guint32 mask) { if (G_LIKELY(path)) { GUtilInotify* inotify = gutil_inotify_new(); if (G_LIKELY(inotify)) { int wd = inotify_add_watch(inotify->fd, path, mask); if (wd >= 0) { GUtilInotifyWatch* self = g_object_new(THIS_TYPE, NULL); self->inotify = inotify; self->wd = wd; self->mask = mask; self->path = g_strdup(path); gutil_inotify_add_watch(inotify, self); return self; } else if (errno == ENOENT) { GDEBUG("%s doesn't exist", path); } else { GERR("Failed to add inotify watch %s mask 0x%04x: %s", path, mask, strerror(errno)); } gutil_inotify_unref(inotify); } } return NULL; } static void gutil_inotify_watch_stop( GUtilInotifyWatch* self) { if (self->wd >= 0) { gutil_inotify_remove_watch(self->inotify, self); inotify_rm_watch(self->inotify->fd, self->wd); self->wd = -1; } } void gutil_inotify_watch_destroy( GUtilInotifyWatch* self) { if (G_LIKELY(self)) { gutil_inotify_watch_stop(self); gutil_inotify_watch_unref(self); } } GUtilInotifyWatch* gutil_inotify_watch_ref( GUtilInotifyWatch* self) { if (G_LIKELY(self)) { g_object_ref(THIS(self)); return self; } else { return NULL; } } void gutil_inotify_watch_unref( GUtilInotifyWatch* self) { if (G_LIKELY(self)) { g_object_unref(THIS(self)); } } gulong gutil_inotify_watch_add_handler( GUtilInotifyWatch* self, GUtilInotifyWatchFunc cb, void* arg) { return (G_LIKELY(self) && G_LIKELY(cb)) ? g_signal_connect(self, SIGNAL_WATCH_EVENT_NAME, G_CALLBACK(cb), arg) : 0; } void gutil_inotify_watch_remove_handler( GUtilInotifyWatch* self, gulong id) { if (G_LIKELY(self) && G_LIKELY(id)) { g_signal_handler_disconnect(self, id); } } static void gutil_inotify_watch_init( GUtilInotifyWatch* self) { } NO_SANITIZE_CFI static void gutil_inotify_watch_finalize( GObject* object) { GUtilInotifyWatch* self = THIS(object); gutil_inotify_watch_stop(self); gutil_inotify_unref(self->inotify); g_free(self->path); G_OBJECT_CLASS(PARENT_CLASS)->finalize(object); } static void gutil_inotify_watch_class_init( GUtilInotifyWatchClass* klass) { GObjectClass* object_class = G_OBJECT_CLASS(klass); object_class->finalize = gutil_inotify_watch_finalize; gutil_inotify_watch_signals[SIGNAL_WATCH_EVENT] = g_signal_new(SIGNAL_WATCH_EVENT_NAME, G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_POINTER); } /*==========================================================================* * GUtilInotifyWatchCallback *==========================================================================*/ GUtilInotifyWatchCallback* gutil_inotify_watch_callback_new( const char* path, guint32 mask, GUtilInotifyWatchFunc fn, void* arg) { GUtilInotifyWatch* watch = gutil_inotify_watch_new(path, mask); if (watch) { GUtilInotifyWatchCallback* cb = g_new(GUtilInotifyWatchCallback,1); cb->watch = watch; cb->id = gutil_inotify_watch_add_handler(watch, fn, arg); return cb; } return NULL; } void gutil_inotify_watch_callback_free( GUtilInotifyWatchCallback* cb) { if (G_LIKELY(cb)) { gutil_inotify_watch_remove_handler(cb->watch, cb->id); gutil_inotify_watch_unref(cb->watch); g_free(cb); } } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000002A000081A40000000000000000000000016633A65C00001DAE000000000000000000000000000000000000003400000000libglibutil-1714660956.7df665e/src/gutil_intarray.c/* * Copyright (C) 2017-2023 Slava Monich <slava@monich.com> * Copyright (C) 2017 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_intarray.h" #include "gutil_ints.h" #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif G_STATIC_ASSERT(sizeof(GUtilIntArray) == sizeof(GArray)); #define ELEMENT_SIZE (sizeof(int)) GUtilIntArray* gutil_int_array_new() { return (GUtilIntArray*)g_array_sized_new(FALSE, FALSE, ELEMENT_SIZE, 0); } GUtilIntArray* gutil_int_array_sized_new( guint reserved) { return (GUtilIntArray*)g_array_sized_new(FALSE, FALSE, ELEMENT_SIZE, reserved * ELEMENT_SIZE); } GUtilIntArray* gutil_int_array_new_from_vals( const int* vals, guint count) { GUtilIntArray* array = gutil_int_array_sized_new(count); gutil_int_array_append_vals(array, vals, count); return array; } GUtilIntArray* gutil_int_array_new_from_value( int value) { return gutil_int_array_new_from_vals(&value, 1); } int* gutil_int_array_free( GUtilIntArray* array, gboolean free_data) { if (array) { if (array->count) { return (int*)g_array_free((GArray*)array, free_data); } else { return (int*)g_array_free((GArray*)array, TRUE); } } else { return NULL; } } GUtilInts* gutil_int_array_free_to_ints( GUtilIntArray* array) { if (array) { if (array->count) { guint count = array->count; int* values = gutil_int_array_free(array, FALSE); return gutil_ints_new_take(values, count); } else { gutil_int_array_free(array, TRUE); } } return NULL; } GUtilIntArray* gutil_int_array_ref( GUtilIntArray* array) { if (array) { return (GUtilIntArray*)g_array_ref((GArray*)array); } return NULL; } void gutil_int_array_unref( GUtilIntArray* array) { if (array) { g_array_unref((GArray*)array); } } GUtilIntArray* gutil_int_array_append( GUtilIntArray* array, int val) { return gutil_int_array_append_vals(array, &val, 1); } GUtilIntArray* gutil_int_array_append_vals( GUtilIntArray* array, const int* vals, guint count) { if (array) { g_array_append_vals((GArray*)array, (void*)vals, count); } return array; } GUtilIntArray* gutil_int_array_prepend( GUtilIntArray* array, int val) { return gutil_int_array_prepend_vals(array, &val, 1); } GUtilIntArray* gutil_int_array_prepend_vals( GUtilIntArray* array, const int* vals, guint count) { if (array) { g_array_prepend_vals((GArray*)array, (void*)vals, count); } return array; } GUtilIntArray* gutil_int_array_insert( GUtilIntArray* array, guint pos, int val) { return gutil_int_array_insert_vals(array, pos, &val, 1); } GUtilIntArray* gutil_int_array_insert_vals( GUtilIntArray* array, guint pos, const int* vals, guint count) { if (array) { g_array_insert_vals((GArray*)array, pos, (void*)vals, count); } return array; } GUtilIntArray* gutil_int_array_set_count( GUtilIntArray* array, guint count) { if (array) { g_array_set_size((GArray*)array, count); } return array; } int gutil_int_array_find( GUtilIntArray* array, int value) { if (array) { guint i; for (i = 0; i < array->count; i++) { if (array->data[i] == value) { return i; } } } return -1; } gboolean gutil_int_array_contains( GUtilIntArray* array, int value) { return gutil_int_array_find(array, value) >= 0; } gboolean gutil_int_array_remove( GUtilIntArray* array, int value) { const int pos = gutil_int_array_find(array, value); if (pos >= 0) { g_array_remove_index((GArray*)array, pos); return TRUE; } return FALSE; } gboolean gutil_int_array_remove_fast( GUtilIntArray* array, int value) { const int pos = gutil_int_array_find(array, value); if (pos >= 0) { g_array_remove_index_fast((GArray*)array, pos); return TRUE; } return FALSE; } guint gutil_int_array_remove_all( GUtilIntArray* array, int value) { guint n; for (n = 0; gutil_int_array_remove(array, value); n++); return n; } guint gutil_int_array_remove_all_fast( GUtilIntArray* array, int value) { guint n; for (n = 0; gutil_int_array_remove_fast(array, value); n++); return n; } GUtilIntArray* gutil_int_array_remove_index( GUtilIntArray* array, guint pos) { if (array && pos < array->count) { g_array_remove_index((GArray*)array, pos); } return array; } GUtilIntArray* gutil_int_array_remove_index_fast( GUtilIntArray* array, guint pos) { if (array) { g_array_remove_index_fast((GArray*)array, pos); } return array; } GUtilIntArray* gutil_int_array_remove_range( GUtilIntArray* array, guint pos, guint count) { if (array && pos < array->count && count) { guint end = pos + count; if (end > array->count) { end = array->count; } g_array_remove_range((GArray*)array, pos, end - pos); } return array; } static gint gutil_int_array_sort_ascending_proc( gconstpointer a, gconstpointer b) { const int* v1 = a; const int* v2 = b; return *v1 - *v2; } void gutil_int_array_sort_ascending( GUtilIntArray* array) { if (array) { g_array_sort((GArray*)array, gutil_int_array_sort_ascending_proc); } } static gint gutil_int_array_sort_descending_proc( gconstpointer a, gconstpointer b) { const int* v1 = a; const int* v2 = b; return *v2 - *v1; } void gutil_int_array_sort_descending( GUtilIntArray* array) { if (array) { g_array_sort((GArray*)array, gutil_int_array_sort_descending_proc); } } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000002B000081A40000000000000000000000016633A65C00001BAA000000000000000000000000000000000000003000000000libglibutil-1714660956.7df665e/src/gutil_ints.c/* * Copyright (C) 2017-2023 Slava Monich <slava@monich.com> * Copyright (C) 2017-2021 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_intarray.h" #include "gutil_ints.h" #include "gutil_misc.h" #include "gutil_macros.h" #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif struct gutil_ints { const int* data; guint count; gint ref_count; GDestroyNotify free_func; gpointer user_data; }; GUtilInts* gutil_ints_new( const int* data, guint n) { if (data && n) { return gutil_ints_new_take(gutil_memdup(data, n * sizeof(int)), n); } else { return NULL; } } GUtilInts* gutil_ints_new_take( int* data, guint count) { return gutil_ints_new_with_free_func(data, count, g_free, data); } GUtilInts* gutil_ints_new_static( const int* data, guint count) { return gutil_ints_new_with_free_func(data, count, NULL, NULL); } GUtilInts* gutil_ints_new_with_free_func( const int* data, guint count, GDestroyNotify free_func, gpointer user_data) { if (data && count) { GUtilInts* ints = g_slice_new(GUtilInts); ints->data = data; ints->count = count; ints->free_func = free_func; ints->user_data = user_data; g_atomic_int_set(&ints->ref_count, 1); return ints; } else { return NULL; } } static void gutil_ints_unref1( gpointer ints) { gutil_ints_unref(ints); } GUtilInts* gutil_ints_new_from_ints( GUtilInts* ints, guint offset, guint count) { if (ints && offset < ints->count) { guint end = offset + count; if (end > ints->count) { end = ints->count; } return gutil_ints_new_with_free_func(ints->data + offset, end - offset, gutil_ints_unref1, gutil_ints_ref(ints)); } return NULL; } GUtilInts* gutil_ints_ref( GUtilInts* ints) { if (ints) { g_atomic_int_inc(&ints->ref_count); return ints; } return NULL; } void gutil_ints_unref( GUtilInts* ints) { if (ints) { if (g_atomic_int_dec_and_test(&ints->ref_count)) { if (ints->free_func) { ints->free_func(ints->user_data); } gutil_slice_free(ints); } } } int* gutil_ints_unref_to_data( GUtilInts* ints, guint* count) { if (ints) { int* result; if (count) { *count = ints->count; } if (g_atomic_int_dec_and_test(&ints->ref_count)) { if (ints->free_func == g_free) { /* We can allow the caller to free the data */ result = (int*)ints->data; } else { result = gutil_memdup(ints->data, ints->count * sizeof(int)); ints->free_func(ints->user_data); } gutil_slice_free(ints); } else { result = gutil_memdup(ints->data, ints->count * sizeof(int)); } return result; } else { if (count) { *count = 0; } return NULL; } } const int* gutil_ints_get_data( GUtilInts* ints, guint* count) { if (ints) { if (count) { *count = ints->count; } return ints->data; } else { if (count) { *count = 0; } return NULL; } } guint gutil_ints_get_count( GUtilInts* ints) { return ints ? ints->count : 0; } int gutil_ints_find( GUtilInts* ints, int value) { if (ints) { guint i; for (i=0; i<ints->count; i++) { if (ints->data[i] == value) { return i; } } } return -1; } gboolean gutil_ints_contains( GUtilInts* ints, int value) { /* * Could use gutil_ints_find() here but it would return negative value * if the array contains more than MAX_INT entries. Let's be a bit more * reliable. */ if (ints) { guint i; for (i=0; i<ints->count; i++) { if (ints->data[i] == value) { return TRUE; } } } return FALSE; } guint gutil_ints_hash( gconstpointer data) { if (data) { const GUtilInts* ints = data; guint i, h = 1234; for (i=0; i<ints->count; i++) { h ^= ints->data[i] * (i+1); } return h; } else { return 0; } } gboolean gutil_ints_equal( gconstpointer a, gconstpointer b) { const GUtilInts* i1 = a; const GUtilInts* i2 = b; if (i1 == i2) { return TRUE; } else if (i1 && i2) { return i1->count == i2->count && !memcmp(i1->data, i2->data, i1->count * sizeof(int)); } else { return FALSE; } } /* * Returns: a negative value if b is greater, * a positive value if a is greater, * and zero if a is equals b */ gint gutil_ints_compare( gconstpointer a, gconstpointer b) { const GUtilInts* i1 = a; const GUtilInts* i2 = b; if (i1 == i2) { return 0; } else if (i1 && i2) { const int ret = memcmp(i1->data, i2->data, MIN(i1->count, i2->count) * sizeof(int)); if (ret || i1->count == i2->count) { return ret; } else { return (i1->count > i2->count) ? 1 : -1; } } else { return i1 ? 1 : -1; } } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000002C000081A40000000000000000000000016633A65C000050C3000000000000000000000000000000000000002F00000000libglibutil-1714660956.7df665e/src/gutil_log.c/* * Copyright (C) 2014-2023 Slava Monich <slava@monich.com> * Copyright (C) 2014-2022 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_log.h" #include "gutil_misc.h" #include <stdlib.h> #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif #ifdef unix # include <unistd.h> # include <sys/syscall.h> # define gettid() ((int)syscall(SYS_gettid)) #elif defined(_WIN32) # include <windows.h> # define gettid() ((int)GetCurrentThreadId()) #endif #ifndef GLOG_SYSLOG # ifdef unix # define GLOG_SYSLOG 1 # else # define GLOG_SYSLOG 0 # endif #endif /* GLOG_SYSLOG */ #ifndef GLOG_GLIB # define GLOG_GLIB 1 #endif /* GLOG_GLIB */ /* Allows timestamps in stdout log */ gboolean gutil_log_timestamp = FALSE; static const char gutil_log_ftime_default[] = "%Y-%m-%d %H:%M:%S "; static const char* gutil_log_ftime = gutil_log_ftime_default; static char* gutil_log_ftime_custom = NULL; /* Adds thread id prefix */ gboolean gutil_log_tid = FALSE; /* Since 1.0.51 */ /* Log configuration */ static GUTIL_DEFINE_LOG_FN2(gutil_log_default_proc); GLogProc gutil_log_func = gutil_log_stdout; GLogProc2 gutil_log_func2 = gutil_log_default_proc; GLogModule gutil_log_default = { NULL, /* name */ NULL, /* parent */ NULL, /* log_proc */ GLOG_LEVEL_MAX, /* max_level */ GLOG_LEVEL_DEFAULT, /* level */ 0, /* flags */ 0 /* reserved2 */ }; /* Log level descriptions */ static const struct _gutil_log_level { const char* name; const char* description; } gutil_log_levels [] = { { "none", "Disable log output" }, { "error", "Errors only"}, { "warning", "From warning level to errors" }, { "info", "From information level to errors" }, { "debug", "From debug messages to errors" }, { "verbose", "From verbose trace messages to errors" } }; const char GLOG_TYPE_STDOUT[] = "stdout"; const char GLOG_TYPE_STDERR[] = "stderr"; const char GLOG_TYPE_CUSTOM[] = "custom"; #if GLOG_GLIB const char GLOG_TYPE_GLIB[] = "glib"; #endif #if GLOG_SYSLOG const char GLOG_TYPE_SYSLOG[] = "syslog"; #endif G_STATIC_ASSERT(G_N_ELEMENTS(gutil_log_levels) > GLOG_LEVEL_MAX); G_STATIC_ASSERT(G_N_ELEMENTS(gutil_log_levels) > GLOG_LEVEL_DEFAULT); /** * Formats the string into the given buffer (most commonly allocated * on caller's stack). If formatted string fits into the provided buffer, * returns pointer to the given buffer. If formatted string is too long * to fit into the provided buffer, allocates a new one and returns pointer * to it. */ static char* gutil_log_format( char* buf, int bufsize, const char* format, va_list va) { int size, nchars = -1; char* buffer; if (buf) { size = bufsize; buffer = buf; } else { size = MAX(100,bufsize); buffer = g_malloc(size); } while (buffer) { /* Try to print in the allocated space. */ va_list va2; G_VA_COPY(va2, va); nchars = g_vsnprintf(buffer, size, format, va2); va_end(va2); /* Return the string or try again with more space. */ if (nchars >= 0) { if (nchars < size) break; size = nchars+1; /* Precisely what is needed */ } else { size *= 2; /* Twice the old size */ } if (buffer != buf) g_free(buffer); buffer = g_malloc(size); } return buffer; } /* Forward output to stdout or stderr */ void gutil_log_stdio( FILE* out, const char* name, int level, const char* format, va_list va) { char t[32]; char buf[512]; const char* prefix = ""; char* msg; /* gutil_log_ftime is never NULL but can be empty */ if (gutil_log_timestamp && gutil_log_ftime[0]) { time_t now; #ifndef _WIN32 struct tm tm_; #define localtime(t) localtime_r(t, &tm_) #endif time(&now); strftime(t, sizeof(t), gutil_log_ftime, localtime(&now)); #undef localtime } else { t[0] = 0; } /* Empty name is treated the same way as NULL */ if (name && !name[0]) { name = NULL; } switch (level) { case GLOG_LEVEL_WARN: prefix = "WARNING: "; break; case GLOG_LEVEL_ERR: prefix = "ERROR: "; break; default: break; } msg = gutil_log_format(buf, sizeof(buf), format, va); #if defined(DEBUG) && defined(_WIN32) { char s[1023]; if (name) { g_snprintf(s, sizeof(s), "%s[%s] %s%s\n", t, name, prefix, msg); } else { g_snprintf(s, sizeof(s), "%s%s%s\n", t, prefix, msg); } OutputDebugStringA(s); } #endif if (name) { #ifdef gettid if (gutil_log_tid) fprintf(out, "[%d] %s[%s] %s%s\n", gettid(), t, name, prefix, msg); else #endif fprintf(out, "%s[%s] %s%s\n", t, name, prefix, msg); } else { #ifdef gettid if (gutil_log_tid) fprintf(out, "[%d] %s%s%s\n", gettid(), t, prefix, msg); else #endif fprintf(out, "%s%s%s\n", t, prefix, msg); } if (msg != buf) g_free(msg); } void gutil_log_stdout( const char* name, int level, const char* format, va_list va) { gutil_log_stdio(stdout, name, level, format, va); } void gutil_log_stderr( const char* name, int level, const char* format, va_list va) { gutil_log_stdio(stderr, name, level, format, va); } void gutil_log_stdout2( const GLogModule* module, int level, const char* format, va_list va) /* Since 1.0.43 */ { gutil_log_stdout(module ? module->name : NULL, level, format, va); } void gutil_log_stderr2( const GLogModule* module, int level, const char* format, va_list va) /* Since 1.0.43 */ { gutil_log_stderr(module ? module->name : NULL, level, format, va); } /* Formards output to syslog */ #if GLOG_SYSLOG #include <syslog.h> void gutil_log_syslog( const char* name, int level, const char* format, va_list va) { int priority; const char* prefix = NULL; switch (level) { default: case GLOG_LEVEL_INFO: priority = LOG_NOTICE; break; case GLOG_LEVEL_VERBOSE: priority = LOG_DEBUG; break; case GLOG_LEVEL_DEBUG: priority = LOG_INFO; break; case GLOG_LEVEL_WARN: priority = LOG_WARNING; prefix = "WARNING! "; break; case GLOG_LEVEL_ERR: priority = LOG_ERR; prefix = "ERROR! "; break; } if (name) { /* We don't want to see default name twice in the log */ if (!name[0] || name == gutil_log_default.name || !g_strcmp0(name, gutil_log_default.name)) { name = NULL; } } if (name || prefix #ifdef gettid || gutil_log_tid #endif ) { char buf[512]; char* msg = gutil_log_format(buf, sizeof(buf), format, va); if (!prefix) prefix = ""; if (name) { #ifdef gettid if (gutil_log_tid) syslog(priority, "[%d] [%s] %s%s", gettid(), name, prefix, msg); else #endif syslog(priority, "[%s] %s%s", name, prefix, msg); } else { #ifdef gettid if (gutil_log_tid) syslog(priority, "[%d] %s%s", gettid(), prefix, msg); else #endif syslog(priority, "%s%s", prefix, msg); } if (msg != buf) g_free(msg); } else { vsyslog(priority, format, va); } } void gutil_log_syslog2( const GLogModule* module, int level, const char* format, va_list va) /* Since 1.0.43 */ { gutil_log_syslog(module ? module->name : NULL, level, format, va); } #endif /* GLOG_SYSLOG */ /* Forwards output to g_logv */ #if GLOG_GLIB void gutil_log_glib( const char* name, int level, const char* format, va_list va) { GLogLevelFlags flags; switch (level) { default: case GLOG_LEVEL_INFO: flags = G_LOG_LEVEL_MESSAGE; break; case GLOG_LEVEL_VERBOSE: flags = G_LOG_LEVEL_DEBUG; break; case GLOG_LEVEL_DEBUG: flags = G_LOG_LEVEL_INFO; break; case GLOG_LEVEL_WARN: flags = G_LOG_LEVEL_WARNING; break; case GLOG_LEVEL_ERR: flags = G_LOG_LEVEL_CRITICAL; break; } g_logv(name, flags, format, va); } void gutil_log_glib2( const GLogModule* module, int level, const char* format, va_list va) /* Since 1.0.43 */ { gutil_log_glib(module ? module->name : NULL, level, format, va); } #endif /* GLOG_GLIB */ /** * The caller of this function has already verified that the message needs * to be printed. The default action is to forward it to gutil_log_func. */ static void gutil_log_default_proc( const GLogModule* module, int level, const char* format, va_list va) { GLogProc log = gutil_log_func; if (G_LIKELY(log)) { log((module->flags & GLOG_FLAG_HIDE_NAME) ? NULL : module->name, level, format, va); } } /* Logging function */ static void gutil_logv_r( const GLogModule* module, const GLogModule* check, int level, const char* format, va_list va) { if (!check || !(check->flags & GLOG_FLAG_DISABLE)) { if (check && check->level == GLOG_LEVEL_INHERIT && check->parent) { gutil_logv_r(module, check->parent, level, format, va); } else { const int max_level = (check && check->level != GLOG_LEVEL_INHERIT) ? check->level : gutil_log_default.level; if ((level > GLOG_LEVEL_NONE && level <= max_level) || (level == GLOG_LEVEL_ALWAYS)) { GLogProc2 log; /* Caller makes sure that at least gutil_log_func2 is there */ if (!module) module = &gutil_log_default; log = module->log_proc ? module->log_proc : gutil_log_func2; log(module, level, format, va); } } } } void gutil_logv( const GLogModule* module, int level, const char* format, va_list va) { if (level != GLOG_LEVEL_NONE && gutil_log_func2) { gutil_logv_r(module, module, level, format, va); } } void gutil_log( const GLogModule* module, int level, const char* format, ...) { va_list va; va_start(va, format); gutil_logv(module, level, format, va); va_end(va); } void gutil_log_assert( const GLogModule* module, int level, const char* expr, const char* file, int line) { gutil_log(module, level, "Assert %s failed at %s:%d", expr, file, line); } /** * Check if logging is enabled for the specified log level */ static gboolean gutil_log_enabled_r( const GLogModule* module, int level) { if (module->flags & GLOG_FLAG_DISABLE) { return FALSE; } else if (module->level == GLOG_LEVEL_INHERIT && module->parent) { return gutil_log_enabled_r(module->parent, level); } else { const int max_level = (module->level == GLOG_LEVEL_INHERIT) ? gutil_log_default.level : module->level; return (level > GLOG_LEVEL_NONE && level <= max_level) || (level == GLOG_LEVEL_ALWAYS); } } gboolean gutil_log_enabled( const GLogModule* module, int level) { if (level != GLOG_LEVEL_NONE && gutil_log_func2) { return gutil_log_enabled_r(module ? module : &gutil_log_default, level); } return FALSE; } static void gutil_log_dump2( const GLogModule* module, int level, const char* prefix, const void* data, gsize size) { const guint8* ptr = data; guint off = 0; if (!prefix) prefix = ""; while (size > 0) { char buf[GUTIL_HEXDUMP_BUFSIZE]; const guint consumed = gutil_hexdump(buf, ptr + off, size); gutil_log(module, level, "%s%04X: %s", prefix, off, buf); size -= consumed; off += consumed; } } void gutil_log_dump( const GLogModule* module, int level, const char* prefix, const void* data, gsize size) /* Since 1.0.55 */ { if (gutil_log_enabled(module, level)) { gutil_log_dump2(module, level, prefix, data, size); } } void gutil_log_dump_bytes( const GLogModule* module, int level, const char* prefix, GBytes* bytes) /* Since 1.0.67 */ { if (G_LIKELY(bytes) && gutil_log_enabled(module, level)) { gsize size = 0; const guint8* data = g_bytes_get_data(bytes, &size); gutil_log_dump2(module, level, prefix, data, size); } } /* * Timestamp format only affects the output if gutil_log_timestamp is set * to TRUE (by default it's FALSE). Ans it only affects stdio logging. * * The default timestamp format is "%Y-%m-%d %H:%M:%S ", see strftime(3) * for details. Note that it includes a separator between the timestamp * and the rest of the message. Passing in an empty string effectively * disables timestamping, NULL restores the default format. */ void gutil_log_set_timestamp_format( const char* f) /* Since 1.0.73 */ { if (f) { if (g_strcmp0(f, gutil_log_ftime_custom)) { char* old = gutil_log_ftime_custom; /* Not sure if the format string should be validated */ gutil_log_ftime = gutil_log_ftime_custom = g_strdup(f); g_free(old); } } else if (gutil_log_ftime_custom) { g_free(gutil_log_ftime_custom); gutil_log_ftime_custom = NULL; gutil_log_ftime = gutil_log_ftime_default; } } /* gutil_log_parse_option helper */ static int gutil_log_parse_level( const char* str, GError** error) { if (str && str[0]) { guint i; const size_t len = strlen(str); if (len == 1) { const char* valid_numbers = "012345"; const char* number = strchr(valid_numbers, str[0]); if (number) { return number - valid_numbers; } } for (i=0; i<G_N_ELEMENTS(gutil_log_levels); i++) { if (!strncmp(gutil_log_levels[i].name, str, len)) { return i; } } } if (error) { *error = g_error_new(G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Invalid log level '%s'", str); } return -1; } /** * Command line parsing helper. Option format is [module:]level where level * can be either a number or log level name ("none", "error", etc.) */ gboolean gutil_log_parse_option( const char* opt, GLogModule** modules, int count, GError** error) { const char* sep = strchr(opt, ':'); if (sep) { const int modlevel = gutil_log_parse_level(sep+1, error); if (modlevel >= 0) { int i; const size_t namelen = sep - opt; for (i=0; i<count; i++) { if (!g_ascii_strncasecmp(modules[i]->name, opt, namelen) && strlen(modules[i]->name) == namelen) { modules[i]->level = modlevel; return TRUE; } } if (error) { *error = g_error_new(G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Unknown log module '%.*s'", (int)namelen, opt); } } } else { const int deflevel = gutil_log_parse_level(opt, error); if (deflevel >= 0) { gutil_log_default.level = deflevel; return TRUE; } } return FALSE; } /** * Generates the string containg description of log levels and list of * log modules. The caller must deallocate the string with g_free */ char* gutil_log_description( GLogModule** modules, /* Known modules */ int count) /* Number of known modules */ { int i; GString* desc = g_string_sized_new(128); g_string_append(desc, "Log Levels:\n"); for (i=0; i<=GLOG_LEVEL_VERBOSE; i++) { g_string_append_printf(desc, " %d, ", i); g_string_append_printf(desc, "%-8s ", gutil_log_levels[i].name); g_string_append(desc, gutil_log_levels[i].description); if (i == GLOG_LEVEL_DEFAULT) g_string_append(desc, " (default)"); g_string_append(desc, "\n"); } if (modules) { g_string_append(desc, "\nLog Modules:\n"); for (i=0; i<count; i++) { g_string_append_printf(desc, " %s\n", modules[i]->name); } } return g_string_free(desc, FALSE); } gboolean gutil_log_set_type( const char* type, const char* default_name) { #if GLOG_SYSLOG if (!g_ascii_strcasecmp(type, GLOG_TYPE_SYSLOG)) { if (gutil_log_func != gutil_log_syslog) { openlog(NULL, LOG_PID | LOG_CONS, LOG_USER); } /* NULL default_name means "don't change the default name" */ if (default_name) { gutil_log_default.name = default_name; } gutil_log_func = gutil_log_syslog; return TRUE; } if (gutil_log_func == gutil_log_syslog) { closelog(); } #endif /* GLOG_SYSLOG */ /* NULL default_name means "don't change the default name" */ if (default_name) { gutil_log_default.name = default_name; } if (!g_ascii_strcasecmp(type, GLOG_TYPE_STDOUT)) { gutil_log_func = gutil_log_stdout; return TRUE; } if (!g_ascii_strcasecmp(type, GLOG_TYPE_STDERR)) { gutil_log_func = gutil_log_stderr; return TRUE; #if GLOG_GLIB } else if (!g_ascii_strcasecmp(type, GLOG_TYPE_GLIB)) { gutil_log_func = gutil_log_glib; return TRUE; #endif /* GLOG_GLIB */ } return FALSE; } const char* gutil_log_get_type() { return (gutil_log_func == gutil_log_stdout) ? GLOG_TYPE_STDOUT : (gutil_log_func == gutil_log_stderr) ? GLOG_TYPE_STDERR : #if GLOG_SYSLOG (gutil_log_func == gutil_log_syslog) ? GLOG_TYPE_SYSLOG : #endif /* GLOG_SYSLOG */ #if GLOG_GLIB (gutil_log_func == gutil_log_glib) ? GLOG_TYPE_GLIB : #endif /* GLOG_GLIB */ GLOG_TYPE_CUSTOM; } /* Initialize defaults from the environment */ #ifdef __GNUC__ __attribute__((constructor)) static void gutil_log_init() { int val = 0; if (gutil_parse_int(getenv("GUTIL_LOG_DEFAULT_LEVEL"), 0, &val) && val >= GLOG_LEVEL_INHERIT) { gutil_log_default.level = val; GDEBUG("Default log level %d", val); } if (gutil_parse_int(getenv("GUTIL_LOG_TIMESTAMP"), 0, &val) && val >= 0) { gutil_log_timestamp = (val > 0); GDEBUG("Timestamps %s", (val > 0) ? "enabled" : "disabled"); } if (gutil_parse_int(getenv("GUTIL_LOG_TID"), 0, &val) && val >= 0) { gutil_log_tid = (val > 0); GDEBUG("Thread id prefix %s", (val > 0) ? "enabled" : "disabled"); } } __attribute__((destructor)) static void gutil_log_deinit() { gutil_log_set_timestamp_format(NULL); } #endif /* __GNUC__ */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000002D000081A40000000000000000000000016633A65C00004DF9000000000000000000000000000000000000003000000000libglibutil-1714660956.7df665e/src/gutil_misc.c/* * Copyright (C) 2016-2024 Slava Monich <slava@monich.com> * Copyright (C) 2016-2022 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_misc.h" #include <glib-object.h> #include <ctype.h> #include <errno.h> #include <limits.h> #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif void gutil_disconnect_handlers( gpointer instance, gulong *ids, int count) { if (G_LIKELY(instance) && G_LIKELY(ids)) { int i; for (i=0; i<count; i++) { if (ids[i]) { g_signal_handler_disconnect(instance, ids[i]); ids[i] = 0; } } } } void* gutil_object_ref( void* object) /* Since 1.0.71 */ { /* Just a NULL-tolerant version of g_object_ref() */ if (object) { g_object_ref(object); } return object; } void gutil_object_unref( void* object) /* Since 1.0.71 */ { /* Just a NULL-tolerant version of g_object_unref */ if (object) { g_object_unref(object); } } gboolean gutil_source_remove( guint id) /* Since 1.0.78 */ { /* Zero-tolerant version of g_source_remove */ if (id) { g_source_remove(id); return TRUE; } return FALSE; } gboolean gutil_source_clear( guint* id) /* Since 1.0.78 */ { /* Yet another zero-tolerant version of g_source_remove */ if (id && *id) { g_source_remove(*id); *id = 0; return TRUE; } return FALSE; } void* gutil_hex2bin( const char* str, gssize len, void* data) { if (str && data && len > 0 && !(len & 1)) { gssize i; guint8* ptr = data; for (i=0; i<len; i+=2) { static const guint8 hex[] = { 0, 1, 2, 3, 4, 5, 6, 7, /* 0x30..0x37 */ 8, 9, 0, 0, 0, 0, 0, 0, /* 0x3a..0x3f */ 0,10,11,12,13,14,15, 0, /* 0x40..0x47 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x4a..0x4f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40..0x47 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x5a..0x5f */ 0,10,11,12,13,14,15 /* 0x60..0x66 */ }; const char x1 = str[i]; const char x2 = str[i+1]; if (g_ascii_isxdigit(x1) && g_ascii_isxdigit(x2)) { *ptr++ = (hex[x1-0x30] << 4) + hex[x2-0x30]; } else { return NULL; } } return data; } return NULL; } char* gutil_bin2hex( const void* data, gsize len, gboolean upper_case) /* Since 1.0.71 */ { static const char hex[] = "0123456789abcdef"; static const char HEX[] = "0123456789ABCDEF"; const char* map = upper_case ? HEX : hex; const guchar* ptr = data; const guchar* end = ptr + len; char* out = g_malloc(2 * len + 1); char* dest = out; while (ptr < end) { const guchar b = *ptr++; *dest++ = map[(b >> 4) & 0xf]; *dest++ = map[b & 0xf]; } *dest = 0; return out; } char* gutil_data2hex( const GUtilData* data, gboolean upper_case) /* Since 1.0.71 */ { return data ? gutil_bin2hex(data->bytes, data->size, upper_case) : NULL; } GBytes* gutil_hex2bytes( const char* str, gssize len) { if (str) { if (len < 0) len = strlen(str); if (len > 0 && !(len & 1)) { const gsize n = len/2; void* data = g_malloc(n); if (gutil_hex2bin(str, len, data)) { return g_bytes_new_take(data, n); } g_free(data); } } return NULL; } /** * The caller makes sure that the destination buffer has at least * GUTIL_HEXDUMP_BUFSIZE bytes available. Returns the number of * bytes actually dumped (no more than GUTIL_HEXDUMP_MAXBYTES). * * Since 1.0.29 */ guint gutil_hexdump( char* buf, const void* data, guint len) { static const char hex[] = "0123456789abcdef"; const guint bytes_dumped = MIN(len, GUTIL_HEXDUMP_MAXBYTES); const guchar* bytes = data; char* ptr = buf; guint i; for (i=0; i<GUTIL_HEXDUMP_MAXBYTES; i++) { if (i > 0) { *ptr++ = ' '; if (i == 8) *ptr++ = ' '; } if (i < len) { const guchar b = bytes[i]; *ptr++ = hex[(b >> 4) & 0xf]; *ptr++ = hex[b & 0xf]; } else { *ptr++ = ' '; *ptr++ = ' '; } } *ptr++ = ' '; *ptr++ = ' '; *ptr++ = ' '; *ptr++ = ' '; for (i=0; i<bytes_dumped; i++) { const char c = bytes[i]; if (i == 8) *ptr++ = ' '; *ptr++ = isprint(c) ? c : '.'; } *ptr++ = 0; return bytes_dumped; } static const char* gutil_strstrip( const char* str, char** tmp) { /* Caller makes sure that str isn't NULL */ const gsize len = strlen(str); if (g_ascii_isspace(str[0]) || g_ascii_isspace(str[len - 1])) { /* Need to modify the original string */ *tmp = gutil_memdup(str, len + 1); return g_strstrip(*tmp); } else { /* The original string is fine as is */ return str; } } gboolean gutil_parse_int( const char* str, int base, int* value) /* Since 1.0.30 */ { gint64 ll; if (gutil_parse_int64(str, base, &ll) && ll >= INT_MIN && ll <= INT_MAX) { if (value) { *value = (int)ll; } return TRUE; } return FALSE; } gboolean gutil_parse_uint( const char* str, int base, unsigned int* value) /* Since 1.0.53 */ { guint64 ull; if (gutil_parse_uint64(str, base, &ull) && ull <= UINT_MAX) { if (value) { *value = (unsigned int)ull; } return TRUE; } return FALSE; } gboolean gutil_parse_int64( const char* str, int base, gint64* value) /* Since 1.0.56 */ { gboolean ok = FALSE; if (str && *str) { char* tmp = NULL; char* end = NULL; const char* stripped = gutil_strstrip(str, &tmp); gint64 ll; errno = 0; ll = g_ascii_strtoll(stripped, &end, base); if (end && !*end && !((ll == G_MAXINT64 || ll == G_MININT64) && errno == ERANGE) && !(ll == 0 && errno == EINVAL)) { if (value) { *value = ll; } ok = TRUE; } g_free(tmp); } return ok; } gboolean gutil_parse_uint64( const char* str, int base, guint64* value) /* Since 1.0.56 */ { gboolean ok = FALSE; /* * Sorry, we don't accept minus as a part of an unsigned number * (unlike strtoul) */ if (str && *str && *str != '-') { char* tmp = NULL; const char* stripped = gutil_strstrip(str, &tmp); if (*stripped != '-') { char* end = NULL; guint64 ull; errno = 0; ull = g_ascii_strtoull(stripped, &end, base); if (end && !*end && !(ull == G_MAXUINT64 && errno == ERANGE) && !(ull == 0 && errno == EINVAL)) { if (value) { *value = ull; } ok = TRUE; } } g_free(tmp); } return ok; } gboolean gutil_data_equal( const GUtilData* data1, const GUtilData* data2) /* Since 1.0.31 */ { if (data1 == data2) { return TRUE; } else if (!data1 || !data2) { return FALSE; } else if (data1->size == data2->size) { return !memcmp(data1->bytes, data2->bytes, data1->size); } else { return FALSE; } } const GUtilData* gutil_data_from_string( GUtilData* data, const char* str) /* Since 1.0.31 */ { if (data) { if (str) { data->bytes = (const void*)str; data->size = strlen(str); } else { data->bytes = NULL; data->size = 0; } } return data; } const GUtilData* gutil_data_from_bytes( GUtilData* data, GBytes* bytes) /* Since 1.0.31 */ { if (data) { if (bytes) { data->bytes = g_bytes_get_data(bytes, &data->size); } else { data->bytes = NULL; data->size = 0; } } return data; } GUtilData* gutil_data_new( const void* bytes, guint len) /* Since 1.0.72 */ { /* * The whole thing is allocated from a single memory block and * has to be freed with a single g_free() */ const gsize total = len + sizeof(GUtilData); GUtilData* data = g_malloc(total); if (bytes) { void* contents = (void*)(data + 1); data->bytes = contents; data->size = len; memcpy(contents, bytes, len); } else { memset(data, 0, sizeof(*data)); } return data; } GUtilData* gutil_data_copy( const GUtilData* data) /* Since 1.0.72 */ { /* * The whole thing is allocated from a single memory block and * has to be freed with a single g_free() */ return data ? gutil_data_new(data->bytes, data->size) : NULL; } GVariant* gutil_data_copy_as_variant( const GUtilData* data) /* Since 1.0.74 */ { /* * Return a floating reference to a new array GVariant instance * or NULL if the input is NULL. */ return !data ? NULL : data->size ? g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, data->bytes, data->size, 1) : g_variant_new_from_data(G_VARIANT_TYPE_BYTESTRING, NULL, 0, TRUE, NULL, NULL); } gboolean gutil_data_has_prefix( const GUtilData* data, const GUtilData* prefix) /* Since 1.0.38 */ { /* * Not that it was overly important, but let's postulate that * NULL begins with NULL, empty block begins with empty block * but NULL doesn't begin with empty block and empty block * doesn't begin with NULL. */ if (G_LIKELY(data)) { return G_LIKELY(prefix) && prefix->size <= data->size && !memcmp(data->bytes, prefix->bytes, prefix->size); } else { return !prefix; } } gboolean gutil_data_has_suffix( const GUtilData* data, const GUtilData* suffix) /* Since 1.0.38 */ { /* * Similarly to gutil_data_has_prefix, NULL ends with NULL, empty * block ends with empty block but NULL doesn't end with empty block * and empty block doesn't end with NULL. */ if (G_LIKELY(data)) { return G_LIKELY(suffix) && suffix->size <= data->size && !memcmp(data->bytes + (data->size - suffix->size), suffix->bytes, suffix->size); } else { return !suffix; } } GBytes* gutil_bytes_concat( GBytes* bytes1, ...) /* Since 1.0.37 */ { if (G_LIKELY(bytes1)) { va_list args; gsize size = g_bytes_get_size(bytes1); gsize total = size; guint non_empty_count; GBytes* non_empty; GBytes* b; if (!size) { non_empty_count = 0; non_empty = NULL; } else { non_empty_count = 1; non_empty = bytes1; } va_start(args, bytes1); b = va_arg(args, GBytes*); while (b) { size = g_bytes_get_size(b); total += size; if (size) { non_empty_count++; non_empty = b; } b = va_arg(args, GBytes*); } va_end(args); if (non_empty_count == 0) { /* All arrays are empty */ return g_bytes_ref(bytes1); } else if (non_empty_count == 1) { /* Only one array is non-empty */ return g_bytes_ref(non_empty); } else { /* We actually need to concatenate something */ guint8* buf = g_malloc(total); guint8* dest; gsize size; const void* src = g_bytes_get_data(bytes1, &size); memcpy(buf, src, size); dest = buf + size; va_start(args, bytes1); b = va_arg(args, GBytes*); while (b) { src = g_bytes_get_data(b, &size); memcpy(dest, src, size); dest += size; b = va_arg(args, GBytes*); } va_end(args); return g_bytes_new_take(buf, total); } } return NULL; } GBytes* gutil_bytes_xor( GBytes* bytes1, GBytes* bytes2) /* Since 1.0.37 */ { if (G_LIKELY(bytes1) && G_LIKELY(bytes2)) { gsize size1, size2; const guint8* data1 = g_bytes_get_data(bytes1, &size1); const guint8* data2 = g_bytes_get_data(bytes2, &size2); const gsize size = MIN(size1, size2); if (G_LIKELY(size)) { gsize i; guint8* xor_data = g_malloc(size); unsigned long* xor_long = (unsigned long*)xor_data; const unsigned long* long1 = (const unsigned long*)data1; const unsigned long* long2 = (const unsigned long*)data2; const guint8* tail1; const guint8* tail2; guint8* xor_tail; /* Optimize by XOR-ing entire words */ for (i = 0; (i + sizeof(*long1)) <= size; i += sizeof(*long1)) { *xor_long++ = (*long1++) ^ (*long2++); } /* Finish the process byte-by-byte */ tail1 = (const guint8*)long1; tail2 = (const guint8*)long2; xor_tail = (guint8*)xor_long; for(; i < size; i++) { *xor_tail++ = (*tail1++) ^ (*tail2++); } return g_bytes_new_take(xor_data, size); } return g_bytes_ref(size1 ? bytes2 : bytes1); } return NULL; } gboolean gutil_bytes_equal( GBytes* bytes, const void* data, gsize size) /* Since 1.0.41 */ { if (bytes && data) { gsize bytes_size; const guint8* contents = g_bytes_get_data(bytes, &bytes_size); if (bytes_size == size) { return !bytes_size || !memcmp(contents, data, size); } else { return FALSE; } } else { /* NULLs are equal to each other but not to anything else */ return !bytes && !data; } } gboolean gutil_bytes_equal_data( GBytes* bytes, const GUtilData* data) /* Since 1.0.41 */ { if (bytes && data) { gsize bytes_size; const guint8* contents = g_bytes_get_data(bytes, &bytes_size); if (bytes_size == data->size) { return !bytes_size || !memcmp(contents, data->bytes, data->size); } else { return FALSE; } } else { /* NULLs are equal to each other but not to anything else */ return !bytes && !data; } } gboolean gutil_bytes_has_prefix( GBytes* bytes, const void* data, gsize size) /* Since 1.0.63 */ { if (!bytes) { /* NULL GBytes has neither prefix nor suffix, even an empty one */ return FALSE; } else if (!size) { /* * That's largely a philosophical question - can anything have * an empty prefix? Let's assume that the answer is yes. And * then if anything can have such a prefix, everything has it. * Right? Except for NULL GBytes which doesn't have anything * as said earlier. */ return TRUE; } else { gsize bytes_size; const guint8* contents = g_bytes_get_data(bytes, &bytes_size); return (bytes_size >= size) && !memcmp(contents, data, size); } } gboolean gutil_bytes_has_suffix( GBytes* bytes, const void* data, gsize size) /* Since 1.0.63 */ { /* Treat an empty suffix the same way as an empty prefix */ if (!bytes) { return FALSE; } else if (!size) { return TRUE; } else { gsize bytes_size; const guint8* contents = g_bytes_get_data(bytes, &bytes_size); return (bytes_size >= size) && !memcmp(contents + (bytes_size - size), data, size); } } /* Calculates the length of NULL-terminated array of pointers */ gsize gutil_ptrv_length( const void* ptrv) /* Since 1.0.50 */ { if (ptrv) { gsize len = 0; const gconstpointer* ptr = ptrv; while (*ptr++) len++; return len; } else { return 0; } } gboolean gutil_ptrv_is_empty( const void* ptrv) /* Since 1.0.71 */ { return !ptrv || !((gconstpointer*)ptrv)[0]; } /* Frees NULL-terminated array of pointers and whatever they're pointing to. */ void gutil_ptrv_free( void** ptrv) /* Since 1.0.51 */ { if (G_LIKELY(ptrv)) { void** ptr = ptrv; while (*ptr) g_free(*ptr++); g_free(ptrv); } } /* Similar to g_memdup but takes gsize as the number of bytes to copy */ void* gutil_memdup( const void* ptr, gsize size) /* Since 1.0.52 */ { if (G_LIKELY(ptr) && G_LIKELY(size)) { void* copy = g_malloc(size); memcpy(copy, ptr, size); return copy; } else { return NULL; } } /* NULL-tolerant version of strlen */ gsize gutil_strlen0( const char* str) /* Since 1.0.62 */ { return str ? strlen(str) : 0; } gsize gutil_range_init_with_bytes( GUtilRange* range, GBytes* bytes) /* Since 1.0.55 */ { gsize size = 0; if (G_LIKELY(range)) { if (G_LIKELY(bytes)) { range->ptr = (const guint8*) g_bytes_get_data(bytes, &size); range->end = range->ptr + size; } else { memset(range, 0, sizeof(*range)); } } return size; } gboolean gutil_range_has_prefix( const GUtilRange* range, const GUtilData* prefix) /* Since 1.0.55 */ { if (G_LIKELY(range) && G_LIKELY(range->ptr) && G_LIKELY(prefix)) { if (range->end > range->ptr) { return (gsize)(range->end - range->ptr) >= prefix->size && !memcmp(range->ptr, prefix->bytes, prefix->size); } else { return !prefix->size; } } return FALSE; } gboolean gutil_range_skip_prefix( GUtilRange* range, const GUtilData* prefix) /* Since 1.0.55 */ { if (gutil_range_has_prefix(range, prefix)) { range->ptr += prefix->size; return TRUE; } return FALSE; } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000002E000081A40000000000000000000000016633A65C00001DC8000000000000000000000000000000000000003000000000libglibutil-1714660956.7df665e/src/gutil_objv.c/* * Copyright (C) 2023 Slava Monich <slava@monich.com> * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_objv.h" #include "gutil_misc.h" #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif GObject** gutil_objv_new( GObject* obj1, ...) /* Since 1.0.72 */ { gsize len = 0; GObject** objv; GObject** ptr; if (obj1) { GObject* obj; va_list args; len++; va_start(args, obj1); while ((obj = va_arg(args, GObject*)) != NULL) { len++; } va_end(args); } ptr = objv = g_new(GObject*, len + 1); if (obj1) { GObject* obj; va_list args; g_object_ref(*ptr++ = obj1); va_start(args, obj1); while ((obj = va_arg(args, GObject*)) != NULL) { g_object_ref(*ptr++ = obj); } va_end(args); } *ptr = NULL; return objv; } void gutil_objv_free( GObject** objv) { if (objv) { GObject** ptr = objv; while (*ptr) g_object_unref(*ptr++); g_free(objv); } } GObject** gutil_objv_copy( GObject* const* objv) { if (objv) { GObject* const* ptr = objv; gsize n = 0; /* Count the objects and bump references at the same time */ while (*ptr) { g_object_ref(*ptr++); n++; } return gutil_memdup(objv, sizeof(GObject*) * (n + 1)); } return NULL; } GObject** gutil_objv_add( GObject** objv, GObject* obj) { if (obj) { gsize len = gutil_ptrv_length(objv); objv = g_renew(GObject*, objv, len + 2); g_object_ref(objv[len++] = obj); objv[len] = NULL; } return objv; } GObject** gutil_objv_insert( GObject** objv, GObject* obj, gsize pos) /* Since 1.0.71 */ { if (obj) { gsize len = gutil_ptrv_length(objv); objv = g_renew(GObject*, objv, len + 2); if (pos >= len) { /* Insert as the last element */ g_object_ref(objv[len++] = obj); objv[len] = NULL; } else { /* Insert somewhere in the middle (or at the very beginning) */ memmove(objv + (pos + 1), objv + pos, sizeof(GObject*) * (len - pos + 1)); /* Move NULL too */ g_object_ref(objv[pos] = obj); } } return objv; } GObject** gutil_objv_append( GObject** objv, GObject* const* objs) /* Since 1.0.71 */ { const gsize len2 = gutil_ptrv_length(objs); if (len2 > 0) { const gsize len1 = gutil_ptrv_length(objv); GObject* const* src; GObject** dest; objv = g_renew(GObject*, objv, len1 + len2 + 1); dest = objv + len1; src = objs; while (*src) { *dest++ = g_object_ref(*src++); } *dest = NULL; } return objv; } static gssize gutil_objv_find_last_impl( GObject* const* objv, GObject* obj, gsize i /* exclisive */) { while (i > 0) { if (objv[--i] == obj) { return i; } } return -1; } static GObject** gutil_objv_remove_impl( GObject** objv, gsize pos, gsize len) { g_object_unref(objv[pos]); memmove(objv + pos, objv + (pos + 1), sizeof(GObject*) * (len - pos)); return g_realloc(objv, sizeof(GObject*) * len); } GObject** gutil_objv_remove( GObject** objv, GObject* obj, gboolean all) { if (objv && obj) { const gssize pos = gutil_objv_find(objv, obj); if (pos >= 0) { gsize len = gutil_ptrv_length(objv); objv = gutil_objv_remove_impl(objv, pos, len); if (all) { gssize i, l; len--; l = len - pos; while ((i = gutil_objv_find_last_impl(objv + pos, obj, l)) >= 0) { objv = gutil_objv_remove_impl(objv, pos + i, len--); l = i; } } } } return objv; } GObject** gutil_objv_remove_at( GObject** objv, gsize pos) { if (objv) { const gsize len = gutil_ptrv_length(objv); if (pos < len) { objv = gutil_objv_remove_impl(objv, pos, len); } } return objv; } GObject* gutil_objv_at( GObject* const* objv, gsize pos) { if (objv) { guint i = 0; while (objv[i] && i < pos) i++; if (i == pos) { /* We also end up here if i == len but that's OK */ return objv[pos]; } } return NULL; } gboolean gutil_objv_equal( GObject* const* v1, GObject* const* v2) { if (v1 == v2) { return TRUE; } else if (!v1) { return !v2[0]; } else if (!v2) { return !v1[0]; } else { gsize len = 0; while (v1[len] && v1[len] == v2[len]) len++; return !v1[len] && !v2[len]; } } GObject* gutil_objv_first( GObject* const* objv) { return objv ? objv[0] : NULL; } GObject* gutil_objv_last( GObject* const* objv) { if (objv && objv[0]) { GObject* const* ptr = objv; while (ptr[1]) ptr++; return *ptr; } return NULL; } gssize gutil_objv_find( GObject* const* objv, GObject* obj) { if (objv && obj) { GObject* const* ptr; for (ptr = objv; *ptr; ptr++) { if (*ptr == obj) { return ptr - objv; } } } return -1; } gssize gutil_objv_find_last( GObject* const* objv, GObject* obj) { return (objv && obj) ? gutil_objv_find_last_impl(objv, obj, gutil_ptrv_length(objv)) : -1; } gboolean gutil_objv_contains( GObject* const* objv, GObject* obj) { if (objv && obj) { GObject* const* ptr; for (ptr = objv; *ptr; ptr++) { if (*ptr == obj) { return TRUE; } } } return FALSE; } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000002F000081A40000000000000000000000016633A65C00002BA6000000000000000000000000000000000000003000000000libglibutil-1714660956.7df665e/src/gutil_ring.c/* * Copyright (C) 2016-2023 Slava Monich <slava@monich.com> * Copyright (C) 2016-2020 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_ring.h" #include "gutil_macros.h" #include "gutil_log.h" #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif struct gutil_ring { gint ref_count; gint alloc; gint maxsiz; gint start; gint end; gpointer* data; GDestroyNotify free_func; }; GUtilRing* gutil_ring_new() { return gutil_ring_sized_new(0, GUTIL_RING_UNLIMITED_SIZE); } GUtilRing* gutil_ring_sized_new( gint reserved_size, gint max_size) { return gutil_ring_new_full(reserved_size, max_size, NULL); } GUtilRing* gutil_ring_new_full( gint reserved_size, gint max_size, GDestroyNotify free_func) { GUtilRing* r = g_slice_new0(GUtilRing); g_atomic_int_set(&r->ref_count, 1); r->start = r->end = -1; r->maxsiz = (max_size < 0) ? GUTIL_RING_UNLIMITED_SIZE : max_size; r->free_func = free_func; if (reserved_size) { r->data = g_new(gpointer, reserved_size); r->alloc = reserved_size; } return r; } GUtilRing* gutil_ring_ref( GUtilRing* r) { if (G_LIKELY(r)) { GASSERT(r->ref_count > 0); g_atomic_int_inc(&r->ref_count); } return r; } void gutil_ring_unref( GUtilRing* r) { if (G_LIKELY(r)) { GASSERT(r->ref_count > 0); if (g_atomic_int_dec_and_test(&r->ref_count)) { if (r->free_func) { const gint n = gutil_ring_size(r); gint i; for (i=0; i<n; i++) { r->free_func(r->data[(r->start + i) % r->alloc]); } } g_free(r->data); gutil_slice_free(r); } } } void gutil_ring_set_free_func( GUtilRing* r, GDestroyNotify free_func) { if (G_LIKELY(r)) { r->free_func = free_func; } } gint gutil_ring_max_size( GUtilRing* r) { return G_LIKELY(r) ? r->maxsiz : 0; } void gutil_ring_set_max_size( GUtilRing* r, gint max_size) { /* Normalize the value */ if (max_size < 0) max_size = GUTIL_RING_UNLIMITED_SIZE; if (G_LIKELY(r) && r->maxsiz != max_size) { const gint size = gutil_ring_size(r); if (max_size >= 0 && size > max_size) { gutil_ring_drop(r, size - max_size); } r->maxsiz = max_size; } } gint gutil_ring_size( GUtilRing* r) { if (G_LIKELY(r) && r->start >= 0) { if (r->start > r->end) { return (r->alloc + r->end - r->start); } else if (r->end > r->start) { return (r->end - r->start); } else { GASSERT(r->start >= 0 && r->start < r->alloc); GASSERT(r->end >= 0 && r->end < r->alloc); return r->alloc; } } return 0; } void gutil_ring_clear( GUtilRing* r) { if (G_LIKELY(r)) { gint n = gutil_ring_size(r); if (n > 0) { GDestroyNotify free_func = r->free_func; if (free_func) { do { free_func(gutil_ring_get(r)); n--; } while (n > 0 && gutil_ring_size(r) > 0); } else { r->start = r->end = -1; } } } } void gutil_ring_compact( GUtilRing* r) { if (G_LIKELY(r)) { int n = gutil_ring_size(r); if (r->alloc > n) { if (n > 0) { gpointer* buf = g_new(gpointer,n); if (r->start < r->end) { memcpy(buf, r->data + r->start, sizeof(gpointer) * n); } else { const int tail = r->alloc - r->start; memcpy(buf, r->data + r->start, sizeof(gpointer) * tail); memcpy(buf + tail, r->data, sizeof(gpointer) * r->end); } g_free(r->data); r->data = buf; r->alloc = n; r->start = 0; r->end = 0; } else { GASSERT(r->data); g_free(r->data); r->data = NULL; r->alloc = 0; } } } } gboolean gutil_ring_reserve( GUtilRing* r, gint minsize) { if (G_LIKELY(r)) { if (minsize <= r->alloc) { /* The buffer is already large enough */ return TRUE; } else if (r->maxsiz >= 0 && r->alloc >= r->maxsiz) { /* Can't grow the buffer anymore */ return FALSE; } else { gpointer* buf; /* At least double the allocation size */ minsize = MAX(minsize, r->alloc*2); if (r->maxsiz > 0 && minsize > r->maxsiz) { /* Do not exceed the maximum size though */ minsize = r->maxsiz; } buf = g_new(gpointer, minsize); if (r->start < r->end) { const int n = r->end - r->start; memcpy(buf, r->data + r->start, sizeof(gpointer) * n); r->start = 0; r->end = n; } else if (r->start >= 0) { const int tail = r->alloc - r->start; memcpy(buf, r->data + r->start, sizeof(gpointer) * tail); memcpy(buf + tail, r->data, sizeof(gpointer) * r->end); r->start = 0; r->end += tail; GASSERT(r->end < minsize); } g_free(r->data); r->data = buf; r->alloc = minsize; return TRUE; } } return FALSE; } gboolean gutil_ring_can_put( GUtilRing* r, gint n) { if (G_LIKELY(r)) { return r->maxsiz < 0 || (gutil_ring_size(r) + n) <= r->maxsiz; } return FALSE; } gboolean gutil_ring_put( GUtilRing* r, gpointer data) { if (gutil_ring_reserve(r, gutil_ring_size(r) + 1)) { if (r->start < 0) { r->start = r->end = 0; } GASSERT(r->end < r->alloc); r->data[r->end++] = data; r->end %= r->alloc; return TRUE; } return FALSE; } gboolean gutil_ring_put_front( GUtilRing* r, gpointer data) { if (gutil_ring_reserve(r, gutil_ring_size(r) + 1)) { if (r->start >= 0) { r->start = (r->start + r->alloc - 1) % r->alloc; } else { r->start = 0; r->end = 1; } r->data[r->start] = data; return TRUE; } return FALSE; } gpointer gutil_ring_get( GUtilRing* r) { if (G_LIKELY(r) && r->start >= 0) { gpointer data = r->data[r->start++]; if (r->start == r->end) { r->start = r->end = -1; } else { r->start %= r->alloc; if (r->start == r->end) { r->start = r->end = -1; } } return data; } return NULL; } gpointer gutil_ring_get_last( GUtilRing* r) { if (G_LIKELY(r) && r->start >= 0) { gpointer data; r->end = (r->end + r->alloc - 1) % r->alloc; data = r->data[r->end]; if (r->start == r->end) { r->start = r->end = -1; } return data; } return NULL; } gint gutil_ring_drop( GUtilRing* r, gint n) { int size, dropped = 0; if (n > 0 && (size = gutil_ring_size(r)) > 0) { if (n >= size) { dropped = size; gutil_ring_clear(r); } else { dropped = n; if (r->free_func) { while ((n--) > 0) { r->free_func(r->data[r->start]); r->start = (r->start + 1) % r->alloc; GASSERT(r->start != r->end); } } else { r->start = (r->start + n) % r->alloc; GASSERT(r->start != r->end); } } } return dropped; } gint gutil_ring_drop_last( GUtilRing* r, gint n) { int size, dropped = 0; if (n > 0 && (size = gutil_ring_size(r)) > 0) { if (n >= size) { dropped = size; gutil_ring_clear(r); } else { dropped = n; if (r->free_func) { while ((n--) > 0) { r->end = (r->end + r->alloc - 1) % r->alloc; r->free_func(r->data[r->end]); GASSERT(r->start != r->end); } } else { r->end = (r->end + r->alloc - n) % r->alloc; GASSERT(r->start != r->end); } } } return dropped; } gpointer gutil_ring_data_at( GUtilRing* r, gint pos) { if (pos >= 0 && pos < gutil_ring_size(r)) { return r->data[(r->start + pos) % r->alloc]; } return NULL; } gpointer* gutil_ring_flatten( GUtilRing* r, gint* size) { gpointer* data = NULL; const gint n = gutil_ring_size(r); if (G_LIKELY(r) && n > 0) { if (r->start > 0 && r->start >= r->end) { gpointer* buf = g_new(gpointer, n); const gint n1 = r->alloc - r->start; memcpy(buf, r->data + r->start, sizeof(gpointer) * n1); memcpy(buf + n1, r->data, sizeof(gpointer) * r->end); g_free(r->data); r->data = buf; r->start = 0; r->end = (n % r->alloc); } data = r->data + r->start; } if (size) *size = n; return data; } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000030000081A40000000000000000000000016633A65C0000243B000000000000000000000000000000000000003000000000libglibutil-1714660956.7df665e/src/gutil_strv.c/* * Copyright (C) 2014-2023 Slava Monich <slava@monich.com> * Copyright (C) 2014-2022 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_strv.h" #include "gutil_misc.h" #include <stdlib.h> #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif /** * NULL-tolerant version of g_strv_length */ guint gutil_strv_length( const GStrV* sv) { return (guint) gutil_ptrv_length(sv); } /** * Returns i-th strings in the array, NULL if index is out of bounds. */ const char* gutil_strv_at( const GStrV* sv, guint i) { if (G_LIKELY(sv)) { guint k = 0; while (sv[k] && k < i) k++; if (k == i) { /* We also end up here if i == len but that's OK */ return sv[k]; } } return NULL; } /** * Returns the last string in the array, NULL if there's nothing there. */ const char* gutil_strv_last( const GStrV* sv) /* Since 1.0.35 */ { if (G_LIKELY(sv) && G_LIKELY(sv[0])) { guint k = 0; while (sv[k + 1]) k++; return sv[k]; } return NULL; } /** * Returns index of the specified string in the string array, * or -1 if the string is not found. */ int gutil_strv_find( const GStrV* sv, const char* s) { if (G_LIKELY(sv) && G_LIKELY(s)) { int i = 0; const GStrV* ptr; for (ptr = sv; *ptr; ptr++, i++) { if (!strcmp(*ptr, s)) { return i; } } } return -1; } /* Helper for gutil_strv_find_last and friends */ static int gutil_strv_find_last_impl( const GStrV* sv, const char* s, int i /* exclisive */) { while (i > 0) { if (!strcmp(sv[--i], s)) { return i; } } return -1; } /** * Returns index of the last occurrence of specified string in the string * array, or -1 if the string is not found. */ int gutil_strv_find_last( const GStrV* sv, const char* s) /* Since 1.0.62 */ { /* NULL sv is handled by gutil_strv_length() */ return G_LIKELY(s) ? gutil_strv_find_last_impl(sv, s, gutil_strv_length(sv)) : -1; } /** * Checks if string array contains the specified string. */ gboolean gutil_strv_contains( const GStrV* sv, const char* s) { return gutil_strv_find(sv, s) >= 0; } /** * Appends new string to the array. */ GStrV* gutil_strv_add( GStrV* sv, const char* s) { if (s) { guint len = gutil_strv_length(sv); sv = g_renew(char*, sv, len + 2); sv[len++] = g_strdup(s); sv[len] = NULL; } return sv; } /** * Appends new strings to the array. */ GStrV* gutil_strv_addv( GStrV* sv, const char* s, ...) { if (s) { va_list va; const char* s1; guint len, i, n; va_start(va, s); for (n = 1; (s1 = va_arg(va, char*)) != NULL; n++); va_end(va); len = gutil_strv_length(sv); sv = g_renew(gchar*, sv, len + n + 1); sv[len++] = g_strdup(s); va_start(va, s); for (i = 1; i < n; i++) sv[len++] = g_strdup(va_arg(va, char*)); va_end(va); sv[len] = NULL; } return sv; } /* Internal helper for removal functions */ static GStrV* gutil_strv_remove_impl( GStrV* sv, guint pos, guint len, gboolean free_string) { if (free_string) { g_free(sv[pos]); } memmove(sv + pos, sv + pos + 1, sizeof(char*)*(len - pos)); return g_realloc(sv, sizeof(char*)*len); } /** * Removes the string from the specified position in the array. */ GStrV* gutil_strv_remove_at( GStrV* sv, int pos, gboolean free_string) { if (G_LIKELY(sv) && G_LIKELY(pos >= 0)) { const int len = gutil_strv_length(sv); if (pos < len) { sv = gutil_strv_remove_impl(sv, pos, len, free_string); } } return sv; } /** * Removes one or all matching strings from the array and frees them. */ GStrV* gutil_strv_remove( GStrV* sv, const char* s, gboolean remove_all) { if (G_LIKELY(sv) && G_LIKELY(s)) { const int pos = gutil_strv_find(sv, s); if (pos >= 0) { guint len = gutil_strv_length(sv); sv = gutil_strv_remove_impl(sv, pos, len, TRUE); if (remove_all) { int i, l; len--; l = len - pos; while ((i = gutil_strv_find_last_impl(sv + pos, s, l)) >= 0) { sv = gutil_strv_remove_impl(sv, pos + i, len--, TRUE); l = i; } } } } return sv; } /** * Removes all duplicates from the string array. */ GStrV* gutil_strv_remove_dups( GStrV* sv) /* Since 1.0.62 */ { if (G_LIKELY(sv)) { guint len = gutil_strv_length(sv), pos = 0, l = len; while (pos < len) { int i = gutil_strv_find_last_impl(sv + pos + 1, sv[pos], l - 1); if (i < 0) { /* Done with this string, switch to the next one */ pos++; l = len - pos; } else { sv = gutil_strv_remove_impl(sv, pos + 1 + i, len--, TRUE); l = i + 1; } } } return sv; } /** * Checks two string arrays for equality. NULL and empty arrays are equal. * * This is basically a NULL-tolerant equivalent of g_strv_equal which * appeared in glib 2.60. */ gboolean gutil_strv_equal( const GStrV* sv1, const GStrV* sv2) { if (sv1 == sv2) { return TRUE; } else if (!sv1) { return !sv2[0]; } else if (!sv2) { return !sv1[0]; } else { guint len = 0; while (sv1[len] && sv2[len]) len++; if (!sv1[len] && !sv2[len]) { guint i; for (i=0; i<len; i++) { if (strcmp(sv1[i], sv2[i])) { return FALSE; } } return TRUE; } return FALSE; } } static int gutil_strv_sort_ascending( const void* p1, const void* p2) { return strcmp(*(char**)p1, *(char**)p2); } static int gutil_strv_sort_descending( const void* p1, const void* p2) { return -strcmp(*(char**)p1, *(char**)p2); } /** * Sorts the string array */ GStrV* gutil_strv_sort( GStrV* sv, gboolean ascending) { const guint len = gutil_strv_length(sv); if (len > 0) { qsort(sv, len, sizeof(char*), ascending ? gutil_strv_sort_ascending : gutil_strv_sort_descending); } return sv; } /** * Binary search in the sorted string array. Returns index of the * specified string in the string array, or -1 if the string is not * found. It's basically a version of gutil_strv_find optimized for * sorted arrays. The string array must be sorted by gutil_strv_sort * with the same 'ascending' argument. */ int gutil_strv_bsearch( GStrV* sv, const char* s, gboolean ascending) /* Since 1.0.40 */ { if (s) { const guint len = gutil_strv_length(sv); if (len > 0) { GStrV* found = bsearch(&s, sv, len, sizeof(char*), ascending ? gutil_strv_sort_ascending : gutil_strv_sort_descending); if (found) { return found - sv; } } } return -1; } /** * Removes leading and trailing whitespaces from all strings in the vector. */ GStrV* gutil_strv_strip( GStrV* sv) { if (sv) { GStrV* ptr; for (ptr = sv; *ptr; ptr++) { *ptr = g_strstrip(*ptr); } } return sv; } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000031000081A40000000000000000000000016633A65C00001AAE000000000000000000000000000000000000003600000000libglibutil-1714660956.7df665e/src/gutil_timenotify.c/* * Copyright (C) 2016-2023 Slava Monich <slava@monich.com> * Copyright (C) 2016-2019 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_timenotify.h" #include "gutil_misc.h" #include "gutil_log.h" #include <glib-object.h> #include <time.h> #include <errno.h> #include <string.h> #include <sys/timerfd.h> #ifdef __clang__ #define NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) #else #define NO_SANITIZE_CFI #endif #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif #ifndef TFD_TIMER_CANCEL_ON_SET # define TFD_TIMER_CANCEL_ON_SET (1 << 1) #endif #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t)*8)-1)) - 1) struct gutil_time_notify { GObject object; GIOChannel* io_channel; guint io_watch_id; }; enum gutil_time_notify_signal { SIGNAL_TIME_CHANGED, SIGNAL_COUNT }; #define SIGNAL_TIME_CHANGED_NAME "time-changed" static guint gutil_time_notify_signals[SIGNAL_COUNT] = { 0 }; #define PARENT_CLASS gutil_time_notify_parent_class #define THIS_TYPE gutil_time_notify_get_type() #define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, THIS_TYPE, GUtilTimeNotify) GType THIS_TYPE G_GNUC_INTERNAL; typedef GObjectClass GUtilTimeNotifyClass; G_DEFINE_TYPE(GUtilTimeNotify, gutil_time_notify, G_TYPE_OBJECT) GUtilTimeNotify* gutil_time_notify_new() { /* There's no need to have more than one instance. */ static GUtilTimeNotify* gutil_time_notify_instance = NULL; if (gutil_time_notify_instance) { gutil_time_notify_ref(gutil_time_notify_instance); } else { gutil_time_notify_instance = g_object_new(THIS_TYPE, 0); g_object_add_weak_pointer(G_OBJECT(gutil_time_notify_instance), (gpointer*)(&gutil_time_notify_instance)); } return gutil_time_notify_instance; } GUtilTimeNotify* gutil_time_notify_ref( GUtilTimeNotify* self) { if (G_LIKELY(self)) { g_object_ref(THIS(self)); } return self; } void gutil_time_notify_unref( GUtilTimeNotify* self) { if (G_LIKELY(self)) { g_object_unref(THIS(self)); } } gulong gutil_time_notify_add_handler( GUtilTimeNotify* self, GUtilTimeNotifyFunc fn, void* arg) { return (G_LIKELY(self) && G_LIKELY(fn)) ? g_signal_connect(self, SIGNAL_TIME_CHANGED_NAME, G_CALLBACK(fn), arg) : 0; } void gutil_time_notify_remove_handler( GUtilTimeNotify* self, gulong id) { if (G_LIKELY(self) && G_LIKELY(id)) { g_signal_handler_disconnect(self, id); } } static gboolean gutil_time_notify_callback( GIOChannel* channel, GIOCondition condition, gpointer user_data) { GUtilTimeNotify* self = THIS(user_data); if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) { self->io_watch_id = 0; return G_SOURCE_REMOVE; } else { G_GNUC_UNUSED GIOStatus status; gsize bytes_read = 0; GError* error = NULL; guint64 exp; gutil_time_notify_ref(self); status = g_io_channel_read_chars(self->io_channel, (void*)&exp, sizeof(exp), &bytes_read, &error); GASSERT(status == G_IO_STATUS_ERROR && error); if (error) { /* ECANCELED is expected */ GDEBUG("%s", error->message); g_error_free(error); } g_signal_emit(self, gutil_time_notify_signals[SIGNAL_TIME_CHANGED], 0); gutil_time_notify_unref(self); return G_SOURCE_CONTINUE; } } static void gutil_time_notify_init( GUtilTimeNotify* self) { const int fd = timerfd_create(CLOCK_REALTIME, 0); if (fd >= 0) { struct itimerspec timer; self->io_channel = g_io_channel_unix_new(fd); g_io_channel_set_close_on_unref(self->io_channel, TRUE); g_io_channel_set_encoding(self->io_channel, NULL, NULL); g_io_channel_set_buffered(self->io_channel, FALSE); self->io_watch_id = g_io_add_watch(self->io_channel, G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR, gutil_time_notify_callback, self); /* Set timeout to the latest possible value */ memset(&timer, 0, sizeof(timer)); timer.it_value.tv_sec = TIME_T_MAX; timer.it_interval.tv_sec = TIME_T_MAX; if (timerfd_settime(fd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &timer, NULL) < 0) { GERR("timerfd settime: %s", strerror(errno)); } } else { GERR("timerfd open: %s", strerror(errno)); } } NO_SANITIZE_CFI static void gutil_time_notify_finalize( GObject* object) { GUtilTimeNotify* self = THIS(object); if (self->io_channel) { gutil_source_remove(self->io_watch_id); g_io_channel_shutdown(self->io_channel, FALSE, NULL); g_io_channel_unref(self->io_channel); } G_OBJECT_CLASS(PARENT_CLASS)->finalize(object); } static void gutil_time_notify_class_init( GUtilTimeNotifyClass* klass) { G_OBJECT_CLASS(klass)->finalize = gutil_time_notify_finalize; gutil_time_notify_signals[SIGNAL_TIME_CHANGED] = g_signal_new(SIGNAL_TIME_CHANGED_NAME, G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000032000081A40000000000000000000000016633A65C000007E3000000000000000000000000000000000000003300000000libglibutil-1714660956.7df665e/src/gutil_version.c/* * Copyright (C) 2023 Slava Monich <slava@monich.com> * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_version.h" #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif const guint gutil_version_major = GUTIL_VERSION_MAJOR; const guint gutil_version_minor = GUTIL_VERSION_MINOR; const guint gutil_version_micro = GUTIL_VERSION_MICRO; /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000033000081A40000000000000000000000016633A65C00000D9E000000000000000000000000000000000000003300000000libglibutil-1714660956.7df665e/src/gutil_weakref.c/* * Copyright (C) 2023 Slava Monich <slava@monich.com> * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "gutil_weakref.h" #include "gutil_log.h" #include "gutil_macros.h" #include <glib-object.h> #if __GNUC__ >= 4 #pragma GCC visibility push(default) #endif /* * Ref-countable weak reference can be used to avoid calling g_weak_ref_set() * too often because it grabs global weak_locations_lock for exclusive access. * Note that g_weak_ref_set() is also invoked internally by g_weak_ref_init() * and g_weak_ref_clear(). * * g_weak_ref_get() on the other hand only acquires weak_locations_lock * for read-only access which is less of a bottleneck in a multi-threaded * environment. And it's generally significantly simpler and faster than * g_weak_ref_set(). * * Since 1.0.68 */ struct gutil_weakref { gint ref_count; GWeakRef weak_ref; }; GUtilWeakRef* gutil_weakref_new( gpointer obj) { GUtilWeakRef* self = g_slice_new(GUtilWeakRef); g_atomic_int_set(&self->ref_count, 1); g_weak_ref_init(&self->weak_ref, obj); return self; } GUtilWeakRef* gutil_weakref_ref( GUtilWeakRef* self) { if (G_LIKELY(self)) { GASSERT(self->ref_count > 0); g_atomic_int_inc(&self->ref_count); } return self; } void gutil_weakref_unref( GUtilWeakRef* self) { if (G_LIKELY(self)) { GASSERT(self->ref_count > 0); if (g_atomic_int_dec_and_test(&self->ref_count)) { g_weak_ref_clear(&self->weak_ref); gutil_slice_free(self); } } } gpointer gutil_weakref_get( GUtilWeakRef* self) { return G_LIKELY(self) ? g_weak_ref_get(&self->weak_ref) : NULL; } void gutil_weakref_set( GUtilWeakRef* self, gpointer obj) { if (G_LIKELY(self)) { g_weak_ref_set(&self->weak_ref, obj); } } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000034000041ED0000000000000000000000116633A65C00000000000000000000000000000000000000000000002400000000libglibutil-1714660956.7df665e/test07070100000035000081A40000000000000000000000016633A65C00000193000000000000000000000000000000000000002D00000000libglibutil-1714660956.7df665e/test/Makefile# -*- Mode: makefile-gmake -*- all: %: @$(MAKE) -C test_datapack $* @$(MAKE) -C test_history $* @$(MAKE) -C test_idlepool $* @$(MAKE) -C test_idlequeue $* @$(MAKE) -C test_inotify $* @$(MAKE) -C test_intarray $* @$(MAKE) -C test_ints $* @$(MAKE) -C test_log $* @$(MAKE) -C test_misc $* @$(MAKE) -C test_objv $* @$(MAKE) -C test_ring $* @$(MAKE) -C test_strv $* @$(MAKE) -C test_weakref $* 07070100000036000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000002B00000000libglibutil-1714660956.7df665e/test/common07070100000037000081A40000000000000000000000016633A65C0000127D000000000000000000000000000000000000003400000000libglibutil-1714660956.7df665e/test/common/Makefile# -*- Mode: makefile-gmake -*- .PHONY: clean all debug release coverage debug_lib release_lib coverage_lib # # Real test makefile defines EXE (and possibly SRC) and includes this one. # ifndef EXE ${error EXE not defined} endif SRC ?= $(EXE).c COMMON_SRC ?= test_main.c test_object.c # # Required packages # PKGS += gobject-2.0 glib-2.0 # # Default target # all: debug release # # Directories # SRC_DIR = . LIB_DIR = ../.. COMMON_DIR = ../common BUILD_DIR = build DEBUG_BUILD_DIR = $(BUILD_DIR)/debug RELEASE_BUILD_DIR = $(BUILD_DIR)/release COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage # # Tools and flags # PKG_CONFIG ?= pkg-config CC ?= $(CROSS_COMPILE)gcc LD = $(CC) WARNINGS = -Wall INCLUDES = -I$(LIB_DIR)/include -I$(LIB_DIR)/src -I$(COMMON_DIR) BASE_FLAGS = -fPIC BASE_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS) BASE_CFLAGS = $(BASE_FLAGS) $(CFLAGS) FULL_CFLAGS = $(BASE_CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \ -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32 \ -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_MAX_ALLOWED \ $(shell $(PKG_CONFIG) --cflags $(PKGS)) FULL_LDFLAGS = $(BASE_LDFLAGS) LIBS = $(shell $(PKG_CONFIG) --libs $(PKGS)) QUIET_MAKE = $(MAKE) --no-print-directory DEBUG_FLAGS = -g RELEASE_FLAGS = COVERAGE_FLAGS = -g KEEP_SYMBOLS ?= 0 ifneq ($(KEEP_SYMBOLS),0) RELEASE_FLAGS += -g SUBMAKE_OPTS += KEEP_SYMBOLS=1 endif DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS) RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS) COVERAGE_LDFLAGS = $(FULL_LDFLAGS) $(COVERAGE_FLAGS) --coverage DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2 COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) --coverage # # Files # DEBUG_OBJS = \ $(COMMON_SRC:%.c=$(DEBUG_BUILD_DIR)/common_%.o) \ $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) RELEASE_OBJS = \ $(COMMON_SRC:%.c=$(RELEASE_BUILD_DIR)/common_%.o) \ $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o) COVERAGE_OBJS = \ $(COMMON_SRC:%.c=$(COVERAGE_BUILD_DIR)/common_%.o) \ $(SRC:%.c=$(COVERAGE_BUILD_DIR)/%.o) DEBUG_LIB_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_lib) RELEASE_LIB_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_lib) COVERAGE_LIB_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_coverage_lib) DEBUG_LIB := $(LIB_DIR)/$(DEBUG_LIB_FILE) RELEASE_LIB := $(LIB_DIR)/$(RELEASE_LIB_FILE) COVERAGE_LIB := $(LIB_DIR)/$(COVERAGE_LIB_FILE) # # Dependencies # DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d) $(COVERAGE_OBJS:%.o=%.d) ifneq ($(MAKECMDGOALS),clean) ifneq ($(strip $(DEPS)),) -include $(DEPS) endif endif $(DEBUG_LIB): | debug_lib $(RELEASE_LIB): | release_lib $(COVERAGE_LIB): | coverage_lib $(DEBUG_OBJS): | $(DEBUG_BUILD_DIR) $(RELEASE_OBJS): | $(RELEASE_BUILD_DIR) $(COVERAGE_OBJS): | $(COVERAGE_BUILD_DIR) # # Rules # DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE) RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE) COVERAGE_EXE = $(COVERAGE_BUILD_DIR)/$(EXE) debug: debug_lib $(DEBUG_EXE) release: release_lib $(RELEASE_EXE) coverage: coverage_lib $(COVERAGE_EXE) clean: rm -f *~ rm -fr $(BUILD_DIR) cleaner: clean @$(MAKE) -C $(LIB_DIR) clean test_banner: @echo "===========" $(EXE) "=========== " test: test_banner debug @$(DEBUG_EXE) valgrind: test_banner debug @G_DEBUG=gc-friendly G_SLICE=always-malloc valgrind --tool=memcheck --leak-check=full --show-possibly-lost=no $(DEBUG_EXE) $(DEBUG_BUILD_DIR): mkdir -p $@ $(RELEASE_BUILD_DIR): mkdir -p $@ $(COVERAGE_BUILD_DIR): mkdir -p $@ $(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c $(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ $(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c $(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ $(COVERAGE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c $(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ $(DEBUG_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c $(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ $(RELEASE_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c $(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ $(COVERAGE_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c $(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ $(DEBUG_EXE): $(DEBUG_LIB) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS) $(LD) $(DEBUG_LDFLAGS) $(DEBUG_OBJS) $< $(LIBS) -o $@ $(RELEASE_EXE): $(RELEASE_LIB) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS) $(LD) $(RELEASE_LDFLAGS) $(RELEASE_OBJS) $< $(LIBS) -o $@ ifeq ($(KEEP_SYMBOLS),0) strip $@ endif $(COVERAGE_EXE): $(COVERAGE_LIB) $(COVERAGE_BUILD_DIR) $(COVERAGE_OBJS) $(LD) $(COVERAGE_LDFLAGS) $(COVERAGE_OBJS) $< $(LIBS) -o $@ debug_lib: @$(MAKE) $(SUBMAKE_OPTS) -C $(LIB_DIR) debug release_lib: @$(MAKE) $(SUBMAKE_OPTS) -C $(LIB_DIR) release coverage_lib: @$(MAKE) $(SUBMAKE_OPTS) -C $(LIB_DIR) coverage 07070100000038000081A40000000000000000000000016633A65C0000094C000000000000000000000000000000000000003900000000libglibutil-1714660956.7df665e/test/common/test_common.h/* * Copyright (C) 2016-2022 Jolla Ltd. * Copyright (C) 2016-2022 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TEST_COMMON_H #define TEST_COMMON_H #include <gutil_types.h> #include <glib-object.h> #define TEST_FLAG_DEBUG (0x01) typedef struct test_opt { int flags; } TestOpt; GType test_object_get_type(void); #define TEST_OBJECT_TYPE (test_object_get_type()) extern gint test_object_count; /* Should be invoked after g_test_init */ void test_init( TestOpt* opt, int argc, char* argv[]); /* Macros */ #define TEST_INIT_DATA(a,b) ((a).bytes = (void*)(b), (a).size = sizeof(b)) #define TEST_ARRAY_AND_SIZE(a) (a), sizeof(a) #endif /* TEST_COMMON_H */ /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000039000081A40000000000000000000000016633A65C000009D2000000000000000000000000000000000000003700000000libglibutil-1714660956.7df665e/test/common/test_main.c/* * Copyright (C) 2016 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Jolla Ltd nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include <gutil_log.h> void test_init( TestOpt* opt, int argc, char* argv[]) { int i; memset(opt, 0, sizeof(*opt)); for (i=1; i<argc; i++) { const char* arg = argv[i]; if (!strcmp(arg, "-d") || !strcmp(arg, "--debug")) { opt->flags |= TEST_FLAG_DEBUG; } else if (!strcmp(arg, "-v")) { GTestConfig* config = (GTestConfig*)g_test_config_vars; config->test_verbose = TRUE; } else { GWARN("Unsupported command line option %s", arg); } } /* Setup logging */ gutil_log_timestamp = FALSE; gutil_log_default.level = g_test_verbose() ? GLOG_LEVEL_VERBOSE : GLOG_LEVEL_NONE; } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000003A000081A40000000000000000000000016633A65C000009AF000000000000000000000000000000000000003900000000libglibutil-1714660956.7df665e/test/common/test_object.c/* * Copyright (C) 2018-2023 Slava Monich <slava@monich.com> * Copyright (C) 2018 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include <gutil_log.h> typedef GObject TestObject; typedef GObjectClass TestObjectClass; G_DEFINE_TYPE(TestObject, test_object, G_TYPE_OBJECT) gint test_object_count = 0; static void test_object_init( TestObject* self) { g_atomic_int_inc(&test_object_count); } #ifdef __clang__ __attribute__((no_sanitize("cfi"))) #endif static void test_object_finalize( GObject* object) { GASSERT(test_object_count > 0); g_atomic_int_add(&test_object_count, -1); G_OBJECT_CLASS(test_object_parent_class)->finalize(object); } static void test_object_class_init( TestObjectClass* klass) { klass->finalize = test_object_finalize; } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000003B000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000002D00000000libglibutil-1714660956.7df665e/test/coverage0707010000003C000081ED0000000000000000000000016633A65C0000048B000000000000000000000000000000000000003100000000libglibutil-1714660956.7df665e/test/coverage/run#!/bin/bash # # This script requires lcov to be installed # TESTS="\ test_datapack \ test_history \ test_idlepool \ test_idlequeue \ test_inotify \ test_intarray \ test_ints \ test_log \ test_misc \ test_objv \ test_ring \ test_strv \ test_weakref" FLAVOR="coverage" pushd `dirname $0` > /dev/null COV_DIR="$PWD" pushd .. > /dev/null TEST_DIR="$PWD" pushd .. > /dev/null BASE_DIR="$PWD" popd > /dev/null popd > /dev/null popd > /dev/null export LD_LIBRARY_PATH="$BASE_DIR/build/$FLAVOR" make GCOV=1 -C "$BASE_DIR" clean $FLAVOR for t in $TESTS ; do pushd "$TEST_DIR/$t" make -C "$TEST_DIR/$t" clean $FLAVOR || exit 1 build/$FLAVOR/$t || exit 1 popd done # LCOV 1.10 has branch coverage disabled per default LCOV_OPT="--rc lcov_branch_coverage=1" GENHTML_OPT="--branch-coverage" FULL_COV="$COV_DIR/full.gcov" GLIBUTIL_COV="$COV_DIR/libglibutil.gcov" rm -f "$FULL_COV" "$GLIBUTIL_COV" lcov $LCOV_OPT -c -d "$LD_LIBRARY_PATH" -b "$BASE_DIR" -o "$FULL_COV" || exit 1 lcov $LCOV_OPT -e "$FULL_COV" "$BASE_DIR/src/*" -o "$GLIBUTIL_COV" || exit 1 genhtml $GENHTML_OPT -t libglibutil "$GLIBUTIL_COV" --output-directory "$COV_DIR/results" || exit 1 0707010000003D000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000003200000000libglibutil-1714660956.7df665e/test/test_datapack0707010000003E000081A40000000000000000000000016633A65C00000050000000000000000000000000000000000000003B00000000libglibutil-1714660956.7df665e/test/test_datapack/Makefile# -*- Mode: makefile-gmake -*- EXE = test_datapack include ../common/Makefile 0707010000003F000081A40000000000000000000000016633A65C00006D48000000000000000000000000000000000000004200000000libglibutil-1714660956.7df665e/test/test_datapack/test_datapack.c/* * Copyright (C) 2023 Slava Monich <slava@monich.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include "gutil_datapack.h" static TestOpt test_opt; #define TEST_(name) "/datapack/" name static const guint8 test_unsigned_mbn_data_0[] = { 0x00 }; static const guint8 test_unsigned_mbn_data_64[] = { 0x40 }; static const guint8 test_unsigned_mbn_data_127[] = { 0x7f }; static const guint8 test_unsigned_mbn_data_128[] = { 0x81, 0x00 }; static const guint8 test_unsigned_mbn_data_257[] = { 0x82, 0x01 }; static const guint8 test_unsigned_mbn_data_383[] = { 0x82, 0x7f }; static const guint8 test_unsigned_mbn_data_16383[] = { 0xff, 0x7f }; static const guint8 test_unsigned_mbn_data_max64[] = { 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }; static const guint8 test_signed_mbn_data_0[] = { 0x00 }; static const guint8 test_signed_mbn_data_33[] = { 0x21 }; static const guint8 test_signed_mbn_data_m33[] = { 0x5f }; static const guint8 test_signed_mbn_data_65[] = { 0x80, 0x41 }; static const guint8 test_signed_mbn_data_m65[] = { 0xff, 0x3f }; static const guint8 test_signed_mbn_data_127[] = { 0x80, 0x7f }; static const guint8 test_signed_mbn_data_128[] = { 0x81, 0x00 }; static const guint8 test_signed_mbn_data_129[] = { 0x81, 0x01 }; static const guint8 test_signed_mbn_data_m129[] = { 0xfe, 0x7f }; static const guint8 test_signed_mbn_data_257[] = { 0x82, 0x01 }; static const guint8 test_signed_mbn_data_383[] = { 0x82, 0x7f }; static const guint8 test_signed_mbn_data_16383[] = { 0x80, 0xff, 0x7f }; static const guint8 test_signed_mbn_data_m16383[] = { 0xff, 0x80, 0x01 }; static const guint8 test_signed_mbn_data_min64[] = { 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00 }; static const guint8 test_signed_mbn_data_max64[] = { 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }; typedef struct { const char* name; GUtilData input; } TestDecodeFail; static const guint8 test_mbn_decode_fail_data_short[] = { 0x80 }; static const guint8 test_mbn_decode_fail_data_too_long[] = { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f }; /*==========================================================================* * mbn/corner_cases *==========================================================================*/ static void test_mbn_corner_cases() { guint8 buf[1]; g_assert_cmpuint(gutil_signed_mbn_encode2(buf, 0, 0), == ,0); g_assert_cmpuint(gutil_unsigned_mbn_encode2(buf, 0, 0), == ,0); } /*==========================================================================* * signed_mbn/size *==========================================================================*/ typedef struct { const char* name; gint64 input; guint output; } TestSignedMbnSizeData; /* Use test_mbn_write test data as input */ static const TestSignedMbnSizeData test_signed_mbn_size_data[] = { #define TEST_CASE(x) TEST_("signed_mbn/size/") x #define TEST_DATA(x) TEST_CASE(#x), x, sizeof(test_signed_mbn_data_##x) #define TEST_DATA_(x) TEST_CASE("-" #x), -x, sizeof(test_signed_mbn_data_m##x) { TEST_DATA(0) }, { TEST_DATA(33) }, { TEST_DATA_(33) }, { TEST_DATA(65) }, { TEST_DATA_(65) }, { TEST_DATA(127) }, { TEST_DATA(128) }, { TEST_DATA(129) }, { TEST_DATA_(129) }, { TEST_DATA(257) }, { TEST_DATA(383) }, { TEST_DATA(16383) }, { TEST_DATA_(16383) }, { TEST_CASE("min64"), G_MININT64, sizeof(test_signed_mbn_data_min64) }, { TEST_CASE("max64"), G_MAXINT64, sizeof(test_signed_mbn_data_max64) } #undef TEST_CASE #undef TEST_DATA #undef TEST_DATA_ }; static void test_signed_mbn_size( gconstpointer data) { const TestSignedMbnSizeData* test = data; g_assert_cmpuint(gutil_signed_mbn_size(test->input), == ,test->output); } /*==========================================================================* * signed_mbn/encode *==========================================================================*/ typedef struct { const char* name; gint64 input; GUtilData output; } TestSignedMbnEncode; static const TestSignedMbnEncode test_signed_mbn_encode_data[] = { #define TEST_CASE(x) TEST_("signed_mbn/encode/") x #define TEST_DATA(x) TEST_CASE(#x), x, \ { TEST_ARRAY_AND_SIZE(test_signed_mbn_data_##x) } #define TEST_DATA_(x) TEST_CASE("-" #x), -x, \ { TEST_ARRAY_AND_SIZE(test_signed_mbn_data_m##x) } { TEST_DATA(0) }, { TEST_DATA(33) }, { TEST_DATA_(33) }, { TEST_DATA(65) }, { TEST_DATA_(65) }, { TEST_DATA(127) }, { TEST_DATA(128) }, { TEST_DATA(129) }, { TEST_DATA_(129) }, { TEST_DATA(257) }, { TEST_DATA(383) }, { TEST_DATA(16383) }, { TEST_DATA_(16383) }, { TEST_CASE("min64"), G_MININT64, { TEST_ARRAY_AND_SIZE(test_signed_mbn_data_min64) } }, { TEST_CASE("max64"), G_MAXINT64, { TEST_ARRAY_AND_SIZE(test_signed_mbn_data_max64) } } #undef TEST_CASE #undef TEST_DATA #undef TEST_DATA_ }; static void test_signed_mbn_encode( gconstpointer data) { const TestSignedMbnEncode* test = data; guint8* buf = g_malloc(test->output.size); memset(buf, 0xaa, test->output.size); g_assert_cmpuint(gutil_signed_mbn_encode(buf, test->input), == , test->output.size); g_assert(!memcmp(buf, test->output.bytes, test->output.size)); g_free(buf); } /*==========================================================================* * signed_mbn/decode/ok *==========================================================================*/ typedef struct { const char* name; GUtilData input; gint64 output; } TestSignedMbnDecodeOk; static const TestSignedMbnDecodeOk test_signed_mbn_decode_ok_data[] = { #define TEST_CASE(x) TEST_("signed_mbn/decode/ok/") x #define TEST_DATA(x) TEST_CASE(#x), \ { TEST_ARRAY_AND_SIZE(test_signed_mbn_data_##x) }, x #define TEST_DATA_(x) TEST_CASE("-" #x), \ { TEST_ARRAY_AND_SIZE(test_signed_mbn_data_m##x) }, -x { TEST_DATA(0) }, { TEST_DATA(33) }, { TEST_DATA_(33) }, { TEST_DATA(65) }, { TEST_DATA_(65) }, { TEST_DATA(127) }, { TEST_DATA(128) }, { TEST_DATA(129) }, { TEST_DATA_(129) }, { TEST_DATA(257) }, { TEST_DATA(383) }, { TEST_DATA(16383) }, { TEST_DATA_(16383) }, { TEST_CASE("min64"), { TEST_ARRAY_AND_SIZE(test_signed_mbn_data_min64) }, G_MININT64 }, { TEST_CASE("max64"), { TEST_ARRAY_AND_SIZE(test_signed_mbn_data_max64) }, G_MAXINT64 } #undef TEST_CASE #undef TEST_DATA #undef TEST_DATA_ }; static void test_signed_mbn_decode_ok( gconstpointer data) { const TestSignedMbnDecodeOk* test = data; GUtilRange range; gint64 value; range.ptr = test->input.bytes; range.end = range.ptr + test->input.size; g_assert(gutil_signed_mbn_decode(&range, NULL)); g_assert(range.ptr == range.end); range.ptr = test->input.bytes; g_assert(gutil_signed_mbn_decode(&range, &value)); g_assert_cmpint(value, == ,test->output); g_assert(range.ptr == range.end); } /*==========================================================================* * signed_mbn/decode/fail *==========================================================================*/ static const guint8 test_signed_mbn_decode_fail_data_positive_sign_ext[] = { 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }; static const guint8 test_signed_mbn_decode_fail_data_negative_sign_ext[] = { 0xf1, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00 }; static const TestDecodeFail test_signed_mbn_decode_fail_data[] = { #define TEST_CASE(x) TEST_("signed_mbn/decode/fail/") x #define TEST_DATA(x) TEST_CASE(#x), \ { TEST_ARRAY_AND_SIZE(test_mbn_decode_fail_data_##x) } #define TEST_DATA_(x) TEST_CASE(#x), \ { TEST_ARRAY_AND_SIZE(test_signed_mbn_decode_fail_data_##x) } { TEST_CASE("null"), { NULL, 0 } }, { TEST_CASE("empty"), {test_mbn_decode_fail_data_short, 0} }, { TEST_DATA(short) }, { TEST_DATA(too_long) }, { TEST_DATA_(positive_sign_ext) }, { TEST_DATA_(negative_sign_ext) } #undef TEST_CASE #undef TEST_DATA #undef TEST_DATA_ }; static void test_signed_mbn_decode_fail( gconstpointer data) { const TestDecodeFail* test = data; GUtilRange range; gint64 value; range.ptr = test->input.bytes; range.end = range.ptr + test->input.size; g_assert(!gutil_signed_mbn_decode(&range, &value)); g_assert(range.ptr == test->input.bytes); g_assert(!gutil_signed_mbn_decode(&range, NULL)); g_assert(range.ptr == test->input.bytes); } /*==========================================================================* * signed_mbn/decode2 *==========================================================================*/ static void test_signed_mbn_decode2() { static const guint8 trailing_garbage[] = { 0x12, 0x34 }; const TestDecodeFail* fail = test_signed_mbn_decode_fail_data; const TestSignedMbnDecodeOk* ok = test_signed_mbn_decode_ok_data; gint64 value = 0xaaaaaaaa; GUtilData in; guint i; g_assert(!gutil_signed_mbn_decode2(NULL, NULL)); g_assert(!gutil_signed_mbn_decode2(NULL, &value)); in.bytes = trailing_garbage; in.size = sizeof(trailing_garbage); g_assert(!gutil_signed_mbn_decode2(&in, NULL)); g_assert(!gutil_signed_mbn_decode2(&in, &value)); /* Run only NULL, empty and short cases */ for (i = 0; i < 3; i++) { g_assert(!gutil_signed_mbn_decode2(&fail[i].input, NULL)); g_assert(!gutil_signed_mbn_decode2(&fail[i].input, &value)); } g_assert(gutil_signed_mbn_decode2(&ok->input, NULL)); g_assert(gutil_signed_mbn_decode2(&ok->input, &value)); g_assert_cmpint(value, == ,ok->output); } /*==========================================================================* * unsigned_mbn/size *==========================================================================*/ typedef struct { const char* name; guint64 input; guint output; } TestUnsignedMbnSizeData; /* Use test_mbn_write test data as input */ static const TestUnsignedMbnSizeData test_unsigned_mbn_size_data[] = { #define TEST_CASE(x) TEST_("unsigned_mbn/size/") x #define TEST_DATA(x) TEST_CASE(#x), x, sizeof(test_unsigned_mbn_data_##x) { TEST_DATA(0) }, { TEST_DATA(64) }, { TEST_DATA(127) }, { TEST_DATA(128) }, { TEST_DATA(257) }, { TEST_DATA(383) }, { TEST_DATA(16383) }, { TEST_CASE("max64"), G_MAXUINT64, sizeof(test_unsigned_mbn_data_max64) } #undef TEST_CASE #undef TEST_DATA }; static void test_unsigned_mbn_size( gconstpointer data) { const TestUnsignedMbnSizeData* test = data; g_assert_cmpuint(gutil_unsigned_mbn_size(test->input), == ,test->output); } /*==========================================================================* * unsigned_mbn/encode *==========================================================================*/ typedef struct { const char* name; guint64 input; GUtilData output; } TestUnsignedMbnEncode; static const TestUnsignedMbnEncode test_unsigned_mbn_encode_data[] = { #define TEST_CASE(x) TEST_("unsigned_mbn/encode/") x #define TEST_DATA(x) TEST_CASE(#x), x, \ { TEST_ARRAY_AND_SIZE(test_unsigned_mbn_data_##x) } { TEST_DATA(0) }, { TEST_DATA(64) }, { TEST_DATA(127) }, { TEST_DATA(128) }, { TEST_DATA(257) }, { TEST_DATA(383) }, { TEST_DATA(16383) }, { TEST_CASE("max64"), G_MAXUINT64, { TEST_ARRAY_AND_SIZE(test_unsigned_mbn_data_max64) } } #undef TEST_CASE #undef TEST_DATA }; static void test_unsigned_mbn_encode( gconstpointer data) { const TestUnsignedMbnEncode* test = data; guint8* buf = g_malloc(test->output.size); memset(buf, 0xaa, test->output.size); g_assert_cmpuint(gutil_unsigned_mbn_encode(buf, test->input), == , test->output.size); g_assert(!memcmp(buf, test->output.bytes, test->output.size)); g_free(buf); } /*==========================================================================* * unsigned_mbn/decode/ok *==========================================================================*/ typedef struct { const char* name; GUtilData input; guint64 output; } TestUnsignedMbnDecodeOk; static const TestUnsignedMbnDecodeOk test_unsigned_mbn_decode_ok_data[] = { #define TEST_CASE(x) TEST_("unsigned_mbn/decode/ok/") x #define TEST_DATA(x) TEST_CASE(#x), \ { TEST_ARRAY_AND_SIZE(test_unsigned_mbn_data_##x) }, x { TEST_DATA(0) }, { TEST_DATA(64) }, { TEST_DATA(127) }, { TEST_DATA(128) }, { TEST_DATA(257) }, { TEST_DATA(383) }, { TEST_DATA(16383) }, { TEST_CASE("max64"), { TEST_ARRAY_AND_SIZE(test_unsigned_mbn_data_max64) }, G_MAXUINT64 } #undef TEST_CASE #undef TEST_DATA }; static void test_unsigned_mbn_decode_ok( gconstpointer data) { const TestUnsignedMbnDecodeOk* test = data; GUtilRange range; guint64 value; range.ptr = test->input.bytes; range.end = range.ptr + test->input.size; g_assert(gutil_unsigned_mbn_decode(&range, NULL)); g_assert(range.ptr == range.end); range.ptr = test->input.bytes; g_assert(gutil_unsigned_mbn_decode(&range, &value)); g_assert_cmpuint(value, == ,test->output); g_assert(range.ptr == range.end); } /*==========================================================================* * unsigned_mbn/decode/fail *==========================================================================*/ static const guint8 test_unsigned_mbn_decode_fail_data_extra_bits[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }; static const TestDecodeFail test_unsigned_mbn_decode_fail_data[] = { #define TEST_CASE(x) TEST_("unsigned_mbn/decode/fail/") x #define TEST_DATA(x) TEST_CASE(#x), \ { TEST_ARRAY_AND_SIZE(test_mbn_decode_fail_data_##x) } #define TEST_DATA_(x) TEST_CASE(#x), \ { TEST_ARRAY_AND_SIZE(test_unsigned_mbn_decode_fail_data_##x) } { TEST_CASE("null"), { NULL, 0 } }, { TEST_CASE("empty"), {test_mbn_decode_fail_data_short, 0} }, { TEST_DATA(short) }, { TEST_DATA(too_long) }, { TEST_DATA_(extra_bits) } #undef TEST_CASE #undef TEST_DATA #undef TEST_DATA_ }; static void test_unsigned_mbn_decode_fail( gconstpointer data) { const TestDecodeFail* test = data; GUtilRange range; guint64 value; range.ptr = test->input.bytes; range.end = range.ptr + test->input.size; g_assert(!gutil_unsigned_mbn_decode(&range, &value)); g_assert(range.ptr == test->input.bytes); g_assert(!gutil_unsigned_mbn_decode(&range, NULL)); g_assert(range.ptr == test->input.bytes); } /*==========================================================================* * unsigned_mbn/decode2 *==========================================================================*/ static void test_unsigned_mbn_decode2() { static const guint8 trailing_garbage[] = { 0x12, 0x34 }; const TestDecodeFail* fail = test_unsigned_mbn_decode_fail_data; const TestUnsignedMbnDecodeOk* ok = test_unsigned_mbn_decode_ok_data; guint64 value = 0xaaaaaaaa; GUtilData in; guint i; g_assert(!gutil_unsigned_mbn_decode2(NULL, NULL)); g_assert(!gutil_unsigned_mbn_decode2(NULL, &value)); in.bytes = trailing_garbage; in.size = sizeof(trailing_garbage); g_assert(!gutil_unsigned_mbn_decode2(&in, NULL)); g_assert(!gutil_unsigned_mbn_decode2(&in, &value)); /* Run only NULL, empty and short cases */ for (i = 0; i < 3; i++) { g_assert(!gutil_unsigned_mbn_decode2(&fail[i].input, NULL)); g_assert(!gutil_unsigned_mbn_decode2(&fail[i].input, &value)); } g_assert(gutil_unsigned_mbn_decode2(&ok->input, NULL)); g_assert(gutil_unsigned_mbn_decode2(&ok->input, &value)); g_assert_cmpuint(value, == ,ok->output); } /*==========================================================================* * tlv/corner_cases *==========================================================================*/ static void test_tlv_corner_cases() { guint8 buf[2]; memset(buf, 0xaa, sizeof(buf)); g_assert_cmpuint(gutil_tlv_encode(buf, 3, NULL), == ,2); g_assert_cmpuint(buf[0], == ,3); g_assert_cmpuint(buf[1], == ,0); } /*==========================================================================* * tlv/size *==========================================================================*/ typedef struct { const char* name; guint tag; gsize len; guint size; } TestTlvSize; static const TestTlvSize test_tlv_size_data[] = { #define TEST_CASE(x) TEST_("tlv/size/") x { TEST_CASE("2"), 1, 0, 2 }, { TEST_CASE("3"), 1, 1, 3 }, { TEST_CASE("4"), 128, 1, 4 }, { TEST_CASE("130"), 128, 127, 130 }, { TEST_CASE("133"), 128, 129, 133 } #undef TEST_CASE }; static void test_tlv_size( gconstpointer data) { const TestTlvSize* test = data; g_assert_cmpuint(gutil_tlv_size(test->tag, test->len), == ,test->size); } /*==========================================================================* * tlv/encode *==========================================================================*/ typedef struct { const char* name; guint tag; GUtilData in; GUtilData out; } TestTlvEncodeDecode; static const guint8 test_tlv_encode_data_out_0[] = { 0x01, 0x00 }; #define TEST_TLV_ENCODE_TAG_1 1 static const guint8 test_tlv_encode_data_in_1[] = { 0x01, 0x02, 0x03 }; static const guint8 test_tlv_encode_data_out_1[] = { 0x01, 0x03, 0x01, 0x02, 0x03 }; static const TestTlvEncodeDecode test_tlv_encode_data[] = { #define TEST_CASE(x) TEST_("tlv/encode/") x #define TEST_DATA(x) TEST_CASE(#x), TEST_TLV_ENCODE_TAG_##x, \ { TEST_ARRAY_AND_SIZE(test_tlv_encode_data_in_##x) }, \ { TEST_ARRAY_AND_SIZE(test_tlv_encode_data_out_##x) } { TEST_CASE("0"), 1, { NULL, 0 }, { TEST_ARRAY_AND_SIZE(test_tlv_encode_data_out_0)} }, { TEST_DATA(1) }, #undef TEST_CASE #undef TEST_DATA }; static void test_tlv_encode( gconstpointer data) { const TestTlvEncodeDecode* test = data; const gsize size = test->out.size; void* buf = g_malloc(size); g_assert_cmpuint(gutil_tlv_size(test->tag, test->in.size), == , size); g_assert_cmpuint(gutil_tlv_encode(buf, test->tag, &test->in), == , size); g_assert(!memcmp(test->out.bytes, buf, size)); g_free(buf); } /*==========================================================================* * tlv/decode/ok *==========================================================================*/ static const TestTlvEncodeDecode test_tlv_decode_ok_data[] = { #define TEST_CASE(x) TEST_("tlv/decode/ok/") x #define TEST_DATA(x) TEST_CASE(#x), TEST_TLV_ENCODE_TAG_##x, \ { TEST_ARRAY_AND_SIZE(test_tlv_encode_data_out_##x) }, \ { TEST_ARRAY_AND_SIZE(test_tlv_encode_data_in_##x) } { TEST_CASE("0"), 1, { TEST_ARRAY_AND_SIZE(test_tlv_encode_data_out_0) }, { NULL, 0 } }, { TEST_DATA(1) }, #undef TEST_CASE #undef TEST_DATA }; static void test_tlv_decode_ok( gconstpointer data) { const TestTlvEncodeDecode* test = data; GUtilRange in; GUtilData val; in.ptr = test->in.bytes; in.end = in.ptr + test->in.size; g_assert_cmpuint(gutil_tlv_decode(&in, NULL), == ,test->tag); g_assert(in.ptr == in.end); in.ptr = test->in.bytes; in.end = in.ptr + test->in.size; g_assert_cmpuint(gutil_tlv_decode(&in, &val), == ,test->tag); g_assert_cmpuint(val.size, == ,test->out.size); g_assert(!memcmp(val.bytes, test->out.bytes, val.size)); g_assert(in.ptr == in.end); } /*==========================================================================* * tlv/decode/fail *==========================================================================*/ static const guint8 test_tlv_decode_fail_data_tag_too_large[] = { 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00 }; static const guint8 test_tlv_decode_fail_data_broken_len[] = { 0x01, 0xff }; static const guint8 test_tlv_decode_fail_data_truncated[] = { 0x01, 0x02, 0x00 }; static const TestDecodeFail test_tlv_decode_fail_data[] = { #define TEST_CASE(x) TEST_("tlv/decode/fail/") x #define TEST_DATA(x) TEST_CASE(#x), \ { TEST_ARRAY_AND_SIZE(test_tlv_decode_fail_data_##x) } { TEST_CASE("null"), { NULL, 0 } }, { TEST_CASE("empty"), {test_tlv_decode_fail_data_tag_too_large, 0} }, { TEST_DATA(tag_too_large) }, { TEST_DATA(broken_len) }, { TEST_DATA(truncated) } #undef TEST_CASE #undef TEST_DATA }; static void test_tlv_decode_fail( gconstpointer data) { const TestDecodeFail* test = data; GUtilRange in; GUtilData value; in.ptr = test->input.bytes; in.end = in.ptr + test->input.size; g_assert(!gutil_tlv_decode(&in, &value)); g_assert(in.ptr == test->input.bytes); g_assert(!gutil_tlv_decode(&in, NULL)); g_assert(in.ptr == test->input.bytes); } /*==========================================================================* * tlvs/decode *==========================================================================*/ typedef struct { const char* name; GUtilData input; const guint* tags; GUTIL_TLVS_DECODE_FLAGS flags; int result; const GUtilData* values; } TestTlvsDecode; static const guint test_tlvs_decode_tags_1[] = { 1, 0 }; static const guint test_tlvs_decode_tags_1_2[] = { 1, 2, 0 }; static const guint test_tlvs_decode_tags_too_many[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70 }; static const guint8 test_tlvs_decode_input_dup[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x00 }; static const guint8 test_tlvs_decode_input_tags_2_x[] = { 0x02, 0x03, 0x04, 0x05, 0x06, 0x7f, 0x00 }; static const guint8 test_tlvs_decode_input_tags_x[] = { 0x7f, 0x00 }; static const guint8 test_tlvs_decode_input_garbage[] = { 0x01, 0x02, 0x03, 0x04, 0x05 }; static const guint8 test_tlvs_decode_output_2_data[] = { 0x04, 0x05, 0x06 }; static const GUtilData test_tlvs_decode_output_x_2[] = { { NULL, 0 }, { TEST_ARRAY_AND_SIZE(test_tlvs_decode_output_2_data) } }; static const TestTlvsDecode test_tlvs_decode_data[] = { #define TEST_CASE(x) TEST_("tlvs/decode/") x { TEST_CASE("empty"), { (void*) test_tlvs_decode_data, 0 }, test_tlvs_decode_tags_1, GUTIL_TLVS_DECODE_NO_FLAGS, 0, NULL },{ TEST_CASE("dup"), { TEST_ARRAY_AND_SIZE(test_tlvs_decode_input_dup) }, test_tlvs_decode_tags_1, GUTIL_TLVS_DECODE_NO_FLAGS, GUTIL_TLVS_DECODE_DUPLICATE_TAG, NULL },{ TEST_CASE("unknown_tag/fail/1"), { TEST_ARRAY_AND_SIZE(test_tlvs_decode_input_tags_2_x) }, test_tlvs_decode_tags_too_many, GUTIL_TLVS_DECODE_NO_FLAGS, GUTIL_TLVS_DECODE_UNKNOWN_TAG, NULL },{ TEST_CASE("unknown_tag/fail/2"), { TEST_ARRAY_AND_SIZE(test_tlvs_decode_input_tags_2_x) }, test_tlvs_decode_tags_1_2, GUTIL_TLVS_DECODE_NO_FLAGS, GUTIL_TLVS_DECODE_UNKNOWN_TAG, NULL },{ TEST_CASE("unknown_tag/ok/1"), { TEST_ARRAY_AND_SIZE(test_tlvs_decode_input_tags_2_x) }, test_tlvs_decode_tags_1_2, GUTIL_TLVS_DECODE_FLAG_SKIP_UNKNOWN_TAGS, 0x02, test_tlvs_decode_output_x_2 },{ TEST_CASE("unknown_tag/ok/2"), { TEST_ARRAY_AND_SIZE(test_tlvs_decode_input_tags_x) }, test_tlvs_decode_tags_1_2, GUTIL_TLVS_DECODE_FLAG_SKIP_UNKNOWN_TAGS, 0, NULL },{ TEST_CASE("garbage"), { TEST_ARRAY_AND_SIZE(test_tlvs_decode_input_garbage) }, test_tlvs_decode_tags_1, GUTIL_TLVS_DECODE_NO_FLAGS, GUTIL_TLVS_DECODE_ERROR, NULL } #undef TEST_CASE }; static void test_tlvs_decode( gconstpointer data) { const TestTlvsDecode* test = data; int i, n = 0; const guint* tag = test->tags; GUtilData* vals = NULL; while (*tag++) n++; if (n) { vals = g_new(GUtilData, n); memset(vals, 0xaa, sizeof(vals[0]) * n); } g_assert_cmpint(gutil_tlvs_decode(&test->input, test->tags, NULL, test->flags), == ,test->result); if (vals) { g_assert_cmpint(gutil_tlvs_decode(&test->input, test->tags, vals, test->flags), == ,test->result); } if (test->result > 0) { for (i = 0; i < n; i++) { if (test->result & (1 << i)) { const GUtilData* expected = test->values + i; g_assert_cmpuint(vals[i].size, == ,expected->size); g_assert(!memcmp(vals[i].bytes, test->values[i].bytes, expected->size)); } else { g_assert(!vals[i].bytes); g_assert_cmpuint(vals[i].size, == ,0); } } } g_free(vals); } /*==========================================================================* * Common *==========================================================================*/ #define TESTS_WITH_DATA(x) \ do { int i; for (i = 0; i < G_N_ELEMENTS(x##_data); i++) { \ g_test_add_data_func(x##_data[i].name, x##_data + i, x); \ } } while (FALSE) int main(int argc, char* argv[]) { g_test_init(&argc, &argv, NULL); test_init(&test_opt, argc, argv); g_test_add_func(TEST_("mbn/corner_cases"), test_mbn_corner_cases); g_test_add_func(TEST_("tlv/corner_cases"), test_tlv_corner_cases); g_test_add_func(TEST_("signed_mbn/decode2"), test_signed_mbn_decode2); g_test_add_func(TEST_("unsigned_mbn/decode2"), test_unsigned_mbn_decode2); TESTS_WITH_DATA(test_signed_mbn_size); TESTS_WITH_DATA(test_signed_mbn_encode); TESTS_WITH_DATA(test_signed_mbn_decode_ok); TESTS_WITH_DATA(test_signed_mbn_decode_fail); TESTS_WITH_DATA(test_unsigned_mbn_size); TESTS_WITH_DATA(test_unsigned_mbn_encode); TESTS_WITH_DATA(test_unsigned_mbn_decode_ok); TESTS_WITH_DATA(test_unsigned_mbn_decode_fail); TESTS_WITH_DATA(test_tlv_size); TESTS_WITH_DATA(test_tlv_encode); TESTS_WITH_DATA(test_tlv_decode_ok); TESTS_WITH_DATA(test_tlv_decode_fail); TESTS_WITH_DATA(test_tlvs_decode); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000040000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000003100000000libglibutil-1714660956.7df665e/test/test_history07070100000041000081A40000000000000000000000016633A65C0000004F000000000000000000000000000000000000003A00000000libglibutil-1714660956.7df665e/test/test_history/Makefile# -*- Mode: makefile-gmake -*- EXE = test_history include ../common/Makefile 07070100000042000081A40000000000000000000000016633A65C00002752000000000000000000000000000000000000004000000000libglibutil-1714660956.7df665e/test/test_history/test_history.c/* * Copyright (C) 2017 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jolla Ltd nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include "gutil_history.h" static TestOpt test_opt; static gint64 test_history_time; static gint64 test_history_time_func(void) { return test_history_time; } /*==========================================================================* * NULL tolerance *==========================================================================*/ static void test_history_null( void) { gutil_int_history_unref(NULL); gutil_int_history_clear(NULL); g_assert(!gutil_int_history_ref(NULL)); g_assert(!gutil_int_history_size(NULL)); g_assert(!gutil_int_history_interval(NULL)); g_assert(!gutil_int_history_add(NULL, 1)); g_assert(!gutil_int_history_median(NULL, 0)); g_assert(!gutil_int_history_new(0, 0)); g_assert(!gutil_int_history_new(1, 0)); g_assert(!gutil_int_history_new(0, 1)); } /*==========================================================================* * Basic *==========================================================================*/ static void test_history_basic( void) { /* The default time functon returns real time, not usable for testing */ GUtilIntHistory* h = gutil_int_history_new(1, 1); g_assert(gutil_int_history_size(h) == 0); g_assert(gutil_int_history_interval(h) == 0); gutil_int_history_unref(gutil_int_history_ref(h)); gutil_int_history_unref(h); } /*==========================================================================* * Clear *==========================================================================*/ static void test_history_clear( void) { GUtilIntHistory* h = gutil_int_history_new_full(2, 2, test_history_time_func); g_assert(gutil_int_history_median(h, 0) == 0); test_history_time = 2; g_assert(gutil_int_history_add(h, 1) == 1); /* Time hasn't changed, 1 is replaced with 2 */ g_assert(gutil_int_history_add(h, 2) == 2); /* Time goes back, 2 is replaced with 3 */ test_history_time -=1; g_assert(gutil_int_history_add(h, 3) == 3); test_history_time += 2; g_assert(gutil_int_history_add(h, 5) == 4); g_assert(gutil_int_history_size(h) == 2); g_assert(gutil_int_history_median(h, 0) == 4); g_assert(gutil_int_history_interval(h) == 1); gutil_int_history_clear(h); g_assert(!gutil_int_history_size(h)); g_assert(!gutil_int_history_interval(h)); gutil_int_history_unref(h); } /*==========================================================================* * Median *==========================================================================*/ static void test_history_median( void) { GUtilIntHistory* h = gutil_int_history_new_full(2, 2, test_history_time_func); test_history_time = 1; g_assert(gutil_int_history_add(h, 1) == 1); test_history_time += 1; g_assert(gutil_int_history_add(h, 5) == 3); test_history_time += 1; /* Still the same, both ends of the interval are inclusive */ g_assert(gutil_int_history_median(h, 0) == 3); test_history_time += 1; /* Now one entry expires */ g_assert(gutil_int_history_median(h, 0) == 5); test_history_time += 1; /* The last one expires too */ g_assert(gutil_int_history_median(h, 0) == 0); gutil_int_history_unref(h); } /*==========================================================================* * Size *==========================================================================*/ static void test_history_size( void) { GUtilIntHistory* h = gutil_int_history_new_full(2, 2, test_history_time_func); test_history_time = 1; g_assert(gutil_int_history_add(h, 1) == 1); test_history_time += 1; g_assert(gutil_int_history_add(h, 5) == 3); g_assert(gutil_int_history_size(h) == 2); test_history_time += 1; /* Still the same, both ends of the interval are inclusive */ g_assert(gutil_int_history_size(h) == 2); test_history_time += 1; /* Now one entry expires */ g_assert(gutil_int_history_size(h) == 1); test_history_time += 1; /* The last one expires too */ g_assert(gutil_int_history_size(h) == 0); gutil_int_history_unref(h); } /*==========================================================================* * Interval *==========================================================================*/ static void test_history_interval( void) { GUtilIntHistory* h = gutil_int_history_new_full(2, 3, test_history_time_func); test_history_time = 1; g_assert(gutil_int_history_add(h, 1) == 1); test_history_time += 1; g_assert(gutil_int_history_add(h, 5) == 3); g_assert(gutil_int_history_interval(h) == 1); test_history_time += 1; /* Both ends of the interval are inclusive */ g_assert(gutil_int_history_interval(h) == 2); test_history_time += 2; /* Now one entry with timestamp 1 expires, the one remaining has * timestamp 2, the current time is 5 so the interval becomes 3 */ g_assert(gutil_int_history_interval(h) == 3); test_history_time += 1; /* The last one expires too */ g_assert(gutil_int_history_interval(h) == 0); gutil_int_history_unref(h); } /*==========================================================================* * Data *==========================================================================*/ typedef struct test_history_sample { gint64 time; int value; int median; } TestHistorySample; typedef struct test_history_data { int max_size; gint64 max_interval; const TestHistorySample* samples; int count; guint size; gint64 interval; } TestHistoryData; static void test_history_data( gconstpointer test_data) { int i; const TestHistoryData* data = test_data; GUtilIntHistory* h = gutil_int_history_new_full(data->max_size, data->max_interval, test_history_time_func); for (i=0; i<data->count; i++) { const TestHistorySample* sample = data->samples + i; test_history_time = sample->time; g_assert(gutil_int_history_add(h, sample->value) == sample->median); } g_assert(gutil_int_history_size(h) == data->size); g_assert(gutil_int_history_interval(h) == data->interval); test_history_time += data->max_interval + 1; g_assert(!gutil_int_history_size(h)); g_assert(!gutil_int_history_interval(h)); gutil_int_history_unref(h); } /*==========================================================================* * Common *==========================================================================*/ static const TestHistorySample samples1[] = {{1, 1, 1}}; static const TestHistoryData data1 = { 1, 1, samples1, G_N_ELEMENTS(samples1), 1, 0 }; static const TestHistorySample samples2[] = {{1, 1, 1}, {3, 2, 2}}; static const TestHistoryData data2 = { 1, 1, samples2, G_N_ELEMENTS(samples2), 1, 0 }; static const TestHistorySample samples3[] = { {1, 2, 2}, {3, 2, 2}, {4, 8, 3} }; static const TestHistoryData data3 = { 3, 4, samples3, G_N_ELEMENTS(samples3), 3, 3 }; static const TestHistorySample samples4[] = { {1, 2, 2}, {3, 2, 2}, {4, 8, 5} }; static const TestHistoryData data4 = { 3, 2, samples4, G_N_ELEMENTS(samples4), 2, 1 }; static const TestHistorySample samples5[] = { {1, 2, 2}, {3, 2, 2}, {4, 8, 5} }; static const TestHistoryData data5 = { 2, 4, samples5, G_N_ELEMENTS(samples5), 2, 1 }; #define TEST_PREFIX "/history/" int main(int argc, char* argv[]) { g_test_init(&argc, &argv, NULL); g_test_add_func(TEST_PREFIX "null", test_history_null); g_test_add_func(TEST_PREFIX "basic", test_history_basic); g_test_add_func(TEST_PREFIX "clear", test_history_clear); g_test_add_func(TEST_PREFIX "median", test_history_median); g_test_add_func(TEST_PREFIX "size", test_history_size); g_test_add_func(TEST_PREFIX "interval", test_history_interval); g_test_add_data_func(TEST_PREFIX "data1", &data1, test_history_data); g_test_add_data_func(TEST_PREFIX "data2", &data2, test_history_data); g_test_add_data_func(TEST_PREFIX "data3", &data3, test_history_data); g_test_add_data_func(TEST_PREFIX "data4", &data4, test_history_data); g_test_add_data_func(TEST_PREFIX "data5", &data5, test_history_data); test_init(&test_opt, argc, argv); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000043000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000003200000000libglibutil-1714660956.7df665e/test/test_idlepool07070100000044000081A40000000000000000000000016633A65C00000050000000000000000000000000000000000000003B00000000libglibutil-1714660956.7df665e/test/test_idlepool/Makefile# -*- Mode: makefile-gmake -*- EXE = test_idlepool include ../common/Makefile 07070100000045000081A40000000000000000000000016633A65C000032B4000000000000000000000000000000000000004200000000libglibutil-1714660956.7df665e/test/test_idlepool/test_idlepool.c/* * Copyright (C) 2016-2024 Slava Monich <slava@monich.com> * Copyright (C) 2016-2018 Jolla Ltd. * * You may use this file under the terms of the BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include "gutil_idlepool.h" #include "gutil_strv.h" #include "gutil_log.h" #define TEST_TIMEOUT_SEC (10) /* seconds */ static TestOpt test_opt; static gboolean test_timeout( gpointer loop) { g_assert(!"TIMEOUT"); return G_SOURCE_REMOVE; } static void test_done( gpointer loop) { g_main_loop_quit(loop); } static gboolean test_done_cb( gpointer loop) { g_main_loop_quit(loop); return G_SOURCE_REMOVE; } /*==========================================================================* * Test thread *==========================================================================*/ typedef struct test_thread TestThread; typedef void (*ThreadBeforeProc)( TestThread* thread, gpointer user_data); struct test_thread { GThread* thread; GMutex mutex; GCond start_cond; GMainLoop* loop; GMainContext* context; ThreadBeforeProc before_proc; gpointer before_data; }; static gpointer test_thread_proc( gpointer user_data) { TestThread* thread = user_data; GMainLoop* loop = g_main_loop_ref(thread->loop); GMainContext* context = g_main_context_ref(thread->context); /* Invoke this callback before pushing GMainContext */ if (thread->before_proc) { thread->before_proc(thread, thread->before_data); } /* Lock */ g_mutex_lock(&thread->mutex); g_main_context_push_thread_default(context); g_cond_broadcast(&thread->start_cond); GDEBUG("Test thread started"); g_mutex_unlock(&thread->mutex); /* Unlock */ g_main_loop_run(loop); g_main_loop_unref(loop); g_main_context_pop_thread_default(context); g_main_context_unref(context); GDEBUG("Test thread exiting"); return NULL; } static TestThread* test_thread_new( ThreadBeforeProc before_proc, gpointer before_data) { TestThread* thread = g_new0(TestThread, 1); g_cond_init(&thread->start_cond); g_mutex_init(&thread->mutex); thread->context = g_main_context_new(); thread->loop = g_main_loop_new(thread->context, FALSE); thread->before_proc = before_proc; thread->before_data = before_data; /* Lock */ g_mutex_lock(&thread->mutex); thread->thread = g_thread_new("test", test_thread_proc, thread); g_assert(g_cond_wait_until(&thread->start_cond, &thread->mutex, g_get_monotonic_time() + TEST_TIMEOUT_SEC * G_TIME_SPAN_SECOND)); g_mutex_unlock(&thread->mutex); /* Unlock */ return thread; } static void test_thread_invoke_later( TestThread* thread, GSourceFunc fn, gpointer user_data) { GSource* src = g_idle_source_new(); g_source_set_priority(src, G_PRIORITY_DEFAULT); g_source_set_callback(src, fn, user_data, NULL); g_source_attach(src, thread->context); g_source_unref(src); } static void test_thread_free( TestThread* thread) { g_main_loop_quit(thread->loop); g_thread_join(thread->thread); g_main_loop_unref(thread->loop); g_main_context_unref(thread->context); g_cond_clear(&thread->start_cond); g_mutex_clear(&thread->mutex); g_free(thread); } /*==========================================================================* * Null *==========================================================================*/ static void test_null( void) { GUtilIdlePool* pool = gutil_idle_pool_new(); /* These have no effect, just testing NULL-telerance */ gutil_idle_pool_add_strv(NULL, NULL); gutil_idle_pool_add_strv(pool, NULL); gutil_idle_pool_add_ptr_array(NULL, NULL); gutil_idle_pool_add_ptr_array(pool, NULL); gutil_idle_pool_add_ptr_array_ref(NULL, NULL); gutil_idle_pool_add_ptr_array_ref(pool, NULL); gutil_idle_pool_add_variant(NULL, NULL); gutil_idle_pool_add_variant(pool, NULL); gutil_idle_pool_add_variant_ref(NULL, NULL); gutil_idle_pool_add_variant_ref(pool, NULL); gutil_idle_pool_add_object(NULL, NULL); gutil_idle_pool_add_object(pool, NULL); gutil_idle_pool_add_object_ref(NULL, NULL); gutil_idle_pool_add_object_ref(pool, NULL); gutil_idle_pool_add_bytes(NULL, NULL); gutil_idle_pool_add_bytes(pool, NULL); gutil_idle_pool_add_bytes_ref(NULL, NULL); gutil_idle_pool_add_bytes_ref(pool, NULL); gutil_idle_pool_add(NULL, NULL, NULL); gutil_idle_pool_add(pool, NULL, NULL); gutil_idle_pool_ref(NULL); gutil_idle_pool_unref(NULL); gutil_idle_pool_drain(NULL); gutil_idle_pool_destroy(NULL); gutil_idle_pool_unref(pool); } /*==========================================================================* * Basic *==========================================================================*/ typedef struct test_basic { GUtilIdlePool* pool; gboolean array_free_count; gboolean ok; } TestBasic; static void test_basic_array_free( gpointer param) { TestBasic* test = param; test->array_free_count++; } static void test_basic_unref_pool( gpointer param) { TestBasic* test = param; gutil_idle_pool_unref(test->pool); } static void test_basic_last( gpointer param) { TestBasic* test = param; if (test->array_free_count == 1) { test->ok = TRUE; } } static void test_basic_add_during_drain( gpointer param) { /* Add an item when pool is being drained */ TestBasic* test = param; gutil_idle_pool_add(test->pool, test, test_basic_last); } static void test_basic( void) { GPtrArray* array = g_ptr_array_new_with_free_func(test_basic_array_free); GVariant* variant = g_variant_take_ref(g_variant_new_int32(1)); GObject* object = g_object_new(TEST_OBJECT_TYPE, NULL); GMainLoop* loop = g_main_loop_new(NULL, TRUE); GStrV* strv = gutil_strv_add(NULL, "foo"); GBytes* bytes = g_bytes_new("bar", 3); TestBasic test; memset(&test, 0, sizeof(test)); test.pool = gutil_idle_pool_new(); if (!(test_opt.flags & TEST_FLAG_DEBUG)) { g_timeout_add_seconds(TEST_TIMEOUT_SEC, test_timeout, loop); } gutil_idle_pool_unref(gutil_idle_pool_new()); gutil_idle_pool_add_strv(test.pool, strv); g_ptr_array_add(array, &test); gutil_idle_pool_add_ptr_array_ref(test.pool, array); g_ptr_array_unref(array); gutil_idle_pool_add_variant_ref(test.pool, variant); g_variant_unref(variant); gutil_idle_pool_add_object_ref(test.pool, object); g_object_unref(object); gutil_idle_pool_add_bytes_ref(test.pool, bytes); g_bytes_unref(bytes); gutil_idle_pool_ref(test.pool); gutil_idle_pool_add(test.pool, &test, test_basic_unref_pool); gutil_idle_pool_add(test.pool, loop, test_done); g_main_loop_run(loop); gutil_idle_pool_add(test.pool, &test, test_basic_add_during_drain); gutil_idle_pool_destroy(test.pool); g_assert(test.ok); g_assert(!test_object_count); g_main_loop_unref(loop); } /*==========================================================================* * Shared *==========================================================================*/ static void test_shared( void) { GUtilIdlePool* shared = NULL; GUtilIdlePool* pool = gutil_idle_pool_get(&shared); GUtilIdlePool* pool2 = gutil_idle_pool_get(NULL); GMainLoop* loop = g_main_loop_new(NULL, TRUE); g_assert(shared == pool); g_assert(gutil_idle_pool_get(&shared) == pool); g_assert(pool2 != pool); if (!(test_opt.flags & TEST_FLAG_DEBUG)) { g_timeout_add_seconds(TEST_TIMEOUT_SEC, test_timeout, loop); } /* The pool invokes the callback and destroys itself */ gutil_idle_pool_add(pool, loop, test_done); g_main_loop_run(loop); g_assert(!shared); gutil_idle_pool_unref(pool2); g_main_loop_unref(loop); } /*==========================================================================* * Default *==========================================================================*/ typedef struct test_default_data { GMainLoop* loop; TestThread* thread; int step; } TestDefault; static void test_default_1( gpointer user_data) { TestDefault* test = user_data; g_assert(g_main_context_get_thread_default()); g_assert_cmpint(test->step, == ,1); test->step++; } static void test_default_2( gpointer user_data) { TestDefault* test = user_data; /* This function is invoked on the test thread */ g_assert(test->thread->thread == g_thread_self()); g_assert_cmpint(test->step, == ,2); test->step++; g_idle_add(test_done_cb, test->loop); } static gboolean test_default_proc( gpointer user_data) { TestDefault* test = user_data; GUtilIdlePool* pool = gutil_idle_pool_get_default(); /* This function is invoked on the test thread */ g_assert(test->thread->thread == g_thread_self()); g_assert(pool == gutil_idle_pool_get_default()); gutil_idle_pool_add(pool, test, test_default_2); return G_SOURCE_REMOVE; } static gboolean test_default_main( gpointer user_data) { TestDefault* test = user_data; /* * This function is invoked on the main thread. * test_default_proc will add an item to the thread specific pool * on the test thread, which will schedule gutil_idle_pool_idle * in the right context and eventually invoke test_default_1 and * test_default_2 on the test thread in the right order. */ test_thread_invoke_later(test->thread, test_default_proc, test); return G_SOURCE_REMOVE; } static void test_default_start( TestThread* thread, gpointer user_data) { TestDefault* test = user_data; GUtilIdlePool* pool = gutil_idle_pool_get_default(); g_assert_cmpint(test->step, == ,0); test->step++; g_assert(!g_main_context_get_thread_default()); g_assert(pool == gutil_idle_pool_get_default()); /* This schedules gutil_idle_pool_idle on the main thread */ gutil_idle_pool_add(NULL /* use default */, test, test_default_1); /* * This will invoke test_default_main on the main thread after * gutil_idle_pool_idle */ g_idle_add(test_default_main, test); } static void test_default( void) { TestDefault test; memset(&test, 0, sizeof(test)); test.loop = g_main_loop_new(NULL, TRUE); test.thread = test_thread_new(test_default_start, &test); if (!(test_opt.flags & TEST_FLAG_DEBUG)) { g_timeout_add_seconds(TEST_TIMEOUT_SEC, test_timeout, test.loop); } g_main_loop_run(test.loop); test_thread_free(test.thread); g_assert_cmpint(test.step, == ,3); g_main_loop_unref(test.loop); } /*==========================================================================* * Common *==========================================================================*/ #define TEST_(test) "/idlepool/" test int main(int argc, char* argv[]) { G_GNUC_BEGIN_IGNORE_DEPRECATIONS; g_type_init(); G_GNUC_END_IGNORE_DEPRECATIONS; g_test_init(&argc, &argv, NULL); g_test_add_func(TEST_("null"), test_null); g_test_add_func(TEST_("basic"), test_basic); g_test_add_func(TEST_("shared"), test_shared); g_test_add_func(TEST_("default"), test_default); test_init(&test_opt, argc, argv); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000046000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000003300000000libglibutil-1714660956.7df665e/test/test_idlequeue07070100000047000081A40000000000000000000000016633A65C00000051000000000000000000000000000000000000003C00000000libglibutil-1714660956.7df665e/test/test_idlequeue/Makefile# -*- Mode: makefile-gmake -*- EXE = test_idlequeue include ../common/Makefile 07070100000048000081A40000000000000000000000016633A65C00002284000000000000000000000000000000000000004400000000libglibutil-1714660956.7df665e/test/test_idlequeue/test_idlequeue.c/* * Copyright (C) 2017 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jolla Ltd nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include "gutil_idlequeue.h" #include "gutil_log.h" #define TEST_TIMEOUT (10) /* seconds */ static TestOpt test_opt; static void test_idlequeue_noooo( gpointer param) { g_assert(!"NOOO!!!"); } static gboolean test_idlequeue_timeout( gpointer param) { g_assert(!"TIMEOUT"); return G_SOURCE_REMOVE; } static void test_idlequeue_loop_quit( gpointer loop) { g_main_loop_quit(loop); } static void test_idlequeue_int_inc( gpointer data) { int* ptr = data; (*ptr)++; } /*==========================================================================* * Null *==========================================================================*/ static void test_idlequeue_null( void) { /* Test NULL tolerance */ int i = 0; g_assert(!gutil_idle_queue_ref(NULL)); gutil_idle_queue_unref(NULL); gutil_idle_queue_free(NULL); g_assert(!gutil_idle_queue_contains_tag(NULL, 0)); g_assert(!gutil_idle_queue_cancel_tag(NULL, 0)); gutil_idle_queue_cancel_all(NULL); gutil_idle_queue_add(NULL, NULL, NULL); gutil_idle_queue_add_full(NULL, NULL, NULL, NULL); gutil_idle_queue_add_tag(NULL, 0, NULL, NULL); gutil_idle_queue_add_tag_full(NULL, 0, NULL, NULL, NULL); /* IF queue is NULL, the destroy function gets invoked immediately: */ gutil_idle_queue_add_tag_full(NULL, 0, NULL, &i, test_idlequeue_int_inc); g_assert(i == 1); } /*==========================================================================* * Basic *==========================================================================*/ static void test_idlequeue_basic( void) { guint timeout_id = 0; int count = 0; GUtilIdleQueue* q = gutil_idle_queue_new(); GMainLoop* loop = g_main_loop_new(NULL, TRUE); gutil_idle_queue_unref(gutil_idle_queue_ref(q)); gutil_idle_queue_add_tag_full(q, 1, test_idlequeue_int_inc, &count, NULL); gutil_idle_queue_add_tag_full(q, 2, NULL, &count, test_idlequeue_int_inc); gutil_idle_queue_add_tag_full(q, 3, test_idlequeue_loop_quit, loop, NULL); g_assert(!gutil_idle_queue_contains_tag(q, 0)); g_assert(gutil_idle_queue_contains_tag(q, 1)); g_assert(gutil_idle_queue_contains_tag(q, 2)); g_assert(gutil_idle_queue_contains_tag(q, 3)); if (!(test_opt.flags & TEST_FLAG_DEBUG)) { timeout_id = g_timeout_add_seconds(TEST_TIMEOUT, test_idlequeue_timeout, NULL); } g_main_loop_run(loop); g_assert(count == 2); if (timeout_id) { g_source_remove(timeout_id); } gutil_idle_queue_unref(q); g_main_loop_unref(loop); } /*==========================================================================* * Add *==========================================================================*/ typedef struct test_idlequeue_add_data { GUtilIdleQueue* q; GMainLoop* loop; } TestAdd; static void test_idlequeue_add_cb( gpointer data) { /* Adding new item from the callback */ TestAdd* test = data; gutil_idle_queue_add(test->q, test_idlequeue_loop_quit, test->loop); } static void test_idlequeue_add( void) { guint timeout_id = 0; TestAdd test; test.q = gutil_idle_queue_new(); test.loop = g_main_loop_new(NULL, TRUE); if (!(test_opt.flags & TEST_FLAG_DEBUG)) { timeout_id = g_timeout_add_seconds(TEST_TIMEOUT, test_idlequeue_timeout, NULL); } gutil_idle_queue_add(test.q, test_idlequeue_add_cb, &test); g_main_loop_run(test.loop); if (timeout_id) { g_source_remove(timeout_id); } gutil_idle_queue_unref(test.q); g_main_loop_unref(test.loop); } /*==========================================================================* * Cancel *==========================================================================*/ static void test_idlequeue_cancel( void) { int count = 0; GUtilIdleQueue* q = gutil_idle_queue_new(); /* Destroying the queue cancels the callbacks */ gutil_idle_queue_add(q, test_idlequeue_int_inc, &count); gutil_idle_queue_add_full(q, NULL, &count, test_idlequeue_int_inc); gutil_idle_queue_add_full(q, NULL, &count, test_idlequeue_int_inc); gutil_idle_queue_unref(q); g_assert(count == 2); count = 0; /* Cancelling all requests in an empty queue has no effect */ q = gutil_idle_queue_new(); gutil_idle_queue_cancel_all(q); /* Cancel by tag */ gutil_idle_queue_add_tag_full(q, 1, NULL, &count, test_idlequeue_int_inc); gutil_idle_queue_add_tag_full(q, 2, NULL, &count, test_idlequeue_int_inc); gutil_idle_queue_add_tag_full(q, 3, NULL, &count, test_idlequeue_int_inc); gutil_idle_queue_add_tag_full(q, 4, NULL, &count, test_idlequeue_int_inc); g_assert(!gutil_idle_queue_cancel_tag(q, 0)); g_assert(gutil_idle_queue_cancel_tag(q, 3)); g_assert(gutil_idle_queue_cancel_tag(q, 4)); g_assert(gutil_idle_queue_cancel_tag(q, 1)); g_assert(gutil_idle_queue_cancel_tag(q, 2)); g_assert(!gutil_idle_queue_cancel_tag(q, 1)); g_assert(count == 4); count = 0; gutil_idle_queue_free(q); } /*==========================================================================* * CancelAll *==========================================================================*/ static void test_idlequeue_cancel_all_submit_new( gpointer q) { /* Adding new item from the destroy callback */ gutil_idle_queue_add_tag(q, 42, test_idlequeue_noooo, NULL); } static void test_idlequeue_cancel_all( void) { int count = 0; GUtilIdleQueue* q = gutil_idle_queue_new(); /* Add new item from the destroy callback */ gutil_idle_queue_add(q, test_idlequeue_int_inc, &count); gutil_idle_queue_add_tag_full(q, 1, NULL, &count, test_idlequeue_int_inc); gutil_idle_queue_add_tag_full(q, 2, NULL, q, test_idlequeue_cancel_all_submit_new); gutil_idle_queue_cancel_all(q); g_assert(count == 1); /* We should still have 42 in there */ g_assert(!gutil_idle_queue_contains_tag(q, 1)); g_assert(!gutil_idle_queue_contains_tag(q, 2)); g_assert(gutil_idle_queue_contains_tag(q, 42)); gutil_idle_queue_cancel_all(q); /* Now it has to be really empty */ g_assert(!gutil_idle_queue_contains_tag(q, 42)); gutil_idle_queue_free(q); } /*==========================================================================* * Common *==========================================================================*/ #define TEST_PREFIX "/idlequeue/" int main(int argc, char* argv[]) { G_GNUC_BEGIN_IGNORE_DEPRECATIONS; g_type_init(); G_GNUC_END_IGNORE_DEPRECATIONS; g_test_init(&argc, &argv, NULL); g_test_add_func(TEST_PREFIX "null", test_idlequeue_null); g_test_add_func(TEST_PREFIX "basic", test_idlequeue_basic); g_test_add_func(TEST_PREFIX "add", test_idlequeue_add); g_test_add_func(TEST_PREFIX "cancel", test_idlequeue_cancel); g_test_add_func(TEST_PREFIX "cancel_all", test_idlequeue_cancel_all); test_init(&test_opt, argc, argv); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000049000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000003100000000libglibutil-1714660956.7df665e/test/test_inotify0707010000004A000081A40000000000000000000000016633A65C0000004F000000000000000000000000000000000000003A00000000libglibutil-1714660956.7df665e/test/test_inotify/Makefile# -*- Mode: makefile-gmake -*- EXE = test_inotify include ../common/Makefile 0707010000004B000081A40000000000000000000000016633A65C00002852000000000000000000000000000000000000004000000000libglibutil-1714660956.7df665e/test/test_inotify/test_inotify.c/* * Copyright (C) 2016-2017 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Jolla Ltd nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include "gutil_inotify.h" #include "gutil_macros.h" #include "gutil_log.h" #include <sys/inotify.h> #define TEST_TIMEOUT (10) /* seconds */ #define TMP_DIR_TEMPLATE "test_inotify_XXXXXX" static TestOpt test_opt; typedef struct test_inotify { const char* name; GMainLoop* loop; GUtilInotifyWatch* watch1; GUtilInotifyWatch* watch2; char* dir1; char* dir2; guint timeout_id; gboolean array_free_count; gboolean ok; } TestInotify; static gboolean test_inotify_timeout( gpointer param) { TestInotify* test = param; GERR("%s TIMEOUT", test->name); test->timeout_id = 0; g_main_loop_quit(test->loop); return G_SOURCE_REMOVE; } static void test_inotify_common( TestInotify* test, gboolean (*init)(TestInotify* test), void (*deinit)(TestInotify* test)) { const int mask = IN_ALL_EVENTS | IN_ONLYDIR | IN_EXCL_UNLINK; test->ok = FALSE; test->dir1 = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL); test->dir2 = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL); test->watch1 = gutil_inotify_watch_new(test->dir1, mask); test->watch2 = gutil_inotify_watch_new(test->dir2, mask); GDEBUG("%s: directory 1: %s", test->name, test->dir1); GDEBUG("%s: directory 2: %s", test->name, test->dir2); /* Initialize the event loop */ test->loop = g_main_loop_new(NULL, TRUE); if (!(test_opt.flags & TEST_FLAG_DEBUG)) { test->timeout_id = g_timeout_add_seconds(TEST_TIMEOUT, test_inotify_timeout, test); } if (init) { init(test); } /* Run the event loop */ g_main_loop_run(test->loop); if (deinit) { deinit(test); } g_assert(test->ok); if (!(test_opt.flags & TEST_FLAG_DEBUG)) { g_assert(test->timeout_id); g_source_remove(test->timeout_id); } g_main_loop_unref(test->loop); gutil_inotify_watch_destroy(test->watch1); gutil_inotify_watch_destroy(test->watch2); remove(test->dir1); remove(test->dir2); g_free(test->dir1); g_free(test->dir2); } /*==========================================================================* * Basic *==========================================================================*/ static void test_inotify_basic( void) { char* dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL); GUtilInotifyWatch* watch = gutil_inotify_watch_new(dir, IN_ALL_EVENTS); /* These have no effect, just testing NULL-telerance */ g_assert(!gutil_inotify_watch_new(NULL, 0)); g_assert(!gutil_inotify_watch_ref(NULL)); gutil_inotify_watch_unref(NULL); gutil_inotify_watch_destroy(NULL); gutil_inotify_watch_remove_handler(NULL, 0); gutil_inotify_watch_remove_handler(watch, 0); g_assert(!gutil_inotify_watch_callback_new(NULL, 0, NULL, NULL)); g_assert(!gutil_inotify_watch_add_handler(NULL, NULL, NULL)); g_assert(!gutil_inotify_watch_add_handler(watch, NULL, NULL)); gutil_inotify_watch_destroy(watch); /* Remove the directory and try to watch it. That should fail */ remove(dir); g_assert(!gutil_inotify_watch_new(dir, IN_ALL_EVENTS)); g_free(dir); } /*==========================================================================* * Move *==========================================================================*/ typedef struct test_inotify_move { TestInotify test; const char* fname; char* dest; gulong id1; gulong id2; int from; } TestInotifyMove; static void test_inotify_move_from( GUtilInotifyWatch* watch, guint mask, guint cookie, const char* name, void* arg) { TestInotifyMove* move = arg; if ((mask & IN_MOVED_FROM) && !g_strcmp0(move->fname, name)) { GDEBUG("%s moved from %s", name, move->test.dir1); move->from++; } } static void test_inotify_move_to( GUtilInotifyWatch* watch, guint mask, guint cookie, const char* name, void* arg) { TestInotifyMove* move = arg; if ((mask & IN_MOVED_TO) && !g_strcmp0(move->fname, name)) { GDEBUG("%s moved to %s", name, move->test.dir2); if (move->from == 1) { move->test.ok = TRUE; g_main_loop_quit(move->test.loop); } } } static gboolean test_inotify_move_init( TestInotify* test) { TestInotifyMove* move = G_CAST(test, TestInotifyMove, test); char* src; move->fname = "test"; src = g_strconcat(test->dir1, G_DIR_SEPARATOR_S, move->fname, NULL); move->dest = g_strconcat(test->dir2, G_DIR_SEPARATOR_S, move->fname, NULL); move->id1 = gutil_inotify_watch_add_handler(test->watch1, test_inotify_move_from, move); move->id2 = gutil_inotify_watch_add_handler(test->watch2, test_inotify_move_to, move); g_file_set_contents(src, "contents", -1, NULL); GDEBUG("%s -> %s", src, move->dest); rename(src, move->dest); g_free(src); return TRUE; } static void test_inotify_move_deinit( TestInotify* test) { TestInotifyMove* move = G_CAST(test, TestInotifyMove, test); gutil_inotify_watch_remove_handler(test->watch1, move->id1); gutil_inotify_watch_remove_handler(test->watch2, move->id2); remove(move->dest); g_free(move->dest); } static void test_inotify_move( void) { TestInotifyMove move; memset(&move, 0, sizeof(move)); move.test.name = "move"; test_inotify_common(&move.test, test_inotify_move_init, test_inotify_move_deinit); } /*==========================================================================* * Callback *==========================================================================*/ typedef struct test_inotify_callback { TestInotify test; const char* fname; char* dest; GUtilInotifyWatchCallback* cb1; GUtilInotifyWatchCallback* cb2; int from; } TestInotifyCallback; static void test_inotify_callback_from( GUtilInotifyWatch* watch, guint mask, guint cookie, const char* name, void* arg) { TestInotifyCallback* cb = arg; if ((mask & IN_MOVED_FROM) && !g_strcmp0(cb->fname, name)) { GDEBUG("%s moved from %s", name, cb->test.dir1); cb->from++; } } static void test_inotify_callback_to( GUtilInotifyWatch* watch, guint mask, guint cookie, const char* name, void* arg) { TestInotifyCallback* cb = arg; if ((mask & IN_MOVED_TO) && !g_strcmp0(cb->fname, name)) { GDEBUG("%s moved to %s", name, cb->test.dir2); if (cb->from == 1) { cb->test.ok = TRUE; g_main_loop_quit(cb->test.loop); } } } static gboolean test_inotify_callback_init( TestInotify* test) { TestInotifyCallback* cb = G_CAST(test, TestInotifyCallback, test); char* src; cb->fname = "test"; src = g_strconcat(test->dir1, G_DIR_SEPARATOR_S, cb->fname, NULL); cb->dest = g_strconcat(test->dir2, G_DIR_SEPARATOR_S, cb->fname, NULL); cb->cb1 = gutil_inotify_watch_callback_new(test->dir1, IN_MOVED_FROM, test_inotify_callback_from, cb); cb->cb2 = gutil_inotify_watch_callback_new(test->dir2, IN_MOVED_TO, test_inotify_callback_to, cb); g_file_set_contents(src, "contents", -1, NULL); GDEBUG("%s -> %s", src, cb->dest); rename(src, cb->dest); g_free(src); return TRUE; } static void test_inotify_callback_deinit( TestInotify* test) { TestInotifyCallback* cb = G_CAST(test, TestInotifyCallback, test); gutil_inotify_watch_callback_free(cb->cb1); gutil_inotify_watch_callback_free(cb->cb2); gutil_inotify_watch_callback_free(NULL); remove(cb->dest); g_free(cb->dest); } static void test_inotify_callback( void) { TestInotifyCallback callback; memset(&callback, 0, sizeof(callback)); callback.test.name = "callback"; test_inotify_common(&callback.test, test_inotify_callback_init, test_inotify_callback_deinit); } /*==========================================================================* * Common *==========================================================================*/ #define TEST_PREFIX "/inotify/" int main(int argc, char* argv[]) { G_GNUC_BEGIN_IGNORE_DEPRECATIONS; g_type_init(); G_GNUC_END_IGNORE_DEPRECATIONS; g_test_init(&argc, &argv, NULL); g_test_add_func(TEST_PREFIX "basic", test_inotify_basic); g_test_add_func(TEST_PREFIX "move", test_inotify_move); g_test_add_func(TEST_PREFIX "callback", test_inotify_callback); test_init(&test_opt, argc, argv); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000004C000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000003200000000libglibutil-1714660956.7df665e/test/test_intarray0707010000004D000081A40000000000000000000000016633A65C00000050000000000000000000000000000000000000003B00000000libglibutil-1714660956.7df665e/test/test_intarray/Makefile# -*- Mode: makefile-gmake -*- EXE = test_intarray include ../common/Makefile 0707010000004E000081A40000000000000000000000016633A65C00002B0E000000000000000000000000000000000000004200000000libglibutil-1714660956.7df665e/test/test_intarray/test_intarray.c/* * Copyright (C) 2017 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jolla Ltd nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include "gutil_intarray.h" #include "gutil_ints.h" static TestOpt test_opt; /*==========================================================================* * NULL tolerance *==========================================================================*/ static void test_intarray_null( void) { gutil_int_array_unref(NULL); g_assert(!gutil_int_array_ref(NULL)); g_assert(!gutil_int_array_free(NULL, FALSE)); g_assert(!gutil_int_array_free_to_ints(NULL)); g_assert(!gutil_int_array_append(NULL, 0)); g_assert(!gutil_int_array_append_vals(NULL, NULL, 0)); g_assert(!gutil_int_array_prepend(NULL, 0)); g_assert(!gutil_int_array_prepend_vals(NULL, NULL, 0)); g_assert(!gutil_int_array_insert(NULL, 0, 0)); g_assert(!gutil_int_array_insert_vals(NULL, 0, NULL, 0)); g_assert(gutil_int_array_find(NULL, 0) == -1); g_assert(!gutil_int_array_contains(NULL, 0)); g_assert(!gutil_int_array_remove(NULL, 0)); g_assert(!gutil_int_array_remove_fast(NULL, 0)); g_assert(!gutil_int_array_remove_all(NULL, 0)); g_assert(!gutil_int_array_remove_all_fast(NULL, 0)); g_assert(!gutil_int_array_set_count(NULL, 0)); g_assert(!gutil_int_array_remove_index(NULL, 0)); g_assert(!gutil_int_array_remove_index_fast(NULL, 0)); g_assert(!gutil_int_array_remove_range(NULL, 0, 0)); gutil_int_array_sort_ascending(NULL); gutil_int_array_sort_descending(NULL); } /*==========================================================================* * Basic *==========================================================================*/ static void test_intarray_basic( void) { static const int vals[] = { 0, 1, 2 }; GUtilIntArray* a = gutil_int_array_new(); GUtilInts* ints; g_assert(gutil_int_array_append(a, 0) == a); g_assert(a->count == 1); g_assert(a->data[0] == 0); g_assert(gutil_int_array_append(a, 1) == a); g_assert(a->count == 2); g_assert(a->data[0] == 0); g_assert(a->data[1] == 1); g_assert(gutil_int_array_prepend(a, 2) == a); g_assert(a->count == 3); g_assert(a->data[0] == 2); g_assert(a->data[1] == 0); g_assert(a->data[2] == 1); gutil_int_array_sort_ascending(a); g_assert(a->data[0] == 0); g_assert(a->data[1] == 1); g_assert(a->data[2] == 2); gutil_int_array_sort_descending(a); g_assert(a->data[0] == 2); g_assert(a->data[1] == 1); g_assert(a->data[2] == 0); g_assert(gutil_int_array_remove_index_fast(a, 0) == a); g_assert(a->count == 2); g_assert(a->data[0] == 0); g_assert(a->data[1] == 1); g_assert(gutil_int_array_remove_range(a, 1, 2) == a); g_assert(a->count == 1); g_assert(a->data[0] == 0); /* This removes nothing (position out of range) */ g_assert(gutil_int_array_remove_range(a, 1, 2) == a); g_assert(a->count == 1); g_assert(a->data[0] == 0); /* This too (zero count) */ g_assert(gutil_int_array_remove_range(a, 0, 0) == a); g_assert(a->count == 1); g_assert(a->data[0] == 0); g_assert(gutil_int_array_remove_range(a, 0, 1) == a); g_assert(a->count == 0); g_assert(gutil_int_array_insert(a, 0, 0) == a); g_assert(gutil_int_array_insert(a, 0, 1) == a); g_assert(a->count == 2); g_assert(a->data[0] == 1); g_assert(a->data[1] == 0); g_assert(gutil_int_array_insert(a, 2, 2) == a); g_assert(a->count == 3); g_assert(a->data[0] == 1); g_assert(a->data[1] == 0); g_assert(a->data[2] == 2); g_assert(gutil_int_array_set_count(a, 2) == a); g_assert(a->count == 2); g_assert(a->data[0] == 1); g_assert(a->data[1] == 0); g_assert(gutil_int_array_remove_index(a, 0) == a); g_assert(a->count == 1); g_assert(a->data[0] == 0); g_assert(gutil_int_array_remove_index(a, 1) == a); g_assert(a->count == 1); g_assert(a->data[0] == 0); gutil_int_array_ref(a); gutil_int_array_free(a, TRUE); g_assert(!a->data); g_assert(!a->count); gutil_int_array_unref(a); a = gutil_int_array_sized_new(0); g_assert(!gutil_int_array_free(a, FALSE)); a = gutil_int_array_sized_new(0); g_assert(!gutil_int_array_free_to_ints(a)); a = gutil_int_array_sized_new(G_N_ELEMENTS(vals)); g_assert(gutil_int_array_append_vals(a, vals, G_N_ELEMENTS(vals)) == a); g_assert(a->count == G_N_ELEMENTS(vals)); g_assert(!memcmp(a->data, vals, sizeof(vals))); ints = gutil_int_array_free_to_ints(a); g_assert(gutil_ints_get_count(ints) == G_N_ELEMENTS(vals)); g_assert(!memcmp(gutil_ints_get_data(ints, NULL), vals, sizeof(vals))); gutil_ints_unref(ints); } /*==========================================================================* * Find *==========================================================================*/ static void test_intarray_find( void) { static const int vals[] = { 0, 1, 2 }; GUtilIntArray* a = gutil_int_array_new(); g_assert(gutil_int_array_append_vals(a, vals, G_N_ELEMENTS(vals)) == a); g_assert(gutil_int_array_find(a, -1) == -1); g_assert(gutil_int_array_find(a, 0) == 0); g_assert(gutil_int_array_find(a, 1) == 1); g_assert(gutil_int_array_find(a, 2) == 2); g_assert(gutil_int_array_find(a, 3) == -1); g_assert(gutil_int_array_contains(a, 2)); g_assert(!gutil_int_array_contains(a, 3)); gutil_int_array_unref(a); } /*==========================================================================* * Remove *==========================================================================*/ static void test_intarray_remove_1( const int* vals, guint n, gboolean (*f)(GUtilIntArray* array, int value), int value, const int* result) { GUtilIntArray* a = gutil_int_array_new_from_vals(vals, n); g_assert(f(a, value)); g_assert(a->count == n - 1); g_assert(!memcmp(a->data, result, sizeof(a->data[0]) * a->count)); gutil_int_array_unref(a); } static void test_intarray_remove( void) { static const int v[] = { 0, 1, 2, 4 }; static const int v0[] = { 1, 2, 4 }; static const int v1[] = { 0, 2, 4 }; static const int v4[] = { 0, 1, 2 }; static const int v0_fast[] = { 4, 1, 2 }; static const int v1_fast[] = { 0, 4, 2 }; const guint n = G_N_ELEMENTS(v); GUtilIntArray* a = gutil_int_array_new_from_value(-1); g_assert(a->count == 1); g_assert(!gutil_int_array_remove(a, 0)); g_assert(!gutil_int_array_remove_fast(a, 0)); gutil_int_array_unref(a); test_intarray_remove_1(v, n, gutil_int_array_remove, 0, v0); test_intarray_remove_1(v, n, gutil_int_array_remove, 1, v1); test_intarray_remove_1(v, n, gutil_int_array_remove, 4, v4); test_intarray_remove_1(v, n, gutil_int_array_remove_fast, 0, v0_fast); test_intarray_remove_1(v, n, gutil_int_array_remove_fast, 1, v1_fast); test_intarray_remove_1(v, n, gutil_int_array_remove_fast, 4, v4); } /*==========================================================================* * RemoveAll *==========================================================================*/ static void test_intarray_remove_all_1( const int* vals, guint n, guint (*f)(GUtilIntArray* array, int value), int value, guint removed, const int* result) { GUtilIntArray* a = gutil_int_array_new_from_vals(vals, n); g_assert(f(a, value) == removed); g_assert(a->count == n - removed); g_assert(!memcmp(a->data, result, sizeof(a->data[0]) * a->count)); gutil_int_array_unref(a); } static void test_intarray_remove_all( void) { static const int v[] = { 0, 1, 2, 1, 0 }; static const int v0[] = { 1, 2, 1 }; static const int v1[] = { 0, 2, 0 }; static const int v2[] = { 0, 1, 1, 0 }; static const int v0f[] = { 1, 1, 2 }; static const int v1f[] = { 0, 0, 2 }; static const int v2f[] = { 0, 1, 0, 1 }; const guint n = G_N_ELEMENTS(v); GUtilIntArray* a = gutil_int_array_new_from_value(-1); g_assert(a->count == 1); g_assert(!gutil_int_array_remove_all(a, 0)); g_assert(!gutil_int_array_remove_all_fast(a, 0)); gutil_int_array_unref(a); test_intarray_remove_all_1(v,n,gutil_int_array_remove_all,0,2,v0); test_intarray_remove_all_1(v,n,gutil_int_array_remove_all,1,2,v1); test_intarray_remove_all_1(v,n,gutil_int_array_remove_all,2,1,v2); test_intarray_remove_all_1(v,n,gutil_int_array_remove_all_fast,0,2,v0f); test_intarray_remove_all_1(v,n,gutil_int_array_remove_all_fast,1,2,v1f); test_intarray_remove_all_1(v,n,gutil_int_array_remove_all_fast,2,1,v2f); } /*==========================================================================* * Common *==========================================================================*/ #define TEST_PREFIX "/intarray/" int main(int argc, char* argv[]) { g_test_init(&argc, &argv, NULL); g_test_add_func(TEST_PREFIX "null", test_intarray_null); g_test_add_func(TEST_PREFIX "basic", test_intarray_basic); g_test_add_func(TEST_PREFIX "find", test_intarray_find); g_test_add_func(TEST_PREFIX "remove", test_intarray_remove); g_test_add_func(TEST_PREFIX "remove_all", test_intarray_remove_all); test_init(&test_opt, argc, argv); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000004F000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000002E00000000libglibutil-1714660956.7df665e/test/test_ints07070100000050000081A40000000000000000000000016633A65C0000004C000000000000000000000000000000000000003700000000libglibutil-1714660956.7df665e/test/test_ints/Makefile# -*- Mode: makefile-gmake -*- EXE = test_ints include ../common/Makefile 07070100000051000081A40000000000000000000000016633A65C00001E64000000000000000000000000000000000000003A00000000libglibutil-1714660956.7df665e/test/test_ints/test_ints.c/* * Copyright (C) 2017-2022 Jolla Ltd. * Copyright (C) 2017-2022 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include "gutil_ints.h" #include "gutil_misc.h" static TestOpt test_opt; /*==========================================================================* * NULL tolerance *==========================================================================*/ static void test_ints_null( void) { int val = 0; guint count; gutil_ints_unref(NULL); g_assert(!gutil_ints_ref(NULL)); g_assert(!gutil_ints_new(NULL, 0)); g_assert(!gutil_ints_new(NULL, 1)); g_assert(!gutil_ints_new(&val, 0)); g_assert(!gutil_ints_new_take(NULL, 0)); g_assert(!gutil_ints_new_take(NULL, 1)); g_assert(!gutil_ints_new_take(&val, 0)); g_assert(!gutil_ints_new_static(NULL, 0)); g_assert(!gutil_ints_new_static(NULL, 1)); g_assert(!gutil_ints_new_static(&val, 0)); g_assert(!gutil_ints_new_with_free_func(NULL, 0, NULL, NULL)); g_assert(!gutil_ints_new_with_free_func(NULL, 1, NULL, NULL)); g_assert(!gutil_ints_new_with_free_func(&val, 0, NULL, NULL)); g_assert(!gutil_ints_new_from_ints(NULL, 0, 0)); g_assert(!gutil_ints_hash(NULL)); g_assert(!gutil_ints_get_count(NULL)); g_assert(!gutil_ints_contains(NULL, 0)); g_assert(gutil_ints_find(NULL, 0) < 0); count = 1; g_assert(!gutil_ints_get_data(NULL, NULL)); g_assert(!gutil_ints_get_data(NULL, &count)); g_assert(!count); count = 1; g_assert(!gutil_ints_unref_to_data(NULL, NULL)); g_assert(!gutil_ints_unref_to_data(NULL, &count)); g_assert(!count); } /*==========================================================================* * Basic *==========================================================================*/ static void test_custom_free( gpointer data) { g_free(data); } static void test_ints_basic( void) { /* First 3 elements match */ const int a1[] = { 1, 2, 3 }; const int a2[] = { 1, 2, 3, 4 }; int* data; guint count; GUtilInts* i1 = gutil_ints_new(a1, G_N_ELEMENTS(a1)); GUtilInts* i2 = gutil_ints_new_static(a2, G_N_ELEMENTS(a2)); GUtilInts* i3; GUtilInts* i4; g_assert(gutil_ints_get_count(i1) == G_N_ELEMENTS(a1)); g_assert(gutil_ints_get_count(i2) == G_N_ELEMENTS(a2)); g_assert(gutil_ints_get_data(i1, NULL) != a2); g_assert(gutil_ints_get_data(i2, &count) == a2); g_assert(count == G_N_ELEMENTS(a2)); g_assert(!gutil_ints_new_from_ints(i1, G_N_ELEMENTS(a2), 1)); i3 = gutil_ints_new_from_ints(i1, 0, G_N_ELEMENTS(a1) + 1); i4 = gutil_ints_new_from_ints(i2, 0, G_N_ELEMENTS(a1)); g_assert(gutil_ints_equal(i1, i1)); g_assert(!gutil_ints_equal(i1, i2)); g_assert(gutil_ints_equal(i1, i3)); g_assert(gutil_ints_equal(i1, i3)); g_assert(!gutil_ints_contains(i1, 0)); g_assert(gutil_ints_contains(i1, 1)); g_assert(gutil_ints_find(i1, 0) < 0); g_assert(gutil_ints_find(i1, 1) == 0); g_assert(gutil_ints_find(i1, 2) == 1); /* This gutil_ints_unref_to_data doesn't actually free i1 because * a reference to it is held by i3: */ data = gutil_ints_unref_to_data(i1, &count); g_assert(count == G_N_ELEMENTS(a1)); g_assert(!memcmp(a1, data, count*sizeof(int))); g_free(data); gutil_ints_unref(i2); gutil_ints_unref(i3); gutil_ints_unref(i4); /* This gutil_ints_unref_to_data actually does free i1: */ i1 = gutil_ints_new(a1, G_N_ELEMENTS(a1)); data = gutil_ints_unref_to_data(i1, NULL); g_assert(!memcmp(a1, data, G_N_ELEMENTS(a1)*sizeof(int))); g_free(data); /* And this one duplicates the data because we use test_custom_free: */ data = gutil_memdup(a1, sizeof(a1)); i1 = gutil_ints_new_with_free_func(data, G_N_ELEMENTS(a1), test_custom_free, data); data = gutil_ints_unref_to_data(i1, &count); g_assert(count == G_N_ELEMENTS(a1)); g_assert(!memcmp(a1, data, count*sizeof(int))); g_free(data); } /*==========================================================================* * Compare *==========================================================================*/ static void test_ints_compare( void) { const int a1[] = { 1 }; const int a2[] = { 1, 2 }; const int a3[] = { 2 }; GUtilInts* i1 = gutil_ints_new_static(a1, G_N_ELEMENTS(a1)); GUtilInts* i2 = gutil_ints_new_static(a2, G_N_ELEMENTS(a2)); GUtilInts* i3 = gutil_ints_new_static(a3, G_N_ELEMENTS(a3)); GUtilInts* i4 = gutil_ints_new_from_ints(i1, 0, G_N_ELEMENTS(a1)); g_assert(gutil_ints_hash(i1) == 1235); g_assert(gutil_ints_hash(i2) == 1239); g_assert(gutil_ints_equal(NULL, NULL)); g_assert(!gutil_ints_equal(NULL, i1)); g_assert(!gutil_ints_equal(i1, NULL)); g_assert(!gutil_ints_equal(i1, i2)); g_assert(!gutil_ints_equal(i2, i1)); g_assert(!gutil_ints_equal(i1, i3)); g_assert(!gutil_ints_equal(i3, i1)); g_assert(gutil_ints_equal(i1, i4)); g_assert(gutil_ints_equal(i4, i1)); g_assert(gutil_ints_compare(NULL, NULL) == 0); g_assert(gutil_ints_compare(NULL, i1) < 0); g_assert(gutil_ints_compare(i1, NULL) > 0); g_assert(gutil_ints_compare(i1, i2) < 0); g_assert(gutil_ints_compare(i2, i1) > 0); g_assert(gutil_ints_compare(i1, i3) < 0); g_assert(gutil_ints_compare(i3, i1) > 0); g_assert(gutil_ints_compare(i1, i4) == 0); g_assert(gutil_ints_compare(i4, i1) == 0); gutil_ints_unref(i1); gutil_ints_unref(i2); gutil_ints_unref(i3); gutil_ints_unref(i4); } /*==========================================================================* * Common *==========================================================================*/ #define TEST_PREFIX "/ints/" int main(int argc, char* argv[]) { g_test_init(&argc, &argv, NULL); g_test_add_func(TEST_PREFIX "null", test_ints_null); g_test_add_func(TEST_PREFIX "basic", test_ints_basic); g_test_add_func(TEST_PREFIX "compare", test_ints_compare); test_init(&test_opt, argc, argv); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000052000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000002D00000000libglibutil-1714660956.7df665e/test/test_log07070100000053000081A40000000000000000000000016633A65C0000009F000000000000000000000000000000000000003600000000libglibutil-1714660956.7df665e/test/test_log/Makefile# -*- Mode: makefile-gmake -*- CFLAGS += -DGLOG_LEVEL_MAX=GLOG_LEVEL_VERBOSE -DGLOG_LEVEL_ASSERT=GLOG_LEVEL_ALWAYS EXE = test_log include ../common/Makefile 07070100000054000081A40000000000000000000000016633A65C000035EF000000000000000000000000000000000000003800000000libglibutil-1714660956.7df665e/test/test_log/test_log.c/* * Copyright (C) 2017-2023 Slava Monich <slava@monich.com> * Copyright (C) 2017-2022 Jolla Ltd. * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #define _GNU_SOURCE /* for fopencookie */ #include "test_common.h" #include "gutil_strv.h" #include "gutil_log.h" #ifdef __GLIBC__ /* glibc has writeable stdout */ # define HAVE_TEST_LOG_FILE #endif static TestOpt test_opt; static GString* test_log_buf; static void test_log_fn( const char* name, int level, const char* format, va_list va) { g_string_append_vprintf(test_log_buf, format, va); g_string_append_c(test_log_buf, '\n'); } /*==========================================================================* * Basic *==========================================================================*/ static void test_log_basic( void) { const GLogProc fn = gutil_log_func; const GLogProc2 fn2 = gutil_log_func2; const int level = gutil_log_default.level; GLOG_MODULE_DEFINE2_(module, "test", gutil_log_default); test_log_buf = g_string_new(NULL); gutil_log_func = test_log_fn; module.level = GLOG_LEVEL_INHERIT; gutil_log_default.level = GLOG_LEVEL_ERR; gutil_log(NULL, GLOG_LEVEL_NONE, "Debug!"); gutil_log(NULL, GLOG_LEVEL_DEBUG, "Debug!"); gutil_log(&module, GLOG_LEVEL_DEBUG, "Debug!"); gutil_log_assert(NULL, GLOG_LEVEL_WARN, "Test!", __FILE__, __LINE__); g_assert(!test_log_buf->len); gutil_log(&module, GLOG_LEVEL_ERR, "Err!"); g_assert(test_log_buf->len); g_string_set_size(test_log_buf, 0); /* With NULL parent, still gutil_log_default is going to be checked */ module.parent = NULL; gutil_log(NULL, GLOG_LEVEL_NONE, "Debug!"); gutil_log(NULL, GLOG_LEVEL_DEBUG, "Debug!"); gutil_log(&module, GLOG_LEVEL_DEBUG, "Debug!"); gutil_log_assert(NULL, GLOG_LEVEL_WARN, "Test!", __FILE__, __LINE__); g_assert(!test_log_buf->len); gutil_log(&module, GLOG_LEVEL_ERR, "Err!"); g_assert(test_log_buf->len); g_string_set_size(test_log_buf, 0); gutil_log(&module, GLOG_LEVEL_ALWAYS, "Always!"); g_assert(test_log_buf->len); g_string_set_size(test_log_buf, 0); /* Test GLOG_FLAG_DISABLE */ module.flags |= GLOG_FLAG_DISABLE; gutil_log(&module, GLOG_LEVEL_ALWAYS, "Always!"); g_assert(!test_log_buf->len); module.flags &= ~GLOG_FLAG_DISABLE; /* Without log functions these calls have no effect */ gutil_log_func = NULL; gutil_log(NULL, GLOG_LEVEL_ALWAYS, "Always!"); gutil_log_func2 = NULL; gutil_log(NULL, GLOG_LEVEL_ALWAYS, "Always!"); g_string_free(test_log_buf, TRUE); test_log_buf = NULL; gutil_log_default.level = level; gutil_log_func = fn; gutil_log_func2 = fn2; } /*==========================================================================* * File *==========================================================================*/ #ifdef HAVE_TEST_LOG_FILE static ssize_t test_log_file_write( void* buf, const char* chars, size_t size) { g_string_append_len(buf, chars, size); return size; } static void test_log_drop( const GLogModule* module, int level, const char* format, va_list va) { } static void test_log_file( void) { static const cookie_io_functions_t funcs = { .write = test_log_file_write }; GString* buf = g_string_new(NULL); FILE* out = fopencookie(buf, "w", funcs); FILE* default_stdout = stdout; const int level = gutil_log_default.level; gboolean use_timestamp; GLogProc2 log_proc; g_assert(out); g_assert(gutil_log_set_type(GLOG_TYPE_STDOUT, NULL)); g_assert(gutil_log_func == gutil_log_stdout); gutil_log_timestamp = FALSE; gutil_log_default.level = GLOG_LEVEL_WARN; /* Warning pefix */ stdout = out; gutil_log(NULL, GLOG_LEVEL_WARN, "Test"); stdout = default_stdout; g_assert(fflush(out) == 0); GDEBUG("%s", buf->str); g_assert_cmpstr(buf->str, == ,"WARNING: Test\n"); g_string_set_size(buf, 0); /* Error prefix */ stdout = out; gutil_log(NULL, GLOG_LEVEL_ERR, "Test"); stdout = default_stdout; g_assert(fflush(out) == 0); GDEBUG("%s", buf->str); g_assert_cmpstr(buf->str, == ,"ERROR: Test\n"); g_string_set_size(buf, 0); /* Empty name (dropped) */ gutil_log_default.name = ""; stdout = out; gutil_log(NULL, GLOG_LEVEL_ALWAYS, "Test"); stdout = default_stdout; g_assert(fflush(out) == 0); GDEBUG("%s", buf->str); g_assert_cmpstr(buf->str, == ,"Test\n"); g_string_set_size(buf, 0); /* Non-empty name */ gutil_log_default.name = "test"; stdout = out; gutil_log(NULL, GLOG_LEVEL_ALWAYS, "Test"); stdout = default_stdout; g_assert(fflush(out) == 0); GDEBUG("%s", buf->str); g_assert_cmpstr(buf->str, == ,"[test] Test\n"); g_string_set_size(buf, 0); /* Hide the name */ gutil_log_default.flags |= GLOG_FLAG_HIDE_NAME; stdout = out; gutil_log(NULL, GLOG_LEVEL_ALWAYS, "Test"); stdout = default_stdout; g_assert(fflush(out) == 0); GDEBUG("%s", buf->str); g_assert_cmpstr(buf->str, == ,"Test\n"); g_string_set_size(buf, 0); /* Timestamp prefix */ use_timestamp = gutil_log_timestamp; gutil_log_timestamp = TRUE; stdout = out; gutil_log_set_timestamp_format("timestamp1 "); gutil_log_set_timestamp_format("timestamp1 "); gutil_log(NULL, GLOG_LEVEL_ALWAYS, "test1"); stdout = default_stdout; g_assert(fflush(out) == 0); GDEBUG("%s", buf->str); g_assert_cmpstr(buf->str, == ,"timestamp1 test1\n"); g_string_set_size(buf, 0); stdout = out; gutil_log_set_timestamp_format("timestamp2 "); gutil_log(NULL, GLOG_LEVEL_ALWAYS, "test2"); stdout = default_stdout; g_assert(fflush(out) == 0); GDEBUG("%s", buf->str); g_assert_cmpstr(buf->str, == ,"timestamp2 test2\n"); g_string_set_size(buf, 0); stdout = out; gutil_log_set_timestamp_format(""); gutil_log(NULL, GLOG_LEVEL_ALWAYS, "test"); stdout = default_stdout; g_assert(fflush(out) == 0); GDEBUG("%s", buf->str); g_assert_cmpstr(buf->str, == ,"test\n"); g_string_set_size(buf, 0); gutil_log_set_timestamp_format(NULL); gutil_log_set_timestamp_format(NULL); gutil_log_timestamp = use_timestamp; /* Forward output to test_log_drop */ log_proc = gutil_log_default.log_proc; gutil_log_default.log_proc = test_log_drop; gutil_log(&gutil_log_default, GLOG_LEVEL_ALWAYS, "Test"); g_assert(!buf->len); /* Dropped by test_log_drop */ gutil_log_default.log_proc = log_proc; fclose(out); gutil_log_default.level = level; g_string_free(buf, TRUE); } #endif /* HAVE_TEST_LOG_FILE */ /*==========================================================================* * Enabled *==========================================================================*/ static void test_log_enabled( void) { const GLogProc2 fn = gutil_log_func2; const int level = gutil_log_default.level; GLOG_MODULE_DEFINE2_(module, "test", gutil_log_default); gutil_log_default.level = GLOG_LEVEL_NONE; g_assert(gutil_log_enabled(NULL, GLOG_LEVEL_ALWAYS)); g_assert(!gutil_log_enabled(NULL, GLOG_LEVEL_ERR)); g_assert(!gutil_log_enabled(NULL, GLOG_LEVEL_NONE)); gutil_log_default.level = GLOG_LEVEL_INFO; g_assert(gutil_log_enabled(&gutil_log_default, GLOG_LEVEL_ALWAYS)); g_assert(gutil_log_enabled(&gutil_log_default, GLOG_LEVEL_INFO)); gutil_log_default.flags |= GLOG_FLAG_DISABLE; g_assert(!gutil_log_enabled(&gutil_log_default, GLOG_LEVEL_INFO)); gutil_log_default.flags &= ~GLOG_FLAG_DISABLE; g_assert(!gutil_log_enabled(&gutil_log_default, GLOG_LEVEL_DEBUG)); /* It makes no sense to have default as INHERIT so it's treated as NONE */ gutil_log_default.level = GLOG_LEVEL_INHERIT; g_assert(!gutil_log_enabled(&module, GLOG_LEVEL_ERR)); g_assert(gutil_log_enabled(&module, GLOG_LEVEL_ALWAYS)); /* Test parenting */ module.level = GLOG_LEVEL_INHERIT; gutil_log_default.level = GLOG_LEVEL_INFO; g_assert(gutil_log_enabled(&module, GLOG_LEVEL_ALWAYS)); g_assert(gutil_log_enabled(&module, GLOG_LEVEL_INFO)); g_assert(!gutil_log_enabled(&module, GLOG_LEVEL_DEBUG)); /* No handler = no logging */ gutil_log_func2 = NULL; gutil_log_default.level = GLOG_LEVEL_VERBOSE; g_assert(!gutil_log_enabled(NULL, GLOG_LEVEL_ALWAYS)); gutil_log_default.level = level; gutil_log_func2 = fn; } /*==========================================================================* * Misc *==========================================================================*/ static void test_log_misc( void) { const GLogProc fn = gutil_log_func; g_assert(gutil_log_set_type(GLOG_TYPE_STDOUT, "test")); g_assert(gutil_log_func == gutil_log_stdout); g_assert_cmpstr(gutil_log_get_type(), == ,GLOG_TYPE_STDOUT); g_assert(gutil_log_set_type(GLOG_TYPE_STDERR, "test")); g_assert(gutil_log_func == gutil_log_stderr); g_assert_cmpstr(gutil_log_get_type(), == ,GLOG_TYPE_STDERR); g_assert(!gutil_log_set_type("whatever", "test")); gutil_log_func = NULL; g_assert_cmpstr(gutil_log_get_type(), == ,GLOG_TYPE_CUSTOM); gutil_log_func = fn; } /*==========================================================================* * Dump *==========================================================================*/ static void test_log_dump( void) { static const guint8 short_data[] = { 0x01, 0x02, 0x03, 0x04 }; static const char short_data_dump[] = " 0000: 01 02 03 04 ....\n"; static const guint8 long_data[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x00 }; static const char long_data_dump[] = "0000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f " "01234567 89:;<=>?\n" "0010: 00 " ".\n"; const GLogProc fn = gutil_log_func; const GLogModule* log = &gutil_log_default; GBytes* bytes; test_log_buf = g_string_new(NULL); gutil_log_func = test_log_fn; gutil_log_dump_bytes(log, GLOG_LEVEL_NONE, " ", NULL); gutil_log_dump(log,GLOG_LEVEL_NONE," ",TEST_ARRAY_AND_SIZE(short_data)); g_assert_cmpuint(test_log_buf->len, == ,0); gutil_log_dump(log,GLOG_LEVEL_ALWAYS," ",TEST_ARRAY_AND_SIZE(short_data)); g_assert_cmpstr(test_log_buf->str, == ,short_data_dump); g_string_set_size(test_log_buf, 0); bytes = g_bytes_new_static(TEST_ARRAY_AND_SIZE(short_data)); gutil_log_dump_bytes(log, GLOG_LEVEL_NONE, " ", bytes); g_assert_cmpuint(test_log_buf->len, == ,0); gutil_log_dump_bytes(log, GLOG_LEVEL_ALWAYS, " ", bytes); g_assert_cmpstr(test_log_buf->str, == ,short_data_dump); g_bytes_unref(bytes); g_string_set_size(test_log_buf, 0); gutil_log_dump(log,GLOG_LEVEL_ALWAYS,NULL,TEST_ARRAY_AND_SIZE(long_data)); g_assert_cmpstr(test_log_buf->str, == ,long_data_dump); g_string_set_size(test_log_buf, 0); bytes = g_bytes_new_static(TEST_ARRAY_AND_SIZE(long_data)); gutil_log_dump_bytes(log, GLOG_LEVEL_ALWAYS, NULL, bytes); g_assert_cmpstr(test_log_buf->str, == ,long_data_dump); g_bytes_unref(bytes); g_string_free(test_log_buf, TRUE); test_log_buf = NULL; gutil_log_func = fn; } /*==========================================================================* * Common *==========================================================================*/ #define TEST_PREFIX "/log/" int main(int argc, char* argv[]) { g_test_init(&argc, &argv, NULL); g_test_add_func(TEST_PREFIX "basic", test_log_basic); #ifdef HAVE_TEST_LOG_FILE g_test_add_func(TEST_PREFIX "file", test_log_file); #endif g_test_add_func(TEST_PREFIX "enabled", test_log_enabled); g_test_add_func(TEST_PREFIX "misc", test_log_misc); g_test_add_func(TEST_PREFIX "dump", test_log_dump); test_init(&test_opt, argc, argv); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000055000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000002E00000000libglibutil-1714660956.7df665e/test/test_misc07070100000056000081A40000000000000000000000016633A65C0000004C000000000000000000000000000000000000003700000000libglibutil-1714660956.7df665e/test/test_misc/Makefile# -*- Mode: makefile-gmake -*- EXE = test_misc include ../common/Makefile 07070100000057000081A40000000000000000000000016633A65C00008B03000000000000000000000000000000000000003A00000000libglibutil-1714660956.7df665e/test/test_misc/test_misc.c/* * Copyright (C) 2023-2024 Slava Monich <slava@monich.com> * Copyright (C) 2016-2022 Jolla Ltd. * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include "gutil_misc.h" #include "gutil_idlepool.h" #include "gutil_log.h" #include "gutil_version.h" static TestOpt test_opt; /*==========================================================================* * version *==========================================================================*/ static void test_version( void) { g_assert_cmpuint(gutil_version(), == ,GUTIL_VERSION); } /*==========================================================================* * disconnect *==========================================================================*/ static void test_notify( GObject* object, GParamSpec* spec, gpointer data) { } static void test_disconnect( void) { gulong id[2]; GObject* obj = g_object_new(TEST_OBJECT_TYPE, NULL); /* These have no effect */ gutil_disconnect_handlers(NULL, id, G_N_ELEMENTS(id)); gutil_disconnect_handlers(obj, NULL, 0); id[0] = g_signal_connect(obj, "notify", G_CALLBACK(test_notify), NULL); id[1] = g_signal_connect(obj, "notify", G_CALLBACK(test_notify), NULL); GASSERT(id[0] && id[1]); /* gutil_disconnect_handlers zeros the ids */ gutil_disconnect_handlers(obj, id, G_N_ELEMENTS(id)); g_assert(!id[0]); g_assert(!id[1]); /* Second time has no effect */ gutil_disconnect_handlers(obj, id, G_N_ELEMENTS(id)); g_assert(!id[0]); g_assert(!id[1]); g_object_unref(obj); } /*==========================================================================* * ref *==========================================================================*/ static void test_ref( void) { GObject* obj = g_object_new(TEST_OBJECT_TYPE, NULL); g_assert(!gutil_object_ref(NULL)); g_assert(gutil_object_ref(obj) == obj); g_object_unref(obj); g_object_unref(obj); } /*==========================================================================* * unref *==========================================================================*/ static void test_unref( void) { gutil_object_unref(NULL); gutil_object_unref(g_object_new(TEST_OBJECT_TYPE, NULL)); } /*==========================================================================* * source *==========================================================================*/ static gboolean test_source_cb( gpointer data) { g_assert_not_reached(); return G_SOURCE_REMOVE; } static void test_source( void) { guint id = 0; g_assert(!gutil_source_clear(NULL)); g_assert(!gutil_source_clear(&id)); id = g_idle_add(test_source_cb, NULL); g_assert(gutil_source_clear(&id)); g_assert_cmpuint(id, == ,0); g_assert(!gutil_source_remove(0)); g_assert(gutil_source_remove(g_idle_add(test_source_cb, NULL))); } /*==========================================================================* * hex2bin *==========================================================================*/ static void test_hex2bin( void) { guint8 buf[4]; GBytes* bytes; gsize size; const void* data; static const guint8 buf1[4] = { 0x01, 0x23, 0x45, 0x67 }; static const guint8 buf2[4] = { 0x89, 0xab, 0xcd, 0xef }; g_assert(!gutil_hex2bin(NULL, 0, NULL)); g_assert(!gutil_hex2bin("x", 0, NULL)); g_assert(!gutil_hex2bin("x", 0, buf)); g_assert(!gutil_hex2bin("x", -1, buf)); g_assert(!gutil_hex2bin("x", 1, buf)); g_assert(!gutil_hex2bin("xy", 2, buf)); g_assert(!gutil_hex2bin(" 1", 2, buf)); g_assert(!gutil_hex2bin("1 ", 2, buf)); g_assert(!gutil_hex2bin("1234FG", 6, buf)); g_assert(gutil_hex2bin("01234567", 8, buf)); g_assert(!memcmp(buf, buf1, sizeof(buf))); g_assert(gutil_hex2bin("89abcdef", 8, buf)); g_assert(!memcmp(buf, buf2, sizeof(buf))); g_assert(gutil_hex2bin("89ABCDEF", 8, buf)); g_assert(!memcmp(buf, buf2, sizeof(buf))); g_assert(!gutil_hex2bytes(NULL, 0)); g_assert(!gutil_hex2bytes("x", 0)); g_assert(!gutil_hex2bytes("x", 1)); g_assert(!gutil_hex2bytes("x", -1)); g_assert(!gutil_hex2bytes("xy", -1)); bytes = gutil_hex2bytes("01234567", -1); g_assert(bytes); data = g_bytes_get_data(bytes, &size); g_assert(data); g_assert(size == 4); g_assert(!memcmp(data, buf1, sizeof(buf1))); g_bytes_unref(bytes); } /*==========================================================================* * bin2hex *==========================================================================*/ static void test_bin2hex( void) { static const guchar bin[] = { 0x89, 0xab, 0xcd, 0xef }; static const GUtilData data = { TEST_ARRAY_AND_SIZE(bin) }; char* str; /* gutil_data2hex return NULL if data is NULL */ g_assert(!gutil_data2hex(NULL, FALSE)); /* Data isn't touched if len is zero */ str = gutil_bin2hex(NULL, 0, FALSE); g_assert_cmpstr(str, == ,""); g_free(str); /* Lower case */ str = gutil_bin2hex(bin, sizeof(bin), FALSE); g_assert_cmpstr(str, == ,"89abcdef"); g_free(str); str = gutil_data2hex(&data, FALSE); g_assert_cmpstr(str, == ,"89abcdef"); g_free(str); /* Upper case */ str = gutil_bin2hex(bin, sizeof(bin), TRUE); g_assert_cmpstr(str, == ,"89ABCDEF"); g_free(str); str = gutil_data2hex(&data, TRUE); g_assert_cmpstr(str, == ,"89ABCDEF"); g_free(str); } /*==========================================================================* * hexdump *==========================================================================*/ static void test_hexdump( void) { char buf[GUTIL_HEXDUMP_BUFSIZE]; static const guchar data[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x00 }; g_assert(gutil_hexdump(buf, data, sizeof(data)) == GUTIL_HEXDUMP_MAXBYTES); g_assert(strlen(buf) == GUTIL_HEXDUMP_BUFSIZE - 1); GDEBUG("%s", buf); g_assert(!strcmp(buf, "30 31 32 33 34 35 36 37 " "38 39 3a 3b 3c 3d 3e 3f " "01234567 89:;<=>?")); g_assert(gutil_hexdump(buf, data + GUTIL_HEXDUMP_MAXBYTES, 1) == 1); g_assert(strlen(buf) == 53); GDEBUG("%s", buf); g_assert(!strcmp(buf, "00 " " " ".")); } /*==========================================================================* * parse_int *==========================================================================*/ static void test_parse_int( void) { int value; g_assert(!gutil_parse_int(NULL, 0, NULL)); g_assert(!gutil_parse_int("", 0, NULL)); g_assert(!gutil_parse_int("garbage", 0, NULL)); g_assert(!gutil_parse_int("0 trailing garbage", 0, NULL)); g_assert(!gutil_parse_int("0", -1, NULL)); g_assert(!gutil_parse_int("0", 1, NULL)); g_assert(gutil_parse_int("0", 0, NULL)); g_assert(gutil_parse_int("0", 0, &value)); g_assert_cmpint(value, == ,0); g_assert(gutil_parse_int("-1", 0, &value)); g_assert_cmpint(value, == ,-1); g_assert(gutil_parse_int("42", 0, &value)); g_assert_cmpint(value, == ,42); g_assert(!gutil_parse_int("0x10000000000000000", 0, &value)); g_assert(!gutil_parse_int("-2147483649", 0, &value)); g_assert(!gutil_parse_int("4294967295", 0, &value)); g_assert(gutil_parse_int(" 0x7fffffff ", 0, &value)); g_assert_cmpint(value, == ,0x7fffffff); g_assert(gutil_parse_int(" 7fffffff ", 16, &value)); g_assert_cmpint(value, == ,0x7fffffff); g_assert(gutil_parse_int("7ffffffe ", 16, &value)); g_assert_cmpint(value, == ,0x7ffffffe); g_assert(!gutil_parse_int("0xffffffff", 0, &value)); } /*==========================================================================* * parse_uint *==========================================================================*/ static void test_parse_uint( void) { unsigned int value; g_assert(!gutil_parse_uint(NULL, 0, NULL)); g_assert(!gutil_parse_uint("", 0, NULL)); g_assert(!gutil_parse_uint("garbage", 0, NULL)); g_assert(!gutil_parse_uint("0 trailing garbage", 0, NULL)); g_assert(!gutil_parse_uint("0", -1, NULL)); g_assert(!gutil_parse_uint("0", 1, NULL)); g_assert(gutil_parse_uint("0", 0, NULL)); g_assert(gutil_parse_uint("0", 0, &value)); g_assert_cmpuint(value, == ,0); g_assert(gutil_parse_uint("42", 0, &value)); g_assert_cmpuint(value, == ,42); g_assert(!gutil_parse_uint("0x10000000000000000", 0, &value)); #if defined __SIZEOF_INT__ && __SIZEOF_INT__ == 4 g_assert(!gutil_parse_uint("0x100000000", 0, &value)); #endif g_assert(!gutil_parse_uint("-2147483649", 0, &value)); g_assert(!gutil_parse_uint("-1", 0, &value)); g_assert(!gutil_parse_uint(" -1 ", 0, &value)); g_assert(gutil_parse_uint("4294967295", 0, &value)); g_assert_cmpuint(value, == ,4294967295U); g_assert(gutil_parse_uint(" 0x7fffffff ", 0, &value)); g_assert_cmpuint(value, == ,0x7fffffff); g_assert(gutil_parse_uint(" 7fffffff ", 16, &value)); g_assert_cmpuint(value, == ,0x7fffffff); g_assert(gutil_parse_uint("7ffffffe ", 16, &value)); g_assert_cmpuint(value, == ,0x7ffffffe); g_assert(gutil_parse_uint("0xffffffff", 0, &value)); g_assert_cmpuint(value, == ,0xffffffff); } /*==========================================================================* * parse_int64 *==========================================================================*/ static void test_parse_int64( void) { gint64 value; g_assert(!gutil_parse_int64(NULL, 0, NULL)); g_assert(!gutil_parse_int64("", 0, NULL)); g_assert(!gutil_parse_int64("garbage", 0, NULL)); g_assert(!gutil_parse_int64("0 trailing garbage", 0, NULL)); g_assert(!gutil_parse_int64("0", -1, NULL)); g_assert(!gutil_parse_int64("0", 1, NULL)); g_assert(gutil_parse_int64("0", 0, NULL)); g_assert(gutil_parse_int64("0", 0, &value)); g_assert_cmpint(value, == ,0); g_assert(gutil_parse_int64("-1", 0, &value)); g_assert_cmpint(value, == ,-1); g_assert(gutil_parse_int64("42", 0, &value)); g_assert_cmpint(value, == ,42); g_assert(gutil_parse_int64("-2147483649", 0, &value)); g_assert_cmpint(value, == ,G_GINT64_CONSTANT(-2147483649)); g_assert(gutil_parse_int64("4294967295", 0, &value)); g_assert_cmpint(value, == ,G_GINT64_CONSTANT(4294967295)); g_assert(gutil_parse_int64(" 0x7fffffff ", 0, &value)); g_assert_cmpint(value, == ,0x7fffffff); g_assert(gutil_parse_int64(" 7fffffff ", 16, &value)); g_assert_cmpint(value, == ,0x7fffffff); g_assert(gutil_parse_int64("7ffffffe ", 16, &value)); g_assert_cmpint(value, == ,0x7ffffffe); g_assert(gutil_parse_int64("0xffffffff", 0, &value)); g_assert_cmpint(value, == ,0xffffffff); g_assert(gutil_parse_int64("-9223372036854775808", 0, &value)); g_assert_cmpint(value, == ,0x8000000000000000); g_assert(gutil_parse_int64("9223372036854775807", 0, &value)); g_assert_cmpint(value, == ,0x7fffffffffffffff); #ifndef _WIN32 g_assert(!gutil_parse_int64("0x10000000000000000", 0, &value)); g_assert(!gutil_parse_int64("-9223372036854775809", 0, &value)); g_assert(!gutil_parse_int64("9223372036854775808", 0, &value)); #endif } /*==========================================================================* * parse_uint64 *==========================================================================*/ static void test_parse_uint64( void) { guint64 value; g_assert(!gutil_parse_uint64(NULL, 0, NULL)); g_assert(!gutil_parse_uint64("", 0, NULL)); g_assert(!gutil_parse_uint64("garbage", 0, NULL)); g_assert(!gutil_parse_uint64("0 trailing garbage", 0, NULL)); g_assert(!gutil_parse_uint64("0", -1, NULL)); g_assert(!gutil_parse_uint64("0", 1, NULL)); g_assert(gutil_parse_uint64("0", 0, NULL)); g_assert(gutil_parse_uint64("0", 0, &value)); g_assert_cmpuint(value, == ,0); g_assert(gutil_parse_uint64("42", 0, &value)); g_assert_cmpuint(value, == ,42); g_assert(!gutil_parse_uint64("-2147483649", 0, &value)); g_assert(!gutil_parse_uint64("-1", 0, &value)); g_assert(!gutil_parse_uint64(" -1 ", 0, &value)); g_assert(gutil_parse_uint64("4294967295", 0, &value)); g_assert_cmpuint(value, == ,4294967295U); g_assert(!gutil_parse_uint64(" 0x7fffffff ffffffff ", 0, &value)); g_assert(gutil_parse_uint64(" 0x7fffffffffffffff ", 0, &value)); g_assert_cmpuint(value, == ,0x7fffffffffffffff); g_assert(!gutil_parse_uint64(" 7fffffff ffffffff", 16, &value)); g_assert(gutil_parse_uint64(" 7fffffffffffffff ", 16, &value)); g_assert_cmpuint(value, == ,0x7fffffffffffffff); g_assert(gutil_parse_uint64("0x100000000", 0, &value)); g_assert_cmpuint(value, == ,0x100000000); g_assert(gutil_parse_uint64("0xffffffffffffffff", 0, &value)); g_assert_cmpuint(value, == ,0xffffffffffffffff); #ifndef _WIN32 g_assert(!gutil_parse_uint64("0x10000000000000000", 0, &value)); #endif } /*==========================================================================* * data_equal *==========================================================================*/ static void test_data_equal( void) { static const guint8 val_123[] = { '1', '2', '3' }; static const guint8 val_1234[] = { '1', '2', '3', '4' }; static const guint8 val_321[] = { '3', '2', '1' }; GUtilData data_123, data_123a, data_1234, data_321; TEST_INIT_DATA(data_123, val_123); TEST_INIT_DATA(data_123a, val_123); TEST_INIT_DATA(data_1234, val_1234); TEST_INIT_DATA(data_321, val_321); g_assert(gutil_data_equal(NULL, NULL)); g_assert(gutil_data_equal(&data_123, &data_123)); g_assert(gutil_data_equal(&data_123, &data_123a)); g_assert(!gutil_data_equal(&data_123, &data_1234)); g_assert(!gutil_data_equal(&data_123, &data_321)); g_assert(!gutil_data_equal(&data_123, NULL)); g_assert(!gutil_data_equal(NULL, &data_123)); } /*==========================================================================* * data_prefix *==========================================================================*/ static void test_data_prefix( void) { static const guint8 val_123[] = { '1', '2', '3' }; static const guint8 val_1234[] = { '1', '2', '3', '4' }; static const guint8 val_234[] = { '2', '3', '4' }; GUtilData data_empty, data_123, data_1234, data_234; memset(&data_empty, 0, sizeof(data_empty)); TEST_INIT_DATA(data_123, val_123); TEST_INIT_DATA(data_1234, val_1234); TEST_INIT_DATA(data_234, val_234); g_assert(gutil_data_has_prefix(NULL, NULL)); g_assert(!gutil_data_has_prefix(&data_empty, NULL)); g_assert(!gutil_data_has_prefix(NULL, &data_empty)); g_assert(gutil_data_has_prefix(&data_empty, &data_empty)); g_assert(gutil_data_has_prefix(&data_123, &data_empty)); g_assert(gutil_data_has_prefix(&data_1234, &data_123)); g_assert(!gutil_data_has_prefix(&data_123, &data_1234)); g_assert(!gutil_data_has_prefix(&data_1234, &data_234)); } /*==========================================================================* * data_suffix *==========================================================================*/ static void test_data_suffix( void) { static const guint8 val_123[] = { '1', '2', '3' }; static const guint8 val_1234[] = { '1', '2', '3', '4' }; static const guint8 val_234[] = { '2', '3', '4' }; GUtilData data_empty, data_123, data_1234, data_234; memset(&data_empty, 0, sizeof(data_empty)); TEST_INIT_DATA(data_123, val_123); TEST_INIT_DATA(data_1234, val_1234); TEST_INIT_DATA(data_234, val_234); g_assert(gutil_data_has_suffix(NULL, NULL)); g_assert(!gutil_data_has_suffix(&data_empty, NULL)); g_assert(!gutil_data_has_suffix(NULL, &data_empty)); g_assert(gutil_data_has_suffix(&data_empty, &data_empty)); g_assert(gutil_data_has_suffix(&data_123, &data_empty)); g_assert(gutil_data_has_suffix(&data_1234, &data_234)); g_assert(!gutil_data_has_suffix(&data_234, &data_1234)); g_assert(!gutil_data_has_suffix(&data_1234, &data_123)); } /*==========================================================================* * data_from_bytes *==========================================================================*/ static void test_data_from_bytes( void) { static const guint8 val_123[] = { '1', '2', '3' }; GBytes* bytes_123 = g_bytes_new_static(val_123, sizeof(val_123)); GUtilData data_123, data; TEST_INIT_DATA(data_123, val_123); TEST_INIT_DATA(data, val_123); g_assert(!gutil_data_from_bytes(NULL, NULL)); g_assert(gutil_data_from_bytes(&data, NULL) == &data); g_assert(!data.bytes); g_assert(!data.size); g_assert(gutil_data_from_bytes(&data, bytes_123) == &data); g_assert(gutil_data_equal(&data_123, &data)); g_bytes_unref(bytes_123); } /*==========================================================================* * data_from_string *==========================================================================*/ static void test_data_from_string( void) { static const guint8 val_123[] = { '1', '2', '3' }; GUtilData data_123, data; TEST_INIT_DATA(data_123, val_123); TEST_INIT_DATA(data, val_123); g_assert(!gutil_data_from_string(NULL, NULL)); g_assert(gutil_data_from_string(&data, NULL) == &data); g_assert(!data.bytes); g_assert(!data.size); g_assert(gutil_data_from_string(&data, "123") == &data); g_assert(gutil_data_equal(&data_123, &data)); } /*==========================================================================* * data_copy *==========================================================================*/ static void test_data_copy( void) { static const guint8 src_data[] = { '1', '2', '3' }; GUtilData* data; GUtilData src; TEST_INIT_DATA(src, src_data); g_assert(!gutil_data_copy(NULL)); data = gutil_data_copy(&src); g_assert(gutil_data_equal(data, &src)); g_free(data); /* This is wrong but when pointer is NULL, the length is ignored */ data = gutil_data_new(NULL, 1000); g_assert(!data->bytes); g_assert(!data->size); g_free(data); data = gutil_data_new(TEST_ARRAY_AND_SIZE(src_data)); g_assert(gutil_data_equal(data, &src)); g_free(data); } /*==========================================================================* * data_copy_as_variant *==========================================================================*/ static void test_data_copy_as_variant( void) { static const guint8 bytes[] = { '1', '2', '3' }; GVariant* var; GUtilData data; g_assert(!gutil_data_copy_as_variant(NULL)); memset(&data, 0, sizeof(data)); var = gutil_data_copy_as_variant(&data); g_assert(var); g_assert_cmpuint(g_variant_get_size(var), == ,0); g_variant_unref(g_variant_ref_sink(var)); TEST_INIT_DATA(data, bytes); var = gutil_data_copy_as_variant(&data); g_assert(var); g_assert_cmpuint(data.size, == ,g_variant_get_size(var)); g_assert(!memcmp(data.bytes, g_variant_get_data(var), data.size)); g_variant_unref(g_variant_ref_sink(var)); } /*==========================================================================* * bytes_concat *==========================================================================*/ static void test_bytes_concat( void) { static const guint8 val1[] = {0x01,0x02,0x03,0x04,0x05}; static const guint8 val2[] = {0x06,0x07,0x08,0x09}; static const guint8 val3[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09}; GBytes* b1 = g_bytes_new_static(val1, sizeof(val1)); GBytes* b2 = g_bytes_new_static(val2, sizeof(val2)); GBytes* b3 = g_bytes_new_static(val3, sizeof(val3)); GBytes* empty = g_bytes_new(NULL, 0); GBytes* b; g_assert(!gutil_bytes_concat(NULL, NULL)); b = gutil_bytes_concat(b1, NULL); g_assert(b == b1); g_bytes_unref(b); b = gutil_bytes_concat(empty, NULL); g_assert(b == empty); g_bytes_unref(b); b = gutil_bytes_concat(b1, empty, NULL); g_assert(b == b1); g_bytes_unref(b); b = gutil_bytes_concat(empty, b1, NULL); g_assert(b == b1); g_bytes_unref(b); b = gutil_bytes_concat(b1, empty, b2, NULL); g_assert(g_bytes_equal(b, b3)); g_bytes_unref(b); g_bytes_unref(b1); g_bytes_unref(b2); g_bytes_unref(b3); g_bytes_unref(empty); } /*==========================================================================* * bytes_xor *==========================================================================*/ static void test_bytes_xor( void) { static const guint8 val1[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09}; static const guint8 val2[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; static const guint8 val3[] = {0x01,0x03,0x01,0x07,0x01,0x03,0x01,0x0F,0x01}; static const guint8 val4[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; static const guint8 val5[] = {0x05,0x06,0x07,0x08}; static const guint8 val6[] = {0x04,0x04,0x04,0x0C}; GBytes* b1 = g_bytes_new_static(val1, sizeof(val1)); GBytes* b2 = g_bytes_new_static(val2, sizeof(val2)); GBytes* b3 = g_bytes_new_static(val3, sizeof(val3)); GBytes* b4 = g_bytes_new_static(val4, sizeof(val4)); GBytes* b5 = g_bytes_new_static(val5, sizeof(val5)); GBytes* b6 = g_bytes_new_static(val6, sizeof(val6)); GBytes* empty = g_bytes_new(NULL, 0); GBytes* b; g_assert(!gutil_bytes_xor(b1, NULL)); g_assert(!gutil_bytes_xor(NULL, b1)); g_assert(!gutil_bytes_xor(NULL, NULL)); b = gutil_bytes_xor(empty, b1); g_assert(b == empty); g_bytes_unref(b); b = gutil_bytes_xor(b1, empty); g_assert(b == empty); g_bytes_unref(b); b = gutil_bytes_xor(b1, b1); /* 010203040506070809^010203040506070809 */ g_assert(g_bytes_equal(b, b4)); /* =000000000000000000 */ g_bytes_unref(b); b = gutil_bytes_xor(b1, b2); /* 010203040506070809^000102030405060708 */ g_assert(g_bytes_equal(b, b3)); /* =010301070103010F01 */ g_bytes_unref(b); b = gutil_bytes_xor(b1, b5); /* 010203040506070809^05060708 */ g_assert(g_bytes_equal(b, b6)); /* =0404040C */ g_bytes_unref(b); g_bytes_unref(b1); g_bytes_unref(b2); g_bytes_unref(b3); g_bytes_unref(b4); g_bytes_unref(b5); g_bytes_unref(b6); g_bytes_unref(empty); } /*==========================================================================* * bytes_equal *==========================================================================*/ static void test_bytes_equal( void) { static const guint8 data1[] = { 0x01 }; static const guint8 data11[] = { 0x01, 0x01 }; static const guint8 data2[] = { 0x02 }; GUtilData data; GBytes* bytes = g_bytes_new(NULL, 0); memset(&data, 0, sizeof(data)); g_assert(gutil_bytes_equal(NULL, NULL, 0)); g_assert(gutil_bytes_equal_data(NULL, NULL)); /* One of the arguments is not NULL => not equal */ g_assert(!gutil_bytes_equal(NULL, &data, 0)); g_assert(!gutil_bytes_equal(bytes, NULL, 0)); g_assert(!gutil_bytes_equal_data(bytes, NULL)); g_assert(!gutil_bytes_equal_data(NULL, &data)); /* Empty blocks of data are equal */ g_assert(gutil_bytes_equal(bytes, &data, 0)); g_assert(gutil_bytes_equal_data(bytes, &data)); /* Different sizes */ data.bytes = data11; data.size = sizeof(data11); g_assert(!gutil_bytes_equal(bytes, data.bytes, data.size)); g_assert(!gutil_bytes_equal_data(bytes, &data)); g_bytes_unref(bytes); bytes = g_bytes_new_static(data1, sizeof(data1)); g_assert(!gutil_bytes_equal(bytes, data.bytes, data.size)); g_assert(!gutil_bytes_equal_data(bytes, &data)); /* Different contents */ data.bytes = data2; data.size = sizeof(data2); g_assert(!gutil_bytes_equal(bytes, data.bytes, data.size)); g_assert(!gutil_bytes_equal_data(bytes, &data)); /* Match */ data.bytes = data1; data.size = sizeof(data1); g_assert(gutil_bytes_equal(bytes, data.bytes, data.size)); g_assert(gutil_bytes_equal_data(bytes, &data)); g_bytes_unref(bytes); } /*==========================================================================* * ptrv_length *==========================================================================*/ static void test_ptrv_length( void) { static const gconstpointer ptrv0[] = { NULL }; static const gconstpointer ptrv1[] = { ptrv0, NULL }; g_assert_cmpuint(gutil_ptrv_length(NULL), == ,0); g_assert_cmpuint(gutil_ptrv_length(ptrv0), == ,0); g_assert_cmpuint(gutil_ptrv_length(ptrv1), == ,1); } /*==========================================================================* * ptrv_is_empty *==========================================================================*/ static void test_ptrv_is_empty( void) { static const gconstpointer ptrv0[] = { NULL }; static const gconstpointer ptrv1[] = { ptrv0, NULL }; g_assert(gutil_ptrv_is_empty(NULL)); g_assert(gutil_ptrv_is_empty(ptrv0)); g_assert(!gutil_ptrv_is_empty(ptrv1)); } /*==========================================================================* * ptrv_free *==========================================================================*/ static void test_ptrv_free( void) { void** ptrv0 = g_new0(void*, 1); void** ptrv1 = g_new0(void*, 2); ptrv1[0] = g_new0(int, 1); gutil_ptrv_free(NULL); gutil_ptrv_free(ptrv0); gutil_ptrv_free(ptrv1); } /*==========================================================================* * memdup *==========================================================================*/ static void test_memdup( void) { static const guint8 data[] = { 0x01, 0x02, 0x03 }; void* copy = gutil_memdup(data, sizeof(data)); g_assert(copy); g_assert(!memcmp(copy, data, sizeof(data))); g_free(copy); g_assert(!gutil_memdup(data, 0)); g_assert(!gutil_memdup(NULL, 0)); g_assert(!gutil_memdup(NULL, 1)); } /*==========================================================================* * strlen *==========================================================================*/ static void test_strlen( void) { g_assert(!gutil_strlen0(NULL)); g_assert_cmpuint(gutil_strlen0(""), == ,0); g_assert_cmpuint(gutil_strlen0("1"), == ,1); } /*==========================================================================* * range_init *==========================================================================*/ static void test_range_init( void) { static const guint8 data[] = { 0x01, 0x02, 0x03 }; GBytes* bytes = g_bytes_new_static(data, sizeof(data)); GUtilRange range; g_assert(!gutil_range_init_with_bytes(NULL, NULL)); g_assert(!gutil_range_init_with_bytes(&range, NULL)); g_assert(!range.ptr); g_assert(!range.end); g_assert(gutil_range_init_with_bytes(&range, bytes) == sizeof(data)); g_assert(range.ptr == data); g_assert(range.end == (data + sizeof(data))); g_bytes_unref(bytes); } /*==========================================================================* * range_prefix *==========================================================================*/ static void test_range_prefix( void) { static const guint8 data[] = { 0x01, 0x02, 0x03, 0x04 }; static const guint8 prefix[] = { 0x01, 0x02 }; static const guint8 not_prefix[] = { 0x03, 0x04 }; static const guint8 too_long[] = { 0x01, 0x02, 0x03, 0x04, 0x05 }; GUtilData prefix_data, not_prefix_data, too_long_data; GUtilRange range; memset(&range, 0, sizeof(range)); g_assert(!gutil_range_has_prefix(NULL, NULL)); g_assert(!gutil_range_has_prefix(&range, NULL)); not_prefix_data.bytes = not_prefix; not_prefix_data.size = sizeof(not_prefix); too_long_data.bytes = too_long; too_long_data.size = sizeof(too_long); range.end = range.ptr = data; /* Empty range */ memset(&prefix_data, 0, sizeof(prefix_data)); /* Empty prefix */ /* Empty range doesn't have NULL prefix */ g_assert(!gutil_range_has_prefix(&range, NULL)); /* But does have empty prefix */ g_assert(gutil_range_has_prefix(&range, &prefix_data)); /* And doesn't have non-empty prefix */ g_assert(!gutil_range_has_prefix(&range, ¬_prefix_data)); prefix_data.bytes = prefix; prefix_data.size = sizeof(prefix); g_assert(!gutil_range_has_prefix(&range, &prefix_data)); range.end = range.ptr + sizeof(data); g_assert(gutil_range_has_prefix(&range, &prefix_data)); g_assert(!gutil_range_has_prefix(&range, ¬_prefix_data)); g_assert(!gutil_range_has_prefix(&range, &too_long_data)); /* Test skipping */ g_assert(!gutil_range_skip_prefix(&range, ¬_prefix_data)); g_assert(range.ptr == data); g_assert(gutil_range_skip_prefix(&range, &prefix_data)); g_assert(range.ptr == (data + prefix_data.size)); } /*==========================================================================* * bytes_prefix *==========================================================================*/ static void test_bytes_prefix( void) { static const guint8 data[] = { 0x01, 0x02, 0x03, 0x04 }; static const guint8 prefix[] = { 0x01, 0x02 }; static const guint8 not_prefix[] = { 0x03, 0x04 }; static const guint8 too_long[] = { 0x01, 0x02, 0x03, 0x04, 0x05 }; GBytes* empty = g_bytes_new_static(NULL, 0); GBytes* bytes = g_bytes_new_static(TEST_ARRAY_AND_SIZE(data)); /* NULL GBytes doesn't have any prefix, even an empty one */ g_assert(!gutil_bytes_has_prefix(NULL, NULL, 0)); /* Anything has an empty prefix */ g_assert(gutil_bytes_has_prefix(empty, NULL, 0)); g_assert(gutil_bytes_has_prefix(bytes, prefix, 0)); /* Test the matching */ g_assert(gutil_bytes_has_prefix(bytes, TEST_ARRAY_AND_SIZE(prefix))); g_assert(!gutil_bytes_has_prefix(bytes, TEST_ARRAY_AND_SIZE(not_prefix))); g_assert(!gutil_bytes_has_prefix(bytes, TEST_ARRAY_AND_SIZE(too_long))); g_bytes_unref(empty); g_bytes_unref(bytes); } /*==========================================================================* * bytes_suffix *==========================================================================*/ static void test_bytes_suffix( void) { static const guint8 data[] = { 0x01, 0x02, 0x03, 0x04 }; static const guint8 suffix[] = { 0x03, 0x04 }; static const guint8 not_suffix[] = { 0x02, 0x03 }; static const guint8 too_long[] = { 0x01, 0x02, 0x03, 0x04, 0x05 }; GBytes* empty = g_bytes_new_static(NULL, 0); GBytes* bytes = g_bytes_new_static(TEST_ARRAY_AND_SIZE(data)); /* NULL GBytes doesn't have any suffix, even an empty one */ g_assert(!gutil_bytes_has_suffix(NULL, NULL, 0)); /* Anything has an empty suffix */ g_assert(gutil_bytes_has_suffix(empty, NULL, 0)); g_assert(gutil_bytes_has_suffix(bytes, suffix, 0)); /* Test the matching */ g_assert(gutil_bytes_has_suffix(bytes, TEST_ARRAY_AND_SIZE(suffix))); g_assert(!gutil_bytes_has_suffix(bytes, TEST_ARRAY_AND_SIZE(not_suffix))); g_assert(!gutil_bytes_has_suffix(bytes, TEST_ARRAY_AND_SIZE(too_long))); g_bytes_unref(empty); g_bytes_unref(bytes); } /*==========================================================================* * Common *==========================================================================*/ #define TEST_(x) "/misc/" x int main(int argc, char* argv[]) { G_GNUC_BEGIN_IGNORE_DEPRECATIONS; g_type_init(); G_GNUC_END_IGNORE_DEPRECATIONS; g_test_init(&argc, &argv, NULL); gutil_log_timestamp = FALSE; gutil_log_default.level = g_test_verbose() ? GLOG_LEVEL_VERBOSE : GLOG_LEVEL_NONE; g_test_add_func(TEST_("version"), test_version); g_test_add_func(TEST_("disconnect"), test_disconnect); g_test_add_func(TEST_("ref"), test_ref); g_test_add_func(TEST_("source"), test_source); g_test_add_func(TEST_("unref"), test_unref); g_test_add_func(TEST_("hex2bin"), test_hex2bin); g_test_add_func(TEST_("bin2hex"), test_bin2hex); g_test_add_func(TEST_("hexdump"), test_hexdump); g_test_add_func(TEST_("parse_int"), test_parse_int); g_test_add_func(TEST_("parse_uint"), test_parse_uint); g_test_add_func(TEST_("parse_int64"), test_parse_int64); g_test_add_func(TEST_("parse_uint64"), test_parse_uint64); g_test_add_func(TEST_("data_equal"), test_data_equal); g_test_add_func(TEST_("data_prefix"), test_data_prefix); g_test_add_func(TEST_("data_suffix"), test_data_suffix); g_test_add_func(TEST_("data_from_bytes"), test_data_from_bytes); g_test_add_func(TEST_("data_from_string"), test_data_from_string); g_test_add_func(TEST_("data_copy"), test_data_copy); g_test_add_func(TEST_("data_copy_as_variant"), test_data_copy_as_variant); g_test_add_func(TEST_("bytes_concat"), test_bytes_concat); g_test_add_func(TEST_("bytes_xor"), test_bytes_xor); g_test_add_func(TEST_("bytes_equal"), test_bytes_equal); g_test_add_func(TEST_("ptrv_length"), test_ptrv_length); g_test_add_func(TEST_("ptrv_is_empty"), test_ptrv_is_empty); g_test_add_func(TEST_("ptrv_free"), test_ptrv_free); g_test_add_func(TEST_("memdup"), test_memdup); g_test_add_func(TEST_("strlen"), test_strlen); g_test_add_func(TEST_("range_init"), test_range_init); g_test_add_func(TEST_("range_prefix"), test_range_prefix); g_test_add_func(TEST_("bytes_prefix"), test_bytes_prefix); g_test_add_func(TEST_("bytes_suffix"), test_bytes_suffix); test_init(&test_opt, argc, argv); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000058000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000002E00000000libglibutil-1714660956.7df665e/test/test_objv07070100000059000081A40000000000000000000000016633A65C0000004C000000000000000000000000000000000000003700000000libglibutil-1714660956.7df665e/test/test_objv/Makefile# -*- Mode: makefile-gmake -*- EXE = test_objv include ../common/Makefile 0707010000005A000081A40000000000000000000000016633A65C0000301E000000000000000000000000000000000000003A00000000libglibutil-1714660956.7df665e/test/test_objv/test_objv.c/* * Copyright (C) 2023 Slava Monich <slava@monich.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include "gutil_objv.h" #include "gutil_misc.h" static TestOpt test_opt; /*==========================================================================* * null *==========================================================================*/ static void test_null( void) { g_assert(!gutil_objv_copy(NULL)); g_assert(!gutil_objv_add(NULL, NULL)); g_assert(!gutil_objv_append(NULL, NULL)); g_assert(!gutil_objv_insert(NULL, NULL, 0)); g_assert(!gutil_objv_remove(NULL, NULL, FALSE)); g_assert(!gutil_objv_remove_at(NULL, 0)); g_assert(!gutil_objv_at(NULL, 0)); g_assert(!gutil_objv_first(NULL)); g_assert(!gutil_objv_last(NULL)); g_assert(!gutil_objv_contains(NULL, NULL)); g_assert_cmpint(gutil_objv_find(NULL, NULL), < ,0); g_assert_cmpint(gutil_objv_find_last(NULL, NULL), < ,0); g_assert(gutil_objv_equal(NULL, NULL)); gutil_objv_free(NULL); } /*==========================================================================* * basic *==========================================================================*/ static void test_basic( void) { GObject* o1 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject* o2 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject** v = gutil_objv_add(NULL, o1); GWeakRef r1, r2; g_weak_ref_init(&r1, o1); g_weak_ref_init(&r2, o2); /* v keeps references to both objects */ g_object_unref(o1); g_assert(g_weak_ref_get(&r1) == o1); g_object_unref(o1); g_assert(gutil_objv_contains(v, o1)); g_assert(!gutil_objv_contains(v, o2)); g_assert_cmpuint(gutil_ptrv_length(v), == ,1); v = gutil_objv_add(v, o2); g_assert_cmpuint(gutil_ptrv_length(v), == ,2); g_assert(gutil_objv_contains(v, o2)); g_assert(gutil_objv_at(v, 0) == o1); g_assert(gutil_objv_at(v, 1) == o2); g_assert(!gutil_objv_at(v, 2)); g_assert(!gutil_objv_at(v, 3)); g_assert(gutil_objv_first(v) == o1); g_assert(gutil_objv_last(v) == o2); g_assert_cmpint(gutil_objv_find(v, o1), == ,0); g_assert_cmpint(gutil_objv_find_last(v, o1), == ,0); v = gutil_objv_remove(v, o1, FALSE); g_assert_cmpuint(gutil_ptrv_length(v), == ,1); g_assert(!gutil_objv_at(v, 1)); g_assert(gutil_objv_remove(v, o1, FALSE) == v); g_assert(gutil_objv_remove(v, NULL, FALSE) == v); g_assert_cmpuint(gutil_ptrv_length(v), == ,1); g_assert(!g_weak_ref_get(&r1)); g_object_unref(o2); gutil_objv_free(v); g_assert(!g_weak_ref_get(&r2)); } /*==========================================================================* * new *==========================================================================*/ static void test_new( void) { GObject* o1 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject* o2 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject** v; GWeakRef r1, r2; g_weak_ref_init(&r1, o1); g_weak_ref_init(&r2, o2); v = gutil_objv_new(NULL, NULL); g_assert(v); g_assert(!gutil_ptrv_length(v)); gutil_objv_free(v); /* v keeps references to both objects */ v = gutil_objv_new(o1, o2, NULL); g_assert(v[0] == o1); g_assert(v[1] == o2); g_assert(!v[2]); g_object_unref(o1); g_assert(g_weak_ref_get(&r1) == o1); g_object_unref(o1); g_object_unref(o2); g_assert(g_weak_ref_get(&r2) == o2); g_object_unref(o2); gutil_objv_free(v); g_assert(!g_weak_ref_get(&r1)); g_assert(!g_weak_ref_get(&r2)); } /*==========================================================================* * insert *==========================================================================*/ static void test_insert( void) { GObject* o1 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject* o2 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject* o3 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject** v; GWeakRef r1, r2, r3; g_weak_ref_init(&r1, o1); g_weak_ref_init(&r2, o2); g_weak_ref_init(&r3, o3); v = gutil_objv_add(gutil_objv_add(NULL, o1), o2); /* Insert at the end (with index beyond the valid range) */ v = gutil_objv_insert(v, o3, 100); g_assert_cmpuint(gutil_ptrv_length(v), == ,3); g_assert(gutil_objv_at(v, 0) == o1); g_assert(gutil_objv_at(v, 1) == o2); g_assert(gutil_objv_at(v, 2) == o3); /* Again at the end (with the right index) */ v = gutil_objv_remove_at(v, 2); g_assert_cmpuint(gutil_ptrv_length(v), == ,2); g_assert(gutil_objv_at(v, 0) == o1); g_assert(gutil_objv_at(v, 1) == o2); v = gutil_objv_insert(v, o3, 2); g_assert_cmpuint(gutil_ptrv_length(v), == ,3); g_assert(gutil_objv_at(v, 0) == o1); g_assert(gutil_objv_at(v, 1) == o2); g_assert(gutil_objv_at(v, 2) == o3); /* At the beginning */ v = gutil_objv_remove_at(v, 0); g_assert_cmpuint(gutil_ptrv_length(v), == ,2); g_assert(gutil_objv_at(v, 0) == o2); g_assert(gutil_objv_at(v, 1) == o3); v = gutil_objv_insert(v, o1, 0); g_assert_cmpuint(gutil_ptrv_length(v), == ,3); g_assert(gutil_objv_at(v, 0) == o1); g_assert(gutil_objv_at(v, 1) == o2); g_assert(gutil_objv_at(v, 2) == o3); /* And at the middle */ v = gutil_objv_remove_at(v, 1); g_assert_cmpuint(gutil_ptrv_length(v), == ,2); g_assert(gutil_objv_at(v, 0) == o1); g_assert(gutil_objv_at(v, 1) == o3); v = gutil_objv_insert(v, o2, 1); g_assert_cmpuint(gutil_ptrv_length(v), == ,3); g_assert(gutil_objv_at(v, 0) == o1); g_assert(gutil_objv_at(v, 1) == o2); g_assert(gutil_objv_at(v, 2) == o3); g_object_unref(o1); g_object_unref(o2); g_object_unref(o3); gutil_objv_free(v); g_assert(!g_weak_ref_get(&r1)); g_assert(!g_weak_ref_get(&r2)); g_assert(!g_weak_ref_get(&r3)); } /*==========================================================================* * append *==========================================================================*/ static void test_append( void) { GObject* o1 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject* o2 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject* o3 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject** v1 = NULL; GObject** v2 = NULL; GWeakRef r1, r2, r3; g_weak_ref_init(&r1, o1); g_weak_ref_init(&r2, o2); g_weak_ref_init(&r3, o3); v1 = gutil_objv_add(NULL, o1); v2 = gutil_objv_append(NULL, v1); g_assert_cmpuint(gutil_ptrv_length(v2), == ,1); g_assert(gutil_objv_equal(v1, v2)); gutil_objv_free(v2); v2 = gutil_objv_add(gutil_objv_add(NULL, o2), o3); g_assert(gutil_objv_append(v2, NULL) == v2); v1 = gutil_objv_append(v1, v2); g_assert_cmpuint(gutil_ptrv_length(v1), == ,3); g_assert_cmpuint(gutil_ptrv_length(v2), == ,2); g_assert(gutil_objv_at(v1, 0) == o1); g_assert(gutil_objv_at(v1, 1) == o2); g_assert(gutil_objv_at(v1, 2) == o3); g_object_unref(o1); g_object_unref(o2); g_object_unref(o3); gutil_objv_free(v1); gutil_objv_free(v2); g_assert(!g_weak_ref_get(&r1)); g_assert(!g_weak_ref_get(&r2)); g_assert(!g_weak_ref_get(&r3)); } /*==========================================================================* * copy *==========================================================================*/ static void test_copy( void) { GObject* o1 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject* o2 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject** v1; GObject** v2; GWeakRef r1, r2; g_weak_ref_init(&r1, o1); g_weak_ref_init(&r2, o2); v1 = gutil_objv_add(gutil_objv_add(NULL, o1), o2); v2 = gutil_objv_copy(v1); /* Don't need these references anymore */ g_object_unref(o1); g_object_unref(o2); g_assert_cmpuint(gutil_ptrv_length(v1), == ,2); g_assert_cmpuint(gutil_ptrv_length(v2), == ,2); g_assert(gutil_objv_equal(v1, v2)); g_assert(gutil_objv_equal(v2, v1)); g_assert(gutil_objv_equal(v1, v1)); v1 = gutil_objv_remove_at(v1, 1); g_assert(!gutil_objv_equal(v1, v2)); g_assert(!gutil_objv_equal(v2, v1)); g_assert(!gutil_objv_equal(v1, NULL)); g_assert(!gutil_objv_equal(NULL, v1)); v2 = gutil_objv_remove_at(v2, 0); g_assert(!gutil_objv_equal(v1, v2)); g_assert(!gutil_objv_equal(v2, v1)); v1 = gutil_objv_remove_at(v1, 0); g_assert(gutil_objv_remove_at(v1, 0) == v1); g_assert(gutil_objv_equal(v1, NULL)); g_assert(gutil_objv_equal(NULL, v1)); g_assert(!gutil_objv_first(v1)); g_assert(!gutil_objv_last(v1)); g_assert_cmpint(gutil_objv_find(v1, NULL), < ,0); g_assert_cmpint(gutil_objv_find_last(v1, NULL), < ,0); g_assert_cmpint(gutil_objv_find(v1, o1), < ,0); g_assert_cmpint(gutil_objv_find_last(v1, o1), < ,0); g_assert(!gutil_objv_contains(v1, NULL)); g_assert(!gutil_objv_contains(v1, o1)); gutil_objv_free(v1); gutil_objv_free(v2); g_assert(!g_weak_ref_get(&r1)); g_assert(!g_weak_ref_get(&r2)); } /*==========================================================================* * remove *==========================================================================*/ static void test_remove( void) { GObject* o1 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject* o2 = g_object_new(TEST_OBJECT_TYPE, NULL); GObject** v; GWeakRef r1, r2; g_weak_ref_init(&r1, o1); g_weak_ref_init(&r2, o2); v = gutil_objv_add(gutil_objv_add(gutil_objv_add(NULL, o1), o2), o1); g_assert_cmpint(gutil_objv_find(v, o1), == ,0); g_assert_cmpint(gutil_objv_find_last(v, o1), == ,2); v = gutil_objv_remove(v, o1, TRUE); g_assert_cmpuint(gutil_ptrv_length(v), == ,1); g_assert(!gutil_objv_contains(v, o1)); gutil_objv_free(v); g_object_unref(o1); g_object_unref(o2); g_assert(!g_weak_ref_get(&r1)); g_assert(!g_weak_ref_get(&r2)); } /*==========================================================================* * Common *==========================================================================*/ #define TEST_(t) "/objv/" t int main(int argc, char* argv[]) { g_type_init(); g_test_init(&argc, &argv, NULL); g_test_add_func(TEST_("null"), test_null); g_test_add_func(TEST_("basic"), test_basic); g_test_add_func(TEST_("new"), test_new); g_test_add_func(TEST_("insert"), test_insert); g_test_add_func(TEST_("append"), test_append); g_test_add_func(TEST_("copy"), test_copy); g_test_add_func(TEST_("remove"), test_remove); test_init(&test_opt, argc, argv); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000005B000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000002E00000000libglibutil-1714660956.7df665e/test/test_ring0707010000005C000081A40000000000000000000000016633A65C0000004C000000000000000000000000000000000000003700000000libglibutil-1714660956.7df665e/test/test_ring/Makefile# -*- Mode: makefile-gmake -*- EXE = test_ring include ../common/Makefile 0707010000005D000081A40000000000000000000000016633A65C00003208000000000000000000000000000000000000003A00000000libglibutil-1714660956.7df665e/test/test_ring/test_ring.c/* * Copyright (C) 2016-2017 Jolla Ltd. * Contact: Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jolla Ltd nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include "gutil_ring.h" static TestOpt test_opt; /*==========================================================================* * Basic *==========================================================================*/ static void test_basic( void) { int i, n = 5; GUtilRing* r = gutil_ring_new(); /* Test NULL tolerance */ g_assert(!gutil_ring_ref(NULL)); gutil_ring_unref(NULL); gutil_ring_set_free_func(NULL, NULL); gutil_ring_set_free_func(r, NULL); gutil_ring_set_free_func(NULL, g_free); gutil_ring_clear(NULL); gutil_ring_compact(NULL); gutil_ring_reserve(NULL, 0); g_assert(!gutil_ring_size(NULL)); g_assert(!gutil_ring_can_put(NULL, 1)); g_assert(!gutil_ring_put(NULL, NULL)); g_assert(!gutil_ring_put_front(NULL, NULL)); g_assert(!gutil_ring_get(NULL)); g_assert(!gutil_ring_data_at(NULL, 0)); g_assert(!gutil_ring_get_last(NULL)); g_assert(!gutil_ring_drop(NULL, 1)); g_assert(!gutil_ring_drop_last(NULL, 1)); g_assert(!gutil_ring_flatten(NULL, NULL)); g_assert(gutil_ring_ref(r) == r); gutil_ring_unref(r); /* Put some data in */ for (i=0; i<n; i++) { g_assert(gutil_ring_can_put(r, 1)); g_assert(gutil_ring_put(r, GINT_TO_POINTER(i))); } /* Access at invalid index */ g_assert(!gutil_ring_data_at(r, -1)); g_assert(!gutil_ring_data_at(r, n)); /* Peek the data */ for (i=0; i<n; i++) { g_assert(gutil_ring_data_at(r, i) == GINT_TO_POINTER(i)); } /* Get the data */ for (i=0; i<n; i++) { gutil_ring_flatten(r, NULL); gutil_ring_compact(r); g_assert(gutil_ring_get(r) == GINT_TO_POINTER(i)); } /* There should be nothing left */ g_assert(!gutil_ring_get(r)); gutil_ring_compact(r); gutil_ring_compact(r); gutil_ring_clear(r); g_assert(!gutil_ring_flatten(r, &i)); g_assert(!i); gutil_ring_unref(r); } /*==========================================================================* * PutFront *==========================================================================*/ static void test_put_front( void) { int i, n = 5; GUtilRing* r = gutil_ring_new(); for (i=0; i<n; i++) { g_assert(gutil_ring_can_put(r, 1)); g_assert(gutil_ring_put_front(r, GINT_TO_POINTER(n-i-1))); } for (i=0; i<n; i++) { gutil_ring_compact(r); g_assert(gutil_ring_get(r) == GINT_TO_POINTER(i)); } /* The same but take it out with get_last */ for (i=0; i<n; i++) { g_assert(gutil_ring_can_put(r, 1)); g_assert(gutil_ring_put_front(r, GINT_TO_POINTER(n-i-1))); } for (i=0; i<n; i++) { gutil_ring_compact(r); g_assert(gutil_ring_get_last(r) == GINT_TO_POINTER(n-i-1)); } g_assert(!gutil_ring_get_last(r)); gutil_ring_unref(r); } /*==========================================================================* * Drop *==========================================================================*/ static void test_drop( void) { int i, n = 5, get = 3, drop = 3; GUtilRing* r = gutil_ring_sized_new(0,n); /* [01234] */ for (i=0; i<n; i++) { gutil_ring_put(r, GINT_TO_POINTER(i)); } /* ...[34] */ for (i=0; i<get; i++) { g_assert(gutil_ring_get(r) == GINT_TO_POINTER(i)); } /* 567][34 */ for (i=0; i<get; i++) { gutil_ring_put(r, GINT_TO_POINTER(n+i)); } /* ..[67].. */ g_assert(gutil_ring_drop(r, drop) == drop); for (i=0; i<(n-drop); i++) { g_assert(gutil_ring_get(r) == GINT_TO_POINTER(get+drop+i)); } /* Drop more than the size of the buffer (i.e. clear it) */ for (i=0; i<n; i++) { gutil_ring_put(r, GINT_TO_POINTER(i)); } g_assert(!gutil_ring_drop(r, 0)); g_assert(gutil_ring_drop(r, n+1) == n); g_assert(!gutil_ring_drop(r, 1)); g_assert(!gutil_ring_size(r)); gutil_ring_unref(r); } /*==========================================================================* * DropLast *==========================================================================*/ static void test_drop_last( void) { int i, n = 5, get = 2, drop = 3; GUtilRing* r = gutil_ring_sized_new(0,n); /* [01234] */ for (i=0; i<n; i++) { gutil_ring_put(r, GINT_TO_POINTER(i)); } /* ..[234] */ for (i=0; i<get; i++) { g_assert(gutil_ring_get(r) == GINT_TO_POINTER(i)); } /* 56][234 */ for (i=0; i<get; i++) { gutil_ring_put(r, GINT_TO_POINTER(n+i)); } /* ..[23]. */ g_assert(gutil_ring_drop_last(r, drop) == drop); gutil_ring_flatten(r, NULL); for (i=0; i<(n-drop); i++) { g_assert(gutil_ring_get(r) == GINT_TO_POINTER(get+i)); } /* Drop more than the size of the buffer (i.e. clear it) */ for (i=0; i<n; i++) { gutil_ring_put(r, GINT_TO_POINTER(i)); } g_assert(!gutil_ring_drop_last(r, 0)); g_assert(gutil_ring_drop_last(r, n+1) == n); g_assert(!gutil_ring_drop_last(r, 1)); g_assert(!gutil_ring_size(r)); gutil_ring_unref(r); } /*==========================================================================* * Limit *==========================================================================*/ static void test_limit( void) { int i, limit = 5, extra = 2; gint size; gpointer* data; GUtilRing* r = gutil_ring_sized_new(2, limit); g_assert(gutil_ring_reserve(r, limit)); g_assert(!gutil_ring_reserve(r, limit+1)); for (i=0; i<limit; i++) { g_assert(gutil_ring_can_put(r, 1)); g_assert(gutil_ring_put(r, GINT_TO_POINTER(i))); } g_assert(!gutil_ring_can_put(r, 1)); g_assert(gutil_ring_get_last(r) == GINT_TO_POINTER(limit-1)); g_assert(gutil_ring_get_last(r) == GINT_TO_POINTER(limit-2)); g_assert(gutil_ring_put(r, GINT_TO_POINTER(limit-2))); g_assert(gutil_ring_put(r, GINT_TO_POINTER(limit-1))); for (i=0; i<extra; i++) { g_assert(gutil_ring_get(r) == GINT_TO_POINTER(i)); g_assert(gutil_ring_can_put(r, 1)); g_assert(gutil_ring_put(r, GINT_TO_POINTER(i+limit))); } g_assert(gutil_ring_size(r) == limit); data = gutil_ring_flatten(r, &size); g_assert(data); g_assert(size == limit); for (i=0; i<size; i++) { g_assert(data[i] == GINT_TO_POINTER(i+extra)); } g_assert(gutil_ring_get_last(r) == GINT_TO_POINTER(size+extra-1)); gutil_ring_compact(r); data = gutil_ring_flatten(r, &size); g_assert(data); g_assert(size == limit-1); for (i=0; i<size; i++) { g_assert(data[i] == GINT_TO_POINTER(i+extra)); } gutil_ring_clear(r); for (i=0; i<limit; i++) { gutil_ring_put(r, GINT_TO_POINTER(i)); } for (i=0; i<limit; i++) { g_assert(gutil_ring_get(r) == GINT_TO_POINTER(i)); } gutil_ring_unref(r); } /*==========================================================================* * MaxSize *==========================================================================*/ static void test_max_size( void) { int i; const int n = 5; GUtilRing* r = gutil_ring_sized_new(0, -2); g_assert(!gutil_ring_max_size(NULL)); g_assert(gutil_ring_max_size(r) == GUTIL_RING_UNLIMITED_SIZE); gutil_ring_set_max_size(NULL, n); /* This one shouldn't crash */ gutil_ring_set_max_size(r, n); for (i=0; i<n; i++) { g_assert(gutil_ring_put(r, GINT_TO_POINTER(i))); } /* The buffer is full, the next put should fail */ g_assert(!gutil_ring_put(r, GINT_TO_POINTER(i))); g_assert(gutil_ring_size(r) == n); gutil_ring_set_max_size(r, n); g_assert(gutil_ring_size(r) == n); /* Allow more space */ gutil_ring_set_max_size(r, 2*n); for (i=0; i<n; i++) { g_assert(gutil_ring_put(r, GINT_TO_POINTER(i+n))); } /* The buffer is full again */ g_assert(!gutil_ring_put(r, GINT_TO_POINTER(i))); g_assert(gutil_ring_size(r) == 2*n); /* Shrink it */ gutil_ring_set_max_size(r, n); g_assert(gutil_ring_size(r) == n); for (i=0; i<n; i++) { g_assert(gutil_ring_get(r) == GINT_TO_POINTER(i+n)); } g_assert(!gutil_ring_size(r)); /* Negative == unlimited */ gutil_ring_set_max_size(r, -2); g_assert(gutil_ring_max_size(r) == GUTIL_RING_UNLIMITED_SIZE); gutil_ring_unref(r); } /*==========================================================================* * Free *==========================================================================*/ static void test_free_func( gpointer ptr) { int* data = ptr; (*data)++; } static void test_free( void) { int data[5]; const int n = G_N_ELEMENTS(data); const int drop = 2; int i; GUtilRing* r = gutil_ring_new(); gutil_ring_set_free_func(r, test_free_func); memset(data, 0, sizeof(data)); for (i=0; i<n; i++) { gutil_ring_put(r, data + i); } /* Clear it twice */ gutil_ring_clear(r); gutil_ring_clear(r); /* Make sure that test_free_func has been called */ for (i=0; i<n; i++) { g_assert(data[i] == 1); } for (i=0; i<n; i++) { gutil_ring_put(r, data + i); } gutil_ring_get(r); gutil_ring_unref(r); /* test_free_func shouldn't be invoked for the element we retreived */ g_assert(data[0] == 1); for (i=1; i<n; i++) { g_assert(data[i] == 2); } r = gutil_ring_new(); gutil_ring_set_free_func(r, test_free_func); memset(data, 0, sizeof(data)); for (i=0; i<n; i++) { gutil_ring_put(r, data + i); } g_assert(gutil_ring_drop(r, drop) == drop); g_assert(gutil_ring_drop_last(r, drop) == drop); g_assert(gutil_ring_size(r) == (n - 2*drop)); for (i=drop; i<(n-drop); i++) { g_assert(gutil_ring_get(r) == data + i); } for (i=0; i<n; i++) { if (i < drop) { /* Invoked by drop */ g_assert(data[i] == 1); } else if (i >= (n-drop)) { /* Invoked by drop last */ g_assert(data[i] == 1); } else { /* Not invoked for those we have retreived */ g_assert(data[i] == 0); } } gutil_ring_unref(r); } /*==========================================================================* * Common *==========================================================================*/ #define TEST_PREFIX "/ring/" int main(int argc, char* argv[]) { g_test_init(&argc, &argv, NULL); g_test_add_func(TEST_PREFIX "basic", test_basic); g_test_add_func(TEST_PREFIX "put_front", test_put_front); g_test_add_func(TEST_PREFIX "drop", test_drop); g_test_add_func(TEST_PREFIX "drop_last", test_drop_last); g_test_add_func(TEST_PREFIX "max_size", test_max_size); g_test_add_func(TEST_PREFIX "limit", test_limit); g_test_add_func(TEST_PREFIX "free", test_free); test_init(&test_opt, argc, argv); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 0707010000005E000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000002E00000000libglibutil-1714660956.7df665e/test/test_strv0707010000005F000081A40000000000000000000000016633A65C0000004C000000000000000000000000000000000000003700000000libglibutil-1714660956.7df665e/test/test_strv/Makefile# -*- Mode: makefile-gmake -*- EXE = test_strv include ../common/Makefile 07070100000060000081A40000000000000000000000016633A65C00002B60000000000000000000000000000000000000003A00000000libglibutil-1714660956.7df665e/test/test_strv/test_strv.c/* * Copyright (C) 2015-2022 Jolla Ltd. * Copyright (C) 2015-2022 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include "gutil_strv.h" #include "gutil_log.h" static TestOpt test_opt; /*==========================================================================* * Basic *==========================================================================*/ static void test_basic( void) { char** sv = g_strsplit("a,b", ",", 0); g_assert(gutil_strv_length(NULL) == 0); g_assert(gutil_strv_length(sv) == 2); g_assert(!g_strcmp0(gutil_strv_at(sv, 0), "a")); g_assert(!g_strcmp0(gutil_strv_at(sv, 1), "b")); g_assert(!gutil_strv_at(sv, 2)); g_assert(!gutil_strv_at(sv, 3)); g_assert(!gutil_strv_at(NULL, 0)); g_assert(!gutil_strv_strip(NULL)); g_strfreev(sv); } /*==========================================================================* * Last *==========================================================================*/ static void test_last( void) { char** empty = g_new0(char*, 1); char** a = g_strsplit("a", ",", 0); char** ab = g_strsplit("a,b", ",", 0); g_assert(!gutil_strv_last(NULL)); g_assert(!gutil_strv_last(empty)); g_assert(!g_strcmp0(gutil_strv_last(a), "a")); g_assert(!g_strcmp0(gutil_strv_last(ab), "b")); g_strfreev(empty); g_strfreev(a); g_strfreev(ab); } /*==========================================================================* * Add *==========================================================================*/ static void test_addv( void) { char** sv1; char** sv2; g_assert(!gutil_strv_add(NULL, NULL)); g_assert(!gutil_strv_addv(NULL, NULL, NULL)); sv1 = gutil_strv_add(NULL, "a"); g_assert(gutil_strv_addv(sv1, NULL, NULL) == sv1); sv2 = gutil_strv_addv(NULL, "a", NULL); g_assert(gutil_strv_equal(sv1, sv2)); g_strfreev(sv1); sv1 = g_strsplit("a,bb,ccc", ",", 0); sv2 = gutil_strv_addv(sv2, "bb", "ccc", NULL); g_assert(gutil_strv_equal(sv1, sv2)); g_strfreev(sv1); g_strfreev(sv2); } /*==========================================================================* * Equal *==========================================================================*/ static void test_equal( void) { char** sv1 = gutil_strv_addv(NULL, "a", "b", "c", " ", "", NULL); char** sv2 = g_strsplit("a,b,c, ,", ",", 0); char** sv3 = g_strsplit("a,a,a, ,", ",", 0); char** sv4 = g_strsplit("a,b,c,,", ",", 0); char** sv5 = g_strsplit("a,b,c,", ",", 0); char* empty = NULL; g_assert(!gutil_strv_add(NULL, NULL)); g_assert(gutil_strv_equal(NULL, NULL)); g_assert(gutil_strv_equal(NULL, &empty)); g_assert(gutil_strv_equal(&empty, NULL)); g_assert(!gutil_strv_equal(sv1, NULL)); g_assert(!gutil_strv_equal(NULL, sv2)); g_assert(gutil_strv_equal(sv1, sv1)); g_assert(gutil_strv_equal(sv1, sv2)); g_assert(!gutil_strv_equal(sv1, sv3)); g_assert(!gutil_strv_equal(sv1, sv4)); g_assert(!gutil_strv_equal(sv1, sv5)); g_assert(!gutil_strv_equal(sv5, sv1)); g_strfreev(sv1); g_strfreev(sv2); g_strfreev(sv3); g_strfreev(sv4); g_strfreev(sv5); } /*==========================================================================* * Find *==========================================================================*/ static void test_find( void) { char** sv = g_strsplit("a,b,b,c", ",", 0); g_assert(gutil_strv_contains(sv, "a")); g_assert(gutil_strv_contains(sv, "b")); g_assert(gutil_strv_contains(sv, "c")); g_assert(!gutil_strv_contains(sv, "d")); g_assert_cmpint(gutil_strv_find(sv, "b"), == ,1); g_assert_cmpint(gutil_strv_find_last(sv, "a"), == ,0); g_assert_cmpint(gutil_strv_find_last(sv, "b"), == ,2); g_assert_cmpint(gutil_strv_find_last(sv, "c"), == ,3); g_assert_cmpint(gutil_strv_find_last(sv, "d"), == ,-1); g_assert_cmpint(gutil_strv_find_last(NULL, NULL), == ,-1); g_assert(!gutil_strv_contains(sv, NULL)); g_assert(!gutil_strv_contains(NULL, "a")); g_assert(!gutil_strv_contains(NULL, NULL)); g_strfreev(sv); } /*==========================================================================* * Remove *==========================================================================*/ static void test_remove( void) { guint orig_len = 8; char** sv = g_strsplit("a,b,c,b,c,c,d,b", ",", 0); /* 8 elements */ char** sv1 = g_strsplit("a,b,b,c,c,d,b", ",", 0); /* Minus one c */ char** sv2 = g_strsplit("a,c,c,d", ",", 0); /* Minus all b's */ char** sv3 = g_strsplit("a,c,c", ",", 0); /* Minus all (actually one) d */ g_assert(!gutil_strv_remove_all(NULL, NULL)); g_assert(gutil_strv_remove_all(sv, NULL) == sv); g_assert_cmpuint(gutil_strv_length(sv), == ,orig_len); g_assert(sv == gutil_strv_remove_all(sv, "e")); /* "e" is not there */ g_assert_cmpuint(gutil_strv_length(sv), == ,orig_len); g_assert(gutil_strv_equal(sv = gutil_strv_remove_one(sv, "c"), sv1)); g_assert(gutil_strv_equal(sv = gutil_strv_remove_all(sv, "b"), sv2)); g_assert(gutil_strv_equal(sv = gutil_strv_remove_all(sv, "d"), sv3)); g_strfreev(sv); g_strfreev(sv1); g_strfreev(sv2); g_strfreev(sv3); } /*==========================================================================* * RemoveAt *==========================================================================*/ static void test_remove_at( void) { char** sv = g_strsplit("a,b,c", ",", 0); char* c = sv[2]; g_assert(!gutil_strv_remove_at(NULL, 0, FALSE)); g_assert(gutil_strv_remove_at(sv, 3, FALSE) == sv); g_assert(gutil_strv_remove_at(sv, -1, FALSE) == sv); sv = gutil_strv_remove_at(sv, 2, FALSE); g_assert(!gutil_strv_contains(sv, "c")); sv = gutil_strv_remove_at(sv, 0, TRUE); g_assert(!gutil_strv_contains(sv, "a")); g_assert(gutil_strv_length(sv) == 1); g_free(c); g_strfreev(sv); } /*==========================================================================* * RemoveDups *==========================================================================*/ static void test_remove_dups( void) { char** sv = g_strsplit("a,b,c,b,c,c,d,b", ",", 0); /* 8 elements */ char** sv1 = g_strsplit("a,b,c,d", ",", 0); /* No dups */ g_assert(!gutil_strv_remove_dups(NULL)); g_assert(gutil_strv_equal(sv = gutil_strv_remove_dups(sv), sv1)); g_assert(sv == gutil_strv_remove_dups(sv)); /* Nothing to realloc */ g_assert(gutil_strv_equal(sv, sv1)); /* Still equal */ g_strfreev(sv); g_strfreev(sv1); } /*==========================================================================* * Sort *==========================================================================*/ static void test_sort( void) { char** in = g_strsplit("c,a,d,b", ",", 0); char** a1 = g_strsplit("a,b,c,d", ",", 0); char** d1 = g_strsplit("d,c,b,a", ",", 0); char** a2 = gutil_strv_sort(g_strdupv(in), TRUE); char** d2 = gutil_strv_sort(g_strdupv(in), FALSE); g_assert(gutil_strv_equal(a1, a2)); g_assert(gutil_strv_equal(d1, d2)); g_assert(!gutil_strv_sort(NULL, FALSE)); g_strfreev(a1); g_strfreev(a2); g_strfreev(d1); g_strfreev(d2); g_strfreev(in); } /*==========================================================================* * Bsearch *==========================================================================*/ static void test_bsearch( void) { char** a = g_strsplit("a,b,c,d", ",", 0); char** d = g_strsplit("d,c,b,a", ",", 0); g_assert(gutil_strv_sort(a, TRUE) == a); g_assert(gutil_strv_sort(d, FALSE) == d); g_assert(gutil_strv_bsearch(NULL, "a", TRUE) < 0); g_assert(gutil_strv_bsearch(a, NULL, TRUE) < 0); g_assert(gutil_strv_bsearch(a, "x", TRUE) < 0); g_assert(gutil_strv_bsearch(a, "a", TRUE) == 0); g_assert(gutil_strv_bsearch(d, "a", FALSE) == 3); g_strfreev(a); g_strfreev(d); } /*==========================================================================* * Strip *==========================================================================*/ static void test_strip( void) { char** in = g_strsplit(" a,b , c ,", ",", 0); char** expect = g_strsplit("a,b,c,", ",", 0); g_assert(gutil_strv_strip(in) == in); g_assert(gutil_strv_equal(in, expect)); g_strfreev(in); g_strfreev(expect); } /*==========================================================================* * Common *==========================================================================*/ #define TEST_PREFIX "/strv/" int main(int argc, char* argv[]) { g_test_init(&argc, &argv, NULL); g_test_add_func(TEST_PREFIX "basic", test_basic); g_test_add_func(TEST_PREFIX "addv", test_addv); g_test_add_func(TEST_PREFIX "last", test_last); g_test_add_func(TEST_PREFIX "equal", test_equal); g_test_add_func(TEST_PREFIX "find", test_find); g_test_add_func(TEST_PREFIX "remove", test_remove); g_test_add_func(TEST_PREFIX "remove_at", test_remove_at); g_test_add_func(TEST_PREFIX "remove_dups", test_remove_dups); g_test_add_func(TEST_PREFIX "sort", test_sort); g_test_add_func(TEST_PREFIX "bsearch", test_bsearch); g_test_add_func(TEST_PREFIX "strip", test_strip); test_init(&test_opt, argc, argv); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000061000041ED0000000000000000000000026633A65C00000000000000000000000000000000000000000000003100000000libglibutil-1714660956.7df665e/test/test_weakref07070100000062000081A40000000000000000000000016633A65C0000004F000000000000000000000000000000000000003A00000000libglibutil-1714660956.7df665e/test/test_weakref/Makefile# -*- Mode: makefile-gmake -*- EXE = test_weakref include ../common/Makefile 07070100000063000081A40000000000000000000000016633A65C00000DCB000000000000000000000000000000000000004000000000libglibutil-1714660956.7df665e/test/test_weakref/test_weakref.c/* * Copyright (C) 2023 Slava Monich <slava@monich.com> * * You may use this file under the terms of BSD license as follows: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_common.h" #include "gutil_weakref.h" #include <glib-object.h> static TestOpt test_opt; /*==========================================================================* * null *==========================================================================*/ static void test_null() { gutil_weakref_unref(NULL); gutil_weakref_set(NULL, NULL); g_assert(!gutil_weakref_ref(NULL)); g_assert(!gutil_weakref_get(NULL)); } /*==========================================================================* * basic *==========================================================================*/ static void test_basic() { GObject* obj = g_object_new(TEST_OBJECT_TYPE, NULL); GUtilWeakRef* ref = gutil_weakref_new(obj); g_assert(gutil_weakref_ref(ref) == ref); gutil_weakref_unref(ref); g_assert(gutil_weakref_get(ref) == obj); g_object_unref(obj); gutil_weakref_unref(ref); ref = gutil_weakref_new(NULL); g_assert(!gutil_weakref_get(ref)); gutil_weakref_set(ref, obj); g_assert(gutil_weakref_get(ref) == obj); g_object_unref(obj); g_object_unref(obj); /* This actually deallocates the object */ g_assert(!gutil_weakref_get(ref)); gutil_weakref_unref(ref); } /*==========================================================================* * Common *==========================================================================*/ #define TEST_(name) "/weakref/" name int main(int argc, char* argv[]) { G_GNUC_BEGIN_IGNORE_DEPRECATIONS; g_type_init(); G_GNUC_END_IGNORE_DEPRECATIONS; g_test_init(&argc, &argv, NULL); test_init(&test_opt, argc, argv); g_test_add_func(TEST_("null"), test_null); g_test_add_func(TEST_("basic"), test_basic); return g_test_run(); } /* * Local Variables: * mode: C * c-basic-offset: 4 * indent-tabs-mode: nil * End: */ 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!899 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor