├── .gitignore ├── LICENSE ├── Makefile ├── README ├── debian ├── changelog ├── compat ├── control ├── copyright ├── libglibutil-dev.install.in ├── libglibutil.install.in ├── rules └── source │ └── format ├── include ├── gutil_datapack.h ├── gutil_history.h ├── gutil_idlepool.h ├── gutil_idlequeue.h ├── gutil_inotify.h ├── gutil_intarray.h ├── gutil_ints.h ├── gutil_log.h ├── gutil_macros.h ├── gutil_misc.h ├── gutil_objv.h ├── gutil_ring.h ├── gutil_strv.h ├── gutil_timenotify.h ├── gutil_types.h ├── gutil_version.h └── gutil_weakref.h ├── libglibutil.pc.in ├── libglibutil.ver ├── rpm └── libglibutil.spec ├── 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_objv.c ├── gutil_ring.c ├── gutil_strv.c ├── gutil_timenotify.c ├── gutil_version.c └── gutil_weakref.c └── test ├── Makefile ├── common ├── Makefile ├── test_common.h ├── test_main.c └── test_object.c ├── coverage └── run ├── test_datapack ├── Makefile └── test_datapack.c ├── test_history ├── Makefile └── test_history.c ├── test_idlepool ├── Makefile └── test_idlepool.c ├── test_idlequeue ├── Makefile └── test_idlequeue.c ├── test_inotify ├── Makefile └── test_inotify.c ├── test_intarray ├── Makefile └── test_intarray.c ├── test_ints ├── Makefile └── test_ints.c ├── test_log ├── Makefile └── test_log.c ├── test_misc ├── Makefile └── test_misc.c ├── test_objv ├── Makefile └── test_objv.c ├── test_ring ├── Makefile └── test_ring.c ├── test_strv ├── Makefile └── test_strv.c └── test_weakref ├── Makefile └── test_weakref.c /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | test/libglibutil_test.ncb 3 | test/libglibutil_test.opt 4 | test/coverage/full.gcov 5 | test/coverage/libglibutil.gcov 6 | test/coverage/results 7 | debian/.debhelper 8 | debian/files 9 | debian/libglibutil-dev.debhelper.log 10 | debian/libglibutil-dev.install 11 | debian/libglibutil-dev.substvars 12 | debian/libglibutil-dev 13 | debian/libglibutil.debhelper.log 14 | debian/libglibutil.install 15 | debian/libglibutil.postinst.debhelper 16 | debian/libglibutil.postrm.debhelper 17 | debian/libglibutil.substvars 18 | debian/libglibutil 19 | debian/tmp 20 | documentation.list 21 | installroot 22 | build 23 | RPMS 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2023-2025 Slava Monich 2 | Copyright (C) 2014-2022 Jolla Ltd. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the names of the copyright holders nor the names of its 14 | contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 21 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 | THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | .PHONY: clean all debug release coverage pkgconfig install install-dev test 4 | .PHONY: print_debug_lib print_release_lib print_coverage_lib 5 | # 6 | # Required packages 7 | # 8 | 9 | PKGS = glib-2.0 gobject-2.0 10 | 11 | # 12 | # Default target 13 | # 14 | 15 | all: debug release pkgconfig 16 | 17 | # 18 | # Directories 19 | # 20 | 21 | SRC_DIR = src 22 | INCLUDE_DIR = include 23 | BUILD_DIR = build 24 | DEBUG_BUILD_DIR = $(BUILD_DIR)/debug 25 | RELEASE_BUILD_DIR = $(BUILD_DIR)/release 26 | COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage 27 | 28 | # 29 | # Library version 30 | # 31 | 32 | VERSION_FILE = $(INCLUDE_DIR)/gutil_version.h 33 | get_version = $(shell grep -E '^ *\#define +GUTIL_VERSION_$1 +[0-9]+$$' $(VERSION_FILE) | sed 's/ */ /g' | cut -d ' ' -f 3) 34 | 35 | VERSION_MAJOR := $(call get_version,MAJOR) 36 | VERSION_MINOR := $(call get_version,MINOR) 37 | VERSION_MICRO := $(call get_version,MICRO) 38 | 39 | # Version for pkg-config 40 | PCVERSION := $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_MICRO) 41 | 42 | # 43 | # Library name 44 | # 45 | 46 | NAME = glibutil 47 | LIB_NAME = lib$(NAME) 48 | LIB_DEV_SYMLINK = $(LIB_NAME).so 49 | LIB_SYMLINK1 = $(LIB_DEV_SYMLINK).$(VERSION_MAJOR) 50 | LIB_SYMLINK2 = $(LIB_SYMLINK1).$(VERSION_MINOR) 51 | LIB_SONAME = $(LIB_SYMLINK1) 52 | LIB = $(LIB_SONAME).$(VERSION_MINOR).$(VERSION_MICRO) 53 | STATIC_LIB = $(LIB_NAME).a 54 | 55 | # 56 | # Sources 57 | # 58 | 59 | SRC = \ 60 | gutil_datapack.c \ 61 | gutil_history.c \ 62 | gutil_idlepool.c \ 63 | gutil_idlequeue.c \ 64 | gutil_inotify.c \ 65 | gutil_intarray.c \ 66 | gutil_ints.c \ 67 | gutil_log.c \ 68 | gutil_misc.c \ 69 | gutil_ring.c \ 70 | gutil_strv.c \ 71 | gutil_timenotify.c \ 72 | gutil_objv.c \ 73 | gutil_version.c \ 74 | gutil_weakref.c 75 | 76 | # 77 | # Tools and flags 78 | # 79 | 80 | PKG_CONFIG ?= pkg-config 81 | CC ?= $(CROSS_COMPILE)gcc 82 | STRIP ?= strip 83 | LD = $(CC) 84 | WARNINGS ?= -Wall -Wsign-compare 85 | INCLUDES = -I$(INCLUDE_DIR) 86 | BASE_FLAGS = -fPIC 87 | FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \ 88 | -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32 \ 89 | -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_MAX_ALLOWED \ 90 | -MMD -MP $(shell $(PKG_CONFIG) --cflags $(PKGS)) 91 | FULL_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS) -shared -Wl,-soname,$(LIB_SONAME) \ 92 | -Wl,--version-script=$(LIB_NAME).ver 93 | LIBS := $(shell $(PKG_CONFIG) --libs $(PKGS)) 94 | DEBUG_FLAGS = -g 95 | RELEASE_FLAGS = 96 | COVERAGE_FLAGS = -g 97 | 98 | KEEP_SYMBOLS ?= 0 99 | ifneq ($(KEEP_SYMBOLS),0) 100 | RELEASE_FLAGS += -g 101 | endif 102 | 103 | DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS) 104 | RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS) 105 | DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG 106 | RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2 107 | COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) -O0 --coverage 108 | 109 | # 110 | # Files 111 | # 112 | 113 | PKGCONFIG = $(BUILD_DIR)/$(LIB_NAME).pc 114 | DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) 115 | RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o) 116 | COVERAGE_OBJS = $(SRC:%.c=$(COVERAGE_BUILD_DIR)/%.o) 117 | 118 | DEBUG_LIB = $(DEBUG_BUILD_DIR)/$(LIB) 119 | RELEASE_LIB = $(RELEASE_BUILD_DIR)/$(LIB) 120 | DEBUG_LINK = $(DEBUG_BUILD_DIR)/$(LIB_SYMLINK1) 121 | RELEASE_LINK = $(RELEASE_BUILD_DIR)/$(LIB_SYMLINK1) 122 | DEBUG_DEV_LINK = $(DEBUG_BUILD_DIR)/$(LIB_DEV_SYMLINK) 123 | RELEASE_DEV_LINK = $(RELEASE_BUILD_DIR)/$(LIB_DEV_SYMLINK) 124 | DEBUG_STATIC_LIB = $(DEBUG_BUILD_DIR)/$(STATIC_LIB) 125 | RELEASE_STATIC_LIB = $(RELEASE_BUILD_DIR)/$(STATIC_LIB) 126 | COVERAGE_STATIC_LIB = $(COVERAGE_BUILD_DIR)/$(STATIC_LIB) 127 | 128 | # 129 | # Dependencies 130 | # 131 | 132 | DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d) $(COVERAGE_OBJS:%.o=%.d) 133 | ifneq ($(MAKECMDGOALS),clean) 134 | ifneq ($(strip $(DEPS)),) 135 | -include $(DEPS) 136 | endif 137 | endif 138 | 139 | $(PKGCONFIG): | $(BUILD_DIR) 140 | $(DEBUG_OBJS) $(DEBUG_LIB) $(DEBUG_STATIC_LIB): | $(DEBUG_BUILD_DIR) 141 | $(RELEASE_OBJS) $(RELEASE_LIB) $(RELEASE_STATIC_LIB): | $(RELEASE_BUILD_DIR) 142 | $(COVERAGE_OBJS) $(COVERAGE_STATIC_LIB): | $(COVERAGE_BUILD_DIR) 143 | 144 | # 145 | # Rules 146 | # 147 | 148 | debug: $(DEBUG_STATIC_LIB) $(DEBUG_DEV_LINK) 149 | 150 | release: $(RELEASE_STATIC_LIB) $(RELEASE_DEV_LINK) 151 | 152 | coverage: $(COVERAGE_STATIC_LIB) 153 | 154 | pkgconfig: $(PKGCONFIG) 155 | 156 | print_debug_lib: 157 | @echo $(DEBUG_STATIC_LIB) 158 | 159 | print_release_lib: 160 | @echo $(RELEASE_STATIC_LIB) 161 | 162 | print_coverage_lib: 163 | @echo $(COVERAGE_STATIC_LIB) 164 | 165 | clean: 166 | $(MAKE) -C test clean 167 | rm -fr test/coverage/results test/coverage/*.gcov 168 | rm -f *~ $(SRC_DIR)/*~ $(INCLUDE_DIR)/*~ 169 | rm -fr $(BUILD_DIR) RPMS installroot 170 | rm -fr debian/tmp debian/libglibutil debian/libglibutil-dev 171 | rm -f documentation.list debian/files debian/*.substvars 172 | rm -f debian/*.debhelper.log debian/*.debhelper debian/*~ 173 | rm -fr debian/*.install 174 | 175 | test: 176 | $(MAKE) -C test test 177 | 178 | $(BUILD_DIR): 179 | mkdir -p $@ 180 | 181 | $(DEBUG_BUILD_DIR): 182 | mkdir -p $@ 183 | 184 | $(RELEASE_BUILD_DIR): 185 | mkdir -p $@ 186 | 187 | $(COVERAGE_BUILD_DIR): 188 | mkdir -p $@ 189 | 190 | $(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c 191 | $(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ 192 | 193 | $(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c 194 | $(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ 195 | 196 | $(COVERAGE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c 197 | $(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ 198 | 199 | $(DEBUG_LIB): $(DEBUG_OBJS) 200 | $(LD) $(DEBUG_OBJS) $(DEBUG_LDFLAGS) -o $@ $(LIBS) 201 | 202 | $(RELEASE_LIB): $(RELEASE_OBJS) 203 | $(LD) $(RELEASE_OBJS) $(RELEASE_LDFLAGS) -o $@ $(LIBS) 204 | ifeq ($(KEEP_SYMBOLS),0) 205 | $(STRIP) $@ 206 | endif 207 | 208 | $(DEBUG_LINK): $(DEBUG_LIB) 209 | ln -sf $(LIB) $@ 210 | 211 | $(RELEASE_LINK): $(RELEASE_LIB) 212 | ln -sf $(LIB) $@ 213 | 214 | $(DEBUG_DEV_LINK): $(DEBUG_LINK) 215 | ln -sf $(LIB_SYMLINK1) $@ 216 | 217 | $(RELEASE_DEV_LINK): $(RELEASE_LINK) 218 | ln -sf $(LIB_SYMLINK1) $@ 219 | 220 | $(DEBUG_STATIC_LIB): $(DEBUG_OBJS) 221 | $(AR) rc $@ $? 222 | 223 | $(RELEASE_STATIC_LIB): $(RELEASE_OBJS) 224 | $(AR) rc $@ $? 225 | 226 | $(COVERAGE_STATIC_LIB): $(COVERAGE_OBJS) 227 | $(AR) rc $@ $? 228 | 229 | # 230 | # LIBDIR usually gets substituted with arch specific dir. 231 | # It's relative in deb build and can be whatever in rpm build. 232 | # 233 | 234 | LIBDIR ?= usr/lib 235 | ABS_LIBDIR := $(shell echo /$(LIBDIR) | sed -r 's|/+|/|g') 236 | 237 | $(PKGCONFIG): $(LIB_NAME).pc.in Makefile 238 | sed -e 's|@version@|$(PCVERSION)|g' -e 's|@libdir@|$(ABS_LIBDIR)|g' $< > $@ 239 | 240 | debian/%.install: debian/%.install.in 241 | sed 's|@LIBDIR@|$(LIBDIR)|g' $< > $@ 242 | 243 | # 244 | # Install 245 | # 246 | 247 | INSTALL_PERM = 644 248 | 249 | INSTALL = install 250 | INSTALL_DIRS = $(INSTALL) -d 251 | INSTALL_FILES = $(INSTALL) -m $(INSTALL_PERM) 252 | 253 | INSTALL_LIB_DIR = $(DESTDIR)$(ABS_LIBDIR) 254 | INSTALL_INCLUDE_DIR = $(DESTDIR)/usr/include/gutil 255 | INSTALL_PKGCONFIG_DIR = $(DESTDIR)$(ABS_LIBDIR)/pkgconfig 256 | 257 | # 258 | # rpm based systems expect libraries to be 755 259 | # deb based systems expect libraries to be 644 260 | # 261 | # 755 works for both because dh_fixperms removes execute permissions 262 | # from any libraries and other files that don't need it. 263 | # 264 | install: $(INSTALL_LIB_DIR) 265 | $(INSTALL) -m 755 $(RELEASE_LIB) $(INSTALL_LIB_DIR) 266 | ln -sf $(LIB) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK2) 267 | ln -sf $(LIB_SYMLINK2) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK1) 268 | 269 | install-dev: install $(INSTALL_INCLUDE_DIR) $(INSTALL_PKGCONFIG_DIR) 270 | $(INSTALL_FILES) $(INCLUDE_DIR)/*.h $(INSTALL_INCLUDE_DIR) 271 | $(INSTALL_FILES) $(PKGCONFIG) $(INSTALL_PKGCONFIG_DIR) 272 | ln -sf $(LIB_SYMLINK1) $(INSTALL_LIB_DIR)/$(LIB_DEV_SYMLINK) 273 | 274 | $(INSTALL_LIB_DIR): 275 | $(INSTALL_DIRS) $@ 276 | 277 | $(INSTALL_INCLUDE_DIR): 278 | $(INSTALL_DIRS) $@ 279 | 280 | $(INSTALL_PKGCONFIG_DIR): 281 | $(INSTALL_DIRS) $@ 282 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Library of glib utilities. 2 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: libglibutil 2 | Section: libs 3 | Priority: optional 4 | Maintainer: Slava Monich 5 | Build-Depends: debhelper (>= 8.1.3), libglib2.0-dev (>= 2.32) 6 | Standards-Version: 3.8.4 7 | 8 | Package: libglibutil 9 | Section: libs 10 | Architecture: any 11 | Depends: ${shlibs:Depends}, ${misc:Depends} 12 | Description: Library of glib utilities 13 | 14 | Package: libglibutil-dev 15 | Section: libdevel 16 | Architecture: any 17 | Depends: libglibutil (= ${binary:Version}), ${misc:Depends} 18 | Description: Development files for libglibutil 19 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Copyright (C) 2023-2025 Slava Monich 2 | Copyright (C) 2014-2022 Jolla Ltd. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the names of the copyright holders nor the names of its 14 | contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 21 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 | THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /debian/libglibutil-dev.install.in: -------------------------------------------------------------------------------- 1 | debian/tmp/@LIBDIR@/libglibutil.so @LIBDIR@ 2 | debian/tmp/@LIBDIR@/pkgconfig/libglibutil.pc @LIBDIR@/pkgconfig 3 | debian/tmp/usr/include/* usr/include/ 4 | -------------------------------------------------------------------------------- /debian/libglibutil.install.in: -------------------------------------------------------------------------------- 1 | debian/tmp/@LIBDIR@/libglibutil.so.* @LIBDIR@ 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | 4 | # Uncomment this to turn on verbose mode. 5 | #export DH_VERBOSE=1 6 | 7 | LIBDIR=usr/lib/$(shell dpkg-architecture -qDEB_HOST_MULTIARCH) 8 | 9 | override_dh_auto_build: 10 | dh_auto_build -- LIBDIR=$(LIBDIR) release pkgconfig debian/libglibutil.install debian/libglibutil-dev.install 11 | 12 | override_dh_auto_install: 13 | dh_auto_install -- LIBDIR=$(LIBDIR) install-dev 14 | 15 | %: 16 | dh $@ 17 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /include/gutil_datapack.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Slava Monich 3 | * 4 | * You may use this file under the terms of BSD license as follows: 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the names of the copyright holders nor the names of its 16 | * contributors may be used to endorse or promote products derived 17 | * from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | * THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef GUTIL_DATAPACK_H 33 | #define GUTIL_DATAPACK_H 34 | 35 | #include "gutil_types.h" 36 | 37 | /* 38 | * Utilities for packing and unpacking simple data types and structures. 39 | * 40 | * Since 1.0.69 41 | */ 42 | 43 | G_BEGIN_DECLS 44 | 45 | /* 46 | * Compact 7 bits per byte representation of a signed integer with 47 | * redundant sign bits removed. Most significant bit is the continuation 48 | * flag. Bit 0x40 in the first (most significant) byte is the sign bit. 49 | * Unused bits in the most significant chunk must be filled with the 50 | * sign bit. 51 | * 52 | * For positive numbers it's slightly less efficient than encoding unsigned 53 | * numbers because of one extra sign bit (e.g. unsigned number 65 can be 54 | * squeezed into a single byte but the signed one takes 2 bytes). 55 | * 56 | * Examples: 57 | * 58 | * 33 (0x0000000000000021) => 00100001 (0x21) 59 | * -33 (0xffffffffffffffdf) => 01011111 (0x5f) 60 | * 65 (0x0000000000000041) => 10000000 01000001 (0x80 0x41) 61 | * -65 (0xffffffffffffff3f) => 11111111 00111111 (0xff 0x3f) 62 | * 129 (0x0000000000000081) => 10000001 00000001 (0x81 0x01) 63 | * -129 (0xffffffffffffff7f) => 11111110 01111110 (0xfe 0x7f) 64 | */ 65 | 66 | guint 67 | gutil_signed_mbn_size( 68 | gint64 value); 69 | 70 | guint 71 | gutil_signed_mbn_encode( 72 | gpointer buf, 73 | gint64 value); 74 | 75 | guint 76 | gutil_signed_mbn_encode2( 77 | gpointer buf, 78 | gint64 value, 79 | guint value_size); 80 | 81 | gboolean 82 | gutil_signed_mbn_decode( 83 | GUtilRange* in, 84 | gint64* out); 85 | 86 | gboolean 87 | gutil_signed_mbn_decode2( 88 | const GUtilData* in, 89 | gint64* out); 90 | 91 | /* 92 | * Compact 7 bits per byte representation of an unsigned integer with 93 | * redundant zero bits removed. Most significant bit is the continuation 94 | * flag. Unused bits in the first byte (most significant chunk) must be 95 | * filled with zeros. 96 | * 97 | * Examples: 98 | * 99 | * 33 (0x0000000000000021) => 00100001 (0x21) 100 | * 65 (0x0000000000000041) => 01000001 (0x41) 101 | * 129 (0x0000000000000081) => 10000001 00000001 (0x81 0x01) 102 | */ 103 | 104 | guint 105 | gutil_unsigned_mbn_size( 106 | guint64 value); 107 | 108 | guint 109 | gutil_unsigned_mbn_encode( 110 | gpointer buf, 111 | guint64 value); 112 | 113 | guint 114 | gutil_unsigned_mbn_encode2( 115 | gpointer buf, 116 | guint64 value, 117 | guint value_size); 118 | 119 | gboolean 120 | gutil_unsigned_mbn_decode( 121 | GUtilRange* in, 122 | guint64* out); 123 | 124 | gboolean 125 | gutil_unsigned_mbn_decode2( 126 | const GUtilData* in, 127 | guint64* out); 128 | 129 | /* 130 | * TLV is a convenient and extendible way to pack various kinds of data 131 | * into a single memory block. Each entry gets encoded as follows: 132 | * 133 | * +--- 134 | * | T (unsigned MBN) : tag (non-zero) 135 | * +--- 136 | * | L (unsigned MBN) : length (zero if there's no data) 137 | * +--- 138 | * | V (L bytes) : tag specific data (optional) 139 | * +--- 140 | * 141 | * To make API even more convenient, these utilities restrict the tag 142 | * value to INT_MAX which should be enough in most real life situations. 143 | * Also, these utilities assume that tags are non-zero. gutil_tlv_decode() 144 | * returns zero ifno TLV can be pulled out of the input data, and the 145 | * tags array passed to gutil_tlvs_decode() is zero terminated. 146 | */ 147 | 148 | typedef enum gutil_tlvs_decode_flags { 149 | GUTIL_TLVS_DECODE_NO_FLAGS = 0, 150 | GUTIL_TLVS_DECODE_FLAG_SKIP_UNKNOWN_TAGS = 0x1 151 | } GUTIL_TLVS_DECODE_FLAGS; 152 | 153 | guint 154 | gutil_tlv_size( 155 | guint tag, 156 | gsize len); 157 | 158 | gsize 159 | gutil_tlv_encode( 160 | gpointer buf, 161 | guint tag, 162 | const GUtilData* val); 163 | 164 | guint 165 | gutil_tlv_decode( 166 | GUtilRange* in, 167 | GUtilData* val); 168 | 169 | #define GUTIL_TLVS_DECODE_ERROR (-1) 170 | #define GUTIL_TLVS_DECODE_DUPLICATE_TAG (-2) 171 | #define GUTIL_TLVS_DECODE_UNKNOWN_TAG (-3) 172 | 173 | int 174 | gutil_tlvs_decode( 175 | const GUtilData* in, 176 | const guint* tags, 177 | GUtilData* vals, 178 | GUTIL_TLVS_DECODE_FLAGS flags); 179 | 180 | G_END_DECLS 181 | 182 | #endif /* GUTIL_DATAPACK_H */ 183 | 184 | /* 185 | * Local Variables: 186 | * mode: C 187 | * c-basic-offset: 4 188 | * indent-tabs-mode: nil 189 | * End: 190 | */ 191 | -------------------------------------------------------------------------------- /include/gutil_history.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Jolla Ltd. 3 | * Contact: Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of Jolla Ltd nor the names of its contributors may 17 | * be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef GUTIL_HISTORY_H 34 | #define GUTIL_HISTORY_H 35 | 36 | #include "gutil_types.h" 37 | 38 | G_BEGIN_DECLS 39 | 40 | /* 41 | * A history of values. Keeps track of no more than last X values submitted 42 | * within the last Y microseconds. Microsecond precision may sound like a bit 43 | * of an overkill but that's what glib functions like g_get_monotonic_time 44 | * return. 45 | * 46 | * Currently it's only useful for calculating the median but the API could 47 | * be extended to provide access to the individual samples, if anyone ever 48 | * needs that. 49 | * 50 | * Also, it's calculating median rather than the average taking into account 51 | * that samples are not necessarily added to the history at uniform intervals. 52 | * If someone needs the straight average, it's easy enough to add API for that 53 | * too. 54 | * 55 | * When you call gutil_int_history_add but the time hasn't changed since the 56 | * last gutil_int_history_add call, the last value is replaced (as opposed to 57 | * adding a new entry). 58 | */ 59 | 60 | #define GUTIL_HISTORY_SEC ((gint64)(G_USEC_PER_SEC)) 61 | typedef gint64 (*GUtilHistoryTimeFunc)(void); 62 | 63 | GUtilIntHistory* 64 | gutil_int_history_new( 65 | int max_size, 66 | gint64 max_interval); 67 | 68 | GUtilIntHistory* 69 | gutil_int_history_new_full( 70 | int max_size, 71 | gint64 max_interval, 72 | GUtilHistoryTimeFunc time_fn); 73 | 74 | GUtilIntHistory* 75 | gutil_int_history_ref( 76 | GUtilIntHistory* history); 77 | 78 | void 79 | gutil_int_history_unref( 80 | GUtilIntHistory* history); 81 | 82 | guint 83 | gutil_int_history_size( 84 | GUtilIntHistory* history); 85 | 86 | gint64 87 | gutil_int_history_interval( 88 | GUtilIntHistory* history); 89 | 90 | void 91 | gutil_int_history_clear( 92 | GUtilIntHistory* history); 93 | 94 | int 95 | gutil_int_history_add( 96 | GUtilIntHistory* history, 97 | int value); 98 | 99 | int 100 | gutil_int_history_median( 101 | GUtilIntHistory* history, 102 | int default_value); 103 | 104 | G_END_DECLS 105 | 106 | #endif /* GUTIL_HISTORY_H */ 107 | 108 | /* 109 | * Local Variables: 110 | * mode: C 111 | * c-basic-offset: 4 112 | * indent-tabs-mode: nil 113 | * End: 114 | */ 115 | -------------------------------------------------------------------------------- /include/gutil_idlepool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016-2024 Slava Monich 3 | * Copyright (C) 2016-2018 Jolla Ltd. 4 | * 5 | * You may use this file under the terms of the BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef GUTIL_IDLEPOOL_H 34 | #define GUTIL_IDLEPOOL_H 35 | 36 | #include "gutil_types.h" 37 | 38 | G_BEGIN_DECLS 39 | 40 | /* 41 | * This is a glib equivalent of NSAutoreleasePool. Its purpose is to 42 | * temporarily hold a reference, until the next idle callback or until 43 | * the pool is drained manually with gutil_idle_pool_drain(). 44 | * 45 | * Note that the following functions don't add references, they hold 46 | * the references which you have created: 47 | * 48 | * gutil_idle_pool_add_object() 49 | * gutil_idle_pool_add_variant() 50 | * gutil_idle_pool_add_ptr_array() 51 | * gutil_idle_pool_add_bytes() 52 | * 53 | * The following functions, however, do add the reference and hold it 54 | * until the pool is drained: 55 | * 56 | * gutil_idle_pool_add_object_ref() 57 | * gutil_idle_pool_add_variant_ref() 58 | * gutil_idle_pool_add_ptr_array_ref() 59 | * gutil_idle_pool_add_bytes_ref() 60 | */ 61 | 62 | GUtilIdlePool* 63 | gutil_idle_pool_new( 64 | void); 65 | 66 | GUtilIdlePool* 67 | gutil_idle_pool_get( 68 | GUtilIdlePool** shared); 69 | 70 | GUtilIdlePool* 71 | gutil_idle_pool_get_default( 72 | void); /* Since 1.0.76 */ 73 | 74 | GUtilIdlePool* 75 | gutil_idle_pool_ref( 76 | GUtilIdlePool* pool); 77 | 78 | void 79 | gutil_idle_pool_unref( 80 | GUtilIdlePool* pool); 81 | 82 | void 83 | gutil_idle_pool_destroy( 84 | GUtilIdlePool* pool); /* Since 1.0.34 */ 85 | 86 | void 87 | gutil_idle_pool_drain( 88 | GUtilIdlePool* pool); 89 | 90 | gpointer /* Since 1.0.76 */ 91 | gutil_idle_pool_add( 92 | GUtilIdlePool* pool, 93 | gpointer pointer, 94 | GDestroyNotify destroy); 95 | 96 | char** /* Since 1.0.76 */ 97 | gutil_idle_pool_add_strv( 98 | GUtilIdlePool* pool, 99 | char** strv); /* Since 1.0.32 */ 100 | 101 | gpointer /* Since 1.0.76 */ 102 | gutil_idle_pool_add_object( 103 | GUtilIdlePool* pool, 104 | gpointer object); 105 | 106 | GVariant* /* Since 1.0.76 */ 107 | gutil_idle_pool_add_variant( 108 | GUtilIdlePool* pool, 109 | GVariant* variant); 110 | 111 | GPtrArray* /* Since 1.0.76 */ 112 | gutil_idle_pool_add_ptr_array( 113 | GUtilIdlePool* pool, 114 | GPtrArray* array); 115 | 116 | GBytes* /* Since 1.0.76 */ 117 | gutil_idle_pool_add_bytes( 118 | GUtilIdlePool* pool, 119 | GBytes* bytes); /* Since 1.0.34 */ 120 | 121 | gpointer /* Since 1.0.76 */ 122 | gutil_idle_pool_add_object_ref( 123 | GUtilIdlePool* pool, 124 | gpointer object); 125 | 126 | GVariant* /* Since 1.0.76 */ 127 | gutil_idle_pool_add_variant_ref( 128 | GUtilIdlePool* pool, 129 | GVariant* variant); 130 | 131 | GPtrArray* /* Since 1.0.76 */ 132 | gutil_idle_pool_add_ptr_array_ref( 133 | GUtilIdlePool* pool, 134 | GPtrArray* array); 135 | 136 | GBytes* /* Since 1.0.76 */ 137 | gutil_idle_pool_add_bytes_ref( 138 | GUtilIdlePool* pool, 139 | GBytes* bytes); /* Since 1.0.34 */ 140 | 141 | G_END_DECLS 142 | 143 | #endif /* GUTIL_IDLEPOOL_H */ 144 | 145 | /* 146 | * Local Variables: 147 | * mode: C 148 | * c-basic-offset: 4 149 | * indent-tabs-mode: nil 150 | * End: 151 | */ 152 | -------------------------------------------------------------------------------- /include/gutil_idlequeue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Jolla Ltd. 3 | * Contact: Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of Jolla Ltd nor the names of its contributors may 17 | * be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef GUTIL_IDLEQUEUE_H 34 | #define GUTIL_IDLEQUEUE_H 35 | 36 | #include "gutil_types.h" 37 | 38 | G_BEGIN_DECLS 39 | 40 | /* 41 | * GUtilIdleQueue allows to queue idle callbacks, tag them, cancel 42 | * individual callbacks or all of them. 43 | */ 44 | 45 | typedef gsize GUtilIdleQueueTag; 46 | 47 | typedef 48 | void 49 | (*GUtilIdleFunc)( 50 | gpointer data); 51 | 52 | GUtilIdleQueue* 53 | gutil_idle_queue_new(void); 54 | 55 | void 56 | gutil_idle_queue_free( 57 | GUtilIdleQueue* queue); 58 | 59 | GUtilIdleQueue* 60 | gutil_idle_queue_ref( 61 | GUtilIdleQueue* queue); 62 | 63 | void 64 | gutil_idle_queue_unref( 65 | GUtilIdleQueue* queue); 66 | 67 | void 68 | gutil_idle_queue_add( 69 | GUtilIdleQueue* queue, 70 | GUtilIdleFunc run, 71 | gpointer data); 72 | 73 | void 74 | gutil_idle_queue_add_full( 75 | GUtilIdleQueue* queue, 76 | GUtilIdleFunc run, 77 | gpointer data, 78 | GFreeFunc free); 79 | 80 | void 81 | gutil_idle_queue_add_tag( 82 | GUtilIdleQueue* queue, 83 | GUtilIdleQueueTag tag, 84 | GUtilIdleFunc run, 85 | gpointer data); 86 | 87 | void 88 | gutil_idle_queue_add_tag_full( 89 | GUtilIdleQueue* queue, 90 | GUtilIdleQueueTag tag, 91 | GUtilIdleFunc run, 92 | gpointer data, 93 | GFreeFunc free); 94 | 95 | gboolean 96 | gutil_idle_queue_contains_tag( 97 | GUtilIdleQueue* queue, 98 | GUtilIdleQueueTag tag); 99 | 100 | gboolean 101 | gutil_idle_queue_cancel_tag( 102 | GUtilIdleQueue* queue, 103 | GUtilIdleQueueTag tag); 104 | 105 | void 106 | gutil_idle_queue_cancel_all( 107 | GUtilIdleQueue* queue); 108 | 109 | G_END_DECLS 110 | 111 | #endif /* GUTIL_IDLEQUEUE_H */ 112 | 113 | /* 114 | * Local Variables: 115 | * mode: C 116 | * c-basic-offset: 4 117 | * indent-tabs-mode: nil 118 | * End: 119 | */ 120 | -------------------------------------------------------------------------------- /include/gutil_inotify.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2018 Jolla Ltd. 3 | * Contact: Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of Jolla Ltd nor the names of its contributors may 17 | * be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef GUTIL_INOTIFY_H 34 | #define GUTIL_INOTIFY_H 35 | 36 | #include "gutil_types.h" 37 | 38 | G_BEGIN_DECLS 39 | 40 | typedef struct gutil_inotify_watch_callback GUtilInotifyWatchCallback; 41 | 42 | typedef void 43 | (*GUtilInotifyWatchFunc)( 44 | GUtilInotifyWatch* watch, 45 | guint mask, 46 | guint cookie, 47 | const char* name, 48 | void* arg); 49 | 50 | GUtilInotifyWatch* 51 | gutil_inotify_watch_new( 52 | const char* path, 53 | guint32 mask); 54 | 55 | GUtilInotifyWatch* 56 | gutil_inotify_watch_ref( 57 | GUtilInotifyWatch* watch); 58 | 59 | void 60 | gutil_inotify_watch_unref( 61 | GUtilInotifyWatch* watch); 62 | 63 | void 64 | gutil_inotify_watch_destroy( 65 | GUtilInotifyWatch* watch); 66 | 67 | gulong 68 | gutil_inotify_watch_add_handler( 69 | GUtilInotifyWatch* watch, 70 | GUtilInotifyWatchFunc fn, 71 | void* arg); 72 | 73 | void 74 | gutil_inotify_watch_remove_handler( 75 | GUtilInotifyWatch* watch, 76 | gulong id); 77 | 78 | GUtilInotifyWatchCallback* 79 | gutil_inotify_watch_callback_new( 80 | const char* path, 81 | guint32 mask, 82 | GUtilInotifyWatchFunc fn, 83 | void* arg); 84 | 85 | void 86 | gutil_inotify_watch_callback_free( 87 | GUtilInotifyWatchCallback* cb); 88 | 89 | G_END_DECLS 90 | 91 | #endif /* GUTIL_INOTIFY_H */ 92 | 93 | /* 94 | * Local Variables: 95 | * mode: C 96 | * c-basic-offset: 4 97 | * indent-tabs-mode: nil 98 | * End: 99 | */ 100 | -------------------------------------------------------------------------------- /include/gutil_intarray.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Jolla Ltd. 3 | * Contact: Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of Jolla Ltd nor the names of its contributors may 17 | * be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef GUTIL_INTARRAY_H 34 | #define GUTIL_INTARRAY_H 35 | 36 | #include "gutil_types.h" 37 | 38 | G_BEGIN_DECLS 39 | 40 | /* 41 | * This is basically a GArray providing better type safety at compile time. 42 | */ 43 | struct gutil_int_array { 44 | int* data; 45 | guint count; 46 | }; 47 | 48 | GUtilIntArray* 49 | gutil_int_array_new( 50 | void); 51 | 52 | GUtilIntArray* 53 | gutil_int_array_sized_new( 54 | guint reserved_count); 55 | 56 | GUtilIntArray* 57 | gutil_int_array_new_from_vals( 58 | const int* vals, 59 | guint count); 60 | 61 | GUtilIntArray* 62 | gutil_int_array_new_from_value( 63 | int value); 64 | 65 | int* 66 | gutil_int_array_free( 67 | GUtilIntArray* array, 68 | gboolean free_data); 69 | 70 | GUtilInts* 71 | gutil_int_array_free_to_ints( 72 | GUtilIntArray* array); 73 | 74 | GUtilIntArray* 75 | gutil_int_array_ref( 76 | GUtilIntArray* array); 77 | 78 | void 79 | gutil_int_array_unref( 80 | GUtilIntArray* array); 81 | 82 | GUtilIntArray* 83 | gutil_int_array_append( 84 | GUtilIntArray* array, 85 | int val); 86 | 87 | GUtilIntArray* 88 | gutil_int_array_append_vals( 89 | GUtilIntArray* array, 90 | const int* vals, 91 | guint count); 92 | 93 | GUtilIntArray* 94 | gutil_int_array_prepend( 95 | GUtilIntArray* array, 96 | int val); 97 | 98 | GUtilIntArray* 99 | gutil_int_array_prepend_vals( 100 | GUtilIntArray* array, 101 | const int* vals, 102 | guint count); 103 | 104 | GUtilIntArray* 105 | gutil_int_array_insert( 106 | GUtilIntArray* array, 107 | guint pos, 108 | int val); 109 | 110 | GUtilIntArray* 111 | gutil_int_array_insert_vals( 112 | GUtilIntArray* array, 113 | guint pos, 114 | const int* vals, 115 | guint count); 116 | 117 | GUtilIntArray* 118 | gutil_int_array_set_count( 119 | GUtilIntArray* array, 120 | guint count); 121 | 122 | int 123 | gutil_int_array_find( 124 | GUtilIntArray* array, 125 | int value); 126 | 127 | gboolean 128 | gutil_int_array_contains( 129 | GUtilIntArray* array, 130 | int value); 131 | 132 | gboolean 133 | gutil_int_array_remove( 134 | GUtilIntArray* array, 135 | int value); 136 | 137 | gboolean 138 | gutil_int_array_remove_fast( 139 | GUtilIntArray* array, 140 | int value); 141 | 142 | guint 143 | gutil_int_array_remove_all( 144 | GUtilIntArray* array, 145 | int value); 146 | 147 | guint 148 | gutil_int_array_remove_all_fast( 149 | GUtilIntArray* array, 150 | int value); 151 | 152 | GUtilIntArray* 153 | gutil_int_array_remove_index( 154 | GUtilIntArray* array, 155 | guint pos); 156 | 157 | GUtilIntArray* 158 | gutil_int_array_remove_index_fast( 159 | GUtilIntArray* array, 160 | guint pos); 161 | 162 | GUtilIntArray* 163 | gutil_int_array_remove_range( 164 | GUtilIntArray* array, 165 | guint pos, 166 | guint count); 167 | 168 | void 169 | gutil_int_array_sort_ascending( 170 | GUtilIntArray* array); 171 | 172 | void 173 | gutil_int_array_sort_descending( 174 | GUtilIntArray* array); 175 | 176 | G_END_DECLS 177 | 178 | #endif /* GUTIL_INTARRAY_H */ 179 | 180 | /* 181 | * Local Variables: 182 | * mode: C 183 | * c-basic-offset: 4 184 | * indent-tabs-mode: nil 185 | * End: 186 | */ 187 | -------------------------------------------------------------------------------- /include/gutil_ints.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Jolla Ltd. 3 | * Contact: Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of Jolla Ltd nor the names of its contributors may 17 | * be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef GUTIL_INTS_H 34 | #define GUTIL_INTS_H 35 | 36 | #include "gutil_types.h" 37 | 38 | G_BEGIN_DECLS 39 | 40 | /* 41 | * A read-only non-empty array of ints. NULL is the empty array. 42 | * If it's not NULL then it's not empty. 43 | */ 44 | 45 | GUtilInts* 46 | gutil_ints_new( 47 | const int* data, 48 | guint count); 49 | 50 | GUtilInts* 51 | gutil_ints_new_take( 52 | int* data, 53 | guint count); 54 | 55 | GUtilInts* 56 | gutil_ints_new_static( 57 | const int* data, 58 | guint count); 59 | 60 | GUtilInts* 61 | gutil_ints_new_with_free_func( 62 | const int* data, 63 | guint count, 64 | GDestroyNotify free_func, 65 | gpointer user_data); 66 | 67 | GUtilInts* 68 | gutil_ints_new_from_ints( 69 | GUtilInts* ints, 70 | guint offset, 71 | guint count); 72 | 73 | GUtilInts* 74 | gutil_ints_ref( 75 | GUtilInts* ints); 76 | 77 | void 78 | gutil_ints_unref( 79 | GUtilInts* ints); 80 | 81 | int* 82 | gutil_ints_unref_to_data( 83 | GUtilInts* ints, 84 | guint* count); 85 | 86 | const int* 87 | gutil_ints_get_data( 88 | GUtilInts* ints, 89 | guint* count); 90 | 91 | guint 92 | gutil_ints_get_count( 93 | GUtilInts* ints); 94 | 95 | int 96 | gutil_ints_find( 97 | GUtilInts* ints, 98 | int value); 99 | 100 | gboolean 101 | gutil_ints_contains( 102 | GUtilInts* ints, 103 | int value); 104 | 105 | guint 106 | gutil_ints_hash( 107 | gconstpointer ints); 108 | 109 | gboolean 110 | gutil_ints_equal( 111 | gconstpointer a, 112 | gconstpointer b); 113 | 114 | gint 115 | gutil_ints_compare( 116 | gconstpointer a, 117 | gconstpointer b); 118 | 119 | G_END_DECLS 120 | 121 | #endif /* GUTIL_INTS_H */ 122 | 123 | /* 124 | * Local Variables: 125 | * mode: C 126 | * c-basic-offset: 4 127 | * indent-tabs-mode: nil 128 | * End: 129 | */ 130 | -------------------------------------------------------------------------------- /include/gutil_macros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2020 Jolla Ltd. 3 | * Copyright (C) 2014-2020 Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef GUTIL_MACROS_H 34 | #define GUTIL_MACROS_H 35 | 36 | #include 37 | 38 | #define G_CAST(address,type,field) \ 39 | ((type *)((guint8*)(address) - G_STRUCT_OFFSET(type,field))) 40 | 41 | #define G_ALIGN2(value) (((value)+1) & ~1) 42 | #define G_ALIGN4(value) (((value)+3) & ~3) 43 | #define G_ALIGN8(value) (((value)+7) & ~7) 44 | 45 | #ifdef __GNUC__ 46 | # define G_PACKED __attribute__((packed)) 47 | #else 48 | # define G_PACKED 49 | #endif 50 | 51 | #define gutil_slice_free(x) g_slice_free1(sizeof(*(x)), x) /* Since 1.0.49 */ 52 | 53 | #endif /* GUTIL_MACROS_H */ 54 | 55 | /* 56 | * Local Variables: 57 | * mode: C 58 | * c-basic-offset: 4 59 | * indent-tabs-mode: nil 60 | * End: 61 | */ 62 | -------------------------------------------------------------------------------- /include/gutil_misc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023-2024 Slava Monich 3 | * Copyright (C) 2016-2022 Jolla Ltd. 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef GUTIL_MISC_H 34 | #define GUTIL_MISC_H 35 | 36 | #include "gutil_types.h" 37 | 38 | G_BEGIN_DECLS 39 | 40 | void 41 | gutil_disconnect_handlers( 42 | gpointer instance, 43 | gulong* ids, 44 | int count); 45 | 46 | void* 47 | gutil_object_ref( 48 | void* object); /* Since 1.0.71 */ 49 | 50 | void 51 | gutil_object_unref( 52 | void* object); /* Since 1.0.71 */ 53 | 54 | gboolean 55 | gutil_source_remove( 56 | guint id); /* Since 1.0.78 */ 57 | 58 | gboolean 59 | gutil_source_clear( 60 | guint* id); /* Since 1.0.78 */ 61 | 62 | void* 63 | gutil_hex2bin( 64 | const char* str, 65 | gssize len, 66 | void* data); 67 | 68 | char* 69 | gutil_bin2hex( 70 | const void* data, 71 | gsize len, 72 | gboolean upper_case) /* Since 1.0.71 */ 73 | G_GNUC_WARN_UNUSED_RESULT; 74 | 75 | char* 76 | gutil_data2hex( 77 | const GUtilData* data, 78 | gboolean upper_case) /* Since 1.0.71 */ 79 | G_GNUC_WARN_UNUSED_RESULT; 80 | 81 | GBytes* 82 | gutil_hex2bytes( 83 | const char* str, 84 | gssize len); 85 | 86 | #define GUTIL_HEXDUMP_BUFSIZE (70) 87 | #define GUTIL_HEXDUMP_MAXBYTES (16) 88 | 89 | guint 90 | gutil_hexdump( 91 | char* buf, 92 | const void* data, 93 | guint size); /* Since 1.0.29 */ 94 | 95 | gboolean 96 | gutil_parse_int( 97 | const char* str, 98 | int base, 99 | int* value); /* Since 1.0.30 */ 100 | 101 | gboolean 102 | gutil_parse_uint( 103 | const char* str, 104 | int base, 105 | unsigned int* value); /* Since 1.0.53 */ 106 | 107 | gboolean 108 | gutil_parse_int64( 109 | const char* str, 110 | int base, 111 | gint64* value); /* Since 1.0.56 */ 112 | 113 | gboolean 114 | gutil_parse_uint64( 115 | const char* str, 116 | int base, 117 | guint64* value); /* Since 1.0.56 */ 118 | 119 | gboolean 120 | gutil_data_equal( 121 | const GUtilData* data1, 122 | const GUtilData* data2); /* Since 1.0.31 */ 123 | 124 | gboolean 125 | gutil_data_has_prefix( 126 | const GUtilData* data, 127 | const GUtilData* prefix); /* Since 1.0.38 */ 128 | 129 | gboolean 130 | gutil_data_has_suffix( 131 | const GUtilData* data, 132 | const GUtilData* suffix); /* Since 1.0.38 */ 133 | 134 | const GUtilData* 135 | gutil_data_from_string( 136 | GUtilData* data, 137 | const char* str); /* Since 1.0.31 */ 138 | 139 | const GUtilData* 140 | gutil_data_from_bytes( 141 | GUtilData* data, 142 | GBytes* bytes); /* Since 1.0.31 */ 143 | 144 | GUtilData* 145 | gutil_data_new( 146 | const void* bytes, 147 | guint len) /* Since 1.0.72 */ 148 | G_GNUC_WARN_UNUSED_RESULT; 149 | 150 | GUtilData* 151 | gutil_data_copy( 152 | const GUtilData* data) /* Since 1.0.72 */ 153 | G_GNUC_WARN_UNUSED_RESULT; 154 | 155 | GVariant* 156 | gutil_data_copy_as_variant( 157 | const GUtilData* data) /* Since 1.0.74 */ 158 | G_GNUC_WARN_UNUSED_RESULT; 159 | 160 | GBytes* 161 | gutil_bytes_concat( 162 | GBytes* bytes, 163 | ...) /* Since 1.0.37 */ 164 | G_GNUC_WARN_UNUSED_RESULT 165 | G_GNUC_NULL_TERMINATED; 166 | 167 | GBytes* 168 | gutil_bytes_xor( 169 | GBytes* bytes1, 170 | GBytes* bytes2); /* Since 1.0.37 */ 171 | 172 | gboolean 173 | gutil_bytes_equal( 174 | GBytes* bytes, 175 | const void* data, 176 | gsize size); /* Since 1.0.41 */ 177 | 178 | gboolean 179 | gutil_bytes_equal_data( 180 | GBytes* bytes, 181 | const GUtilData* data); /* Since 1.0.41 */ 182 | 183 | gboolean 184 | gutil_bytes_has_prefix( 185 | GBytes* bytes, 186 | const void* data, 187 | gsize size); /* Since 1.0.63 */ 188 | 189 | gboolean 190 | gutil_bytes_has_suffix( 191 | GBytes* bytes, 192 | const void* data, 193 | gsize size); /* Since 1.0.63 */ 194 | 195 | gsize 196 | gutil_ptrv_length( 197 | const void* ptrv); /* Since 1.0.50 */ 198 | 199 | gboolean 200 | gutil_ptrv_is_empty( 201 | const void* ptrv); /* Since 1.0.71 */ 202 | 203 | void 204 | gutil_ptrv_free( 205 | void** ptrv); /* Since 1.0.51 */ 206 | 207 | void* 208 | gutil_memdup( 209 | const void* ptr, 210 | gsize size); /* Since 1.0.52 */ 211 | 212 | gsize 213 | gutil_strlen0( 214 | const char* str); /* Since 1.0.62 */ 215 | 216 | gsize 217 | gutil_range_init_with_bytes( 218 | GUtilRange* range, 219 | GBytes* bytes); /* Since 1.0.55 */ 220 | 221 | gboolean 222 | gutil_range_has_prefix( 223 | const GUtilRange* range, 224 | const GUtilData* prefix); /* Since 1.0.55 */ 225 | 226 | gboolean 227 | gutil_range_skip_prefix( 228 | GUtilRange* range, 229 | const GUtilData* prefix); /* Since 1.0.55 */ 230 | 231 | G_END_DECLS 232 | 233 | #endif /* GUTIL_MISC_H */ 234 | 235 | /* 236 | * Local Variables: 237 | * mode: C 238 | * c-basic-offset: 4 239 | * indent-tabs-mode: nil 240 | * End: 241 | */ 242 | -------------------------------------------------------------------------------- /include/gutil_objv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Slava Monich 3 | * 4 | * You may use this file under the terms of BSD license as follows: 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the names of the copyright holders nor the names of its 16 | * contributors may be used to endorse or promote products derived 17 | * from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | * THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef GUTIL_OBJV_H 33 | #define GUTIL_OBJV_H 34 | 35 | #include "gutil_types.h" 36 | 37 | #include 38 | 39 | /* 40 | * Operations on NULL-terminated array of references to GObjects. 41 | * 42 | * Since 1.0.70 43 | */ 44 | 45 | G_BEGIN_DECLS 46 | 47 | GObject** 48 | gutil_objv_new( 49 | GObject* obj, 50 | ...) /* Since 1.0.72 */ 51 | G_GNUC_WARN_UNUSED_RESULT 52 | G_GNUC_NULL_TERMINATED; 53 | 54 | void 55 | gutil_objv_free( 56 | GObject** objv); 57 | 58 | GObject** 59 | gutil_objv_copy( 60 | GObject* const* objv) 61 | G_GNUC_WARN_UNUSED_RESULT; 62 | 63 | GObject** 64 | gutil_objv_add( 65 | GObject** objv, 66 | GObject* obj) 67 | G_GNUC_WARN_UNUSED_RESULT; 68 | 69 | GObject** 70 | gutil_objv_insert( 71 | GObject** objv, 72 | GObject* obj, 73 | gsize pos) /* Since 1.0.71 */ 74 | G_GNUC_WARN_UNUSED_RESULT; 75 | 76 | GObject** 77 | gutil_objv_append( 78 | GObject** objv, 79 | GObject* const* objs) /* Since 1.0.71 */ 80 | G_GNUC_WARN_UNUSED_RESULT; 81 | 82 | GObject** 83 | gutil_objv_remove( 84 | GObject** objv, 85 | GObject* obj, 86 | gboolean all) 87 | G_GNUC_WARN_UNUSED_RESULT; 88 | 89 | GObject** 90 | gutil_objv_remove_at( 91 | GObject** objv, 92 | gsize pos) 93 | G_GNUC_WARN_UNUSED_RESULT; 94 | 95 | GObject* 96 | gutil_objv_at( 97 | GObject* const* objv, 98 | gsize pos); 99 | 100 | gboolean 101 | gutil_objv_equal( 102 | GObject* const* objv1, 103 | GObject* const* objv2); 104 | 105 | GObject* 106 | gutil_objv_first( 107 | GObject* const* objv); 108 | 109 | GObject* 110 | gutil_objv_last( 111 | GObject* const* objv); 112 | 113 | gssize 114 | gutil_objv_find( 115 | GObject* const* objv, 116 | GObject* obj); 117 | 118 | gssize 119 | gutil_objv_find_last( 120 | GObject* const* objv, 121 | GObject* obj); 122 | 123 | gboolean 124 | gutil_objv_contains( 125 | GObject* const* objv, 126 | GObject* obj); 127 | 128 | G_END_DECLS 129 | 130 | #endif /* GUTIL_OBJV_H */ 131 | 132 | /* 133 | * Local Variables: 134 | * mode: C 135 | * c-basic-offset: 4 136 | * indent-tabs-mode: nil 137 | * End: 138 | */ 139 | -------------------------------------------------------------------------------- /include/gutil_ring.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016-2017 Jolla Ltd. 3 | * Contact: Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of Jolla Ltd nor the names of its contributors may 17 | * be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef GUTIL_RING_H 34 | #define GUTIL_RING_H 35 | 36 | #include "gutil_types.h" 37 | 38 | G_BEGIN_DECLS 39 | 40 | /* 41 | * GLib-style "first in, first out" ring buffer. 42 | * 43 | * Note that `get' functions don't invoke the free function on the 44 | * elements they remove from the ring buffer. The ring buffer only 45 | * frees the elements it removes internally in gutil_ring_clear, 46 | * gutil_ring_drop functions and the last gutil_ring_unref. 47 | */ 48 | 49 | #define GUTIL_RING_UNLIMITED_SIZE (-1) 50 | 51 | GUtilRing* 52 | gutil_ring_new(void); 53 | 54 | GUtilRing* 55 | gutil_ring_sized_new( 56 | gint reserved_size, 57 | gint max_size); 58 | 59 | GUtilRing* 60 | gutil_ring_new_full( 61 | gint reserved_size, 62 | gint max_size, 63 | GDestroyNotify free_func); 64 | 65 | GUtilRing* 66 | gutil_ring_ref( 67 | GUtilRing* ring); 68 | 69 | void 70 | gutil_ring_unref( 71 | GUtilRing* ring); 72 | 73 | void 74 | gutil_ring_set_free_func( 75 | GUtilRing* ring, 76 | GDestroyNotify free_func); 77 | 78 | gint 79 | gutil_ring_max_size( 80 | GUtilRing* ring); 81 | 82 | void 83 | gutil_ring_set_max_size( 84 | GUtilRing* ring, 85 | gint max_size); 86 | 87 | gint 88 | gutil_ring_size( 89 | GUtilRing* ring); 90 | 91 | void 92 | gutil_ring_clear( 93 | GUtilRing* ring); 94 | 95 | void 96 | gutil_ring_compact( 97 | GUtilRing* ring); 98 | 99 | gboolean 100 | gutil_ring_reserve( 101 | GUtilRing* ring, 102 | gint reserved_size); 103 | 104 | gboolean 105 | gutil_ring_can_put( 106 | GUtilRing* ring, 107 | gint num_elements); 108 | 109 | gboolean 110 | gutil_ring_put( 111 | GUtilRing* ring, 112 | gpointer data); 113 | 114 | gboolean 115 | gutil_ring_put_front( 116 | GUtilRing* ring, 117 | gpointer data); 118 | 119 | gpointer 120 | gutil_ring_get( 121 | GUtilRing* ring); 122 | 123 | gpointer 124 | gutil_ring_get_last( 125 | GUtilRing* ring); 126 | 127 | gint 128 | gutil_ring_drop( 129 | GUtilRing* ring, 130 | gint count); 131 | 132 | gint 133 | gutil_ring_drop_last( 134 | GUtilRing* ring, 135 | gint count); 136 | 137 | gpointer 138 | gutil_ring_data_at( 139 | GUtilRing* ring, 140 | gint pos); 141 | 142 | gpointer* 143 | gutil_ring_flatten( 144 | GUtilRing* ring, 145 | gint* size); 146 | 147 | G_END_DECLS 148 | 149 | #endif /* GUTIL_RING_H */ 150 | 151 | /* 152 | * Local Variables: 153 | * mode: C 154 | * c-basic-offset: 4 155 | * indent-tabs-mode: nil 156 | * End: 157 | */ 158 | -------------------------------------------------------------------------------- /include/gutil_strv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2022 Jolla Ltd. 3 | * Copyright (C) 2014-2022 Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef GUTIL_STRV_H 34 | #define GUTIL_STRV_H 35 | 36 | #include "gutil_types.h" 37 | 38 | G_BEGIN_DECLS 39 | 40 | /** 41 | * NULL-tolerant version of g_strv_length 42 | */ 43 | guint 44 | gutil_strv_length( 45 | const GStrV* sv); 46 | 47 | /** 48 | * Returns i-th strings in the array, NULL if index is out of bounds. 49 | */ 50 | const char* 51 | gutil_strv_at( 52 | const GStrV* sv, 53 | guint i); 54 | 55 | /** 56 | * Returns the last string in the array, NULL if there's nothing there. 57 | */ 58 | const char* 59 | gutil_strv_last( 60 | const GStrV* sv); /* Since 1.0.35 */ 61 | 62 | /** 63 | * Returns index of the specified string in the string array, 64 | * or -1 if the string is not found. 65 | */ 66 | int 67 | gutil_strv_find( 68 | const GStrV* sv, 69 | const char* s); 70 | 71 | /** 72 | * Returns index of the last occurrence of specified string in the string 73 | * array, or -1 if the string is not found. 74 | */ 75 | int 76 | gutil_strv_find_last( 77 | const GStrV* sv, 78 | const char* s); /* Since 1.0.62 */ 79 | 80 | /** 81 | * Checks if string array contains the specified string. 82 | */ 83 | gboolean 84 | gutil_strv_contains( 85 | const GStrV* sv, 86 | const char* s); 87 | 88 | /** 89 | * Appends new string to the array. 90 | */ 91 | GStrV* 92 | gutil_strv_add( 93 | GStrV* sv, 94 | const char* s) 95 | G_GNUC_WARN_UNUSED_RESULT; 96 | 97 | /** 98 | * Appends new string(s) to the array. 99 | */ 100 | GStrV* 101 | gutil_strv_addv( 102 | GStrV* sv, 103 | const char* s, 104 | ...) /* Since 1.0.47 */ 105 | G_GNUC_WARN_UNUSED_RESULT 106 | G_GNUC_NULL_TERMINATED; 107 | 108 | /** 109 | * Removes the string from the specified position in the array. 110 | */ 111 | GStrV* 112 | gutil_strv_remove_at( 113 | GStrV* sv, 114 | int pos, 115 | gboolean free_string) 116 | G_GNUC_WARN_UNUSED_RESULT; 117 | 118 | /** 119 | * Removes one or all matching strings from the array and frees them. 120 | */ 121 | GStrV* 122 | gutil_strv_remove( 123 | GStrV* sv, 124 | const char* s, 125 | gboolean remove_all) /* Since 1.0.61 */ 126 | G_GNUC_WARN_UNUSED_RESULT; 127 | 128 | #define gutil_strv_remove_one(sv, s) gutil_strv_remove(sv, s, FALSE) 129 | #define gutil_strv_remove_all(sv, s) gutil_strv_remove(sv, s, TRUE) 130 | 131 | /** 132 | * Checks two string arrays for equality. 133 | */ 134 | gboolean 135 | gutil_strv_equal( 136 | const GStrV* sv1, 137 | const GStrV* sv2); 138 | 139 | /** 140 | * Removes all duplicates from the string array. 141 | */ 142 | GStrV* 143 | gutil_strv_remove_dups( 144 | GStrV* sv); /* Since 1.0.62 */ 145 | 146 | /** 147 | * Sorts the string array 148 | */ 149 | GStrV* 150 | gutil_strv_sort( 151 | GStrV* sv, 152 | gboolean ascending); 153 | 154 | /** 155 | * Binary search in the sorted string array. Returns index of the 156 | * specified string in the string array, or -1 if the string is not 157 | * found. It's basically a version of gutil_strv_find optimized for 158 | * sorted arrays. The string array must be sorted by gutil_strv_sort 159 | * with the same 'ascending' argument. 160 | */ 161 | int 162 | gutil_strv_bsearch( 163 | GStrV* sv, 164 | const char* s, 165 | gboolean ascending); /* Since 1.0.40 */ 166 | 167 | /** 168 | * Removes leading and trailing whitespaces from all strings in the vector. 169 | */ 170 | GStrV* 171 | gutil_strv_strip( 172 | GStrV* sv); 173 | 174 | G_END_DECLS 175 | 176 | #endif /* GUTIL_STRV_H */ 177 | 178 | /* 179 | * Local Variables: 180 | * mode: C 181 | * c-basic-offset: 4 182 | * indent-tabs-mode: nil 183 | * End: 184 | */ 185 | -------------------------------------------------------------------------------- /include/gutil_timenotify.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016-2018 Jolla Ltd. 3 | * Contact: Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of Jolla Ltd nor the names of its contributors may 17 | * be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef GUTIL_TIMENOTIFY_H 34 | #define GUTIL_TIMENOTIFY_H 35 | 36 | #include "gutil_types.h" 37 | 38 | G_BEGIN_DECLS 39 | 40 | typedef void 41 | (*GUtilTimeNotifyFunc)( 42 | GUtilTimeNotify* notify, 43 | void* arg); 44 | 45 | GUtilTimeNotify* 46 | gutil_time_notify_new( 47 | void); 48 | 49 | GUtilTimeNotify* 50 | gutil_time_notify_ref( 51 | GUtilTimeNotify* notify); 52 | 53 | void 54 | gutil_time_notify_unref( 55 | GUtilTimeNotify* notify); 56 | 57 | gulong 58 | gutil_time_notify_add_handler( 59 | GUtilTimeNotify* notify, 60 | GUtilTimeNotifyFunc fn, 61 | void* arg); 62 | 63 | void 64 | gutil_time_notify_remove_handler( 65 | GUtilTimeNotify* notify, 66 | gulong id); 67 | 68 | G_END_DECLS 69 | 70 | #endif /* GUTIL_TIMENOTIFY_H */ 71 | 72 | /* 73 | * Local Variables: 74 | * mode: C 75 | * c-basic-offset: 4 76 | * indent-tabs-mode: nil 77 | * End: 78 | */ 79 | -------------------------------------------------------------------------------- /include/gutil_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2021 Jolla Ltd. 3 | * Copyright (C) 2023 Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef GUTIL_TYPES_H 34 | #define GUTIL_TYPES_H 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | G_BEGIN_DECLS 41 | 42 | typedef char* GStrV; 43 | typedef struct gutil_idle_pool GUtilIdlePool; 44 | typedef struct gutil_idle_queue GUtilIdleQueue; 45 | typedef struct gutil_ints GUtilInts; 46 | typedef struct gutil_int_array GUtilIntArray; 47 | typedef struct gutil_int_history GUtilIntHistory; 48 | typedef struct gutil_inotify_watch GUtilInotifyWatch; 49 | typedef struct gutil_ring GUtilRing; 50 | typedef struct gutil_time_notify GUtilTimeNotify; 51 | typedef struct gutil_weakref GUtilWeakRef; /* Since 1.0.68 */ 52 | 53 | typedef struct gutil_data { 54 | const guint8* bytes; 55 | gsize size; 56 | } GUtilData; 57 | 58 | typedef struct gutil_range { 59 | const guint8* ptr; 60 | const guint8* end; 61 | } GUtilRange; /* Since 1.0.54 */ 62 | 63 | #define GLOG_MODULE_DECL(m) extern GLogModule m; 64 | typedef struct glog_module GLogModule; 65 | 66 | G_END_DECLS 67 | 68 | #endif /* GUTIL_TYPES_H */ 69 | 70 | /* 71 | * Local Variables: 72 | * mode: C 73 | * c-basic-offset: 4 74 | * indent-tabs-mode: nil 75 | * End: 76 | */ 77 | -------------------------------------------------------------------------------- /include/gutil_version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023-2025 Slava Monich 3 | * 4 | * You may use this file under the terms of the BSD license as follows: 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the names of the copyright holders nor the names of its 16 | * contributors may be used to endorse or promote products derived 17 | * from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | * THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef GUTIL_VERSION_H 33 | #define GUTIL_VERSION_H 34 | 35 | #include "gutil_types.h" 36 | 37 | /* 38 | * GUTIL_VERSION_X_Y_Z macros will be added with each release. The fact that 39 | * such macro is defined means that you're compiling against libgutil version 40 | * X.Y.Z or greater. 41 | * 42 | * Since 1.0.69 43 | */ 44 | 45 | G_BEGIN_DECLS 46 | 47 | #define GUTIL_VERSION_MAJOR 1 48 | #define GUTIL_VERSION_MINOR 0 49 | #define GUTIL_VERSION_MICRO 80 50 | #define GUTIL_VERSION_STRING "1.0.80" 51 | 52 | extern const guint gutil_version_major; /* GUTIL_VERSION_MAJOR */ 53 | extern const guint gutil_version_minor; /* GUTIL_VERSION_MINOR */ 54 | extern const guint gutil_version_micro; /* GUTIL_VERSION_MICRO */ 55 | 56 | /* Version as a single word */ 57 | #define GUTIL_VERSION_(v1,v2,v3) \ 58 | ((((v1) & 0x7f) << 24) | \ 59 | (((v2) & 0xfff) << 12) | \ 60 | ((v3) & 0xfff)) 61 | 62 | #define GUTIL_VERSION_MAJOR_(v) (((v) >> 24) & 0x7f) 63 | #define GUTIL_VERSION_MINOR_(v) (((v) >> 12) & 0xfff) 64 | #define GUTIL_VERSION_MICRO_(v) (((v) & 0xfff)) 65 | 66 | /* Current compile time version as a single word */ 67 | #define GUTIL_VERSION GUTIL_VERSION_ \ 68 | (GUTIL_VERSION_MAJOR, GUTIL_VERSION_MINOR, GUTIL_VERSION_MICRO) 69 | 70 | /* Runtime version as a single word */ 71 | #define gutil_version() GUTIL_VERSION_ \ 72 | (gutil_version_major, gutil_version_minor, gutil_version_micro) 73 | 74 | /* Specific versions */ 75 | #define GUTIL_VERSION_1_0_69 GUTIL_VERSION_(1,0,69) 76 | #define GUTIL_VERSION_1_0_70 GUTIL_VERSION_(1,0,70) 77 | #define GUTIL_VERSION_1_0_71 GUTIL_VERSION_(1,0,71) 78 | #define GUTIL_VERSION_1_0_72 GUTIL_VERSION_(1,0,72) 79 | #define GUTIL_VERSION_1_0_73 GUTIL_VERSION_(1,0,73) 80 | #define GUTIL_VERSION_1_0_74 GUTIL_VERSION_(1,0,74) 81 | #define GUTIL_VERSION_1_0_75 GUTIL_VERSION_(1,0,75)) 82 | #define GUTIL_VERSION_1_0_76 GUTIL_VERSION_(1,0,76)) 83 | #define GUTIL_VERSION_1_0_77 GUTIL_VERSION_(1,0,77)) 84 | #define GUTIL_VERSION_1_0_78 GUTIL_VERSION_(1,0,78)) 85 | #define GUTIL_VERSION_1_0_79 GUTIL_VERSION_(1,0,79)) 86 | #define GUTIL_VERSION_1_0_80 GUTIL_VERSION_(1,0,80)) 87 | 88 | G_END_DECLS 89 | 90 | #endif /* GUTIL_VERSION_H */ 91 | 92 | /* 93 | * Local Variables: 94 | * mode: C 95 | * c-basic-offset: 4 96 | * indent-tabs-mode: nil 97 | * End: 98 | */ 99 | -------------------------------------------------------------------------------- /include/gutil_weakref.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Slava Monich 3 | * 4 | * You may use this file under the terms of BSD license as follows: 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the names of the copyright holders nor the names of its 16 | * contributors may be used to endorse or promote products derived 17 | * from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | * THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef GUTIL_WEAKREF_H 33 | #define GUTIL_WEAKREF_H 34 | 35 | #include "gutil_types.h" 36 | 37 | /* 38 | * Ref-countable weak reference can be used to avoid calling g_weak_ref_set() 39 | * too often because it grabs global weak_locations_lock for exclusive access. 40 | * Note that g_weak_ref_set() is also invoked internally by g_weak_ref_init() 41 | * and g_weak_ref_clear(). 42 | * 43 | * g_weak_ref_get() on the other hand only acquires weak_locations_lock 44 | * for read-only access which is less of a bottleneck in a multi-threaded 45 | * environment. And it's generally significantly simpler and faster than 46 | * g_weak_ref_set(). 47 | * 48 | * Since 1.0.68 49 | */ 50 | 51 | G_BEGIN_DECLS 52 | 53 | GUtilWeakRef* 54 | gutil_weakref_new( 55 | gpointer obj); 56 | 57 | GUtilWeakRef* 58 | gutil_weakref_ref( 59 | GUtilWeakRef* ref); 60 | 61 | void 62 | gutil_weakref_unref( 63 | GUtilWeakRef* ref); 64 | 65 | gpointer 66 | gutil_weakref_get( 67 | GUtilWeakRef* ref); 68 | 69 | void 70 | gutil_weakref_set( 71 | GUtilWeakRef* ref, 72 | gpointer obj); 73 | 74 | G_END_DECLS 75 | 76 | #endif /* GUTIL_WEAKREF_H */ 77 | 78 | /* 79 | * Local Variables: 80 | * mode: C 81 | * c-basic-offset: 4 82 | * indent-tabs-mode: nil 83 | * End: 84 | */ 85 | -------------------------------------------------------------------------------- /libglibutil.pc.in: -------------------------------------------------------------------------------- 1 | name=glibutil 2 | libdir=@libdir@ 3 | includedir=/usr/include 4 | 5 | Name: libglibutil 6 | Description: Library of glib utilities 7 | Version: @version@ 8 | Requires.private: glib-2.0 9 | Libs: -L${libdir} -l${name} 10 | Cflags: -I${includedir} -I${includedir}/gutil 11 | -------------------------------------------------------------------------------- /libglibutil.ver: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | GLOG_TYPE_CUSTOM; 4 | GLOG_TYPE_GLIB; 5 | GLOG_TYPE_STDERR; 6 | GLOG_TYPE_STDOUT; 7 | GLOG_TYPE_SYSLOG; 8 | gutil_bin2hex; 9 | gutil_bytes_concat; 10 | gutil_bytes_equal; 11 | gutil_bytes_equal_data; 12 | gutil_bytes_has_prefix; 13 | gutil_bytes_has_suffix; 14 | gutil_bytes_xor; 15 | gutil_data2hex; 16 | gutil_data_copy; 17 | gutil_data_copy_as_variant; 18 | gutil_data_equal; 19 | gutil_data_from_bytes; 20 | gutil_data_from_string; 21 | gutil_data_has_prefix; 22 | gutil_data_has_suffix; 23 | gutil_data_new; 24 | gutil_disconnect_handlers; 25 | gutil_hex2bin; 26 | gutil_hex2bytes; 27 | gutil_hexdump; 28 | gutil_idle_pool_add; 29 | gutil_idle_pool_add_bytes; 30 | gutil_idle_pool_add_bytes_ref; 31 | gutil_idle_pool_add_object; 32 | gutil_idle_pool_add_object_ref; 33 | gutil_idle_pool_add_ptr_array; 34 | gutil_idle_pool_add_ptr_array_ref; 35 | gutil_idle_pool_add_strv; 36 | gutil_idle_pool_add_variant; 37 | gutil_idle_pool_add_variant_ref; 38 | gutil_idle_pool_destroy; 39 | gutil_idle_pool_drain; 40 | gutil_idle_pool_get; 41 | gutil_idle_pool_get_default; 42 | gutil_idle_pool_new; 43 | gutil_idle_pool_ref; 44 | gutil_idle_pool_unref; 45 | gutil_idle_queue_add; 46 | gutil_idle_queue_add_full; 47 | gutil_idle_queue_add_tag; 48 | gutil_idle_queue_add_tag_full; 49 | gutil_idle_queue_cancel_all; 50 | gutil_idle_queue_cancel_tag; 51 | gutil_idle_queue_contains_tag; 52 | gutil_idle_queue_free; 53 | gutil_idle_queue_new; 54 | gutil_idle_queue_ref; 55 | gutil_idle_queue_unref; 56 | gutil_inotify_watch_add_handler; 57 | gutil_inotify_watch_callback_free; 58 | gutil_inotify_watch_callback_new; 59 | gutil_inotify_watch_destroy; 60 | gutil_inotify_watch_new; 61 | gutil_inotify_watch_ref; 62 | gutil_inotify_watch_remove_handler; 63 | gutil_inotify_watch_unref; 64 | gutil_int_array_append; 65 | gutil_int_array_append_vals; 66 | gutil_int_array_contains; 67 | gutil_int_array_find; 68 | gutil_int_array_free; 69 | gutil_int_array_free_to_ints; 70 | gutil_int_array_insert; 71 | gutil_int_array_insert_vals; 72 | gutil_int_array_new; 73 | gutil_int_array_new_from_vals; 74 | gutil_int_array_new_from_value; 75 | gutil_int_array_prepend; 76 | gutil_int_array_prepend_vals; 77 | gutil_int_array_ref; 78 | gutil_int_array_remove; 79 | gutil_int_array_remove_all; 80 | gutil_int_array_remove_all_fast; 81 | gutil_int_array_remove_fast; 82 | gutil_int_array_remove_index; 83 | gutil_int_array_remove_index_fast; 84 | gutil_int_array_remove_range; 85 | gutil_int_array_set_count; 86 | gutil_int_array_sized_new; 87 | gutil_int_array_sort_ascending; 88 | gutil_int_array_sort_descending; 89 | gutil_int_array_unref; 90 | gutil_int_history_add; 91 | gutil_int_history_clear; 92 | gutil_int_history_interval; 93 | gutil_int_history_median; 94 | gutil_int_history_new; 95 | gutil_int_history_new_full; 96 | gutil_int_history_ref; 97 | gutil_int_history_size; 98 | gutil_int_history_unref; 99 | gutil_ints_compare; 100 | gutil_ints_contains; 101 | gutil_ints_equal; 102 | gutil_ints_find; 103 | gutil_ints_get_count; 104 | gutil_ints_get_data; 105 | gutil_ints_hash; 106 | gutil_ints_new; 107 | gutil_ints_new_from_ints; 108 | gutil_ints_new_static; 109 | gutil_ints_new_take; 110 | gutil_ints_new_with_free_func; 111 | gutil_ints_ref; 112 | gutil_ints_unref; 113 | gutil_ints_unref_to_data; 114 | gutil_log; 115 | gutil_log_assert; 116 | gutil_log_default; 117 | gutil_log_description; 118 | gutil_log_dump; 119 | gutil_log_dump_bytes; 120 | gutil_log_enabled; 121 | gutil_log_func; 122 | gutil_log_func2; 123 | gutil_log_get_type; 124 | gutil_log_glib; 125 | gutil_log_glib2; 126 | gutil_log_parse_option; 127 | gutil_log_set_timestamp_format; 128 | gutil_log_set_type; 129 | gutil_log_stderr; 130 | gutil_log_stderr2; 131 | gutil_log_stdio; 132 | gutil_log_stdout; 133 | gutil_log_stdout2; 134 | gutil_log_syslog; 135 | gutil_log_syslog2; 136 | gutil_log_tid; 137 | gutil_log_timestamp; 138 | gutil_logv; 139 | gutil_memdup; 140 | gutil_object_ref; 141 | gutil_object_unref; 142 | gutil_objv_add; 143 | gutil_objv_append; 144 | gutil_objv_at; 145 | gutil_objv_contains; 146 | gutil_objv_copy; 147 | gutil_objv_equal; 148 | gutil_objv_find; 149 | gutil_objv_find_last; 150 | gutil_objv_first; 151 | gutil_objv_free; 152 | gutil_objv_insert; 153 | gutil_objv_last; 154 | gutil_objv_new; 155 | gutil_objv_remove; 156 | gutil_objv_remove_at; 157 | gutil_parse_int; 158 | gutil_parse_int64; 159 | gutil_parse_uint; 160 | gutil_parse_uint64; 161 | gutil_ptrv_free; 162 | gutil_ptrv_is_empty; 163 | gutil_ptrv_length; 164 | gutil_range_has_prefix; 165 | gutil_range_init_with_bytes; 166 | gutil_range_skip_prefix; 167 | gutil_ring_can_put; 168 | gutil_ring_clear; 169 | gutil_ring_compact; 170 | gutil_ring_data_at; 171 | gutil_ring_drop; 172 | gutil_ring_drop_last; 173 | gutil_ring_flatten; 174 | gutil_ring_get; 175 | gutil_ring_get_last; 176 | gutil_ring_max_size; 177 | gutil_ring_new; 178 | gutil_ring_new_full; 179 | gutil_ring_put; 180 | gutil_ring_put_front; 181 | gutil_ring_ref; 182 | gutil_ring_reserve; 183 | gutil_ring_set_free_func; 184 | gutil_ring_set_max_size; 185 | gutil_ring_size; 186 | gutil_ring_sized_new; 187 | gutil_ring_unref; 188 | gutil_signed_mbn_decode; 189 | gutil_signed_mbn_decode2; 190 | gutil_signed_mbn_encode; 191 | gutil_signed_mbn_encode2; 192 | gutil_signed_mbn_size; 193 | gutil_source_clear; 194 | gutil_source_remove; 195 | gutil_strlen0; 196 | gutil_strv_add; 197 | gutil_strv_addv; 198 | gutil_strv_at; 199 | gutil_strv_bsearch; 200 | gutil_strv_contains; 201 | gutil_strv_equal; 202 | gutil_strv_find; 203 | gutil_strv_find_last; 204 | gutil_strv_last; 205 | gutil_strv_length; 206 | gutil_strv_remove; 207 | gutil_strv_remove_at; 208 | gutil_strv_remove_dups; 209 | gutil_strv_sort; 210 | gutil_strv_strip; 211 | gutil_time_notify_add_handler; 212 | gutil_time_notify_new; 213 | gutil_time_notify_ref; 214 | gutil_time_notify_remove_handler; 215 | gutil_time_notify_unref; 216 | gutil_tlv_decode; 217 | gutil_tlv_encode; 218 | gutil_tlvs_decode; 219 | gutil_tlv_size; 220 | gutil_unsigned_mbn_decode; 221 | gutil_unsigned_mbn_decode2; 222 | gutil_unsigned_mbn_encode; 223 | gutil_unsigned_mbn_encode2; 224 | gutil_unsigned_mbn_size; 225 | gutil_version_major; 226 | gutil_version_micro; 227 | gutil_version_minor; 228 | gutil_weakref_get; 229 | gutil_weakref_new; 230 | gutil_weakref_ref; 231 | gutil_weakref_set; 232 | gutil_weakref_unref; 233 | local: 234 | *; 235 | }; 236 | -------------------------------------------------------------------------------- /rpm/libglibutil.spec: -------------------------------------------------------------------------------- 1 | Name: libglibutil 2 | 3 | Version: 1.0.80 4 | Release: 0 5 | Summary: Library of glib utilities 6 | License: BSD 7 | URL: https://github.com/sailfishos/libglibutil 8 | Source: %{name}-%{version}.tar.bz2 9 | 10 | %define glib_version 2.32 11 | 12 | BuildRequires: pkgconfig 13 | BuildRequires: pkgconfig(glib-2.0) >= %{glib_version} 14 | 15 | # license macro requires rpm >= 4.11 16 | BuildRequires: pkgconfig(rpm) 17 | %define license_support %(pkg-config --exists 'rpm >= 4.11'; echo $?) 18 | 19 | # make_build macro appeared in rpm 4.12 20 | %{!?make_build: %define make_build make %{_smp_mflags}} 21 | 22 | Requires: glib2 >= %{glib_version} 23 | Requires(post): /sbin/ldconfig 24 | Requires(postun): /sbin/ldconfig 25 | 26 | %description 27 | Provides glib utility functions and macros 28 | 29 | %package devel 30 | Summary: Development library for %{name} 31 | Requires: %{name} = %{version} 32 | Requires: pkgconfig(glib-2.0) >= %{glib_version} 33 | 34 | %description devel 35 | This package contains the development library for %{name}. 36 | 37 | %prep 38 | %setup -q 39 | 40 | %build 41 | %make_build LIBDIR=%{_libdir} KEEP_SYMBOLS=1 release pkgconfig 42 | 43 | %install 44 | make LIBDIR=%{_libdir} DESTDIR=%{buildroot} install-dev 45 | 46 | %check 47 | make -C test test 48 | 49 | %post -p /sbin/ldconfig 50 | 51 | %postun -p /sbin/ldconfig 52 | 53 | %files 54 | %defattr(-,root,root,-) 55 | %{_libdir}/%{name}.so.* 56 | %if %{license_support} == 0 57 | %license LICENSE 58 | %endif 59 | 60 | %files devel 61 | %defattr(-,root,root,-) 62 | %dir %{_includedir}/gutil 63 | %{_libdir}/pkgconfig/*.pc 64 | %{_libdir}/%{name}.so 65 | %{_includedir}/gutil/*.h 66 | -------------------------------------------------------------------------------- /src/gutil_history.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017-2023 Slava Monich 3 | * Copyright (C) 2017 Jolla Ltd. 4 | * 5 | * You may use this file under the terms of the BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "gutil_history.h" 34 | #include "gutil_log.h" 35 | 36 | #if __GNUC__ >= 4 37 | #pragma GCC visibility push(default) 38 | #endif 39 | 40 | #define GUTIL_HISTORY_DEFAULT_TIME_FUNC g_get_monotonic_time 41 | 42 | typedef struct gutil_int_history_entry { 43 | gint64 time; 44 | int value; 45 | } GUtilIntHistoryEntry; 46 | 47 | struct gutil_int_history { 48 | gint ref_count; 49 | GUtilHistoryTimeFunc time; 50 | gint64 max_interval; 51 | int first; /* Oldest position (inclusive) */ 52 | int last; /* Latest position (inclusive) */ 53 | int max_size; /* Number of entries */ 54 | GUtilIntHistoryEntry entry[1]; 55 | }; 56 | 57 | GUtilIntHistory* 58 | gutil_int_history_new( 59 | int max_size, 60 | gint64 max_interval) 61 | { 62 | return gutil_int_history_new_full(max_size, max_interval, NULL); 63 | } 64 | 65 | GUtilIntHistory* 66 | gutil_int_history_new_full( 67 | int max_size, 68 | gint64 max_interval, 69 | GUtilHistoryTimeFunc fn) 70 | { 71 | if (max_size > 0 && max_interval > 0) { 72 | /* 73 | * We don't allow to dynamically change the maximum history size 74 | * so we can allocate the whole thing from a single memory block. 75 | */ 76 | GUtilIntHistory* h = g_malloc0(sizeof(GUtilIntHistory) + 77 | (max_size - 1) * sizeof(GUtilIntHistoryEntry)); 78 | 79 | g_atomic_int_set(&h->ref_count, 1); 80 | h->max_size = max_size; 81 | h->max_interval = max_interval; 82 | h->first = h->last = -1; 83 | h->time = fn ? fn : GUTIL_HISTORY_DEFAULT_TIME_FUNC; 84 | return h; 85 | } 86 | return NULL; 87 | } 88 | 89 | GUtilIntHistory* 90 | gutil_int_history_ref( 91 | GUtilIntHistory* h) 92 | { 93 | if (G_LIKELY(h)) { 94 | GASSERT(h->ref_count > 0); 95 | g_atomic_int_inc(&h->ref_count); 96 | } 97 | return h; 98 | } 99 | 100 | void 101 | gutil_int_history_unref( 102 | GUtilIntHistory* h) 103 | { 104 | if (G_LIKELY(h)) { 105 | GASSERT(h->ref_count > 0); 106 | if (g_atomic_int_dec_and_test(&h->ref_count)) { 107 | g_free(h); 108 | } 109 | } 110 | } 111 | 112 | static 113 | gboolean 114 | gutil_int_history_flush( 115 | GUtilIntHistory* h, 116 | const gint64 now) 117 | { 118 | const gint64 cutoff = now - h->max_interval; 119 | 120 | if (h->entry[h->last].time >= cutoff) { 121 | /* At least the last entry is valid */ 122 | while (h->entry[h->first].time < cutoff) { 123 | h->first = (h->first + 1) % h->max_size; 124 | } 125 | return TRUE; 126 | } else { 127 | /* The last entry has expired */ 128 | h->last = h->first = -1; 129 | return FALSE; 130 | } 131 | } 132 | 133 | guint 134 | gutil_int_history_size( 135 | GUtilIntHistory* h) 136 | { 137 | if (G_LIKELY(h) && h->last >= 0) { 138 | if (gutil_int_history_flush(h, h->time())) { 139 | if (h->first > h->last) { 140 | return (h->max_size + h->last - h->first + 1); 141 | } else { 142 | GASSERT(h->last > h->first); 143 | return (h->last - h->first + 1); 144 | } 145 | } 146 | } 147 | return 0; 148 | } 149 | 150 | gint64 151 | gutil_int_history_interval( 152 | GUtilIntHistory* h) 153 | { 154 | if (G_LIKELY(h) && h->last >= 0) { 155 | const gint64 now = h->time(); 156 | 157 | if (gutil_int_history_flush(h, now)) { 158 | return now - h->entry[h->first].time; 159 | } 160 | } 161 | return 0; 162 | } 163 | 164 | void 165 | gutil_int_history_clear( 166 | GUtilIntHistory* h) 167 | { 168 | if (G_LIKELY(h)) { 169 | h->last = h->first = -1; 170 | } 171 | } 172 | 173 | 174 | static 175 | int 176 | gutil_int_history_median_at( 177 | GUtilIntHistory* h, 178 | const gint64 now) 179 | { 180 | /* The caller has already checked that the history is not empty */ 181 | if (h->first == h->last) { 182 | return h->entry[h->last].value; 183 | } else { 184 | int pos = h->first; 185 | int v = h->entry[pos].value; 186 | gint64 t = h->entry[pos].time; 187 | gint64 dt = 0; 188 | gint64 area = 0; 189 | 190 | while (pos != h->last) { 191 | gint64 t1; 192 | int v1; 193 | 194 | pos = (pos + 1) % h->max_size; 195 | t1 = h->entry[pos].time; 196 | v1 = h->entry[pos].value; 197 | dt += t1 - t; 198 | area += (t1 - t)*(v + v1)/2; 199 | t = t1; 200 | v = v1; 201 | } 202 | /* Integral area divided by time */ 203 | return (int)(area/dt); 204 | } 205 | } 206 | 207 | int 208 | gutil_int_history_add( 209 | GUtilIntHistory* h, 210 | int value) 211 | { 212 | if (G_LIKELY(h)) { 213 | gint64 now = h->time(); 214 | 215 | if (h->last < 0 || !gutil_int_history_flush(h, now)) { 216 | h->last = h->first = 0; 217 | } else { 218 | const gint64 last_time = h->entry[h->last].time; 219 | 220 | if (now > last_time) { 221 | /* Need a new entry */ 222 | h->last = (h->last + 1) % h->max_size; 223 | if (h->last == h->first) { 224 | h->first = (h->first + 1) % h->max_size; 225 | } 226 | } else if (now < last_time) { 227 | /* Time goes back? */ 228 | now = last_time; 229 | } 230 | } 231 | h->entry[h->last].time = now; 232 | h->entry[h->last].value = value; 233 | return gutil_int_history_median_at(h, now); 234 | } 235 | return 0; 236 | } 237 | 238 | int 239 | gutil_int_history_median( 240 | GUtilIntHistory* h, 241 | int default_value) 242 | { 243 | if (G_LIKELY(h) && h->last >= 0) { 244 | const gint64 now = h->time(); 245 | 246 | if (gutil_int_history_flush(h, now)) { 247 | return gutil_int_history_median_at(h, now); 248 | } 249 | } 250 | return default_value; 251 | } 252 | 253 | /* 254 | * Local Variables: 255 | * mode: C 256 | * c-basic-offset: 4 257 | * indent-tabs-mode: nil 258 | * End: 259 | */ 260 | -------------------------------------------------------------------------------- /src/gutil_idlequeue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017-2024 Slava Monich 3 | * Copyright (C) 2017-2020 Jolla Ltd. 4 | * 5 | * You may use this file under the terms of the BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "gutil_idlequeue.h" 34 | #include "gutil_macros.h" 35 | #include "gutil_misc.h" 36 | #include "gutil_log.h" 37 | 38 | #if __GNUC__ >= 4 39 | #pragma GCC visibility push(default) 40 | #endif 41 | 42 | typedef struct gutil_idle_queue_item GUtilIdleQueueItem; 43 | 44 | struct gutil_idle_queue_item { 45 | GUtilIdleQueueItem* next; 46 | GUtilIdleQueueTag tag; 47 | gpointer data; 48 | GUtilIdleFunc run; 49 | GFreeFunc destroy; 50 | gboolean completed; 51 | }; 52 | 53 | struct gutil_idle_queue { 54 | gint ref_count; 55 | guint source_id; 56 | GUtilIdleQueueItem* first; 57 | GUtilIdleQueueItem* last; 58 | }; 59 | 60 | static 61 | void 62 | gutil_idle_queue_item_destroy( 63 | GUtilIdleQueueItem* item) 64 | { 65 | GASSERT(item->completed); 66 | if (item->destroy) { 67 | item->destroy(item->data); 68 | } 69 | gutil_slice_free(item); 70 | } 71 | 72 | static 73 | gboolean 74 | gutil_idle_queue_run( 75 | gpointer data) 76 | { 77 | GUtilIdleQueue* q = data; 78 | GUtilIdleQueueItem* item; 79 | GUtilIdleQueueItem* done = NULL; 80 | 81 | /* 82 | * Mark all currently existing items as as completed. Callbacks 83 | * that we are about to invoke may add more items, those we are 84 | * not supposed to run until the next idle loop. Also, note that 85 | * callbacks may cancel some of the completed items, that's why 86 | * we can't remove them from the list just yet. 87 | */ 88 | for (item = q->first; item; item = item->next) { 89 | item->completed = TRUE; 90 | } 91 | 92 | while ((item = q->first) && item->completed) { 93 | /* Remove this one from the list */ 94 | q->first = item->next; 95 | if (!q->first) { 96 | q->last = NULL; 97 | } 98 | 99 | /* Place it to the "done" list */ 100 | item->next = done; 101 | done = item; 102 | 103 | /* Invoke the callbacks */ 104 | if (item->run) { 105 | item->run(item->data); 106 | } 107 | 108 | if (item->destroy) { 109 | item->destroy(item->data); 110 | } 111 | } 112 | 113 | /* Free the completed items */ 114 | g_slice_free_chain(GUtilIdleQueueItem, done, next); 115 | 116 | if (q->first) { 117 | /* New callbacks have been added */ 118 | return G_SOURCE_CONTINUE; 119 | } else { 120 | q->source_id = 0; 121 | return G_SOURCE_REMOVE; 122 | } 123 | } 124 | 125 | GUtilIdleQueue* 126 | gutil_idle_queue_new() 127 | { 128 | GUtilIdleQueue* q = g_slice_new0(GUtilIdleQueue); 129 | 130 | g_atomic_int_set(&q->ref_count, 1); 131 | return q; 132 | } 133 | 134 | void 135 | gutil_idle_queue_free( 136 | GUtilIdleQueue* q) 137 | { 138 | gutil_idle_queue_cancel_all(q); 139 | gutil_idle_queue_unref(q); 140 | } 141 | 142 | GUtilIdleQueue* 143 | gutil_idle_queue_ref( 144 | GUtilIdleQueue* q) 145 | { 146 | if (G_LIKELY(q)) { 147 | GASSERT(q->ref_count > 0); 148 | g_atomic_int_inc(&q->ref_count); 149 | } 150 | return q; 151 | } 152 | 153 | void 154 | gutil_idle_queue_unref( 155 | GUtilIdleQueue* q) 156 | { 157 | if (G_LIKELY(q)) { 158 | GASSERT(q->ref_count > 0); 159 | if (g_atomic_int_dec_and_test(&q->ref_count)) { 160 | gutil_idle_queue_cancel_all(q); 161 | gutil_slice_free(q); 162 | } 163 | } 164 | } 165 | 166 | void 167 | gutil_idle_queue_add( 168 | GUtilIdleQueue* q, 169 | GUtilIdleFunc run, 170 | gpointer data) 171 | { 172 | gutil_idle_queue_add_tag_full(q, 0, run, data, NULL); 173 | } 174 | 175 | void 176 | gutil_idle_queue_add_full( 177 | GUtilIdleQueue* q, 178 | GUtilIdleFunc run, 179 | gpointer data, 180 | GFreeFunc free) 181 | { 182 | gutil_idle_queue_add_tag_full(q, 0, run, data, free); 183 | } 184 | 185 | void 186 | gutil_idle_queue_add_tag( 187 | GUtilIdleQueue* q, 188 | GUtilIdleQueueTag tag, 189 | GUtilIdleFunc run, 190 | gpointer data) 191 | { 192 | gutil_idle_queue_add_tag_full(q, tag, run, data, NULL); 193 | } 194 | 195 | void 196 | gutil_idle_queue_add_tag_full( 197 | GUtilIdleQueue* q, 198 | GUtilIdleQueueTag tag, 199 | GUtilIdleFunc run, 200 | gpointer data, 201 | GFreeFunc destroy) 202 | { 203 | if (G_LIKELY(q)) { 204 | GUtilIdleQueueItem* item = g_slice_new0(GUtilIdleQueueItem); 205 | 206 | /* Fill the item */ 207 | item->tag = tag; 208 | item->run = run; 209 | item->destroy = destroy; 210 | item->data = data; 211 | 212 | /* Add it to the queue */ 213 | if (q->last) { 214 | GASSERT(q->first); 215 | q->last->next = item; 216 | } else { 217 | GASSERT(!q->first); 218 | q->first = item; 219 | } 220 | q->last = item; 221 | 222 | /* Schedule the callback if necessary */ 223 | if (!q->source_id) { 224 | q->source_id = g_idle_add(gutil_idle_queue_run, q); 225 | } 226 | } else if (destroy) { 227 | destroy(data); 228 | } 229 | } 230 | 231 | gboolean 232 | gutil_idle_queue_contains_tag( 233 | GUtilIdleQueue* q, 234 | GUtilIdleQueueTag tag) 235 | { 236 | if (G_LIKELY(q)) { 237 | const GUtilIdleQueueItem* item; 238 | for (item = q->first; item; item = item->next) { 239 | if (item->tag == tag) { 240 | return TRUE; 241 | } 242 | } 243 | } 244 | return FALSE; 245 | } 246 | 247 | static 248 | void 249 | gutil_idle_queue_cancel_first( 250 | GUtilIdleQueue* q) 251 | { 252 | GUtilIdleQueueItem* item = q->first; 253 | q->first = item->next; 254 | if (!q->first) { 255 | q->last = NULL; 256 | } 257 | gutil_idle_queue_item_destroy(item); 258 | } 259 | 260 | gboolean 261 | gutil_idle_queue_cancel_tag( 262 | GUtilIdleQueue* q, 263 | GUtilIdleQueueTag tag) 264 | { 265 | if (G_LIKELY(q) && q->first) { 266 | GUtilIdleQueueItem* item = q->first; 267 | if (item->tag == tag) { 268 | item->completed = TRUE; 269 | gutil_idle_queue_cancel_first(q); 270 | GASSERT(q->source_id); 271 | if (!q->first) { 272 | gutil_source_clear(&q->source_id); 273 | } 274 | return TRUE; 275 | } else { 276 | GUtilIdleQueueItem* prev = item; 277 | for (item = item->next; item; prev = item, item = item->next) { 278 | if (item->tag == tag) { 279 | if (item->next) { 280 | prev->next = item->next; 281 | } else { 282 | GASSERT(q->last == item); 283 | prev->next = NULL; 284 | q->last = prev; 285 | } 286 | item->completed = TRUE; 287 | gutil_idle_queue_item_destroy(item); 288 | return TRUE; 289 | } 290 | } 291 | } 292 | } 293 | return FALSE; 294 | } 295 | 296 | void 297 | gutil_idle_queue_cancel_all( 298 | GUtilIdleQueue* q) 299 | { 300 | if (G_LIKELY(q)) { 301 | GUtilIdleQueueItem* item; 302 | for (item = q->first; item; item = item->next) { 303 | item->completed = TRUE; 304 | } 305 | while (q->first && q->first->completed) { 306 | gutil_idle_queue_cancel_first(q); 307 | } 308 | if (!q->first) { 309 | gutil_source_clear(&q->source_id); 310 | } 311 | } 312 | } 313 | 314 | /* 315 | * Local Variables: 316 | * mode: C 317 | * c-basic-offset: 4 318 | * indent-tabs-mode: nil 319 | * End: 320 | */ 321 | -------------------------------------------------------------------------------- /src/gutil_intarray.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017-2023 Slava Monich 3 | * Copyright (C) 2017 Jolla Ltd. 4 | * 5 | * You may use this file under the terms of the BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "gutil_intarray.h" 34 | #include "gutil_ints.h" 35 | 36 | #if __GNUC__ >= 4 37 | #pragma GCC visibility push(default) 38 | #endif 39 | 40 | G_STATIC_ASSERT(sizeof(GUtilIntArray) == sizeof(GArray)); 41 | #define ELEMENT_SIZE (sizeof(int)) 42 | 43 | GUtilIntArray* 44 | gutil_int_array_new() 45 | { 46 | return (GUtilIntArray*)g_array_sized_new(FALSE, FALSE, ELEMENT_SIZE, 0); 47 | } 48 | 49 | GUtilIntArray* 50 | gutil_int_array_sized_new( 51 | guint reserved) 52 | { 53 | return (GUtilIntArray*)g_array_sized_new(FALSE, FALSE, ELEMENT_SIZE, 54 | reserved * ELEMENT_SIZE); 55 | } 56 | 57 | GUtilIntArray* 58 | gutil_int_array_new_from_vals( 59 | const int* vals, 60 | guint count) 61 | { 62 | GUtilIntArray* array = gutil_int_array_sized_new(count); 63 | 64 | gutil_int_array_append_vals(array, vals, count); 65 | return array; 66 | } 67 | 68 | GUtilIntArray* 69 | gutil_int_array_new_from_value( 70 | int value) 71 | { 72 | return gutil_int_array_new_from_vals(&value, 1); 73 | } 74 | 75 | int* 76 | gutil_int_array_free( 77 | GUtilIntArray* array, 78 | gboolean free_data) 79 | { 80 | if (array) { 81 | if (array->count) { 82 | return (int*)g_array_free((GArray*)array, free_data); 83 | } else { 84 | return (int*)g_array_free((GArray*)array, TRUE); 85 | } 86 | } else { 87 | return NULL; 88 | } 89 | } 90 | 91 | GUtilInts* 92 | gutil_int_array_free_to_ints( 93 | GUtilIntArray* array) 94 | { 95 | if (array) { 96 | if (array->count) { 97 | guint count = array->count; 98 | int* values = gutil_int_array_free(array, FALSE); 99 | 100 | return gutil_ints_new_take(values, count); 101 | } else { 102 | gutil_int_array_free(array, TRUE); 103 | } 104 | } 105 | return NULL; 106 | } 107 | 108 | GUtilIntArray* 109 | gutil_int_array_ref( 110 | GUtilIntArray* array) 111 | { 112 | if (array) { 113 | return (GUtilIntArray*)g_array_ref((GArray*)array); 114 | } 115 | return NULL; 116 | } 117 | 118 | void 119 | gutil_int_array_unref( 120 | GUtilIntArray* array) 121 | { 122 | if (array) { 123 | g_array_unref((GArray*)array); 124 | } 125 | } 126 | 127 | GUtilIntArray* 128 | gutil_int_array_append( 129 | GUtilIntArray* array, 130 | int val) 131 | { 132 | return gutil_int_array_append_vals(array, &val, 1); 133 | } 134 | 135 | GUtilIntArray* 136 | gutil_int_array_append_vals( 137 | GUtilIntArray* array, 138 | const int* vals, 139 | guint count) 140 | { 141 | if (array) { 142 | g_array_append_vals((GArray*)array, (void*)vals, count); 143 | } 144 | return array; 145 | } 146 | 147 | GUtilIntArray* 148 | gutil_int_array_prepend( 149 | GUtilIntArray* array, 150 | int val) 151 | { 152 | return gutil_int_array_prepend_vals(array, &val, 1); 153 | } 154 | 155 | GUtilIntArray* 156 | gutil_int_array_prepend_vals( 157 | GUtilIntArray* array, 158 | const int* vals, 159 | guint count) 160 | { 161 | if (array) { 162 | g_array_prepend_vals((GArray*)array, (void*)vals, count); 163 | } 164 | return array; 165 | } 166 | 167 | GUtilIntArray* 168 | gutil_int_array_insert( 169 | GUtilIntArray* array, 170 | guint pos, 171 | int val) 172 | { 173 | return gutil_int_array_insert_vals(array, pos, &val, 1); 174 | } 175 | 176 | GUtilIntArray* 177 | gutil_int_array_insert_vals( 178 | GUtilIntArray* array, 179 | guint pos, 180 | const int* vals, 181 | guint count) 182 | { 183 | if (array) { 184 | g_array_insert_vals((GArray*)array, pos, (void*)vals, count); 185 | } 186 | return array; 187 | } 188 | 189 | GUtilIntArray* 190 | gutil_int_array_set_count( 191 | GUtilIntArray* array, 192 | guint count) 193 | { 194 | if (array) { 195 | g_array_set_size((GArray*)array, count); 196 | } 197 | return array; 198 | } 199 | 200 | int 201 | gutil_int_array_find( 202 | GUtilIntArray* array, 203 | int value) 204 | { 205 | if (array) { 206 | guint i; 207 | 208 | for (i = 0; i < array->count; i++) { 209 | if (array->data[i] == value) { 210 | return i; 211 | } 212 | } 213 | } 214 | return -1; 215 | } 216 | 217 | gboolean 218 | gutil_int_array_contains( 219 | GUtilIntArray* array, 220 | int value) 221 | { 222 | return gutil_int_array_find(array, value) >= 0; 223 | } 224 | 225 | gboolean 226 | gutil_int_array_remove( 227 | GUtilIntArray* array, 228 | int value) 229 | { 230 | const int pos = gutil_int_array_find(array, value); 231 | 232 | if (pos >= 0) { 233 | g_array_remove_index((GArray*)array, pos); 234 | return TRUE; 235 | } 236 | return FALSE; 237 | } 238 | 239 | gboolean 240 | gutil_int_array_remove_fast( 241 | GUtilIntArray* array, 242 | int value) 243 | { 244 | const int pos = gutil_int_array_find(array, value); 245 | 246 | if (pos >= 0) { 247 | g_array_remove_index_fast((GArray*)array, pos); 248 | return TRUE; 249 | } 250 | return FALSE; 251 | } 252 | 253 | guint 254 | gutil_int_array_remove_all( 255 | GUtilIntArray* array, 256 | int value) 257 | { 258 | guint n; 259 | 260 | for (n = 0; gutil_int_array_remove(array, value); n++); 261 | return n; 262 | } 263 | 264 | guint 265 | gutil_int_array_remove_all_fast( 266 | GUtilIntArray* array, 267 | int value) 268 | { 269 | guint n; 270 | 271 | for (n = 0; gutil_int_array_remove_fast(array, value); n++); 272 | return n; 273 | } 274 | 275 | GUtilIntArray* 276 | gutil_int_array_remove_index( 277 | GUtilIntArray* array, 278 | guint pos) 279 | { 280 | if (array && pos < array->count) { 281 | g_array_remove_index((GArray*)array, pos); 282 | } 283 | return array; 284 | } 285 | 286 | GUtilIntArray* 287 | gutil_int_array_remove_index_fast( 288 | GUtilIntArray* array, 289 | guint pos) 290 | { 291 | if (array) { 292 | g_array_remove_index_fast((GArray*)array, pos); 293 | } 294 | return array; 295 | } 296 | 297 | GUtilIntArray* 298 | gutil_int_array_remove_range( 299 | GUtilIntArray* array, 300 | guint pos, 301 | guint count) 302 | { 303 | if (array && pos < array->count && count) { 304 | guint end = pos + count; 305 | 306 | if (end > array->count) { 307 | end = array->count; 308 | } 309 | g_array_remove_range((GArray*)array, pos, end - pos); 310 | } 311 | return array; 312 | } 313 | 314 | static 315 | gint 316 | gutil_int_array_sort_ascending_proc( 317 | gconstpointer a, 318 | gconstpointer b) 319 | { 320 | const int* v1 = a; 321 | const int* v2 = b; 322 | 323 | return *v1 - *v2; 324 | } 325 | 326 | void 327 | gutil_int_array_sort_ascending( 328 | GUtilIntArray* array) 329 | { 330 | if (array) { 331 | g_array_sort((GArray*)array, gutil_int_array_sort_ascending_proc); 332 | } 333 | } 334 | 335 | static 336 | gint 337 | gutil_int_array_sort_descending_proc( 338 | gconstpointer a, 339 | gconstpointer b) 340 | { 341 | const int* v1 = a; 342 | const int* v2 = b; 343 | 344 | return *v2 - *v1; 345 | } 346 | 347 | void 348 | gutil_int_array_sort_descending( 349 | GUtilIntArray* array) 350 | { 351 | if (array) { 352 | g_array_sort((GArray*)array, gutil_int_array_sort_descending_proc); 353 | } 354 | } 355 | 356 | /* 357 | * Local Variables: 358 | * mode: C 359 | * c-basic-offset: 4 360 | * indent-tabs-mode: nil 361 | * End: 362 | */ 363 | -------------------------------------------------------------------------------- /src/gutil_ints.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017-2023 Slava Monich 3 | * Copyright (C) 2017-2021 Jolla Ltd. 4 | * 5 | * You may use this file under the terms of the BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "gutil_intarray.h" 34 | #include "gutil_ints.h" 35 | #include "gutil_misc.h" 36 | #include "gutil_macros.h" 37 | 38 | #if __GNUC__ >= 4 39 | #pragma GCC visibility push(default) 40 | #endif 41 | 42 | struct gutil_ints { 43 | const int* data; 44 | guint count; 45 | gint ref_count; 46 | GDestroyNotify free_func; 47 | gpointer user_data; 48 | }; 49 | 50 | GUtilInts* 51 | gutil_ints_new( 52 | const int* data, 53 | guint n) 54 | { 55 | if (data && n) { 56 | return gutil_ints_new_take(gutil_memdup(data, n * sizeof(int)), n); 57 | } else { 58 | return NULL; 59 | } 60 | } 61 | 62 | GUtilInts* 63 | gutil_ints_new_take( 64 | int* data, 65 | guint count) 66 | { 67 | return gutil_ints_new_with_free_func(data, count, g_free, data); 68 | } 69 | 70 | GUtilInts* 71 | gutil_ints_new_static( 72 | const int* data, 73 | guint count) 74 | { 75 | return gutil_ints_new_with_free_func(data, count, NULL, NULL); 76 | } 77 | 78 | GUtilInts* 79 | gutil_ints_new_with_free_func( 80 | const int* data, 81 | guint count, 82 | GDestroyNotify free_func, 83 | gpointer user_data) 84 | { 85 | if (data && count) { 86 | GUtilInts* ints = g_slice_new(GUtilInts); 87 | 88 | ints->data = data; 89 | ints->count = count; 90 | ints->free_func = free_func; 91 | ints->user_data = user_data; 92 | g_atomic_int_set(&ints->ref_count, 1); 93 | return ints; 94 | } else { 95 | return NULL; 96 | } 97 | } 98 | 99 | static 100 | void 101 | gutil_ints_unref1( 102 | gpointer ints) 103 | { 104 | gutil_ints_unref(ints); 105 | } 106 | 107 | GUtilInts* 108 | gutil_ints_new_from_ints( 109 | GUtilInts* ints, 110 | guint offset, 111 | guint count) 112 | { 113 | if (ints && offset < ints->count) { 114 | guint end = offset + count; 115 | 116 | if (end > ints->count) { 117 | end = ints->count; 118 | } 119 | return gutil_ints_new_with_free_func(ints->data + offset, end - offset, 120 | gutil_ints_unref1, gutil_ints_ref(ints)); 121 | } 122 | return NULL; 123 | } 124 | 125 | GUtilInts* 126 | gutil_ints_ref( 127 | GUtilInts* ints) 128 | { 129 | if (ints) { 130 | g_atomic_int_inc(&ints->ref_count); 131 | return ints; 132 | } 133 | return NULL; 134 | } 135 | 136 | void 137 | gutil_ints_unref( 138 | GUtilInts* ints) 139 | { 140 | if (ints) { 141 | if (g_atomic_int_dec_and_test(&ints->ref_count)) { 142 | if (ints->free_func) { 143 | ints->free_func(ints->user_data); 144 | } 145 | gutil_slice_free(ints); 146 | } 147 | } 148 | } 149 | 150 | int* 151 | gutil_ints_unref_to_data( 152 | GUtilInts* ints, 153 | guint* count) 154 | { 155 | if (ints) { 156 | int* result; 157 | 158 | if (count) { 159 | *count = ints->count; 160 | } 161 | if (g_atomic_int_dec_and_test(&ints->ref_count)) { 162 | if (ints->free_func == g_free) { 163 | /* We can allow the caller to free the data */ 164 | result = (int*)ints->data; 165 | } else { 166 | result = gutil_memdup(ints->data, ints->count * sizeof(int)); 167 | ints->free_func(ints->user_data); 168 | } 169 | gutil_slice_free(ints); 170 | } else { 171 | result = gutil_memdup(ints->data, ints->count * sizeof(int)); 172 | } 173 | return result; 174 | } else { 175 | if (count) { 176 | *count = 0; 177 | } 178 | return NULL; 179 | } 180 | } 181 | 182 | const int* 183 | gutil_ints_get_data( 184 | GUtilInts* ints, 185 | guint* count) 186 | { 187 | if (ints) { 188 | if (count) { 189 | *count = ints->count; 190 | } 191 | return ints->data; 192 | } else { 193 | if (count) { 194 | *count = 0; 195 | } 196 | return NULL; 197 | } 198 | } 199 | 200 | guint 201 | gutil_ints_get_count( 202 | GUtilInts* ints) 203 | { 204 | return ints ? ints->count : 0; 205 | } 206 | 207 | int 208 | gutil_ints_find( 209 | GUtilInts* ints, 210 | int value) 211 | { 212 | if (ints) { 213 | guint i; 214 | 215 | for (i=0; icount; i++) { 216 | if (ints->data[i] == value) { 217 | return i; 218 | } 219 | } 220 | } 221 | return -1; 222 | } 223 | 224 | gboolean 225 | gutil_ints_contains( 226 | GUtilInts* ints, 227 | int value) 228 | { 229 | /* 230 | * Could use gutil_ints_find() here but it would return negative value 231 | * if the array contains more than MAX_INT entries. Let's be a bit more 232 | * reliable. 233 | */ 234 | if (ints) { 235 | guint i; 236 | 237 | for (i=0; icount; i++) { 238 | if (ints->data[i] == value) { 239 | return TRUE; 240 | } 241 | } 242 | } 243 | return FALSE; 244 | } 245 | 246 | guint 247 | gutil_ints_hash( 248 | gconstpointer data) 249 | { 250 | if (data) { 251 | const GUtilInts* ints = data; 252 | guint i, h = 1234; 253 | 254 | for (i=0; icount; i++) { 255 | h ^= ints->data[i] * (i+1); 256 | } 257 | return h; 258 | } else { 259 | return 0; 260 | } 261 | } 262 | 263 | gboolean 264 | gutil_ints_equal( 265 | gconstpointer a, 266 | gconstpointer b) 267 | { 268 | const GUtilInts* i1 = a; 269 | const GUtilInts* i2 = b; 270 | 271 | if (i1 == i2) { 272 | return TRUE; 273 | } else if (i1 && i2) { 274 | return i1->count == i2->count && 275 | !memcmp(i1->data, i2->data, i1->count * sizeof(int)); 276 | } else { 277 | return FALSE; 278 | } 279 | } 280 | 281 | 282 | /* 283 | * Returns: a negative value if b is greater, 284 | * a positive value if a is greater, 285 | * and zero if a is equals b 286 | */ 287 | gint 288 | gutil_ints_compare( 289 | gconstpointer a, 290 | gconstpointer b) 291 | { 292 | const GUtilInts* i1 = a; 293 | const GUtilInts* i2 = b; 294 | 295 | if (i1 == i2) { 296 | return 0; 297 | } else if (i1 && i2) { 298 | const int ret = memcmp(i1->data, i2->data, 299 | MIN(i1->count, i2->count) * sizeof(int)); 300 | 301 | if (ret || i1->count == i2->count) { 302 | return ret; 303 | } else { 304 | return (i1->count > i2->count) ? 1 : -1; 305 | } 306 | } else { 307 | return i1 ? 1 : -1; 308 | } 309 | } 310 | 311 | /* 312 | * Local Variables: 313 | * mode: C 314 | * c-basic-offset: 4 315 | * indent-tabs-mode: nil 316 | * End: 317 | */ 318 | -------------------------------------------------------------------------------- /src/gutil_objv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Slava Monich 3 | * 4 | * You may use this file under the terms of the BSD license as follows: 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the names of the copyright holders nor the names of its 16 | * contributors may be used to endorse or promote products derived 17 | * from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | * THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "gutil_objv.h" 33 | #include "gutil_misc.h" 34 | 35 | #if __GNUC__ >= 4 36 | #pragma GCC visibility push(default) 37 | #endif 38 | 39 | GObject** 40 | gutil_objv_new( 41 | GObject* obj1, 42 | ...) /* Since 1.0.72 */ 43 | { 44 | gsize len = 0; 45 | GObject** objv; 46 | GObject** ptr; 47 | 48 | if (obj1) { 49 | GObject* obj; 50 | va_list args; 51 | 52 | len++; 53 | va_start(args, obj1); 54 | while ((obj = va_arg(args, GObject*)) != NULL) { 55 | len++; 56 | } 57 | va_end(args); 58 | } 59 | 60 | ptr = objv = g_new(GObject*, len + 1); 61 | if (obj1) { 62 | GObject* obj; 63 | va_list args; 64 | 65 | g_object_ref(*ptr++ = obj1); 66 | va_start(args, obj1); 67 | while ((obj = va_arg(args, GObject*)) != NULL) { 68 | g_object_ref(*ptr++ = obj); 69 | } 70 | va_end(args); 71 | } 72 | *ptr = NULL; 73 | return objv; 74 | } 75 | 76 | void 77 | gutil_objv_free( 78 | GObject** objv) 79 | { 80 | if (objv) { 81 | GObject** ptr = objv; 82 | 83 | while (*ptr) g_object_unref(*ptr++); 84 | g_free(objv); 85 | } 86 | } 87 | 88 | GObject** 89 | gutil_objv_copy( 90 | GObject* const* objv) 91 | { 92 | if (objv) { 93 | GObject* const* ptr = objv; 94 | gsize n = 0; 95 | 96 | /* Count the objects and bump references at the same time */ 97 | while (*ptr) { 98 | g_object_ref(*ptr++); 99 | n++; 100 | } 101 | return gutil_memdup(objv, sizeof(GObject*) * (n + 1)); 102 | } 103 | return NULL; 104 | 105 | } 106 | 107 | GObject** 108 | gutil_objv_add( 109 | GObject** objv, 110 | GObject* obj) 111 | { 112 | if (obj) { 113 | gsize len = gutil_ptrv_length(objv); 114 | 115 | objv = g_renew(GObject*, objv, len + 2); 116 | g_object_ref(objv[len++] = obj); 117 | objv[len] = NULL; 118 | } 119 | return objv; 120 | } 121 | 122 | GObject** 123 | gutil_objv_insert( 124 | GObject** objv, 125 | GObject* obj, 126 | gsize pos) /* Since 1.0.71 */ 127 | { 128 | if (obj) { 129 | gsize len = gutil_ptrv_length(objv); 130 | 131 | objv = g_renew(GObject*, objv, len + 2); 132 | if (pos >= len) { 133 | /* Insert as the last element */ 134 | g_object_ref(objv[len++] = obj); 135 | objv[len] = NULL; 136 | } else { 137 | /* Insert somewhere in the middle (or at the very beginning) */ 138 | memmove(objv + (pos + 1), objv + pos, sizeof(GObject*) * 139 | (len - pos + 1)); /* Move NULL too */ 140 | g_object_ref(objv[pos] = obj); 141 | } 142 | } 143 | return objv; 144 | } 145 | 146 | GObject** 147 | gutil_objv_append( 148 | GObject** objv, 149 | GObject* const* objs) /* Since 1.0.71 */ 150 | { 151 | const gsize len2 = gutil_ptrv_length(objs); 152 | 153 | if (len2 > 0) { 154 | const gsize len1 = gutil_ptrv_length(objv); 155 | GObject* const* src; 156 | GObject** dest; 157 | 158 | objv = g_renew(GObject*, objv, len1 + len2 + 1); 159 | dest = objv + len1; 160 | src = objs; 161 | while (*src) { 162 | *dest++ = g_object_ref(*src++); 163 | } 164 | *dest = NULL; 165 | } 166 | return objv; 167 | } 168 | 169 | static 170 | gssize 171 | gutil_objv_find_last_impl( 172 | GObject* const* objv, 173 | GObject* obj, 174 | gsize i /* exclisive */) 175 | { 176 | while (i > 0) { 177 | if (objv[--i] == obj) { 178 | return i; 179 | } 180 | } 181 | return -1; 182 | } 183 | 184 | static 185 | GObject** 186 | gutil_objv_remove_impl( 187 | GObject** objv, 188 | gsize pos, 189 | gsize len) 190 | { 191 | g_object_unref(objv[pos]); 192 | memmove(objv + pos, objv + (pos + 1), sizeof(GObject*) * (len - pos)); 193 | return g_realloc(objv, sizeof(GObject*) * len); 194 | } 195 | 196 | GObject** 197 | gutil_objv_remove( 198 | GObject** objv, 199 | GObject* obj, 200 | gboolean all) 201 | { 202 | if (objv && obj) { 203 | const gssize pos = gutil_objv_find(objv, obj); 204 | 205 | if (pos >= 0) { 206 | gsize len = gutil_ptrv_length(objv); 207 | 208 | objv = gutil_objv_remove_impl(objv, pos, len); 209 | if (all) { 210 | gssize i, l; 211 | 212 | len--; 213 | l = len - pos; 214 | while ((i = gutil_objv_find_last_impl(objv + pos, 215 | obj, l)) >= 0) { 216 | objv = gutil_objv_remove_impl(objv, pos + i, len--); 217 | l = i; 218 | } 219 | } 220 | } 221 | } 222 | return objv; 223 | } 224 | 225 | GObject** 226 | gutil_objv_remove_at( 227 | GObject** objv, 228 | gsize pos) 229 | { 230 | if (objv) { 231 | const gsize len = gutil_ptrv_length(objv); 232 | 233 | if (pos < len) { 234 | objv = gutil_objv_remove_impl(objv, pos, len); 235 | } 236 | } 237 | return objv; 238 | } 239 | 240 | GObject* 241 | gutil_objv_at( 242 | GObject* const* objv, 243 | gsize pos) 244 | { 245 | if (objv) { 246 | guint i = 0; 247 | 248 | while (objv[i] && i < pos) i++; 249 | if (i == pos) { 250 | /* We also end up here if i == len but that's OK */ 251 | return objv[pos]; 252 | } 253 | } 254 | return NULL; 255 | 256 | } 257 | 258 | gboolean 259 | gutil_objv_equal( 260 | GObject* const* v1, 261 | GObject* const* v2) 262 | { 263 | if (v1 == v2) { 264 | return TRUE; 265 | } else if (!v1) { 266 | return !v2[0]; 267 | } else if (!v2) { 268 | return !v1[0]; 269 | } else { 270 | gsize len = 0; 271 | 272 | while (v1[len] && v1[len] == v2[len]) len++; 273 | return !v1[len] && !v2[len]; 274 | } 275 | } 276 | 277 | GObject* 278 | gutil_objv_first( 279 | GObject* const* objv) 280 | { 281 | return objv ? objv[0] : NULL; 282 | } 283 | 284 | GObject* 285 | gutil_objv_last( 286 | GObject* const* objv) 287 | { 288 | if (objv && objv[0]) { 289 | GObject* const* ptr = objv; 290 | 291 | while (ptr[1]) ptr++; 292 | return *ptr; 293 | } 294 | return NULL; 295 | } 296 | 297 | gssize 298 | gutil_objv_find( 299 | GObject* const* objv, 300 | GObject* obj) 301 | { 302 | if (objv && obj) { 303 | GObject* const* ptr; 304 | 305 | for (ptr = objv; *ptr; ptr++) { 306 | if (*ptr == obj) { 307 | return ptr - objv; 308 | } 309 | } 310 | } 311 | return -1; 312 | } 313 | 314 | gssize 315 | gutil_objv_find_last( 316 | GObject* const* objv, 317 | GObject* obj) 318 | { 319 | return (objv && obj) ? 320 | gutil_objv_find_last_impl(objv, obj, gutil_ptrv_length(objv)) : 321 | -1; 322 | } 323 | 324 | gboolean 325 | gutil_objv_contains( 326 | GObject* const* objv, 327 | GObject* obj) 328 | { 329 | if (objv && obj) { 330 | GObject* const* ptr; 331 | 332 | for (ptr = objv; *ptr; ptr++) { 333 | if (*ptr == obj) { 334 | return TRUE; 335 | } 336 | } 337 | } 338 | return FALSE; 339 | } 340 | 341 | /* 342 | * Local Variables: 343 | * mode: C 344 | * c-basic-offset: 4 345 | * indent-tabs-mode: nil 346 | * End: 347 | */ 348 | -------------------------------------------------------------------------------- /src/gutil_strv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2025 Slava Monich 3 | * Copyright (C) 2014-2022 Jolla Ltd. 4 | * 5 | * You may use this file under the terms of the BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "gutil_strv.h" 34 | #include "gutil_misc.h" 35 | 36 | #include 37 | 38 | #if __GNUC__ >= 4 39 | #pragma GCC visibility push(default) 40 | #endif 41 | 42 | /** 43 | * NULL-tolerant version of g_strv_length 44 | */ 45 | guint 46 | gutil_strv_length( 47 | const GStrV* sv) 48 | { 49 | return (guint) gutil_ptrv_length(sv); 50 | } 51 | 52 | /** 53 | * Returns i-th strings in the array, NULL if index is out of bounds. 54 | */ 55 | const char* 56 | gutil_strv_at( 57 | const GStrV* sv, 58 | guint i) 59 | { 60 | if (G_LIKELY(sv)) { 61 | guint k = 0; 62 | 63 | while (sv[k] && k < i) k++; 64 | if (k == i) { 65 | /* We also end up here if i == len but that's OK */ 66 | return sv[k]; 67 | } 68 | } 69 | return NULL; 70 | } 71 | 72 | /** 73 | * Returns the last string in the array, NULL if there's nothing there. 74 | */ 75 | const char* 76 | gutil_strv_last( 77 | const GStrV* sv) /* Since 1.0.35 */ 78 | { 79 | if (G_LIKELY(sv) && G_LIKELY(sv[0])) { 80 | guint k = 0; 81 | 82 | while (sv[k + 1]) k++; 83 | return sv[k]; 84 | } 85 | return NULL; 86 | } 87 | 88 | /** 89 | * Returns index of the specified string in the string array, 90 | * or -1 if the string is not found. 91 | */ 92 | int 93 | gutil_strv_find( 94 | const GStrV* sv, 95 | const char* s) 96 | { 97 | if (G_LIKELY(sv) && G_LIKELY(s)) { 98 | int i = 0; 99 | const GStrV* ptr; 100 | 101 | for (ptr = sv; *ptr; ptr++, i++) { 102 | if (!strcmp(*ptr, s)) { 103 | return i; 104 | } 105 | } 106 | } 107 | return -1; 108 | } 109 | 110 | /* Helper for gutil_strv_find_last and friends */ 111 | static 112 | int 113 | gutil_strv_find_last_impl( 114 | const GStrV* sv, 115 | const char* s, 116 | int i /* exclisive */) 117 | { 118 | while (i > 0) { 119 | if (!strcmp(sv[--i], s)) { 120 | return i; 121 | } 122 | } 123 | return -1; 124 | } 125 | 126 | /** 127 | * Returns index of the last occurrence of specified string in the string 128 | * array, or -1 if the string is not found. 129 | */ 130 | int 131 | gutil_strv_find_last( 132 | const GStrV* sv, 133 | const char* s) /* Since 1.0.62 */ 134 | { 135 | /* NULL sv is handled by gutil_strv_length() */ 136 | return G_LIKELY(s) ? gutil_strv_find_last_impl(sv, s, 137 | gutil_strv_length(sv)) : -1; 138 | } 139 | 140 | /** 141 | * Checks if string array contains the specified string. 142 | */ 143 | gboolean 144 | gutil_strv_contains( 145 | const GStrV* sv, 146 | const char* s) 147 | { 148 | return gutil_strv_find(sv, s) >= 0; 149 | } 150 | 151 | /** 152 | * Appends new string to the array. 153 | */ 154 | GStrV* 155 | gutil_strv_add( 156 | GStrV* sv, 157 | const char* s) 158 | { 159 | if (s) { 160 | guint len = gutil_strv_length(sv); 161 | 162 | sv = g_renew(char*, sv, len + 2); 163 | sv[len++] = g_strdup(s); 164 | sv[len] = NULL; 165 | } 166 | return sv; 167 | } 168 | 169 | /** 170 | * Appends new strings to the array. 171 | */ 172 | GStrV* 173 | gutil_strv_addv( 174 | GStrV* sv, 175 | const char* s, 176 | ...) 177 | { 178 | if (s) { 179 | va_list va; 180 | const char* s1; 181 | guint len, i, n; 182 | 183 | va_start(va, s); 184 | for (n = 1; (s1 = va_arg(va, char*)) != NULL; n++); 185 | va_end(va); 186 | 187 | len = gutil_strv_length(sv); 188 | sv = g_renew(gchar*, sv, len + n + 1); 189 | sv[len++] = g_strdup(s); 190 | va_start(va, s); 191 | for (i = 1; i < n; i++) sv[len++] = g_strdup(va_arg(va, char*)); 192 | va_end(va); 193 | sv[len] = NULL; 194 | } 195 | return sv; 196 | } 197 | 198 | /* Internal helper for removal functions */ 199 | static 200 | GStrV* 201 | gutil_strv_remove_impl( 202 | GStrV* sv, 203 | guint pos, 204 | guint len, 205 | gboolean free_string) 206 | { 207 | if (free_string) { 208 | g_free(sv[pos]); 209 | } 210 | memmove(sv + pos, sv + pos + 1, sizeof(char*)*(len - pos)); 211 | return g_realloc(sv, sizeof(char*)*len); 212 | } 213 | 214 | /** 215 | * Removes the string from the specified position in the array. 216 | */ 217 | GStrV* 218 | gutil_strv_remove_at( 219 | GStrV* sv, 220 | int pos, 221 | gboolean free_string) 222 | { 223 | if (G_LIKELY(sv) && G_LIKELY(pos >= 0)) { 224 | const int len = gutil_strv_length(sv); 225 | 226 | if (pos < len) { 227 | sv = gutil_strv_remove_impl(sv, pos, len, free_string); 228 | } 229 | } 230 | return sv; 231 | } 232 | 233 | /** 234 | * Removes one or all matching strings from the array and frees them. 235 | */ 236 | GStrV* 237 | gutil_strv_remove( 238 | GStrV* sv, 239 | const char* s, 240 | gboolean remove_all) 241 | { 242 | if (G_LIKELY(sv) && G_LIKELY(s)) { 243 | /* coverity[tainted_data_return:FALSE] */ 244 | const int pos = gutil_strv_find(sv, s); 245 | 246 | if (pos >= 0) { 247 | guint len = gutil_strv_length(sv); 248 | 249 | sv = gutil_strv_remove_impl(sv, pos, len, TRUE); 250 | if (remove_all) { 251 | int i, l; 252 | 253 | len--; 254 | l = len - pos; 255 | while ((i = gutil_strv_find_last_impl(sv + pos, s, l)) >= 0) { 256 | sv = gutil_strv_remove_impl(sv, pos + i, len--, TRUE); 257 | l = i; 258 | } 259 | } 260 | } 261 | } 262 | return sv; 263 | } 264 | 265 | /** 266 | * Removes all duplicates from the string array. 267 | */ 268 | GStrV* 269 | gutil_strv_remove_dups( 270 | GStrV* sv) /* Since 1.0.62 */ 271 | { 272 | if (G_LIKELY(sv)) { 273 | guint len = gutil_strv_length(sv), pos = 0, l = len; 274 | 275 | while (pos < len) { 276 | int i = gutil_strv_find_last_impl(sv + pos + 1, sv[pos], l - 1); 277 | 278 | if (i < 0) { 279 | /* Done with this string, switch to the next one */ 280 | pos++; 281 | l = len - pos; 282 | } else { 283 | sv = gutil_strv_remove_impl(sv, pos + 1 + i, len--, TRUE); 284 | l = i + 1; 285 | } 286 | } 287 | } 288 | return sv; 289 | } 290 | 291 | /** 292 | * Checks two string arrays for equality. NULL and empty arrays are equal. 293 | * 294 | * This is basically a NULL-tolerant equivalent of g_strv_equal which 295 | * appeared in glib 2.60. 296 | */ 297 | gboolean 298 | gutil_strv_equal( 299 | const GStrV* sv1, 300 | const GStrV* sv2) 301 | { 302 | if (sv1 == sv2) { 303 | return TRUE; 304 | } else if (!sv1) { 305 | return !sv2[0]; 306 | } else if (!sv2) { 307 | return !sv1[0]; 308 | } else { 309 | guint len = 0; 310 | 311 | while (sv1[len] && sv2[len]) len++; 312 | if (!sv1[len] && !sv2[len]) { 313 | guint i; 314 | for (i=0; i 0) { 354 | qsort(sv, len, sizeof(char*), ascending ? 355 | gutil_strv_sort_ascending : 356 | gutil_strv_sort_descending); 357 | } 358 | return sv; 359 | } 360 | 361 | /** 362 | * Binary search in the sorted string array. Returns index of the 363 | * specified string in the string array, or -1 if the string is not 364 | * found. It's basically a version of gutil_strv_find optimized for 365 | * sorted arrays. The string array must be sorted by gutil_strv_sort 366 | * with the same 'ascending' argument. 367 | */ 368 | int 369 | gutil_strv_bsearch( 370 | GStrV* sv, 371 | const char* s, 372 | gboolean ascending) /* Since 1.0.40 */ 373 | { 374 | if (s) { 375 | const guint len = gutil_strv_length(sv); 376 | 377 | if (len > 0) { 378 | GStrV* found = bsearch(&s, sv, len, sizeof(char*), ascending ? 379 | gutil_strv_sort_ascending : gutil_strv_sort_descending); 380 | 381 | if (found) { 382 | return found - sv; 383 | } 384 | } 385 | } 386 | return -1; 387 | } 388 | 389 | /** 390 | * Removes leading and trailing whitespaces from all strings in the vector. 391 | */ 392 | GStrV* 393 | gutil_strv_strip( 394 | GStrV* sv) 395 | { 396 | if (sv) { 397 | GStrV* ptr; 398 | 399 | for (ptr = sv; *ptr; ptr++) { 400 | *ptr = g_strstrip(*ptr); 401 | } 402 | } 403 | return sv; 404 | } 405 | 406 | /* 407 | * Local Variables: 408 | * mode: C 409 | * c-basic-offset: 4 410 | * indent-tabs-mode: nil 411 | * End: 412 | */ 413 | -------------------------------------------------------------------------------- /src/gutil_timenotify.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016-2023 Slava Monich 3 | * Copyright (C) 2016-2019 Jolla Ltd. 4 | * 5 | * You may use this file under the terms of the BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "gutil_timenotify.h" 34 | #include "gutil_misc.h" 35 | #include "gutil_log.h" 36 | 37 | #include 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #ifdef __clang__ 45 | #define NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) 46 | #else 47 | #define NO_SANITIZE_CFI 48 | #endif 49 | 50 | #if __GNUC__ >= 4 51 | #pragma GCC visibility push(default) 52 | #endif 53 | 54 | #ifndef TFD_TIMER_CANCEL_ON_SET 55 | # define TFD_TIMER_CANCEL_ON_SET (1 << 1) 56 | #endif 57 | 58 | #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t)*8)-1)) - 1) 59 | 60 | struct gutil_time_notify { 61 | GObject object; 62 | GIOChannel* io_channel; 63 | guint io_watch_id; 64 | }; 65 | 66 | enum gutil_time_notify_signal { 67 | SIGNAL_TIME_CHANGED, 68 | SIGNAL_COUNT 69 | }; 70 | 71 | #define SIGNAL_TIME_CHANGED_NAME "time-changed" 72 | 73 | static guint gutil_time_notify_signals[SIGNAL_COUNT] = { 0 }; 74 | 75 | #define PARENT_CLASS gutil_time_notify_parent_class 76 | #define THIS_TYPE gutil_time_notify_get_type() 77 | #define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, THIS_TYPE, GUtilTimeNotify) 78 | 79 | GType THIS_TYPE G_GNUC_INTERNAL; 80 | typedef GObjectClass GUtilTimeNotifyClass; 81 | G_DEFINE_TYPE(GUtilTimeNotify, gutil_time_notify, G_TYPE_OBJECT) 82 | 83 | GUtilTimeNotify* 84 | gutil_time_notify_new() 85 | { 86 | /* There's no need to have more than one instance. */ 87 | static GUtilTimeNotify* gutil_time_notify_instance = NULL; 88 | 89 | if (gutil_time_notify_instance) { 90 | gutil_time_notify_ref(gutil_time_notify_instance); 91 | } else { 92 | gutil_time_notify_instance = g_object_new(THIS_TYPE, 0); 93 | g_object_add_weak_pointer(G_OBJECT(gutil_time_notify_instance), 94 | (gpointer*)(&gutil_time_notify_instance)); 95 | } 96 | return gutil_time_notify_instance; 97 | } 98 | 99 | GUtilTimeNotify* 100 | gutil_time_notify_ref( 101 | GUtilTimeNotify* self) 102 | { 103 | if (G_LIKELY(self)) { 104 | g_object_ref(THIS(self)); 105 | } 106 | return self; 107 | } 108 | 109 | void 110 | gutil_time_notify_unref( 111 | GUtilTimeNotify* self) 112 | { 113 | if (G_LIKELY(self)) { 114 | g_object_unref(THIS(self)); 115 | } 116 | } 117 | 118 | gulong 119 | gutil_time_notify_add_handler( 120 | GUtilTimeNotify* self, 121 | GUtilTimeNotifyFunc fn, 122 | void* arg) 123 | { 124 | return (G_LIKELY(self) && G_LIKELY(fn)) ? g_signal_connect(self, 125 | SIGNAL_TIME_CHANGED_NAME, G_CALLBACK(fn), arg) : 0; 126 | } 127 | 128 | void 129 | gutil_time_notify_remove_handler( 130 | GUtilTimeNotify* self, 131 | gulong id) 132 | { 133 | if (G_LIKELY(self) && G_LIKELY(id)) { 134 | g_signal_handler_disconnect(self, id); 135 | } 136 | } 137 | 138 | static 139 | gboolean 140 | gutil_time_notify_callback( 141 | GIOChannel* channel, 142 | GIOCondition condition, 143 | gpointer user_data) 144 | { 145 | GUtilTimeNotify* self = THIS(user_data); 146 | 147 | if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) { 148 | self->io_watch_id = 0; 149 | return G_SOURCE_REMOVE; 150 | } else { 151 | G_GNUC_UNUSED GIOStatus status; 152 | gsize bytes_read = 0; 153 | GError* error = NULL; 154 | guint64 exp; 155 | 156 | gutil_time_notify_ref(self); 157 | status = g_io_channel_read_chars(self->io_channel, (void*)&exp, sizeof(exp), 158 | &bytes_read, &error); 159 | GASSERT(status == G_IO_STATUS_ERROR && error); 160 | if (error) { 161 | /* ECANCELED is expected */ 162 | GDEBUG("%s", error->message); 163 | g_error_free(error); 164 | } 165 | g_signal_emit(self, gutil_time_notify_signals[SIGNAL_TIME_CHANGED], 0); 166 | gutil_time_notify_unref(self); 167 | return G_SOURCE_CONTINUE; 168 | } 169 | } 170 | 171 | static 172 | void 173 | gutil_time_notify_init( 174 | GUtilTimeNotify* self) 175 | { 176 | const int fd = timerfd_create(CLOCK_REALTIME, 0); 177 | 178 | if (fd >= 0) { 179 | struct itimerspec timer; 180 | 181 | self->io_channel = g_io_channel_unix_new(fd); 182 | g_io_channel_set_close_on_unref(self->io_channel, TRUE); 183 | g_io_channel_set_encoding(self->io_channel, NULL, NULL); 184 | g_io_channel_set_buffered(self->io_channel, FALSE); 185 | self->io_watch_id = g_io_add_watch(self->io_channel, 186 | G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR, 187 | gutil_time_notify_callback, self); 188 | 189 | /* Set timeout to the latest possible value */ 190 | memset(&timer, 0, sizeof(timer)); 191 | timer.it_value.tv_sec = TIME_T_MAX; 192 | timer.it_interval.tv_sec = TIME_T_MAX; 193 | if (timerfd_settime(fd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, 194 | &timer, NULL) < 0) { 195 | GERR("timerfd settime: %s", strerror(errno)); 196 | } 197 | } else { 198 | GERR("timerfd open: %s", strerror(errno)); 199 | } 200 | } 201 | 202 | NO_SANITIZE_CFI 203 | static 204 | void 205 | gutil_time_notify_finalize( 206 | GObject* object) 207 | { 208 | GUtilTimeNotify* self = THIS(object); 209 | 210 | if (self->io_channel) { 211 | gutil_source_remove(self->io_watch_id); 212 | g_io_channel_shutdown(self->io_channel, FALSE, NULL); 213 | g_io_channel_unref(self->io_channel); 214 | } 215 | G_OBJECT_CLASS(PARENT_CLASS)->finalize(object); 216 | } 217 | 218 | static 219 | void 220 | gutil_time_notify_class_init( 221 | GUtilTimeNotifyClass* klass) 222 | { 223 | G_OBJECT_CLASS(klass)->finalize = gutil_time_notify_finalize; 224 | gutil_time_notify_signals[SIGNAL_TIME_CHANGED] = 225 | g_signal_new(SIGNAL_TIME_CHANGED_NAME, G_OBJECT_CLASS_TYPE(klass), 226 | G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); 227 | } 228 | 229 | /* 230 | * Local Variables: 231 | * mode: C 232 | * c-basic-offset: 4 233 | * indent-tabs-mode: nil 234 | * End: 235 | */ 236 | -------------------------------------------------------------------------------- /src/gutil_version.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Slava Monich 3 | * 4 | * You may use this file under the terms of the BSD license as follows: 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the names of the copyright holders nor the names of its 16 | * contributors may be used to endorse or promote products derived 17 | * from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | * THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "gutil_version.h" 33 | 34 | #if __GNUC__ >= 4 35 | #pragma GCC visibility push(default) 36 | #endif 37 | 38 | const guint gutil_version_major = GUTIL_VERSION_MAJOR; 39 | const guint gutil_version_minor = GUTIL_VERSION_MINOR; 40 | const guint gutil_version_micro = GUTIL_VERSION_MICRO; 41 | 42 | /* 43 | * Local Variables: 44 | * mode: C 45 | * c-basic-offset: 4 46 | * indent-tabs-mode: nil 47 | * End: 48 | */ 49 | -------------------------------------------------------------------------------- /src/gutil_weakref.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Slava Monich 3 | * 4 | * You may use this file under the terms of the BSD license as follows: 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the names of the copyright holders nor the names of its 16 | * contributors may be used to endorse or promote products derived 17 | * from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | * THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "gutil_weakref.h" 33 | #include "gutil_log.h" 34 | #include "gutil_macros.h" 35 | 36 | #include 37 | 38 | #if __GNUC__ >= 4 39 | #pragma GCC visibility push(default) 40 | #endif 41 | 42 | /* 43 | * Ref-countable weak reference can be used to avoid calling g_weak_ref_set() 44 | * too often because it grabs global weak_locations_lock for exclusive access. 45 | * Note that g_weak_ref_set() is also invoked internally by g_weak_ref_init() 46 | * and g_weak_ref_clear(). 47 | * 48 | * g_weak_ref_get() on the other hand only acquires weak_locations_lock 49 | * for read-only access which is less of a bottleneck in a multi-threaded 50 | * environment. And it's generally significantly simpler and faster than 51 | * g_weak_ref_set(). 52 | * 53 | * Since 1.0.68 54 | */ 55 | 56 | struct gutil_weakref { 57 | gint ref_count; 58 | GWeakRef weak_ref; 59 | }; 60 | 61 | GUtilWeakRef* 62 | gutil_weakref_new( 63 | gpointer obj) 64 | { 65 | GUtilWeakRef* self = g_slice_new(GUtilWeakRef); 66 | 67 | g_atomic_int_set(&self->ref_count, 1); 68 | g_weak_ref_init(&self->weak_ref, obj); 69 | return self; 70 | } 71 | 72 | GUtilWeakRef* 73 | gutil_weakref_ref( 74 | GUtilWeakRef* self) 75 | { 76 | if (G_LIKELY(self)) { 77 | GASSERT(self->ref_count > 0); 78 | g_atomic_int_inc(&self->ref_count); 79 | } 80 | return self; 81 | } 82 | 83 | void 84 | gutil_weakref_unref( 85 | GUtilWeakRef* self) 86 | { 87 | if (G_LIKELY(self)) { 88 | GASSERT(self->ref_count > 0); 89 | if (g_atomic_int_dec_and_test(&self->ref_count)) { 90 | g_weak_ref_clear(&self->weak_ref); 91 | gutil_slice_free(self); 92 | } 93 | } 94 | } 95 | 96 | gpointer 97 | gutil_weakref_get( 98 | GUtilWeakRef* self) 99 | { 100 | return G_LIKELY(self) ? g_weak_ref_get(&self->weak_ref) : NULL; 101 | } 102 | 103 | void 104 | gutil_weakref_set( 105 | GUtilWeakRef* self, 106 | gpointer obj) 107 | { 108 | if (G_LIKELY(self)) { 109 | g_weak_ref_set(&self->weak_ref, obj); 110 | } 111 | } 112 | 113 | /* 114 | * Local Variables: 115 | * mode: C 116 | * c-basic-offset: 4 117 | * indent-tabs-mode: nil 118 | * End: 119 | */ 120 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | all: 4 | %: 5 | @$(MAKE) -C test_datapack $* 6 | @$(MAKE) -C test_history $* 7 | @$(MAKE) -C test_idlepool $* 8 | @$(MAKE) -C test_idlequeue $* 9 | @$(MAKE) -C test_inotify $* 10 | @$(MAKE) -C test_intarray $* 11 | @$(MAKE) -C test_ints $* 12 | @$(MAKE) -C test_log $* 13 | @$(MAKE) -C test_misc $* 14 | @$(MAKE) -C test_objv $* 15 | @$(MAKE) -C test_ring $* 16 | @$(MAKE) -C test_strv $* 17 | @$(MAKE) -C test_weakref $* 18 | -------------------------------------------------------------------------------- /test/common/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | .PHONY: clean all debug release coverage debug_lib release_lib coverage_lib 4 | 5 | # 6 | # Real test makefile defines EXE (and possibly SRC) and includes this one. 7 | # 8 | 9 | ifndef EXE 10 | ${error EXE not defined} 11 | endif 12 | 13 | SRC ?= $(EXE).c 14 | COMMON_SRC ?= test_main.c test_object.c 15 | 16 | # 17 | # Required packages 18 | # 19 | 20 | PKGS += gobject-2.0 glib-2.0 21 | 22 | # 23 | # Default target 24 | # 25 | 26 | all: debug release 27 | 28 | # 29 | # Directories 30 | # 31 | 32 | SRC_DIR = . 33 | LIB_DIR = ../.. 34 | COMMON_DIR = ../common 35 | BUILD_DIR = build 36 | DEBUG_BUILD_DIR = $(BUILD_DIR)/debug 37 | RELEASE_BUILD_DIR = $(BUILD_DIR)/release 38 | COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage 39 | 40 | # 41 | # Tools and flags 42 | # 43 | 44 | PKG_CONFIG ?= pkg-config 45 | CC ?= $(CROSS_COMPILE)gcc 46 | LD = $(CC) 47 | WARNINGS = -Wall 48 | INCLUDES = -I$(LIB_DIR)/include -I$(LIB_DIR)/src -I$(COMMON_DIR) 49 | BASE_FLAGS = -fPIC 50 | BASE_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS) 51 | BASE_CFLAGS = $(BASE_FLAGS) $(CFLAGS) 52 | FULL_CFLAGS = $(BASE_CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) -MMD -MP \ 53 | -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32 \ 54 | -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_MAX_ALLOWED \ 55 | $(shell $(PKG_CONFIG) --cflags $(PKGS)) 56 | FULL_LDFLAGS = $(BASE_LDFLAGS) 57 | LIBS = $(shell $(PKG_CONFIG) --libs $(PKGS)) 58 | QUIET_MAKE = $(MAKE) --no-print-directory 59 | DEBUG_FLAGS = -g 60 | RELEASE_FLAGS = 61 | COVERAGE_FLAGS = -g 62 | 63 | KEEP_SYMBOLS ?= 0 64 | ifneq ($(KEEP_SYMBOLS),0) 65 | RELEASE_FLAGS += -g 66 | SUBMAKE_OPTS += KEEP_SYMBOLS=1 67 | endif 68 | 69 | DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS) 70 | RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS) 71 | COVERAGE_LDFLAGS = $(FULL_LDFLAGS) $(COVERAGE_FLAGS) --coverage 72 | 73 | DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG 74 | RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2 75 | COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) --coverage 76 | 77 | # 78 | # Files 79 | # 80 | 81 | DEBUG_OBJS = \ 82 | $(COMMON_SRC:%.c=$(DEBUG_BUILD_DIR)/common_%.o) \ 83 | $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) 84 | RELEASE_OBJS = \ 85 | $(COMMON_SRC:%.c=$(RELEASE_BUILD_DIR)/common_%.o) \ 86 | $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o) 87 | COVERAGE_OBJS = \ 88 | $(COMMON_SRC:%.c=$(COVERAGE_BUILD_DIR)/common_%.o) \ 89 | $(SRC:%.c=$(COVERAGE_BUILD_DIR)/%.o) 90 | 91 | DEBUG_LIB_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_lib) 92 | RELEASE_LIB_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_lib) 93 | COVERAGE_LIB_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_coverage_lib) 94 | 95 | DEBUG_LIB := $(LIB_DIR)/$(DEBUG_LIB_FILE) 96 | RELEASE_LIB := $(LIB_DIR)/$(RELEASE_LIB_FILE) 97 | COVERAGE_LIB := $(LIB_DIR)/$(COVERAGE_LIB_FILE) 98 | 99 | # 100 | # Dependencies 101 | # 102 | 103 | DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d) $(COVERAGE_OBJS:%.o=%.d) 104 | ifneq ($(MAKECMDGOALS),clean) 105 | ifneq ($(strip $(DEPS)),) 106 | -include $(DEPS) 107 | endif 108 | endif 109 | 110 | $(DEBUG_LIB): | debug_lib 111 | $(RELEASE_LIB): | release_lib 112 | $(COVERAGE_LIB): | coverage_lib 113 | 114 | $(DEBUG_OBJS): | $(DEBUG_BUILD_DIR) 115 | $(RELEASE_OBJS): | $(RELEASE_BUILD_DIR) 116 | $(COVERAGE_OBJS): | $(COVERAGE_BUILD_DIR) 117 | 118 | # 119 | # Rules 120 | # 121 | 122 | DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE) 123 | RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE) 124 | COVERAGE_EXE = $(COVERAGE_BUILD_DIR)/$(EXE) 125 | 126 | debug: debug_lib $(DEBUG_EXE) 127 | 128 | release: release_lib $(RELEASE_EXE) 129 | 130 | coverage: coverage_lib $(COVERAGE_EXE) 131 | 132 | clean: 133 | rm -f *~ 134 | rm -fr $(BUILD_DIR) 135 | 136 | cleaner: clean 137 | @$(MAKE) -C $(LIB_DIR) clean 138 | 139 | test_banner: 140 | @echo "===========" $(EXE) "=========== " 141 | 142 | test: test_banner debug 143 | @$(DEBUG_EXE) 144 | 145 | valgrind: test_banner debug 146 | @G_DEBUG=gc-friendly G_SLICE=always-malloc valgrind --tool=memcheck --leak-check=full --show-possibly-lost=no $(DEBUG_EXE) 147 | 148 | $(DEBUG_BUILD_DIR): 149 | mkdir -p $@ 150 | 151 | $(RELEASE_BUILD_DIR): 152 | mkdir -p $@ 153 | 154 | $(COVERAGE_BUILD_DIR): 155 | mkdir -p $@ 156 | 157 | $(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c 158 | $(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ 159 | 160 | $(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c 161 | $(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ 162 | 163 | $(COVERAGE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c 164 | $(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ 165 | 166 | $(DEBUG_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c 167 | $(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ 168 | 169 | $(RELEASE_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c 170 | $(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ 171 | 172 | $(COVERAGE_BUILD_DIR)/common_%.o : $(COMMON_DIR)/%.c 173 | $(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ 174 | 175 | $(DEBUG_EXE): $(DEBUG_LIB) $(DEBUG_BUILD_DIR) $(DEBUG_OBJS) 176 | $(LD) $(DEBUG_LDFLAGS) $(DEBUG_OBJS) $< $(LIBS) -o $@ 177 | 178 | $(RELEASE_EXE): $(RELEASE_LIB) $(RELEASE_BUILD_DIR) $(RELEASE_OBJS) 179 | $(LD) $(RELEASE_LDFLAGS) $(RELEASE_OBJS) $< $(LIBS) -o $@ 180 | ifeq ($(KEEP_SYMBOLS),0) 181 | strip $@ 182 | endif 183 | 184 | $(COVERAGE_EXE): $(COVERAGE_LIB) $(COVERAGE_BUILD_DIR) $(COVERAGE_OBJS) 185 | $(LD) $(COVERAGE_LDFLAGS) $(COVERAGE_OBJS) $< $(LIBS) -o $@ 186 | 187 | debug_lib: 188 | @$(MAKE) $(SUBMAKE_OPTS) -C $(LIB_DIR) debug 189 | 190 | release_lib: 191 | @$(MAKE) $(SUBMAKE_OPTS) -C $(LIB_DIR) release 192 | 193 | coverage_lib: 194 | @$(MAKE) $(SUBMAKE_OPTS) -C $(LIB_DIR) coverage 195 | -------------------------------------------------------------------------------- /test/common/test_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016-2022 Jolla Ltd. 3 | * Copyright (C) 2016-2022 Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef TEST_COMMON_H 34 | #define TEST_COMMON_H 35 | 36 | #include 37 | 38 | #include 39 | 40 | #define TEST_FLAG_DEBUG (0x01) 41 | 42 | typedef struct test_opt { 43 | int flags; 44 | } TestOpt; 45 | 46 | GType test_object_get_type(void); 47 | #define TEST_OBJECT_TYPE (test_object_get_type()) 48 | 49 | extern gint test_object_count; 50 | 51 | /* Should be invoked after g_test_init */ 52 | void 53 | test_init( 54 | TestOpt* opt, 55 | int argc, 56 | char* argv[]); 57 | 58 | /* Macros */ 59 | 60 | #define TEST_INIT_DATA(a,b) ((a).bytes = (void*)(b), (a).size = sizeof(b)) 61 | #define TEST_ARRAY_AND_SIZE(a) (a), sizeof(a) 62 | 63 | #endif /* TEST_COMMON_H */ 64 | 65 | /* 66 | * Local Variables: 67 | * mode: C 68 | * c-basic-offset: 4 69 | * indent-tabs-mode: nil 70 | * End: 71 | */ 72 | -------------------------------------------------------------------------------- /test/common/test_main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Jolla Ltd. 3 | * Contact: Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of the Jolla Ltd nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "test_common.h" 34 | 35 | #include 36 | 37 | void 38 | test_init( 39 | TestOpt* opt, 40 | int argc, 41 | char* argv[]) 42 | { 43 | int i; 44 | memset(opt, 0, sizeof(*opt)); 45 | for (i=1; iflags |= TEST_FLAG_DEBUG; 49 | } else if (!strcmp(arg, "-v")) { 50 | GTestConfig* config = (GTestConfig*)g_test_config_vars; 51 | config->test_verbose = TRUE; 52 | } else { 53 | GWARN("Unsupported command line option %s", arg); 54 | } 55 | } 56 | 57 | /* Setup logging */ 58 | gutil_log_timestamp = FALSE; 59 | gutil_log_default.level = g_test_verbose() ? GLOG_LEVEL_VERBOSE : 60 | GLOG_LEVEL_NONE; 61 | } 62 | 63 | /* 64 | * Local Variables: 65 | * mode: C 66 | * c-basic-offset: 4 67 | * indent-tabs-mode: nil 68 | * End: 69 | */ 70 | -------------------------------------------------------------------------------- /test/common/test_object.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018-2023 Slava Monich 3 | * Copyright (C) 2018 Jolla Ltd. 4 | * 5 | * You may use this file under the terms of the BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "test_common.h" 34 | 35 | #include 36 | 37 | typedef GObject TestObject; 38 | typedef GObjectClass TestObjectClass; 39 | 40 | G_DEFINE_TYPE(TestObject, test_object, G_TYPE_OBJECT) 41 | 42 | gint test_object_count = 0; 43 | 44 | static 45 | void 46 | test_object_init( 47 | TestObject* self) 48 | { 49 | g_atomic_int_inc(&test_object_count); 50 | } 51 | 52 | #ifdef __clang__ 53 | __attribute__((no_sanitize("cfi"))) 54 | #endif 55 | static 56 | void 57 | test_object_finalize( 58 | GObject* object) 59 | { 60 | GASSERT(test_object_count > 0); 61 | g_atomic_int_add(&test_object_count, -1); 62 | G_OBJECT_CLASS(test_object_parent_class)->finalize(object); 63 | } 64 | 65 | static 66 | void 67 | test_object_class_init( 68 | TestObjectClass* klass) 69 | { 70 | klass->finalize = test_object_finalize; 71 | } 72 | 73 | /* 74 | * Local Variables: 75 | * mode: C 76 | * c-basic-offset: 4 77 | * indent-tabs-mode: nil 78 | * End: 79 | */ 80 | -------------------------------------------------------------------------------- /test/coverage/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script requires lcov to be installed 4 | # 5 | 6 | TESTS="\ 7 | test_datapack \ 8 | test_history \ 9 | test_idlepool \ 10 | test_idlequeue \ 11 | test_inotify \ 12 | test_intarray \ 13 | test_ints \ 14 | test_log \ 15 | test_misc \ 16 | test_objv \ 17 | test_ring \ 18 | test_strv \ 19 | test_weakref" 20 | 21 | FLAVOR="coverage" 22 | 23 | pushd `dirname $0` > /dev/null 24 | COV_DIR="$PWD" 25 | pushd .. > /dev/null 26 | TEST_DIR="$PWD" 27 | pushd .. > /dev/null 28 | BASE_DIR="$PWD" 29 | popd > /dev/null 30 | popd > /dev/null 31 | popd > /dev/null 32 | 33 | export LD_LIBRARY_PATH="$BASE_DIR/build/$FLAVOR" 34 | 35 | make GCOV=1 -C "$BASE_DIR" clean $FLAVOR 36 | for t in $TESTS ; do 37 | pushd "$TEST_DIR/$t" 38 | make -C "$TEST_DIR/$t" clean $FLAVOR || exit 1 39 | build/$FLAVOR/$t || exit 1 40 | popd 41 | done 42 | 43 | # LCOV 1.10 has branch coverage disabled per default 44 | LCOV_OPT="--rc lcov_branch_coverage=1" 45 | GENHTML_OPT="--branch-coverage" 46 | 47 | FULL_COV="$COV_DIR/full.gcov" 48 | GLIBUTIL_COV="$COV_DIR/libglibutil.gcov" 49 | rm -f "$FULL_COV" "$GLIBUTIL_COV" 50 | lcov $LCOV_OPT -c -d "$LD_LIBRARY_PATH" -b "$BASE_DIR" -o "$FULL_COV" || exit 1 51 | lcov $LCOV_OPT -e "$FULL_COV" "$BASE_DIR/src/*" -o "$GLIBUTIL_COV" || exit 1 52 | genhtml $GENHTML_OPT -t libglibutil "$GLIBUTIL_COV" --output-directory "$COV_DIR/results" || exit 1 53 | -------------------------------------------------------------------------------- /test/test_datapack/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | EXE = test_datapack 4 | 5 | include ../common/Makefile 6 | -------------------------------------------------------------------------------- /test/test_history/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | EXE = test_history 4 | 5 | include ../common/Makefile 6 | -------------------------------------------------------------------------------- /test/test_history/test_history.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Jolla Ltd. 3 | * Contact: Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of Jolla Ltd nor the names of its contributors may 17 | * be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "test_common.h" 34 | 35 | #include "gutil_history.h" 36 | 37 | static TestOpt test_opt; 38 | static gint64 test_history_time; 39 | 40 | static 41 | gint64 42 | test_history_time_func(void) 43 | { 44 | return test_history_time; 45 | } 46 | 47 | /*==========================================================================* 48 | * NULL tolerance 49 | *==========================================================================*/ 50 | 51 | static 52 | void 53 | test_history_null( 54 | void) 55 | { 56 | gutil_int_history_unref(NULL); 57 | gutil_int_history_clear(NULL); 58 | g_assert(!gutil_int_history_ref(NULL)); 59 | g_assert(!gutil_int_history_size(NULL)); 60 | g_assert(!gutil_int_history_interval(NULL)); 61 | g_assert(!gutil_int_history_add(NULL, 1)); 62 | g_assert(!gutil_int_history_median(NULL, 0)); 63 | g_assert(!gutil_int_history_new(0, 0)); 64 | g_assert(!gutil_int_history_new(1, 0)); 65 | g_assert(!gutil_int_history_new(0, 1)); 66 | } 67 | 68 | /*==========================================================================* 69 | * Basic 70 | *==========================================================================*/ 71 | 72 | static 73 | void 74 | test_history_basic( 75 | void) 76 | { 77 | /* The default time functon returns real time, not usable for testing */ 78 | GUtilIntHistory* h = gutil_int_history_new(1, 1); 79 | g_assert(gutil_int_history_size(h) == 0); 80 | g_assert(gutil_int_history_interval(h) == 0); 81 | gutil_int_history_unref(gutil_int_history_ref(h)); 82 | gutil_int_history_unref(h); 83 | } 84 | 85 | /*==========================================================================* 86 | * Clear 87 | *==========================================================================*/ 88 | 89 | static 90 | void 91 | test_history_clear( 92 | void) 93 | { 94 | GUtilIntHistory* h = gutil_int_history_new_full(2, 2, 95 | test_history_time_func); 96 | g_assert(gutil_int_history_median(h, 0) == 0); 97 | test_history_time = 2; 98 | g_assert(gutil_int_history_add(h, 1) == 1); 99 | /* Time hasn't changed, 1 is replaced with 2 */ 100 | g_assert(gutil_int_history_add(h, 2) == 2); 101 | /* Time goes back, 2 is replaced with 3 */ 102 | test_history_time -=1; 103 | g_assert(gutil_int_history_add(h, 3) == 3); 104 | test_history_time += 2; 105 | g_assert(gutil_int_history_add(h, 5) == 4); 106 | g_assert(gutil_int_history_size(h) == 2); 107 | g_assert(gutil_int_history_median(h, 0) == 4); 108 | g_assert(gutil_int_history_interval(h) == 1); 109 | gutil_int_history_clear(h); 110 | g_assert(!gutil_int_history_size(h)); 111 | g_assert(!gutil_int_history_interval(h)); 112 | gutil_int_history_unref(h); 113 | } 114 | 115 | /*==========================================================================* 116 | * Median 117 | *==========================================================================*/ 118 | 119 | static 120 | void 121 | test_history_median( 122 | void) 123 | { 124 | GUtilIntHistory* h = gutil_int_history_new_full(2, 2, 125 | test_history_time_func); 126 | test_history_time = 1; 127 | g_assert(gutil_int_history_add(h, 1) == 1); 128 | test_history_time += 1; 129 | g_assert(gutil_int_history_add(h, 5) == 3); 130 | test_history_time += 1; 131 | /* Still the same, both ends of the interval are inclusive */ 132 | g_assert(gutil_int_history_median(h, 0) == 3); 133 | test_history_time += 1; 134 | /* Now one entry expires */ 135 | g_assert(gutil_int_history_median(h, 0) == 5); 136 | test_history_time += 1; 137 | /* The last one expires too */ 138 | g_assert(gutil_int_history_median(h, 0) == 0); 139 | gutil_int_history_unref(h); 140 | } 141 | 142 | /*==========================================================================* 143 | * Size 144 | *==========================================================================*/ 145 | 146 | static 147 | void 148 | test_history_size( 149 | void) 150 | { 151 | GUtilIntHistory* h = gutil_int_history_new_full(2, 2, 152 | test_history_time_func); 153 | test_history_time = 1; 154 | g_assert(gutil_int_history_add(h, 1) == 1); 155 | test_history_time += 1; 156 | g_assert(gutil_int_history_add(h, 5) == 3); 157 | g_assert(gutil_int_history_size(h) == 2); 158 | test_history_time += 1; 159 | /* Still the same, both ends of the interval are inclusive */ 160 | g_assert(gutil_int_history_size(h) == 2); 161 | test_history_time += 1; 162 | /* Now one entry expires */ 163 | g_assert(gutil_int_history_size(h) == 1); 164 | test_history_time += 1; 165 | /* The last one expires too */ 166 | g_assert(gutil_int_history_size(h) == 0); 167 | gutil_int_history_unref(h); 168 | } 169 | 170 | /*==========================================================================* 171 | * Interval 172 | *==========================================================================*/ 173 | 174 | static 175 | void 176 | test_history_interval( 177 | void) 178 | { 179 | GUtilIntHistory* h = gutil_int_history_new_full(2, 3, 180 | test_history_time_func); 181 | test_history_time = 1; 182 | g_assert(gutil_int_history_add(h, 1) == 1); 183 | test_history_time += 1; 184 | g_assert(gutil_int_history_add(h, 5) == 3); 185 | g_assert(gutil_int_history_interval(h) == 1); 186 | test_history_time += 1; 187 | /* Both ends of the interval are inclusive */ 188 | g_assert(gutil_int_history_interval(h) == 2); 189 | test_history_time += 2; 190 | /* Now one entry with timestamp 1 expires, the one remaining has 191 | * timestamp 2, the current time is 5 so the interval becomes 3 */ 192 | g_assert(gutil_int_history_interval(h) == 3); 193 | test_history_time += 1; 194 | /* The last one expires too */ 195 | g_assert(gutil_int_history_interval(h) == 0); 196 | gutil_int_history_unref(h); 197 | } 198 | 199 | /*==========================================================================* 200 | * Data 201 | *==========================================================================*/ 202 | 203 | typedef struct test_history_sample { 204 | gint64 time; 205 | int value; 206 | int median; 207 | } TestHistorySample; 208 | 209 | typedef struct test_history_data { 210 | int max_size; 211 | gint64 max_interval; 212 | const TestHistorySample* samples; 213 | int count; 214 | guint size; 215 | gint64 interval; 216 | } TestHistoryData; 217 | 218 | static 219 | void 220 | test_history_data( 221 | gconstpointer test_data) 222 | { 223 | int i; 224 | const TestHistoryData* data = test_data; 225 | GUtilIntHistory* h = gutil_int_history_new_full(data->max_size, 226 | data->max_interval, test_history_time_func); 227 | for (i=0; icount; i++) { 228 | const TestHistorySample* sample = data->samples + i; 229 | test_history_time = sample->time; 230 | g_assert(gutil_int_history_add(h, sample->value) == sample->median); 231 | } 232 | g_assert(gutil_int_history_size(h) == data->size); 233 | g_assert(gutil_int_history_interval(h) == data->interval); 234 | test_history_time += data->max_interval + 1; 235 | g_assert(!gutil_int_history_size(h)); 236 | g_assert(!gutil_int_history_interval(h)); 237 | gutil_int_history_unref(h); 238 | } 239 | 240 | /*==========================================================================* 241 | * Common 242 | *==========================================================================*/ 243 | static const TestHistorySample samples1[] = {{1, 1, 1}}; 244 | static const TestHistoryData data1 = { 245 | 1, 1, samples1, G_N_ELEMENTS(samples1), 1, 0 246 | }; 247 | 248 | static const TestHistorySample samples2[] = {{1, 1, 1}, {3, 2, 2}}; 249 | static const TestHistoryData data2 = { 250 | 1, 1, samples2, G_N_ELEMENTS(samples2), 1, 0 251 | }; 252 | 253 | static const TestHistorySample samples3[] = { 254 | {1, 2, 2}, {3, 2, 2}, {4, 8, 3} 255 | }; 256 | static const TestHistoryData data3 = { 257 | 3, 4, samples3, G_N_ELEMENTS(samples3), 3, 3 258 | }; 259 | 260 | static const TestHistorySample samples4[] = { 261 | {1, 2, 2}, {3, 2, 2}, {4, 8, 5} 262 | }; 263 | static const TestHistoryData data4 = { 264 | 3, 2, samples4, G_N_ELEMENTS(samples4), 2, 1 265 | }; 266 | 267 | static const TestHistorySample samples5[] = { 268 | {1, 2, 2}, {3, 2, 2}, {4, 8, 5} 269 | }; 270 | static const TestHistoryData data5 = { 271 | 2, 4, samples5, G_N_ELEMENTS(samples5), 2, 1 272 | }; 273 | 274 | #define TEST_PREFIX "/history/" 275 | 276 | int main(int argc, char* argv[]) 277 | { 278 | g_test_init(&argc, &argv, NULL); 279 | g_test_add_func(TEST_PREFIX "null", test_history_null); 280 | g_test_add_func(TEST_PREFIX "basic", test_history_basic); 281 | g_test_add_func(TEST_PREFIX "clear", test_history_clear); 282 | g_test_add_func(TEST_PREFIX "median", test_history_median); 283 | g_test_add_func(TEST_PREFIX "size", test_history_size); 284 | g_test_add_func(TEST_PREFIX "interval", test_history_interval); 285 | g_test_add_data_func(TEST_PREFIX "data1", &data1, test_history_data); 286 | g_test_add_data_func(TEST_PREFIX "data2", &data2, test_history_data); 287 | g_test_add_data_func(TEST_PREFIX "data3", &data3, test_history_data); 288 | g_test_add_data_func(TEST_PREFIX "data4", &data4, test_history_data); 289 | g_test_add_data_func(TEST_PREFIX "data5", &data5, test_history_data); 290 | test_init(&test_opt, argc, argv); 291 | return g_test_run(); 292 | } 293 | 294 | /* 295 | * Local Variables: 296 | * mode: C 297 | * c-basic-offset: 4 298 | * indent-tabs-mode: nil 299 | * End: 300 | */ 301 | -------------------------------------------------------------------------------- /test/test_idlepool/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | EXE = test_idlepool 4 | 5 | include ../common/Makefile 6 | -------------------------------------------------------------------------------- /test/test_idlequeue/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | EXE = test_idlequeue 4 | 5 | include ../common/Makefile 6 | -------------------------------------------------------------------------------- /test/test_idlequeue/test_idlequeue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Jolla Ltd. 3 | * Contact: Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of Jolla Ltd nor the names of its contributors may 17 | * be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "test_common.h" 34 | 35 | #include "gutil_idlequeue.h" 36 | #include "gutil_log.h" 37 | 38 | #define TEST_TIMEOUT (10) /* seconds */ 39 | 40 | static TestOpt test_opt; 41 | 42 | static 43 | void 44 | test_idlequeue_noooo( 45 | gpointer param) 46 | { 47 | g_assert(!"NOOO!!!"); 48 | } 49 | 50 | static 51 | gboolean 52 | test_idlequeue_timeout( 53 | gpointer param) 54 | { 55 | g_assert(!"TIMEOUT"); 56 | return G_SOURCE_REMOVE; 57 | } 58 | 59 | static 60 | void 61 | test_idlequeue_loop_quit( 62 | gpointer loop) 63 | { 64 | g_main_loop_quit(loop); 65 | } 66 | 67 | static 68 | void 69 | test_idlequeue_int_inc( 70 | gpointer data) 71 | { 72 | int* ptr = data; 73 | (*ptr)++; 74 | } 75 | 76 | /*==========================================================================* 77 | * Null 78 | *==========================================================================*/ 79 | 80 | static 81 | void 82 | test_idlequeue_null( 83 | void) 84 | { 85 | /* Test NULL tolerance */ 86 | int i = 0; 87 | g_assert(!gutil_idle_queue_ref(NULL)); 88 | gutil_idle_queue_unref(NULL); 89 | gutil_idle_queue_free(NULL); 90 | g_assert(!gutil_idle_queue_contains_tag(NULL, 0)); 91 | g_assert(!gutil_idle_queue_cancel_tag(NULL, 0)); 92 | gutil_idle_queue_cancel_all(NULL); 93 | gutil_idle_queue_add(NULL, NULL, NULL); 94 | gutil_idle_queue_add_full(NULL, NULL, NULL, NULL); 95 | gutil_idle_queue_add_tag(NULL, 0, NULL, NULL); 96 | gutil_idle_queue_add_tag_full(NULL, 0, NULL, NULL, NULL); 97 | /* IF queue is NULL, the destroy function gets invoked immediately: */ 98 | gutil_idle_queue_add_tag_full(NULL, 0, NULL, &i, test_idlequeue_int_inc); 99 | g_assert(i == 1); 100 | } 101 | 102 | /*==========================================================================* 103 | * Basic 104 | *==========================================================================*/ 105 | 106 | static 107 | void 108 | test_idlequeue_basic( 109 | void) 110 | { 111 | guint timeout_id = 0; 112 | int count = 0; 113 | GUtilIdleQueue* q = gutil_idle_queue_new(); 114 | GMainLoop* loop = g_main_loop_new(NULL, TRUE); 115 | 116 | gutil_idle_queue_unref(gutil_idle_queue_ref(q)); 117 | gutil_idle_queue_add_tag_full(q, 1, test_idlequeue_int_inc, &count, NULL); 118 | gutil_idle_queue_add_tag_full(q, 2, NULL, &count, test_idlequeue_int_inc); 119 | gutil_idle_queue_add_tag_full(q, 3, test_idlequeue_loop_quit, loop, NULL); 120 | g_assert(!gutil_idle_queue_contains_tag(q, 0)); 121 | g_assert(gutil_idle_queue_contains_tag(q, 1)); 122 | g_assert(gutil_idle_queue_contains_tag(q, 2)); 123 | g_assert(gutil_idle_queue_contains_tag(q, 3)); 124 | 125 | if (!(test_opt.flags & TEST_FLAG_DEBUG)) { 126 | timeout_id = g_timeout_add_seconds(TEST_TIMEOUT, 127 | test_idlequeue_timeout, NULL); 128 | } 129 | 130 | g_main_loop_run(loop); 131 | g_assert(count == 2); 132 | 133 | if (timeout_id) { 134 | g_source_remove(timeout_id); 135 | } 136 | 137 | gutil_idle_queue_unref(q); 138 | g_main_loop_unref(loop); 139 | } 140 | /*==========================================================================* 141 | * Add 142 | *==========================================================================*/ 143 | 144 | typedef struct test_idlequeue_add_data { 145 | GUtilIdleQueue* q; 146 | GMainLoop* loop; 147 | } TestAdd; 148 | 149 | static 150 | void 151 | test_idlequeue_add_cb( 152 | gpointer data) 153 | { 154 | /* Adding new item from the callback */ 155 | TestAdd* test = data; 156 | gutil_idle_queue_add(test->q, test_idlequeue_loop_quit, test->loop); 157 | } 158 | 159 | static 160 | void 161 | test_idlequeue_add( 162 | void) 163 | { 164 | guint timeout_id = 0; 165 | TestAdd test; 166 | 167 | test.q = gutil_idle_queue_new(); 168 | test.loop = g_main_loop_new(NULL, TRUE); 169 | 170 | if (!(test_opt.flags & TEST_FLAG_DEBUG)) { 171 | timeout_id = g_timeout_add_seconds(TEST_TIMEOUT, 172 | test_idlequeue_timeout, NULL); 173 | } 174 | 175 | gutil_idle_queue_add(test.q, test_idlequeue_add_cb, &test); 176 | g_main_loop_run(test.loop); 177 | 178 | if (timeout_id) { 179 | g_source_remove(timeout_id); 180 | } 181 | 182 | gutil_idle_queue_unref(test.q); 183 | g_main_loop_unref(test.loop); 184 | } 185 | 186 | /*==========================================================================* 187 | * Cancel 188 | *==========================================================================*/ 189 | 190 | static 191 | void 192 | test_idlequeue_cancel( 193 | void) 194 | { 195 | int count = 0; 196 | GUtilIdleQueue* q = gutil_idle_queue_new(); 197 | 198 | /* Destroying the queue cancels the callbacks */ 199 | gutil_idle_queue_add(q, test_idlequeue_int_inc, &count); 200 | gutil_idle_queue_add_full(q, NULL, &count, test_idlequeue_int_inc); 201 | gutil_idle_queue_add_full(q, NULL, &count, test_idlequeue_int_inc); 202 | gutil_idle_queue_unref(q); 203 | g_assert(count == 2); 204 | count = 0; 205 | 206 | /* Cancelling all requests in an empty queue has no effect */ 207 | q = gutil_idle_queue_new(); 208 | gutil_idle_queue_cancel_all(q); 209 | 210 | /* Cancel by tag */ 211 | gutil_idle_queue_add_tag_full(q, 1, NULL, &count, test_idlequeue_int_inc); 212 | gutil_idle_queue_add_tag_full(q, 2, NULL, &count, test_idlequeue_int_inc); 213 | gutil_idle_queue_add_tag_full(q, 3, NULL, &count, test_idlequeue_int_inc); 214 | gutil_idle_queue_add_tag_full(q, 4, NULL, &count, test_idlequeue_int_inc); 215 | g_assert(!gutil_idle_queue_cancel_tag(q, 0)); 216 | g_assert(gutil_idle_queue_cancel_tag(q, 3)); 217 | g_assert(gutil_idle_queue_cancel_tag(q, 4)); 218 | g_assert(gutil_idle_queue_cancel_tag(q, 1)); 219 | g_assert(gutil_idle_queue_cancel_tag(q, 2)); 220 | g_assert(!gutil_idle_queue_cancel_tag(q, 1)); 221 | g_assert(count == 4); 222 | count = 0; 223 | 224 | gutil_idle_queue_free(q); 225 | } 226 | 227 | /*==========================================================================* 228 | * CancelAll 229 | *==========================================================================*/ 230 | 231 | static 232 | void 233 | test_idlequeue_cancel_all_submit_new( 234 | gpointer q) 235 | { 236 | /* Adding new item from the destroy callback */ 237 | gutil_idle_queue_add_tag(q, 42, test_idlequeue_noooo, NULL); 238 | } 239 | 240 | static 241 | void 242 | test_idlequeue_cancel_all( 243 | void) 244 | { 245 | int count = 0; 246 | GUtilIdleQueue* q = gutil_idle_queue_new(); 247 | 248 | /* Add new item from the destroy callback */ 249 | gutil_idle_queue_add(q, test_idlequeue_int_inc, &count); 250 | gutil_idle_queue_add_tag_full(q, 1, NULL, &count, test_idlequeue_int_inc); 251 | gutil_idle_queue_add_tag_full(q, 2, NULL, q, 252 | test_idlequeue_cancel_all_submit_new); 253 | gutil_idle_queue_cancel_all(q); 254 | g_assert(count == 1); 255 | 256 | /* We should still have 42 in there */ 257 | g_assert(!gutil_idle_queue_contains_tag(q, 1)); 258 | g_assert(!gutil_idle_queue_contains_tag(q, 2)); 259 | g_assert(gutil_idle_queue_contains_tag(q, 42)); 260 | gutil_idle_queue_cancel_all(q); 261 | 262 | /* Now it has to be really empty */ 263 | g_assert(!gutil_idle_queue_contains_tag(q, 42)); 264 | gutil_idle_queue_free(q); 265 | } 266 | 267 | /*==========================================================================* 268 | * Common 269 | *==========================================================================*/ 270 | 271 | #define TEST_PREFIX "/idlequeue/" 272 | 273 | int main(int argc, char* argv[]) 274 | { 275 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS; 276 | g_type_init(); 277 | G_GNUC_END_IGNORE_DEPRECATIONS; 278 | g_test_init(&argc, &argv, NULL); 279 | g_test_add_func(TEST_PREFIX "null", test_idlequeue_null); 280 | g_test_add_func(TEST_PREFIX "basic", test_idlequeue_basic); 281 | g_test_add_func(TEST_PREFIX "add", test_idlequeue_add); 282 | g_test_add_func(TEST_PREFIX "cancel", test_idlequeue_cancel); 283 | g_test_add_func(TEST_PREFIX "cancel_all", test_idlequeue_cancel_all); 284 | test_init(&test_opt, argc, argv); 285 | return g_test_run(); 286 | } 287 | 288 | /* 289 | * Local Variables: 290 | * mode: C 291 | * c-basic-offset: 4 292 | * indent-tabs-mode: nil 293 | * End: 294 | */ 295 | -------------------------------------------------------------------------------- /test/test_inotify/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | EXE = test_inotify 4 | 5 | include ../common/Makefile 6 | -------------------------------------------------------------------------------- /test/test_inotify/test_inotify.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016-2017 Jolla Ltd. 3 | * Contact: Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the name of the Jolla Ltd nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "test_common.h" 34 | 35 | #include "gutil_inotify.h" 36 | #include "gutil_macros.h" 37 | #include "gutil_log.h" 38 | 39 | #include 40 | 41 | #define TEST_TIMEOUT (10) /* seconds */ 42 | #define TMP_DIR_TEMPLATE "test_inotify_XXXXXX" 43 | 44 | static TestOpt test_opt; 45 | 46 | typedef struct test_inotify { 47 | const char* name; 48 | GMainLoop* loop; 49 | GUtilInotifyWatch* watch1; 50 | GUtilInotifyWatch* watch2; 51 | char* dir1; 52 | char* dir2; 53 | guint timeout_id; 54 | gboolean array_free_count; 55 | gboolean ok; 56 | } TestInotify; 57 | 58 | static 59 | gboolean 60 | test_inotify_timeout( 61 | gpointer param) 62 | { 63 | TestInotify* test = param; 64 | GERR("%s TIMEOUT", test->name); 65 | test->timeout_id = 0; 66 | g_main_loop_quit(test->loop); 67 | return G_SOURCE_REMOVE; 68 | } 69 | 70 | static 71 | void 72 | test_inotify_common( 73 | TestInotify* test, 74 | gboolean (*init)(TestInotify* test), 75 | void (*deinit)(TestInotify* test)) 76 | { 77 | const int mask = IN_ALL_EVENTS | IN_ONLYDIR | IN_EXCL_UNLINK; 78 | 79 | test->ok = FALSE; 80 | test->dir1 = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL); 81 | test->dir2 = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL); 82 | test->watch1 = gutil_inotify_watch_new(test->dir1, mask); 83 | test->watch2 = gutil_inotify_watch_new(test->dir2, mask); 84 | 85 | GDEBUG("%s: directory 1: %s", test->name, test->dir1); 86 | GDEBUG("%s: directory 2: %s", test->name, test->dir2); 87 | 88 | /* Initialize the event loop */ 89 | test->loop = g_main_loop_new(NULL, TRUE); 90 | if (!(test_opt.flags & TEST_FLAG_DEBUG)) { 91 | test->timeout_id = g_timeout_add_seconds(TEST_TIMEOUT, 92 | test_inotify_timeout, test); 93 | } 94 | 95 | if (init) { 96 | init(test); 97 | } 98 | 99 | /* Run the event loop */ 100 | g_main_loop_run(test->loop); 101 | 102 | if (deinit) { 103 | deinit(test); 104 | } 105 | 106 | g_assert(test->ok); 107 | if (!(test_opt.flags & TEST_FLAG_DEBUG)) { 108 | g_assert(test->timeout_id); 109 | g_source_remove(test->timeout_id); 110 | } 111 | 112 | g_main_loop_unref(test->loop); 113 | gutil_inotify_watch_destroy(test->watch1); 114 | gutil_inotify_watch_destroy(test->watch2); 115 | remove(test->dir1); 116 | remove(test->dir2); 117 | g_free(test->dir1); 118 | g_free(test->dir2); 119 | } 120 | 121 | /*==========================================================================* 122 | * Basic 123 | *==========================================================================*/ 124 | 125 | static 126 | void 127 | test_inotify_basic( 128 | void) 129 | { 130 | char* dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL); 131 | GUtilInotifyWatch* watch = gutil_inotify_watch_new(dir, IN_ALL_EVENTS); 132 | 133 | /* These have no effect, just testing NULL-telerance */ 134 | g_assert(!gutil_inotify_watch_new(NULL, 0)); 135 | g_assert(!gutil_inotify_watch_ref(NULL)); 136 | gutil_inotify_watch_unref(NULL); 137 | gutil_inotify_watch_destroy(NULL); 138 | gutil_inotify_watch_remove_handler(NULL, 0); 139 | gutil_inotify_watch_remove_handler(watch, 0); 140 | 141 | g_assert(!gutil_inotify_watch_callback_new(NULL, 0, NULL, NULL)); 142 | g_assert(!gutil_inotify_watch_add_handler(NULL, NULL, NULL)); 143 | g_assert(!gutil_inotify_watch_add_handler(watch, NULL, NULL)); 144 | 145 | gutil_inotify_watch_destroy(watch); 146 | 147 | /* Remove the directory and try to watch it. That should fail */ 148 | remove(dir); 149 | g_assert(!gutil_inotify_watch_new(dir, IN_ALL_EVENTS)); 150 | g_free(dir); 151 | } 152 | 153 | /*==========================================================================* 154 | * Move 155 | *==========================================================================*/ 156 | 157 | typedef struct test_inotify_move { 158 | TestInotify test; 159 | const char* fname; 160 | char* dest; 161 | gulong id1; 162 | gulong id2; 163 | int from; 164 | } TestInotifyMove; 165 | 166 | static 167 | void 168 | test_inotify_move_from( 169 | GUtilInotifyWatch* watch, 170 | guint mask, 171 | guint cookie, 172 | const char* name, 173 | void* arg) 174 | { 175 | TestInotifyMove* move = arg; 176 | if ((mask & IN_MOVED_FROM) && !g_strcmp0(move->fname, name)) { 177 | GDEBUG("%s moved from %s", name, move->test.dir1); 178 | move->from++; 179 | } 180 | } 181 | 182 | static 183 | void 184 | test_inotify_move_to( 185 | GUtilInotifyWatch* watch, 186 | guint mask, 187 | guint cookie, 188 | const char* name, 189 | void* arg) 190 | { 191 | TestInotifyMove* move = arg; 192 | if ((mask & IN_MOVED_TO) && !g_strcmp0(move->fname, name)) { 193 | GDEBUG("%s moved to %s", name, move->test.dir2); 194 | if (move->from == 1) { 195 | move->test.ok = TRUE; 196 | g_main_loop_quit(move->test.loop); 197 | } 198 | } 199 | } 200 | 201 | static 202 | gboolean 203 | test_inotify_move_init( 204 | TestInotify* test) 205 | { 206 | TestInotifyMove* move = G_CAST(test, TestInotifyMove, test); 207 | char* src; 208 | 209 | move->fname = "test"; 210 | src = g_strconcat(test->dir1, G_DIR_SEPARATOR_S, move->fname, NULL); 211 | move->dest = g_strconcat(test->dir2, G_DIR_SEPARATOR_S, move->fname, NULL); 212 | move->id1 = gutil_inotify_watch_add_handler(test->watch1, 213 | test_inotify_move_from, move); 214 | move->id2 = gutil_inotify_watch_add_handler(test->watch2, 215 | test_inotify_move_to, move); 216 | g_file_set_contents(src, "contents", -1, NULL); 217 | GDEBUG("%s -> %s", src, move->dest); 218 | rename(src, move->dest); 219 | g_free(src); 220 | return TRUE; 221 | } 222 | 223 | static 224 | void 225 | test_inotify_move_deinit( 226 | TestInotify* test) 227 | { 228 | TestInotifyMove* move = G_CAST(test, TestInotifyMove, test); 229 | gutil_inotify_watch_remove_handler(test->watch1, move->id1); 230 | gutil_inotify_watch_remove_handler(test->watch2, move->id2); 231 | remove(move->dest); 232 | g_free(move->dest); 233 | } 234 | 235 | static 236 | void 237 | test_inotify_move( 238 | void) 239 | { 240 | TestInotifyMove move; 241 | memset(&move, 0, sizeof(move)); 242 | move.test.name = "move"; 243 | test_inotify_common(&move.test, 244 | test_inotify_move_init, 245 | test_inotify_move_deinit); 246 | } 247 | 248 | /*==========================================================================* 249 | * Callback 250 | *==========================================================================*/ 251 | 252 | typedef struct test_inotify_callback { 253 | TestInotify test; 254 | const char* fname; 255 | char* dest; 256 | GUtilInotifyWatchCallback* cb1; 257 | GUtilInotifyWatchCallback* cb2; 258 | int from; 259 | } TestInotifyCallback; 260 | 261 | static 262 | void 263 | test_inotify_callback_from( 264 | GUtilInotifyWatch* watch, 265 | guint mask, 266 | guint cookie, 267 | const char* name, 268 | void* arg) 269 | { 270 | TestInotifyCallback* cb = arg; 271 | if ((mask & IN_MOVED_FROM) && !g_strcmp0(cb->fname, name)) { 272 | GDEBUG("%s moved from %s", name, cb->test.dir1); 273 | cb->from++; 274 | } 275 | } 276 | 277 | static 278 | void 279 | test_inotify_callback_to( 280 | GUtilInotifyWatch* watch, 281 | guint mask, 282 | guint cookie, 283 | const char* name, 284 | void* arg) 285 | { 286 | TestInotifyCallback* cb = arg; 287 | if ((mask & IN_MOVED_TO) && !g_strcmp0(cb->fname, name)) { 288 | GDEBUG("%s moved to %s", name, cb->test.dir2); 289 | if (cb->from == 1) { 290 | cb->test.ok = TRUE; 291 | g_main_loop_quit(cb->test.loop); 292 | } 293 | } 294 | } 295 | 296 | static 297 | gboolean 298 | test_inotify_callback_init( 299 | TestInotify* test) 300 | { 301 | TestInotifyCallback* cb = G_CAST(test, TestInotifyCallback, test); 302 | char* src; 303 | cb->fname = "test"; 304 | src = g_strconcat(test->dir1, G_DIR_SEPARATOR_S, cb->fname, NULL); 305 | cb->dest = g_strconcat(test->dir2, G_DIR_SEPARATOR_S, cb->fname, NULL); 306 | cb->cb1 = gutil_inotify_watch_callback_new(test->dir1, IN_MOVED_FROM, 307 | test_inotify_callback_from, cb); 308 | cb->cb2 = gutil_inotify_watch_callback_new(test->dir2, IN_MOVED_TO, 309 | test_inotify_callback_to, cb); 310 | g_file_set_contents(src, "contents", -1, NULL); 311 | GDEBUG("%s -> %s", src, cb->dest); 312 | rename(src, cb->dest); 313 | g_free(src); 314 | return TRUE; 315 | } 316 | 317 | static 318 | void 319 | test_inotify_callback_deinit( 320 | TestInotify* test) 321 | { 322 | TestInotifyCallback* cb = G_CAST(test, TestInotifyCallback, test); 323 | gutil_inotify_watch_callback_free(cb->cb1); 324 | gutil_inotify_watch_callback_free(cb->cb2); 325 | gutil_inotify_watch_callback_free(NULL); 326 | remove(cb->dest); 327 | g_free(cb->dest); 328 | } 329 | 330 | static 331 | void 332 | test_inotify_callback( 333 | void) 334 | { 335 | TestInotifyCallback callback; 336 | memset(&callback, 0, sizeof(callback)); 337 | callback.test.name = "callback"; 338 | test_inotify_common(&callback.test, 339 | test_inotify_callback_init, 340 | test_inotify_callback_deinit); 341 | } 342 | 343 | /*==========================================================================* 344 | * Common 345 | *==========================================================================*/ 346 | 347 | #define TEST_PREFIX "/inotify/" 348 | 349 | int main(int argc, char* argv[]) 350 | { 351 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS; 352 | g_type_init(); 353 | G_GNUC_END_IGNORE_DEPRECATIONS; 354 | g_test_init(&argc, &argv, NULL); 355 | g_test_add_func(TEST_PREFIX "basic", test_inotify_basic); 356 | g_test_add_func(TEST_PREFIX "move", test_inotify_move); 357 | g_test_add_func(TEST_PREFIX "callback", test_inotify_callback); 358 | test_init(&test_opt, argc, argv); 359 | return g_test_run(); 360 | } 361 | 362 | /* 363 | * Local Variables: 364 | * mode: C 365 | * c-basic-offset: 4 366 | * indent-tabs-mode: nil 367 | * End: 368 | */ 369 | -------------------------------------------------------------------------------- /test/test_intarray/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | EXE = test_intarray 4 | 5 | include ../common/Makefile 6 | -------------------------------------------------------------------------------- /test/test_ints/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | EXE = test_ints 4 | 5 | include ../common/Makefile 6 | -------------------------------------------------------------------------------- /test/test_ints/test_ints.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017-2022 Jolla Ltd. 3 | * Copyright (C) 2017-2022 Slava Monich 4 | * 5 | * You may use this file under the terms of BSD license as follows: 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. Neither the names of the copyright holders nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | * THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "test_common.h" 34 | 35 | #include "gutil_ints.h" 36 | #include "gutil_misc.h" 37 | 38 | static TestOpt test_opt; 39 | 40 | /*==========================================================================* 41 | * NULL tolerance 42 | *==========================================================================*/ 43 | 44 | static 45 | void 46 | test_ints_null( 47 | void) 48 | { 49 | int val = 0; 50 | guint count; 51 | gutil_ints_unref(NULL); 52 | g_assert(!gutil_ints_ref(NULL)); 53 | g_assert(!gutil_ints_new(NULL, 0)); 54 | g_assert(!gutil_ints_new(NULL, 1)); 55 | g_assert(!gutil_ints_new(&val, 0)); 56 | g_assert(!gutil_ints_new_take(NULL, 0)); 57 | g_assert(!gutil_ints_new_take(NULL, 1)); 58 | g_assert(!gutil_ints_new_take(&val, 0)); 59 | g_assert(!gutil_ints_new_static(NULL, 0)); 60 | g_assert(!gutil_ints_new_static(NULL, 1)); 61 | g_assert(!gutil_ints_new_static(&val, 0)); 62 | g_assert(!gutil_ints_new_with_free_func(NULL, 0, NULL, NULL)); 63 | g_assert(!gutil_ints_new_with_free_func(NULL, 1, NULL, NULL)); 64 | g_assert(!gutil_ints_new_with_free_func(&val, 0, NULL, NULL)); 65 | g_assert(!gutil_ints_new_from_ints(NULL, 0, 0)); 66 | g_assert(!gutil_ints_hash(NULL)); 67 | g_assert(!gutil_ints_get_count(NULL)); 68 | g_assert(!gutil_ints_contains(NULL, 0)); 69 | g_assert(gutil_ints_find(NULL, 0) < 0); 70 | count = 1; 71 | g_assert(!gutil_ints_get_data(NULL, NULL)); 72 | g_assert(!gutil_ints_get_data(NULL, &count)); 73 | g_assert(!count); 74 | count = 1; 75 | g_assert(!gutil_ints_unref_to_data(NULL, NULL)); 76 | g_assert(!gutil_ints_unref_to_data(NULL, &count)); 77 | g_assert(!count); 78 | } 79 | 80 | /*==========================================================================* 81 | * Basic 82 | *==========================================================================*/ 83 | 84 | static 85 | void 86 | test_custom_free( 87 | gpointer data) 88 | { 89 | g_free(data); 90 | } 91 | 92 | static 93 | void 94 | test_ints_basic( 95 | void) 96 | { 97 | /* First 3 elements match */ 98 | const int a1[] = { 1, 2, 3 }; 99 | const int a2[] = { 1, 2, 3, 4 }; 100 | int* data; 101 | guint count; 102 | GUtilInts* i1 = gutil_ints_new(a1, G_N_ELEMENTS(a1)); 103 | GUtilInts* i2 = gutil_ints_new_static(a2, G_N_ELEMENTS(a2)); 104 | GUtilInts* i3; 105 | GUtilInts* i4; 106 | g_assert(gutil_ints_get_count(i1) == G_N_ELEMENTS(a1)); 107 | g_assert(gutil_ints_get_count(i2) == G_N_ELEMENTS(a2)); 108 | g_assert(gutil_ints_get_data(i1, NULL) != a2); 109 | g_assert(gutil_ints_get_data(i2, &count) == a2); 110 | g_assert(count == G_N_ELEMENTS(a2)); 111 | g_assert(!gutil_ints_new_from_ints(i1, G_N_ELEMENTS(a2), 1)); 112 | i3 = gutil_ints_new_from_ints(i1, 0, G_N_ELEMENTS(a1) + 1); 113 | i4 = gutil_ints_new_from_ints(i2, 0, G_N_ELEMENTS(a1)); 114 | 115 | g_assert(gutil_ints_equal(i1, i1)); 116 | g_assert(!gutil_ints_equal(i1, i2)); 117 | g_assert(gutil_ints_equal(i1, i3)); 118 | g_assert(gutil_ints_equal(i1, i3)); 119 | 120 | g_assert(!gutil_ints_contains(i1, 0)); 121 | g_assert(gutil_ints_contains(i1, 1)); 122 | 123 | g_assert(gutil_ints_find(i1, 0) < 0); 124 | g_assert(gutil_ints_find(i1, 1) == 0); 125 | g_assert(gutil_ints_find(i1, 2) == 1); 126 | 127 | /* This gutil_ints_unref_to_data doesn't actually free i1 because 128 | * a reference to it is held by i3: */ 129 | data = gutil_ints_unref_to_data(i1, &count); 130 | g_assert(count == G_N_ELEMENTS(a1)); 131 | g_assert(!memcmp(a1, data, count*sizeof(int))); 132 | g_free(data); 133 | 134 | gutil_ints_unref(i2); 135 | gutil_ints_unref(i3); 136 | gutil_ints_unref(i4); 137 | 138 | /* This gutil_ints_unref_to_data actually does free i1: */ 139 | i1 = gutil_ints_new(a1, G_N_ELEMENTS(a1)); 140 | data = gutil_ints_unref_to_data(i1, NULL); 141 | g_assert(!memcmp(a1, data, G_N_ELEMENTS(a1)*sizeof(int))); 142 | g_free(data); 143 | 144 | /* And this one duplicates the data because we use test_custom_free: */ 145 | data = gutil_memdup(a1, sizeof(a1)); 146 | i1 = gutil_ints_new_with_free_func(data, G_N_ELEMENTS(a1), 147 | test_custom_free, data); 148 | data = gutil_ints_unref_to_data(i1, &count); 149 | g_assert(count == G_N_ELEMENTS(a1)); 150 | g_assert(!memcmp(a1, data, count*sizeof(int))); 151 | g_free(data); 152 | } 153 | 154 | /*==========================================================================* 155 | * Compare 156 | *==========================================================================*/ 157 | 158 | static 159 | void 160 | test_ints_compare( 161 | void) 162 | { 163 | const int a1[] = { 1 }; 164 | const int a2[] = { 1, 2 }; 165 | const int a3[] = { 2 }; 166 | GUtilInts* i1 = gutil_ints_new_static(a1, G_N_ELEMENTS(a1)); 167 | GUtilInts* i2 = gutil_ints_new_static(a2, G_N_ELEMENTS(a2)); 168 | GUtilInts* i3 = gutil_ints_new_static(a3, G_N_ELEMENTS(a3)); 169 | GUtilInts* i4 = gutil_ints_new_from_ints(i1, 0, G_N_ELEMENTS(a1)); 170 | 171 | g_assert(gutil_ints_hash(i1) == 1235); 172 | g_assert(gutil_ints_hash(i2) == 1239); 173 | 174 | g_assert(gutil_ints_equal(NULL, NULL)); 175 | g_assert(!gutil_ints_equal(NULL, i1)); 176 | g_assert(!gutil_ints_equal(i1, NULL)); 177 | g_assert(!gutil_ints_equal(i1, i2)); 178 | g_assert(!gutil_ints_equal(i2, i1)); 179 | g_assert(!gutil_ints_equal(i1, i3)); 180 | g_assert(!gutil_ints_equal(i3, i1)); 181 | g_assert(gutil_ints_equal(i1, i4)); 182 | g_assert(gutil_ints_equal(i4, i1)); 183 | 184 | g_assert(gutil_ints_compare(NULL, NULL) == 0); 185 | g_assert(gutil_ints_compare(NULL, i1) < 0); 186 | g_assert(gutil_ints_compare(i1, NULL) > 0); 187 | g_assert(gutil_ints_compare(i1, i2) < 0); 188 | g_assert(gutil_ints_compare(i2, i1) > 0); 189 | g_assert(gutil_ints_compare(i1, i3) < 0); 190 | g_assert(gutil_ints_compare(i3, i1) > 0); 191 | g_assert(gutil_ints_compare(i1, i4) == 0); 192 | g_assert(gutil_ints_compare(i4, i1) == 0); 193 | 194 | gutil_ints_unref(i1); 195 | gutil_ints_unref(i2); 196 | gutil_ints_unref(i3); 197 | gutil_ints_unref(i4); 198 | } 199 | 200 | /*==========================================================================* 201 | * Common 202 | *==========================================================================*/ 203 | 204 | #define TEST_PREFIX "/ints/" 205 | 206 | int main(int argc, char* argv[]) 207 | { 208 | g_test_init(&argc, &argv, NULL); 209 | g_test_add_func(TEST_PREFIX "null", test_ints_null); 210 | g_test_add_func(TEST_PREFIX "basic", test_ints_basic); 211 | g_test_add_func(TEST_PREFIX "compare", test_ints_compare); 212 | test_init(&test_opt, argc, argv); 213 | return g_test_run(); 214 | } 215 | 216 | /* 217 | * Local Variables: 218 | * mode: C 219 | * c-basic-offset: 4 220 | * indent-tabs-mode: nil 221 | * End: 222 | */ 223 | -------------------------------------------------------------------------------- /test/test_log/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | CFLAGS += -DGLOG_LEVEL_MAX=GLOG_LEVEL_VERBOSE -DGLOG_LEVEL_ASSERT=GLOG_LEVEL_ALWAYS 4 | EXE = test_log 5 | 6 | include ../common/Makefile 7 | -------------------------------------------------------------------------------- /test/test_misc/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | EXE = test_misc 4 | 5 | include ../common/Makefile 6 | -------------------------------------------------------------------------------- /test/test_objv/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | EXE = test_objv 4 | 5 | include ../common/Makefile 6 | -------------------------------------------------------------------------------- /test/test_ring/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | EXE = test_ring 4 | 5 | include ../common/Makefile 6 | -------------------------------------------------------------------------------- /test/test_strv/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | EXE = test_strv 4 | 5 | include ../common/Makefile 6 | -------------------------------------------------------------------------------- /test/test_weakref/Makefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile-gmake -*- 2 | 3 | EXE = test_weakref 4 | 5 | include ../common/Makefile 6 | -------------------------------------------------------------------------------- /test/test_weakref/test_weakref.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Slava Monich 3 | * 4 | * You may use this file under the terms of BSD license as follows: 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the names of the copyright holders nor the names of its 16 | * contributors may be used to endorse or promote products derived 17 | * from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | * THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "test_common.h" 33 | 34 | #include "gutil_weakref.h" 35 | 36 | #include 37 | 38 | static TestOpt test_opt; 39 | 40 | /*==========================================================================* 41 | * null 42 | *==========================================================================*/ 43 | 44 | static 45 | void 46 | test_null() 47 | { 48 | gutil_weakref_unref(NULL); 49 | gutil_weakref_set(NULL, NULL); 50 | g_assert(!gutil_weakref_ref(NULL)); 51 | g_assert(!gutil_weakref_get(NULL)); 52 | } 53 | 54 | /*==========================================================================* 55 | * basic 56 | *==========================================================================*/ 57 | 58 | static 59 | void 60 | test_basic() 61 | { 62 | GObject* obj = g_object_new(TEST_OBJECT_TYPE, NULL); 63 | GUtilWeakRef* ref = gutil_weakref_new(obj); 64 | 65 | g_assert(gutil_weakref_ref(ref) == ref); 66 | gutil_weakref_unref(ref); 67 | g_assert(gutil_weakref_get(ref) == obj); 68 | g_object_unref(obj); 69 | gutil_weakref_unref(ref); 70 | 71 | ref = gutil_weakref_new(NULL); 72 | g_assert(!gutil_weakref_get(ref)); 73 | gutil_weakref_set(ref, obj); 74 | g_assert(gutil_weakref_get(ref) == obj); 75 | g_object_unref(obj); 76 | g_object_unref(obj); /* This actually deallocates the object */ 77 | g_assert(!gutil_weakref_get(ref)); 78 | gutil_weakref_unref(ref); 79 | } 80 | 81 | /*==========================================================================* 82 | * Common 83 | *==========================================================================*/ 84 | 85 | #define TEST_(name) "/weakref/" name 86 | 87 | int main(int argc, char* argv[]) 88 | { 89 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS; 90 | g_type_init(); 91 | G_GNUC_END_IGNORE_DEPRECATIONS; 92 | g_test_init(&argc, &argv, NULL); 93 | test_init(&test_opt, argc, argv); 94 | g_test_add_func(TEST_("null"), test_null); 95 | g_test_add_func(TEST_("basic"), test_basic); 96 | return g_test_run(); 97 | } 98 | 99 | /* 100 | * Local Variables: 101 | * mode: C 102 | * c-basic-offset: 4 103 | * indent-tabs-mode: nil 104 | * End: 105 | */ 106 | --------------------------------------------------------------------------------