diff --git a/arlib/array.h b/arlib/array.h index 5b86e3d..703af8c 100644 --- a/arlib/array.h +++ b/arlib/array.h @@ -16,6 +16,17 @@ protected: // this->count=other.count; // this->items=other.items; //} + +protected: + static const bool trivial_cons = std::is_trivial::value; // constructor is memset(0) +#if __GNUC__ >= 5 + static const bool trivial_copy = std::is_trivially_copyable::value; +#else + static const bool trivial_copy = trivial_cons; // copy constructor is memcpy +#endif + //static const bool trivial_comp = std::has_unique_object_representations::value; + static const bool trivial_comp = std::is_integral::value; + public: const T& operator[](size_t n) const { return items[n]; } @@ -82,6 +93,28 @@ public: // return *this; //} + bool operator==(arrayview other) + { + if (size() != other.size()) return false; + if (this->trivial_comp) + { + return memcmp(ptr(), other.ptr(), sizeof(T)*size())==0; + } + else + { + for (size_t i=0;i other) + { + return !(*this == other); + } + const T* begin() { return this->items; } const T* end() { return this->items+this->count; } }; @@ -148,24 +181,11 @@ template class array : public arrayvieww { //T * items; //size_t count; - //My requirements: - //- all fields initialized by the default constructor are initialized to 0 - //- all copy/move constructors are equivalent to memcpy() - //- there is no destructor - //I believe that is equivalent to (possibly slightly looser than) std::is_trivial. - //If true, constructor calls are replaced with memset. (Destructor is still called; it'll get optimized out anyways.) - static const bool trivial_cons = std::is_trivial::value; -#if __GNUC__ >= 5 - static const bool trivial_copy = std::is_trivially_copyable::value; -#else - static const bool trivial_copy = trivial_cons; -#endif - void clone(const arrayview& other) { this->count = other.size(); // I can't access non-this instances of my base class, so let's just use the public interface. this->items = malloc(sizeof(T)*bitround(this->count)); - if (trivial_copy) + if (this->trivial_copy) { memcpy(this->items, other.ptr(), sizeof(T)*this->count); } @@ -211,7 +231,7 @@ template class array : public arrayvieww { if (this->count >= count) return; size_t prevcount = this->count; resize_grow_noinit(count); - if (trivial_cons) + if (this->trivial_cons) { memset(this->items+prevcount, 0, sizeof(T)*(count-prevcount)); } @@ -247,12 +267,12 @@ public: T& operator[](size_t n) { resize_grow(n+1); return this->items[n]; } void resize(size_t len) { resize_to(len); } - void resize_noinit(size_t len) - { - if (trivial_cons && len > this->size()) resize_grow_noinit(len); - else resize_to(len); - } void reserve(size_t len) { resize_grow(len); } + void reserve_noinit(size_t len) + { + if (this->trivial_cons) resize_grow_noinit(len); + else resize_grow(len); + } void append(const T& item) { size_t pos = this->count; resize_grow(pos+1); this->items[pos] = item; } void reset() { resize_shrink(0); } @@ -343,7 +363,7 @@ public: resize_grow_noinit(prevcount + othercount); - if (trivial_copy) + if (this->trivial_copy) { memcpy(this->items+prevcount, other.ptr(), sizeof(T)*othercount); } diff --git a/arlib/crc32.cpp b/arlib/crc32.cpp index 9dc032b..b45b8b9 100644 --- a/arlib/crc32.cpp +++ b/arlib/crc32.cpp @@ -39,10 +39,22 @@ uint32_t crc32_update(arrayview data, uint32_t crc) const uint8_t* ptr = data.ptr(); size_t len = data.size(); crc = ~crc; - for (size_t i=0;i>8); } + for (size_t i=len&7;i>8); + crc = crctable[(crc & 0xFF) ^ ptr[i+1]] ^ (crc>>8); + crc = crctable[(crc & 0xFF) ^ ptr[i+2]] ^ (crc>>8); + crc = crctable[(crc & 0xFF) ^ ptr[i+3]] ^ (crc>>8); + crc = crctable[(crc & 0xFF) ^ ptr[i+4]] ^ (crc>>8); + crc = crctable[(crc & 0xFF) ^ ptr[i+5]] ^ (crc>>8); + crc = crctable[(crc & 0xFF) ^ ptr[i+6]] ^ (crc>>8); + crc = crctable[(crc & 0xFF) ^ ptr[i+7]] ^ (crc>>8); + } + return ~crc; } diff --git a/arlib/file.h b/arlib/file.h index a474aaa..5e706c8 100644 --- a/arlib/file.h +++ b/arlib/file.h @@ -85,9 +85,9 @@ public: array read() const { array ret; - ret.resize_noinit(this->size()); + ret.reserve_noinit(this->size()); size_t actual = this->read(ret, 0); - ret.resize_noinit(actual); + ret.resize(actual); return ret; } static array read(cstring path) @@ -154,7 +154,7 @@ private: { if (!datawr) return false; size_t nbyte = newdata.size(); - datawr->reserve(start+nbyte); + datawr->reserve_noinit(start+nbyte); memcpy(datawr->slice(start, nbyte).ptr(), newdata.ptr(), nbyte); datard=*datawr; return true; diff --git a/arlib/safeint.h b/arlib/safeint.h index 19d2286..add6f0e 100644 --- a/arlib/safeint.h +++ b/arlib/safeint.h @@ -11,38 +11,38 @@ template class safeint { T data; #define HANDLE_BASE(stype, utype) \ - static inline bool addov(utype a, utype b, utype* c) \ + static inline bool addov_i(utype a, utype b, utype* c) \ { \ *c = a+b; /* rely on unsigned overflow wrapping */ \ return *c < a; \ } \ - static inline bool subov(utype a, utype b, utype* c) \ + static inline bool subov_i(utype a, utype b, utype* c) \ { \ *c = a-b; \ return (b > a); \ } \ - static inline bool mulov(utype a, utype b, utype* c) \ + static inline bool mulov_i(utype a, utype b, utype* c) \ { \ *c = a*b; \ return a!=0 && *c/a!=b; \ } \ - static inline bool lslov(utype a, utype b, utype* c) \ + static inline bool lslov_i(utype a, utype b, utype* c) \ { \ if (b >= sizeof(utype)*8) return true; \ *c = a<>b != a); \ } \ - static inline bool addov(stype a, stype b, stype* c) \ + static inline bool addov_i(stype a, stype b, stype* c) \ { \ *c = (utype)a+(utype)b; \ return (a>0 && b>0 && *c<0) || (a<0 && b<0 && *c>0); \ } \ - static inline bool subov(stype a, stype b, stype* c) \ + static inline bool subov_i(stype a, stype b, stype* c) \ { \ *c = (utype)a-(utype)b; \ return (a>0 && b<0 && *c<0) || (a<0 && b>0 && *c>0); \ } \ - static inline bool mulov(stype a, stype b, stype* c) \ + static inline bool mulov_i(stype a, stype b, stype* c) \ { \ stype min = ((stype)-1)<<(sizeof(stype)*8-1); \ stype max = -(min+1); \ @@ -54,7 +54,7 @@ template class safeint { *c = a*b; \ return false; \ } \ - static inline bool lslov(stype a, stype b, stype* c) \ + static inline bool lslov_i(stype a, stype b, stype* c) \ { \ if (b<0 || b >= sizeof(stype)*8) return true; \ *c = (a << b); \ @@ -73,22 +73,22 @@ template class safeint { *c = (ext)a op (ext)b; \ return false; \ } -HANDLE_EXT(addov, +, signed short, signed int) -HANDLE_EXT(addov, +, signed char, signed int) -HANDLE_EXT(addov, +, unsigned short, unsigned int) -HANDLE_EXT(addov, +, unsigned char, unsigned int) -HANDLE_EXT(subov, -, signed short, signed int) -HANDLE_EXT(subov, -, signed char, signed int) -HANDLE_EXT(subov, -, unsigned short, unsigned int) -HANDLE_EXT(subov, -, unsigned char, unsigned int) -HANDLE_EXT(mulov, *, signed short, signed int) -HANDLE_EXT(mulov, *, signed char, signed int) -HANDLE_EXT(mulov, *, unsigned short, unsigned int) -HANDLE_EXT(mulov, *, unsigned char, unsigned int) -HANDLE_EXT(lslov,<<, signed short, signed int) -HANDLE_EXT(lslov,<<, signed char, signed int) -HANDLE_EXT(lslov,<<, unsigned short, unsigned int) -HANDLE_EXT(lslov,<<, unsigned char, unsigned int) +HANDLE_EXT(addov_i, +, signed short, signed int) +HANDLE_EXT(addov_i, +, signed char, signed int) +HANDLE_EXT(addov_i, +, unsigned short, unsigned int) +HANDLE_EXT(addov_i, +, unsigned char, unsigned int) +HANDLE_EXT(subov_i, -, signed short, signed int) +HANDLE_EXT(subov_i, -, signed char, signed int) +HANDLE_EXT(subov_i, -, unsigned short, unsigned int) +HANDLE_EXT(subov_i, -, unsigned char, unsigned int) +HANDLE_EXT(mulov_i, *, signed short, signed int) +HANDLE_EXT(mulov_i, *, signed char, signed int) +HANDLE_EXT(mulov_i, *, unsigned short, unsigned int) +HANDLE_EXT(mulov_i, *, unsigned char, unsigned int) +HANDLE_EXT(lslov_i,<<, signed short, signed int) +HANDLE_EXT(lslov_i,<<, signed char, signed int) +HANDLE_EXT(lslov_i,<<, unsigned short, unsigned int) +HANDLE_EXT(lslov_i,<<, unsigned char, unsigned int) #undef HANDLE_EXT #else //allow forcing the non-casting algorithm, so an exhaustive search can be done over the full range of some types @@ -99,9 +99,9 @@ HANDLE_EXT(lslov,<<, unsigned char, unsigned int) #undef HANDLE_BASE #if __GNUC__>=5 -#define addov __builtin_add_overflow -#define subov __builtin_sub_overflow -#define mulov __builtin_mul_overflow +#define addov_i __builtin_add_overflow +#define subov_i __builtin_sub_overflow +#define mulov_i __builtin_mul_overflow #endif public: @@ -131,21 +131,21 @@ ALLOPER(OP) { if (!valid() || !b.valid()) return invalid; T ret; - if (addov(val(), b.val(), &ret)) return invalid; + if (addov_i(val(), b.val(), &ret)) return invalid; else return ret; } safeint operator-(safeint b) { if (!valid() || !b.valid()) return invalid; T ret; - if (subov(val(), b.val(), &ret)) return invalid; + if (subov_i(val(), b.val(), &ret)) return invalid; else return ret; } safeint operator*(safeint b) { if (!valid() || !b.valid()) return invalid; T ret; - if (mulov(val(), b.val(), &ret)) return invalid; + if (mulov_i(val(), b.val(), &ret)) return invalid; else return ret; } safeint operator/(safeint b) @@ -182,7 +182,7 @@ ALLOPER(OP) { if (!valid() || !b.valid()) return invalid; T ret; - if (lslov(val(), b.val(), &ret)) return invalid; + if (lslov_i(val(), b.val(), &ret)) return invalid; else return ret; } safeint operator>>(safeint b) @@ -222,6 +222,14 @@ ALLOPER(OP) if (!valid() || !b.valid()) return false; return val()>=b.val(); } + + static bool addov(T a, T b, T* c) { return addov_i(a, b, c); } + static bool subov(T a, T b, T* c) { return subov_i(a, b, c); } + static bool mulov(T a, T b, T* c) { return mulov_i(a, b, c); } + static bool lslov(T a, T b, T* c) { return lslov_i(a, b, c); } +#undef addov_i +#undef subov_i +#undef mulov_i }; #define OP(op, ope) \