Update Arlib

This commit is contained in:
Alcaro
2016-12-25 11:46:06 +01:00
parent 2ab71fc9c4
commit 89c8f06533
4 changed files with 96 additions and 56 deletions

View File

@@ -16,6 +16,17 @@ protected:
// this->count=other.count;
// this->items=other.items;
//}
protected:
static const bool trivial_cons = std::is_trivial<T>::value; // constructor is memset(0)
#if __GNUC__ >= 5
static const bool trivial_copy = std::is_trivially_copyable<T>::value;
#else
static const bool trivial_copy = trivial_cons; // copy constructor is memcpy
#endif
//static const bool trivial_comp = std::has_unique_object_representations<T>::value;
static const bool trivial_comp = std::is_integral<T>::value;
public:
const T& operator[](size_t n) const { return items[n]; }
@@ -82,6 +93,28 @@ public:
// return *this;
//}
bool operator==(arrayview<T> 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<size();i++)
{
if (!(items[i]==other[i])) return false;
}
return true;
}
}
bool operator!=(arrayview<T> other)
{
return !(*this == other);
}
const T* begin() { return this->items; }
const T* end() { return this->items+this->count; }
};
@@ -148,24 +181,11 @@ template<typename T> class array : public arrayvieww<T> {
//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<T>::value;
#if __GNUC__ >= 5
static const bool trivial_copy = std::is_trivially_copyable<T>::value;
#else
static const bool trivial_copy = trivial_cons;
#endif
void clone(const arrayview<T>& 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<typename T> class array : public arrayvieww<T> {
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);
}

View File

@@ -39,10 +39,22 @@ uint32_t crc32_update(arrayview<uint8_t> data, uint32_t crc)
const uint8_t* ptr = data.ptr();
size_t len = data.size();
crc = ~crc;
for (size_t i=0;i<len;i++)
for (size_t i=0;i<(len&7);i++)
{
crc = crctable[(crc & 0xFF) ^ ptr[i]] ^ (crc>>8);
}
for (size_t i=len&7;i<len;i+=8)
{
crc = crctable[(crc & 0xFF) ^ ptr[i+0]] ^ (crc>>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;
}

View File

@@ -85,9 +85,9 @@ public:
array<byte> read() const
{
array<byte> 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<byte> 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;

View File

@@ -11,38 +11,38 @@ template<typename T> 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; \
return (*c>>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<typename T> 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<typename T> 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<T> operator-(safeint<T> 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<T> operator*(safeint<T> 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<T> operator/(safeint<T> 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<T> operator>>(safeint<T> 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) \