├── .gitignore ├── .tarballignore ├── LICENSE ├── Makefile.am ├── README ├── THIRD-PARTY ├── arena.cc ├── atomic.cc ├── base64.cc ├── buffer.cc ├── configure.ac ├── e ├── ao_hash_map.h ├── arena.h ├── array_ptr.h ├── atomic.h ├── base64.h ├── bitsteal.h ├── buffer.h ├── compat.h ├── daemon.h ├── daemonize.h ├── endian.h ├── error.h ├── flagfd.h ├── garbage_collector.h ├── guard.h ├── hazard_ptrs.h ├── identity.h ├── intrusive_ptr.h ├── lockfile.h ├── lockfree_fifo.h ├── lockfree_hash_map.h ├── lockfree_mpsc_fifo.h ├── lookup3.h ├── nwf_hash_map.h ├── popt.h ├── pow2.h ├── safe_math.h ├── seqno_collector.h ├── serialization.h ├── slice.h ├── state_hash_table.h ├── strescape.h ├── subcommand.h ├── tuple_compare.h └── varint.h ├── endian.cc ├── error.cc ├── file_lock_table.cc ├── file_lock_table.h ├── flagfd.cc ├── garbage_collector.cc ├── identity.cc ├── libe.pc.in ├── lockfile.cc ├── lookup3-wrap.cc ├── lookup3.c ├── m4 ├── anal_warnings.m4 ├── ax_check_compile_flag.m4 ├── ax_check_link_flag.m4 └── ax_check_preproc_flag.m4 ├── seqno_collector.cc ├── serialization.cc ├── slice.cc ├── strescape.cc ├── test ├── array_ptr.cc ├── bitsteal.cc ├── buffer.cc ├── convert.cc ├── endian.cc ├── guard.cc ├── intrusive_ptr.cc ├── pow2.cc ├── runner.cc ├── safe_math.cc ├── seqno_collector.cc └── varint.cc ├── th.cc ├── th.h └── varint.cc /.gitignore: -------------------------------------------------------------------------------- 1 | # wildcards 2 | .deps 3 | .dirstamp 4 | .libs 5 | *.la 6 | *.lo 7 | *.o 8 | # specific files 9 | /aclocal.m4 10 | /autom4te.cache 11 | /compile 12 | /config.guess 13 | /config.h 14 | /config.h.in 15 | /config.log 16 | /config.status 17 | /config.sub 18 | /configure 19 | /depcomp 20 | /install-sh 21 | /libe.pc 22 | /libe.upack 23 | /libtool 24 | /ltmain.sh 25 | /m4 26 | /Makefile 27 | /Makefile.in 28 | /missing 29 | /stamp-h1 30 | /test/array_ptr 31 | /test/bitfield 32 | /test/bitsteal 33 | /test/buffer 34 | /test/convert 35 | /test/endian 36 | /test/guard 37 | /test/intrusive_ptr 38 | /test/locking_iterable_fifo 39 | /test/nonblocking_bounded_fifo 40 | /test/pow2 41 | /test/safe_math 42 | /test/seqno_collector 43 | /test/varint 44 | -------------------------------------------------------------------------------- /.tarballignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | m4/ax_check_link_flag.m4 3 | m4/ax_check_preproc_flag.m4 4 | .tarballignore 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, Robert Escriva 2 | All rights reserved. 3 | 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 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * 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 | * Neither the name of this project nor the names of its contributors 13 | may be used to endorse or promote products derived from this software 14 | without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | 3 | AM_CPPFLAGS = $(PO6_CFLAGS) 4 | AM_CFLAGS = $(PTHREAD_CFLAGS) $(WANAL_CFLAGS) 5 | AM_CXXFLAGS = $(PO6_CFLAGS) $(PTHREAD_CFLAGS) $(WANAL_CXXFLAGS) 6 | if MAKE_NO_PRINT_DIRECTORY 7 | AM_MAKEFLAGS = --no-print-directory 8 | endif 9 | 10 | EXTRA_DIST = LICENSE README THIRD-PARTY 11 | 12 | pkgconfigdir = $(libdir)/pkgconfig 13 | pkgconfig_DATA = libe.pc 14 | 15 | nobase_include_HEADERS = 16 | nobase_include_HEADERS += e/ao_hash_map.h 17 | nobase_include_HEADERS += e/arena.h 18 | nobase_include_HEADERS += e/array_ptr.h 19 | nobase_include_HEADERS += e/atomic.h 20 | nobase_include_HEADERS += e/base64.h 21 | nobase_include_HEADERS += e/bitsteal.h 22 | nobase_include_HEADERS += e/buffer.h 23 | nobase_include_HEADERS += e/compat.h 24 | nobase_include_HEADERS += e/daemon.h 25 | nobase_include_HEADERS += e/daemonize.h 26 | nobase_include_HEADERS += e/endian.h 27 | nobase_include_HEADERS += e/error.h 28 | nobase_include_HEADERS += e/flagfd.h 29 | nobase_include_HEADERS += e/garbage_collector.h 30 | nobase_include_HEADERS += e/guard.h 31 | nobase_include_HEADERS += e/hazard_ptrs.h 32 | nobase_include_HEADERS += e/identity.h 33 | nobase_include_HEADERS += e/intrusive_ptr.h 34 | nobase_include_HEADERS += e/lockfile.h 35 | nobase_include_HEADERS += e/lockfree_fifo.h 36 | nobase_include_HEADERS += e/lockfree_hash_map.h 37 | nobase_include_HEADERS += e/lockfree_mpsc_fifo.h 38 | nobase_include_HEADERS += e/lookup3.h 39 | nobase_include_HEADERS += e/nwf_hash_map.h 40 | nobase_include_HEADERS += e/popt.h 41 | nobase_include_HEADERS += e/pow2.h 42 | nobase_include_HEADERS += e/safe_math.h 43 | nobase_include_HEADERS += e/seqno_collector.h 44 | nobase_include_HEADERS += e/serialization.h 45 | nobase_include_HEADERS += e/slice.h 46 | nobase_include_HEADERS += e/state_hash_table.h 47 | nobase_include_HEADERS += e/strescape.h 48 | nobase_include_HEADERS += e/subcommand.h 49 | nobase_include_HEADERS += e/tuple_compare.h 50 | nobase_include_HEADERS += e/varint.h 51 | 52 | noinst_HEADERS = 53 | noinst_HEADERS += file_lock_table.h 54 | 55 | #################################### Source #################################### 56 | 57 | lib_LTLIBRARIES = libe.la 58 | libe_la_SOURCES = 59 | libe_la_SOURCES += arena.cc 60 | libe_la_SOURCES += atomic.cc 61 | libe_la_SOURCES += base64.cc 62 | libe_la_SOURCES += buffer.cc 63 | libe_la_SOURCES += endian.cc 64 | libe_la_SOURCES += error.cc 65 | libe_la_SOURCES += file_lock_table.cc 66 | libe_la_SOURCES += flagfd.cc 67 | libe_la_SOURCES += garbage_collector.cc 68 | libe_la_SOURCES += identity.cc 69 | libe_la_SOURCES += lockfile.cc 70 | libe_la_SOURCES += lookup3.c 71 | libe_la_SOURCES += lookup3-wrap.cc 72 | libe_la_SOURCES += seqno_collector.cc 73 | libe_la_SOURCES += serialization.cc 74 | libe_la_SOURCES += slice.cc 75 | libe_la_SOURCES += strescape.cc 76 | libe_la_SOURCES += varint.cc 77 | libe_la_LIBADD = 78 | libe_la_LIBADD += $(PO6_LIBS) 79 | libe_la_LIBADD += $(PTHREAD_LIBS) 80 | libe_la_LDFLAGS = -version-info 5:0:0 81 | 82 | ##################################### Tests #################################### 83 | 84 | th_sources = test/runner.cc th.cc th.h 85 | 86 | TESTS = $(check_PROGRAMS) 87 | check_PROGRAMS = 88 | check_PROGRAMS += test/array_ptr 89 | check_PROGRAMS += test/bitsteal 90 | check_PROGRAMS += test/buffer 91 | check_PROGRAMS += test/endian 92 | check_PROGRAMS += test/guard 93 | check_PROGRAMS += test/intrusive_ptr 94 | check_PROGRAMS += test/pow2 95 | check_PROGRAMS += test/safe_math 96 | check_PROGRAMS += test/seqno_collector 97 | check_PROGRAMS += test/varint 98 | 99 | test_array_ptr_SOURCES = test/array_ptr.cc $(th_sources) 100 | test_bitsteal_SOURCES = test/bitsteal.cc $(th_sources) 101 | test_buffer_SOURCES = test/buffer.cc $(th_sources) 102 | test_buffer_LDADD = libe.la 103 | test_endian_SOURCES = test/endian.cc $(th_sources) 104 | test_endian_LDADD = libe.la 105 | test_guard_SOURCES = test/guard.cc $(th_sources) 106 | test_intrusive_ptr_SOURCES = test/intrusive_ptr.cc $(th_sources) 107 | test_pow2_SOURCES = test/pow2.cc $(th_sources) 108 | test_safe_math_SOURCES = test/safe_math.cc $(th_sources) 109 | test_seqno_collector_SOURCES = test/seqno_collector.cc $(th_sources) 110 | test_seqno_collector_LDADD = libe.la 111 | test_varint_SOURCES = test/varint.cc $(th_sources) 112 | test_varint_LDADD = libe.la 113 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a library I use as a deposit for all the useful code snippets I use that 2 | make it easier to write robust applications quickly. 3 | -------------------------------------------------------------------------------- /THIRD-PARTY: -------------------------------------------------------------------------------- 1 | e/atomic.h: 2 | Copyright: 2006, Google Inc. 3 | License: 3-clause BSD 4 | 5 | atomic.cc: 6 | Copyright: 2007, Google Inc. 7 | License: 3-clause BSD 8 | 9 | e/varint.h: 10 | varint.cc: 11 | Copyright: 2011, Google Inc. 12 | License: 3-clause BSD 13 | 14 | lookup3.c: 15 | Copyright: 2006, Bob Jenkins 16 | License: Public Domain 17 | -------------------------------------------------------------------------------- /arena.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // e 29 | #include "e/arena.h" 30 | #include "e/buffer.h" 31 | 32 | using e::arena; 33 | 34 | arena :: arena() 35 | : m_to_free() 36 | , m_buffers() 37 | , m_start() 38 | , m_limit() 39 | { 40 | } 41 | 42 | arena :: ~arena() 43 | { 44 | for (size_t i = 0; i < m_to_free.size(); ++i) 45 | { 46 | free(m_to_free[i]); 47 | } 48 | 49 | for (size_t i = 0; i < m_buffers.size(); ++i) 50 | { 51 | delete m_buffers[i]; 52 | } 53 | } 54 | 55 | void 56 | arena :: reserve(size_t sz) 57 | { 58 | if (m_start + sz <= m_limit) 59 | { 60 | return; 61 | } 62 | 63 | unsigned char* tmp = NULL; 64 | raw_allocate(sz, &tmp); 65 | 66 | if (tmp) 67 | { 68 | m_start = tmp; 69 | m_limit = m_start + sz; 70 | } 71 | } 72 | 73 | void 74 | arena :: allocate(size_t sz, char** ptr) 75 | { 76 | return allocate(sz, reinterpret_cast(ptr)); 77 | } 78 | 79 | void 80 | arena :: allocate(size_t sz, unsigned char** ptr) 81 | { 82 | if (m_start + sz <= m_limit) 83 | { 84 | *ptr = m_start; 85 | m_start += sz; 86 | } 87 | else 88 | { 89 | raw_allocate(sz, ptr); 90 | } 91 | } 92 | 93 | void 94 | arena :: takeover(char* ptr) 95 | { 96 | takeover(reinterpret_cast(ptr)); 97 | } 98 | 99 | void 100 | arena :: takeover(unsigned char* ptr) 101 | { 102 | m_to_free.push_back(ptr); 103 | } 104 | 105 | void 106 | arena :: takeover(e::buffer* buf) 107 | { 108 | m_buffers.push_back(buf); 109 | } 110 | 111 | void 112 | arena :: clear() 113 | { 114 | for (size_t i = 0; i < m_to_free.size(); ++i) 115 | { 116 | free(m_to_free[i]); 117 | } 118 | 119 | for (size_t i = 0; i < m_buffers.size(); ++i) 120 | { 121 | delete m_buffers[i]; 122 | } 123 | } 124 | 125 | void 126 | arena :: raw_allocate(size_t sz, unsigned char** ptr) 127 | { 128 | unsigned char* tmp = reinterpret_cast(malloc(sz)); 129 | *ptr = tmp; 130 | 131 | if (tmp) 132 | { 133 | m_to_free.push_back(tmp); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /atomic.cc: -------------------------------------------------------------------------------- 1 | // This code is derived from code distributed as part of Google Perftools. 2 | // The original is available in from google-perftools-2.0 in the file 3 | // src/base/atomicops-internals-x86.cc. This file was retrieved Feb 06, 2012 by 4 | // Robert Escriva. 5 | 6 | /* Copyright (c) 2007, Google Inc. 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 11 | * met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above 16 | * copyright notice, this list of conditions and the following disclaimer 17 | * in the documentation and/or other materials provided with the 18 | * distribution. 19 | * * Neither the name of Google Inc. nor the names of its 20 | * contributors may be used to endorse or promote products derived from 21 | * this software without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | * --- 36 | * This module gets enough CPU information to optimize the 37 | * atomicops module on x86. 38 | */ 39 | 40 | // C 41 | #include 42 | 43 | // e 44 | #include "e/atomic.h" 45 | 46 | // Inline cpuid instruction. In PIC compilations, %ebx contains the address 47 | // of the global offset table. To avoid breaking such executables, this code 48 | // must preserve that register's value across cpuid instructions. 49 | #if defined(__i386__) 50 | #define cpuid(a, b, c, d, inp) \ 51 | asm ("mov %%ebx, %%edi\n" \ 52 | "cpuid\n" \ 53 | "xchg %%edi, %%ebx\n" \ 54 | : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) 55 | #elif defined (__x86_64__) 56 | #define cpuid(a, b, c, d, inp) \ 57 | asm ("mov %%rbx, %%rdi\n" \ 58 | "cpuid\n" \ 59 | "xchg %%rdi, %%rbx\n" \ 60 | : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) 61 | #endif 62 | 63 | #if defined(cpuid) // initialize the struct only on x86 64 | 65 | // Set the flags so that code will run correctly and conservatively 66 | // until InitGoogle() is called. 67 | struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = 68 | { 69 | false, // bug can't exist before process spawns multiple threads 70 | false, // no SSE2 71 | false, // no cmpxchg16b 72 | }; 73 | 74 | // Initialize the AtomicOps_Internalx86CPUFeatures struct. 75 | static void AtomicOps_Internalx86CPUFeaturesInit() 76 | { 77 | uint32_t eax; 78 | uint32_t ebx; 79 | uint32_t ecx; 80 | uint32_t edx; 81 | 82 | // Get vendor string (issue CPUID with eax = 0) 83 | cpuid(eax, ebx, ecx, edx, 0); 84 | char vendor[13]; 85 | memcpy(vendor, &ebx, 4); 86 | memcpy(vendor + 4, &edx, 4); 87 | memcpy(vendor + 8, &ecx, 4); 88 | vendor[12] = 0; 89 | 90 | // get feature flags in ecx/edx, and family/model in eax 91 | cpuid(eax, ebx, ecx, edx, 1); 92 | 93 | int family = (eax >> 8) & 0xf; // family and model fields 94 | int model = (eax >> 4) & 0xf; 95 | 96 | // use extended family and model fields 97 | if (family == 0xf) 98 | { 99 | family += (eax >> 20) & 0xff; 100 | model += ((eax >> 16) & 0xf) << 4; 101 | } 102 | 103 | // Opteron Rev E has a bug in which on very rare occasions a locked 104 | // instruction doesn't act as a read-acquire barrier if followed by a 105 | // non-locked read-modify-write instruction. Rev F has this bug in 106 | // pre-release versions, but not in versions released to customers, 107 | // so we test only for Rev E, which is family 15, model 32..63 inclusive. 108 | if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD 109 | family == 15 && 110 | 32 <= model && model <= 63) 111 | { 112 | AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true; 113 | } 114 | else 115 | { 116 | AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false; 117 | } 118 | 119 | // edx bit 26 is SSE2 which we use to tell use whether we can use mfence 120 | AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1); 121 | 122 | // ecx bit 13 indicates whether the cmpxchg16b instruction is supported 123 | AtomicOps_Internalx86CPUFeatures.has_cmpxchg16b = ((ecx >> 13) & 1); 124 | } 125 | 126 | class __attribute__ ((visibility ("hidden"))) initializer 127 | { 128 | public: 129 | initializer() { AtomicOps_Internalx86CPUFeaturesInit(); } 130 | }; 131 | 132 | static initializer init; 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /buffer.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // C 29 | #include 30 | 31 | // STL 32 | #include 33 | 34 | // e 35 | #include "e/buffer.h" 36 | 37 | using e::buffer; 38 | 39 | void* 40 | buffer :: operator new (size_t, size_t num) 41 | { 42 | return new char[offsetof(buffer, m_data) + num]; 43 | } 44 | 45 | void 46 | buffer :: operator delete (void* mem) 47 | { 48 | delete[] static_cast(mem); 49 | } 50 | 51 | buffer :: buffer(size_t sz) 52 | : m_cap(sz) 53 | , m_size(0) 54 | , m_data() 55 | { 56 | } 57 | 58 | buffer :: buffer(const char* buf, size_t sz) 59 | : m_cap(sz) 60 | , m_size(sz) 61 | , m_data() 62 | { 63 | memmove(m_data, buf, sz); 64 | } 65 | 66 | buffer :: ~buffer() throw () 67 | { 68 | } 69 | 70 | bool 71 | buffer :: cmp(const char* buf, size_t sz) const 72 | { 73 | if (m_size == sz) 74 | { 75 | return memcmp(m_data, buf, sz) == 0; 76 | } 77 | 78 | return false; 79 | } 80 | 81 | buffer* 82 | buffer :: copy() const 83 | { 84 | std::auto_ptr ret(create(m_cap)); 85 | ret->m_cap = m_cap; 86 | ret->m_size = m_size; 87 | memmove(ret->m_data, m_data, m_cap); 88 | return ret.release(); 89 | } 90 | 91 | void 92 | buffer :: resize(size_t sz) 93 | { 94 | assert(sz <= m_cap); 95 | m_size = sz; 96 | } 97 | 98 | e::packer 99 | buffer :: pack() 100 | { 101 | return pack_at(0); 102 | } 103 | 104 | e::packer 105 | buffer :: pack_at(size_t off) 106 | { 107 | return packer(this, off); 108 | } 109 | 110 | e::unpacker 111 | buffer :: unpack() 112 | { 113 | return unpack_from(0); 114 | } 115 | 116 | e::unpacker 117 | buffer :: unpack_from(size_t off) 118 | { 119 | if (off > m_size) 120 | { 121 | return e::unpacker::error_out(); 122 | } 123 | 124 | return e::unpacker(m_data + off, m_size - off); 125 | } 126 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.61]) 5 | AC_INIT([libe], [0.12.dev], [robert@hyperdex.org]) 6 | m4_define([serial_tests], [ 7 | m4_esyscmd([case `automake --version | head -n 1` in 8 | *1.11*);; 9 | *) echo serial-tests;; 10 | esac]) 11 | ]) 12 | AC_CONFIG_AUX_DIR([.]) 13 | AC_CONFIG_SRCDIR([e/buffer.h]) 14 | AC_CONFIG_HEADERS([config.h]) 15 | AC_CONFIG_MACRO_DIR([m4]) 16 | AM_INIT_AUTOMAKE(foreign serial_tests subdir-objects dist-bzip2) 17 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) 18 | LT_PREREQ([2.2]) 19 | LT_INIT 20 | 21 | # Checks for programs. 22 | AC_PROG_CXX 23 | AC_PROG_CC 24 | 25 | AS_IF([make -h 2>/dev/null | grep no-print-directory > /dev/null], [make_no_print=yes]) 26 | AM_CONDITIONAL([MAKE_NO_PRINT_DIRECTORY], [test x"${make_no_print}" != x]) 27 | 28 | ANAL_WARNINGS 29 | 30 | # Checks for libraries. 31 | PKG_CHECK_MODULES([PO6], [libpo6 >= 0.8]) 32 | 33 | # Checks for header files. 34 | AC_CHECK_HEADERS([arpa/inet.h stdint.h stdlib.h string.h]) 35 | 36 | # Checks for typedefs, structures, and compiler characteristics. 37 | AC_HEADER_STDBOOL 38 | AC_C_INLINE 39 | AC_TYPE_SIZE_T 40 | AC_TYPE_UINT16_T 41 | AC_TYPE_UINT32_T 42 | AC_TYPE_UINT64_T 43 | AC_TYPE_UINT8_T 44 | 45 | # Checks for library functions. 46 | AC_FUNC_ERROR_AT_LINE 47 | AC_CHECK_FUNCS([memchr memmove strtoul strtoull]) 48 | 49 | AC_CONFIG_FILES([Makefile 50 | libe.pc]) 51 | AC_OUTPUT 52 | -------------------------------------------------------------------------------- /e/arena.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_arena_h_ 29 | #define e_arena_h_ 30 | 31 | // C 32 | #include 33 | 34 | // STL 35 | #include 36 | 37 | namespace e 38 | { 39 | class buffer; 40 | 41 | class arena 42 | { 43 | public: 44 | arena(); 45 | ~arena(); 46 | 47 | public: 48 | void reserve(size_t sz); 49 | void allocate(size_t sz, char** ptr); 50 | void allocate(size_t sz, unsigned char** ptr); 51 | void takeover(char* ptr); 52 | void takeover(unsigned char* ptr); 53 | void takeover(void* ptr); 54 | void takeover(e::buffer* buf); 55 | void clear(); 56 | 57 | private: 58 | arena(const arena&); 59 | arena& operator = (const arena&); 60 | 61 | private: 62 | void raw_allocate(size_t sz, unsigned char** ptr); 63 | 64 | private: 65 | std::vector m_to_free; 66 | std::vector m_buffers; 67 | unsigned char* m_start; 68 | unsigned char* m_limit; 69 | }; 70 | 71 | } // namespace e 72 | 73 | #endif // e_arena_h_ 74 | -------------------------------------------------------------------------------- /e/array_ptr.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_array_ptr_h_ 29 | #define e_array_ptr_h_ 30 | 31 | // C 32 | #include 33 | 34 | #pragma GCC diagnostic push 35 | #pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" 36 | 37 | namespace e 38 | { 39 | 40 | template 41 | class array_ptr 42 | { 43 | public: 44 | array_ptr() throw () 45 | : m_ptr(0) 46 | { 47 | } 48 | 49 | explicit 50 | array_ptr(T* ptr) throw () 51 | : m_ptr(ptr) 52 | { 53 | } 54 | 55 | array_ptr(array_ptr& other) throw () 56 | : m_ptr(other.m_ptr) 57 | { 58 | other.m_ptr = NULL; 59 | } 60 | 61 | ~array_ptr() throw () 62 | { 63 | if (m_ptr) 64 | { 65 | delete[] m_ptr; 66 | } 67 | } 68 | 69 | public: 70 | T* 71 | get() const throw () 72 | { 73 | return m_ptr; 74 | } 75 | 76 | public: 77 | array_ptr& 78 | operator = (array_ptr& rhs) throw () 79 | { 80 | if (m_ptr) 81 | { 82 | delete[] m_ptr; 83 | m_ptr = NULL; 84 | } 85 | 86 | m_ptr = rhs.m_ptr; 87 | 88 | if (this != &rhs) 89 | { 90 | rhs.m_ptr = NULL; 91 | } 92 | 93 | return *this; 94 | } 95 | 96 | array_ptr& 97 | operator = (T* rhs) 98 | { 99 | if (m_ptr) 100 | { 101 | delete[] m_ptr; 102 | m_ptr = NULL; 103 | } 104 | 105 | m_ptr = rhs; 106 | return *this; 107 | } 108 | 109 | T& 110 | operator [] (size_t idx) 111 | { 112 | return m_ptr[idx]; 113 | } 114 | 115 | const T& 116 | operator [] (size_t idx) const 117 | { 118 | return m_ptr[idx]; 119 | } 120 | 121 | // Trick from the tr1 shared_ptr impl. 122 | private: 123 | typedef T* array_ptr::*bool_type; 124 | 125 | public: 126 | operator bool_type () const 127 | { 128 | return m_ptr == 0 ? 0 : &array_ptr::m_ptr; 129 | } 130 | 131 | bool 132 | operator < (const array_ptr& rhs) const 133 | { 134 | return m_ptr < rhs.m_ptr; 135 | } 136 | 137 | bool 138 | operator <= (const array_ptr& rhs) const 139 | { 140 | return m_ptr <= rhs.m_ptr; 141 | } 142 | 143 | bool 144 | operator == (const array_ptr& rhs) const 145 | { 146 | return m_ptr == rhs.m_ptr; 147 | } 148 | 149 | bool 150 | operator != (const array_ptr& rhs) const 151 | { 152 | return m_ptr != rhs.m_ptr; 153 | } 154 | 155 | bool 156 | operator >= (const array_ptr& rhs) const 157 | { 158 | return m_ptr >= rhs.m_ptr; 159 | } 160 | 161 | bool 162 | operator > (const array_ptr& rhs) const 163 | { 164 | return m_ptr > rhs.m_ptr; 165 | } 166 | 167 | private: 168 | T* m_ptr; 169 | }; 170 | 171 | } // namespace e 172 | 173 | #pragma GCC diagnostic pop 174 | 175 | #endif // e_buffer_h_ 176 | -------------------------------------------------------------------------------- /e/base64.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_base64_h_ 29 | #define e_base64_h_ 30 | 31 | namespace e 32 | { 33 | 34 | int 35 | b64_ntop(const unsigned char* src, size_t srclength, 36 | char* target, size_t targsize); 37 | 38 | int 39 | b64_pton(const char* src, 40 | unsigned char* target, size_t targsize); 41 | 42 | } // namespace e 43 | 44 | #endif // e_base64_h_ 45 | -------------------------------------------------------------------------------- /e/bitsteal.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_bitsteal_h_ 29 | #define e_bitsteal_h_ 30 | 31 | #ifndef _MSC_VER 32 | #ifndef __x86_64__ 33 | #error Bit stealing requires x86 64. 34 | #endif 35 | #endif 36 | 37 | // C 38 | #include 39 | #include 40 | #include 41 | 42 | // On current 64-bit x86 chips, only the 48 lower-order bits are used for 43 | // addressing, yet a pointer has 64 bits. Those extra 16 bits sound like a good 44 | // opportunity for extra storage which may be CASed atomically with the 45 | // pointer. Intel may not provide DCAS, but this sounds like the next best 46 | // thing. 47 | 48 | namespace e 49 | { 50 | namespace bitsteal 51 | { 52 | 53 | template 54 | inline bool 55 | get(T* t, size_t i) 56 | { 57 | assert(sizeof(T*) == sizeof(uint64_t)); 58 | assert(i < 16); 59 | uint64_t ret = reinterpret_cast(t); 60 | uint64_t bit = 1; 61 | bit <<= i + 48; 62 | return ret & bit; 63 | } 64 | 65 | template 66 | inline T* 67 | set(T* t, size_t i) 68 | { 69 | assert(sizeof(T*) == sizeof(uint64_t)); 70 | assert(i < 16); 71 | uint64_t ret = reinterpret_cast(t); 72 | uint64_t bit = 1; 73 | bit <<= i + 48; 74 | ret |= bit; 75 | return reinterpret_cast(ret); 76 | } 77 | 78 | template 79 | inline T* 80 | strip(T* t) 81 | { 82 | assert(sizeof(T*) == sizeof(uint64_t)); 83 | uint64_t ret = reinterpret_cast(t); 84 | return reinterpret_cast(0x0000ffffffffffff & ret); 85 | } 86 | 87 | template 88 | inline T* 89 | unset(T* t, size_t i) 90 | { 91 | assert(sizeof(T*) == sizeof(uint64_t)); 92 | assert(i < 16); 93 | uint64_t ret = reinterpret_cast(t); 94 | uint64_t bit = 1; 95 | bit <<= i + 48; 96 | ret &= ~bit; 97 | return reinterpret_cast(ret); 98 | } 99 | 100 | } // namespace bitsteal 101 | } // namespace e 102 | 103 | #endif // e_bitsteal_h_ 104 | -------------------------------------------------------------------------------- /e/buffer.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011-2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_buffer_h_ 29 | #define e_buffer_h_ 30 | 31 | // C 32 | #include 33 | 34 | // STL 35 | #include 36 | 37 | // e 38 | #include 39 | #include 40 | 41 | namespace e 42 | { 43 | 44 | class buffer 45 | { 46 | public: 47 | static buffer* create(size_t sz) { return new (sz) buffer(sz); } 48 | static buffer* create(const char* buf, size_t sz) { return new (sz) buffer(buf, sz); } 49 | 50 | public: 51 | void operator delete (void* mem); 52 | ~buffer() throw (); 53 | 54 | public: 55 | size_t capacity() const { return m_cap; } 56 | size_t size() const { return m_size; } 57 | const uint8_t* data() const { return m_data; } 58 | const char* cdata() const { return reinterpret_cast(m_data); } 59 | const uint8_t* end() const { return data() + m_size; } 60 | const char* cend() const { return cdata() + m_size; } 61 | uint8_t* data() { return m_data; } 62 | char* cdata() { return reinterpret_cast(m_data); } 63 | uint8_t* end() { return data() + m_size; } 64 | char* cend() { return cdata() + m_size; } 65 | bool cmp(const char* buf, size_t sz) const; 66 | e::slice as_slice() const { return e::slice(m_data, m_size); } 67 | std::string hex() const { return as_slice().hex(); } 68 | std::string b64() const { return as_slice().b64(); } 69 | e::buffer* copy() const; 70 | 71 | public: 72 | void resize(size_t size); 73 | 74 | public: 75 | e::packer pack(); 76 | e::packer pack_at(size_t off); 77 | e::unpacker unpack(); 78 | e::unpacker unpack_from(size_t off); 79 | 80 | private: 81 | void* operator new (size_t sz, size_t num); 82 | buffer(size_t sz); 83 | buffer(const char* buf, size_t sz); 84 | 85 | private: 86 | size_t m_cap; 87 | size_t m_size; 88 | uint8_t m_data[1]; 89 | }; 90 | 91 | } // namespace e 92 | 93 | #endif // e_buffer_h_ 94 | -------------------------------------------------------------------------------- /e/compat.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_compat_h_ 29 | #define e_compat_h_ 30 | 31 | // C++ 32 | #include 33 | #ifdef _LIBCPP_VERSION 34 | #include 35 | #include 36 | #else 37 | #include 38 | #include 39 | #endif 40 | 41 | namespace e 42 | { 43 | 44 | #ifdef _LIBCPP_VERSION 45 | #define BEGIN_E_COMPAT_NAMESPACE namespace std { 46 | #define END_E_COMPAT_NAMESPACE } 47 | namespace compat = ::std; 48 | #else 49 | #define BEGIN_E_COMPAT_NAMESPACE namespace std { namespace tr1 { 50 | #define END_E_COMPAT_NAMESPACE }} 51 | namespace compat = ::std::tr1; 52 | #endif 53 | 54 | } // namespace e 55 | 56 | #endif // e_compat_h_ 57 | -------------------------------------------------------------------------------- /e/daemon.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_daemon_h_ 29 | #define e_daemon_h_ 30 | 31 | // C 32 | #include 33 | #include 34 | 35 | // POSIX 36 | #include 37 | #include 38 | 39 | // STL 40 | #include 41 | 42 | // po6 43 | #include 44 | 45 | namespace e 46 | { 47 | 48 | inline bool 49 | create_pidfile(const char* path) 50 | { 51 | char buf[21]; 52 | ssize_t buf_sz = sprintf(buf, "%d\n", getpid()); 53 | assert(buf_sz < static_cast(sizeof(buf))); 54 | po6::io::fd pid(open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)); 55 | 56 | if (pid.get() < 0 || pid.xwrite(buf, buf_sz) != buf_sz) 57 | { 58 | PLOG(ERROR) << "could not create pidfile " << path; 59 | return false; 60 | } 61 | } 62 | 63 | inline bool 64 | create_pidfile(const std::string& path) 65 | { 66 | return create_pidfile(path.c_str()); 67 | } 68 | 69 | inline bool 70 | install_signal_handler(int signum, void (*f)(int)) 71 | { 72 | struct sigaction handle; 73 | handle.sa_handler = f; 74 | sigfillset(&handle.sa_mask); 75 | handle.sa_flags = SA_RESTART; 76 | return sigaction(signum, &handle, NULL) >= 0; 77 | } 78 | 79 | inline bool 80 | block_all_signals() 81 | { 82 | sigset_t ss; 83 | return sigfillset(&ss) >= 0 && 84 | pthread_sigmask(SIG_SETMASK, &ss, NULL) >= 0; 85 | } 86 | 87 | inline bool 88 | generate_token(uint64_t* token) 89 | { 90 | po6::io::fd sysrand(open("/dev/urandom", O_RDONLY)); 91 | 92 | if (sysrand.get() < 0) 93 | { 94 | return false; 95 | } 96 | 97 | if (sysrand.read(token, sizeof(*token)) != sizeof(*token)) 98 | { 99 | return false; 100 | } 101 | 102 | return true; 103 | } 104 | 105 | } // namespace e 106 | 107 | #endif // e_daemon_h_ 108 | -------------------------------------------------------------------------------- /e/daemonize.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_daemonize_h_ 29 | #define e_daemonize_h_ 30 | 31 | // C 32 | #include 33 | 34 | // STL 35 | #include 36 | 37 | // po6 38 | #include 39 | 40 | // e 41 | #include 42 | 43 | namespace e 44 | { 45 | 46 | inline bool 47 | daemonize(bool background, 48 | std::string log, 49 | std::string log_prefix, 50 | std::string pidfile, 51 | bool has_pidfile 52 | ) 53 | { 54 | google::LogToStderr(); 55 | 56 | if (background) 57 | { 58 | char buf[PATH_MAX]; 59 | char* cwd = getcwd(buf, PATH_MAX); 60 | 61 | if (!cwd) 62 | { 63 | LOG(ERROR) << "could not get current working directory"; 64 | return false; 65 | } 66 | 67 | log = po6::path::join(cwd, log); 68 | struct stat x; 69 | 70 | if (lstat(log.c_str(), &x) < 0 || !S_ISDIR(x.st_mode)) 71 | { 72 | LOG(ERROR) << "cannot fork off to the background because " 73 | << log << " does not exist or is not writable"; 74 | return false; 75 | } 76 | 77 | if (!has_pidfile) 78 | { 79 | LOG(INFO) << "forking off to the background"; 80 | LOG(INFO) << "you can find the log at " << log << "/" << log_prefix << "YYYYMMDD-HHMMSS.sssss"; 81 | LOG(INFO) << "provide \"--foreground\" on the command-line if you want to run in the foreground"; 82 | } 83 | 84 | google::SetLogSymlink(google::INFO, ""); 85 | google::SetLogSymlink(google::WARNING, ""); 86 | google::SetLogSymlink(google::ERROR, ""); 87 | google::SetLogSymlink(google::FATAL, ""); 88 | log = po6::path::join(log, log_prefix); 89 | google::SetLogDestination(google::INFO, log.c_str()); 90 | 91 | if (::daemon(1, 0) < 0) 92 | { 93 | PLOG(ERROR) << "could not daemonize"; 94 | return false; 95 | } 96 | 97 | if (has_pidfile && !create_pidfile(pidfile)) 98 | { 99 | PLOG(ERROR) << "could not create pidfile " << pidfile.c_str(); 100 | return false; 101 | } 102 | } 103 | else 104 | { 105 | LOG(INFO) << "running in the foreground"; 106 | LOG(INFO) << "no log will be generated; instead, the log messages will print to the terminal"; 107 | LOG(INFO) << "provide \"--daemon\" on the command-line if you want to run in the background"; 108 | } 109 | 110 | return true; 111 | } 112 | 113 | } // namespace e 114 | 115 | #endif // e_daemonize_h_ 116 | -------------------------------------------------------------------------------- /e/endian.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012,2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_endian_h_ 29 | #define e_endian_h_ 30 | 31 | // C 32 | #include 33 | 34 | namespace e 35 | { 36 | 37 | uint8_t* pack8be(uint8_t number, uint8_t* buffer); 38 | uint8_t* pack8le(uint8_t number, uint8_t* buffer); 39 | uint8_t* pack16be(uint16_t number, uint8_t* buffer); 40 | uint8_t* pack16le(uint16_t number, uint8_t* buffer); 41 | uint8_t* pack32be(uint32_t number, uint8_t* buffer); 42 | uint8_t* pack32le(uint32_t number, uint8_t* buffer); 43 | uint8_t* pack64be(uint64_t number, uint8_t* buffer); 44 | uint8_t* pack64le(uint64_t number, uint8_t* buffer); 45 | uint8_t* packfloatbe(float number, uint8_t* buffer); 46 | uint8_t* packfloatle(float number, uint8_t* buffer); 47 | uint8_t* packdoublebe(double number, uint8_t* buffer); 48 | uint8_t* packdoublele(double number, uint8_t* buffer); 49 | 50 | const uint8_t* unpack8be(const uint8_t* buffer, uint8_t* number); 51 | const uint8_t* unpack8le(const uint8_t* buffer, uint8_t* number); 52 | const uint8_t* unpack16be(const uint8_t* buffer, uint16_t* number); 53 | const uint8_t* unpack16le(const uint8_t* buffer, uint16_t* number); 54 | const uint8_t* unpack32be(const uint8_t* buffer, uint32_t* number); 55 | const uint8_t* unpack32le(const uint8_t* buffer, uint32_t* number); 56 | const uint8_t* unpack64be(const uint8_t* buffer, uint64_t* number); 57 | const uint8_t* unpack64le(const uint8_t* buffer, uint64_t* number); 58 | const uint8_t* unpackfloatbe(const uint8_t* buffer, float* number); 59 | const uint8_t* unpackfloatle(const uint8_t* buffer, float* number); 60 | const uint8_t* unpackdoublebe(const uint8_t* buffer, double* number); 61 | const uint8_t* unpackdoublele(const uint8_t* buffer, double* number); 62 | 63 | #define SIGNED_WRAPPER(SZ, END) \ 64 | inline const uint8_t* \ 65 | unpack ## SZ ## END(const uint8_t* buffer, int ## SZ ## _t* number) \ 66 | { \ 67 | uint ## SZ ## _t tmp; \ 68 | const uint8_t* ret = unpack ## SZ ## END(buffer, &tmp); \ 69 | *number = static_cast(tmp); \ 70 | return ret; \ 71 | } 72 | 73 | SIGNED_WRAPPER(8, be) 74 | SIGNED_WRAPPER(8, le) 75 | SIGNED_WRAPPER(16, be) 76 | SIGNED_WRAPPER(16, le) 77 | SIGNED_WRAPPER(32, be) 78 | SIGNED_WRAPPER(32, le) 79 | SIGNED_WRAPPER(64, be) 80 | SIGNED_WRAPPER(64, le) 81 | 82 | #undef SIGNED_WRAPPER 83 | 84 | #define PACKCHAR_INT_WRAPPER(SZ, END) \ 85 | inline const char* \ 86 | unpack ## SZ ## END(const char* buffer, uint ## SZ ## _t* number) \ 87 | { \ 88 | return reinterpret_cast(unpack ## SZ ## END(reinterpret_cast(buffer), number)); \ 89 | } \ 90 | inline const char* \ 91 | unpack ## SZ ## END(const char* buffer, int ## SZ ## _t* number) \ 92 | { \ 93 | return reinterpret_cast(unpack ## SZ ## END(reinterpret_cast(buffer), number)); \ 94 | } \ 95 | inline char* \ 96 | pack ## SZ ## END(int ## SZ ## _t number, char* buffer) \ 97 | { \ 98 | return reinterpret_cast(pack ## SZ ## END(number, reinterpret_cast(buffer))); \ 99 | } 100 | 101 | PACKCHAR_INT_WRAPPER(8, be) 102 | PACKCHAR_INT_WRAPPER(8, le) 103 | PACKCHAR_INT_WRAPPER(16, be) 104 | PACKCHAR_INT_WRAPPER(16, le) 105 | PACKCHAR_INT_WRAPPER(32, be) 106 | PACKCHAR_INT_WRAPPER(32, le) 107 | PACKCHAR_INT_WRAPPER(64, be) 108 | PACKCHAR_INT_WRAPPER(64, le) 109 | 110 | #undef PACKCHAR_INT_WRAPPER 111 | 112 | #define PACKCHAR_FLOAT_WRAPPER(TYPE, END) \ 113 | inline const char* \ 114 | unpack ## TYPE ## END(const char* buffer, TYPE* number) \ 115 | { \ 116 | return reinterpret_cast(unpack ## TYPE ## END(reinterpret_cast(buffer), number)); \ 117 | } \ 118 | inline char* \ 119 | pack ## TYPE ## END(TYPE number, char* buffer) \ 120 | { \ 121 | return reinterpret_cast(pack ## TYPE ## END(number, reinterpret_cast(buffer))); \ 122 | } 123 | 124 | PACKCHAR_FLOAT_WRAPPER(float, be) 125 | PACKCHAR_FLOAT_WRAPPER(float, le) 126 | PACKCHAR_FLOAT_WRAPPER(double, be) 127 | PACKCHAR_FLOAT_WRAPPER(double, le) 128 | 129 | #undef PACKCHAR_FLOAT_WRAPPER 130 | 131 | } // namespace e 132 | 133 | #endif // e_endian_h_ 134 | -------------------------------------------------------------------------------- /e/error.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_error_h_ 29 | #define e_error_h_ 30 | 31 | // C 32 | #include 33 | #include 34 | 35 | #include 36 | 37 | // STL 38 | #include 39 | #include 40 | 41 | namespace e 42 | { 43 | 44 | class error 45 | { 46 | public: 47 | error(); 48 | error(const error&); 49 | virtual ~error() throw (); 50 | 51 | public: 52 | const char* loc(); 53 | const char* msg(); 54 | void set_loc(const char* file, size_t line); 55 | std::ostream& set_msg(); 56 | 57 | public: 58 | error& operator = (const error&); 59 | 60 | private: 61 | std::ostringstream m_msg; 62 | std::string m_msg_s; 63 | std::string m_loc_s; 64 | const char* m_file; 65 | unsigned long m_line; 66 | }; 67 | 68 | } // namespace e 69 | 70 | #endif // e_error_h_ 71 | -------------------------------------------------------------------------------- /e/flagfd.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_flagfd_h_ 29 | #define e_flagfd_h_ 30 | 31 | // po6 32 | #include 33 | 34 | namespace e 35 | { 36 | 37 | class flagfd 38 | { 39 | public: 40 | flagfd(); 41 | ~flagfd() throw (); 42 | 43 | public: 44 | bool valid() const; 45 | int error() const; 46 | int poll_fd(); 47 | bool isset(); 48 | void set(); 49 | void clear(); 50 | 51 | private: 52 | po6::io::fd m_read; 53 | po6::io::fd m_write; 54 | bool m_flagged; 55 | int m_error; 56 | 57 | private: 58 | flagfd(const flagfd&); 59 | flagfd& operator = (const flagfd&); 60 | }; 61 | 62 | } // namespace e 63 | 64 | #endif // e_flagfd_h_ 65 | -------------------------------------------------------------------------------- /e/garbage_collector.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_garbage_collector_h_ 29 | #define e_garbage_collector_h_ 30 | 31 | // C 32 | #include 33 | #include 34 | 35 | // po6 36 | #include 37 | 38 | // e 39 | #include 40 | 41 | namespace e 42 | { 43 | 44 | class garbage_collector 45 | { 46 | public: 47 | class thread_state; 48 | template static void free_ptr(void* ptr) { delete static_cast(ptr); } 49 | 50 | public: 51 | garbage_collector(); 52 | ~garbage_collector() throw (); 53 | 54 | public: 55 | void register_thread(thread_state* ts); 56 | void deregister_thread(thread_state* ts); 57 | void quiescent_state(thread_state* ts); 58 | void offline(thread_state* ts); 59 | void online(thread_state* ts); 60 | void collect(void* ptr, void(*func)(void* ptr)); 61 | 62 | private: 63 | class thread_state_node; 64 | class garbage; 65 | // read_timestamp is a full-barrier operation 66 | uint64_t read_timestamp(); 67 | void enqueue(garbage** list, garbage* g); 68 | 69 | private: 70 | uint64_t m_timestamp; 71 | uint64_t m_offline_transitions; 72 | uint64_t m_minimum; 73 | thread_state_node* m_registered; 74 | garbage* m_garbage; 75 | po6::threads::mutex m_protect_registration; 76 | 77 | private: 78 | garbage_collector(const garbage_collector&); 79 | garbage_collector& operator = (const garbage_collector&); 80 | }; 81 | 82 | class garbage_collector::thread_state 83 | { 84 | public: 85 | thread_state() : m_tsn(NULL) {} 86 | ~thread_state() throw () {} 87 | 88 | private: 89 | friend class garbage_collector; 90 | thread_state_node* m_tsn; 91 | 92 | private: 93 | thread_state(const thread_state&); 94 | thread_state& operator = (const thread_state&); 95 | }; 96 | 97 | } // namespace e 98 | 99 | #endif // e_garbage_collector_h_ 100 | -------------------------------------------------------------------------------- /e/identity.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_identity_h_ 29 | #define e_identity_h_ 30 | 31 | // po6 32 | #include 33 | 34 | namespace e 35 | { 36 | 37 | bool 38 | load_identity(const char* path, bool* saved, uint64_t* id, 39 | bool set_bind_to, po6::net::location* bind_to, 40 | bool set_rendezvous, std::string* rendezvous); 41 | 42 | bool 43 | save_identity(const char* path, uint64_t id, 44 | const po6::net::location& bind_to, 45 | const std::string& rendezvous); 46 | 47 | } // namespace e 48 | 49 | #endif // e_identity_h_ 50 | -------------------------------------------------------------------------------- /e/intrusive_ptr.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_intrusive_ptr_h_ 29 | #define e_intrusive_ptr_h_ 30 | 31 | // C 32 | #include 33 | 34 | // C++ 35 | #include 36 | 37 | namespace e 38 | { 39 | 40 | // A reference-counted pointer which stores the reference count inside the 41 | // pointer. This requires you to have "void inc()" and "void dec()" functions 42 | // which increment and decrement the reference count. If the reference count 43 | // is decremented to 0, the object should delete itself. 44 | // 45 | // It is the explicit goal of this implementation to enable copies of the 46 | // intrusive pointer to be created and destroyed without requiring any 47 | // additional form of synchronization. Specifically, as long as the 48 | // intrusive_ptr that is the source of a copy operation remains valid 49 | // throughout the entire copy operation, there is no need for additional 50 | // synchronization. 51 | // 52 | // Usage tips for maximum safety: 53 | // - The reference count should start at 0 as it will be incremented. 54 | // - intrusive_ptr must be a friend of T, or at least be able to call 55 | // inc/dec. 56 | // - Only use the intrusive_ptr(T*) constructor for the initial 57 | // intrusive_ptr. All copies thereafter should come from the copy 58 | // constructor and assignment operators. 59 | // - Make sure that the intrusive_ptr you are copying from remains valid 60 | // throughout the copy. This means don't do anything like copying from an 61 | // intrusive_ptr you are going to delete from another thread. 62 | // - Destructors should never throw exceptions. The throw specifiers in here 63 | // assume that this convention is adhered to. 64 | // - Inc/Dec need to bring their own synchronization around the reference 65 | // count. 66 | 67 | template 68 | class intrusive_ptr; 69 | 70 | template 71 | std::ostream& 72 | operator << (std::ostream& lhs, const intrusive_ptr& rhs); 73 | 74 | template 75 | class intrusive_ptr 76 | { 77 | public: 78 | intrusive_ptr() throw () 79 | : m_ptr(0) 80 | { 81 | } 82 | 83 | intrusive_ptr(T* ptr) throw () 84 | : m_ptr(ptr) 85 | { 86 | if (m_ptr) 87 | { 88 | m_ptr->inc(); 89 | } 90 | } 91 | 92 | intrusive_ptr(const intrusive_ptr& rhs) throw () 93 | : m_ptr(rhs.m_ptr) 94 | { 95 | if (m_ptr) 96 | { 97 | m_ptr->inc(); 98 | } 99 | } 100 | 101 | ~intrusive_ptr() throw () 102 | { 103 | if (m_ptr) 104 | { 105 | m_ptr->dec(); 106 | } 107 | } 108 | 109 | public: 110 | T* 111 | get() const throw () 112 | { 113 | return m_ptr; 114 | } 115 | 116 | public: 117 | intrusive_ptr& 118 | operator = (const intrusive_ptr& rhs) throw () 119 | { 120 | if (m_ptr != rhs.m_ptr) 121 | { 122 | if (rhs.m_ptr) 123 | { 124 | rhs->inc(); 125 | } 126 | 127 | T* tmp = m_ptr; 128 | m_ptr = rhs.m_ptr; 129 | 130 | if (tmp) 131 | { 132 | tmp->dec(); 133 | } 134 | } 135 | 136 | return *this; 137 | } 138 | 139 | T& 140 | operator * () const throw() 141 | { 142 | return *m_ptr; 143 | } 144 | 145 | T* 146 | operator -> () const throw() 147 | { 148 | return m_ptr; 149 | } 150 | 151 | // Trick from the tr1 shared_ptr impl. 152 | private: 153 | typedef T* intrusive_ptr::*bool_type; 154 | 155 | public: 156 | operator bool_type () const 157 | { 158 | return m_ptr == 0 ? 0 : &intrusive_ptr::m_ptr; 159 | } 160 | 161 | bool 162 | operator < (const intrusive_ptr& rhs) const 163 | { 164 | return m_ptr < rhs.m_ptr; 165 | } 166 | 167 | bool 168 | operator <= (const intrusive_ptr& rhs) const 169 | { 170 | return m_ptr <= rhs.m_ptr; 171 | } 172 | 173 | bool 174 | operator == (const intrusive_ptr& rhs) const 175 | { 176 | return m_ptr == rhs.m_ptr; 177 | } 178 | 179 | bool 180 | operator != (const intrusive_ptr& rhs) const 181 | { 182 | return m_ptr != rhs.m_ptr; 183 | } 184 | 185 | bool 186 | operator >= (const intrusive_ptr& rhs) const 187 | { 188 | return m_ptr >= rhs.m_ptr; 189 | } 190 | 191 | bool 192 | operator > (const intrusive_ptr& rhs) const 193 | { 194 | return m_ptr > rhs.m_ptr; 195 | } 196 | 197 | private: 198 | friend std::ostream& operator << <>(std::ostream& lhs, const intrusive_ptr& rhs); 199 | 200 | private: 201 | T* m_ptr; 202 | }; 203 | 204 | template 205 | inline std::ostream& 206 | operator << (std::ostream& lhs, const intrusive_ptr& rhs) 207 | { 208 | lhs << rhs.m_ptr; 209 | return lhs; 210 | } 211 | 212 | } // namespace e 213 | 214 | #endif // e_buffer_h_ 215 | -------------------------------------------------------------------------------- /e/lockfile.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_lockfile_h_ 29 | #define e_lockfile_h_ 30 | 31 | // po6 32 | #include 33 | #include 34 | 35 | namespace e 36 | { 37 | 38 | class lockfile 39 | { 40 | public: 41 | lockfile(); 42 | virtual ~lockfile() throw (); 43 | 44 | public: 45 | PO6_WARN_UNUSED bool lock(const char* name); 46 | PO6_WARN_UNUSED bool lock(int fd); 47 | 48 | private: 49 | po6::io::fd m_fd; 50 | dev_t m_dev; 51 | ino_t m_ino; 52 | 53 | private: 54 | lockfile(const lockfile&); 55 | lockfile& operator = (const lockfile&); 56 | }; 57 | 58 | } // namespace e 59 | 60 | #endif // e_lockfile_h_ 61 | -------------------------------------------------------------------------------- /e/lockfree_fifo.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_lockfree_fifo_h_ 29 | #define e_lockfree_fifo_h_ 30 | 31 | // C 32 | #include 33 | 34 | // STL 35 | #include 36 | 37 | // e 38 | #include 39 | 40 | namespace e 41 | { 42 | 43 | template 44 | class lockfree_fifo 45 | { 46 | public: 47 | lockfree_fifo(); 48 | ~lockfree_fifo() throw (); 49 | 50 | public: 51 | // Return true if the queue is temporarily empty. If there are no other 52 | // operations in progress, then this will intuitively correspond to the 53 | // notion of empty() in the STL queue. 54 | bool optimistically_empty(); 55 | void push(T& val); 56 | bool pop(T* val); 57 | 58 | private: 59 | class node; 60 | 61 | private: 62 | lockfree_fifo(const lockfree_fifo&); 63 | 64 | private: 65 | lockfree_fifo& operator = (const lockfree_fifo&); 66 | 67 | private: 68 | hazard_ptrs m_hazards; 69 | node* m_head; 70 | node* m_tail; 71 | }; 72 | 73 | template 74 | lockfree_fifo :: lockfree_fifo() 75 | : m_hazards() 76 | , m_head(new node()) 77 | , m_tail(m_head) 78 | { 79 | } 80 | 81 | template 82 | lockfree_fifo :: ~lockfree_fifo() throw () 83 | { 84 | std::auto_ptr::hazard_ptr> hptr = m_hazards.get(); 85 | 86 | while (m_head) 87 | { 88 | hptr->set(0, m_head); 89 | hptr->retire(m_head); 90 | m_head = m_head->next; 91 | } 92 | } 93 | 94 | template 95 | void 96 | lockfree_fifo :: push(T& val) 97 | { 98 | std::auto_ptr::hazard_ptr> hptr = m_hazards.get(); 99 | node* tail; 100 | node* next; 101 | std::auto_ptr n(new node(NULL, val)); 102 | 103 | while (true) 104 | { 105 | tail = m_tail; 106 | hptr->set(0, tail); 107 | 108 | // Check to make sure the tail reference wasn't changed. 109 | if (tail != m_tail) 110 | { 111 | continue; 112 | } 113 | 114 | next = tail->next; 115 | 116 | // Make sure that it still hasn't changed. 117 | if (tail != m_tail) 118 | { 119 | continue; 120 | } 121 | 122 | // If we need to swing the tail pointer. 123 | if (next) 124 | { 125 | __sync_bool_compare_and_swap(&m_tail, tail, next); 126 | continue; 127 | } 128 | 129 | // Set our node as the next one. We win! 130 | if (__sync_bool_compare_and_swap(&tail->next, NULL, n.get())) 131 | { 132 | break; 133 | } 134 | } 135 | 136 | // Swing the tail pointer. 137 | __sync_bool_compare_and_swap(&m_tail, tail, n.get()); 138 | n.release(); 139 | } 140 | 141 | template 142 | bool 143 | lockfree_fifo :: pop(T* val) 144 | { 145 | std::auto_ptr::hazard_ptr> hptr = m_hazards.get(); 146 | node* head; 147 | node* tail; 148 | node* next; 149 | 150 | while (true) 151 | { 152 | head = m_head; 153 | hptr->set(0, head); 154 | 155 | // Check to make sure the head reference wasn't changed. 156 | if (head != m_head) 157 | { 158 | continue; 159 | } 160 | 161 | tail = m_tail; 162 | next = head->next; 163 | hptr->set(1, next); 164 | 165 | // Check that the head is still valid. 166 | if (head != m_head || next != head->next) 167 | { 168 | continue; 169 | } 170 | 171 | // Check if there is an element to return. 172 | if (next == NULL) 173 | { 174 | return false; 175 | } 176 | 177 | // Swing the tail. 178 | if (head == tail) 179 | { 180 | __sync_bool_compare_and_swap(&m_tail, tail, next); 181 | continue; 182 | } 183 | 184 | if (__sync_bool_compare_and_swap(&m_head, head, next)) 185 | { 186 | break; 187 | } 188 | } 189 | 190 | // XXX We should put a scope guard in place to make sure we retire head 191 | // even if the assignment fails. 192 | *val = next->data; 193 | hptr->retire(head); 194 | return true; 195 | } 196 | 197 | template 198 | class lockfree_fifo :: node 199 | { 200 | public: 201 | node() : next(NULL), data() {} 202 | node(node* n, T& d) : next(n), data(d) {} 203 | 204 | public: 205 | node* next; 206 | T data; 207 | 208 | private: 209 | node(const node&); 210 | node& operator = (const node&); 211 | }; 212 | 213 | } // namespace e 214 | 215 | #endif // e_lockfree_fifo_h_ 216 | -------------------------------------------------------------------------------- /e/lockfree_mpsc_fifo.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_lockfree_mpsc_fifo_h_ 29 | #define e_lockfree_mpsc_fifo_h_ 30 | 31 | // e 32 | #include 33 | #include 34 | 35 | namespace e 36 | { 37 | 38 | template 39 | class lockfree_mpsc_fifo 40 | { 41 | public: 42 | lockfree_mpsc_fifo(); 43 | ~lockfree_mpsc_fifo() throw (); 44 | 45 | public: 46 | void push(T* val); 47 | bool pop(e::garbage_collector* gc, T** val); 48 | 49 | private: 50 | class node; 51 | 52 | private: 53 | node* m_head; 54 | node* m_tail; 55 | 56 | private: 57 | lockfree_mpsc_fifo(const lockfree_mpsc_fifo&); 58 | lockfree_mpsc_fifo& operator = (const lockfree_mpsc_fifo&); 59 | }; 60 | 61 | template 62 | class lockfree_mpsc_fifo :: node 63 | { 64 | public: 65 | node() : next(NULL), data(NULL) {} 66 | node(T* d) : next(NULL), data(d) {} 67 | ~node() throw () { if (data) { delete data; } } 68 | 69 | public: 70 | node* next; 71 | T* data; 72 | 73 | private: 74 | node(const node&); 75 | node& operator = (const node&); 76 | }; 77 | 78 | template 79 | lockfree_mpsc_fifo :: lockfree_mpsc_fifo() 80 | : m_head(new node()) 81 | , m_tail(m_head) 82 | { 83 | atomic::memory_barrier(); 84 | } 85 | 86 | template 87 | lockfree_mpsc_fifo :: ~lockfree_mpsc_fifo() throw () 88 | { 89 | while (atomic::load_ptr_acquire(&m_head)) 90 | { 91 | node* tmp = atomic::load_ptr_acquire(&m_head); 92 | node* next = atomic::load_ptr_acquire(&tmp->next); 93 | atomic::store_ptr_nobarrier(&m_head, next); 94 | delete tmp; 95 | } 96 | } 97 | 98 | template 99 | void 100 | lockfree_mpsc_fifo :: push(T* val) 101 | { 102 | node* nn = new node(val); 103 | node* tail; 104 | 105 | while (true) 106 | { 107 | tail = atomic::load_ptr_acquire(&m_tail); 108 | node* next = atomic::compare_and_swap_ptr_fullbarrier(&tail->next, (node*)NULL, nn); 109 | 110 | if (next == NULL) 111 | { 112 | break; 113 | } 114 | else 115 | { 116 | atomic::compare_and_swap_ptr_fullbarrier(&m_tail, tail, next); 117 | } 118 | } 119 | 120 | atomic::compare_and_swap_ptr_fullbarrier(&m_tail, tail, nn); 121 | } 122 | 123 | template 124 | bool 125 | lockfree_mpsc_fifo :: pop(e::garbage_collector* gc, T** val) 126 | { 127 | atomic::memory_barrier(); 128 | node* head = atomic::load_ptr_acquire(&m_head); 129 | node* tail = atomic::load_ptr_acquire(&m_tail); 130 | node* next = atomic::load_ptr_acquire(&head->next); 131 | 132 | if (next == NULL) 133 | { 134 | return false; 135 | } 136 | 137 | if (head == tail) 138 | { 139 | atomic::compare_and_swap_ptr_fullbarrier(&m_tail, tail, next); 140 | } 141 | 142 | atomic::store_ptr_release(&m_head, next); 143 | *val = atomic::load_ptr_acquire(&next->data); 144 | atomic::store_ptr_release(&next->data, (T*)NULL); 145 | gc->collect(head, garbage_collector::free_ptr); 146 | return true; 147 | } 148 | 149 | } // namespace e 150 | 151 | #endif // e_lockfree_mpsc_fifo_h_ 152 | -------------------------------------------------------------------------------- /e/lookup3.h: -------------------------------------------------------------------------------- 1 | // Header file for lookup3.c by Bob Jenkins 2 | // lookup3.c, by Bob Jenkins, May 2006, Public Domain. 3 | 4 | #ifndef e_lookup3_h_ 5 | #define e_lookup3_h_ 6 | 7 | // C 8 | #include 9 | 10 | namespace e 11 | { 12 | 13 | // These functions wrap the lookup3.c functions provided by Bob Jenkins. The 14 | // library exposes those functions directly, but I prefer using this wrapper 15 | // instead: 16 | uint64_t lookup3_64(uint64_t in); 17 | inline uint64_t lookup3_64_ref(const uint64_t& in) { return lookup3_64(in); } 18 | 19 | } // namespace e 20 | 21 | #endif // e_lookup3_h_ 22 | -------------------------------------------------------------------------------- /e/pow2.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_pow2_h_ 29 | #define e_pow2_h_ 30 | 31 | // C 32 | #include 33 | 34 | namespace e 35 | { 36 | 37 | // Compute the next highest power of two 38 | 39 | inline uint64_t 40 | next_pow2(uint64_t in) 41 | { 42 | --in; 43 | in = (in >> 1) | in; 44 | in = (in >> 2) | in; 45 | in = (in >> 4) | in; 46 | in = (in >> 8) | in; 47 | in = (in >> 16) | in; 48 | in = (in >> 32) | in; 49 | ++in; 50 | return in; 51 | } 52 | 53 | inline bool 54 | is_pow2(uint64_t x) 55 | { 56 | return ((x != 0) && !(x & (x - 1))); 57 | } 58 | 59 | } // namespace e 60 | 61 | #endif // e_pow2_h_ 62 | -------------------------------------------------------------------------------- /e/safe_math.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_safe_math_h_ 29 | #define e_safe_math_h_ 30 | 31 | #ifndef __STDC_LIMIT_MACROS 32 | #define __STDC_LIMIT_MACROS 33 | #endif 34 | 35 | // C 36 | #include 37 | 38 | namespace e 39 | { 40 | 41 | inline bool 42 | safe_add(int64_t lhs, int64_t rhs, int64_t* result) 43 | { 44 | #ifdef _MSC_VER 45 | return false; /* not required for client */ 46 | #else 47 | uint64_t OF = 0; 48 | int64_t sum = lhs; 49 | __asm__ __volatile__("addq %2, %0\n\t" 50 | "mov $0, %%rax\n\t" 51 | "seto %%al\n\t" 52 | "movq %%rax, %1\n\t" 53 | : "+r" (sum), "=r" (OF) 54 | : "r" (rhs) 55 | : "rax"); 56 | *result = sum; 57 | return OF == 0; 58 | #endif 59 | } 60 | 61 | inline bool 62 | safe_sub(int64_t lhs, int64_t rhs, int64_t* result) 63 | { 64 | #ifdef _MSC_VER 65 | return false; 66 | #else 67 | uint64_t OF = 0; 68 | int64_t difference = lhs; 69 | __asm__ __volatile__("subq %2, %0\n\t" 70 | "mov $0, %%rax\n\t" 71 | "seto %%al\n\t" 72 | "movq %%rax, %1\n\t" 73 | : "+r" (difference), "=r" (OF) 74 | : "r" (rhs) 75 | : "rax"); 76 | *result = difference; 77 | return OF == 0; 78 | #endif 79 | } 80 | 81 | inline bool 82 | safe_mul(int64_t lhs, int64_t rhs, int64_t* result) 83 | { 84 | #ifdef _MSC_VER 85 | return false; 86 | #else 87 | uint64_t OF = 0; 88 | int64_t product = lhs; 89 | __asm__ __volatile__("imulq %2\n\t" 90 | "mov $0, %%rdx\n\t" 91 | "seto %%dl\n\t" 92 | : "+a" (product), "=d" (OF) 93 | : "r" (rhs) 94 | : ); 95 | *result = product; 96 | return OF == 0; 97 | #endif 98 | } 99 | 100 | inline bool 101 | safe_div(int64_t lhs, int64_t rhs, int64_t* result) 102 | { 103 | if (rhs == 0) 104 | { 105 | return false; 106 | } 107 | 108 | if (rhs == -1 && (lhs == INT64_MIN)) 109 | { 110 | return false; 111 | } 112 | 113 | int64_t div = lhs / rhs; 114 | int64_t mod = static_cast(lhs - static_cast(div) * rhs); 115 | 116 | if (mod && ((rhs ^ mod) < 0)) 117 | { 118 | --div; 119 | // mod += rhs; 120 | } 121 | 122 | *result = div; 123 | return true; 124 | } 125 | 126 | inline bool 127 | safe_mod(int64_t lhs, int64_t rhs, int64_t* result) 128 | { 129 | if (rhs == 0) 130 | { 131 | return false; 132 | } 133 | 134 | if (rhs == -1 && (lhs == INT64_MIN)) 135 | { 136 | return false; 137 | } 138 | 139 | int64_t div = lhs / rhs; 140 | int64_t mod = static_cast(lhs - static_cast(div) * rhs); 141 | 142 | if (mod && ((rhs ^ mod) < 0)) 143 | { 144 | --div; 145 | mod += rhs; 146 | } 147 | 148 | *result = mod; 149 | return true; 150 | } 151 | 152 | } // namespace e 153 | 154 | #endif // e_safe_math_h_ 155 | -------------------------------------------------------------------------------- /e/seqno_collector.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_seqno_collector_h_ 29 | #define e_seqno_collector_h_ 30 | 31 | // C 32 | #include 33 | 34 | // e 35 | #include 36 | #include 37 | 38 | // collect sequential identifiers in non-sequential order efficiently. 39 | // valid identifiers are any uint64_t < UINT64_MAX. 40 | // start counting at 0, and work upwards. 41 | 42 | namespace e 43 | { 44 | 45 | class seqno_collector 46 | { 47 | public: 48 | seqno_collector(garbage_collector* gc); 49 | ~seqno_collector() throw (); 50 | 51 | public: 52 | void collect(uint64_t seqno); 53 | void collect_up_to(uint64_t seqno); 54 | void lower_bound(uint64_t* seqno); 55 | 56 | private: 57 | struct run; 58 | 59 | private: 60 | run* get_run(uint64_t idx); 61 | void collect(uint64_t seqno, uint64_t idx, run* r); 62 | void compress(uint64_t idx, run* r); 63 | void set_hint(uint64_t idx); 64 | 65 | private: 66 | static uint64_t id(const uint64_t& x) { return x; } 67 | typedef nwf_hash_map run_map_t; 68 | garbage_collector* m_gc; 69 | run_map_t m_runs; 70 | uint64_t m_lb_hint; 71 | 72 | private: 73 | seqno_collector(const seqno_collector&); 74 | seqno_collector& operator = (const seqno_collector&); 75 | }; 76 | 77 | } // namespace e 78 | 79 | #endif // e_seqno_collector_h_ 80 | -------------------------------------------------------------------------------- /e/slice.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_slice_h_ 29 | #define e_slice_h_ 30 | 31 | // C 32 | #include 33 | #include 34 | #include 35 | 36 | // STL 37 | #include 38 | #include 39 | 40 | namespace e 41 | { 42 | 43 | // Refer to another piece of memory. The memory is assumed to be managed 44 | // somewhere else, and must outlive the use of all slices using it. 45 | // 46 | // Comparisons are NOT lexicographic, just guaranteed to follow be consistent. 47 | class slice 48 | { 49 | public: 50 | slice(); 51 | slice(const char* data); 52 | slice(const char* data, size_t sz); 53 | slice(const uint8_t* data, size_t sz); 54 | slice(const std::string& str); 55 | slice(const std::vector& buf); 56 | slice(const slice& other); 57 | ~slice() throw (); 58 | 59 | public: 60 | int compare(const slice& rhs) const; 61 | const uint8_t* data() const { return m_data; } 62 | const char* cdata() const { return reinterpret_cast(m_data); } 63 | bool empty() const { return m_sz == 0; } 64 | std::string hex() const; 65 | std::string b64() const; 66 | size_t size() const { return m_sz; } 67 | bool starts_with(const e::slice& other) const; 68 | std::string str() const { return std::string(cdata(), size()); } 69 | 70 | public: 71 | void advance(size_t sz); 72 | void reset(); 73 | void reset(const uint8_t* data, size_t sz); 74 | 75 | public: 76 | slice& operator = (const slice& rhs); 77 | bool operator < (const slice& rhs) const { return compare(rhs) < 0; } 78 | bool operator <= (const slice& rhs) const { return compare(rhs) <= 0; } 79 | bool operator == (const slice& rhs) const { return compare(rhs) == 0; } 80 | bool operator != (const slice& rhs) const { return compare(rhs) != 0; } 81 | bool operator >= (const slice& rhs) const { return compare(rhs) >= 0; } 82 | bool operator > (const slice& rhs) const { return compare(rhs) > 0; } 83 | 84 | private: 85 | const uint8_t* m_data; 86 | size_t m_sz; 87 | }; 88 | 89 | } // namespace e 90 | 91 | #endif // e_slice_h_ 92 | -------------------------------------------------------------------------------- /e/strescape.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013,2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_strescape_h_ 29 | #define e_strescape_h_ 30 | 31 | // STL 32 | #include 33 | 34 | namespace e 35 | { 36 | 37 | std::string 38 | strescape(const std::string& input); 39 | 40 | } // namespace e 41 | 42 | #endif // e_strescape_h_ 43 | -------------------------------------------------------------------------------- /e/tuple_compare.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_tuple_compare_h_ 29 | #define e_tuple_compare_h_ 30 | 31 | namespace e 32 | { 33 | 34 | template 35 | int 36 | tuple_compare(const T1& lhs1, const T1& rhs1) 37 | { 38 | if (lhs1 < rhs1) 39 | { 40 | return -1; 41 | } 42 | else if (lhs1 > rhs1) 43 | { 44 | return 1; 45 | } 46 | else 47 | { 48 | return 0; 49 | } 50 | } 51 | 52 | template 53 | int 54 | tuple_compare(const T1& lhs1, const T2& lhs2, 55 | const T1& rhs1, const T2& rhs2) 56 | { 57 | int prefix = tuple_compare(lhs1, rhs1); 58 | 59 | if (prefix == 0) 60 | { 61 | return tuple_compare(lhs2, rhs2); 62 | } 63 | else 64 | { 65 | return prefix; 66 | } 67 | } 68 | 69 | template 70 | int 71 | tuple_compare(const T1& lhs1, const T2& lhs2, const T3& lhs3, 72 | const T1& rhs1, const T2& rhs2, const T3& rhs3) 73 | { 74 | int prefix = tuple_compare(lhs1, lhs2, rhs1, rhs2); 75 | 76 | if (prefix == 0) 77 | { 78 | return tuple_compare(lhs3, rhs3); 79 | } 80 | else 81 | { 82 | return prefix; 83 | } 84 | } 85 | 86 | template 87 | int 88 | tuple_compare(const T1& lhs1, const T2& lhs2, const T3& lhs3, const T4& lhs4, 89 | const T1& rhs1, const T2& rhs2, const T3& rhs3, const T4& rhs4) 90 | { 91 | int prefix = tuple_compare(lhs1, lhs2, lhs3, rhs1, rhs2, rhs3); 92 | 93 | if (prefix == 0) 94 | { 95 | return tuple_compare(lhs4, rhs4); 96 | } 97 | else 98 | { 99 | return prefix; 100 | } 101 | } 102 | 103 | template 104 | int 105 | tuple_compare(const T1& lhs1, const T2& lhs2, const T3& lhs3, const T4& lhs4, const T5& lhs5, 106 | const T1& rhs1, const T2& rhs2, const T3& rhs3, const T4& rhs4, const T5& rhs5) 107 | { 108 | int prefix = tuple_compare(lhs1, lhs2, lhs3, lhs4, rhs1, rhs2, rhs3, rhs4); 109 | 110 | if (prefix == 0) 111 | { 112 | return tuple_compare(lhs5, rhs5); 113 | } 114 | else 115 | { 116 | return prefix; 117 | } 118 | } 119 | 120 | template 121 | int 122 | tuple_compare(const T1& lhs1, const T2& lhs2, const T3& lhs3, const T4& lhs4, const T5& lhs5, const T6& lhs6, 123 | const T1& rhs1, const T2& rhs2, const T3& rhs3, const T4& rhs4, const T5& rhs5, const T6& rhs6) 124 | { 125 | int prefix = tuple_compare(lhs1, lhs2, lhs3, lhs4, lhs5, 126 | rhs1, rhs2, rhs3, rhs4, rhs5); 127 | 128 | if (prefix == 0) 129 | { 130 | return tuple_compare(lhs6, rhs6); 131 | } 132 | else 133 | { 134 | return prefix; 135 | } 136 | } 137 | 138 | } // namespace e 139 | 140 | #endif // e_tuple_compare_h_ 141 | -------------------------------------------------------------------------------- /e/varint.h: -------------------------------------------------------------------------------- 1 | // This code is derived from code distributed as part of Google LevelDB. 2 | // The original is available in leveldb as util/coding.h. 3 | // This file was retrieved Jul 15, 2013 by Robert Escriva. 4 | 5 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | // 9 | // Endian-neutral encoding: 10 | // * Fixed-length numbers are encoded with least-significant byte first 11 | // * In addition we support variable length "varint" encoding 12 | // * Strings are encoded prefixed by their length in varint format 13 | 14 | #ifndef e_varint_h_ 15 | #define e_varint_h_ 16 | 17 | #include 18 | 19 | namespace e 20 | { 21 | 22 | #define VARINT_32_MAX_SIZE 5 23 | #define VARINT_64_MAX_SIZE 10 24 | 25 | // These either store a value in *v and return a pointer just past the parsed 26 | // value, or return NULL on error. These routines only look at bytes in the 27 | // range [p..limit-1] 28 | const char* 29 | varint32_decode(const char* p,const char* limit, uint32_t* v); 30 | const char* 31 | varint64_decode(const char* p,const char* limit, uint64_t* v); 32 | 33 | inline const unsigned char* 34 | varint32_decode(const unsigned char* p,const unsigned char* limit, uint32_t* v) 35 | { 36 | return reinterpret_cast(varint32_decode( 37 | reinterpret_cast(p), 38 | reinterpret_cast(limit), v)); 39 | } 40 | 41 | inline const unsigned char* 42 | varint64_decode(const unsigned char* p,const unsigned char* limit, uint64_t* v) 43 | { 44 | return reinterpret_cast(varint64_decode( 45 | reinterpret_cast(p), 46 | reinterpret_cast(limit), v)); 47 | } 48 | 49 | // Write directly into a character buffer and return a pointer just past the 50 | // last byte written. 51 | // REQUIRES: dst has enough space for the value being written 52 | char* 53 | varint32_encode(char* dst, uint32_t value); 54 | char* 55 | varint64_encode(char* dst, uint64_t value); 56 | 57 | // Returns the length of the varint32 or varint64 encoding of "v" 58 | inline int 59 | varint_length(uint64_t v) 60 | { 61 | int len = 1; 62 | 63 | while (v >= 128) 64 | { 65 | v >>= 7; 66 | len++; 67 | } 68 | 69 | return len; 70 | } 71 | 72 | // Helpful wrappers to match conventions from elsewhwere 73 | 74 | inline char* 75 | packvarint64(uint64_t value, char* ptr) 76 | { 77 | return varint64_encode(ptr, value); 78 | } 79 | 80 | inline char* 81 | packvarint32(uint32_t value, char* ptr) 82 | { 83 | return varint32_encode(ptr, value); 84 | } 85 | 86 | inline unsigned char* 87 | packvarint64(uint64_t value, unsigned char* ptr) 88 | { 89 | return reinterpret_cast(packvarint64(value, reinterpret_cast(ptr))); 90 | } 91 | 92 | inline unsigned char* 93 | packvarint32(uint32_t value, unsigned char* ptr) 94 | { 95 | return reinterpret_cast(packvarint32(value, reinterpret_cast(ptr))); 96 | } 97 | 98 | } // namespace e 99 | 100 | #endif // e_varint_h_ 101 | -------------------------------------------------------------------------------- /error.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // e 29 | #include "e/error.h" 30 | 31 | using e::error; 32 | 33 | error :: error() 34 | : m_msg() 35 | , m_msg_s() 36 | , m_loc_s() 37 | , m_file("") 38 | , m_line(0) 39 | { 40 | } 41 | 42 | error :: error(const error& other) 43 | : m_msg(other.m_msg.str()) 44 | , m_msg_s(other.m_msg_s) 45 | , m_loc_s(other.m_loc_s) 46 | , m_file(other.m_file) 47 | , m_line(other.m_line) 48 | { 49 | } 50 | 51 | error :: ~error() throw () 52 | { 53 | } 54 | 55 | const char* 56 | error :: loc() 57 | { 58 | char buf[21]; 59 | snprintf(buf, 21, "%lu", m_line); 60 | m_loc_s = m_file; 61 | m_loc_s += ":"; 62 | m_loc_s += buf; 63 | return m_loc_s.c_str(); 64 | } 65 | 66 | const char* 67 | error :: msg() 68 | { 69 | m_msg_s = m_msg.str(); 70 | return m_msg_s.c_str(); 71 | } 72 | 73 | void 74 | error :: set_loc(const char* file, size_t line) 75 | { 76 | m_file = file; 77 | m_line = line; 78 | } 79 | 80 | std::ostream& 81 | error :: set_msg() 82 | { 83 | m_msg.str(""); 84 | m_msg.clear(); 85 | return m_msg; 86 | } 87 | 88 | error& 89 | error :: operator = (const error& rhs) 90 | { 91 | if (this != &rhs) 92 | { 93 | m_msg.str(rhs.m_msg.str()); 94 | m_msg.clear(); 95 | m_msg_s = rhs.m_msg_s; 96 | m_loc_s = rhs.m_loc_s; 97 | m_file = rhs.m_file; 98 | m_line = rhs.m_line; 99 | } 100 | 101 | return *this; 102 | } 103 | -------------------------------------------------------------------------------- /file_lock_table.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // e 29 | #include "file_lock_table.h" 30 | 31 | using e::file_lock_table; 32 | 33 | static file_lock_table _neo; 34 | 35 | file_lock_table* 36 | file_lock_table :: the_one_and_only() 37 | { 38 | return &_neo; 39 | } 40 | 41 | file_lock_table :: file_lock_table() 42 | : m_mtx() 43 | , m_files() 44 | { 45 | } 46 | 47 | file_lock_table :: ~file_lock_table() throw () 48 | { 49 | } 50 | 51 | bool 52 | file_lock_table :: acquire(dev_t dev, ino_t ino) 53 | { 54 | po6::threads::mutex::hold hold(&m_mtx); 55 | file_t key(dev, ino); 56 | std::pair x = m_files.insert(key); 57 | return x.second; 58 | } 59 | 60 | void 61 | file_lock_table :: release(dev_t dev, ino_t ino) 62 | { 63 | po6::threads::mutex::hold hold(&m_mtx); 64 | file_t key(dev, ino); 65 | file_map_t::iterator it = m_files.find(key); 66 | 67 | if (it != m_files.end()) 68 | { 69 | m_files.erase(it); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /file_lock_table.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #ifndef e_file_lock_table_h_ 29 | #define e_file_lock_table_h_ 30 | 31 | // POSIX 32 | #include 33 | 34 | // STL 35 | #include 36 | 37 | // po6 38 | #include 39 | 40 | namespace e 41 | { 42 | 43 | class file_lock_table 44 | { 45 | public: 46 | static file_lock_table* the_one_and_only(); 47 | 48 | public: 49 | file_lock_table(); 50 | ~file_lock_table() throw (); 51 | 52 | public: 53 | bool acquire(dev_t dev, ino_t ino); 54 | void release(dev_t dev, ino_t ino); 55 | 56 | private: 57 | typedef std::pair file_t; 58 | typedef std::set file_map_t; 59 | po6::threads::mutex m_mtx; 60 | file_map_t m_files; 61 | 62 | private: 63 | file_lock_table(const file_lock_table&); 64 | file_lock_table& operator = (const file_lock_table&); 65 | }; 66 | 67 | } // namespace e 68 | 69 | #endif // e_file_lock_table_h_ 70 | -------------------------------------------------------------------------------- /flagfd.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // POSIX 29 | #include 30 | #include 31 | 32 | // e 33 | #include "e/flagfd.h" 34 | 35 | using e::flagfd; 36 | 37 | flagfd :: flagfd() 38 | : m_read() 39 | , m_write() 40 | , m_flagged(false) 41 | , m_error(0) 42 | { 43 | int fds[2]; 44 | 45 | if (pipe(fds) < 0) 46 | { 47 | m_error = errno; 48 | return; 49 | } 50 | 51 | m_read = fds[0]; 52 | m_write = fds[1]; 53 | } 54 | 55 | flagfd :: ~flagfd() throw () 56 | { 57 | } 58 | 59 | bool 60 | flagfd :: valid() const 61 | { 62 | return m_read.get() >= 0; 63 | } 64 | 65 | int 66 | flagfd :: error() const 67 | { 68 | return m_error; 69 | } 70 | 71 | int 72 | flagfd :: poll_fd() 73 | { 74 | return m_read.get(); 75 | } 76 | 77 | bool 78 | flagfd :: isset() 79 | { 80 | return m_flagged; 81 | } 82 | 83 | void 84 | flagfd :: set() 85 | { 86 | if (!m_flagged) 87 | { 88 | char c = 'A'; 89 | PO6_EXPLICITLY_IGNORE(m_write.xwrite(&c, 1)); 90 | } 91 | 92 | m_flagged = true; 93 | } 94 | 95 | void 96 | flagfd :: clear() 97 | { 98 | if (m_flagged) 99 | { 100 | char buf[32]; 101 | 102 | while (m_read.read(buf, 32) == 32) 103 | ; 104 | } 105 | 106 | m_flagged = false; 107 | } 108 | -------------------------------------------------------------------------------- /identity.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // C 29 | #include 30 | #include 31 | #include 32 | 33 | // POSIX 34 | #include 35 | 36 | // STL 37 | #include 38 | #include 39 | #include 40 | 41 | // po6 42 | #include 43 | 44 | // e 45 | #include "e/identity.h" 46 | 47 | static bool 48 | atomic_read(const char* path, std::string* contents) 49 | { 50 | contents->clear(); 51 | po6::io::fd fd(open(path, O_RDONLY)); 52 | 53 | if (fd.get() < 0) 54 | { 55 | return false; 56 | } 57 | 58 | char buf[512]; 59 | ssize_t amt; 60 | 61 | while ((amt = fd.xread(buf, 512)) > 0) 62 | { 63 | contents->append(buf, amt); 64 | } 65 | 66 | return amt == 0; 67 | } 68 | 69 | static bool 70 | atomic_write(const char* path, const std::string& contents) 71 | { 72 | std::string tmp(path); 73 | tmp += ".tmp"; 74 | po6::io::fd fd(open(tmp.c_str(), O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)); 75 | return fd.get() >= 0 && 76 | fd.xwrite(contents.data(), contents.size()) == ssize_t(contents.size()) && 77 | fsync(fd.get()) >= 0 && 78 | rename(tmp.c_str(), path) >= 0; 79 | } 80 | 81 | bool 82 | e :: load_identity(const char* path, bool* saved, uint64_t* id, 83 | bool set_bind_to, po6::net::location* bind_to, 84 | bool set_rendezvous, std::string* rendezvous) 85 | { 86 | std::string ident; 87 | 88 | if (!atomic_read(path, &ident)) 89 | { 90 | if (errno != ENOENT) 91 | { 92 | return false; 93 | } 94 | 95 | *saved = false; 96 | return true; 97 | } 98 | 99 | *saved = true; 100 | std::vector buf(ident.c_str(), ident.c_str() + ident.size() + 1); 101 | const char* ptr = &buf[0]; 102 | const char* const end = ptr + buf.size(); 103 | const char* eol = NULL; 104 | char* tmp = NULL; 105 | 106 | if (strncmp(ptr, "id=", 3) != 0) 107 | { 108 | return false; 109 | } 110 | 111 | ptr += 3; 112 | errno = 0; 113 | *id = strtoull(ptr, &tmp, 10); 114 | 115 | if (errno != 0 || *tmp != '\n') 116 | { 117 | return false; 118 | } 119 | 120 | *tmp = '\0'; 121 | ptr = tmp + 1; 122 | 123 | if (strncmp(ptr, "bind_to=", 8) != 0) 124 | { 125 | return false; 126 | } 127 | 128 | ptr += 8; 129 | eol = strchr(ptr, '\n'); 130 | 131 | if (!eol) 132 | { 133 | return false; 134 | } 135 | 136 | tmp = &buf[0] + (eol - &buf[0]); 137 | *tmp = '\0'; 138 | const char* colon = strrchr(ptr, ':'); 139 | 140 | if (!colon) 141 | { 142 | return false; 143 | } 144 | 145 | errno = 0; 146 | unsigned long port = strtoul(colon + 1, &tmp, 10); 147 | 148 | if (errno != 0 || *tmp != '\0') 149 | { 150 | return false; 151 | } 152 | 153 | std::string host; 154 | 155 | if (*ptr == '[' && colon > ptr && *(colon - 1) == ']') 156 | { 157 | host.assign(ptr + 1, colon - 1); 158 | } 159 | else 160 | { 161 | host.assign(ptr, colon); 162 | } 163 | 164 | if (!set_bind_to) 165 | { 166 | if (!bind_to->set(host.c_str(), port)) 167 | { 168 | return false; 169 | } 170 | } 171 | 172 | ptr = eol + 1; 173 | 174 | if (ptr < end && !set_rendezvous) 175 | { 176 | eol = strchr(ptr, '\n'); 177 | eol = eol ? eol : end; 178 | *rendezvous = std::string(ptr, eol); 179 | } 180 | 181 | return true; 182 | } 183 | 184 | bool 185 | e :: save_identity(const char* path, uint64_t id, 186 | const po6::net::location& bind_to, 187 | const std::string& rendezvous) 188 | { 189 | std::ostringstream ostr; 190 | ostr << "id=" << id << "\n" 191 | << "bind_to=" << bind_to << "\n" 192 | << rendezvous << "\n"; 193 | return atomic_write(path, ostr.str()); 194 | } 195 | -------------------------------------------------------------------------------- /libe.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libe 7 | Description: C++ systems-building utilities 8 | Version: @VERSION@ 9 | 10 | Requires: libpo6 >= 0.3.1 11 | Libs: -L${libdir} -le 12 | Cflags: -I${includedir} 13 | -------------------------------------------------------------------------------- /lockfile.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // C 29 | #include 30 | #include 31 | 32 | // POSIX 33 | #include 34 | #include 35 | #include 36 | 37 | // e 38 | #include "e/lockfile.h" 39 | #include "file_lock_table.h" 40 | 41 | using e::lockfile; 42 | 43 | lockfile :: lockfile() 44 | : m_fd() 45 | , m_dev(0) 46 | , m_ino(0) 47 | { 48 | } 49 | 50 | lockfile :: ~lockfile() throw () 51 | { 52 | if (m_fd.get()) 53 | { 54 | file_lock_table* flt = file_lock_table::the_one_and_only(); 55 | assert(flt); 56 | flt->release(m_dev, m_ino); 57 | } 58 | } 59 | 60 | bool 61 | lockfile :: lock(const char* name) 62 | { 63 | int fd = open(name, O_RDWR|O_CREAT, S_IRWXU); 64 | 65 | if (fd < 0) 66 | { 67 | return false; 68 | } 69 | 70 | if (!lock(fd)) 71 | { 72 | close(fd); 73 | return false; 74 | } 75 | 76 | return true; 77 | } 78 | 79 | bool 80 | lockfile :: lock(int fd) 81 | { 82 | assert(fd >= 0); 83 | assert(m_fd.get() < 0); 84 | m_fd = fd; 85 | struct stat stbuf; 86 | 87 | if (fstat(m_fd.get(), &stbuf) < 0) 88 | { 89 | m_fd.close(); 90 | return false; 91 | } 92 | 93 | m_dev = stbuf.st_dev; 94 | m_ino = stbuf.st_ino; 95 | file_lock_table* flt = file_lock_table::the_one_and_only(); 96 | assert(flt); 97 | 98 | struct flock f; 99 | memset(&f, 0, sizeof(f)); 100 | f.l_type = F_WRLCK; 101 | f.l_whence = SEEK_SET; 102 | f.l_start = 0; 103 | f.l_len = 0; 104 | 105 | if (fcntl(m_fd.get(), F_SETLK, &f) < 0 || 106 | !flt->acquire(m_dev, m_ino)) 107 | { 108 | m_fd.close(); 109 | return false; 110 | } 111 | 112 | return true; 113 | } 114 | 115 | #if 0 116 | 117 | 118 | m_dir_fd = dir_fd; 119 | m_lock_fd = lock_fd; 120 | m_lock_dev = stbuf.st_dev; 121 | m_lock_ino = stbuf.st_ino; 122 | g_flt.dismiss(); 123 | g_lock_fd.dismiss(); 124 | g_dir_fd.dismiss(); 125 | return true; 126 | #endif 127 | -------------------------------------------------------------------------------- /lookup3-wrap.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // C 29 | #include 30 | 31 | // e 32 | #include 33 | 34 | // Declare the C functions 35 | extern "C" 36 | { 37 | 38 | void 39 | hashlittle2(const void* key, size_t length, uint32_t* pc, uint32_t* pb); 40 | 41 | } // extern "C" 42 | 43 | uint64_t 44 | e :: lookup3_64(uint64_t in) 45 | { 46 | uint32_t pc = 0; 47 | uint32_t pb = 0; 48 | hashlittle2(&in, sizeof(in), &pc, &pb); 49 | uint64_t out = pc; 50 | out <<= 32; 51 | out |= pb; 52 | return out; 53 | } 54 | -------------------------------------------------------------------------------- /m4/ax_check_compile_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's compiler 12 | # or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the current language's default 18 | # flags (e.g. CFLAGS) when the check is done. The check is thus made with 19 | # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 20 | # force the compiler to issue an error when a bad flag is given. 21 | # 22 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 23 | # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 24 | # 25 | # LICENSE 26 | # 27 | # Copyright (c) 2008 Guido U. Draheim 28 | # Copyright (c) 2011 Maarten Bosmans 29 | # 30 | # This program is free software: you can redistribute it and/or modify it 31 | # under the terms of the GNU General Public License as published by the 32 | # Free Software Foundation, either version 3 of the License, or (at your 33 | # option) any later version. 34 | # 35 | # This program is distributed in the hope that it will be useful, but 36 | # WITHOUT ANY WARRANTY; without even the implied warranty of 37 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 38 | # Public License for more details. 39 | # 40 | # You should have received a copy of the GNU General Public License along 41 | # with this program. If not, see . 42 | # 43 | # As a special exception, the respective Autoconf Macro's copyright owner 44 | # gives unlimited permission to copy, distribute and modify the configure 45 | # scripts that are the output of Autoconf when processing the Macro. You 46 | # need not follow the terms of the GNU General Public License when using 47 | # or distributing such scripts, even though portions of the text of the 48 | # Macro appear in them. The GNU General Public License (GPL) does govern 49 | # all other use of the material that constitutes the Autoconf Macro. 50 | # 51 | # This special exception to the GPL applies to versions of the Autoconf 52 | # Macro released by the Autoconf Archive. When you make and distribute a 53 | # modified version of the Autoconf Macro, you may extend this special 54 | # exception to the GPL to apply to your modified version as well. 55 | 56 | #serial 2 57 | 58 | AC_DEFUN([AX_CHECK_COMPILE_FLAG], 59 | [AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX 60 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl 61 | AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ 62 | ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 63 | _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" 64 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], 65 | [AS_VAR_SET(CACHEVAR,[yes])], 66 | [AS_VAR_SET(CACHEVAR,[no])]) 67 | _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) 68 | AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], 69 | [m4_default([$2], :)], 70 | [m4_default([$3], :)]) 71 | AS_VAR_POPDEF([CACHEVAR])dnl 72 | ])dnl AX_CHECK_COMPILE_FLAGS 73 | -------------------------------------------------------------------------------- /m4/ax_check_link_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the linker or gives an error. 12 | # (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the linker's default flags 18 | # when the check is done. The check is thus made with the flags: "LDFLAGS 19 | # EXTRA-FLAGS FLAG". This can for example be used to force the linker to 20 | # issue an error when a bad flag is given. 21 | # 22 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 23 | # macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. 24 | # 25 | # LICENSE 26 | # 27 | # Copyright (c) 2008 Guido U. Draheim 28 | # Copyright (c) 2011 Maarten Bosmans 29 | # 30 | # This program is free software: you can redistribute it and/or modify it 31 | # under the terms of the GNU General Public License as published by the 32 | # Free Software Foundation, either version 3 of the License, or (at your 33 | # option) any later version. 34 | # 35 | # This program is distributed in the hope that it will be useful, but 36 | # WITHOUT ANY WARRANTY; without even the implied warranty of 37 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 38 | # Public License for more details. 39 | # 40 | # You should have received a copy of the GNU General Public License along 41 | # with this program. If not, see . 42 | # 43 | # As a special exception, the respective Autoconf Macro's copyright owner 44 | # gives unlimited permission to copy, distribute and modify the configure 45 | # scripts that are the output of Autoconf when processing the Macro. You 46 | # need not follow the terms of the GNU General Public License when using 47 | # or distributing such scripts, even though portions of the text of the 48 | # Macro appear in them. The GNU General Public License (GPL) does govern 49 | # all other use of the material that constitutes the Autoconf Macro. 50 | # 51 | # This special exception to the GPL applies to versions of the Autoconf 52 | # Macro released by the Autoconf Archive. When you make and distribute a 53 | # modified version of the Autoconf Macro, you may extend this special 54 | # exception to the GPL to apply to your modified version as well. 55 | 56 | #serial 2 57 | 58 | AC_DEFUN([AX_CHECK_LINK_FLAG], 59 | [AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl 60 | AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ 61 | ax_check_save_flags=$LDFLAGS 62 | LDFLAGS="$LDFLAGS $4 $1" 63 | AC_LINK_IFELSE([AC_LANG_PROGRAM()], 64 | [AS_VAR_SET(CACHEVAR,[yes])], 65 | [AS_VAR_SET(CACHEVAR,[no])]) 66 | LDFLAGS=$ax_check_save_flags]) 67 | AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], 68 | [m4_default([$2], :)], 69 | [m4_default([$3], :)]) 70 | AS_VAR_POPDEF([CACHEVAR])dnl 71 | ])dnl AX_CHECK_LINK_FLAGS 72 | -------------------------------------------------------------------------------- /m4/ax_check_preproc_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_preproc_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_PREPROC_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's 12 | # preprocessor or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the preprocessor's default 18 | # flags when the check is done. The check is thus made with the flags: 19 | # "CPPFLAGS EXTRA-FLAGS FLAG". This can for example be used to force the 20 | # preprocessor to issue an error when a bad flag is given. 21 | # 22 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 23 | # macro in sync with AX_CHECK_{COMPILE,LINK}_FLAG. 24 | # 25 | # LICENSE 26 | # 27 | # Copyright (c) 2008 Guido U. Draheim 28 | # Copyright (c) 2011 Maarten Bosmans 29 | # 30 | # This program is free software: you can redistribute it and/or modify it 31 | # under the terms of the GNU General Public License as published by the 32 | # Free Software Foundation, either version 3 of the License, or (at your 33 | # option) any later version. 34 | # 35 | # This program is distributed in the hope that it will be useful, but 36 | # WITHOUT ANY WARRANTY; without even the implied warranty of 37 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 38 | # Public License for more details. 39 | # 40 | # You should have received a copy of the GNU General Public License along 41 | # with this program. If not, see . 42 | # 43 | # As a special exception, the respective Autoconf Macro's copyright owner 44 | # gives unlimited permission to copy, distribute and modify the configure 45 | # scripts that are the output of Autoconf when processing the Macro. You 46 | # need not follow the terms of the GNU General Public License when using 47 | # or distributing such scripts, even though portions of the text of the 48 | # Macro appear in them. The GNU General Public License (GPL) does govern 49 | # all other use of the material that constitutes the Autoconf Macro. 50 | # 51 | # This special exception to the GPL applies to versions of the Autoconf 52 | # Macro released by the Autoconf Archive. When you make and distribute a 53 | # modified version of the Autoconf Macro, you may extend this special 54 | # exception to the GPL to apply to your modified version as well. 55 | 56 | #serial 2 57 | 58 | AC_DEFUN([AX_CHECK_PREPROC_FLAG], 59 | [AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX 60 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]cppflags_$4_$1])dnl 61 | AC_CACHE_CHECK([whether _AC_LANG preprocessor accepts $1], CACHEVAR, [ 62 | ax_check_save_flags=$CPPFLAGS 63 | CPPFLAGS="$CPPFLAGS $4 $1" 64 | AC_PREPROC_IFELSE([AC_LANG_PROGRAM()], 65 | [AS_VAR_SET(CACHEVAR,[yes])], 66 | [AS_VAR_SET(CACHEVAR,[no])]) 67 | CPPFLAGS=$ax_check_save_flags]) 68 | AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], 69 | [m4_default([$2], :)], 70 | [m4_default([$3], :)]) 71 | AS_VAR_POPDEF([CACHEVAR])dnl 72 | ])dnl AX_CHECK_PREPROC_FLAGS 73 | -------------------------------------------------------------------------------- /seqno_collector.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #define __STDC_LIMIT_MACROS 29 | 30 | // e 31 | #include "e/atomic.h" 32 | #include "e/seqno_collector.h" 33 | 34 | using namespace e::atomic; 35 | using e::seqno_collector; 36 | 37 | struct seqno_collector::run 38 | { 39 | run() { for (size_t i = 0; i < 8; ++i) { nums[i] = 0; } } 40 | uint64_t nums[8]; 41 | } __attribute__ ((aligned (64))); 42 | 43 | seqno_collector :: seqno_collector(garbage_collector* gc) 44 | : m_gc(gc) 45 | , m_runs(gc) 46 | , m_lb_hint(0) 47 | { 48 | assert(sizeof(run) == 64); 49 | } 50 | 51 | seqno_collector :: ~seqno_collector() throw () 52 | { 53 | for (run_map_t::iterator it = m_runs.begin(); it != m_runs.end(); ++it) 54 | { 55 | if (m_runs.del(it->first)) 56 | { 57 | m_gc->collect(it->second, garbage_collector::free_ptr); 58 | } 59 | } 60 | } 61 | 62 | void 63 | seqno_collector :: collect(uint64_t seqno) 64 | { 65 | const uint64_t idx = seqno & ~511ULL; 66 | run* r = get_run(idx); 67 | collect(seqno, idx, r); 68 | } 69 | 70 | void 71 | seqno_collector :: collect_up_to(uint64_t seqno) 72 | { 73 | assert(seqno < UINT64_MAX); 74 | const uint64_t idx = seqno & ~511ULL; 75 | run* r = get_run(idx); 76 | set_hint(idx); 77 | 78 | for (uint64_t i = idx; i < seqno; ++i) 79 | { 80 | collect(i, idx, r); 81 | } 82 | 83 | for (run_map_t::iterator it = m_runs.begin(); it != m_runs.end(); ++it) 84 | { 85 | if (false && it->first < idx && 86 | m_runs.del(it->first)) 87 | { 88 | m_gc->collect(it->second, garbage_collector::free_ptr); 89 | } 90 | } 91 | } 92 | 93 | void 94 | seqno_collector :: lower_bound(uint64_t* seqno) 95 | { 96 | while (true) 97 | { 98 | uint64_t lb = load_64_nobarrier(&m_lb_hint); 99 | run* r = NULL; 100 | 101 | if (!m_runs.get(lb, &r)) 102 | { 103 | *seqno = lb; 104 | return; 105 | } 106 | 107 | assert(r); 108 | size_t i = 0; 109 | uint64_t witness = 0; 110 | 111 | for (; i < 8; ++i) 112 | { 113 | if ((witness = compare_and_swap_64_nobarrier(&r->nums[i], UINT64_MAX, UINT64_MAX)) != UINT64_MAX) 114 | { 115 | break; 116 | } 117 | } 118 | 119 | if (i >= 8) 120 | { 121 | compress(lb, r); 122 | continue; 123 | } 124 | 125 | *seqno = lb + i * 64; 126 | 127 | while ((witness & 1)) 128 | { 129 | ++*seqno; 130 | witness >>= 1; 131 | } 132 | 133 | return; 134 | } 135 | } 136 | 137 | seqno_collector::run* 138 | seqno_collector :: get_run(uint64_t idx) 139 | { 140 | run* r = NULL; 141 | 142 | // fill in r with a run that's in the table for idx 143 | while (true) 144 | { 145 | if (!m_runs.get(idx, &r)) 146 | { 147 | r = new run(); 148 | 149 | if (m_runs.put_ine(idx, r)) 150 | { 151 | break; 152 | } 153 | 154 | delete r; 155 | r = NULL; 156 | continue; 157 | } 158 | else 159 | { 160 | break; 161 | } 162 | } 163 | 164 | assert(r); 165 | return r; 166 | } 167 | 168 | void 169 | seqno_collector :: collect(uint64_t seqno, uint64_t idx, run* r) 170 | { 171 | const uint64_t diff = (seqno - idx); 172 | const uint64_t byte = diff >> 6; 173 | const uint64_t bit = diff & 63ULL; 174 | 175 | uint64_t expect = load_64_nobarrier(&r->nums[byte]); 176 | uint64_t newval = expect | (1ULL << bit); 177 | uint64_t witness; 178 | 179 | while ((witness = compare_and_swap_64_nobarrier(&r->nums[byte], expect, newval)) != expect) 180 | { 181 | expect = witness; 182 | newval = expect | (1ULL << bit); 183 | } 184 | 185 | if (newval == UINT64_MAX) 186 | { 187 | compress(idx, r); 188 | } 189 | } 190 | 191 | void 192 | seqno_collector :: compress(uint64_t idx, run* r) 193 | { 194 | for (size_t i = 0; i < 8; ++i) 195 | { 196 | if (compare_and_swap_64_nobarrier(&r->nums[i], UINT64_MAX, UINT64_MAX) != UINT64_MAX) 197 | { 198 | return; 199 | } 200 | } 201 | 202 | if (load_64_nobarrier(&m_lb_hint) != idx) 203 | { 204 | return; 205 | } 206 | 207 | set_hint(idx + 512); 208 | 209 | if (m_runs.del(idx)) 210 | { 211 | m_gc->collect(r, garbage_collector::free_ptr); 212 | r = get_run(idx + 512); 213 | compress(idx + 512, r); 214 | } 215 | } 216 | 217 | void 218 | seqno_collector :: set_hint(uint64_t idx) 219 | { 220 | uint64_t expect = load_64_nobarrier(&m_lb_hint); 221 | uint64_t newval = idx; 222 | uint64_t witness; 223 | 224 | while (expect < newval && 225 | (witness = compare_and_swap_64_nobarrier(&m_lb_hint, expect, newval)) != expect) 226 | { 227 | expect = witness; 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /slice.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // C 29 | #include 30 | 31 | // STL 32 | #include 33 | #include 34 | 35 | // e 36 | #include "e/slice.h" 37 | #include "e/base64.h" 38 | 39 | using e::slice; 40 | 41 | slice :: slice() 42 | : m_data(NULL) 43 | , m_sz(0) 44 | { 45 | } 46 | 47 | slice :: slice(const char* data) 48 | : m_data(reinterpret_cast(data)) 49 | , m_sz(strlen(data)) 50 | { 51 | } 52 | 53 | slice :: slice(const char* d, size_t sz) 54 | : m_data(reinterpret_cast(d)) 55 | , m_sz(sz) 56 | { 57 | } 58 | 59 | slice :: slice(const uint8_t* d, size_t sz) 60 | : m_data(d) 61 | , m_sz(sz) 62 | { 63 | } 64 | 65 | slice :: slice(const std::string& s) 66 | : m_data(reinterpret_cast(s.data())) 67 | , m_sz(s.size()) 68 | { 69 | } 70 | 71 | slice :: slice(const std::vector& buf) 72 | : m_data(&buf.front()) 73 | , m_sz(buf.size()) 74 | { 75 | } 76 | 77 | slice :: slice(const slice& other) 78 | : m_data(other.m_data) 79 | , m_sz(other.m_sz) 80 | { 81 | } 82 | 83 | slice :: ~slice() throw () 84 | { 85 | } 86 | 87 | int 88 | slice :: compare(const slice& rhs) const 89 | { 90 | if (m_sz < rhs.m_sz) 91 | { 92 | return -1; 93 | } 94 | else if (m_sz > rhs.m_sz) 95 | { 96 | return 1; 97 | } 98 | else 99 | { 100 | return memcmp(m_data, rhs.m_data, m_sz); 101 | } 102 | } 103 | 104 | std::string 105 | slice :: hex() const 106 | { 107 | std::ostringstream ostr; 108 | ostr << std::hex; 109 | 110 | for (uint32_t i = 0; i < m_sz; ++i) 111 | { 112 | unsigned int num = m_data[i]; 113 | ostr << std::setw(2) << std::setfill('0') << num; 114 | } 115 | 116 | return ostr.str(); 117 | } 118 | 119 | std::string 120 | slice :: b64() const 121 | { 122 | std::vector buf(m_sz * 2); 123 | ssize_t sz = b64_ntop(m_data, m_sz, &buf[0], buf.size()); 124 | assert(sz >= 0 && sz <= buf.size()); 125 | return std::string(&buf[0], sz); 126 | } 127 | 128 | bool 129 | slice :: starts_with(const e::slice& prefix) const 130 | { 131 | return size() >= prefix.size() && 132 | memcmp(data(), prefix.data(), prefix.size()) == 0; 133 | } 134 | 135 | void 136 | slice :: advance(size_t sz) 137 | { 138 | assert(sz <= m_sz); 139 | m_data += sz; 140 | m_sz -= sz; 141 | } 142 | 143 | void 144 | slice :: reset() 145 | { 146 | m_data = NULL; 147 | m_sz = 0; 148 | } 149 | 150 | void 151 | slice :: reset(const uint8_t* d, size_t sz) 152 | { 153 | m_data = d; 154 | m_sz = sz; 155 | } 156 | 157 | slice& 158 | slice :: operator = (const slice& rhs) 159 | { 160 | // We do not need to check for self-assignment. 161 | m_data = rhs.m_data; 162 | m_sz = rhs.m_sz; 163 | return *this; 164 | } 165 | -------------------------------------------------------------------------------- /strescape.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013,2015, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // C 29 | #include 30 | 31 | // STL 32 | #include 33 | 34 | // e 35 | #include "e/strescape.h" 36 | 37 | std::string 38 | e :: strescape(const std::string& input) 39 | { 40 | const char* data = input.c_str(); 41 | size_t data_sz = input.size(); 42 | std::vector tmp(data_sz * 4 + 1); 43 | char* ptr = &tmp.front(); 44 | 45 | for (size_t i = 0; i < data_sz; ++i) 46 | { 47 | if (isalnum(data[i]) || 48 | (ispunct(data[i]) && data[i] != '\'') || 49 | data[i] == ' ') 50 | { 51 | *ptr = data[i]; 52 | ++ptr; 53 | } 54 | else if (data[i] == '\n') 55 | { 56 | *ptr = '\\'; 57 | ++ptr; 58 | *ptr = 'n'; 59 | ++ptr; 60 | } 61 | else if (data[i] == '\r') 62 | { 63 | *ptr = '\\'; 64 | ++ptr; 65 | *ptr = 'r'; 66 | ++ptr; 67 | } 68 | else if (data[i] == '\t') 69 | { 70 | *ptr = '\\'; 71 | ++ptr; 72 | *ptr = 't'; 73 | ++ptr; 74 | } 75 | else if (data[i] == '\'') 76 | { 77 | *ptr = '\\'; 78 | ++ptr; 79 | *ptr = '\''; 80 | ++ptr; 81 | } 82 | else 83 | { 84 | *ptr = '\\'; 85 | ++ptr; 86 | *ptr = 'x'; 87 | ++ptr; 88 | sprintf(ptr, "%02x", data[i] & 0xff); 89 | ptr += 2; 90 | } 91 | } 92 | 93 | *ptr = '\0'; 94 | return std::string(&tmp.front(), ptr); 95 | } 96 | -------------------------------------------------------------------------------- /test/array_ptr.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // e 29 | #include "th.h" 30 | #include "e/array_ptr.h" 31 | 32 | namespace 33 | { 34 | 35 | TEST(ArrayPtr, CtorAndDtor) 36 | { 37 | e::array_ptr a; 38 | e::array_ptr b(new int[1]); 39 | e::array_ptr c(b); 40 | } 41 | 42 | TEST(ArrayPtr, BoolOperator) 43 | { 44 | e::array_ptr x; 45 | ASSERT_FALSE(x); 46 | x = new int[5]; 47 | ASSERT_TRUE(x); 48 | } 49 | 50 | TEST(ArrayPtr, BracketOperator) 51 | { 52 | e::array_ptr x(new int[5]); 53 | x[0] = 0; 54 | x[1] = 1; 55 | x[2] = 2; 56 | x[3] = 3; 57 | x[4] = 4; 58 | ASSERT_EQ(0, x[0]); 59 | ASSERT_EQ(1, x[1]); 60 | ASSERT_EQ(2, x[2]); 61 | ASSERT_EQ(3, x[3]); 62 | ASSERT_EQ(4, x[4]); 63 | 64 | const e::array_ptr y(x); 65 | ASSERT_EQ(0, y[0]); 66 | ASSERT_EQ(1, y[1]); 67 | ASSERT_EQ(2, y[2]); 68 | ASSERT_EQ(3, y[3]); 69 | ASSERT_EQ(4, y[4]); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /test/bitsteal.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // C 29 | #include 30 | 31 | // e 32 | #include "th.h" 33 | #include "e/bitsteal.h" 34 | 35 | namespace 36 | { 37 | 38 | TEST(BitStealingTest, Strip) 39 | { 40 | uintptr_t v = 0xdeadbeefcafebabeul; 41 | uint64_t* p = reinterpret_cast(v); 42 | p = e::bitsteal::strip(p); 43 | v = reinterpret_cast(p); 44 | ASSERT_EQ(0x0000beefcafebabeul, v); 45 | } 46 | 47 | TEST(BitStealingTest, SetAndUnset) 48 | { 49 | using e::bitsteal::set; 50 | using e::bitsteal::unset; 51 | uintptr_t v1 = 0x0000beefcafebabeULL; 52 | uint64_t* p1 = reinterpret_cast(v1); 53 | uintptr_t v2 = 0xffffbeefcafebabeULL; 54 | uint64_t* p2 = reinterpret_cast(v2); 55 | p1 = set(p1, 0); p2 = set(p2, 0); 56 | p1 = unset(p1, 1); p2 = unset(p2, 1); 57 | p1 = set(p1, 2); p2 = set(p2, 2); 58 | p1 = set(p1, 3); p2 = set(p2, 3); 59 | p1 = unset(p1, 4); p2 = unset(p2, 4); 60 | p1 = set(p1, 5); p2 = set(p2, 5); 61 | p1 = unset(p1, 6); p2 = unset(p2, 6); 62 | p1 = set(p1, 7); p2 = set(p2, 7); 63 | p1 = unset(p1, 8); p2 = unset(p2, 8); 64 | p1 = set(p1, 9); p2 = set(p2, 9); 65 | p1 = set(p1, 10); p2 = set(p2, 10); 66 | p1 = set(p1, 11); p2 = set(p2, 11); 67 | p1 = set(p1, 12); p2 = set(p2, 12); 68 | p1 = unset(p1, 13); p2 = unset(p2, 13); 69 | p1 = set(p1, 14); p2 = set(p2, 14); 70 | p1 = set(p1, 15); p2 = set(p2, 15); 71 | ASSERT_EQ(p1, p2); 72 | ASSERT_EQ(0xdeadbeefcafebabeul, reinterpret_cast(p1)); 73 | ASSERT_EQ(0xdeadbeefcafebabeul, reinterpret_cast(p2)); 74 | } 75 | 76 | } // namespace 77 | -------------------------------------------------------------------------------- /test/buffer.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // C 29 | #include 30 | 31 | // C++ 32 | #include 33 | 34 | // e 35 | #include "th.h" 36 | #include "e/buffer.h" 37 | 38 | #define ASSERT_MEMCMP(X, Y, S) ASSERT_EQ(0, memcmp(X, Y, S)) 39 | 40 | namespace 41 | { 42 | 43 | TEST(BufferTest, CtorAndDtor) 44 | { 45 | // Create a buffer without any size 46 | std::auto_ptr a(e::buffer::create(0)); 47 | ASSERT_EQ(0U, a->size()); 48 | ASSERT_EQ(0U, a->capacity()); 49 | // Create a buffer which can pack 2 bytes 50 | std::auto_ptr b(e::buffer::create(2)); 51 | ASSERT_EQ(0U, b->size()); 52 | ASSERT_EQ(2U, b->capacity()); 53 | // Create a buffer with the three bytes "XYZ" 54 | std::auto_ptr c(e::buffer::create("xyz", 3)); 55 | ASSERT_EQ(3U, c->size()); 56 | ASSERT_EQ(3U, c->capacity()); 57 | } 58 | 59 | TEST(BufferTest, PackBuffer) 60 | { 61 | uint64_t a = 0xdeadbeefcafebabe; 62 | uint32_t b = 0x8badf00d; 63 | uint16_t c = 0xface; 64 | uint8_t d = '!'; 65 | std::auto_ptr buf(e::buffer::create("the buffer", 10)); 66 | std::auto_ptr packed(e::buffer::create(34)); 67 | 68 | packed->pack() << a << b << c << d << buf->as_slice(); 69 | ASSERT_EQ(26U, packed->size()); 70 | ASSERT_MEMCMP(packed->data(), 71 | "\xde\xad\xbe\xef\xca\xfe\xba\xbe" 72 | "\x8b\xad\xf0\x0d" 73 | "\xfa\xce" 74 | "!" 75 | "\x0athe buffer", 76 | 26); 77 | 78 | packed->pack_at(12) << d << c << buf->as_slice(); 79 | ASSERT_EQ(26U, packed->size()); 80 | ASSERT_MEMCMP(packed->data(), 81 | "\xde\xad\xbe\xef\xca\xfe\xba\xbe" 82 | "\x8b\xad\xf0\x0d" 83 | "!" 84 | "\xfa\xce" 85 | "\x0athe buffer", 86 | 26); 87 | } 88 | 89 | TEST(BufferTest, UnpackBuffer) 90 | { 91 | uint64_t a; 92 | uint32_t b; 93 | uint16_t c; 94 | uint8_t d; 95 | e::slice sl; 96 | std::auto_ptr packed(e::buffer::create( 97 | "\xde\xad\xbe\xef\xca\xfe\xba\xbe" 98 | "\x8b\xad\xf0\x0d" 99 | "\xfa\xce" 100 | "!" 101 | "\x0athe buffer", 26)); 102 | 103 | packed->unpack() >> a >> b >> c >> d >> sl; 104 | ASSERT_EQ(0xdeadbeefcafebabeULL, a); 105 | ASSERT_EQ(0x8badf00dUL, b); 106 | ASSERT_EQ(0xface, c); 107 | ASSERT_EQ('!', d); 108 | ASSERT_EQ(10U, sl.size()); 109 | ASSERT_MEMCMP("the buffer", sl.data(), 10); 110 | } 111 | 112 | TEST(BufferTest, UnpackErrors) 113 | { 114 | std::auto_ptr buf(e::buffer::create("\x8b\xad\xf0\x0d" "\xfa\xce", 6)); 115 | uint32_t a; 116 | e::unpacker up = buf->unpack() >> a; 117 | ASSERT_EQ(0x8badf00d, a); 118 | ASSERT_EQ(2U, up.remain()); 119 | ASSERT_FALSE(up.error()); 120 | 121 | // "a" should not change even if nup fails 122 | e::unpacker nup = up >> a; 123 | ASSERT_EQ(0x8badf00d, a); 124 | ASSERT_EQ(2U, up.remain()); 125 | ASSERT_FALSE(up.error()); 126 | ASSERT_TRUE(nup.error()); 127 | 128 | // Getting the next value should succeed 129 | uint16_t b; 130 | up = up >> b; 131 | ASSERT_EQ(0xface, b); 132 | ASSERT_EQ(0U, up.remain()); 133 | ASSERT_FALSE(up.error()); 134 | } 135 | 136 | TEST(BufferTest, Hex) 137 | { 138 | std::auto_ptr buf1(e::buffer::create("\xde\xad\xbe\xef", 4)); 139 | std::auto_ptr buf2(e::buffer::create("\x00\xff\x0f\xf0", 4)); 140 | 141 | ASSERT_EQ("deadbeef", buf1->hex()); 142 | ASSERT_EQ("00ff0ff0", buf2->hex()); 143 | } 144 | 145 | TEST(BufferTest, VectorPack) 146 | { 147 | std::auto_ptr buf(e::buffer::create(12)); 148 | std::vector vector; 149 | vector.push_back(0xdead); 150 | vector.push_back(0xbeef); 151 | vector.push_back(0xcafe); 152 | vector.push_back(0xbabe); 153 | e::packer p = buf->pack_at(0); 154 | p = p << vector; 155 | ASSERT_TRUE(buf->cmp("\x04" 156 | "\xde\xad\xbe\xef" 157 | "\xca\xfe\xba\xbe", 9)); 158 | } 159 | 160 | TEST(BufferTest, VectorUnpack) 161 | { 162 | std::auto_ptr buf(e::buffer::create("\x04" 163 | "\xde\xad\xbe\xef" 164 | "\xca\xfe\xba\xbe", 9)); 165 | std::vector vector; 166 | buf->unpack() >> vector; 167 | ASSERT_EQ(4U, vector.size()); 168 | ASSERT_EQ(0xdead, vector[0]); 169 | ASSERT_EQ(0xbeef, vector[1]); 170 | ASSERT_EQ(0xcafe, vector[2]); 171 | ASSERT_EQ(0xbabe, vector[3]); 172 | } 173 | 174 | TEST(BufferTest, VectorUnpackFail) 175 | { 176 | std::auto_ptr buf(e::buffer::create("\x04" 177 | "\xde\xad\xbe\xef" 178 | "\xca\xfe\xba\xbe", 9)); 179 | std::vector vector_bad; 180 | std::vector vector_good; 181 | e::unpacker bad = buf->unpack() >> vector_bad; 182 | e::unpacker good = buf->unpack() >> vector_good; 183 | ASSERT_TRUE(bad.error()); 184 | ASSERT_FALSE(good.error()); 185 | ASSERT_EQ(4U, vector_good.size()); 186 | ASSERT_EQ(0xdead, vector_good[0]); 187 | ASSERT_EQ(0xbeef, vector_good[1]); 188 | ASSERT_EQ(0xcafe, vector_good[2]); 189 | ASSERT_EQ(0xbabe, vector_good[3]); 190 | } 191 | 192 | } // namespace 193 | -------------------------------------------------------------------------------- /test/convert.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // e 29 | #include "th.h" 30 | #include "e/convert.h" 31 | 32 | namespace 33 | { 34 | 35 | TEST(ConvertTest, Uint64NormalCases) 36 | { 37 | ASSERT_GE(sizeof(unsigned long int), sizeof(uint32_t)); 38 | 39 | try 40 | { 41 | ASSERT_EQ(0U, e::convert::to_uint64_t("0")); 42 | ASSERT_EQ(0U, e::convert::to_uint64_t("0x0")); 43 | ASSERT_EQ(0U, e::convert::to_uint64_t("0x0", 16)); 44 | ASSERT_EQ(0U, e::convert::to_uint64_t("00")); 45 | ASSERT_EQ(0U, e::convert::to_uint64_t("00", 8)); 46 | 47 | ASSERT_EQ(18446744073709551615ULL, e::convert::to_uint64_t("18446744073709551615")); 48 | ASSERT_EQ(18446744073709551615ULL, e::convert::to_uint64_t("0xffffffffffffffff")); 49 | ASSERT_EQ(18446744073709551615ULL, e::convert::to_uint64_t("0xffffffffffffffff", 16)); 50 | ASSERT_EQ(18446744073709551615ULL, e::convert::to_uint64_t("01777777777777777777777")); 51 | ASSERT_EQ(18446744073709551615ULL, e::convert::to_uint64_t("01777777777777777777777", 8)); 52 | } 53 | catch (...) 54 | { 55 | FAIL(); 56 | } 57 | } 58 | 59 | TEST(ConvertTest, Uint32NormalCases) 60 | { 61 | ASSERT_GE(sizeof(unsigned long int), sizeof(uint32_t)); 62 | 63 | try 64 | { 65 | ASSERT_EQ(0U, e::convert::to_uint32_t("0")); 66 | ASSERT_EQ(0U, e::convert::to_uint32_t("0x0")); 67 | ASSERT_EQ(0U, e::convert::to_uint32_t("0x0", 16)); 68 | ASSERT_EQ(0U, e::convert::to_uint32_t("00")); 69 | ASSERT_EQ(0U, e::convert::to_uint32_t("00", 8)); 70 | 71 | ASSERT_EQ(4294967295UL, e::convert::to_uint32_t("4294967295")); 72 | ASSERT_EQ(4294967295UL, e::convert::to_uint32_t("0xffffffff")); 73 | ASSERT_EQ(4294967295UL, e::convert::to_uint32_t("0xffffffff", 16)); 74 | ASSERT_EQ(4294967295UL, e::convert::to_uint32_t("037777777777")); 75 | ASSERT_EQ(4294967295UL, e::convert::to_uint32_t("037777777777", 8)); 76 | } 77 | catch (...) 78 | { 79 | FAIL(); 80 | } 81 | } 82 | 83 | TEST(ConvertTest, Uint16NormalCases) 84 | { 85 | ASSERT_GE(sizeof(unsigned long int), sizeof(uint16_t)); 86 | 87 | try 88 | { 89 | ASSERT_EQ(0U, e::convert::to_uint16_t("0")); 90 | ASSERT_EQ(0U, e::convert::to_uint16_t("0x0")); 91 | ASSERT_EQ(0U, e::convert::to_uint16_t("0x0", 16)); 92 | ASSERT_EQ(0U, e::convert::to_uint16_t("00")); 93 | ASSERT_EQ(0U, e::convert::to_uint16_t("00", 8)); 94 | 95 | ASSERT_EQ(65535, e::convert::to_uint16_t("65535")); 96 | ASSERT_EQ(65535, e::convert::to_uint16_t("0xffff")); 97 | ASSERT_EQ(65535, e::convert::to_uint16_t("0xffff", 16)); 98 | ASSERT_EQ(65535, e::convert::to_uint16_t("0177777")); 99 | ASSERT_EQ(65535, e::convert::to_uint16_t("0177777", 8)); 100 | } 101 | catch (...) 102 | { 103 | FAIL(); 104 | } 105 | } 106 | 107 | TEST(ConvertTest, Uint8NormalCases) 108 | { 109 | ASSERT_GE(sizeof(unsigned long int), sizeof(uint8_t)); 110 | 111 | try 112 | { 113 | ASSERT_EQ(0U, e::convert::to_uint8_t("0")); 114 | ASSERT_EQ(0U, e::convert::to_uint8_t("0x0")); 115 | ASSERT_EQ(0U, e::convert::to_uint8_t("0x0", 16)); 116 | ASSERT_EQ(0U, e::convert::to_uint8_t("00")); 117 | ASSERT_EQ(0U, e::convert::to_uint8_t("00", 8)); 118 | 119 | ASSERT_EQ(255, e::convert::to_uint8_t("255")); 120 | ASSERT_EQ(255, e::convert::to_uint8_t("0xff")); 121 | ASSERT_EQ(255, e::convert::to_uint8_t("0xff", 16)); 122 | ASSERT_EQ(255, e::convert::to_uint8_t("0377")); 123 | ASSERT_EQ(255, e::convert::to_uint8_t("0377", 8)); 124 | } 125 | catch (...) 126 | { 127 | FAIL(); 128 | } 129 | } 130 | 131 | } // namespace 132 | -------------------------------------------------------------------------------- /test/endian.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 GCC diagnostic ignored "-Wfloat-equal" 29 | 30 | // C 31 | #include 32 | 33 | // e 34 | #include "th.h" 35 | #include "e/endian.h" 36 | 37 | #define ASSERT_MEMCMP(X, Y, S) ASSERT_EQ(0, memcmp(X, Y, S)) 38 | 39 | namespace 40 | { 41 | 42 | TEST(EndianTest, Pack) 43 | { 44 | uint8_t buffer[sizeof(int64_t)]; 45 | 46 | e::pack8be(uint8_t(0xde), buffer); 47 | ASSERT_MEMCMP(buffer, "\xde", 1); 48 | e::pack8le(uint8_t(0xde), buffer); 49 | ASSERT_MEMCMP(buffer, "\xde", 1); 50 | e::pack8be(int8_t(0xde), buffer); 51 | ASSERT_MEMCMP(buffer, "\xde", 1); 52 | e::pack8le(int8_t(0xde), buffer); 53 | ASSERT_MEMCMP(buffer, "\xde", 1); 54 | 55 | e::pack16be(uint16_t(0xdead), buffer); 56 | ASSERT_MEMCMP(buffer, "\xde\xad", 2); 57 | e::pack16le(uint16_t(0xdead), buffer); 58 | ASSERT_MEMCMP(buffer, "\xad\xde", 2); 59 | e::pack16be(int16_t(0xdead), buffer); 60 | ASSERT_MEMCMP(buffer, "\xde\xad", 2); 61 | e::pack16le(int16_t(0xdead), buffer); 62 | ASSERT_MEMCMP(buffer, "\xad\xde", 2); 63 | 64 | e::pack32be(uint32_t(0xdeadbeefUL), buffer); 65 | ASSERT_MEMCMP(buffer, "\xde\xad\xbe\xef", 4); 66 | e::pack32le(uint32_t(0xdeadbeefUL), buffer); 67 | ASSERT_MEMCMP(buffer, "\xef\xbe\xad\xde", 4); 68 | e::pack32be(int32_t(0xdeadbeefUL), buffer); 69 | ASSERT_MEMCMP(buffer, "\xde\xad\xbe\xef", 4); 70 | e::pack32le(int32_t(0xdeadbeefUL), buffer); 71 | ASSERT_MEMCMP(buffer, "\xef\xbe\xad\xde", 4); 72 | 73 | e::pack64be(uint64_t(0xdeadbeefcafebabeULL), buffer); 74 | ASSERT_MEMCMP(buffer, "\xde\xad\xbe\xef\xca\xfe\xba\xbe", 8); 75 | e::pack64le(uint64_t(0xdeadbeefcafebabeULL), buffer); 76 | ASSERT_MEMCMP(buffer, "\xbe\xba\xfe\xca\xef\xbe\xad\xde", 8); 77 | e::pack64be(int64_t(0xdeadbeefcafebabeULL), buffer); 78 | ASSERT_MEMCMP(buffer, "\xde\xad\xbe\xef\xca\xfe\xba\xbe", 8); 79 | e::pack64le(int64_t(0xdeadbeefcafebabeULL), buffer); 80 | ASSERT_MEMCMP(buffer, "\xbe\xba\xfe\xca\xef\xbe\xad\xde", 8); 81 | 82 | float f = 16711938.0; 83 | e::packfloatbe(f, buffer); 84 | ASSERT_MEMCMP(buffer, "\x4b\x7f\x01\x02", 4); 85 | e::packfloatle(f, buffer); 86 | ASSERT_MEMCMP(buffer, "\x02\x01\x7f\x4b", 4); 87 | 88 | double d = 9006104071832581.0; 89 | e::packdoublebe(d, buffer); 90 | ASSERT_MEMCMP(buffer, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8); 91 | e::packdoublele(d, buffer); 92 | ASSERT_MEMCMP(buffer, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8); 93 | } 94 | 95 | TEST(EndianTest, Unpack) 96 | { 97 | const uint8_t buffer8[] = "\xde"; 98 | const uint8_t buffer16[] = "\xde\xad"; 99 | const uint8_t buffer32[] = "\xde\xad\xbe\xef"; 100 | const uint8_t buffer64[] = "\xde\xad\xbe\xef\xca\xfe\xba\xbe"; 101 | const uint8_t bufferfloatbe[] = "\x4b\x7f\x01\x02"; 102 | const uint8_t bufferfloatle[] = "\x02\x01\x7f\x4b"; 103 | const uint8_t bufferdoublebe[] = "\x43\x3f\xff\x01\x02\x03\x04\x05"; 104 | const uint8_t bufferdoublele[] = "\x05\x04\x03\x02\x01\xff\x3f\x43"; 105 | 106 | uint8_t unsigned8; 107 | int8_t signed8; 108 | uint16_t unsigned16; 109 | int16_t signed16; 110 | uint32_t unsigned32; 111 | int32_t signed32; 112 | uint64_t unsigned64; 113 | int64_t signed64; 114 | float f; 115 | double d; 116 | 117 | e::unpack8be(buffer8, &unsigned8); 118 | ASSERT_EQ(0xde, unsigned8); 119 | e::unpack8le(buffer8, &unsigned8); 120 | ASSERT_EQ(0xde, unsigned8); 121 | e::unpack8be(buffer8, &signed8); 122 | ASSERT_EQ(int8_t(0xde), signed8); 123 | e::unpack8le(buffer8, &signed8); 124 | ASSERT_EQ(int8_t(0xde), signed8); 125 | 126 | e::unpack16be(buffer16, &unsigned16); 127 | ASSERT_EQ(0xdead, unsigned16); 128 | e::unpack16le(buffer16, &unsigned16); 129 | ASSERT_EQ(0xadde, unsigned16); 130 | e::unpack16be(buffer16, &signed16); 131 | ASSERT_EQ(int16_t(0xdead), signed16); 132 | e::unpack16le(buffer16, &signed16); 133 | ASSERT_EQ(int16_t(0xadde), signed16); 134 | 135 | e::unpack32be(buffer32, &unsigned32); 136 | ASSERT_EQ(0xdeadbeefUL, unsigned32); 137 | e::unpack32le(buffer32, &unsigned32); 138 | ASSERT_EQ(0xefbeaddeUL, unsigned32); 139 | e::unpack32be(buffer32, &signed32); 140 | ASSERT_EQ(int32_t(0xdeadbeefUL), signed32); 141 | e::unpack32le(buffer32, &signed32); 142 | ASSERT_EQ(int32_t(0xefbeaddeUL), signed32); 143 | 144 | e::unpack64be(buffer64, &unsigned64); 145 | ASSERT_EQ(0xdeadbeefcafebabeULL, unsigned64); 146 | e::unpack64le(buffer64, &unsigned64); 147 | ASSERT_EQ(0xbebafecaefbeaddeULL, unsigned64); 148 | e::unpack64be(buffer64, &signed64); 149 | ASSERT_EQ(int64_t(0xdeadbeefcafebabeULL), signed64); 150 | e::unpack64le(buffer64, &signed64); 151 | ASSERT_EQ(int64_t(0xbebafecaefbeaddeULL), signed64); 152 | 153 | e::unpackfloatbe(bufferfloatbe, &f); 154 | ASSERT_EQ(16711938.0, f); 155 | e::unpackfloatle(bufferfloatle, &f); 156 | ASSERT_EQ(16711938.0, f); 157 | 158 | e::unpackdoublebe(bufferdoublebe, &d); 159 | ASSERT_EQ(9006104071832581.0, d); 160 | e::unpackdoublele(bufferdoublele, &d); 161 | ASSERT_EQ(9006104071832581.0, d); 162 | } 163 | 164 | } // namespace 165 | -------------------------------------------------------------------------------- /test/guard.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // e 29 | #include "th.h" 30 | #include "e/guard.h" 31 | 32 | namespace 33 | { 34 | 35 | int check; 36 | 37 | void 38 | func0() 39 | { 40 | check = 0; 41 | } 42 | 43 | void 44 | func1(int a) 45 | { 46 | check = a; 47 | } 48 | 49 | void 50 | func2(int a, int b) 51 | { 52 | check = a + b; 53 | } 54 | 55 | void 56 | func3(int a, int b, int c) 57 | { 58 | check = a + b + c; 59 | } 60 | 61 | TEST(GuardTest, Function0) 62 | { 63 | check = -1; 64 | 65 | { 66 | e::guard g = e::makeguard(&func0); 67 | g.use_variable(); 68 | ASSERT_EQ(-1, check); 69 | } 70 | 71 | ASSERT_EQ(0, check); 72 | } 73 | 74 | TEST(GuardTest, Function1) 75 | { 76 | check = -1; 77 | 78 | { 79 | e::guard g = e::makeguard(func1, 1); 80 | g.use_variable(); 81 | ASSERT_EQ(-1, check); 82 | } 83 | 84 | ASSERT_EQ(1, check); 85 | } 86 | 87 | TEST(GuardTest, Function2) 88 | { 89 | check = -1; 90 | 91 | { 92 | e::guard g = e::makeguard(func2, 1, 2); 93 | g.use_variable(); 94 | ASSERT_EQ(-1, check); 95 | } 96 | 97 | ASSERT_EQ(3, check); 98 | } 99 | 100 | TEST(GuardTest, Function3) 101 | { 102 | check = -1; 103 | 104 | { 105 | e::guard g = e::makeguard(func3, 1, 2, 3); 106 | g.use_variable(); 107 | ASSERT_EQ(-1, check); 108 | } 109 | 110 | ASSERT_EQ(6, check); 111 | } 112 | 113 | TEST(GuardTest, Function0Dismiss) 114 | { 115 | check = -1; 116 | 117 | { 118 | e::guard g = e::makeguard(func0); 119 | ASSERT_EQ(-1, check); 120 | g.dismiss(); 121 | } 122 | 123 | ASSERT_EQ(-1, check); 124 | } 125 | 126 | TEST(GuardTest, Function1Dismiss) 127 | { 128 | check = -1; 129 | 130 | { 131 | e::guard g = e::makeguard(func1, 1); 132 | ASSERT_EQ(-1, check); 133 | g.dismiss(); 134 | } 135 | 136 | ASSERT_EQ(-1, check); 137 | } 138 | 139 | TEST(GuardTest, Function2Dismiss) 140 | { 141 | check = -1; 142 | 143 | { 144 | e::guard g = e::makeguard(func2, 1, 2); 145 | ASSERT_EQ(-1, check); 146 | g.dismiss(); 147 | } 148 | 149 | ASSERT_EQ(-1, check); 150 | } 151 | 152 | TEST(GuardTest, Function3Dismiss) 153 | { 154 | check = -1; 155 | 156 | { 157 | e::guard g = e::makeguard(func3, 1, 2, 3); 158 | ASSERT_EQ(-1, check); 159 | g.dismiss(); 160 | } 161 | 162 | ASSERT_EQ(-1, check); 163 | } 164 | 165 | class object 166 | { 167 | public: 168 | object() : m_count(-1) {} 169 | 170 | public: 171 | void func0() { m_count = 0; } 172 | void func1(int a) { m_count = a; } 173 | void func2(int a, int b) { m_count = a + b; } 174 | void func3(int a, int b, int c) { m_count = a + b + c; } 175 | int count() const { return m_count; } 176 | 177 | private: 178 | int m_count; 179 | }; 180 | 181 | TEST(GuardTest, Object0) 182 | { 183 | object obj; 184 | 185 | { 186 | e::guard g = e::makeobjguard(obj, &object::func0); 187 | g.use_variable(); 188 | ASSERT_EQ(-1, obj.count()); 189 | } 190 | 191 | ASSERT_EQ(0, obj.count()); 192 | } 193 | 194 | TEST(GuardTest, Object1) 195 | { 196 | object obj; 197 | 198 | { 199 | e::guard g = e::makeobjguard(obj, &object::func1, 1); 200 | g.use_variable(); 201 | ASSERT_EQ(-1, obj.count()); 202 | } 203 | 204 | ASSERT_EQ(1, obj.count()); 205 | } 206 | 207 | TEST(GuardTest, Object2) 208 | { 209 | object obj; 210 | 211 | { 212 | e::guard g = e::makeobjguard(obj, &object::func2, 1, 2); 213 | g.use_variable(); 214 | ASSERT_EQ(-1, obj.count()); 215 | } 216 | 217 | ASSERT_EQ(3, obj.count()); 218 | } 219 | 220 | TEST(GuardTest, Object3) 221 | { 222 | object obj; 223 | 224 | { 225 | e::guard g = e::makeobjguard(obj, &object::func3, 1, 2, 3); 226 | g.use_variable(); 227 | ASSERT_EQ(-1, obj.count()); 228 | } 229 | 230 | ASSERT_EQ(6, obj.count()); 231 | } 232 | 233 | TEST(GuardTest, Object0Dismiss) 234 | { 235 | object obj; 236 | 237 | { 238 | e::guard g = e::makeobjguard(obj, &object::func0); 239 | ASSERT_EQ(-1, obj.count()); 240 | g.dismiss(); 241 | } 242 | 243 | ASSERT_EQ(-1, obj.count()); 244 | } 245 | 246 | TEST(GuardTest, Object1Dismiss) 247 | { 248 | object obj; 249 | 250 | { 251 | e::guard g = e::makeobjguard(obj, &object::func1, 1); 252 | ASSERT_EQ(-1, obj.count()); 253 | g.dismiss(); 254 | } 255 | 256 | ASSERT_EQ(-1, obj.count()); 257 | } 258 | 259 | TEST(GuardTest, Object2Dismiss) 260 | { 261 | object obj; 262 | 263 | { 264 | e::guard g = e::makeobjguard(obj, &object::func2, 1, 2); 265 | ASSERT_EQ(-1, obj.count()); 266 | g.dismiss(); 267 | } 268 | 269 | ASSERT_EQ(-1, obj.count()); 270 | } 271 | 272 | TEST(GuardTest, Object3Dismiss) 273 | { 274 | object obj; 275 | 276 | { 277 | e::guard g = e::makeobjguard(obj, &object::func3, 1, 2, 3); 278 | ASSERT_EQ(-1, obj.count()); 279 | g.dismiss(); 280 | } 281 | 282 | ASSERT_EQ(-1, obj.count()); 283 | } 284 | 285 | } // namespace 286 | -------------------------------------------------------------------------------- /test/pow2.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // C 29 | #include 30 | 31 | // e 32 | #include "th.h" 33 | #include "e/pow2.h" 34 | 35 | namespace 36 | { 37 | 38 | TEST(Pow2Test, Many) 39 | { 40 | ASSERT_EQ(uint64_t(0), e::next_pow2(0)); 41 | ASSERT_EQ(uint64_t(1), e::next_pow2(1)); 42 | ASSERT_EQ(uint64_t(2), e::next_pow2(2)); 43 | ASSERT_EQ(uint64_t(4), e::next_pow2(3)); 44 | ASSERT_EQ(uint64_t(4), e::next_pow2(4)); 45 | for (uint64_t i = 5; i <= 8; ++i) { ASSERT_EQ(8, e::next_pow2(i)); } 46 | for (uint64_t i = 9; i <= 16; ++i) { ASSERT_EQ(16, e::next_pow2(i)); } 47 | for (uint64_t i = 17; i <= 32; ++i) { ASSERT_EQ(32, e::next_pow2(i)); } 48 | ASSERT_EQ(562949953421312ULL, e::next_pow2(281474976710657)); 49 | } 50 | 51 | TEST(Pow2Test, IsPow2) 52 | { 53 | ASSERT_FALSE(e::is_pow2(0)); 54 | ASSERT_TRUE(e::is_pow2(1)); 55 | ASSERT_TRUE(e::is_pow2(2)); 56 | ASSERT_FALSE(e::is_pow2(3)); 57 | ASSERT_TRUE(e::is_pow2(4)); 58 | ASSERT_FALSE(e::is_pow2(5)); 59 | ASSERT_FALSE(e::is_pow2(6)); 60 | ASSERT_FALSE(e::is_pow2(7)); 61 | ASSERT_TRUE(e::is_pow2(8)); 62 | } 63 | 64 | } // namespace 65 | -------------------------------------------------------------------------------- /test/runner.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of po6 nor the names of its contributors may be used 13 | // to endorse or promote products derived from this software without 14 | // specific prior written permission. 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 | // th 29 | #include "th.h" 30 | 31 | int 32 | main(int argc, char* argv[]) 33 | { 34 | argc = argc; 35 | argv = argv; 36 | return th::run_tests(); 37 | } 38 | -------------------------------------------------------------------------------- /test/safe_math.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | #define __STDC_LIMIT_MACROS 29 | 30 | // e 31 | #include "th.h" 32 | #include "e/safe_math.h" 33 | 34 | namespace 35 | { 36 | 37 | TEST(SafeMath, Add) 38 | { 39 | int64_t result; 40 | 41 | ASSERT_TRUE(e::safe_add(0, 0, &result)); 42 | ASSERT_EQ(0, result); 43 | 44 | ASSERT_TRUE(e::safe_add(0, INT64_MAX, &result)); 45 | ASSERT_EQ(INT64_MAX, result); 46 | ASSERT_TRUE(e::safe_add(INT64_MAX, 0, &result)); 47 | ASSERT_EQ(INT64_MAX, result); 48 | 49 | ASSERT_FALSE(e::safe_add(1, INT64_MAX, &result)); 50 | ASSERT_FALSE(e::safe_add(INT64_MAX, 1, &result)); 51 | 52 | ASSERT_TRUE(e::safe_add(0, INT64_MIN, &result)); 53 | ASSERT_EQ(INT64_MIN, result); 54 | ASSERT_TRUE(e::safe_add(INT64_MIN, 0, &result)); 55 | ASSERT_EQ(INT64_MIN, result); 56 | 57 | ASSERT_FALSE(e::safe_add(-1, INT64_MIN, &result)); 58 | ASSERT_FALSE(e::safe_add(INT64_MIN, -1, &result)); 59 | 60 | ASSERT_TRUE(e::safe_add(INT64_MIN, INT64_MAX, &result)); 61 | ASSERT_EQ(-1, result); 62 | ASSERT_TRUE(e::safe_add(INT64_MAX, INT64_MIN, &result)); 63 | ASSERT_EQ(-1, result); 64 | } 65 | 66 | TEST(SafeMath, Sub) 67 | { 68 | int64_t result; 69 | 70 | ASSERT_TRUE(e::safe_sub(0, 0, &result)); 71 | ASSERT_EQ(0, result); 72 | 73 | ASSERT_TRUE(e::safe_sub(0, -INT64_MAX, &result)); 74 | ASSERT_EQ(INT64_MAX, result); 75 | ASSERT_TRUE(e::safe_sub(INT64_MAX, 0, &result)); 76 | ASSERT_EQ(INT64_MAX, result); 77 | 78 | ASSERT_FALSE(e::safe_sub(INT64_MAX, -1, &result)); 79 | ASSERT_FALSE(e::safe_sub(INT64_MIN, 1, &result)); 80 | 81 | ASSERT_TRUE(e::safe_sub(INT64_MIN, -INT64_MAX, &result)); 82 | ASSERT_EQ(-1, result); 83 | ASSERT_TRUE(e::safe_sub(-INT64_MAX, INT64_MIN, &result)); 84 | ASSERT_EQ(1, result); 85 | } 86 | 87 | TEST(SafeMath, Mul) 88 | { 89 | int64_t result; 90 | 91 | ASSERT_TRUE(e::safe_mul(0, 0, &result)); 92 | ASSERT_EQ(0, result); 93 | 94 | ASSERT_TRUE(e::safe_mul(1, INT64_MAX, &result)); 95 | ASSERT_EQ(INT64_MAX, result); 96 | ASSERT_TRUE(e::safe_mul(INT64_MAX, 1, &result)); 97 | ASSERT_EQ(INT64_MAX, result); 98 | ASSERT_TRUE(e::safe_mul(1, INT64_MIN, &result)); 99 | ASSERT_EQ(INT64_MIN, result); 100 | ASSERT_TRUE(e::safe_mul(INT64_MIN, 1, &result)); 101 | ASSERT_EQ(INT64_MIN, result); 102 | 103 | ASSERT_FALSE(e::safe_mul(4611686018427387904LL, 2, &result)); 104 | ASSERT_FALSE(e::safe_mul(2, 4611686018427387904LL, &result)); 105 | 106 | ASSERT_TRUE(e::safe_mul(-4611686018427387904LL, 2, &result)); 107 | ASSERT_EQ(INT64_MIN, result); 108 | ASSERT_TRUE(e::safe_mul(2, -4611686018427387904LL, &result)); 109 | ASSERT_EQ(INT64_MIN, result); 110 | ASSERT_TRUE(e::safe_mul(4611686018427387904LL, -2, &result)); 111 | ASSERT_EQ(INT64_MIN, result); 112 | ASSERT_TRUE(e::safe_mul(-2, 4611686018427387904LL, &result)); 113 | ASSERT_EQ(INT64_MIN, result); 114 | 115 | ASSERT_FALSE(e::safe_mul(3074457345618258603, -3, &result)); 116 | ASSERT_FALSE(e::safe_mul(-3, 3074457345618258603, &result)); 117 | ASSERT_FALSE(e::safe_mul(-3074457345618258603, 3, &result)); 118 | ASSERT_FALSE(e::safe_mul(3, -3074457345618258603, &result)); 119 | } 120 | 121 | TEST(SafeMath, Div) 122 | { 123 | int64_t result; 124 | 125 | ASSERT_FALSE(e::safe_div(INT64_MIN, -1, &result)); 126 | ASSERT_FALSE(e::safe_div(INT64_MIN, 0, &result)); 127 | 128 | ASSERT_TRUE(e::safe_div(INT64_MIN, 1, &result)); 129 | ASSERT_EQ(INT64_MIN, result); 130 | ASSERT_TRUE(e::safe_div(INT64_MAX, 1, &result)); 131 | ASSERT_EQ(INT64_MAX, result); 132 | ASSERT_TRUE(e::safe_div(INT64_MAX, -1, &result)); 133 | ASSERT_EQ(INT64_MIN + 1, result); 134 | 135 | ASSERT_TRUE(e::safe_div(-5, 2, &result)); 136 | ASSERT_EQ(-3, result); 137 | 138 | ASSERT_TRUE(e::safe_div(-5, 3, &result)); 139 | ASSERT_EQ(-2, result); 140 | 141 | ASSERT_TRUE(e::safe_div(5, -2, &result)); 142 | ASSERT_EQ(-3, result); 143 | 144 | ASSERT_TRUE(e::safe_div(5, -3, &result)); 145 | ASSERT_EQ(-2, result); 146 | } 147 | 148 | TEST(SafeMath, Mod) 149 | { 150 | int64_t result; 151 | 152 | ASSERT_FALSE(e::safe_mod(INT64_MAX, 0, &result)); 153 | 154 | ASSERT_TRUE(e::safe_mod(INT64_MAX, INT64_MAX, &result)); 155 | ASSERT_EQ(0, result); 156 | ASSERT_TRUE(e::safe_mod(INT64_MAX, INT64_MIN, &result)); 157 | ASSERT_EQ(-1, result); 158 | ASSERT_TRUE(e::safe_mod(INT64_MIN, INT64_MAX, &result)); 159 | ASSERT_EQ(INT64_MAX - 1, result); 160 | ASSERT_TRUE(e::safe_mod(INT64_MIN, INT64_MIN, &result)); 161 | ASSERT_EQ(0, result); 162 | 163 | ASSERT_TRUE(e::safe_mod(-5, 2, &result)); 164 | ASSERT_EQ(1, result); 165 | 166 | ASSERT_TRUE(e::safe_mod(-5, 3, &result)); 167 | ASSERT_EQ(1, result); 168 | 169 | ASSERT_TRUE(e::safe_mod(5, -2, &result)); 170 | ASSERT_EQ(-1, result); 171 | 172 | ASSERT_TRUE(e::safe_mod(5, -3, &result)); 173 | ASSERT_EQ(-1, result); 174 | } 175 | 176 | } // namespace 177 | -------------------------------------------------------------------------------- /test/seqno_collector.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Cornell University 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of this project nor the names of its contributors may 13 | // be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 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 | // e 29 | #include "th.h" 30 | #include "e/seqno_collector.h" 31 | 32 | TEST(SeqnoCollector, Test) 33 | { 34 | e::garbage_collector gc; 35 | e::garbage_collector::thread_state ts; 36 | gc.register_thread(&ts); 37 | e::seqno_collector sc(&gc); 38 | uint64_t id; 39 | // first try, nothing collected 40 | sc.lower_bound(&id); 41 | ASSERT_EQ(id, 0U); 42 | // collect zero 43 | sc.collect(0); 44 | sc.lower_bound(&id); 45 | ASSERT_EQ(id, 1U); 46 | // collect one 47 | sc.collect(1); 48 | sc.lower_bound(&id); 49 | ASSERT_EQ(id, 2U); 50 | // collect three 51 | sc.collect(3); 52 | sc.lower_bound(&id); 53 | ASSERT_EQ(id, 2U); 54 | // collect three again 55 | sc.collect(3); 56 | sc.lower_bound(&id); 57 | ASSERT_EQ(id, 2U); 58 | // collect two 59 | sc.collect(2); 60 | sc.lower_bound(&id); 61 | ASSERT_EQ(id, 4U); 62 | // collect_up_to! 63 | sc.collect_up_to(9); 64 | sc.lower_bound(&id); 65 | ASSERT_EQ(id, 9U); 66 | sc.lower_bound(&id); 67 | ASSERT_EQ(id, 9U); 68 | 69 | for (uint64_t i = 9; i < 65536; ++i) 70 | { 71 | sc.collect(i); 72 | sc.lower_bound(&id); 73 | ASSERT_EQ(id, i + 1); 74 | } 75 | 76 | for (uint64_t i = 65536 + 512; i < 65536 + 1024; ++i) 77 | { 78 | sc.collect(i); 79 | sc.lower_bound(&id); 80 | ASSERT_EQ(id, 65536); 81 | } 82 | 83 | for (uint64_t i = 65536; i < 65536 + 511; ++i) 84 | { 85 | sc.collect(i); 86 | sc.lower_bound(&id); 87 | ASSERT_EQ(id, i + 1); 88 | } 89 | 90 | sc.collect(65536 + 511); 91 | sc.lower_bound(&id); 92 | ASSERT_EQ(id, 65536 + 1024); 93 | 94 | gc.quiescent_state(&ts); 95 | gc.deregister_thread(&ts); 96 | } 97 | -------------------------------------------------------------------------------- /test/varint.cc: -------------------------------------------------------------------------------- 1 | // This code is derived from code distributed as part of Google LevelDB. 2 | // The original is available in leveldb as util/coding_test.cc. 3 | // This file was retrieved Jul 15, 2013 by Robert Escriva. 4 | 5 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | 9 | // STL 10 | #include 11 | 12 | // e 13 | #include "th.h" 14 | #include "e/varint.h" 15 | 16 | TEST(Varint, Varint32) 17 | { 18 | std::string s; 19 | 20 | for (uint32_t i = 0; i < (32 * 32); i++) 21 | { 22 | uint32_t v = (i / 32) << (i % 32); 23 | char buf[10]; 24 | char* ptr = e::varint32_encode(buf, v); 25 | s += std::string(buf, ptr - buf); 26 | } 27 | 28 | const char* p = s.data(); 29 | const char* limit = p + s.size(); 30 | 31 | for (uint32_t i = 0; i < (32 * 32); i++) 32 | { 33 | uint32_t expected = (i / 32) << (i % 32); 34 | uint32_t actual; 35 | const char* start = p; 36 | p = e::varint32_decode(p, limit, &actual); 37 | ASSERT_TRUE(p != NULL); 38 | ASSERT_EQ(expected, actual); 39 | ASSERT_EQ(e::varint_length(actual), p - start); 40 | } 41 | 42 | ASSERT_EQ(p, s.data() + s.size()); 43 | } 44 | 45 | TEST(Coding, Varint64) 46 | { 47 | // Construct the list of values to check 48 | std::vector values; 49 | // Some special values 50 | values.push_back(0); 51 | values.push_back(100); 52 | values.push_back(~static_cast(0)); 53 | values.push_back(~static_cast(0) - 1); 54 | 55 | for (uint32_t k = 0; k < 64; k++) 56 | { 57 | // Test values near powers of two 58 | const uint64_t power = 1ull << k; 59 | values.push_back(power); 60 | values.push_back(power-1); 61 | values.push_back(power+1); 62 | } 63 | 64 | std::string s; 65 | 66 | for (size_t i = 0; i < values.size(); i++) 67 | { 68 | char buf[10]; 69 | char* ptr = e::varint64_encode(buf, values[i]); 70 | s += std::string(buf, ptr - buf); 71 | } 72 | 73 | const char* p = s.data(); 74 | const char* limit = p + s.size(); 75 | 76 | for (size_t i = 0; i < values.size(); i++) 77 | { 78 | ASSERT_TRUE(p < limit); 79 | uint64_t actual; 80 | const char* start = p; 81 | p = e::varint64_decode(p, limit, &actual); 82 | ASSERT_TRUE(p != NULL); 83 | ASSERT_EQ(values[i], actual); 84 | ASSERT_EQ(e::varint_length(actual), p - start); 85 | } 86 | 87 | ASSERT_EQ(p, limit); 88 | } 89 | 90 | TEST(Coding, Varint32Overflow) 91 | { 92 | uint32_t result; 93 | std::string input("\x81\x82\x83\x84\x85\x11"); 94 | ASSERT_TRUE(e::varint32_decode(input.data(), input.data() + input.size(), &result) 95 | == NULL); 96 | } 97 | 98 | TEST(Coding, Varint32Truncation) 99 | { 100 | uint32_t large_value = (1u << 31) + 100; 101 | std::string s; 102 | char buf[10]; 103 | char* ptr = e::varint32_encode(buf, large_value); 104 | s += std::string(buf, ptr - buf); 105 | uint32_t result; 106 | 107 | for (size_t len = 0; len < s.size() - 1; len++) 108 | { 109 | ASSERT_TRUE(e::varint32_decode(s.data(), s.data() + len, &result) == NULL); 110 | } 111 | 112 | ASSERT_TRUE(e::varint32_decode(s.data(), s.data() + s.size(), &result) != NULL); 113 | ASSERT_EQ(large_value, result); 114 | } 115 | 116 | TEST(Coding, Varint64Overflow) 117 | { 118 | uint64_t result; 119 | std::string input("\x81\x82\x83\x84\x85\x81\x82\x83\x84\x85\x11"); 120 | ASSERT_TRUE(e::varint64_decode(input.data(), input.data() + input.size(), &result) 121 | == NULL); 122 | } 123 | 124 | TEST(Coding, Varint64Truncation) 125 | { 126 | uint64_t large_value = (1ull << 63) + 100ull; 127 | std::string s; 128 | char buf[10]; 129 | char* ptr = e::varint64_encode(buf, large_value); 130 | s += std::string(buf, ptr - buf); 131 | uint64_t result; 132 | 133 | for (size_t len = 0; len < s.size() - 1; len++) 134 | { 135 | ASSERT_TRUE(e::varint64_decode(s.data(), s.data() + len, &result) == NULL); 136 | } 137 | 138 | ASSERT_TRUE(e::varint64_decode(s.data(), s.data() + s.size(), &result) != NULL); 139 | ASSERT_EQ(large_value, result); 140 | } 141 | -------------------------------------------------------------------------------- /th.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of th nor the names of its contributors may be used to 13 | // endorse or promote products derived from this software without specific 14 | // prior written permission. 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 | // C 29 | #include 30 | 31 | // C++ 32 | #include 33 | 34 | // STL 35 | #include 36 | #include 37 | 38 | // th 39 | #include "th.h" 40 | 41 | static std::vector* _th_tests = NULL; 42 | 43 | class escape_from_test_failure 44 | { 45 | public: 46 | escape_from_test_failure() {} 47 | }; 48 | 49 | th :: test_base :: test_base(const char* group, 50 | const char* name, 51 | const char* file, 52 | size_t line) 53 | : m_group(group) 54 | , m_name(name) 55 | , m_file(file) 56 | , m_line(line) 57 | { 58 | if (_th_tests == NULL) 59 | { 60 | _th_tests = new std::vector(); 61 | } 62 | 63 | _th_tests->push_back(this); 64 | } 65 | 66 | void 67 | th :: test_base :: run(bool* failed) 68 | { 69 | std::cerr << "===== Test " << m_group << "::" << m_name << " @ " << m_file << ":" << m_line << std::endl; 70 | 71 | try 72 | { 73 | this->_run(); 74 | *failed = false; 75 | } 76 | catch (escape_from_test_failure& ttotf) 77 | { 78 | *failed = true; 79 | } 80 | } 81 | 82 | bool 83 | th :: test_base :: operator < (const test_base& rhs) const 84 | { 85 | return compare(rhs) < 0; 86 | } 87 | 88 | int 89 | th :: test_base :: compare(const test_base& rhs) const 90 | { 91 | const test_base& lhs(*this); 92 | int cmp; 93 | 94 | // Compare file 95 | cmp = strcmp(lhs.m_file, rhs.m_file); 96 | 97 | if (cmp < 0) 98 | { 99 | return -1; 100 | } 101 | if (cmp > 0) 102 | { 103 | return 1; 104 | } 105 | 106 | // Compare line 107 | if (lhs.m_line < rhs.m_line) 108 | { 109 | return -1; 110 | } 111 | if (lhs.m_line > rhs.m_line) 112 | { 113 | return 1; 114 | } 115 | 116 | // Compare group 117 | cmp = strcmp(lhs.m_group, rhs.m_group); 118 | 119 | if (cmp < 0) 120 | { 121 | return -1; 122 | } 123 | if (cmp > 0) 124 | { 125 | return 1; 126 | } 127 | 128 | // Compare name 129 | cmp = strcmp(lhs.m_name, rhs.m_name); 130 | 131 | if (cmp < 0) 132 | { 133 | return -1; 134 | } 135 | if (cmp > 0) 136 | { 137 | return 1; 138 | } 139 | 140 | return 0; 141 | } 142 | 143 | th :: predicate :: predicate(const char* file, size_t line, const char* a, const char* b) 144 | : m_file(file) 145 | , m_line(line) 146 | , m_a(a) 147 | , m_b(b) 148 | { 149 | } 150 | 151 | void 152 | th :: predicate :: assert_true(bool T) 153 | { 154 | if (!T) 155 | { 156 | std::cerr << "FAIL @ " << m_file << ":" << m_line << ": tested " << m_a << "; expected true, but got false" << std::endl; 157 | th::fail(); 158 | } 159 | } 160 | 161 | void 162 | th :: predicate :: assert_false(bool F) 163 | { 164 | if (F) 165 | { 166 | std::cerr << "FAIL @ " << m_file << ":" << m_line << ": tested " << m_a << "; expected false, but got true" << std::endl; 167 | th::fail(); 168 | } 169 | } 170 | 171 | void 172 | th :: predicate :: fail() 173 | { 174 | std::cerr << "FAIL @ " << m_file << ":" << m_line << ": forced fail" << std::endl; 175 | th::fail(); 176 | } 177 | 178 | static bool 179 | compare_test_base_ptrs(const th::test_base* lhs, const th::test_base* rhs) 180 | { 181 | return *lhs < *rhs; 182 | } 183 | 184 | int 185 | th :: run_tests() 186 | { 187 | if (!_th_tests) 188 | { 189 | return 0; 190 | } 191 | 192 | std::sort(_th_tests->begin(), _th_tests->end(), compare_test_base_ptrs); 193 | const std::vector& th_tests(*_th_tests); 194 | int failures = 0; 195 | 196 | for (size_t i = 0; i < th_tests.size(); ++i) 197 | { 198 | bool fail = false; 199 | th_tests[i]->run(&fail); 200 | 201 | if (fail) 202 | { 203 | ++failures; 204 | } 205 | } 206 | 207 | return failures; 208 | } 209 | 210 | void 211 | th :: fail() 212 | { 213 | escape_from_test_failure eftf; 214 | throw eftf; 215 | } 216 | -------------------------------------------------------------------------------- /th.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Robert Escriva 2 | // All rights reserved. 3 | // 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 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of th nor the names of its contributors may be used to 13 | // endorse or promote products derived from this software without specific 14 | // prior written permission. 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 | #ifndef th_h_ 29 | #define th_h_ 30 | 31 | // C 32 | #include 33 | 34 | // C++ 35 | #include 36 | 37 | #define TH_XSTR(x) #x 38 | #define TH_STR(x) TH_XSTR(x) 39 | #define TH_XCONCAT(x, y) x ## y 40 | #define TH_CONCAT(x, y) TH_XCONCAT(x, y) 41 | 42 | namespace th 43 | { 44 | 45 | int 46 | run_tests(); 47 | 48 | void 49 | fail(); 50 | 51 | class test_base 52 | { 53 | public: 54 | test_base(const char* group, 55 | const char* name, 56 | const char* file, 57 | size_t line); 58 | virtual ~test_base() throw () {} 59 | 60 | public: 61 | void run(bool* failed); 62 | 63 | public: 64 | bool operator < (const test_base& rhs) const; 65 | 66 | private: 67 | virtual void _run() = 0; 68 | int compare(const test_base& rhs) const; 69 | 70 | private: 71 | test_base(const test_base&); 72 | test_base& operator = (const test_base&); 73 | 74 | private: 75 | const char* m_group; 76 | const char* m_name; 77 | const char* m_file; 78 | size_t m_line; 79 | }; 80 | 81 | #define BINARY_PREDICATE(english, compiler) \ 82 | template \ 83 | void \ 84 | assert_ ## english(const A& a, const B& b) \ 85 | { \ 86 | if (!(a compiler b)) \ 87 | { \ 88 | std::cerr << "FAIL @ " << m_file << ":" << m_line << ": tested " << m_a << " " TH_XSTR(compiler) " " << m_b << "; got " << a << " " TH_XSTR(compiler) " " << b << std::endl; \ 89 | th::fail(); \ 90 | } \ 91 | } 92 | 93 | class predicate 94 | { 95 | public: 96 | predicate(const char* file, 97 | size_t line, 98 | const char* a, 99 | const char* b); 100 | void assert_true(bool T); 101 | void assert_false(bool F); 102 | BINARY_PREDICATE(lt, <) 103 | BINARY_PREDICATE(le, <=) 104 | BINARY_PREDICATE(eq, ==) 105 | BINARY_PREDICATE(ne, !=) 106 | BINARY_PREDICATE(ge, >=) 107 | BINARY_PREDICATE(gt, >) 108 | void fail(); 109 | 110 | private: 111 | const char* m_file; 112 | size_t m_line; 113 | const char* m_a; 114 | const char* m_b; 115 | }; 116 | 117 | #undef BINARY_PREDICATE 118 | 119 | } // namespace th 120 | 121 | #define TEST(GROUP, NAME) \ 122 | class TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__)))) : public th::test_base \ 123 | { \ 124 | public: \ 125 | TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__))))() \ 126 | : test_base(TH_STR(GROUP), TH_STR(NAME), __FILE__, __LINE__) {} \ 127 | protected: \ 128 | virtual void _run(); \ 129 | }; \ 130 | TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__)))) \ 131 | TH_CONCAT(_test_instance_, TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__))))); \ 132 | void TH_CONCAT(GROUP, TH_CONCAT(_, TH_CONCAT(NAME, TH_CONCAT(_, __LINE__)))) :: _run() 133 | 134 | #define ASSERT_TRUE(P) th::predicate(__FILE__, __LINE__, TH_STR(P), NULL).assert_true(P) 135 | #define ASSERT_FALSE(P) th::predicate(__FILE__, __LINE__, TH_STR(P), NULL).assert_false(P) 136 | #define ASSERT_LT(a, b) th::predicate(__FILE__, __LINE__, TH_STR(a), TH_STR(b)).assert_lt(a, b) 137 | #define ASSERT_LE(a, b) th::predicate(__FILE__, __LINE__, TH_STR(a), TH_STR(b)).assert_le(a, b) 138 | #define ASSERT_EQ(a, b) th::predicate(__FILE__, __LINE__, TH_STR(a), TH_STR(b)).assert_eq(a, b) 139 | #define ASSERT_NE(a, b) th::predicate(__FILE__, __LINE__, TH_STR(a), TH_STR(b)).assert_ne(a, b) 140 | #define ASSERT_GE(a, b) th::predicate(__FILE__, __LINE__, TH_STR(a), TH_STR(b)).assert_ge(a, b) 141 | #define ASSERT_GT(a, b) th::predicate(__FILE__, __LINE__, TH_STR(a), TH_STR(b)).assert_gt(a, b) 142 | #define FAIL() th::predicate(__FILE__, __LINE__, NULL, NULL).fail() 143 | 144 | #endif // th_h_ 145 | -------------------------------------------------------------------------------- /varint.cc: -------------------------------------------------------------------------------- 1 | // This code is derived from code distributed as part of Google LevelDB. 2 | // The original is available in leveldb as util/coding.cc. 3 | // This file was retrieved Jul 15, 2013 by Robert Escriva. 4 | 5 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | 9 | // C 10 | #include 11 | 12 | // e 13 | #include "e/varint.h" 14 | 15 | namespace 16 | { 17 | 18 | const char* 19 | decode_32_fallback(const char* p, 20 | const char* limit, 21 | uint32_t* value) 22 | 23 | { 24 | uint32_t result = 0; 25 | 26 | for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) 27 | { 28 | uint32_t byte = *(reinterpret_cast(p)); 29 | p++; 30 | 31 | if (byte & 128) 32 | { 33 | // More bytes are present 34 | result |= ((byte & 127) << shift); 35 | } 36 | else 37 | { 38 | result |= (byte << shift); 39 | *value = result; 40 | return reinterpret_cast(p); 41 | } 42 | } 43 | 44 | return NULL; 45 | } 46 | 47 | } // namespace 48 | 49 | const char* 50 | e :: varint32_decode(const char* p, 51 | const char* limit, 52 | uint32_t* value) 53 | 54 | { 55 | if (p < limit) 56 | { 57 | uint32_t result = *(reinterpret_cast(p)); 58 | 59 | if ((result & 128) == 0) 60 | { 61 | *value = result; 62 | return p + 1; 63 | } 64 | } 65 | 66 | return decode_32_fallback(p, limit, value); 67 | } 68 | 69 | const char* 70 | e :: varint64_decode(const char* p, const char* limit, uint64_t* value) 71 | { 72 | uint64_t result = 0; 73 | 74 | for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) 75 | { 76 | uint64_t byte = *(reinterpret_cast(p)); 77 | p++; 78 | 79 | if (byte & 128) 80 | { 81 | // More bytes are present 82 | result |= ((byte & 127) << shift); 83 | } 84 | else 85 | { 86 | result |= (byte << shift); 87 | *value = result; 88 | return reinterpret_cast(p); 89 | } 90 | } 91 | 92 | return NULL; 93 | } 94 | 95 | char* 96 | e :: varint32_encode(char* dst, uint32_t v) 97 | { 98 | // Operate on characters as unsigneds 99 | unsigned char* ptr = reinterpret_cast(dst); 100 | static const int B = 128; 101 | 102 | if (v < (1<<7)) 103 | { 104 | *(ptr++) = v; 105 | } 106 | else if (v < (1<<14)) 107 | { 108 | *(ptr++) = v | B; 109 | *(ptr++) = v>>7; 110 | } 111 | else if (v < (1<<21)) 112 | { 113 | *(ptr++) = v | B; 114 | *(ptr++) = (v>>7) | B; 115 | *(ptr++) = v>>14; 116 | } 117 | else if (v < (1<<28)) 118 | { 119 | *(ptr++) = v | B; 120 | *(ptr++) = (v>>7) | B; 121 | *(ptr++) = (v>>14) | B; 122 | *(ptr++) = v>>21; 123 | } 124 | else 125 | { 126 | *(ptr++) = v | B; 127 | *(ptr++) = (v>>7) | B; 128 | *(ptr++) = (v>>14) | B; 129 | *(ptr++) = (v>>21) | B; 130 | *(ptr++) = v>>28; 131 | } 132 | 133 | return reinterpret_cast(ptr); 134 | } 135 | 136 | char* 137 | e :: varint64_encode(char* dst, uint64_t v) 138 | { 139 | static const unsigned B = 128; 140 | unsigned char* ptr = reinterpret_cast(dst); 141 | 142 | while (v >= B) 143 | { 144 | *(ptr++) = (v & (B-1)) | B; 145 | v >>= 7; 146 | } 147 | 148 | *(ptr++) = static_cast(v); 149 | return reinterpret_cast(ptr); 150 | } 151 | --------------------------------------------------------------------------------