├── debian ├── compat ├── librd0.install ├── .gitignore ├── librd-dev.install ├── changelog ├── rules ├── copyright └── control ├── tests ├── .gitignore ├── Makefile ├── Makefile.tests ├── 0002-units.c ├── 0003-file.c ├── 0007-rand.c ├── 0008-buf.c ├── 0001-fifoq.c ├── 0013-event.c ├── 0010-encoding.c ├── rdtests.h ├── 0005-opt.c ├── 0004-bits.c └── 0009-string.c ├── examples ├── .gitignore ├── Makefile └── rdvarint.c ├── .dir-locals.el ├── .gitignore ├── LICENSE.pycrc ├── LICENSE ├── rd.c ├── rdtypes.h ├── rdunits.h ├── rdio.h ├── rdiothread.h ├── rdrand.h ├── Makefile ├── rdio.c ├── rdgz.h ├── rdrand.c ├── rdsignal.h ├── rdlog.h ├── rdalert.h ├── rdlru.h ├── rdfloat.h ├── rdevent.c ├── rdbits.h ├── rdfile.h ├── rdlru.c ├── rdtime.h ├── rdalert.c ├── rdcrc32.h ├── rdenum2str.pl ├── rdfile.c ├── rd.h ├── rdevent.h ├── rdgz.c ├── rdbits.c ├── rdencoding.h ├── rdunits.c ├── rdqueue.h ├── rdavg.h ├── rdstring.h ├── rdencoding.c ├── README.markdown ├── rdlog.c ├── rdqueue.c ├── rdavg.c ├── rdcrc32.c ├── rdopt.h ├── rdthread.c ├── rdtimer.h ├── rdbuf.h └── rdstring.c /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | *.test 2 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | rdvarint 2 | -------------------------------------------------------------------------------- /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ( (c-mode . ((c-file-style . "linux"))) ) 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | \#* 3 | *.o 4 | *.so 5 | *.so.? 6 | *.a 7 | *.d 8 | core 9 | -------------------------------------------------------------------------------- /debian/librd0.install: -------------------------------------------------------------------------------- 1 | usr/lib/*.so.* 2 | usr/share/doc/*/README.markdown 3 | -------------------------------------------------------------------------------- /debian/.gitignore: -------------------------------------------------------------------------------- 1 | tmp 2 | librd-dbg 3 | librd0 4 | librd-dev 5 | *.substvars 6 | *.log 7 | *.debhelper 8 | files 9 | -------------------------------------------------------------------------------- /debian/librd-dev.install: -------------------------------------------------------------------------------- 1 | usr/include 2 | usr/lib/*.a 3 | #usr/lib/*/pkgconfig 4 | #usr/share/info 5 | #usr/share/man 6 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | librd (0.2.0-1) unstable; urgency=low 2 | 3 | * Initial debian packaging. 4 | 5 | -- Magnus Edenhill Fri, 01 Mar 2013 09:03:37 +0100 6 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Makefile wrapper for expanding 0*.c glob. 3 | 4 | .PHONY: all test clean testcontinue 5 | 6 | all test clean: 7 | @echo "=================== SELFTESTS =======================" 8 | @(export TEST_SRCS="`echo 0*.c`"; make -B -f Makefile.tests $@) 9 | 10 | testcontinue: 11 | @echo "=================== SELFTESTS (continue on fail) ====" 12 | @(export TEST_SRCS="`echo 0*.c`"; make -B -k -f Makefile.tests test) 13 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | CC ?= cc 2 | CFLAGS += -g 3 | CFLAGS += -Wall -Werror -Wfloat-equal -Wpointer-arith -O2 -I../ 4 | LDFLAGS += -L../ ../librd.a 5 | LDFLAGS += -lpthread -lrt -lz 6 | 7 | # Profiling 8 | #CFLAGS += -O0 -pg 9 | #LDFLAGS += -pg 10 | 11 | .PHONY: all clean 12 | 13 | all: 14 | @echo "# Examples are built individually" 15 | @echo " make rdvarint" 16 | 17 | rdvarint: rdvarint.c 18 | $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) 19 | 20 | clean: 21 | rm -f rdvarint 22 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | #export DH_VERBOSE=1 3 | 4 | %: 5 | dh $@ 6 | 7 | 8 | override_dh_auto_build: 9 | make libs 10 | 11 | #override_dh_auto_install: 12 | # dh_auto_install 13 | 14 | override_dh_builddeb: 15 | dh_builddeb -- -Zgzip -z9 16 | 17 | override_dh_auto_install: 18 | dh_auto_install --destdir=debian/tmp/usr 19 | 20 | override_dh_install: 21 | dh_install --autodest --list-missing 22 | 23 | override_dh_strip: 24 | dh_strip --dbg-package=librd-dbg 25 | -------------------------------------------------------------------------------- /tests/Makefile.tests: -------------------------------------------------------------------------------- 1 | 2 | CC ?= cc 3 | TEST_PROGS := ${TEST_SRCS:%.c=%.test} 4 | CFLAGS += -g 5 | CFLAGS += -fstack-protector --param=ssp-buffer-size=4 -Wformat 6 | -Werror=format-security 7 | CFLAGS += -Wall -Werror -Wfloat-equal -Wpointer-arith -O2 -I../ 8 | LDFLAGS += ../librd.a -lpthread -lrt -lz 9 | 10 | # Profiling 11 | #CFLAGS += -O0 -pg 12 | #LDFLAGS += -pg 13 | 14 | all: test 15 | 16 | %.test: %.c 17 | @(LIBS=`grep '^//LIBS=' $< | sed -e 's/^\/\/LIBS=//'` ; \ 18 | if ! $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) $$LIBS ; then \ 19 | echo "########################################";\ 20 | echo "########################################";\ 21 | echo "Test $< did not compile" ; \ 22 | echo "########################################";\ 23 | echo "########################################";\ 24 | false ; \ 25 | else \ 26 | echo -n "Test $< "; \ 27 | (LD_LIBRARY_PATH=../ ./$@ && echo "passed") || \ 28 | (echo "failed";\ 29 | echo "########################################";\ 30 | echo "########################################";\ 31 | echo "Test $< failed";\ 32 | echo "########################################";\ 33 | echo "########################################";\ 34 | false); \ 35 | fi) 36 | 37 | 38 | test: $(TEST_PROGS) 39 | 40 | clean: 41 | rm -f $(TEST_PROGS) 42 | -------------------------------------------------------------------------------- /LICENSE.pycrc: -------------------------------------------------------------------------------- 1 | The following license applies to the files rdcrc32.c and rdcrc32.h which 2 | have been generated by the pycrc tool. 3 | ============================================================================ 4 | 5 | Copyright (c) 2006-2012, Thomas Pircher 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | librd - Rapid Development C library 2 | 3 | Copyright (c) 2012-2013 Magnus Edenhill 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /rd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | 31 | 32 | void rd_init (void) { 33 | extern void rd_thread_init (void); 34 | extern void rd_timers_init(); 35 | rd_thread_init(); 36 | rd_timers_init(); 37 | } 38 | -------------------------------------------------------------------------------- /rdtypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include 32 | 33 | 34 | /* 35 | * Fundamental types 36 | */ 37 | 38 | 39 | 40 | 41 | typedef pthread_mutex_t rd_mutex_t; 42 | typedef pthread_rwlock_t rd_rwlock_t; 43 | typedef pthread_cond_t rd_cond_t; 44 | 45 | 46 | /* Timestamp (microseconds) */ 47 | typedef uint64_t rd_ts_t; 48 | -------------------------------------------------------------------------------- /rdunits.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #define RD_SIZE_KIB(V) ((V) * 1024LLU) 32 | #define RD_SIZE_MIB(V) ((V) * 1048576LLU) 33 | #define RD_SIZE_GIB(V) ((V) * 1073741824LLU) 34 | #define RD_SIZE_TIB(V) ((V) * 1099511627776LLU) 35 | #define RD_SIZE_PIB(V) ((V) * 1125899906842624LLU) 36 | 37 | const char *rd_size2str (uint64_t size, int si, const char *unitsuffix); 38 | -------------------------------------------------------------------------------- /rdio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | 32 | #include 33 | 34 | #define RD_POLL_INFINITE -1 35 | #define RD_POLL_NOWAIT 0 36 | 37 | 38 | /** 39 | * Poll a single 'fd' for 'events' with timeout 'timeout_ms' according to 40 | * poll(2) behaviour. 41 | * Returns the revents bits, or 0 on no events, or -1 on failure. 42 | */ 43 | int rd_io_poll_single (int fd, short events, int timeout_ms); 44 | -------------------------------------------------------------------------------- /rdiothread.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include "rdthread.h" 32 | 33 | #include 34 | 35 | 36 | int rd_io_del (int fd); 37 | 38 | #define RD_IO_F_NONBLOCKING 0x1 /* Handler promises only to perform 39 | * nonblocking ops. */ 40 | 41 | int rd_io_add (int fd, int events, int flags, rd_thread_t *target_thread, 42 | void (*handler) (int fd, int events, 43 | rd_thread_t *target_thread, void *opaque), 44 | void *opaque); 45 | -------------------------------------------------------------------------------- /rdrand.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | 32 | /** 33 | * Returns a random (using rand(3)) number between 'low'..'high' (inclusive). 34 | */ 35 | static inline int rd_jitter (int low, int high) RD_UNUSED; 36 | static inline int rd_jitter (int low, int high) { 37 | return (low + (rand() % (high+1))); 38 | 39 | } 40 | 41 | 42 | /** 43 | * Shuffles (randomizes) an array using the modern Fisher-Yates algorithm. 44 | */ 45 | void rd_array_shuffle (void *base, size_t nmemb, size_t entry_size); 46 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | LIBNAME=librd 3 | LIBVER=0 4 | LIBVER_FULL=$(LIBVER).0.0 5 | 6 | DESTDIR?=/usr/local 7 | 8 | SRCS= rd.c rdevent.c rdqueue.c rdthread.c rdtimer.c rdfile.c rdunits.c \ 9 | rdlog.c rdbits.c rdopt.c rdmem.c rdaddr.c rdstring.c rdcrc32.c \ 10 | rdgz.c rdrand.c rdbuf.c rdavl.c rdio.c rdencoding.c rdiothread.c \ 11 | rdlru.c rdavg.c rdalert.c 12 | 13 | HDRS= rdbits.h rdevent.h rdfloat.h rd.h rdsysqueue.h rdqueue.h \ 14 | rdsignal.h rdthread.h rdtime.h rdtimer.h rdtypes.h rdfile.h rdunits.h \ 15 | rdlog.h rdopt.h rdmem.h rdaddr.h rdstring.h rdcrc32.h \ 16 | rdgz.h rdrand.h rdbuf.h rdavl.h rdio.h rdencoding.h rdiothread.h \ 17 | rdlru.h rdavg.h rdalert.h 18 | 19 | OBJS= $(SRCS:.c=.o) 20 | DEPS= ${OBJS:%.o=%.d} 21 | 22 | CFLAGS+=-Wformat -fno-stack-protector 23 | CFLAGS+=-O2 -Wall -Werror -Wfloat-equal -Wformat-security -Wpointer-arith -fPIC -I. 24 | CFLAGS+=-g 25 | 26 | # Profiling 27 | #CFLAGS+=-O0 28 | #CFLAGS += -pg 29 | #LDFLAGS += -pg 30 | 31 | LDFLAGS+=-g 32 | 33 | .PHONY: testcontinue test libs install clean 34 | 35 | all: libs testcontinue 36 | 37 | libs: $(LIBNAME).so.$(LIBVER) $(LIBNAME).a 38 | 39 | %.o: %.c 40 | $(CC) -MD -MP $(CFLAGS) -c $< 41 | 42 | $(LIBNAME).so.$(LIBVER): $(OBJS) 43 | $(LD) -fPIC -shared -soname,$@ \ 44 | $(LDFLAGS) $(OBJS) -o $@ 45 | ln -fs $(LIBNAME).so.$(LIBVER) $(LIBNAME).so 46 | 47 | $(LIBNAME).a: $(OBJS) 48 | $(AR) rcs $@ $(OBJS) 49 | 50 | testcontinue: 51 | make -C tests $@ 52 | 53 | test: 54 | make -C tests $@ 55 | 56 | install: 57 | install -d $(DESTDIR)/include/librd 58 | install -d $(DESTDIR)/lib 59 | install -d $(DESTDIR)/share/doc/librd$(LIBVER) 60 | install -t $(DESTDIR)/include/librd $(HDRS) 61 | install -t $(DESTDIR)/lib $(LIBNAME).so 62 | install -t $(DESTDIR)/lib $(LIBNAME).so.$(LIBVER) 63 | install -t $(DESTDIR)/lib $(LIBNAME).a 64 | install -t $(DESTDIR)/share/doc/librd$(LIBVER) README.markdown 65 | 66 | clean: 67 | make -C tests clean 68 | rm -f $(OBJS) $(DEPS) $(LIBNAME).a $(LIBNAME).so $(LIBNAME).so.$(LIBVER) 69 | 70 | -include $(DEPS) 71 | -------------------------------------------------------------------------------- /rdio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #define __need_IOV_MAX 36 | #include 37 | 38 | #include "rd.h" 39 | #include "rdio.h" 40 | 41 | 42 | 43 | int rd_io_poll_single (int fd, short events, int timeout_ms) { 44 | struct pollfd fds = { .fd = fd, .events = events }; 45 | int r; 46 | 47 | if ((r = poll(&fds, 1, timeout_ms)) <= 0) 48 | return r; 49 | 50 | return fds.revents; 51 | } 52 | -------------------------------------------------------------------------------- /rdgz.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | /** 32 | * Simple gzip decompression returning the inflated data 33 | * in a malloced buffer. 34 | * '*decompressed_lenp' must be 0 if the length of the uncompressed data 35 | * is not known in which case it will be calculated. 36 | * The returned buffer is nul-terminated (the actual allocated length 37 | * is '*decompressed_lenp'+1. 38 | * 39 | * The decompressed length is returned in '*decompressed_lenp'. 40 | */ 41 | void *rd_gz_decompress (void *compressed, int compressed_len, 42 | uint64_t *decompressed_lenp); 43 | -------------------------------------------------------------------------------- /rdrand.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdrand.h" 31 | 32 | 33 | 34 | void rd_array_shuffle (void *base, size_t nmemb, size_t entry_size) { 35 | int i; 36 | void *tmp = alloca(entry_size); 37 | 38 | /* FIXME: Optimized version for word-sized entries. */ 39 | 40 | for (i = nmemb - 1 ; i > 0 ; i--) { 41 | int j = rd_jitter(0, i); 42 | if (unlikely(i == j)) 43 | continue; 44 | 45 | memcpy(tmp, (char *)base + (i*entry_size), entry_size); 46 | memcpy((char *)base+(i*entry_size), 47 | (char *)base+(j*entry_size), entry_size); 48 | memcpy((char *)base+(j*entry_size), tmp, entry_size); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /rdsignal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include 32 | 33 | #define RD_SIG_ALL -1 34 | #define RD_SIG_END -2 35 | 36 | extern sigset_t rd_intr_sigset; 37 | extern int rd_intr_blocked; 38 | 39 | static inline void rd_intr_block (void) RD_UNUSED; 40 | static inline void rd_intr_block (void) { 41 | if (rd_intr_blocked++) 42 | return; 43 | 44 | sigprocmask(SIG_BLOCK, &rd_intr_sigset, NULL); 45 | } 46 | 47 | static inline void rd_intr_unblock (void) RD_UNUSED; 48 | static inline void rd_intr_unblock (void) { 49 | assert(rd_intr_blocked > 0); 50 | if (--rd_intr_blocked) 51 | return; 52 | 53 | sigprocmask(SIG_UNBLOCK, &rd_intr_sigset, NULL); 54 | } 55 | -------------------------------------------------------------------------------- /rdlog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include 32 | #include 33 | 34 | void rdputs0 (const char *file, const char *func, int line, 35 | int severity,const char *fmt, ...) 36 | __attribute__((format (printf, 5, 6))); 37 | 38 | #define rdbg(fmt...) \ 39 | rdputs0(__FILE__,__FUNCTION__,__LINE__,LOG_DEBUG,fmt) 40 | #define rdlog(severity,fmt...) \ 41 | rdputs0(__FILE__,__FUNCTION__,__LINE__,severity,fmt) 42 | 43 | void rd_dbg_ctx_push (const char *fmt, ...); 44 | void rd_dbg_ctx_pop (void); 45 | void rd_dbg_ctx_clear (void); 46 | void rd_log_set_severity (int severity); 47 | 48 | #define rd_dbg_set(onoff) rd_log_set_severity(onoff ? LOG_DEBUG : LOG_INFO) 49 | 50 | void rd_hexdump (FILE *fp, const char *name, const void *ptr, size_t len); 51 | -------------------------------------------------------------------------------- /examples/rdvarint.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | 30 | /* Typical include path would be , but this program 31 | * is builtin from within the librd source tree and thus differs. */ 32 | #include "rd.h" /* librd base */ 33 | #include "rdlog.h" 34 | #include "rdencoding.h" 35 | 36 | int main (int argc, char **argv) { 37 | uint64_t u64; 38 | char buf[16]; 39 | int len, vlen; 40 | 41 | if (argc < 3) { 42 | fprintf(stderr, "Usage: %s {encode|decode} \n", argv[0]); 43 | exit(1); 44 | } 45 | 46 | 47 | if (argv[1][0] == 'e') { 48 | u64 = strtoull(argv[2], NULL, 0); 49 | len = rd_varint_encode_u64(u64, buf, sizeof(buf)); 50 | printf("encoded u64 %"PRIu64" to:\n", u64); 51 | rd_hexdump(stdout, "hexdump", buf, len); 52 | } else { 53 | len = rd_hex2bin(argv[2], -1, buf, sizeof(buf)); 54 | u64 = rd_varint_decode_u64(buf, len, &vlen); 55 | printf("decoded %s to vlen %i: %"PRIu64 "\n", 56 | argv[2], vlen, u64); 57 | if (vlen < 0) 58 | printf("Error: overflow\n"); 59 | else if (vlen == 0) 60 | printf("Error: buffer was empty\n"); 61 | } 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Files: * 2 | Copyright: (C) 2012-2013 Magnus Edenhill () 3 | License: BSD-2-clause 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | . 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | . 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | POSSIBILITY OF SUCH DAMAGE. 24 | 25 | Files: rdcrc32.* 26 | Copyright: (C) 2006-2012, Thomas Pircher 27 | License: MIT 28 | 29 | Permission is hereby granted, free of charge, to any person obtaining a copy 30 | of this software and associated documentation files (the "Software"), to deal 31 | in the Software without restriction, including without limitation the rights 32 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 33 | copies of the Software, and to permit persons to whom the Software is 34 | furnished to do so, subject to the following conditions: 35 | . 36 | The above copyright notice and this permission notice shall be included in 37 | all copies or substantial portions of the Software. 38 | . 39 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 41 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 42 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 43 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 44 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 45 | THE SOFTWARE. 46 | 47 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: librd 2 | Section: libs 3 | Priority: optional 4 | Maintainer: Magnus Edenhill 5 | Build-Depends: zlib1g-dev 6 | Standards-Version: 3.9.3 7 | Vcs-Git: git://github.com/edenhill/librd.git 8 | Vcs-Browser: https://github.com/edenhill/librd 9 | Homepage: https://github.com/edenhill/librd 10 | 11 | Package: librd0 12 | Provides: librd 13 | Architecture: any 14 | Pre-Depends: multiarch-support 15 | Depends: zlib1g, ${misc:Depends}, ${shlibs:Depends} 16 | Description: Rapid Development C library 17 | librd aims to provide the commonly needed helpers, sub systems, snippets and 18 | misc. functionality that lacks from the standard C libraries, allowing for 19 | rapid development of new programs and non-intrusive extension of existing 20 | applications. 21 | librd provides, on a higher level: 22 | * proper thread support throughout the library 23 | * consistent, natural and non-bloated APIs and interfaces 24 | * scalability and performance 25 | * suitable for embedded systems, large-scale backend systems, 26 | GUI applications, etc. 27 | 28 | Package: librd-dbg 29 | Section: debug 30 | Priority: extra 31 | Architecture: any 32 | Depends: 33 | ${misc:Depends}, librd0 (= ${binary:Version}), 34 | librd-dev (= ${binary:Version}) 35 | Description: Rapid Development C library 36 | librd aims to provide the commonly needed helpers, sub systems, snippets and 37 | misc. functionality that lacks from the standard C libraries, allowing for 38 | rapid development of new programs and non-intrusive extension of existing 39 | applications. 40 | librd provides, on a higher level: 41 | * proper thread support throughout the library 42 | * consistent, natural and non-bloated APIs and interfaces 43 | * scalability and performance 44 | * suitable for embedded systems, large-scale backend systems, 45 | GUI applications, etc. 46 | . 47 | This package contains the debugging symbols. 48 | 49 | Package: librd-dev 50 | Section: libdevel 51 | Architecture: any 52 | Depends: ${misc:Depends}, librd0 (= ${binary:Version}) 53 | Description: Rapid Development C library 54 | librd aims to provide the commonly needed helpers, sub systems, snippets and 55 | misc. functionality that lacks from the standard C libraries, allowing for 56 | rapid development of new programs and non-intrusive extension of existing 57 | applications. 58 | librd provides, on a higher level: 59 | * proper thread support throughout the library 60 | * consistent, natural and non-bloated APIs and interfaces 61 | * scalability and performance 62 | * suitable for embedded systems, large-scale backend systems, 63 | GUI applications, etc. 64 | . 65 | This package contains the development files. 66 | -------------------------------------------------------------------------------- /tests/0002-units.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdunits.h" 31 | 32 | 33 | static int size2str_tests (void) { 34 | int fails = 0; 35 | static const struct { 36 | uint64_t val; 37 | int si; 38 | const char *exp; 39 | } in[] = { 40 | { 1023, 0, "1023B" }, 41 | { 1024, 0, "1KiB" }, 42 | { 1025, 0, "1KiB" }, 43 | { 149982691759LLU, 0, "139.68GiB" }, 44 | { 213921076233013234LLU, 0, "190PiB" }, 45 | /* SI units */ 46 | { 1023, 1, "1.02KB" }, 47 | { 2048, 1, "2.05KB" }, 48 | { 1234567LLU, 1, "1.23MB" }, 49 | { 189890123456794833LLU, 1, "189.89PB" }, 50 | { 0, 0, NULL }, 51 | }; 52 | int i = 0; 53 | const char *t; 54 | 55 | 56 | do { 57 | t = rd_size2str(in[i].val, in[i].si, "B"); 58 | if (strcmp(t, in[i].exp)) { 59 | printf("rd_size2str() test #%i failed: " 60 | "val %" PRIu64 ", si=%i expected '%s', " 61 | "but got '%s'\n", 62 | i, in[i].val, in[i].si, in[i].exp, t); 63 | fails++; 64 | } 65 | 66 | } while (in[++i].exp); 67 | 68 | return fails; 69 | } 70 | 71 | 72 | int main (int argc, char **argv) { 73 | int fails = 0; 74 | 75 | rd_init(); 76 | 77 | fails += size2str_tests(); 78 | 79 | return fails ? 1 : 0; 80 | } 81 | -------------------------------------------------------------------------------- /rdalert.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | 30 | 31 | typedef enum { 32 | /* A thread has stalled its operation. 33 | * (May be legit due to a long-running operation). 34 | * 35 | * Locality: any thread 36 | * Arguments: 37 | * rd_thread_t *stalling_thread 38 | * int stall_time <-- in seconds, may be 0 if unknown. 39 | */ 40 | RD_ALERT_THREAD_STALL, 41 | 42 | /* Used for registration: subscribe to all alert types. */ 43 | RD_ALERT_ALL, 44 | } rd_alert_type_t; 45 | 46 | 47 | 48 | void rd_alert0 (const char *file, const char *func, int line, 49 | rd_alert_type_t type, int level, const char *reason, ...); 50 | 51 | #define rd_alert(type, level...) \ 52 | rd_alert0(__FILE__,__FUNCTION__,__LINE__,type, level) 53 | 54 | 55 | 56 | 57 | /** 58 | * Register callback for alert type 'type' (or all types if type 59 | * is RD_ALERT_ALL). 60 | * The callbacks will be called with the fixed arguments as well as the 61 | * type-specific arguments documented above in rd_alert_type_t. 62 | * 63 | * NOTE: A callback must not call rd_alert_register(). 64 | * 65 | * Any number of callbacks can be registered. 66 | */ 67 | void rd_alert_register (rd_alert_type_t type, 68 | void (*callback) (rd_alert_type_t type, int level, 69 | const char *reason, void *opaque, 70 | va_list ap), 71 | void *opaque); 72 | -------------------------------------------------------------------------------- /rdlru.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include "rdthread.h" 32 | #include "rdsysqueue.h" 33 | 34 | 35 | 36 | typedef struct rd_lru_elm_s { 37 | TAILQ_ENTRY(rd_lru_elm_s) rlrue_link; 38 | void *rlrue_ptr; 39 | } rd_lru_elm_t; 40 | 41 | TAILQ_HEAD(rd_lru_elm_head, rd_lru_elm_s); 42 | 43 | 44 | typedef struct rd_lru_s { 45 | rd_mutex_t rlru_lock; 46 | rd_cond_t rlru_cond; 47 | int rlru_cnt; 48 | struct rd_lru_elm_head rlru_elms; 49 | } rd_lru_t; 50 | 51 | 52 | #define RD_LRU_INITIALIZER(st) \ 53 | { .rlru_elms = TAILQ_HEAD_INITIALIZER(st.rlru_elms) } 54 | 55 | #define rd_lru_lock(rlru) rd_mutex_lock(&(rlru)->rlru_lock) 56 | #define rd_lru_unlock(rlru) rd_mutex_unlock(&(rlru)->rlru_lock) 57 | 58 | 59 | /** 60 | * Destroys an LRU 61 | */ 62 | void rd_lru_destroy (rd_lru_t *rlru); 63 | 64 | 65 | /** 66 | * Creates a new LRU 67 | */ 68 | rd_lru_t *rd_lru_new (void); 69 | 70 | 71 | /** 72 | * Push a new entry to the LRU. 73 | */ 74 | void rd_lru_push (rd_lru_t *rlru, void *ptr); 75 | 76 | /** 77 | * Returns and removes the oldest entry in the LRU, or NULL. 78 | */ 79 | void *rd_lru_pop (rd_lru_t *rlru); 80 | 81 | /** 82 | * Returns and removes the youngest entry in the LRU, or NULL. 83 | */ 84 | void *rd_lru_shift (rd_lru_t *rlru); 85 | 86 | /** 87 | * Returns the number of entries in the LRU 88 | */ 89 | #define rd_lru_cnt(rlru) ((rlru)->rlru_cnt) 90 | -------------------------------------------------------------------------------- /tests/0003-file.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdfile.h" 31 | 32 | #include "rdtests.h" 33 | 34 | static int test_read_write (void) { 35 | TEST_VARS; 36 | const char *path = "__tmp_test_0003"; 37 | int r; 38 | char buf[] = 39 | "Line1 is 22 bytes long\n" 40 | "Line2 is just 16\n"; 41 | int blen = strlen(buf); 42 | int len; 43 | char *tmp; 44 | 45 | r = rd_file_write(path, buf, blen, O_TRUNC, 0600); 46 | if (r == -1) { 47 | unlink(path); 48 | TEST_FAIL_RETURN("file write: %s", strerror(errno)); 49 | } 50 | 51 | tmp = rd_file_read(path, &len); 52 | if (!tmp) { 53 | unlink(path); 54 | TEST_FAIL_RETURN("file read: %s", strerror(errno)); 55 | } 56 | 57 | if (len != blen) 58 | TEST_FAIL("file read: written len %i != read len %i", 59 | blen, len); 60 | 61 | free(tmp); 62 | 63 | unlink(path); 64 | 65 | TEST_RETURN; 66 | } 67 | 68 | 69 | int main (int argc, char **argv) { 70 | TEST_VARS; 71 | const char *path1 = "/abra/cadabra/bot"; 72 | const char *name1 = "bot"; 73 | const char *path2 = "/abra/camambra/bark/"; 74 | const char *name2 = ""; 75 | const char *path3 = "/"; 76 | const char *name3 = ""; 77 | 78 | rd_init(); 79 | 80 | fails += strcmp(rd_basename(path1), name1); 81 | fails += strcmp(rd_basename(path2), name2); 82 | fails += strcmp(rd_basename(path3), name3); 83 | if (fails) 84 | TEST_FAIL("rd_basename tests failed"); 85 | 86 | fails += test_read_write(); 87 | 88 | TEST_EXIT; 89 | } 90 | -------------------------------------------------------------------------------- /rdfloat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include 32 | 33 | /** 34 | * rd_deq0(a,b,prec) 35 | * Check two doubles for equality with the specified precision. 36 | * Use this instead of != and == for all floats/doubles. 37 | * More info: 38 | * http://docs.sun.com/source/806-3568/ncg_goldberg.html 39 | */ 40 | static inline int rd_deq0 (double a, double b, double prec) RD_UNUSED; 41 | static inline int rd_deq0 (double a, double b, double prec) { 42 | return fabs(a - b) < prec; 43 | } 44 | 45 | /* A default 'good' double-equality precision value. 46 | * This rather timid epsilon value is useful for tenths, hundreths, 47 | * and thousands parts, but not anything more precis than that. 48 | * If a higher precision is needed, use deq0 and deq0 directly 49 | * and specify your own precision. */ 50 | #define RD_DBL_EPSILON 0.00001 51 | 52 | /** 53 | * rd_deq(a,b) 54 | * Same as rd_deq0() above but with a predefined 'good' precision. 55 | */ 56 | #define rd_deq(a,b) rd_deq0(a,b,RD_DBL_EPSILON) 57 | 58 | /** 59 | * rd_dne(a,b) 60 | * Same as rd_deq() above but with reversed logic: not-equal. 61 | */ 62 | #define rd_dne(a,b) (!rd_deq0(a,b,RD_DBL_EPSILON)) 63 | 64 | /** 65 | * rd_dz(a) 66 | * Checks if the double `a' is zero (or close enough). 67 | */ 68 | #define rd_dz(a) rd_deq0(a,0.0,RD_DBL_EPSILON) 69 | 70 | /** 71 | * rd_dnz(a) 72 | * Checks if the double `a' is not zero. 73 | */ 74 | #define rd_dnz(a) (!rd_deq0(a,0.0,RD_DBL_EPSILON)) 75 | -------------------------------------------------------------------------------- /rdevent.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdevent.h" 31 | 32 | 33 | struct func_cb_ctx { 34 | int argcnt; 35 | void *args[4]; 36 | void *cb; 37 | }; 38 | 39 | static rd_thread_event_f(rd_thread_event_func_cb) { 40 | struct func_cb_ctx *ctx = ptr; 41 | 42 | /* This might look silly, but it's convenient. */ 43 | switch (ctx->argcnt) 44 | { 45 | case 0: 46 | ((void (*)(void)) 47 | (ctx->cb))(); 48 | break; 49 | 50 | case 1: 51 | ((void (*)(void *)) 52 | (ctx->cb))(ctx->args[0]); 53 | break; 54 | 55 | case 2: 56 | ((void (*)(void *, void *)) 57 | (ctx->cb))(ctx->args[0], 58 | ctx->args[1]); 59 | break; 60 | 61 | case 3: 62 | ((void (*)(void *, void *, void *)) 63 | (ctx->cb))(ctx->args[0], 64 | ctx->args[1], 65 | ctx->args[2]); 66 | break; 67 | 68 | case 4: 69 | ((void (*)(void *, void *, void *, void *)) 70 | (ctx->cb))(ctx->args[0], 71 | ctx->args[1], 72 | ctx->args[2], 73 | ctx->args[3]); 74 | break; 75 | 76 | default: 77 | assert(!*"rd_thread_func_call: invalid argcnt"); 78 | } 79 | 80 | free(ctx); 81 | } 82 | 83 | 84 | void rd_thread_func_call (rd_thread_t *rdt, void *cb, int argcnt, void **args) { 85 | struct func_cb_ctx *ctx; 86 | 87 | ctx = malloc(sizeof(*ctx)); 88 | ctx->cb = cb; 89 | 90 | assert(argcnt <= 4); 91 | for (ctx->argcnt = 0 ; ctx->argcnt < argcnt ; ctx->argcnt++) 92 | ctx->args[ctx->argcnt] = args[ctx->argcnt]; 93 | 94 | rd_thread_event_add(rdt, rd_thread_event_func_cb, ctx); 95 | } 96 | -------------------------------------------------------------------------------- /rdbits.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include 32 | 33 | #define BIT_SET(f,b) ((f) |= (b)) 34 | #define BIT_RESET(f,b) ((f) &= ~(b)) 35 | #define BIT_TEST(f,b) ((f) & (b)) 36 | #define BIT_MATCH(f,b) (((f) & (b)) == (b)) 37 | 38 | 39 | #define rd_assert_bit(VAR,BIT) assert(((VAR) & (BIT))) 40 | #define rd_assert_nbit(VAR,BIT) assert(!((VAR) & (BIT))) 41 | 42 | 43 | /** 44 | * Bit vectors 45 | */ 46 | 47 | typedef enum { 48 | RD_BITVEC_STATIC, /* Vector does not grow, allocated on init. */ 49 | } rd_bitvec_type_t; 50 | 51 | typedef struct rd_bitvec_s { 52 | uint64_t rbv_max; 53 | uint64_t rbv_size; 54 | int rbv_buckets; 55 | uint32_t *rbv_b; 56 | } rd_bitvec_t; 57 | 58 | void rd_bitvec_init (rd_bitvec_t *rbv, rd_bitvec_type_t type, 59 | uint64_t max_val); 60 | void rd_bitvec_free (rd_bitvec_t *rbv); 61 | 62 | typedef enum { 63 | RD_BITVEC_OP_SET, 64 | RD_BITVEC_OP_RESET, 65 | RD_BITVEC_OP_TEST, 66 | RD_BITVEC_OP_FFS, 67 | RD_BITVEC_OP_FLS 68 | } rd_bitvec_op_t; 69 | 70 | int rd_bitvec_op (rd_bitvec_t *rbv, uint64_t i, rd_bitvec_op_t op); 71 | 72 | #define rd_bitvec_set(rbv,i) rd_bitvec_op(rbv,i,RD_BITVEC_OP_SET) 73 | #define rd_bitvec_reset(rbv,i) rd_bitvec_op(rbv,i,RD_BITVEC_OP_RESET) 74 | #define rd_bitvec_test(rbv,i) rd_bitvec_op(rbv,i,RD_BITVEC_OP_TEST) 75 | 76 | 77 | uint64_t rd_bitvec_fxs (const rd_bitvec_t *rbv, rd_bitvec_op_t op); 78 | #define rd_bitvec_ffs(rbv) rd_bitvec_fxs(rbv,RD_BITVEC_OP_FFS) 79 | #define rd_bitvec_fls(rbv) rd_bitvec_fxs(rbv,RD_BITVEC_OP_FLS) 80 | -------------------------------------------------------------------------------- /rdfile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | 38 | /** 39 | * Behaves pretty much like basename(3) but does not alter the 40 | * input string in any way. 41 | */ 42 | const char *rd_basename (const char *path); 43 | 44 | /** 45 | * Returns the current directory in a static buffer. 46 | */ 47 | const char *rd_pwd (void); 48 | 49 | 50 | /** 51 | * Returns the size of the file, or -1 on failure. 52 | */ 53 | ssize_t rd_file_size (const char *path); 54 | 55 | /** 56 | * Returns the size of the file already opened, or -1 on failure. 57 | */ 58 | ssize_t rd_file_size_fd (int fd); 59 | 60 | 61 | /** 62 | * Performs stat(2) on 'path' and returns 'struct stat.st_mode' on success 63 | * or 0 on failure. 64 | * 65 | * Example usage: 66 | * if (S_ISDIR(rd_file_mode(mypath))) 67 | * .. 68 | */ 69 | mode_t rd_file_mode (const char *path); 70 | 71 | 72 | /** 73 | * Opens the specified file and reads the entire content into a malloced 74 | * buffer which is null-terminated. The actual length of the buffer, without 75 | * the conveniant null-terminator, is returned in '*lenp'. 76 | * The buffer is returned, or NULL on failure. 77 | */ 78 | char *rd_file_read (const char *path, int *lenp); 79 | 80 | 81 | /** 82 | * Writes 'buf' of 'len' bytes to 'path'. 83 | * Hint: Use O_APPEND or O_TRUNC in 'flags'. 84 | * Returns 0 on success or -1 on error. 85 | * See open(2) for more info. 86 | */ 87 | int rd_file_write (const char *path, const char *buf, int len, 88 | int flags, mode_t mode); 89 | -------------------------------------------------------------------------------- /rdlru.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdlru.h" 31 | 32 | 33 | static void rd_lru_elm_destroy (rd_lru_t *rlru, rd_lru_elm_t *rlrue) { 34 | assert(rlru->rlru_cnt > 0); 35 | rlru->rlru_cnt--; 36 | if (rlru) 37 | TAILQ_REMOVE(&rlru->rlru_elms, rlrue, rlrue_link); 38 | free(rlrue); 39 | } 40 | 41 | 42 | void rd_lru_destroy (rd_lru_t *rlru) { 43 | rd_lru_elm_t *rlrue; 44 | 45 | while ((rlrue = TAILQ_FIRST(&rlru->rlru_elms))) 46 | rd_lru_elm_destroy(rlru, rlrue); 47 | 48 | free(rlru); 49 | } 50 | 51 | 52 | rd_lru_t *rd_lru_new (void) { 53 | rd_lru_t *rlru; 54 | 55 | rlru = calloc(1, sizeof(*rlru)); 56 | 57 | TAILQ_INIT(&rlru->rlru_elms); 58 | 59 | return rlru; 60 | } 61 | 62 | 63 | void rd_lru_push (rd_lru_t *rlru, void *ptr) { 64 | rd_lru_elm_t *rlrue; 65 | 66 | rlrue = calloc(1, sizeof(*rlrue)); 67 | rlrue->rlrue_ptr = ptr; 68 | 69 | TAILQ_INSERT_HEAD(&rlru->rlru_elms, rlrue, rlrue_link); 70 | rlru->rlru_cnt++; 71 | } 72 | 73 | 74 | void *rd_lru_pop (rd_lru_t *rlru) { 75 | rd_lru_elm_t *rlrue; 76 | void *ptr; 77 | 78 | if ((rlrue = TAILQ_LAST(&rlru->rlru_elms, rd_lru_elm_head))) { 79 | ptr = rlrue->rlrue_ptr; 80 | rd_lru_elm_destroy(rlru, rlrue); 81 | } else 82 | ptr = NULL; 83 | 84 | return ptr; 85 | } 86 | 87 | 88 | void *rd_lru_shift (rd_lru_t *rlru) { 89 | rd_lru_elm_t *rlrue; 90 | void *ptr; 91 | 92 | if ((rlrue = TAILQ_FIRST(&rlru->rlru_elms))) { 93 | ptr = rlrue->rlrue_ptr; 94 | rd_lru_elm_destroy(rlru, rlrue); 95 | } else 96 | ptr = NULL; 97 | 98 | return ptr; 99 | } 100 | -------------------------------------------------------------------------------- /rdtime.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | 32 | #ifndef TIMEVAL_TO_TIMESPEC 33 | #define TIMEVAL_TO_TIMESPEC(tv,ts) do { \ 34 | (ts)->tv_sec = (tv)->tv_sec; \ 35 | (ts)->tv_nsec = (tv)->tv_usec * 1000; \ 36 | } while (0) 37 | 38 | #define TIMESPEC_TO_TIMEVAL(tv, ts) do { \ 39 | (tv)->tv_sec = (ts)->tv_sec; \ 40 | (tv)->tv_usec = (ts)->tv_nsec / 1000; \ 41 | } while (0) 42 | #endif 43 | 44 | #define TIMESPEC_TO_TS(ts) \ 45 | (((rd_ts_t)(ts)->tv_sec * 1000000LLU) + ((ts)->tv_nsec / 1000)) 46 | 47 | #define TS_TO_TIMESPEC(ts,tsx) do { \ 48 | (ts)->tv_sec = (tsx) / 1000000; \ 49 | (ts)->tv_nsec = ((tsx) % 1000000) * 1000; \ 50 | if ((ts)->tv_nsec >= 1000000000LLU) { \ 51 | (ts)->tv_sec++; \ 52 | (ts)->tv_nsec -= 1000000000LLU; \ 53 | } \ 54 | } while (0) 55 | 56 | #define TIMESPEC_CLEAR(ts) ((ts)->tv_sec = (ts)->tv_nsec = 0LLU) 57 | 58 | 59 | static inline rd_ts_t rd_clock (void) RD_UNUSED; 60 | static inline rd_ts_t rd_clock (void) { 61 | #ifdef __APPLE__ 62 | /* No monotonic clock on Darwin */ 63 | struct timeval tv; 64 | gettimeofday(&tv, NULL); 65 | TIMEVAL_TO_TIMESPEC(&tv, &ts); 66 | return ((rd_ts_t)tv.tv_sec * 1000000LLU) + (rd_ts_t)tv.tv_usec; 67 | #else 68 | struct timespec ts; 69 | clock_gettime(CLOCK_MONOTONIC, &ts); 70 | return ((rd_ts_t)ts.tv_sec * 1000000LLU) + 71 | ((rd_ts_t)ts.tv_nsec / 1000LLU); 72 | #endif 73 | } 74 | 75 | 76 | 77 | /** 78 | * Thread-safe version of ctime() that strips the trailing newline. 79 | */ 80 | static inline const char *rd_ctime (const time_t *t) RD_UNUSED; 81 | static inline const char *rd_ctime (const time_t *t) { 82 | static __thread char ret[27]; 83 | 84 | ctime_r(t, ret); 85 | 86 | ret[25] = '\0'; 87 | 88 | return ret; 89 | } 90 | -------------------------------------------------------------------------------- /rdalert.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdsysqueue.h" 31 | #include "rdthread.h" 32 | #include "rdalert.h" 33 | #include "rdlog.h" 34 | #include 35 | 36 | struct rd_alert_cb { 37 | TAILQ_ENTRY(rd_alert_cb) link; 38 | rd_alert_type_t type; 39 | void (*callback) (rd_alert_type_t type, int level, 40 | const char *reason, void *opaque, va_list ap); 41 | void *opaque; 42 | }; 43 | 44 | static TAILQ_HEAD(, rd_alert_cb) rd_alert_cbs = 45 | TAILQ_HEAD_INITIALIZER(rd_alert_cbs); 46 | static rd_mutex_t rd_alert_lock; 47 | 48 | static const char *rd_alert_names[] = { 49 | "THREAD_STALL" 50 | }; 51 | 52 | void rd_alert0 (const char *file, const char *func, int line, 53 | rd_alert_type_t type, int level, const char *reason, ...) { 54 | va_list ap; 55 | struct rd_alert_cb *rac; 56 | 57 | rdbg("%%%i: %s ALERT at %s:%i:%s: %s", 58 | level, rd_alert_names[type], file, line, func, reason); 59 | 60 | rd_mutex_lock(&rd_alert_lock); 61 | va_start(ap, reason); 62 | TAILQ_FOREACH(rac, &rd_alert_cbs, link) { 63 | if (rac->type == type || rac->type == RD_ALERT_ALL) { 64 | va_list ap2; 65 | va_copy(ap2, ap); 66 | rac->callback(type, level, reason, rac->opaque, ap2); 67 | } 68 | } 69 | va_end(ap); 70 | rd_mutex_unlock(&rd_alert_lock); 71 | } 72 | 73 | 74 | 75 | void rd_alert_register (rd_alert_type_t type, 76 | void (*callback) (rd_alert_type_t type, int level, 77 | const char *reason, void *opaque, 78 | va_list ap), 79 | void *opaque) { 80 | struct rd_alert_cb *rac; 81 | 82 | rac = calloc(1, sizeof(*rac)); 83 | rac->type = type; 84 | rac->callback = callback; 85 | rac->opaque = opaque; 86 | 87 | rd_mutex_lock(&rd_alert_lock); 88 | TAILQ_INSERT_TAIL(&rd_alert_cbs, rac, link); 89 | rd_mutex_unlock(&rd_alert_lock); 90 | } 91 | 92 | -------------------------------------------------------------------------------- /rdcrc32.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file rdcrc32.h 3 | * Functions and types for CRC checks. 4 | * 5 | * Generated on Tue May 8 17:36:59 2012, 6 | * by pycrc v0.7.10, http://www.tty1.net/pycrc/ 7 | * 8 | * NOTE: Contains librd modifications: 9 | * - rd_crc32() helper. 10 | * - __RDCRC32___H__ define (was missing the '32' part). 11 | * 12 | * using the configuration: 13 | * Width = 32 14 | * Poly = 0x04c11db7 15 | * XorIn = 0xffffffff 16 | * ReflectIn = True 17 | * XorOut = 0xffffffff 18 | * ReflectOut = True 19 | * Algorithm = table-driven 20 | *****************************************************************************/ 21 | #ifndef __RDCRC32___H__ 22 | #define __RDCRC32___H__ 23 | 24 | #include 25 | #include 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | 32 | /** 33 | * The definition of the used algorithm. 34 | *****************************************************************************/ 35 | #define CRC_ALGO_TABLE_DRIVEN 1 36 | 37 | 38 | /** 39 | * The type of the CRC values. 40 | * 41 | * This type must be big enough to contain at least 32 bits. 42 | *****************************************************************************/ 43 | typedef uint32_t rd_crc32_t; 44 | 45 | 46 | /** 47 | * Reflect all bits of a \a data word of \a data_len bytes. 48 | * 49 | * \param data The data word to be reflected. 50 | * \param data_len The width of \a data expressed in number of bits. 51 | * \return The reflected data. 52 | *****************************************************************************/ 53 | rd_crc32_t rd_crc32_reflect(rd_crc32_t data, size_t data_len); 54 | 55 | 56 | /** 57 | * Calculate the initial crc value. 58 | * 59 | * \return The initial crc value. 60 | *****************************************************************************/ 61 | static inline rd_crc32_t rd_crc32_init(void) 62 | { 63 | return 0xffffffff; 64 | } 65 | 66 | 67 | /** 68 | * Update the crc value with new data. 69 | * 70 | * \param crc The current crc value. 71 | * \param data Pointer to a buffer of \a data_len bytes. 72 | * \param data_len Number of bytes in the \a data buffer. 73 | * \return The updated crc value. 74 | *****************************************************************************/ 75 | rd_crc32_t rd_crc32_update(rd_crc32_t crc, const unsigned char *data, size_t data_len); 76 | 77 | 78 | /** 79 | * Calculate the final crc value. 80 | * 81 | * \param crc The current crc value. 82 | * \return The final crc value. 83 | *****************************************************************************/ 84 | static inline rd_crc32_t rd_crc32_finalize(rd_crc32_t crc) 85 | { 86 | return crc ^ 0xffffffff; 87 | } 88 | 89 | 90 | /** 91 | * Wrapper for performing CRC32 on the provided buffer. 92 | */ 93 | static inline rd_crc32_t rd_crc32 (const char *data, size_t data_len) { 94 | return rd_crc32_finalize(rd_crc32_update(rd_crc32_init(), 95 | (const unsigned char *)data, 96 | data_len)); 97 | } 98 | 99 | #ifdef __cplusplus 100 | } /* closing brace for extern "C" */ 101 | #endif 102 | 103 | #endif /* __RDCRC32___H__ */ 104 | -------------------------------------------------------------------------------- /rdenum2str.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # 4 | # librd - Rapid Development C library 5 | # 6 | # Copyright (c) 2012-2013, Magnus Edenhill 7 | # All rights reserved. 8 | # 9 | # Redistribution and use in source and binary forms, with or without 10 | # modification, are permitted provided that the following conditions are met: 11 | # 12 | # 1. Redistributions of source code must retain the above copyright notice, 13 | # this list of conditions and the following disclaimer. 14 | # 2. Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | # POSSIBILITY OF SUCH DAMAGE. 29 | #/ 30 | # 31 | 32 | 33 | 34 | # 35 | # Reads header file content from stdin and produces enum2str functions 36 | # for each found typedeffed enum. 37 | # 38 | # Usage: cat *.h | ./enum2str.pl > autoenum.h 39 | # 40 | # Followed by: 41 | # #include "autoenum.h" 42 | # 43 | 44 | 45 | my $anonid = 1; 46 | my $curr_enum = undef; 47 | 48 | foreach () { 49 | chomp; 50 | 51 | if (/^\s*(typedef)\s*enum\s*\{?/) { 52 | $curr_enum = ++$anonid; 53 | } elsif ($curr_enum && /^\s*\}\s*(\S+)?\s*\;/) { 54 | my $name; 55 | if ($1) { 56 | $enum{$curr_enum}->{origtype} = $1; 57 | $name = $1; 58 | $name =~ s/_t$//; 59 | $enum{$curr_enum}->{name} = $name; 60 | if (scalar @{ $enum{$curr_enum}->{items} } > 0) { 61 | push @good_enums, $curr_enum; 62 | } 63 | } 64 | $curr_enum = undef; 65 | 66 | } elsif ($curr_enum && /^\s*(\S+)\s*,/) { 67 | push @{ $enum{$curr_enum}->{items} }, $1; 68 | } 69 | } 70 | 71 | my $date = scalar localtime; 72 | print <{name}; 81 | my $origtype = $enum{$id}->{origtype}; 82 | next if (!$origtype); 83 | print <{items} }) { 93 | print " [$e] = \"$e\",\n"; 94 | } 95 | 96 | print < avg3 + maxdev3) { 75 | printf("rd_array_shuffle biastest failed: " 76 | "combo %i misrepresented/biased: " 77 | "%i (outside +-%i from average %i)\n", 78 | stats3map[i], stats3[stats3map[i]], 79 | maxdev3, avg3); 80 | fails++; 81 | } 82 | } 83 | } 84 | 85 | 86 | return fails; 87 | } 88 | 89 | 90 | 91 | int main (int argc, char **argv) { 92 | int fails = 0; 93 | 94 | srand(rd_clock()); 95 | fails += test_shuffle(); 96 | 97 | return fails ? 1 : 0; 98 | 99 | } 100 | -------------------------------------------------------------------------------- /rdfile.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdfile.h" 31 | 32 | 33 | const char *rd_basename (const char *path) { 34 | const char *t = path; 35 | const char *t2 = t; 36 | 37 | while ((t = strchr(t, '/'))) 38 | t2 = ++t; 39 | 40 | return t2; 41 | } 42 | 43 | 44 | const char *rd_pwd (void) { 45 | static __thread char path[PATH_MAX]; 46 | 47 | if (!getcwd(path, sizeof(path)-1)) 48 | return NULL; 49 | 50 | return path; 51 | } 52 | 53 | 54 | ssize_t rd_file_size (const char *path) { 55 | struct stat st; 56 | 57 | if (stat(path, &st) == -1) 58 | return (ssize_t)-1; 59 | 60 | return st.st_size; 61 | } 62 | 63 | ssize_t rd_file_size_fd (int fd) { 64 | struct stat st; 65 | 66 | if (fstat(fd, &st) == -1) 67 | return (ssize_t)-1; 68 | 69 | return st.st_size; 70 | } 71 | 72 | 73 | mode_t rd_file_mode (const char *path) { 74 | struct stat st; 75 | 76 | if (stat(path, &st) == -1) 77 | return 0; 78 | 79 | return st.st_mode; 80 | } 81 | 82 | 83 | char *rd_file_read (const char *path, int *lenp) { 84 | char *buf; 85 | int fd; 86 | ssize_t size; 87 | int r; 88 | 89 | if ((fd = open(path, O_RDONLY)) == -1) 90 | return NULL; 91 | 92 | if ((size = rd_file_size_fd(fd)) == -1) { 93 | close(fd); 94 | return NULL; 95 | } 96 | 97 | if (!(buf = malloc(size+1))) { 98 | close(fd); 99 | return NULL; 100 | } 101 | 102 | if ((r = read(fd, buf, size)) == -1) { 103 | close(fd); 104 | free(buf); 105 | return NULL; 106 | } 107 | 108 | close(fd); 109 | 110 | buf[r] = '\0'; 111 | 112 | if (lenp) 113 | *lenp = r; 114 | 115 | return buf; 116 | } 117 | 118 | 119 | 120 | int rd_file_write (const char *path, const char *buf, int len, 121 | int flags, mode_t mode) { 122 | int fd; 123 | int r; 124 | int of = 0; 125 | 126 | if ((fd = open(path, O_CREAT|O_WRONLY|flags, mode)) == -1) 127 | return -1; 128 | 129 | while (of < len) { 130 | if ((r = write(fd, buf+of, RD_MIN(16384, len - of))) == -1) { 131 | close(fd); 132 | return -1; 133 | } 134 | 135 | of += r; 136 | } 137 | 138 | close(fd); 139 | 140 | return 0; 141 | } 142 | -------------------------------------------------------------------------------- /rd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | 30 | 31 | #pragma once 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include "rdtypes.h" 46 | 47 | 48 | #ifndef likely 49 | #define likely(x) __builtin_expect((x),1) 50 | #endif 51 | #ifndef unlikely 52 | #define unlikely(x) __builtin_expect((x),0) 53 | #endif 54 | 55 | #define RD_UNUSED __attribute__((unused)) 56 | #define RD_PACKED __attribute__((packed)) 57 | 58 | #define RD_ARRAY_SIZE(A) (sizeof((A)) / sizeof(*(A))) 59 | #define RD_ARRAYSIZE(A) RD_ARRAY_SIZE(A) 60 | #define RD_SIZEOF(TYPE,MEMBER) sizeof(((TYPE *)NULL)->MEMBER) 61 | #define RD_OFFSETOF(TYPE,MEMBER) ((size_t) &(((TYPE *)NULL)->MEMBER)) 62 | 63 | /** 64 | * Returns the 'I'th array element from static sized array 'A' 65 | * or NULL if 'I' is out of range. 66 | * 'PFX' is an optional prefix to provide the correct return type. 67 | */ 68 | #define RD_ARRAY_ELEM(A,I,PFX...) \ 69 | ((unsigned int)(I) < RD_ARRAY_SIZE(A) ? PFX (A)[(I)] : NULL) 70 | 71 | 72 | #define RD_STRINGIFY(X) # X 73 | 74 | 75 | 76 | #define RD_MIN(a,b) ((a) < (b) ? (a) : (b)) 77 | #define RD_MAX(a,b) ((a) > (b) ? (a) : (b)) 78 | 79 | 80 | /** 81 | * Cap an integer (of any type) to reside within the defined limit. 82 | */ 83 | #define RD_INT_CAP(val,low,hi) \ 84 | ((val) < (low) ? low : ((val) > (hi) ? (hi) : (val))) 85 | 86 | 87 | #define rd_atomic_add(PTR,VAL) __sync_add_and_fetch(PTR,VAL) 88 | #define rd_atomic_sub(PTR,VAL) __sync_sub_and_fetch(PTR,VAL) 89 | 90 | #define rd_atomic_add_prev(PTR,VAL) __sync_fetch_and_add(PTR,VAL) 91 | #define rd_atomic_sub_prev(PTR,VAL) __sync_fetch_and_sub(PTR,VAL) 92 | 93 | 94 | 95 | #ifndef be64toh 96 | #include 97 | 98 | #if __BYTE_ORDER == __BIG_ENDIAN 99 | #define be64toh(x) (x) 100 | #else 101 | # if __BYTE_ORDER == __LITTLE_ENDIAN 102 | #define be64toh(x) bswap_64(x) 103 | # endif 104 | #endif 105 | 106 | #define htobe64(x) be64toh(x) 107 | #endif 108 | 109 | 110 | void rd_init (void); 111 | -------------------------------------------------------------------------------- /rdevent.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include "rdthread.h" 32 | 33 | 34 | 35 | #define rd_thread_event_f(F) void (F) (void *ptr) 36 | 37 | typedef struct rd_thread_event_s { 38 | rd_thread_event_f(*rte_callback); 39 | void *rte_ptr; 40 | } rd_thread_event_t; 41 | 42 | 43 | 44 | /** 45 | * Enqueue event (callback call) on thread 'rdt'. 46 | * Requires 'rdt' to call rd_thread_dispatch(). 47 | */ 48 | static void rd_thread_event_add (rd_thread_t *rdt, 49 | rd_thread_event_f(*callback), 50 | void *ptr) RD_UNUSED; 51 | 52 | static void rd_thread_event_add (rd_thread_t *rdt, 53 | rd_thread_event_f(*callback), 54 | void *ptr) { 55 | rd_thread_event_t *rte = malloc(sizeof(*rte)); 56 | 57 | rte->rte_callback = callback; 58 | rte->rte_ptr = ptr; 59 | 60 | rd_fifoq_add(&rdt->rdt_eventq, rte); 61 | } 62 | 63 | 64 | /** 65 | * Convenience function to enqueue a call to function 'cb' on thread 'rdt'. 66 | * Depending on the value of 'argcnt' (0..4) 'cb' may be one of: 67 | * 68 | * argcnt | prototype 69 | * -------+-------------------------------------------------------------- 70 | * 0 | void (*cb) (void) 71 | * 1 | void (*cb) (void *arg1) 72 | * 2 | void (*cb) (void *arg1, void *arg2) 73 | * 3 | void (*cb) (void *arg1, void *arg2, void *arg3) 74 | * 4 | void (*cb) (void *arg1, void *arg2, void *arg3, void *arg4) 75 | */ 76 | void rd_thread_func_call (rd_thread_t *rdt, void *cb, int argcnt, void **args); 77 | #define rd_thread_func_call0(rdt,cb) \ 78 | rd_thread_func_call(rdt,cb,0,NULL) 79 | #define rd_thread_func_call1(rdt,cb,arg1) \ 80 | rd_thread_func_call(rdt, cb, 1, ((void *[]){ arg1 })) 81 | #define rd_thread_func_call2(rdt,cb,arg1,arg2) \ 82 | rd_thread_func_call(rdt, cb, 2, ((void *[]){ arg1, arg2 })) 83 | #define rd_thread_func_call3(rdt,cb,arg1,arg2,arg3) \ 84 | rd_thread_func_call(rdt, cb, 3, ((void *[]){ arg1, arg2, arg3 })) 85 | #define rd_thread_func_call4(rdt,cb,arg1,arg2,arg3,arg4) \ 86 | rd_thread_func_call(rdt, cb, 4, ((void *[]){ arg1, arg2, arg3, arg4 })) 87 | 88 | /** 89 | * Calls the callback and destroys the event. 90 | */ 91 | static void rd_thread_event_call (rd_thread_event_t *rte) RD_UNUSED; 92 | static void rd_thread_event_call (rd_thread_event_t *rte) { 93 | 94 | rte->rte_callback(rte->rte_ptr); 95 | 96 | free(rte); 97 | } 98 | -------------------------------------------------------------------------------- /rdgz.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdgz.h" 31 | #include "rdlog.h" 32 | 33 | #include 34 | 35 | 36 | #define RD_GZ_CHUNK 262144 37 | 38 | void *rd_gz_decompress (void *compressed, int compressed_len, 39 | uint64_t *decompressed_lenp) { 40 | int pass = 1; 41 | char *decompressed = NULL; 42 | 43 | /* First pass (1): calculate decompressed size. 44 | * (pass-1 is skipped if *decompressed_lenp is 45 | * non-zero). 46 | * Second pass (2): perform actual decompression. 47 | */ 48 | 49 | if (*decompressed_lenp != 0LLU) 50 | pass++; 51 | 52 | for (; pass <= 2 ; pass++) { 53 | z_stream strm = {}; 54 | gz_header hdr; 55 | char buf[512]; 56 | char *p; 57 | int len; 58 | int r; 59 | 60 | if ((r = inflateInit2(&strm, 15+32)) != Z_OK) 61 | goto fail; 62 | 63 | strm.next_in = compressed; 64 | strm.avail_in = compressed_len; 65 | 66 | if ((r = inflateGetHeader(&strm, &hdr)) != Z_OK) { 67 | inflateEnd(&strm); 68 | goto fail; 69 | } 70 | 71 | if (pass == 1) { 72 | /* Use dummy output buffer */ 73 | p = buf; 74 | len = sizeof(buf); 75 | } else { 76 | /* Use real output buffer */ 77 | p = decompressed; 78 | len = *decompressed_lenp; 79 | } 80 | 81 | do { 82 | strm.next_out = (unsigned char *)p; 83 | strm.avail_out = len; 84 | 85 | r = inflate(&strm, Z_NO_FLUSH); 86 | switch (r) { 87 | case Z_STREAM_ERROR: 88 | case Z_NEED_DICT: 89 | case Z_DATA_ERROR: 90 | case Z_MEM_ERROR: 91 | inflateEnd(&strm); 92 | goto fail; 93 | } 94 | 95 | p += len - strm.avail_out; 96 | len -= len - strm.avail_out; 97 | 98 | } while (strm.avail_out == 0 && r != Z_STREAM_END); 99 | 100 | 101 | if (pass == 1) { 102 | *decompressed_lenp = strm.total_out; 103 | if (!(decompressed = malloc(*decompressed_lenp+1))) { 104 | inflateEnd(&strm); 105 | return NULL; 106 | } 107 | /* For convenience of the caller we nul-terminate 108 | * the buffer. If it happens to be a string there 109 | * is no need for extra copies. */ 110 | decompressed[*decompressed_lenp] = '\0'; 111 | } 112 | 113 | inflateEnd(&strm); 114 | } 115 | 116 | return decompressed; 117 | 118 | fail: 119 | if (decompressed) 120 | free(decompressed); 121 | return NULL; 122 | } 123 | -------------------------------------------------------------------------------- /rdbits.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdbits.h" 31 | 32 | /** 33 | * FIXME: support for other bitvec types than static, 34 | * a dynamicly growable and shrinkable would be nice, 35 | * and a sparse one for larger spans. 36 | */ 37 | 38 | void rd_bitvec_free (rd_bitvec_t *rbv) { 39 | free(rbv->rbv_b); 40 | } 41 | 42 | void rd_bitvec_init (rd_bitvec_t *rbv, rd_bitvec_type_t type, 43 | uint64_t max_val) { 44 | 45 | assert(type == RD_BITVEC_STATIC); 46 | 47 | memset(rbv, 0, sizeof(*rbv)); 48 | 49 | rbv->rbv_max = max_val; 50 | 51 | /* FIXME: Proper tree-algo for larger maxes */ 52 | assert(rbv->rbv_max <= 4096); 53 | rbv->rbv_buckets = 1 + (rbv->rbv_max / (8 * sizeof(*rbv->rbv_b))); 54 | rbv->rbv_b = calloc(rbv->rbv_buckets, sizeof(*rbv->rbv_b)); 55 | } 56 | 57 | int rd_bitvec_op (rd_bitvec_t *rbv, uint64_t i, rd_bitvec_op_t op) { 58 | int bucket; 59 | int bit; 60 | 61 | if (i > rbv->rbv_max) { 62 | if (op == RD_BITVEC_OP_TEST) 63 | return 0; 64 | 65 | errno = ERANGE; 66 | return -1; 67 | } 68 | 69 | bucket = i / (8 * sizeof(*rbv->rbv_b)); 70 | bit = 1 << (i % (8 * sizeof(*rbv->rbv_b))); 71 | 72 | switch (op) 73 | { 74 | case RD_BITVEC_OP_SET: 75 | rbv->rbv_b[bucket] |= bit; 76 | break; 77 | case RD_BITVEC_OP_RESET: 78 | rbv->rbv_b[bucket] &= ~bit; 79 | break; 80 | case RD_BITVEC_OP_TEST: 81 | return rbv->rbv_b[bucket] & bit; 82 | default: 83 | errno = EINVAL; 84 | return -1; 85 | } 86 | 87 | return 0; 88 | } 89 | 90 | /** 91 | * rd_bitvec_ffs() and rd_bitvec_fls() returns the bit number 92 | * according to ffs(3). 93 | */ 94 | uint64_t rd_bitvec_fxs (const rd_bitvec_t *rbv, rd_bitvec_op_t op) { 95 | int bucket = 0; 96 | uint32_t bit = 0; 97 | 98 | if (op == RD_BITVEC_OP_FFS) { 99 | for (bucket = 0 ; bucket < rbv->rbv_buckets ; bucket++) 100 | if (rbv->rbv_b[bucket] && 101 | (bit = ffs(rbv->rbv_b[bucket]))) 102 | break; 103 | 104 | } else if (op == RD_BITVEC_OP_FLS) { 105 | for (bucket = rbv->rbv_buckets - 1 ; bucket >= 0 ; bucket--) { 106 | if (rbv->rbv_b[bucket] && 107 | (bit = __builtin_clz(rbv->rbv_b[bucket]))) { 108 | bit = (8 * sizeof(*rbv->rbv_b)) - bit; 109 | break; 110 | } 111 | } 112 | 113 | 114 | } else { 115 | assert(!*"unknown RD_BITVEC_OP_.."); 116 | } 117 | 118 | return (uint64_t)bit + (uint64_t)(bucket * (8 * sizeof(*rbv->rbv_b))); 119 | } 120 | -------------------------------------------------------------------------------- /rdencoding.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | #pragma once 29 | 30 | 31 | #include 32 | #include 33 | 34 | /** 35 | * Various encoding/decoding schemes. 36 | */ 37 | 38 | 39 | 40 | /** 41 | * 42 | * Varint decoding & encoding 43 | * 44 | * https://developers.google.com/protocol-buffers/docs/encoding#varints 45 | * 46 | */ 47 | 48 | #define RD_VARINT_DECODE_ERR(vlen) ((vlen) <= 0) 49 | #define RD_VARINT_DECODE_OVERFLOW(vlen) ((vlen) <= -9) 50 | #define RD_VARINT_DECODE_UNDERFLOW(vlen) (-(vlen)) 51 | 52 | /** 53 | * Decode a variant at 'buf' (buffer is of size 'len') and return 54 | * it as a uint64. The read length is stored in '*vlenp'. 55 | * If '*vlenp' is < -9 the varint would overflow. 56 | * If '*vlenp' is <= 0 > -9 the varint could not be decoded due to 57 | * buffer shortage. 58 | */ 59 | uint64_t rd_varint_decode_u64 (const void *buf, size_t size, int *vlenp); 60 | 61 | /** 62 | * Same as rd_varint_decode_u64 but returns a signed int64 instead. 63 | */ 64 | int64_t rd_varint_decode_s64 (const void *buf, size_t size, int *vlenp); 65 | 66 | 67 | /** 68 | * Encodes a uint64 as a varint in destination buffer 'dest'. 69 | * Returns the number of written bytes on success or -1 on buffer shortage. 70 | */ 71 | int rd_varint_encode_u64 (uint64_t uval, void *dest, size_t size); 72 | 73 | /** 74 | * Same as rd_varint_encode_u64() but for signed int64 instead. 75 | */ 76 | int rd_varint_encode_s64 (int64_t val, void *dest, size_t size); 77 | 78 | 79 | 80 | 81 | /** 82 | * Decode hex string 'hexstr' into binary data stored in 'dst'. 83 | * 'dst' should be sized at least 'inlen'/2. 84 | * 85 | * If 'inlen' is -1 the 'hexstr' is scanned until '\0' else until 'inlen' 86 | * bytes have been scanned. 87 | * 88 | * The following characters are ignored in 'hexstr': 89 | * ' ', '\', '.', ':' 90 | * Any hex characters (0-9a-fA-F) are decoded, 91 | * while any other characters causes the decoding to stop. 92 | * 93 | * Returns the number of bytes written to 'dst'. 94 | */ 95 | int rd_hex2bin (const char *hexstr, int inlen, char *dst, int dstlen); 96 | 97 | 98 | /** 99 | * Encode binary buffer 'bin' of 'inline' bytes as hex and store it in 'dst'. 100 | * 'dst' should be sized at least 'inline'*2+1. 101 | * 102 | * 'dst' will be nul-terminated. 103 | * 104 | * Returns the number of characters written to 'dst', excluding the 105 | * trailing '\0'. 106 | */ 107 | int rd_bin2hex (const char *bin, int inlen, char *dst, int dstlen); 108 | -------------------------------------------------------------------------------- /rdunits.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdunits.h" 31 | 32 | 33 | /** 34 | * Returns a thread-local temporary usable string comprising 35 | * the abbreviated string representation of an integer number. 36 | * Either according to the SI units (where kilo means 1000) when 37 | * si=1, or by the IEC units (where kilo means 1024) when si=0. 38 | * An optional unitsuffix may be specified, e.g., "B" for bytes. 39 | * 40 | * Abbreviated numbers will be shown at a precision of 2 decimals. 41 | * 42 | * Thread-safe. 43 | */ 44 | const char *rd_size2str (uint64_t size, int si, const char *unitsuffix) { 45 | static __thread char ret[16][40]; 46 | static __thread int reti = 0; 47 | static const struct { 48 | char *suffix; 49 | uint64_t val; 50 | } sizes[2][6] = 51 | { 52 | [0] = { /* IEC units (i.e., 2^20 for MiB) */ 53 | { "Pi", RD_SIZE_PIB(1) }, 54 | { "Ti", RD_SIZE_TIB(1) }, 55 | { "Gi", RD_SIZE_GIB(1) }, 56 | { "Mi", RD_SIZE_MIB(1) }, 57 | { "Ki", RD_SIZE_KIB(1) }, 58 | { "", 0 }, 59 | }, 60 | [1] = { /* SI units (i.e., 10^6 for MB) */ 61 | { "P", 1000000000000000LLU }, 62 | { "T", 1000000000000LLU }, 63 | { "G", 1000000000LLU }, 64 | { "M", 1000000LLU }, 65 | { "K", 1000LLU }, 66 | { "", 0 }, 67 | }, 68 | }; 69 | uint64_t sub; 70 | int i = -1; 71 | 72 | reti = (reti + 1) % 16; 73 | 74 | if (size == 0LLU) { 75 | /* Quick case for zero. */ 76 | snprintf(ret[reti], sizeof(ret[reti]) 77 | , "0%s", unitsuffix ? : ""); 78 | return ret[reti]; 79 | } 80 | 81 | 82 | si = !!si; 83 | 84 | /* Find proper size */ 85 | while (sizes[si][++i].val > size) 86 | ; 87 | 88 | /* Display according to size-abbreviation and precision */ 89 | if (size < sizes[si][i].val || sizes[si][i].val == 0) 90 | snprintf(ret[reti], sizeof(ret[reti]), 91 | "%" PRIu64 "%s%s", 92 | size, 93 | sizes[si][i].suffix, unitsuffix ? : ""); 94 | else if (!(sub = size % sizes[si][i].val) || 95 | (float)sub / (float)sizes[si][i].val < 0.01) 96 | snprintf(ret[reti], sizeof(ret[reti]), 97 | "%" PRIu64 "%s%s", 98 | sizes[si][i].val ? size / sizes[si][i].val : size, 99 | sizes[si][i].suffix, unitsuffix ? : ""); 100 | 101 | else 102 | snprintf(ret[reti], sizeof(ret[reti]), 103 | "%.2f%s%s", 104 | (double)size / (double)sizes[si][i].val, 105 | sizes[si][i].suffix, unitsuffix ? : ""); 106 | 107 | return ret[reti]; 108 | } 109 | 110 | 111 | -------------------------------------------------------------------------------- /tests/0008-buf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdbuf.h" 31 | #include "rdlog.h" 32 | 33 | static int test_bufs (void) { 34 | rd_bufh_t *rbh; 35 | struct { 36 | int len; 37 | char *data; 38 | } bufs[] = { 39 | { 16, "ABCDEFGHIJKLMNOP" }, 40 | { 4, "\n\ta\n" }, 41 | { 5, "bye\n\0" }, 42 | { 0, NULL }, 43 | }; 44 | int i; 45 | int totlen = 0; 46 | int fails = 0; 47 | char buf2[256]; 48 | char *out; 49 | 50 | rbh = rd_bufh_new(NULL, 0); 51 | 52 | bufs[3].len = 512; 53 | bufs[3].data = alloca(bufs[3].len); 54 | for (i = 0 ; i < bufs[3].len ; i++) 55 | bufs[3].data[i] = i % 256; 56 | 57 | for (i = 0 ; i < RD_ARRAY_SIZE(bufs) ; i++) { 58 | totlen += bufs[i].len; 59 | rd_bufh_append(rbh, bufs[i].data, bufs[i].len, 0); 60 | } 61 | 62 | if (rd_bufh_len(rbh) != totlen) { 63 | printf("%s:%i: bufh length %i should be %i\n", 64 | __FUNCTION__,__LINE__, rd_bufh_len(rbh), totlen); 65 | fails++; 66 | } 67 | 68 | rd_bufh_sprintf(rbh, "Hi there %s, you are #%i", "Mike", 8); 69 | 70 | out = alloca(rd_bufh_len(rbh)+1); 71 | out[rd_bufh_len(rbh)] = '\0'; 72 | rd_bufh_copyout(rbh, out); 73 | 74 | /* We inserted a null-character in the bye-string, thats why 75 | * we only match the beginning of the buffer. */ 76 | if (strcmp(out, "ABCDEFGHIJKLMNOP\n\ta\nbye\n")) { 77 | printf("%s:%i: unexpected serialize#1 result: \"%s\"\n", 78 | __FUNCTION__,__LINE__, out); 79 | fails++; 80 | } 81 | 82 | rd_bufh_destroy(rbh); 83 | 84 | 85 | /* 86 | * Try small writes. 87 | */ 88 | rbh = rd_bufh_new(NULL, 0); 89 | for (i = 0 ; i < sizeof(buf2) ; i++) { 90 | buf2[i] = i % 256; 91 | rd_bufh_append(rbh, &buf2[i], 1, 0); 92 | } 93 | 94 | if (rd_bufh_len(rbh) != sizeof(buf2)) { 95 | printf("%s:%i: unexpected length for buf2: %i, should be %i\n", 96 | __FUNCTION__,__LINE__, rd_bufh_len(rbh), 97 | (int)sizeof(buf2)); 98 | fails++; 99 | } 100 | 101 | out = alloca(rd_bufh_len(rbh)); 102 | rd_bufh_copyout(rbh, out); 103 | 104 | if (memcmp(out, buf2, sizeof(buf2))) { 105 | printf("%s:%i: unexpected serialize buf2 result:\n", 106 | __FUNCTION__,__LINE__); 107 | rd_hexdump(stdout, "serialized", out, rd_bufh_len(rbh)); 108 | rd_hexdump(stdout, "buf2", buf2, sizeof(buf2)); 109 | fails++; 110 | } 111 | 112 | rd_bufh_destroy(rbh); 113 | 114 | return fails; 115 | } 116 | 117 | 118 | 119 | 120 | int main (int argc, char **argv) { 121 | int fails = 0; 122 | 123 | rd_dbg_set(1); 124 | 125 | fails += test_bufs(); 126 | 127 | return fails ? 1 : 0; 128 | } 129 | -------------------------------------------------------------------------------- /rdqueue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include "rd.h" 32 | #include "rdtypes.h" 33 | #include "rdsysqueue.h" 34 | 35 | 36 | 37 | 38 | /** 39 | * Thread-safe FIFO queues. 40 | * Typical usage is for work-queues (see tests/0001-fifoq.c for an example) 41 | * 42 | * 43 | * It is up the object code to properly lock the object itself. 44 | * 45 | * 46 | * Usage: 47 | * 48 | * Caller thread: 49 | * -- Add to fifoq: 50 | * rd_fifoq_add(&my_fifoq, myobj); 51 | * 52 | * In worker thread: 53 | * -- Dequeue and process: 54 | * while (1) { 55 | * rfqe = rd_fifoq_pop_wait(&my_fifoq); 56 | * myobj = rfqe->ptr; 57 | * perform_work(myobj); 58 | * rd_fifoq_elm_release(rfqe); 59 | * } 60 | */ 61 | 62 | typedef struct rd_fifoq_elm_s { 63 | TAILQ_ENTRY(rd_fifoq_elm_s) rfqe_link; 64 | int rfqe_refcnt; 65 | void *rfqe_ptr; 66 | } rd_fifoq_elm_t; 67 | 68 | 69 | TAILQ_HEAD(rd_fifoq_elm_head_s, rd_fifoq_elm_s); 70 | 71 | typedef struct rd_fifoq_s { 72 | TAILQ_HEAD(, rd_fifoq_elm_s) rfq_q; 73 | rd_mutex_t rfq_lock; 74 | rd_cond_t rfq_cond; 75 | int rfq_cnt; 76 | int rfq_max_size; 77 | int rfq_taildrop; 78 | int rfq_inited; 79 | } rd_fifoq_t; 80 | 81 | void rd_fifoq_destroy (rd_fifoq_t *rfg); 82 | rd_fifoq_t *rd_fifoq_init (rd_fifoq_t *rfq); 83 | 84 | #define RD_FIFOQ_INITIALIZER(rfq) \ 85 | { \ 86 | .rfq_q = TAILQ_HEAD_INITIALIZER((rfq).rfq_q), \ 87 | .rfq_lock = RD_MUTEX_INITIALIZER, \ 88 | .rfq_cond = RD_COND_INITIALIZER, \ 89 | .rfq_inited = 1 \ 90 | } 91 | 92 | 93 | void rd_fifoq_set_max_size (rd_fifoq_t *rfq, int max_size, int taildrop); 94 | 95 | void rd_fifoq_add0 (rd_fifoq_t *rfq, void *ptr, void **ptr_purged); 96 | #define rd_fifoq_add(rfq,ptr) rd_fifoq_add0(rfq,ptr,NULL) 97 | #define rd_fifoq_add_purge(rfq,ptr,ptr_purged) \ 98 | rd_fifoq_add0(rfq,ptr,(void **)ptr_purged) 99 | 100 | rd_fifoq_elm_t *rd_fifoq_pop0 (rd_fifoq_t *rfq, int no_wait, int timeout_ms); 101 | #define rd_fifoq_pop_wait(rfq) rd_fifoq_pop0(rfq, 0, 0) 102 | #define rd_fifoq_pop_timedwait(rfq,tmo) rd_fifoq_pop0(rfq, 0, tmo) 103 | #define rd_fifoq_pop(rfq) rd_fifoq_pop0(rfq, 1, 0) 104 | 105 | static inline void rd_fifoq_elm_release0 (rd_fifoq_t *rfq, 106 | rd_fifoq_elm_t *rfqe) { 107 | (void)rfq; 108 | if (rd_atomic_sub(&rfqe->rfqe_refcnt, 1) > 0) 109 | return; 110 | 111 | free(rfqe); 112 | } 113 | 114 | #define rd_fifoq_elm_release(RFQ,RFQE) do { \ 115 | rd_mutex_lock(&(RFQ)->rfq_lock); \ 116 | rd_fifoq_elm_release0(RFQ, RFQE); \ 117 | rd_mutex_unlock(&(RFQ)->rfq_lock); \ 118 | } while (0) 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /rdavg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | 32 | /** 33 | * NOTE: THIS IS WORK IN PROGRESS 34 | **/ 35 | 36 | #include "rdsysqueue.h" 37 | 38 | typedef enum { 39 | RD_AVG_RATE, /* x/time-interval rate */ 40 | RD_AVG_HIST, /* fixed-bucket histogram */ 41 | 42 | } rd_avg_type_t; 43 | 44 | #define RD_AVG_NO_VALUE 0xffffffffffffffff 45 | 46 | /* Result struct */ 47 | typedef struct rd_avg_res_s { 48 | double dbl; 49 | uint64_t sum; 50 | uint64_t high; 51 | uint64_t low; 52 | } rd_avg_res_t; 53 | 54 | typedef struct rd_avg_rate_s { 55 | uint64_t cnt; 56 | } rd_avg_rate_t; 57 | 58 | typedef struct rd_avg_hist_s { 59 | uint64_t *bucket; 60 | } rd_avg_hist_t; 61 | 62 | typedef struct rd_avg_period_s { 63 | rd_ts_t last; /* last data point */ 64 | rd_ts_t duration; 65 | rd_ts_t closed; 66 | int missed; 67 | union { 68 | rd_avg_rate_t rate; 69 | rd_avg_hist_t hist; 70 | } u; 71 | rd_avg_res_t res; 72 | } rd_avg_period_t; 73 | 74 | typedef struct rd_avg_s { 75 | TAILQ_ENTRY(rd_avg_s) ra_link; 76 | 77 | rd_avg_type_t ra_type; 78 | rd_avg_period_t *ra_curr; /* current period */ 79 | int ra_periods; /* current + previous periods */ 80 | rd_avg_period_t *ra_period; 81 | int ra_curri; /* current period index */ 82 | 83 | int ra_duration; /* config: period duration */ 84 | 85 | rd_ts_t ra_start; /* start time of current period */ 86 | rd_ts_t ra_end; /* future stop time of current period*/ 87 | 88 | /* Type-specific configuration */ 89 | union { 90 | struct { 91 | int interval; 92 | } rate; 93 | struct { 94 | int buckets; 95 | int (*val2bucket) (struct rd_avg_s *ra, 96 | uint64_t val, int buckets); 97 | } hist; 98 | } ra_u; 99 | 100 | struct rd_avg_s *ra_parent; 101 | 102 | void (*ra_roll_cb) (struct rd_avg_s *ra, int period, void *opaque); 103 | void *ra_opaque; 104 | } rd_avg_t; 105 | 106 | 107 | /** 108 | * Optional application callback that is called whenever a period 109 | * is rolled over and a new period is started. 110 | * 'period' argument is the index of the rolled period. 111 | */ 112 | #define rd_avg_roll_callback_set(ra,cb) ((ra)->ra_roll_cb) = (cb) 113 | 114 | 115 | /** 116 | * Sets opaque provided in avg callbacks. 117 | */ 118 | #define rd_avg_opaque_set(ra,cb) ((ra)->ra_opaque) = (opaque) 119 | 120 | 121 | #define RD_AVG_CURR -1 /* current period */ 122 | #define RD_AVG_PREV -2 /* previous period */ 123 | 124 | rd_avg_t *rd_avg_new_rate (int periods, int duration, int interval); 125 | rd_avg_res_t rd_avg (rd_avg_t *ra, int period); 126 | void rd_avg_start (rd_avg_t *ra); 127 | void rd_avg_put (rd_avg_t *ra, uint64_t val); 128 | -------------------------------------------------------------------------------- /tests/0001-fifoq.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | 30 | #include "rd.h" 31 | #include "rdqueue.h" 32 | #include "rdevent.h" 33 | #include "rdtimer.h" 34 | 35 | /** 36 | * This test has a set of caller threads and worker threads. 37 | * The caller threads allocate an object and adds it to the fifoq, 38 | * the fifoq is served by the worker threads that perform some work 39 | * and then pass the object through thread events (extra-thread callbacks) 40 | * to the main thread, which count the number of objects and exits. 41 | * To catch the case where too many objects are passed the main thread 42 | * waits a short while after receiving the last expected object before 43 | * exiting, as to catch any late duplicates. 44 | */ 45 | 46 | const int numcallers = 4; 47 | const int numobjs = 1000; /* per caller */ 48 | int numobjsdone = 0; 49 | int objid = 0; 50 | 51 | struct myobj { 52 | int id; 53 | int a,b,c; 54 | }; 55 | 56 | static rd_fifoq_t fifoq; 57 | 58 | static rd_thread_event_f(really_done) { 59 | rd_thread_exit(); 60 | } 61 | 62 | static rd_thread_event_f(obj_done) { 63 | struct myobj *obj = ptr; 64 | 65 | assert(pthread_equal(pthread_self(), rd_mainthread->rdt_thread)); 66 | 67 | assert(obj->id <= numcallers * numobjs); 68 | 69 | free(obj); 70 | 71 | if (++numobjsdone >= numcallers * numobjs) { 72 | rd_timer_add(RD_TIMER_ONCE, 100/*ms*/, 73 | rd_mainthread, really_done, NULL); 74 | } 75 | } 76 | 77 | 78 | static void *worker (void *ignore) { 79 | 80 | while (1) { 81 | rd_fifoq_elm_t *rfqe; 82 | struct myobj *obj; 83 | 84 | rfqe = rd_fifoq_pop_wait(&fifoq); 85 | 86 | obj = rfqe->rfqe_ptr; 87 | obj->c = obj->a + obj->b; 88 | 89 | rd_thread_event_add(rd_mainthread, obj_done, obj); 90 | 91 | rd_fifoq_elm_release(&fifoq, rfqe); 92 | 93 | } 94 | 95 | return NULL; 96 | } 97 | 98 | 99 | static void *caller (void *ignore) { 100 | int i; 101 | 102 | for (i = 0 ; i < numobjs ; i++) { 103 | struct myobj *obj = calloc(1, sizeof(*obj)); 104 | 105 | obj->id = rd_atomic_add(&objid, 1); 106 | obj->a = 1; 107 | obj->b = i; 108 | 109 | rd_fifoq_add(&fifoq, obj); 110 | } 111 | 112 | sleep(5); 113 | return NULL; 114 | } 115 | 116 | 117 | static rd_thread_event_f(test_timeout) { 118 | printf("Test timed out\n"); 119 | exit(1); 120 | } 121 | 122 | 123 | int main (int argc, char **argv) { 124 | 125 | rd_init(); 126 | 127 | rd_timer_add(RD_TIMER_ONCE, 2000, NULL, test_timeout, NULL); 128 | 129 | rd_fifoq_init(&fifoq); 130 | 131 | rd_threads_create("worker", 4, NULL, worker, NULL); 132 | rd_threads_create("caller", numcallers, NULL, caller, NULL); 133 | 134 | rd_thread_dispatch(); 135 | 136 | if (numobjsdone != numcallers * numobjs) { 137 | printf("%i objects are done, but %i expected!\n", 138 | numobjsdone, numcallers * numobjs); 139 | return 1; 140 | } 141 | 142 | return 0; 143 | } 144 | -------------------------------------------------------------------------------- /tests/0013-event.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdevent.h" 31 | #include "rdthread.h" 32 | 33 | #include "rdtests.h" 34 | 35 | 36 | static int calltrace = 0; 37 | static int callfails = 0; 38 | 39 | static void func0 (void) { 40 | calltrace |= (1 << 0); 41 | } 42 | 43 | static void func1 (void *arg1) { 44 | TEST_VARS; 45 | 46 | if (arg1 != (void *)0x11111111) 47 | TEST_FAIL("func1 arg1 is wrong %p", arg1); 48 | 49 | calltrace |= (1 << 1); 50 | 51 | callfails += fails; 52 | } 53 | 54 | static void func2 (void *arg1, void *arg2) { 55 | TEST_VARS; 56 | 57 | if (arg1 != (void *)0x11111111) 58 | TEST_FAIL("func2 arg1 is wrong %p", arg1); 59 | if (arg2 != (void *)0x22222222) 60 | TEST_FAIL("func2 arg2 is wrong %p", arg2); 61 | 62 | calltrace |= (1 << 2); 63 | 64 | callfails += fails; 65 | } 66 | 67 | static void func3 (void *arg1, void *arg2, void *arg3) { 68 | TEST_VARS; 69 | 70 | if (arg1 != (void *)0x11111111) 71 | TEST_FAIL("func3 arg1 is wrong %p", arg1); 72 | if (arg2 != (void *)0x22222222) 73 | TEST_FAIL("func3 arg2 is wrong %p", arg2); 74 | if (arg3 != (void *)0x33333333) 75 | TEST_FAIL("func3 arg3 is wrong %p", arg3); 76 | 77 | calltrace |= (1 << 3); 78 | 79 | callfails += fails; 80 | } 81 | 82 | static void func4 (void *arg1, void *arg2, void *arg3, void *arg4) { 83 | TEST_VARS; 84 | 85 | if (arg1 != (void *)0x11111111) 86 | TEST_FAIL("func4 arg1 is wrong %p", arg1); 87 | if (arg2 != (void *)0x22222222) 88 | TEST_FAIL("func4 arg2 is wrong %p", arg2); 89 | if (arg3 != (void *)0x33333333) 90 | TEST_FAIL("func4 arg3 is wrong %p", arg3); 91 | if (arg4 != (void *)0x44444444) 92 | TEST_FAIL("func4 arg4 is wrong %p", arg4); 93 | 94 | calltrace |= (1 << 4); 95 | 96 | callfails += fails; 97 | } 98 | 99 | 100 | static int test_event_func_call (void) { 101 | TEST_VARS; 102 | 103 | rd_thread_func_call0(rd_mainthread, func0); 104 | rd_thread_func_call1(rd_mainthread, func1, (void *)0x11111111); 105 | rd_thread_func_call2(rd_mainthread, func2, 106 | (void *)0x11111111, (void *)0x22222222); 107 | rd_thread_func_call3(rd_mainthread, func3, 108 | (void *)0x11111111, (void *)0x22222222, 109 | (void *)0x33333333); 110 | rd_thread_func_call4(rd_mainthread, func4, 111 | (void *)0x11111111, (void *)0x22222222, 112 | (void *)0x33333333, (void *)0x44444444); 113 | 114 | while (calltrace != 0x1f) 115 | rd_thread_poll(100); 116 | 117 | fails += callfails; 118 | 119 | TEST_RETURN; 120 | } 121 | 122 | 123 | static void test_timeout (int sig) { 124 | TEST_VARS; 125 | TEST_FAIL("Test timed out"); 126 | exit(1); 127 | } 128 | 129 | int main (int argc, char **argv) { 130 | TEST_VARS; 131 | 132 | TEST_INIT; 133 | 134 | signal(SIGALRM, test_timeout); 135 | alarm(3); 136 | 137 | rd_init(); 138 | 139 | fails += test_event_func_call(); 140 | 141 | TEST_EXIT; 142 | } 143 | 144 | -------------------------------------------------------------------------------- /tests/0010-encoding.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdencoding.h" 31 | #include "rdlog.h" 32 | 33 | #include "rdtests.h" 34 | 35 | static int test_varint (void) { 36 | TEST_VARS; 37 | char buf[24]; 38 | int r; 39 | int vlen; 40 | uint64_t u64is[] = { 0, 12345678910112131415llu, 300 }; 41 | uint64_t s64is[] = { 0, -12345678910112131415llu, 42 | 481924891llu -300, 300 }; 43 | uint64_t v, v2; 44 | int i; 45 | 46 | /* Unsigned */ 47 | for (i = 0 ; i < RD_ARRAY_SIZE(u64is) ; i++) { 48 | if ((r = rd_varint_encode_u64(u64is[i], 49 | buf, sizeof(buf))) == -1) 50 | TEST_FAIL("#%i: varint encode failed", i); 51 | 52 | v = rd_varint_decode_u64(buf, sizeof(buf), &vlen); 53 | if (vlen <= 0) 54 | TEST_FAIL("#%i: varint decode failed: vlen = %i", 55 | i, vlen); 56 | if (u64is[i] != v) 57 | TEST_FAIL("#%i: varint decode incorrect: " 58 | "in %"PRIx64 " != out %"PRIx64, 59 | i, u64is[i], v); 60 | } 61 | 62 | /* Signed */ 63 | for (i = 0 ; i < RD_ARRAY_SIZE(s64is) ; i++) { 64 | if ((r = rd_varint_encode_s64(s64is[i], 65 | buf, sizeof(buf))) == -1) 66 | TEST_FAIL("#%i: varint encode failed", i); 67 | 68 | v = rd_varint_decode_s64(buf, sizeof(buf), &vlen); 69 | if (vlen <= 0) 70 | TEST_FAIL("#%i: varint decode failed: vlen = %i", 71 | i, vlen); 72 | if (s64is[i] != v) 73 | TEST_FAIL("#%i: varint decode incorrect: " 74 | "in %"PRId64 " != out %"PRId64, 75 | i, s64is[i], v); 76 | } 77 | 78 | /* Reference buffer (300) */ 79 | v2 = 300llu; 80 | buf[0] = 0xac; 81 | buf[1] = 0x02; 82 | buf[2] = 0xff; 83 | v = rd_varint_decode_u64(buf, sizeof(buf), &vlen); 84 | if (RD_VARINT_DECODE_ERR(vlen)) 85 | TEST_FAIL("#%i: varint decode failed: vlen = %i", 86 | i, vlen); 87 | if (v2 != v) 88 | TEST_FAIL("#%i: varint decode incorrect: " 89 | "in %"PRId64 " != out %"PRId64, 90 | i, v2, v); 91 | 92 | /* Buffer under flow */ 93 | v = rd_varint_decode_u64(buf, 1, &vlen); 94 | TEST_ASSERT(RD_VARINT_DECODE_ERR(vlen)); 95 | TEST_ASSERT(RD_VARINT_DECODE_UNDERFLOW(vlen)); 96 | 97 | 98 | TEST_RETURN; 99 | } 100 | 101 | 102 | static int test_hex (void) { 103 | TEST_VARS; 104 | const char *in = "My hex testing string is here, 123456789\0notincl"; 105 | char tmp1[512], tmp2[256]; 106 | char bin[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 107 | 0x11, 0x3f, 0x7f, 0xf1, 0x44, 0xff }; 108 | int r; 109 | 110 | rd_bin2hex(in, strlen(in)+1, tmp1, sizeof(tmp1)); 111 | rd_hex2bin(tmp1, -1, tmp2, sizeof(tmp2)); 112 | TEST_STR_EQ(tmp2, in); 113 | 114 | rd_bin2hex(bin, sizeof(bin), tmp1, sizeof(tmp1)); 115 | TEST_STR_EQ(tmp1, "00010203040506070809113f7ff144ff"); 116 | r = rd_hex2bin(tmp1, -1, tmp2, sizeof(tmp2)); 117 | TEST_INT_EQ(r, 16); 118 | TEST_ASSERT(!memcmp(tmp2, bin, 16)); 119 | 120 | TEST_RETURN; 121 | } 122 | 123 | int main (int argc, char **argv) { 124 | TEST_VARS; 125 | 126 | TEST_INIT; 127 | 128 | fails += test_varint(); 129 | fails += test_hex(); 130 | 131 | TEST_EXIT; 132 | } 133 | 134 | -------------------------------------------------------------------------------- /rdstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include 32 | #include 33 | #include "rdmem.h" 34 | 35 | #define RD_TSPRINTF_BUFCNT 64 /* Number of simultaneously valid 36 | * thread-local buffers returned by 37 | * rd_tsprintf(). */ 38 | 39 | /** 40 | * Returns a temporary string (from a circular buffer wrapping 41 | * at RD_TSPRINTF_BUFCNT thread-local calls) containing the formatted 42 | * string as described by 'format' and the following var-args. 43 | * 44 | * To free the allocated memory, rd_string_thread_cleanup() must be called 45 | * prior to destroying the thread. 46 | * This is done automatically by rd_thread_exit() or rd_thread_cleanup(). 47 | */ 48 | char *rd_tsprintf (const char *format, ...) 49 | __attribute__((format (printf, 1, 2))); 50 | 51 | 52 | /** 53 | * Wrapper for snprintf() that concatenates the current content of 'str' 54 | * with the one described in 'format' and then returns the full length of 'str'. 55 | */ 56 | int rd_snprintf_cat (char *str, size_t size, const char *format, ...) 57 | __attribute__((format (printf, 3, 4))); 58 | 59 | 60 | 61 | /** 62 | * Looks for any of the characters in '*delimiters' and returns 63 | * the pointer to it. 64 | * One big difference from strchr() is that it supports matching '\0' 65 | * if `match_eol' is set, thus allowing 66 | * conveniant scan-to-token(s)-or-end-of-buffer operations. 67 | * The other difference is that supports multiple tokens to look for. 68 | * 'size' is either the length of 's' or '-1' if it is to scan to '\0'. 69 | */ 70 | char *rd_strnchrs (const char *s, ssize_t size, const char *delimiters, 71 | int match_eol); 72 | 73 | 74 | 75 | /** 76 | * Acts like strspn(3) (if accept=1) or strcspn(3) (if accept=0) 77 | * but takes a sized input string (rather than a nul-terminated one) 78 | * and the accept/reject characters are specified in a 1:1 map instead. 79 | * If 'accept' is 1 it acts like strspn(3), if 0 like strcspn(3). 80 | */ 81 | size_t rd_strnspn_map (const char *s, size_t size, 82 | int accept, const char map[256]); 83 | 84 | /** 85 | * Acts like strspn(3) but allows for non-terminated strings. 86 | */ 87 | size_t rd_strnspn (const char *s, size_t size, const char *accept); 88 | 89 | /** 90 | * Acts like strcspn(3) but allows for non-terminated strings. 91 | */ 92 | size_t rd_strncspn (const char *s, size_t size, const char *reject); 93 | 94 | 95 | 96 | /** 97 | * strncmp() wrapper which takes two input lengths. 98 | */ 99 | static inline int rd_strnncmp (const char *s1, size_t n1, 100 | const char *s2, size_t n2) RD_UNUSED; 101 | static inline int rd_strnncmp (const char *s1, size_t n1, 102 | const char *s2, size_t n2) { 103 | int r; 104 | 105 | if ((r = strncmp(s1, s2, RD_MIN(n1, n2)))) 106 | return r; 107 | 108 | return (int)n1-n2; 109 | } 110 | 111 | 112 | /** 113 | * Return the character position where s1 and s2 begin to differ. 114 | * If the strings are equal -1 will be returned. 115 | */ 116 | ssize_t rd_strdiffpos (const char *s1, const char *s2); 117 | ssize_t rd_strndiffpos (const char *s1, size_t size1, 118 | const char *s2, size_t size2); 119 | 120 | 121 | 122 | 123 | 124 | /** 125 | * Frees thread-local resources on thread exit. 126 | */ 127 | void rd_string_thread_cleanup (void); 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /tests/rdtests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | * librd - Rapid Development C library 4 | * 5 | * Copyright (c) 2012-2013, Magnus Edenhill 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 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 OWNER OR CONTRIBUTORS BE 21 | * 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 THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | /** 31 | * Common helpers for test programs. 32 | */ 33 | 34 | 35 | 36 | /* Globals */ 37 | static int tests_dbg RD_UNUSED = 0; 38 | 39 | 40 | #define TEST_VARS int fails = 0 41 | #define TEST_RETURN return fails 42 | #define TEST_EXIT do { \ 43 | if (fails > 0) \ 44 | fprintf(stderr, "\n\n%s: %i TESTS FAILED\n", \ 45 | __FILE__, fails); \ 46 | exit(fails ? 1 : 0); \ 47 | } while (0) 48 | 49 | 50 | #define TEST_ACCUM(call) fails += call 51 | 52 | #define TEST_IS_DBG tests_dbg 53 | 54 | #define TEST_DBG(desc...) do { \ 55 | if (tests_dbg) { \ 56 | fprintf(stderr, "%s: TEST DEBUG: %s:%i: ", \ 57 | __FILE__, __FUNCTION__, __LINE__); \ 58 | fprintf(stderr, desc); \ 59 | fprintf(stderr, "\n"); \ 60 | } \ 61 | } while (0) 62 | 63 | 64 | 65 | #define TEST_FAIL(reason...) do { \ 66 | fails++; \ 67 | fprintf(stderr, "%s: TEST FAILED: %s:%i: ", \ 68 | __FILE__, __FUNCTION__, __LINE__); \ 69 | fprintf(stderr, reason); \ 70 | fprintf(stderr, "\n"); \ 71 | } while (0) 72 | 73 | #define TEST_FAIL_RETURN(reason...) do { \ 74 | fails++; \ 75 | fprintf(stderr, "%s: TEST FAILED: %s:%i: ", \ 76 | __FILE__, __FUNCTION__, __LINE__); \ 77 | fprintf(stderr, reason); \ 78 | fprintf(stderr, "\n"); \ 79 | return fails; \ 80 | } while (0) 81 | 82 | 83 | #define TEST_ASSERT(expr) do { \ 84 | if (!(expr)) \ 85 | TEST_FAIL("test expression \"%s\" failed", #expr); \ 86 | else \ 87 | TEST_OK("test expression \"%s\" is true", #expr); \ 88 | } while (0) 89 | 90 | #define TEST_STR_EQ(a, b) do { \ 91 | if (strcmp(a, b)) \ 92 | TEST_FAIL("test equality comparison of '%s' and '%s' failed", \ 93 | a, b); \ 94 | else \ 95 | TEST_OK("test equality comparison of '%s' and '%s' is true", \ 96 | a, b); \ 97 | } while (0) 98 | 99 | 100 | #define TEST_STR_NEQ(a, b) do { \ 101 | if (strcmp(a, b)) \ 102 | TEST_FAIL("test inequality comparison of '%s' " \ 103 | "and '%s' failed", a, b); \ 104 | else \ 105 | TEST_OK("test inequality comparison of '%s' " \ 106 | " and '%s' is true", a, b); \ 107 | } while (0) 108 | 109 | #define TEST_INT_EQ(a, b) do { \ 110 | if ((a) != (b)) \ 111 | TEST_FAIL("test equality comparison of %i and %i failed", \ 112 | a, b); \ 113 | else \ 114 | TEST_OK("test equality comparison of %i and %i is true", \ 115 | a, b); \ 116 | } while (0) 117 | 118 | #define TEST_INT_NEQ(a, b) do { \ 119 | if ((a) == (b)) \ 120 | TEST_FAIL("test inequality comparison of %i and %i failed", a, b); \ 121 | else \ 122 | TEST_OK("test inequality comparison of %i and %i is true", a, b); \ 123 | } while (0) 124 | 125 | 126 | #define TEST_OK(desc...) do { \ 127 | if (tests_dbg) { \ 128 | fprintf(stderr, "%s: TEST OK: %s:%i: ", \ 129 | __FILE__, __FUNCTION__, __LINE__); \ 130 | fprintf(stderr, desc); \ 131 | fprintf(stderr, "\n"); \ 132 | } \ 133 | } while (0) 134 | 135 | 136 | #define TEST_INIT do { \ 137 | if (getenv("LIBRD_TEST_DBG")) \ 138 | tests_dbg = 1; \ 139 | } while (0) 140 | -------------------------------------------------------------------------------- /rdencoding.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /** 30 | * Various encoding/decoding schemes. 31 | */ 32 | #include "rdencoding.h" 33 | 34 | 35 | uint64_t rd_varint_decode_u64 (const void *buf, 36 | size_t size, int *vlenp) { 37 | const unsigned char *s = buf; 38 | const unsigned char *end = s + size; 39 | uint64_t uval = 0; 40 | int bits = 0; 41 | 42 | *vlenp = 0; 43 | 44 | while (&s[*vlenp] < end) { 45 | if (s[*vlenp] < 0x80) { 46 | if (*vlenp > 9) { 47 | /* Overflow */ 48 | *vlenp = -*vlenp; 49 | return 0; 50 | } 51 | return uval | (((uint64_t)s[(*vlenp)++]) << bits); 52 | } 53 | 54 | uval |= ((uint64_t)(s[(*vlenp)++] & 0x7f)) << bits; 55 | bits += 7; 56 | } 57 | 58 | if (*vlenp == 0 || s[(*vlenp)-1] >= 0x80) { 59 | /* Buffer underflow, indicate that we need more data. */ 60 | *vlenp = -((*vlenp)+1); 61 | } 62 | 63 | return 0; 64 | } 65 | 66 | 67 | int64_t rd_varint_decode_s64 (const void *buf, size_t size, int *vlenp) { 68 | uint64_t uval; 69 | int64_t val; 70 | 71 | uval = rd_varint_decode_u64(buf, size, vlenp); 72 | 73 | if (*vlenp <= 0) 74 | return 0; 75 | 76 | val = uval >> 1; 77 | if (uval & 1) 78 | val ^= val; 79 | 80 | return val; 81 | } 82 | 83 | 84 | int rd_varint_encode_u64 (uint64_t uval, void *dest, size_t size) { 85 | unsigned char *s = dest; 86 | const unsigned char *end = s + size; 87 | 88 | while (uval >= 0x80) { 89 | if (s >= end) 90 | return -1; 91 | 92 | *(s++) = (uval & 0xff) | 0x80; 93 | uval >>= 7; 94 | } 95 | 96 | if (s >= end) 97 | return -1; 98 | 99 | *(s++) = uval & 0xff; 100 | 101 | return (int)(s - (unsigned char *)dest); 102 | } 103 | 104 | 105 | int rd_varint_encode_s64 (int64_t val, void *dest, size_t size) { 106 | uint64_t uval = (uint64_t)val << 1; 107 | if (val < 0) 108 | uval ^= uval; 109 | 110 | return rd_varint_encode_u64(uval, dest, size); 111 | } 112 | 113 | 114 | 115 | 116 | int rd_hex2bin (const char *hexstr, int inlen, char *dst, int dstlen) { 117 | const char *end = inlen == -1 ? 118 | (const char *)UINTPTR_MAX : hexstr+inlen; 119 | const char *s = hexstr; 120 | char *d = dst; 121 | char *dend = dst + dstlen; 122 | int state = 0; 123 | static const char ignore[256] = { 124 | [' '] = 1, ['\t'] = 1, ['.'] = 1, [':'] = 1, 125 | ['\n'] = 1, ['\r'] = 1, 126 | }; 127 | 128 | while (*s && s < end && d < dend) { 129 | char c; 130 | 131 | if (ignore[(int)*s]) { 132 | s++; 133 | continue; 134 | } 135 | 136 | if (*s >= '0' && *s <= '9') 137 | c = *s - '0'; 138 | else if (*s >= 'A' && *s <= 'F') 139 | c = *s - 'A' + 10; 140 | else if (*s >= 'a' && *s <= 'f') 141 | c = *s - 'a' + 10; 142 | else 143 | break; 144 | 145 | if (state++ & 1) 146 | *(d++) |= c; 147 | else 148 | *d = c << 4; 149 | 150 | s++; 151 | } 152 | 153 | return (int)(d-dst); 154 | } 155 | 156 | 157 | int rd_bin2hex (const char *bin, int inlen, char *dst, int dstlen) { 158 | const char *end = bin+inlen; 159 | const char *s = bin; 160 | char *d = dst; 161 | char *dend = dst + dstlen; 162 | static const char map[16] = { 163 | '0', '1', '2', '3', '4', '5', '6', '7', 164 | '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 165 | 166 | while (s < end && d+3 < dend) { 167 | *d++ = map[(*s & 0xff) >> 4]; 168 | *d++ = map[*s & 0x0f]; 169 | s++; 170 | } 171 | if (d < dend) 172 | *d = '\0'; 173 | 174 | return (int)(d - dst); 175 | } 176 | 177 | -------------------------------------------------------------------------------- /tests/0005-opt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdopt.h" 31 | 32 | struct storeval { 33 | char *c; 34 | int d; 35 | int elf; 36 | char *path; 37 | }; 38 | 39 | static int opt_tests (void) { 40 | int fails = 0; 41 | struct storeval store; 42 | rd_opt_t myopts[] = { 43 | { RD_OPT_NIL|RD_OPT_REQ, 'r', "required", 0 }, 44 | { 0, 'a', "alpha" }, 45 | { RD_OPT_NIL, 0, "beta" }, 46 | { RD_OPT_STR, 'c', "csar", 1, &store.c }, 47 | { RD_OPT_BOOL, 'd', NULL, 0, &store.d }, 48 | { RD_OPT_INT, 0, "--elf", 1, &store.elf }, 49 | { RD_OPT_PATH, 'p', "path", 1, &store.path }, 50 | { RD_OPT_NIL|RD_OPT_MUT1, 0, "mg1a" }, 51 | { RD_OPT_NIL|RD_OPT_MUT1, 0, "mg1b" }, 52 | { RD_OPT_NIL|RD_OPT_MUT2, 0, "mg2a" }, 53 | { RD_OPT_NIL|RD_OPT_MUT2, 0, "mg2b" }, 54 | { RD_OPT_NIL|RD_OPT_MUT3|RD_OPT_REQ, 0, "mg3a" }, 55 | { RD_OPT_NIL|RD_OPT_MUT3|RD_OPT_REQ, 0, "mg3b" }, 56 | { RD_OPT_END }, 57 | }; 58 | struct { 59 | enum { 60 | _PASS = 0, 61 | _FAIL, 62 | } expect; 63 | int argc; 64 | char *argv[32]; 65 | int check_store; 66 | struct storeval store; 67 | } t[] = { 68 | { _FAIL, 4, { "", "--mach", "2", "--mg3a" } }, 69 | { _PASS, 8, { "", "-c", "2", "-d", "--path", "/tmp", 70 | "--required", "--mg3b" }, 71 | 1, { .c = "2", .d = 1, .path = "/tmp" } }, 72 | { _FAIL, 5, { "", "--required", 73 | "--path", "/probably wont exist", "--mg3a"}, 74 | 1, { .path = NULL } }, 75 | { _PASS, 5, { "", "-r", "--mg1a", "--mg2a", "--mg3a" }, 0 }, 76 | { _FAIL, 5, { "", "-r", "--mg1a", "--mg1b", "--mg3a" }, 0 }, 77 | { _PASS, 3, { "", "-r", "--mg3a", }, 0 }, 78 | { _PASS, 3, { "", "-r", "--mg3b", }, 0 }, 79 | { _FAIL, 2, { "", "-r", }, 0 }, 80 | }; 81 | int i; 82 | 83 | for (i = 0 ; i < RD_ARRAYSIZE(t) ; i++) { 84 | const char *ret; 85 | int argi = -1; 86 | 87 | memset(&store, 0, sizeof(store)); 88 | 89 | ret = rd_opt_parse(myopts, t[i].argc, t[i].argv, &argi); 90 | 91 | if (t[i].expect == _PASS && ret) { 92 | printf("rd_opt test #%i failed: expected PASS, got " 93 | "error: %s\n", i, ret); 94 | fails++; 95 | } else if (t[i].expect == _FAIL && !ret) { 96 | printf("rd_opt test #%i failed: expected FAIL, got " 97 | "success\n", i); 98 | fails++; 99 | } else if (t[i].check_store) { 100 | if (t[i].store.c && (!store.c || 101 | strcmp(t[i].store.c, store.c))) { 102 | printf("rd opt test #%i failed: " 103 | "opt value c should be '%s' but is " 104 | "'%s'\n", 105 | i, t[i].store.c, store.c); 106 | fails++; 107 | } 108 | 109 | if (t[i].store.path && (!store.path || 110 | strcmp(t[i].store.path, 111 | store.path))) { 112 | printf("rd opt test #%i failed: " 113 | "opt value path should be '%s' but is " 114 | "'%s'\n", 115 | i, t[i].store.path, store.path); 116 | fails++; 117 | } 118 | 119 | if (t[i].store.d != store.d) { 120 | printf("rd opt test #%i failed: " 121 | "opt value d should be %i but is %i\n", 122 | i, t[i].store.d, store.d); 123 | fails++; 124 | } 125 | 126 | if (t[i].store.elf != store.elf) { 127 | printf("rd opt test #%i failed: " 128 | "opt value elf should be %i but " 129 | "is %i\n", 130 | i, t[i].store.elf, store.elf); 131 | fails++; 132 | } 133 | } 134 | 135 | } 136 | 137 | 138 | return fails; 139 | } 140 | 141 | 142 | int main (int argc, char **argv) { 143 | int fails = 0; 144 | 145 | fails += opt_tests(); 146 | 147 | return fails ? 1 : 0; 148 | } 149 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | librd - Rapid Development C library 2 | =================================== 3 | 4 | Copyright (c) 2012-2013, [Magnus Edenhill](http://www.edenhill.se/), et.al. 5 | 6 | [https://github.com/edenhill/librd](https://github.com/edenhill/librd) 7 | 8 | **librd** aims to provide the commonly needed helpers, sub systems, snippets 9 | and misc. functionality that lacks from the standard C libraries, allowing for 10 | rapid development of new programs and **non-intrusive** extension of existing 11 | applications. 12 | 13 | **librd** is **non-intrusive** in the sense that single specific functionality 14 | from **librd** can be used by the application without having to use or 15 | initialize other parts of the library. In its most simple form you add 16 | `-lrd -lz -lrt` to your linking step and include the proper `rd.h` 17 | include file for your desired functionality. 18 | 19 | **librd** is licensed under the 2-clause BSD license. 20 | 21 | 22 | 23 | **librd** provides, on a higher level: 24 | 25 | - proper thread support throughout the library 26 | - consistent, natural and non-bloated APIs and interfaces 27 | - scalability and performance 28 | - proper documentation (some time in the future) 29 | - suitable for embedded systems, large-scale backend systems, GUI applications, 30 | etc. 31 | 32 | 33 | # Functionality 34 | 35 | Non-exhaustive list of current **librd** functionality: 36 | 37 | - `rdqueue.h`: Thread-safe FIFO queues (nice for worker queues). 38 | - `rdthread.h`: Thread management abstraction. 39 | - `rdmem.h`: Memory contexts for contextual malloc's allowing memory 40 | usage supervision and free-all-context-memory-at-once. 41 | - `rdmem.h`: Efficient memory and allocation helpers: `rd_calloc_ 42 | - `rdsysqueue.h`: Improved sys/queue.h 43 | - `rdopt.h`: Short (-c) and long (--config) command line argument option 44 | parsing with input validation and automatic variable assignments. 45 | - `rdfloat.h`: Float comparison helpers. 46 | - `rdaddr.h`: `AF_INET` and `AF_INET6` agnostification. 47 | - `rdbuf.h`: Generic buffers with (de)serializer/writer/reader callbacks. 48 | - `rdstring.h`: String helpers: `rd_strnchrs()`. 49 | - `rd.h`: Convenience macros and porting alleviation: 50 | `RD_CAP*(), RD_ARRAY_SIZE(), RD_ARRAY_ELEM(), RD_MIN(), RD_MAX()`. 51 | - `rdavl.h`: Thread-safe AVL trees. 52 | - `rdio.h`: Socket/fd IO abstraction and helpers. 53 | - `rdfile.h`: File/filesystem access helpers. 54 | - `rdencoding.h`: Various encoder and decoder helpers (varint). 55 | 56 | 57 | # Usage 58 | 59 | ## Requirements 60 | The GNU toolchain 61 | pthreads 62 | zlib 63 | 64 | ## Instructions 65 | 66 | ### Building 67 | 68 | make all 69 | make install 70 | # or to install in another location than /usr/local: 71 | DESTDIR=/my/prefix make install 72 | 73 | ### Rigid building 74 | 75 | The above procedure continues on test failures, but that might not be 76 | desirable, so here's how to do make sure the tests pass before installing. 77 | 78 | make libs test install 79 | 80 | 81 | 82 | ### Usage in code 83 | 84 | #include 85 | #include 86 | 87 | ... 88 | rd_init(); 89 | ... 90 | 91 | rd_....(); 92 | 93 | Link your program with `-lrd -lz -lrt`. 94 | 95 | 96 | ## Documentation 97 | 98 | Documentation is still lacking, but each public function and concept is 99 | described in its `.h` header file while internal functions are described 100 | in their `.c` files. 101 | 102 | 103 | ## Testing 104 | 105 | Regression tests are integrated into the build process. 106 | The tests are in the `tests/` sub-directory. 107 | 108 | 109 | ## Examples 110 | 111 | The test programs in the `tests/` sub-directory serve as examples, but some 112 | more explicit examples will be provided in the `examples/` sub-directory. 113 | 114 | More documentation and usage examples will come. 115 | 116 | 117 | # Apache Kafka 118 | 119 | **NOTE:** The Kafka implementation has been moved to its own library. 120 | See [librdkafka](https://github.com/edenhill/librdkafka). 121 | 122 | 123 | # Public projects using librd 124 | 125 | - [Image Judge](https://github.com/edenhill/imagejudge) (TBA) 126 | 127 | 128 | 129 | # TODO 130 | 131 | Scattered lists of things to do: 132 | 133 | - Generic thread-safe linked-lists that does not require a struct field. 134 | i.e.: `obj->ll = rd_ll_add(mylist, obj);` 135 | - **librd** should be aware of the number of CPU cores so it can be used 136 | to create an appropriate number of workers, if thats what matters. 137 | i.e.: `rd_workers_create(..., rd_conf_getu32("sys.cpu.cores") * 16);` 138 | - Configuration/.rc file support using the rd_opt_t framework allowing 139 | the same configuration token to be specified both as command line 140 | argument, CLI command and configuration file directive without any 141 | extra development effort. 142 | - rdmkbuildtree.sh - script to generate makefiles at the start of a project, 143 | debian directories, etc. 144 | - Add anything else that may come in handy for more than one program ever. 145 | 146 | -------------------------------------------------------------------------------- /rdlog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "rd.h" 34 | #include "rdthread.h" 35 | #include "rdlog.h" 36 | 37 | 38 | 39 | 40 | #define RD_DBG_CTXS_MAX 32 41 | static __thread char *rd_dbg_ctxs[RD_DBG_CTXS_MAX]; 42 | static __thread int rd_dbg_ctx_idx = 0; 43 | static __thread int rd_dbg_ctx_wanted_idx = 0; 44 | 45 | static int rd_current_severity = LOG_INFO; 46 | 47 | void rd_log_set_severity (int severity) { 48 | rd_current_severity = severity; 49 | } 50 | 51 | 52 | void rd_dbg_ctx_push (const char *fmt, ...) { 53 | va_list ap; 54 | char *buf; 55 | 56 | rd_dbg_ctx_wanted_idx++; 57 | 58 | if (rd_dbg_ctx_idx + 1 == RD_DBG_CTXS_MAX) 59 | return; 60 | 61 | buf = malloc(64); 62 | 63 | va_start(ap, fmt); 64 | vsnprintf(buf, 64, "%s", ap); 65 | va_end(ap); 66 | 67 | rd_dbg_ctx_idx++; 68 | } 69 | 70 | void rd_dbg_ctx_pop (void) { 71 | assert(rd_dbg_ctx_wanted_idx-- > 0); 72 | assert(rd_dbg_ctx_idx-- > 0); 73 | free(rd_dbg_ctxs[rd_dbg_ctx_idx]); 74 | } 75 | 76 | void rd_dbg_ctx_clear (void) { 77 | while (rd_dbg_ctx_idx > 0) 78 | rd_dbg_ctx_pop(); 79 | } 80 | 81 | 82 | 83 | void rdputs0 (const char *file, const char *func, int line, 84 | int severity, const char *fmt, ...) { 85 | va_list ap; 86 | char buf[4096]; 87 | int of = 0; 88 | int i; 89 | int r RD_UNUSED; 90 | rd_ts_t now; 91 | static __thread char thrname[16]; 92 | int printf_rc; 93 | 94 | if (severity > rd_current_severity) 95 | return; 96 | 97 | now = rd_clock(); 98 | 99 | if (unlikely(!rd_currthread && !*thrname)) { 100 | const pthread_t tid = pthread_self(); 101 | char *cursor = thrname; 102 | int of = sprintf(cursor, "thr:"); 103 | 104 | for (i=0; irdt_name : thrname); 117 | 118 | if (rd_dbg_ctx_idx > 0) { 119 | for (i = 0 ; i < rd_dbg_ctx_idx ; i++) 120 | of += snprintf(buf+of, sizeof(buf)-of, "%s[%s]", 121 | i ? "->" : "", 122 | rd_dbg_ctxs[i]); 123 | 124 | of += snprintf(buf+of, sizeof(buf)-of, " "); 125 | } 126 | 127 | va_start(ap, fmt); 128 | printf_rc = vsnprintf(buf+of, sizeof(buf)-of, fmt, ap); 129 | va_end(ap); 130 | 131 | if( printf_rc > sizeof(buf) - of ) { 132 | // Should we log a log buffer overflow? should we care about 133 | // log overflow log overflows? 134 | of = sizeof(buf)-2; 135 | buf[of-1] = buf[of-2] = buf[of-3] = '.'; 136 | } else { 137 | of += printf_rc; 138 | } 139 | 140 | buf[of++] = '\n'; 141 | buf[of] = '\0'; 142 | 143 | r = write(STDOUT_FILENO, buf, of); 144 | } 145 | 146 | 147 | 148 | 149 | 150 | void rd_hexdump (FILE *fp, const char *name, const void *ptr, size_t len) { 151 | const char *p = (const char *)ptr; 152 | size_t of = 0; 153 | 154 | 155 | if (name) 156 | fprintf(fp, "%s hexdump (%zu bytes):\n", name, len); 157 | 158 | for (of = 0 ; of < len ; of += 16) { 159 | char hexen[16*3+1]; 160 | char charen[16+1]; 161 | int hof = 0; 162 | 163 | int cof = 0; 164 | int i; 165 | 166 | for (i = of ; i < of + 16 && i < len ; i++) { 167 | hof += sprintf(hexen+hof, "%02x ", p[i] & 0xff); 168 | cof += sprintf(charen+cof, "%c", 169 | isprint(p[i]) ? p[i] : '.'); 170 | } 171 | fprintf(fp, "%08zu: %-48s %-16s\n", 172 | of, hexen, charen); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /tests/0004-bits.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdbits.h" 31 | 32 | 33 | struct bitseries { 34 | uint64_t val; 35 | enum { 36 | _SET = 0, 37 | _FAIL, 38 | _DONTSET, 39 | _END, 40 | } expect; 41 | }; 42 | 43 | static int bitvec_tests (void) { 44 | int fails = 0; 45 | rd_bitvec_t rbv; 46 | static const struct { 47 | int max; 48 | struct bitseries series[32]; 49 | } t[] = { 50 | { 31, 51 | { {0}, {1}, {2}, {3}, {4, _DONTSET}, {9}, 52 | {22}, {22}, {30}, {31}, 53 | {32, _FAIL}, 54 | { 0, _END } }, 55 | }, 56 | { 32, 57 | { {31}, {32}, { 0, _END } } 58 | }, 59 | { 2000, 60 | { {2001, _FAIL}, {23512351235LLU, _FAIL}, {1}, {1920}, 61 | {1999, _DONTSET}, {2000}, {0}, 62 | { 0, _END } }, 63 | } 64 | }; 65 | static const char *expectstr[] = { "SET", "FAIL", "DONTSET", "END" }; 66 | int i, j; 67 | uint64_t bit; 68 | 69 | 70 | #define FAIL(fmt...) do { \ 71 | printf("%s:%i: " \ 72 | "bitvec test #%i FAILED: " \ 73 | "series[%i] = %" PRIu64 " (expect=%s): ", \ 74 | __FUNCTION__,__LINE__, \ 75 | i, j, t[i].series[j].val, \ 76 | expectstr[t[i].series[j].expect]); \ 77 | printf(fmt); \ 78 | printf("\n"); \ 79 | fails++; \ 80 | } while (0) 81 | 82 | 83 | for (i = 0 ; i < RD_ARRAYSIZE(t) ; i++) { 84 | rd_bitvec_init(&rbv, RD_BITVEC_STATIC, t[i].max); 85 | 86 | /* Set test */ 87 | for (j = 0 ; j < RD_ARRAYSIZE(t[i].series) ; j++) { 88 | if (t[i].series[j].expect == _END) 89 | break; 90 | 91 | if (t[i].series[j].expect != _DONTSET) 92 | rd_bitvec_set(&rbv, t[i].series[j].val); 93 | 94 | if (rd_bitvec_test(&rbv, t[i].series[j].val)) { 95 | if (t[i].series[j].expect != _SET) 96 | FAIL("bit should not be set but is"); 97 | } else if (t[i].series[j].expect == _SET) 98 | FAIL("bit should be set but isnt"); 99 | } 100 | 101 | /* Check test */ 102 | for (j = 0 ; j < RD_ARRAYSIZE(t[i].series) ; j++) { 103 | if (t[i].series[j].expect == _END) 104 | break; 105 | 106 | if (rd_bitvec_test(&rbv, t[i].series[j].val)) { 107 | if (t[i].series[j].expect != _SET) 108 | FAIL("bit should not be set but is"); 109 | } else if (t[i].series[j].expect == _SET) 110 | FAIL("bit should be set but isnt"); 111 | } 112 | 113 | /* Reset test */ 114 | for (j = 0 ; j < RD_ARRAYSIZE(t[i].series) ; j++) { 115 | if (t[i].series[j].expect == _END) 116 | break; 117 | 118 | if (t[i].series[j].expect != _DONTSET) 119 | rd_bitvec_reset(&rbv, t[i].series[j].val); 120 | 121 | if (rd_bitvec_test(&rbv, t[i].series[j].val)) { 122 | if (t[i].series[j].expect == _SET) 123 | FAIL("bit should not be set but is"); 124 | } 125 | } 126 | 127 | rd_bitvec_free(&rbv); 128 | } 129 | 130 | #undef FAIL 131 | #define FAIL(fmt...) do { \ 132 | printf("%s:%i: " \ 133 | "bitvec test FAILED: ", \ 134 | __FUNCTION__,__LINE__); \ 135 | printf(fmt); \ 136 | printf("\n"); \ 137 | fails++; \ 138 | } while (0) 139 | 140 | /* ffs/fsl */ 141 | rd_bitvec_init(&rbv, RD_BITVEC_STATIC, 300); 142 | rd_bitvec_set(&rbv, 17); 143 | rd_bitvec_set(&rbv, 168); 144 | rd_bitvec_set(&rbv, 288); 145 | 146 | if ((bit = rd_bitvec_ffs(&rbv)) != 18) 147 | FAIL("ffs returned %" PRIu64 ", should've been 18", bit); 148 | if ((bit = rd_bitvec_fls(&rbv)) != 289) 149 | FAIL("fls returned %" PRIu64 ", should've been 289", bit); 150 | 151 | rd_bitvec_set(&rbv, 300); 152 | 153 | if ((bit = rd_bitvec_fls(&rbv)) != 301) 154 | FAIL("fls returned %" PRIu64 ", should've been 301", bit); 155 | 156 | rd_bitvec_free(&rbv); 157 | 158 | return fails; 159 | } 160 | 161 | 162 | int main (int argc, char **argv) { 163 | int fails = 0; 164 | 165 | fails += bitvec_tests(); 166 | 167 | return fails ? 1 : 0; 168 | } 169 | -------------------------------------------------------------------------------- /rdqueue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdthread.h" 31 | #include "rdqueue.h" 32 | 33 | 34 | 35 | void rd_fifoq_destroy (rd_fifoq_t *rfq) { 36 | rd_fifoq_elm_t *rfqe; 37 | 38 | rd_mutex_lock(&rfq->rfq_lock); 39 | while ((rfqe = TAILQ_FIRST(&rfq->rfq_q))) { 40 | TAILQ_REMOVE(&rfq->rfq_q, rfqe, rfqe_link); 41 | free(rfqe); 42 | } 43 | 44 | rd_mutex_unlock(&rfq->rfq_lock); 45 | rd_mutex_destroy(&rfq->rfq_lock); 46 | rd_cond_destroy(&rfq->rfq_cond); 47 | } 48 | 49 | rd_fifoq_t *rd_fifoq_init (rd_fifoq_t *rfq) { 50 | if (!rfq) 51 | rfq = calloc(1, sizeof(*rfq)); 52 | 53 | TAILQ_INIT(&rfq->rfq_q); 54 | rd_mutex_init(&rfq->rfq_lock); 55 | rd_cond_init(&rfq->rfq_cond, NULL); 56 | 57 | rfq->rfq_inited = 1; 58 | 59 | return rfq; 60 | } 61 | 62 | void rd_fifoq_set_max_size (rd_fifoq_t *rfq, int max_size, int taildrop) { 63 | rd_mutex_lock(&rfq->rfq_lock); 64 | rfq->rfq_max_size = max_size; 65 | rfq->rfq_taildrop = !!taildrop; 66 | rd_mutex_unlock(&rfq->rfq_lock); 67 | } 68 | 69 | 70 | /** 71 | * Adds 'ptr' to FIFO queue. 72 | * The optional '*ptr_purged' will be set to the purged element's ptr 73 | * if the max_size settings of the fifo has been exceeded; i.e., it will 74 | * contain the pushed-out element's ptr so that the application can 75 | * update that object's state. 76 | */ 77 | 78 | void rd_fifoq_add0 (rd_fifoq_t *rfq, void *ptr, void **ptr_purged) { 79 | rd_fifoq_elm_t *rfqe; 80 | 81 | if (ptr_purged) 82 | *ptr_purged = NULL; 83 | 84 | assert(rfq->rfq_inited); 85 | 86 | rfqe = malloc(sizeof(*rfqe)); 87 | 88 | rfqe->rfqe_refcnt = 2; /* one for rfq, one for caller */ 89 | rfqe->rfqe_ptr = ptr; 90 | 91 | rd_mutex_lock(&rfq->rfq_lock); 92 | 93 | if (rfq->rfq_max_size != 0 && 94 | rfq->rfq_cnt >= rfq->rfq_max_size) { 95 | rd_fifoq_elm_t *purge; 96 | /* Queue has reached max size, drop an entry. */ 97 | 98 | if (rfq->rfq_taildrop) 99 | purge = TAILQ_LAST(&rfq->rfq_q, rd_fifoq_elm_head_s); 100 | else 101 | purge = TAILQ_FIRST(&rfq->rfq_q); 102 | 103 | if (ptr_purged) 104 | *ptr_purged = purge->rfqe_ptr; 105 | 106 | rfq->rfq_cnt--; 107 | TAILQ_REMOVE(&rfq->rfq_q, purge, rfqe_link); 108 | 109 | if (purge->rfqe_refcnt == 1) { 110 | /* Only fifoq's refcount remained, 111 | * this entry is no longer desired on the fifo, 112 | * ignore and remove it. */ 113 | rd_fifoq_elm_release0(rfq, purge); 114 | } 115 | 116 | } 117 | 118 | TAILQ_INSERT_TAIL(&rfq->rfq_q, rfqe, rfqe_link); 119 | rfq->rfq_cnt++; 120 | rd_cond_signal(&rfq->rfq_cond); 121 | rd_mutex_unlock(&rfq->rfq_lock); 122 | } 123 | 124 | 125 | 126 | 127 | rd_fifoq_elm_t *rd_fifoq_pop0 (rd_fifoq_t *rfq, int nowait, int timeout_ms) { 128 | rd_fifoq_elm_t *rfqe; 129 | 130 | /* Pop the next valid element from the FIFO. */ 131 | do { 132 | rd_mutex_lock(&rfq->rfq_lock); 133 | 134 | while (!(rfqe = TAILQ_FIRST(&rfq->rfq_q))) { 135 | if (nowait) { 136 | rd_mutex_unlock(&rfq->rfq_lock); 137 | return NULL; 138 | } 139 | 140 | if (timeout_ms) { 141 | if (rd_cond_timedwait_ms(&rfq->rfq_cond, 142 | &rfq->rfq_lock, 143 | timeout_ms) 144 | == ETIMEDOUT) { 145 | rd_mutex_unlock(&rfq->rfq_lock); 146 | return NULL; 147 | } 148 | } else 149 | rd_cond_wait(&rfq->rfq_cond, &rfq->rfq_lock); 150 | } 151 | 152 | assert(rfq->rfq_cnt > 0); 153 | rfq->rfq_cnt--; 154 | TAILQ_REMOVE(&rfq->rfq_q, rfqe, rfqe_link); 155 | 156 | if (rfqe->rfqe_refcnt == 1) { 157 | /* Only fifoq's refcount remains, 158 | * this entry is no longer desired on the fifo, 159 | * ignore and remove it. */ 160 | rd_fifoq_elm_release0(rfq, rfqe); 161 | continue; 162 | } 163 | 164 | break; 165 | 166 | } while (rfqe == NULL); 167 | 168 | rd_fifoq_elm_release0(rfq, rfqe); 169 | 170 | rd_mutex_unlock(&rfq->rfq_lock); 171 | 172 | return rfqe; 173 | } 174 | 175 | 176 | -------------------------------------------------------------------------------- /tests/0009-string.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdstring.h" 31 | 32 | static int test_string (void) { 33 | char *str1 = "1234\n5678"; 34 | char *str2; 35 | const char *delimiters = "14\n8"; 36 | char *match[] = { str1, str1+3, str1+4, str1+8, 37 | str1+strlen(str1) }; 38 | const char *d = delimiters; 39 | char *m; 40 | int i; 41 | int fails = 0; 42 | 43 | for (i = 0 ; i < RD_ARRAY_SIZE(match) ; i++) { 44 | m = match[i]; 45 | 46 | char *t; 47 | t = rd_strnchrs(str1, -1, d, 1); 48 | if (t != m) { 49 | printf("%s:%i: rd_strnchrs#1:%i failed: " 50 | "delimiters '%s': expected '%s' but got '%s'\n", 51 | __FUNCTION__,__LINE__, i, d, m, t); 52 | fails++; 53 | break; 54 | } 55 | d++; 56 | } 57 | 58 | str2 = "123456789"; 59 | /* Look for something outside the buffer. */ 60 | if ((m = rd_strnchrs(str2, 3, "4", 0))) { 61 | printf("%s:%i: rd_strnchrs#2 failed: " 62 | "expected nothing, but got '%s'\n", 63 | __FUNCTION__,__LINE__, m); 64 | fails++; 65 | } 66 | 67 | 68 | /* Look for something outside the buffer but with match_eol=1 */ 69 | if (!(m = rd_strnchrs(str2, 3, "4", 1)) || m != str2+3) { 70 | printf("%s:%i: rd_strnchrs#2 failed: " 71 | "expected eob, but got '%s'\n", 72 | __FUNCTION__,__LINE__, m); 73 | fails++; 74 | } 75 | 76 | /* 77 | * Test rd_strn*spn() 78 | */ 79 | str1 = "1234abcde"; 80 | if ((i = rd_strnspn(str1, strlen(str1), "1234")) != 4) { 81 | printf("%s:%i: rd_strnspn#1 failed: " 82 | "expected %i, got %i\n", 83 | __FUNCTION__,__LINE__, 4, i); 84 | fails++; 85 | } 86 | 87 | if ((i = rd_strncspn(str1, strlen(str1), "1234")) != 0) { 88 | printf("%s:%i: rd_strncspn#1 failed: " 89 | "expected %i, got %i\n", 90 | __FUNCTION__,__LINE__, 0, i); 91 | fails++; 92 | } 93 | 94 | if ((i = rd_strncspn(str1, strlen(str1), "abcd")) != 4) { 95 | printf("%s:%i: rd_strncspn#2 failed: " 96 | "expected %i, got %i\n", 97 | __FUNCTION__,__LINE__, 4, i); 98 | fails++; 99 | } 100 | 101 | if ((i = rd_strncspn(str1, strlen(str1)-2, "e")) != 7) { 102 | printf("%s:%i: rd_strncspn#3 failed: " 103 | "expected %i, got %i\n", 104 | __FUNCTION__,__LINE__, 7, i); 105 | fails++; 106 | } 107 | 108 | 109 | 110 | 111 | /* 112 | * Test rd_tsprintf() cyclicar. 113 | */ 114 | str1 = rd_tsprintf("Telma %s!", "rocks"); 115 | str2 = rd_tsprintf("%s too!", "Magda"); 116 | if (strcmp(str1, "Telma rocks!")) { 117 | printf("%s:%i: rd_tsprintf#1 failed: got '%s'\n", 118 | __FUNCTION__,__LINE__, str1); 119 | fails++; 120 | } 121 | if (strcmp(str2, "Magda too!")) { 122 | printf("%s:%i: rd_tsprintf#2 failed: got '%s'\n", 123 | __FUNCTION__,__LINE__, str2); 124 | fails++; 125 | } 126 | 127 | /* 128 | * rd_strdiffpos 129 | */ 130 | if ((i = rd_strdiffpos("Magnus", "Mike")) != 1) { 131 | printf("%s:%i: rd_strdiffpos#1 failed: expected %i, got %i\n", 132 | __FUNCTION__,__LINE__, 1, i); 133 | fails++; 134 | } 135 | 136 | if ((i = rd_strdiffpos("Magnus", "Magnus")) != -1) { 137 | printf("%s:%i: rd_strdiffpos#1 failed: expected %i, got %i\n", 138 | __FUNCTION__,__LINE__, -1, i); 139 | fails++; 140 | } 141 | 142 | if ((i = rd_strndiffpos("Magnus", 4, "Magnolia", 4)) != -1) { 143 | printf("%s:%i: rd_strdiffpos#1 failed: expected %i, got %i\n", 144 | __FUNCTION__,__LINE__, -1, i); 145 | fails++; 146 | } 147 | 148 | if ((i = rd_strndiffpos("Magnus", 6, "Magnolia", 4)) != 4) { 149 | printf("%s:%i: rd_strdiffpos#1 failed: expected %i, got %i\n", 150 | __FUNCTION__,__LINE__, 4, i); 151 | fails++; 152 | } 153 | 154 | 155 | 156 | return fails; 157 | } 158 | 159 | 160 | 161 | 162 | int main (int argc, char **argv) { 163 | int fails = 0; 164 | 165 | fails += test_string(); 166 | 167 | return fails ? 1 : 0; 168 | } 169 | -------------------------------------------------------------------------------- /rdavg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdavg.h" 31 | #include "rdtime.h" 32 | 33 | /** 34 | * NOTE: THIS IS WORK IN PROGRESS 35 | **/ 36 | 37 | 38 | rd_avg_t *rd_avg_new (rd_avg_type_t type, int periods, int duration) { 39 | rd_avg_t *ra; 40 | 41 | ra = calloc(1, sizeof(*ra)); 42 | 43 | ra->ra_type = type; 44 | ra->ra_periods = periods; 45 | ra->ra_duration = duration; 46 | return ra; 47 | } 48 | 49 | 50 | 51 | rd_avg_t *rd_avg_new_rate (int periods, int duration, int interval) { 52 | rd_avg_t *ra; 53 | 54 | if (periods < 1 || periods > 10000) { 55 | errno = EINVAL; 56 | return NULL; 57 | } 58 | 59 | ra = rd_avg_new(RD_AVG_RATE, periods, duration); 60 | 61 | ra->ra_u.rate.interval = interval; 62 | 63 | ra->ra_period = calloc(periods, sizeof(*ra->ra_period)); 64 | 65 | return ra; 66 | } 67 | 68 | static const rd_avg_res_t *rd_avg_calc (rd_avg_t *ra, rd_avg_period_t *p) { 69 | rd_avg_res_t *res = &p->res; 70 | 71 | if (p->duration == 0) { 72 | /* No data values */ 73 | no_data: 74 | memset(res, 0, sizeof(*res)); 75 | return res; 76 | } 77 | 78 | switch (ra->ra_type) 79 | { 80 | case RD_AVG_RATE: 81 | res->dbl = ((double)p->u.rate.cnt / (double)p->duration) * 82 | 1000000.0f; 83 | res->sum = p->u.rate.cnt; 84 | break; 85 | 86 | case RD_AVG_HIST: 87 | /* No average for histograms, return 0. */ 88 | goto no_data; 89 | } 90 | 91 | return res; 92 | } 93 | 94 | 95 | rd_avg_res_t rd_avg (rd_avg_t *ra, int period) { 96 | rd_avg_period_t *p; 97 | 98 | if (period == -1) 99 | period = ra->ra_curri; 100 | else if (period == -2) { 101 | if (ra->ra_curri == 0) 102 | period = ra->ra_periods-1; 103 | else 104 | period = (ra->ra_curri - 1) % ra->ra_periods; 105 | } 106 | 107 | p = &ra->ra_period[period]; 108 | 109 | if (p == ra->ra_curr) 110 | p->duration = (p->last ? : rd_clock()) - ra->ra_start; 111 | 112 | return *(rd_avg_calc(ra, p)); 113 | } 114 | 115 | 116 | static void rd_avg_period_next (rd_avg_t *ra, rd_ts_t now) { 117 | 118 | ra->ra_curri = (ra->ra_curri + 1) % ra->ra_periods; 119 | ra->ra_curr = &ra->ra_period[ra->ra_curri]; 120 | 121 | ra->ra_start = now; 122 | ra->ra_end = ra->ra_start + ra->ra_duration; 123 | 124 | memset(ra->ra_curr, 0, sizeof(*ra->ra_curr)); 125 | ra->ra_curr->res.low = RD_AVG_NO_VALUE; 126 | 127 | } 128 | 129 | void rd_avg_start (rd_avg_t *ra) { 130 | rd_avg_period_next(ra, rd_clock()); 131 | } 132 | 133 | 134 | 135 | /** 136 | * Roll-over, stop and perform average calculations on the current period. 137 | * Set up a new current period. 138 | */ 139 | static void rd_avg_roll (rd_avg_t *ra, rd_ts_t now) { 140 | int missed; 141 | 142 | /* Calculate the average */ 143 | ra->ra_curr->closed = now; 144 | ra->ra_curr->duration = (ra->ra_curr->last ? : now) - ra->ra_start; 145 | rd_avg_calc(ra, ra->ra_curr); 146 | 147 | /* Calculate missed periods */ 148 | missed = (now - ra->ra_end) / ra->ra_duration; 149 | ra->ra_curr->missed = missed; 150 | 151 | /* Call application roll callback, if any. */ 152 | if (ra->ra_roll_cb) 153 | ra->ra_roll_cb(ra, ra->ra_curri, ra->ra_opaque); 154 | 155 | /* Set up new current period */ 156 | rd_avg_period_next(ra, now); 157 | } 158 | 159 | static inline void rd_avg_put_rate (rd_avg_t *ra, uint64_t val, rd_ts_t now) { 160 | ra->ra_curr->u.rate.cnt += val; 161 | } 162 | 163 | static inline void rd_avg_put_hist (rd_avg_t *ra, uint64_t val, rd_ts_t now) { 164 | int b; 165 | 166 | b = ra->ra_u.hist.val2bucket(ra, val, ra->ra_u.hist.buckets); 167 | if (unlikely(b == -1)) 168 | return; /* Ignore data point */ 169 | 170 | ra->ra_curr->u.hist.bucket[b]++; 171 | } 172 | 173 | void rd_avg_put (rd_avg_t *ra, uint64_t val) { 174 | rd_ts_t now = rd_clock(); 175 | 176 | /* Check if current period has ended */ 177 | if (ra->ra_end <= now) 178 | rd_avg_roll(ra, now); 179 | 180 | ra->ra_curr->last = now; 181 | 182 | if (ra->ra_curr->res.high < val) 183 | ra->ra_curr->res.high = val; 184 | if (ra->ra_curr->res.low > val) 185 | ra->ra_curr->res.low = val; 186 | 187 | switch (ra->ra_type) 188 | { 189 | case RD_AVG_RATE: 190 | return rd_avg_put_rate(ra, val, now); 191 | case RD_AVG_HIST: 192 | return rd_avg_put_hist(ra, val, now); 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /rdcrc32.c: -------------------------------------------------------------------------------- 1 | /** 2 | * \file rdcrc32.c 3 | * Functions and types for CRC checks. 4 | * 5 | * Generated on Tue May 8 17:37:04 2012, 6 | * by pycrc v0.7.10, http://www.tty1.net/pycrc/ 7 | * using the configuration: 8 | * Width = 32 9 | * Poly = 0x04c11db7 10 | * XorIn = 0xffffffff 11 | * ReflectIn = True 12 | * XorOut = 0xffffffff 13 | * ReflectOut = True 14 | * Algorithm = table-driven 15 | *****************************************************************************/ 16 | #include "rdcrc32.h" /* include the header file generated with pycrc */ 17 | #include 18 | #include 19 | 20 | /** 21 | * Static table used for the table_driven implementation. 22 | *****************************************************************************/ 23 | static const rd_crc32_t crc_table[256] = { 24 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 25 | 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 26 | 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 27 | 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 28 | 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 29 | 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 30 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 31 | 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 32 | 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 33 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 34 | 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 35 | 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 36 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 37 | 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 38 | 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 39 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 40 | 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 41 | 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 42 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 43 | 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 44 | 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 45 | 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 46 | 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 47 | 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 48 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 49 | 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 50 | 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 51 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 52 | 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 53 | 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 54 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 55 | 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 56 | 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 57 | 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 58 | 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 59 | 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 60 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 61 | 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 62 | 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 63 | 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 64 | 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 65 | 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 66 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 67 | 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 68 | 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 69 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 70 | 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 71 | 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 72 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 73 | 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 74 | 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 75 | 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 76 | 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 77 | 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 78 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 79 | 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 80 | 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 81 | 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 82 | 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 83 | 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 84 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 85 | 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 86 | 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 87 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 88 | }; 89 | 90 | /** 91 | * Reflect all bits of a \a data word of \a data_len bytes. 92 | * 93 | * \param data The data word to be reflected. 94 | * \param data_len The width of \a data expressed in number of bits. 95 | * \return The reflected data. 96 | *****************************************************************************/ 97 | rd_crc32_t rd_crc32_reflect(rd_crc32_t data, size_t data_len) 98 | { 99 | unsigned int i; 100 | rd_crc32_t ret; 101 | 102 | ret = data & 0x01; 103 | for (i = 1; i < data_len; i++) { 104 | data >>= 1; 105 | ret = (ret << 1) | (data & 0x01); 106 | } 107 | return ret; 108 | } 109 | 110 | 111 | /** 112 | * Update the crc value with new data. 113 | * 114 | * \param crc The current crc value. 115 | * \param data Pointer to a buffer of \a data_len bytes. 116 | * \param data_len Number of bytes in the \a data buffer. 117 | * \return The updated crc value. 118 | *****************************************************************************/ 119 | rd_crc32_t rd_crc32_update(rd_crc32_t crc, const unsigned char *data, size_t data_len) 120 | { 121 | unsigned int tbl_idx; 122 | 123 | while (data_len--) { 124 | tbl_idx = (crc ^ *data) & 0xff; 125 | crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff; 126 | 127 | data++; 128 | } 129 | return crc & 0xffffffff; 130 | } 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /rdopt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | 32 | #define rd_opt_parse_f(f) const char *(f) (const struct rd_opt_s *ro, \ 33 | char **argv, \ 34 | int argc, int *argip, \ 35 | void *opaque) 36 | 37 | typedef struct rd_opt_s { 38 | int ro_type; /* Argument type (and attributes) */ 39 | #define RD_OPT_NIL 0x0 /* No argument. */ 40 | #define RD_OPT_END 0x1 /* Defines the end of the option list */ 41 | #define RD_OPT_REQ 0x2 /* Required option */ 42 | 43 | /* 44 | * RD_OPT_MUT1..4 - Mutual exclusivity groups 45 | * 46 | * Any options marked with the same RD_OPT_MUTn group will only 47 | * allow one of them to be seen in the argument list. 48 | * 49 | * This works as expected with RD_OPT_REQ: it will only allow one option 50 | * in a mut group to be set and it will not complain of missing .._REQ 51 | * arguments if they are in a satisfied mut group. 52 | */ 53 | #define RD_OPT_MUT1 0x10 /* Mutual exclusivity group 1 */ 54 | #define RD_OPT_MUT2 0x20 /* Mutual exclusivity group 2 */ 55 | #define RD_OPT_MUT3 0x40 /* Mutual exclusivity group 3 */ 56 | #define RD_OPT_MUT4 0x80 /* Mutual exclusivity group 4 */ 57 | 58 | /* For rdopt internal use */ 59 | #define RD_OPT_MUT_MASK 0xf0 60 | #define RD_OPT_MUT_GRP(B) (((B)&RD_OPT_MUT_MASK) >> 4) 61 | #define RD_OPT_MUT_NUM 4 62 | 63 | /* The following are for rd_opt_parse_assign() use. */ 64 | #define RD_OPT_STR 0x1000 /* String argument. opaque: char ** */ 65 | #define RD_OPT_INT 0x2000 /* Integer argument. opaque: int * */ 66 | #define RD_OPT_PATH 0x4000 /* Argument is a path that must exist. 67 | * opaque: char ** */ 68 | #define RD_OPT_BOOL 0x8000 /* Non-argument option. opaque: int * */ 69 | char ro_short; /* Short option, e.g., -s */ 70 | const char *ro_long; /* Long option, e.g., --server */ 71 | int ro_argcnt; /* Number of expected args: 0..N */ 72 | void *ro_opaque; /* Parse function opaque pointer */ 73 | const char *ro_help; /* Optional help text */ 74 | const char *ro_confname; /* Configuration token name, e.g. server*/ 75 | rd_opt_parse_f(*ro_parse); /* Parse function */ 76 | } rd_opt_t; 77 | 78 | 79 | 80 | /** 81 | * Parse the provided argument list and map it to the options defined 82 | * in 'ros'. 83 | * 84 | * Returns NULL on success or an error string on failure. 85 | * 86 | * If "--help" is encountered as an option the function returns the 87 | * literal string "(help)" without further processing, the application 88 | * should usually run rd_opt_usage() and exit in this case. 89 | * 90 | * Also see: rd_opt_get() for a common wrapper. 91 | * 92 | * NOTE: Currently treats ro_argcnt as a boolean, i.e., no support 93 | * for more than 1 argument per option. 94 | */ 95 | 96 | const char *rd_opt_parse (const rd_opt_t *ros, 97 | int argc, char **argv, int *argip); 98 | 99 | 100 | /** 101 | * Convenience wrapper for rd_opt_parse() and rd_opt_usage(), that on 102 | * failure of rd_opt_parse() prints the error message as well as the usage. 103 | * 104 | * Returns 1 on success or 0 on error. 105 | * 106 | * Example (in your main()): 107 | * if (!rd_opt_get(opts, argc, argv, &nextargi, "")) 108 | * exit(1); 109 | * 110 | */ 111 | int rd_opt_get (const rd_opt_t *ros, 112 | int argc, char **argv, int *argip, 113 | const char *extra_args); 114 | 115 | 116 | /** 117 | * Prints program command line option usage. 118 | * 'extra_args' is an optional string of non-option arguments that is appended 119 | * to the syntax description output. 120 | */ 121 | void rd_opt_usage (const rd_opt_t *ros, FILE *fp, 122 | const char *argv0, const char *extra_args); 123 | 124 | /** 125 | * Sets an optional description string that is printed with the usage 126 | * message, after the command line syntax and before the option definition. 127 | */ 128 | void rd_opt_description_set (const char *fmt, ...); 129 | 130 | 131 | /** 132 | * Standard parser that assigns the value to the specified pointer 133 | * in the ro_opaque field according to the ro_type. 134 | * 135 | * This is the default parser if 'ro_parse' is not set. 136 | */ 137 | rd_opt_parse_f(rd_opt_parse_assign); 138 | 139 | -------------------------------------------------------------------------------- /rdthread.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdthread.h" 31 | #include "rdqueue.h" 32 | #include "rdevent.h" 33 | #include "rdlog.h" 34 | 35 | #include 36 | #include 37 | 38 | rd_thread_t *rd_mainthread; 39 | __thread rd_thread_t *rd_currthread; 40 | 41 | 42 | void rd_thread_init (void) { 43 | pthread_t thr = pthread_self(); 44 | rd_mainthread = rd_thread_create0("main", &thr); 45 | rd_currthread = rd_mainthread; 46 | } 47 | 48 | int rd_thread_poll (int timeout_ms) { 49 | rd_fifoq_elm_t *rfqe; 50 | int cnt = 0; 51 | int nowait = timeout_ms == RD_POLL_NOWAIT; 52 | 53 | while ((rfqe = rd_fifoq_pop0(&rd_currthread->rdt_eventq, 54 | nowait, timeout_ms))) { 55 | rd_thread_event_t *rte = rfqe->rfqe_ptr; 56 | 57 | rd_thread_event_call(rte); 58 | 59 | rd_fifoq_elm_release(&rd_currthread->rdt_eventq, rfqe); 60 | 61 | cnt++; 62 | 63 | if (unlikely(rd_currthread->rdt_state == RD_THREAD_S_EXITING)) 64 | break; 65 | } 66 | 67 | return cnt; 68 | } 69 | 70 | 71 | static void rd_thread_destroy (rd_thread_t *rdt) { 72 | assert(rdt->rdt_state != RD_THREAD_S_RUNNING); 73 | if (rdt->rdt_name) 74 | free(rdt->rdt_name); 75 | rd_fifoq_destroy(&rdt->rdt_eventq); 76 | free(rdt); 77 | } 78 | 79 | void rd_thread_cleanup (void) { 80 | extern void rd_string_thread_cleanup (); 81 | rd_string_thread_cleanup(); 82 | } 83 | 84 | 85 | void rd_thread_dispatch (void) { 86 | 87 | while (rd_currthread->rdt_state == RD_THREAD_S_RUNNING) { 88 | /* FIXME: Proper conding for all thread inputs. */ 89 | rd_thread_poll(100); 90 | } 91 | 92 | rd_thread_cleanup(); 93 | } 94 | 95 | 96 | static void *rd_thread_start_routine (void *arg) { 97 | rd_thread_t *rdt = arg; 98 | void *ret; 99 | 100 | /* By default with block the user-defined signals. */ 101 | rd_thread_sigmask(SIG_BLOCK, SIGUSR1, SIGUSR2, RD_SIG_END); 102 | 103 | rd_currthread = rdt; 104 | 105 | ret = rdt->rdt_start(rdt->rdt_start_arg); 106 | 107 | rd_thread_cleanup(); 108 | rd_thread_destroy(rdt); 109 | 110 | return ret; 111 | } 112 | 113 | 114 | rd_thread_t *rd_thread_create0 (const char *name, pthread_t *pthread) { 115 | rd_thread_t *rdt; 116 | 117 | rdt = calloc(1, sizeof(*rdt)); 118 | 119 | if (name) 120 | rdt->rdt_name = strdup(name); 121 | 122 | rdt->rdt_state = RD_THREAD_S_RUNNING; 123 | 124 | rd_fifoq_init(&rdt->rdt_eventq); 125 | 126 | if (pthread) 127 | rdt->rdt_thread = *pthread; 128 | 129 | return rdt; 130 | } 131 | 132 | 133 | int rd_thread_create (rd_thread_t **rdt, 134 | const char *name, 135 | const pthread_attr_t *attr, 136 | void *(*start_routine)(void*), 137 | void *arg) { 138 | rd_thread_t *rdt0; 139 | 140 | rdt0 = rd_thread_create0(name, NULL); 141 | 142 | rdt0->rdt_start = start_routine; 143 | rdt0->rdt_start_arg = arg; 144 | 145 | if (rdt) 146 | *rdt = rdt0; 147 | 148 | /* FIXME: We should block all signals until pthread_create returns. */ 149 | if (pthread_create(&rdt0->rdt_thread, attr, 150 | rd_thread_start_routine, rdt0)) { 151 | int errno_save = errno; 152 | rd_thread_destroy(rdt0); 153 | if (rdt) 154 | *rdt = NULL; 155 | errno = errno_save; 156 | return -1; 157 | } 158 | 159 | #ifdef PR_SET_NAME 160 | prctl(PR_SET_NAME, (char *)rdt0->rdt_name, 0, 0, 0); 161 | #endif 162 | 163 | return 0; 164 | } 165 | 166 | 167 | int rd_threads_create (const char *nameprefix, int threadcount, 168 | const pthread_attr_t *attr, 169 | void *(*start_routine)(void*), 170 | void *arg) { 171 | int i; 172 | char *name = alloca(strlen(nameprefix) + 4); 173 | int failed = 0; 174 | 175 | if (threadcount >= 1000) { 176 | errno = E2BIG; 177 | return -1; 178 | } 179 | 180 | for (i = 0 ; i < threadcount ; i++) { 181 | sprintf(name, "%s%i", nameprefix, i); 182 | if (!rd_thread_create(NULL, name, attr, start_routine, arg)) 183 | failed++; 184 | } 185 | 186 | if (failed == threadcount) 187 | return -1; 188 | 189 | return threadcount - failed; 190 | } 191 | 192 | 193 | int rd_thread_sigmask (int how, ...) { 194 | va_list ap; 195 | sigset_t set; 196 | int sig; 197 | 198 | sigemptyset(&set); 199 | 200 | va_start(ap, how); 201 | while ((sig = va_arg(ap, int)) != RD_SIG_END) { 202 | if (sig == RD_SIG_ALL) 203 | sigfillset(&set); 204 | else 205 | sigaddset(&set, sig); 206 | } 207 | va_end(ap); 208 | 209 | return pthread_sigmask(how, &set, NULL); 210 | } 211 | 212 | -------------------------------------------------------------------------------- /rdtimer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #include "rdthread.h" 32 | #include "rdevent.h" 33 | 34 | typedef enum { 35 | RD_TIMER_ONCE, 36 | RD_TIMER_RECURR, 37 | } rd_timer_type_t; 38 | 39 | typedef struct rd_timer_s { 40 | LIST_ENTRY(rd_timer_s) rt_link; /* Waiting-to-expire list */ 41 | TAILQ_ENTRY(rd_timer_s) rt_callout_link; /* Temporary call list */ 42 | rd_thread_t *rt_thread; /* Thread to call callback in */ 43 | rd_thread_event_t rt_rte; /* Callback skeleton */ 44 | rd_timer_type_t rt_type; /* Timer type */ 45 | unsigned int rt_interval; /* Timer interval in milliseconds */ 46 | rd_ts_t rt_next; /* Calculated next firing time in 47 | * absolute timestamp (usec) */ 48 | int rt_called; /* Timer has fired and callback is 49 | * scheduled or executing. 50 | * In this state the timer will not 51 | * be freed on rd_timer_destroy(), just 52 | * flagged for future removal. 53 | * This value may be higher than one 54 | * if the timer interval is faster 55 | * than the fire events can be 56 | * handled. */ 57 | 58 | int rt_flags; 59 | #define RD_TIMER_F_ATOMIC 0x1 /* Allocated by librd, will be freed 60 | * automatically after callback has fired. 61 | * Application must not keep a reference 62 | * to the timer since it allows no such 63 | * locking. */ 64 | #define RD_TIMER_F_REMOVED 0x4 /* Timer was removed while being handled. 65 | * Real destruction is delayed. */ 66 | } rd_timer_t; 67 | 68 | 69 | extern rd_mutex_t rd_timers_lock; 70 | 71 | void rd_timer_destroy0 (rd_timer_t *rt); 72 | void rd_timer_start0 (rd_timer_t *rt, unsigned int interval_ms, 73 | int next_update); 74 | void rd_timer_stop0 (rd_timer_t *rt); 75 | 76 | static void rd_timer_init (rd_timer_t *rt, rd_timer_type_t type, 77 | rd_thread_t *rdt, rd_thread_event_f(*callback), 78 | void *ptr) RD_UNUSED; 79 | static void rd_timer_init (rd_timer_t *rt, rd_timer_type_t type, 80 | rd_thread_t *rdt, rd_thread_event_f(*callback), 81 | void *ptr) { 82 | memset(rt, 0, sizeof(*rt)); 83 | 84 | rt->rt_type = type; 85 | rt->rt_thread = rdt ? : rd_currthread_get(); 86 | rt->rt_rte.rte_callback = callback; 87 | rt->rt_rte.rte_ptr = ptr; 88 | } 89 | 90 | /** 91 | * Initializes an rd_timer_t. 92 | * It is pointless to provide an rt_thread argument here since no 93 | * threads will have been created. 94 | * Use RD_TIMER_SET_THREAD() later on instead if an alternate thread is 95 | * required. 96 | */ 97 | #define RD_TIMER_INITIALIZER(TYPE,CB,PTR) \ 98 | { rt_type: TYPE, rt_rte: { rte_callback: CB, rte_ptr: PTR } } 99 | 100 | #define RD_TIMER_SET_THREAD(rt,thread) ((rt)->rt_thread = (thread)) 101 | 102 | rd_timer_t *rd_timer_new (rd_timer_type_t type, rd_thread_t *rdt, 103 | rd_thread_event_f(*callback), void *ptr); 104 | void rd_timer_add (rd_timer_type_t type, unsigned int interval_ms, 105 | rd_thread_t *rdt, rd_thread_event_f(*callback), void *ptr); 106 | 107 | 108 | static inline void rd_timer_start (rd_timer_t *rt, unsigned int interval_ms) 109 | RD_UNUSED; 110 | static inline void rd_timer_start (rd_timer_t *rt, unsigned int interval_ms) { 111 | rd_mutex_lock(&rd_timers_lock); 112 | 113 | rt->rt_interval = interval_ms; 114 | rd_timer_start0(rt, interval_ms, 1); 115 | 116 | rd_mutex_unlock(&rd_timers_lock); 117 | } 118 | 119 | static inline void rd_timer_stop (rd_timer_t *rt) RD_UNUSED; 120 | static inline void rd_timer_stop (rd_timer_t *rt) { 121 | rd_mutex_lock(&rd_timers_lock); 122 | rd_timer_stop0(rt); 123 | rd_mutex_unlock(&rd_timers_lock); 124 | } 125 | 126 | 127 | static inline int rd_timer_next (const rd_timer_t *rt) RD_UNUSED; 128 | static inline int rd_timer_next (const rd_timer_t *rt) { 129 | rd_ts_t now; 130 | int next; 131 | 132 | rd_mutex_lock(&rd_timers_lock); 133 | 134 | if (!rt->rt_next) { 135 | /* Timer is not armed */ 136 | next = 0; 137 | } else if ((now = rd_clock()) < rt->rt_next) { 138 | /* Timer is delayed, indicate immediate firing */ 139 | next = 1; 140 | } else { 141 | next = (int)((now - rt->rt_next) / 1000); 142 | } 143 | 144 | rd_mutex_unlock(&rd_timers_lock); 145 | return next; 146 | } 147 | 148 | static inline void rd_timer_destroy (rd_timer_t *rt) RD_UNUSED; 149 | static inline void rd_timer_destroy (rd_timer_t *rt) { 150 | rd_mutex_lock(&rd_timers_lock); 151 | rd_timer_destroy0(rt); 152 | rd_mutex_unlock(&rd_timers_lock); 153 | } 154 | 155 | -------------------------------------------------------------------------------- /rdbuf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /* NOTE: rdbuf is work in progress. */ 30 | 31 | #pragma once 32 | 33 | #include 34 | #include "rdqueue.h" 35 | 36 | typedef struct rd_buf_s { 37 | TAILQ_ENTRY(rd_buf_s) rb_link; 38 | uint32_t rb_len; /* current length */ 39 | uint32_t rb_olen; /* original allocated length */ 40 | int rb_flags; 41 | #define RD_BUF_F_OWNER 0x1 42 | char *rb_data; /* Read pointer */ 43 | char *rb_orig; /* Beginning of buffer */ 44 | } rd_buf_t; 45 | 46 | 47 | #define RD_BUF_READ_SIZE 256 48 | 49 | typedef enum { 50 | RD_BUF_ERROR = 0, 51 | RD_BUF_WANT_MORE, 52 | RD_BUF_DONE, 53 | } rd_buf_status_t; 54 | 55 | 56 | /** 57 | * Decoder semantics: 58 | * rbh is always non-NULL. 59 | * rb != NULL && rb->rb_len > 0: new data received 60 | * rb != NULL && rb->rb_len == 0: recv returned 0 61 | * rb == NULL: recv returned -1 62 | * 63 | * The decoder must return with one of the rd_buf_status_t codes. 64 | */ 65 | 66 | #define rd_buf_decoder(f) \ 67 | rd_buf_status_t (f) (rd_bufh_t *rbh, rd_buf_t *rb, void *opaque) 68 | 69 | TAILQ_HEAD(rd_buf_tq_head, rd_buf_s); 70 | 71 | typedef struct rd_bufh_s { 72 | TAILQ_ENTRY(rd_buf_s) rbh_link; 73 | struct rd_buf_tq_head rbh_bufs; 74 | uint32_t rbh_len; 75 | int rbh_flags; 76 | #define RD_BUFH_F_FREE 0x1 /* Free rd_buf_t on destroy */ 77 | int rbh_read_size; 78 | void *rbh_opaque; 79 | } rd_bufh_t; 80 | 81 | typedef struct rd_bufq_s { 82 | TAILQ_HEAD(, rd_bufh_s) rbq_bufhs; 83 | int rbq_cnt; 84 | uint64_t rbq_len; 85 | } rd_bufq_t; 86 | 87 | 88 | 89 | static inline uint32_t rd_bufh_len (const rd_bufh_t *rbh) { 90 | return rbh->rbh_len; 91 | } 92 | 93 | void rd_bufh_destroy (rd_bufh_t *rbh); 94 | rd_bufh_t *rd_bufh_new (rd_bufh_t *rbh, int read_size); 95 | rd_buf_t *rd_bufh_recv (rd_bufh_t *rbh, int s, uint32_t len); 96 | rd_buf_t *rd_bufh_prepend (rd_bufh_t *rbh, void *data, uint32_t len, int flags); 97 | rd_buf_t *rd_bufh_append (rd_bufh_t *rbh, void *data, uint32_t len, int flags); 98 | 99 | rd_buf_t *rd_bufh_vsprintf (rd_bufh_t *rbh, const char *format, va_list ap); 100 | rd_buf_t *rd_bufh_sprintf (rd_bufh_t *rbh, const char *format, ...); 101 | void rd_bufh_move (rd_bufh_t *dst, rd_bufh_t *src); 102 | 103 | rd_buf_t *rd_buf_vsprintf (const char *format, va_list ap); 104 | rd_buf_t *rd_buf_sprintf (const char *format, ...); 105 | 106 | void rd_bufh_buf_insert (rd_bufh_t *rbh, rd_buf_t *after, 107 | rd_buf_t *rb); 108 | 109 | /** 110 | * The buffer writer callback writes serialized data to the destination, 111 | * whatever it may be. 112 | * It is to be called by the serializer to write out its encoded chunks. 113 | */ 114 | #define rd_bufh_writer_f(f) \ 115 | ssize_t (f) (const rd_bufh_t *rbh, void *data, size_t len, \ 116 | void *writer_opaque) 117 | 118 | /** 119 | * The buffer serializer callback encodes the buffer into a serialized form. 120 | */ 121 | #define rd_bufh_serializer_f(f) \ 122 | ssize_t (f) (const rd_bufh_t *rbh, rd_bufh_writer_f(*writer), \ 123 | size_t of, const rd_buf_t *rb, \ 124 | void *serializer_opaque, void *writer_opaque) 125 | 126 | 127 | ssize_t rd_bufh_serialize (const rd_bufh_t *rbh, 128 | rd_bufh_serializer_f(*serializer), 129 | rd_bufh_writer_f(*writer), 130 | void *serializer_opaque, 131 | void *writer_opaque); 132 | 133 | 134 | /** 135 | * Contiguous destination memory writer, 136 | * i.e. memcpy() on preallocated memory. 137 | */ 138 | rd_bufh_writer_f(rd_bufh_write_mem); 139 | 140 | /** 141 | * File descriptor writer. 142 | */ 143 | rd_bufh_writer_f(rd_bufh_write_fd); 144 | 145 | /** 146 | * Standard binary serializer that simply copies the data without alteration. 147 | */ 148 | rd_bufh_serializer_f(rd_bufh_serialize_binary); 149 | 150 | 151 | /** 152 | * Binary-serializes and writes the buffer to contiguous memory 'dst'. 153 | * i.e.: memcpy(). 154 | */ 155 | #define rd_bufh_copyout(rbh,dst) \ 156 | rd_bufh_serialize(rbh,rd_bufh_serialize_binary,rd_bufh_write_mem,\ 157 | NULL,dst) 158 | 159 | /** 160 | * Binary-serializes and writes the buffer to opened for writing 161 | * file descriptor 'fd'. 162 | * i.e: write(fd, ..) 163 | */ 164 | static ssize_t rd_bufh_writeout_fd (const rd_bufh_t *rbh, int fd) RD_UNUSED; 165 | static ssize_t rd_bufh_writeout_fd (const rd_bufh_t *rbh, int fd) { 166 | return rd_bufh_serialize(rbh, 167 | rd_bufh_serialize_binary, 168 | rd_bufh_write_fd, 169 | NULL, &fd); 170 | } 171 | 172 | void rd_bufh_dump (const char *indent, const rd_bufh_t *rbh); 173 | -------------------------------------------------------------------------------- /rdstring.c: -------------------------------------------------------------------------------- 1 | /* 2 | * librd - Rapid Development C library 3 | * 4 | * Copyright (c) 2012-2013, Magnus Edenhill 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "rd.h" 30 | #include "rdstring.h" 31 | #include "rdmem.h" 32 | 33 | /* 34 | * Thread-local states 35 | */ 36 | 37 | struct rdstr_cyclic { 38 | int size; 39 | char **buf; 40 | int *len; 41 | int i; 42 | }; 43 | 44 | static __thread struct { 45 | 46 | /* rd_tsprintf() states */ 47 | struct rdstr_cyclic tsp; 48 | } rdstr_states; 49 | 50 | 51 | /** 52 | * Initializes a cyclic state or updates it to the next index. 53 | */ 54 | static inline struct rdstr_cyclic *rdstr_cyclic_get (struct rdstr_cyclic *cyc, 55 | int size) { 56 | 57 | if (unlikely(cyc->size == 0)) { 58 | /* Not initialized. */ 59 | 60 | /* Allocate cyclic buffer array. */ 61 | cyc->size = size; 62 | cyc->buf = calloc(sizeof(*cyc->buf), cyc->size); 63 | cyc->len = calloc(sizeof(*cyc->len), cyc->size); 64 | } else /* Update to the next pointer. */ 65 | cyc->i = (cyc->i + 1) % cyc->size; 66 | 67 | return cyc; 68 | } 69 | 70 | 71 | 72 | char *rd_tsprintf (const char *format, ...) { 73 | va_list ap; 74 | int len; 75 | struct rdstr_cyclic *cyc; 76 | 77 | cyc = rdstr_cyclic_get(&rdstr_states.tsp, RD_TSPRINTF_BUFCNT); 78 | 79 | va_start(ap, format); 80 | len = vsnprintf(NULL, 0, format, ap); 81 | va_end(ap); 82 | 83 | if (len < 0) /* Error */ 84 | return NULL; 85 | 86 | len++; /* Include nul-byte */ 87 | 88 | if (cyc->buf[cyc->i] == NULL || 89 | cyc->len[cyc->i] < len || 90 | (cyc->len[cyc->i] > (len * 4) && 91 | cyc->len[cyc->i] > 64)) { 92 | if (cyc->buf[cyc->i]) 93 | free(cyc->buf[cyc->i]); 94 | 95 | cyc->len[cyc->i] = len; 96 | cyc->buf[cyc->i] = malloc(len); 97 | } 98 | 99 | 100 | va_start(ap, format); 101 | vsnprintf(cyc->buf[cyc->i], cyc->len[cyc->i], format, ap); 102 | va_end(ap); 103 | 104 | return cyc->buf[cyc->i]; 105 | } 106 | 107 | 108 | int rd_snprintf_cat (char *str, size_t size, const char *format, ...) { 109 | va_list ap; 110 | int of; 111 | 112 | of = strlen(str); 113 | 114 | if (of >= size) { 115 | errno = ERANGE; 116 | return -1; 117 | } 118 | 119 | va_start(ap, format); 120 | of += vsnprintf(str+of, size-of, format, ap); 121 | va_end(ap); 122 | 123 | return of; 124 | } 125 | 126 | 127 | void rd_string_thread_cleanup (void) { 128 | int i; 129 | struct rdstr_cyclic *cyc; 130 | 131 | /* rd_tsprintf() states */ 132 | cyc = &rdstr_states.tsp; 133 | if (cyc->size) { 134 | for (i = 0 ; i < cyc->size ; i++) 135 | if (cyc->buf[i]) 136 | free(cyc->buf[i]); 137 | 138 | free(cyc->buf); 139 | free(cyc->len); 140 | cyc->size = 0; 141 | } 142 | } 143 | 144 | 145 | 146 | char *rd_strnchrs (const char *s, ssize_t size, const char *delimiters, 147 | int match_eol) { 148 | const char *end = s + size; 149 | char map[256] = {}; 150 | 151 | while (*delimiters) { 152 | map[(int)*delimiters] = 1; 153 | delimiters++; 154 | } 155 | 156 | while ((size == -1 || s < end) && *s) { 157 | if (map[(unsigned char)*s]) 158 | return (char *)s; 159 | 160 | s++; 161 | } 162 | 163 | if (match_eol) 164 | return (char *)s; 165 | 166 | return NULL; 167 | } 168 | 169 | 170 | 171 | 172 | size_t rd_strnspn_map (const char *s, size_t size, 173 | int accept, const char map[256]) { 174 | const char *end = s + size; 175 | int cnt = 0; 176 | 177 | while ((size == -1 || s < end) && *s) { 178 | if (map[(int)*s] != accept) 179 | return cnt; 180 | s++; 181 | cnt++; 182 | } 183 | 184 | return cnt; 185 | } 186 | 187 | size_t rd_strnspn (const char *s, size_t size, const char *accept) { 188 | char map[256] = {}; 189 | 190 | while (*accept) { 191 | map[(int)*accept] = 1; 192 | accept++; 193 | } 194 | 195 | return rd_strnspn_map(s, size, 1, map); 196 | } 197 | 198 | 199 | 200 | size_t rd_strncspn (const char *s, size_t size, const char *reject) { 201 | char map[256] = {}; 202 | 203 | while (*reject) { 204 | map[(int)*reject] = 1; 205 | reject++; 206 | } 207 | 208 | return rd_strnspn_map(s, size, 0, map); 209 | } 210 | 211 | 212 | 213 | ssize_t rd_strndiffpos (const char *s1, size_t size1, 214 | const char *s2, size_t size2) { 215 | ssize_t i; 216 | size_t minlen = RD_MIN(size1, size2); 217 | 218 | for (i = 0 ; i < minlen ; i++) 219 | if (s1[i] != s2[i]) 220 | return i; 221 | 222 | if (size1 != size2) 223 | return minlen; 224 | 225 | return -1; 226 | } 227 | 228 | 229 | ssize_t rd_strdiffpos (const char *s1, const char *s2) { 230 | const char *begin = s1; 231 | 232 | while (*s1 == *s2) { 233 | if (!*s1) 234 | return -1; 235 | s1++; 236 | s2++; 237 | } 238 | 239 | return (ssize_t)(s1 - begin); 240 | } 241 | --------------------------------------------------------------------------------