diff --git a/nall/foreach.hpp b/nall/foreach.hpp index 2b79c52..30c694d 100644 --- a/nall/foreach.hpp +++ b/nall/foreach.hpp @@ -4,8 +4,14 @@ #include #undef foreach -#define foreach(iter, object) \ + +#define foreach2(iter, object) foreach3(iter, object, foreach_counter) +#define foreach3(iter, object, foreach_counter) \ for(unsigned foreach_counter = 0, foreach_limit = container_size(object), foreach_once = 0, foreach_broken = 0; foreach_counter < foreach_limit && foreach_broken == 0; foreach_counter++, foreach_once = 0) \ for(typeof(object[0]) &iter = object[foreach_counter]; foreach_once == 0 && (foreach_broken = 1); foreach_once++, foreach_broken = 0) +#define foreach_impl(...) foreach_decl(__VA_ARGS__, foreach3(__VA_ARGS__), foreach2(__VA_ARGS__), foreach_too_few_arguments) +#define foreach_decl(_1, _2, _3, N, ...) N +#define foreach(...) foreach_impl(__VA_ARGS__) + #endif diff --git a/nall/public_cast.hpp b/nall/public_cast.hpp new file mode 100644 index 0000000..331800e --- /dev/null +++ b/nall/public_cast.hpp @@ -0,0 +1,32 @@ +#ifndef NALL_PUBLIC_CAST_HPP +#define NALL_PUBLIC_CAST_HPP + +//this is a proof-of-concept-*only* C++ access-privilege elevation exploit. +//this code is 100% legal C++, per C++98 section 14.7.2 paragraph 8: +//"access checking rules do not apply to names in explicit instantiations." +//usage example: + +//struct N { typedef void (Class::*)(); }; +//template class public_cast; +//(class.*public_cast::value); + +//Class::Reference may be public, protected or private +//Class::Reference may be a function, object or variable + +namespace nall { + template struct public_cast; + + template struct public_cast { + static typename T::type value; + }; + + template typename T::type public_cast::value; + + template struct public_cast { + static typename T::type value; + }; + + template typename T::type public_cast::value = public_cast::value = P; +} + +#endif diff --git a/nall/reference_array.hpp b/nall/reference_array.hpp new file mode 100644 index 0000000..ac47c32 --- /dev/null +++ b/nall/reference_array.hpp @@ -0,0 +1,103 @@ +#ifndef NALL_REFERENCE_ARRAY_HPP +#define NALL_REFERENCE_ARRAY_HPP + +#include +#include +#include + +namespace nall { + template struct reference_array { + protected: + typedef typename std::remove_reference::type *Tptr; + Tptr *pool; + unsigned poolsize, buffersize; + + public: + unsigned size() const { return buffersize; } + unsigned capacity() const { return poolsize; } + + void reset() { + if(pool) free(pool); + pool = 0; + poolsize = 0; + buffersize = 0; + } + + void reserve(unsigned newsize) { + if(newsize == poolsize) return; + + pool = (Tptr*)realloc(pool, newsize * sizeof(T)); + poolsize = newsize; + buffersize = min(buffersize, newsize); + } + + void resize(unsigned newsize) { + if(newsize > poolsize) reserve(bit::round(newsize)); + buffersize = newsize; + } + + void append(const T data) { + unsigned index = buffersize++; + if(index >= poolsize) resize(index + 1); + pool[index] = &data; + } + + template reference_array(Args&... args) : pool(0), poolsize(0), buffersize(0) { + construct(args...); + } + + ~reference_array() { + reset(); + } + + reference_array& operator=(const reference_array &source) { + if(pool) free(pool); + buffersize = source.buffersize; + poolsize = source.poolsize; + pool = (Tptr*)malloc(sizeof(T) * poolsize); + memcpy(pool, source.pool, sizeof(T) * buffersize); + return *this; + } + + reference_array& operator=(const reference_array &&source) { + if(pool) free(pool); + pool = source.pool; + poolsize = source.poolsize; + buffersize = source.buffersize; + source.pool = 0; + source.reset(); + return *this; + } + + inline T operator[](unsigned index) { + if(index >= buffersize) throw "reference_array[] out of bounds"; + return *pool[index]; + } + + inline const T operator[](unsigned index) const { + if(index >= buffersize) throw "reference_array[] out of bounds"; + return *pool[index]; + } + + private: + void construct() { + } + + void construct(const reference_array &source) { + operator=(source); + } + + void construct(const reference_array &&source) { + operator=(std::move(source)); + } + + template void construct(T data, Args&... args) { + append(data); + construct(args...); + } + }; + + template struct has_size> { enum { value = true }; }; +} + +#endif diff --git a/nall/string/base.hpp b/nall/string/base.hpp index 21ad0ce..9972547 100644 --- a/nall/string/base.hpp +++ b/nall/string/base.hpp @@ -71,7 +71,7 @@ namespace nall { inline ~string(); - inline bool readfile(const char*); + inline bool readfile(const string&); inline string& replace (const char*, const char*); inline string& qreplace(const char*, const char*); diff --git a/nall/string/convert.hpp b/nall/string/convert.hpp index 2f6a5ba..4c679ab 100644 --- a/nall/string/convert.hpp +++ b/nall/string/convert.hpp @@ -69,8 +69,11 @@ inline intmax_t integer(const char *str) { intmax_t result = 0; bool negate = false; - //check for negation - if(*str == '-') { + //check for sign + if(*str == '+') { + negate = false; + str++; + } else if(*str == '-') { negate = true; str++; } diff --git a/nall/string/core.hpp b/nall/string/core.hpp index 67c4d3f..16a74af 100644 --- a/nall/string/core.hpp +++ b/nall/string/core.hpp @@ -252,7 +252,7 @@ string::~string() { if(data) free(data); } -bool string::readfile(const char *filename) { +bool string::readfile(const string &filename) { assign(""); #if !defined(_WIN32) diff --git a/nall/string/utility.hpp b/nall/string/utility.hpp index 718d642..9ffae94 100644 --- a/nall/string/utility.hpp +++ b/nall/string/utility.hpp @@ -50,10 +50,10 @@ inline string integer(intmax_t value) { result[x] = buffer[y]; } - return result; + return (const char*)result; } -template inline string linteger(intmax_t value) { +template inline string linteger(intmax_t value) { bool negative = value < 0; if(negative) value = abs(value); @@ -68,7 +68,8 @@ template inline string linteger(intmax_t value) { buffer[size++] = negative ? '-' : '+'; buffer[size] = 0; - char result[length + 1]; + unsigned length = (length_ == 0 ? size : length_); + char result[64]; memset(result, ' ', length); result[length] = 0; @@ -76,10 +77,10 @@ template inline string linteger(intmax_t value) { result[x] = buffer[y]; } - return result; + return (const char*)result; } -template inline string rinteger(intmax_t value) { +template inline string rinteger(intmax_t value) { bool negative = value < 0; if(negative) value = abs(value); @@ -94,7 +95,8 @@ template inline string rinteger(intmax_t value) { buffer[size++] = negative ? '-' : '+'; buffer[size] = 0; - char result[length + 1]; + unsigned length = (length_ == 0 ? size : length_); + char result[64]; memset(result, ' ', length); result[length] = 0; @@ -102,7 +104,7 @@ template inline string rinteger(intmax_t value) { result[x] = buffer[y]; } - return result; + return (const char*)result; } inline string decimal(uintmax_t value) { @@ -124,10 +126,10 @@ inline string decimal(uintmax_t value) { result[x] = buffer[y]; } - return &result[0]; + return (const char*)result; } -template inline string ldecimal(uintmax_t value) { +template inline string ldecimal(uintmax_t value) { char buffer[64]; unsigned size = 0; @@ -138,7 +140,8 @@ template inline string ldecimal(uintmax_t value) { } while(value); buffer[size] = 0; - char result[length + 1]; + unsigned length = (length_ == 0 ? size : length_); + char result[64]; memset(result, ' ', length); result[length] = 0; @@ -146,10 +149,10 @@ template inline string ldecimal(uintmax_t value) { result[x] = buffer[y]; } - return result; + return (const char*)result; } -template inline string rdecimal(uintmax_t value) { +template inline string rdecimal(uintmax_t value) { char buffer[64]; unsigned size = 0; @@ -160,7 +163,8 @@ template inline string rdecimal(uintmax_t value) { } while(value); buffer[size] = 0; - char result[length + 1]; + unsigned length = (length_ == 0 ? size : length_); + char result[64]; memset(result, ' ', length); result[length] = 0; @@ -168,53 +172,51 @@ template inline string rdecimal(uintmax_t value) { result[x] = buffer[y]; } - return result; + return (const char*)result; } -template inline string hex(uintmax_t value) { - string output; - unsigned offset = 0; +template inline string hex(uintmax_t value) { + char buffer[64]; + unsigned size = 0; - //render string backwards, as we do not know its length yet do { unsigned n = value & 15; - output[offset++] = n < 10 ? '0' + n : 'a' + n - 10; + buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10; value >>= 4; } while(value); - while(offset < length) output[offset++] = '0'; - output[offset--] = 0; + unsigned length = (length_ == 0 ? size : length_); + char result[64]; + memset(result, '0', length); + result[length] = 0; - //reverse the string in-place - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; + for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { + result[x] = buffer[y]; } - return output; + return (const char*)result; } -template inline string binary(uintmax_t value) { - string output; - unsigned offset = 0; +template inline string binary(uintmax_t value) { + char buffer[256]; + unsigned size = 0; do { unsigned n = value & 1; - output[offset++] = '0' + n; + buffer[size++] = '0' + n; value >>= 1; } while(value); - while(offset < length) output[offset++] = '0'; - output[offset--] = 0; + unsigned length = (length_ == 0 ? size : length_); + char result[64]; + memset(result, '0', length); + result[length] = 0; - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; + for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { + result[x] = buffer[y]; } - return output; + return (const char*)result; } //using sprintf is certainly not the most ideal method to convert