osh.h

My personal stdc++ replacement
git clone git://git.oshgnacknak.de/osh.h.git
Log | Files | Refs | README

osh.h (10410B)


      1 #ifndef OSH_H
      2 #define OSH_H 
      3 
      4 #define OSH_H_VERSION 1.0
      5 
      6 #include <stdio.h>
      7 
      8 namespace osh {
      9 
     10     template<typename T, typename P>
     11     concept PrintableTo = requires(T t, P p) {
     12         print1(p, t);
     13     };
     14 
     15     template<typename T>
     16     concept Formatter = requires(T t) {
     17         t.format("If it supports %s, it suppots %p!!1%d!elf", "printf", "printp", 1);
     18     };
     19 
     20     class FileFormatter {
     21         FILE* stream;
     22 
     23         public:
     24         FileFormatter(FILE* stream);
     25 
     26         template<typename... Args>
     27         void format(const char* fmt, Args&&...);
     28         void flush();
     29     };
     30 
     31     extern FileFormatter fout;
     32     extern FileFormatter ferr;
     33 
     34     template<typename P, PrintableTo<P>... Args>
     35     void printp(P&, Args...);
     36 
     37     template<PrintableTo<FileFormatter>... Args>
     38     void print(Args&&...);
     39     template<PrintableTo<FileFormatter>... Args>
     40     void println(Args&&...);
     41 
     42     template<PrintableTo<FileFormatter>... Args>
     43     void eprint(Args&&...);
     44     template<PrintableTo<FileFormatter>... Args>
     45     void eprintln(Args&&...);
     46 
     47     void print1(Formatter auto&, const char*);
     48     void print1(Formatter auto&, char*);
     49     template<typename T> void print1(Formatter auto&, const T*);
     50     void print1(Formatter auto&, const char&);
     51     void print1(Formatter auto&, const int&);
     52     void print1(Formatter auto&, const short int&);
     53     void print1(Formatter auto&, const long int&);
     54     void print1(Formatter auto&, const long long int&);
     55     void print1(Formatter auto&, const unsigned char&);
     56     void print1(Formatter auto&, const unsigned int&);
     57     void print1(Formatter auto&, const unsigned short int&);
     58     void print1(Formatter auto&, const unsigned long int&);
     59     void print1(Formatter auto&, const unsigned long long int&);
     60     void print1(Formatter auto&, const float&);
     61     void print1(Formatter auto&, const double&);
     62     void print1(Formatter auto&, const long double&);
     63 
     64     template<PrintableTo<FileFormatter>... Args>
     65     [[noreturn]] void panic(Args&&... args);
     66 
     67     template<typename... Args>
     68     void assert(bool condition, Args&&... args);
     69 
     70     template<typename T>
     71     concept Destructible = requires(T t) {
     72         t.destruct();
     73     };
     74 
     75     template<Destructible T>
     76     struct AutoDestruct : public T {
     77         template<typename... Args>
     78         AutoDestruct(Args&&... args);
     79 
     80         ~AutoDestruct();
     81     };
     82 
     83     template<typename T>
     84     class DArray {
     85     protected:
     86         T* elements;
     87         size_t size_ = 0;
     88         size_t capacity;
     89     public:
     90         DArray(size_t = 10);
     91         void destruct();
     92         size_t size() const;
     93         void setSize(size_t);
     94         void growToCapacity(size_t);
     95         void ensureCapacity(size_t);
     96         void push(const T&);
     97         void clear();
     98         T& operator[](ssize_t);
     99     };
    100 
    101     template<Destructible T>
    102     AutoDestruct<T> autoDestruct(T t);
    103 
    104     class StringBuffer : public DArray<char> {
    105     public:
    106         StringBuffer(size_t = 10);
    107         StringBuffer(const char*);
    108         char* cstr() const;
    109         template<typename... Args> void format(const char* fmt, Args&&...);
    110         StringBuffer substr(ssize_t begin, ssize_t end) const;
    111         void setSize(size_t);
    112         char& operator[](int index);
    113     };
    114 
    115     void print1(Formatter auto&, const StringBuffer&);
    116 
    117     StringBuffer fileContentAsBuffer(const char* filename);
    118 
    119     int listIndex(int index, const int& size);
    120 
    121     template<typename T>
    122     void swap(T& a, T& b);
    123 
    124     template<typename T>
    125     T min(T a, T b);
    126     
    127     template<typename T>
    128     T max(T a, T b);
    129 }
    130 
    131 #endif /* OSH_H */
    132 
    133 #ifdef OSH_H_IMPLEMENTATION
    134 
    135 #include <stdlib.h>
    136 #include <string.h>
    137 
    138 namespace osh {
    139 
    140     void print1(Formatter auto& fmt, const char* s) {
    141         fmt.format("%s", s);
    142     }
    143 
    144     void print1(Formatter auto& fmt, char* s) {
    145         fmt.format("%s", s);
    146     }
    147 
    148     template<typename T>
    149     void print1(Formatter auto& fmt, const T* p) {
    150         fmt.format("%p", p);
    151     }
    152 
    153     void print1(Formatter auto& fmt, const char& c) {
    154         fmt.format("%c", c);
    155     }
    156 
    157     void print1(Formatter auto& fmt, const int& n) {
    158         fmt.format("%d", n);
    159     }
    160 
    161     void print1(Formatter auto& fmt, const short int& n) {
    162         fmt.format("%d", n);
    163     }
    164 
    165     void print1(Formatter auto& fmt, const long int& n) {
    166         fmt.format("%ld", n);
    167     }
    168 
    169     void print1(Formatter auto& fmt, const long long int& n) {
    170         fmt.format("%lld", n);
    171     }
    172 
    173     void print1(Formatter auto& fmt, const unsigned char& c) {
    174         printp(fmt, (char) c);
    175     }
    176 
    177     void print1(Formatter auto& fmt, const unsigned int& n) {
    178         fmt.format("%u", n);
    179     }
    180 
    181     void print1(Formatter auto& fmt, const unsigned short int& n) {
    182         fmt.format("%lu", n);
    183     }
    184 
    185     void print1(Formatter auto& fmt, const unsigned long int& n) {
    186         fmt.format("%llu", n);
    187     }
    188 
    189     void print1(Formatter auto& fmt, const unsigned long long int& n) {
    190         fmt.format("%llu", n);
    191     }
    192 
    193     void print1(Formatter auto& fmt, const float& f) {
    194         fmt.format("%f", f);
    195     }
    196 
    197     void print1(Formatter auto& fmt, const double& d) {
    198         fmt.format("%f", d);
    199     }
    200 
    201     void print1(Formatter auto& fmt, const long double& d) {
    202         fmt.format("%Lf", d);
    203     }
    204 
    205     template<typename P, PrintableTo<P>... Args>
    206     void printp(P& p, Args... args) {
    207         (print1(p, args), ...);
    208     }
    209 
    210     template<PrintableTo<FileFormatter>... Args>
    211     void print(Args&&... args) {
    212         printp(fout, args...);
    213     }
    214 
    215     template<PrintableTo<FileFormatter>... Args>
    216     void println(Args&&... args) {
    217         printp(fout, args..., '\n');
    218     }
    219 
    220     template<PrintableTo<FileFormatter>... Args>
    221     void eprint(Args&&... args) {
    222         printp(ferr, args...);
    223     }
    224 
    225     template<PrintableTo<FileFormatter>... Args>
    226     void eprintln(Args&&... args) {
    227         printp(ferr, args..., '\n');
    228     }
    229 
    230     FileFormatter fout(stdout);
    231     FileFormatter ferr(stderr);
    232 
    233     FileFormatter::FileFormatter(FILE* stream)
    234         : stream(stream) {}
    235 
    236     template<typename... Args>
    237     void FileFormatter::format(const char* fmt, Args&&... args) {
    238         fprintf(stream, fmt, args...);
    239     }
    240 
    241     void FileFormatter::flush() {
    242        fflush(stream);
    243     }
    244 
    245     template<PrintableTo<FileFormatter>... Args>
    246     void panic(Args&&... args) {
    247         printp(ferr, args...);
    248         exit(1);
    249     }
    250 
    251     template<typename... Args>
    252     void assert(bool condition, Args&&... args) {
    253         if (!condition) {
    254             if (sizeof...(Args) > 0) {
    255                 panic(args...);
    256             } else {
    257                 panic("Assertion failed");
    258             }
    259         }
    260     }
    261 
    262     template<typename T>
    263     template<typename... Args>
    264     AutoDestruct<T>::AutoDestruct(Args&&... args) : T(args...) {}
    265 
    266     template<Destructible T>
    267     AutoDestruct<T>::~AutoDestruct() {
    268         this->destruct();
    269     }
    270 
    271     template<Destructible T>
    272     AutoDestruct<T> autoDestruct(T t) {
    273         return (AutoDestruct<T>) t;
    274     }
    275 
    276 
    277     template<typename T>
    278     DArray<T>::DArray(size_t capacity) : capacity(capacity) {
    279         elements = (T*) malloc(sizeof(T) * capacity);
    280     }
    281 
    282     template<typename T>
    283     void DArray<T>::destruct() {
    284         if (elements != nullptr) {
    285             free(elements);
    286         }
    287     }
    288 
    289     template<typename T>
    290     size_t DArray<T>::size() const {
    291         return size_;
    292     }
    293 
    294     template<typename T>
    295     void DArray<T>::setSize(size_t newSize) {
    296         growToCapacity(newSize);
    297         size_ = newSize;
    298     }
    299 
    300     template<typename T>
    301     void DArray<T>::growToCapacity(size_t newCapacity) {
    302         if (newCapacity > capacity) {
    303             capacity = max(capacity *= 2, newCapacity);
    304             elements = (T*) realloc(elements, sizeof(T) * capacity);
    305         }
    306     }
    307 
    308     template<typename T>
    309     void DArray<T>::ensureCapacity(size_t required) {
    310         growToCapacity(size_ + required);
    311     }
    312 
    313     template<typename T>
    314     void DArray<T>::push(const T& t) {
    315         ensureCapacity(1);
    316         elements[size_++] = t;
    317     }
    318 
    319     template<typename T>
    320     void DArray<T>::clear() {
    321         setSize(0);
    322     }
    323 
    324     template<typename T>
    325     T& DArray<T>::operator[](ssize_t index) {
    326         index = listIndex(index, size_);
    327         return elements[index];
    328     }
    329 
    330     StringBuffer::StringBuffer(size_t capacity) : DArray(capacity) {
    331         if (capacity > 0) {
    332             elements[0] = '\0';
    333         }
    334     }
    335 
    336     StringBuffer::StringBuffer(const char* initial) : DArray(strlen(initial)) {
    337         size_ = capacity;
    338         memcpy(this->elements, initial, size_);
    339     }
    340 
    341     char* StringBuffer::cstr() const {
    342         return elements;
    343     }
    344 
    345     StringBuffer StringBuffer::substr(ssize_t begin, ssize_t end) const {
    346         begin = listIndex(begin, size_);
    347         end = listIndex(end, size_);
    348         assert(begin <= end);
    349 
    350         size_t size = end - begin + 1;
    351         StringBuffer s(size);
    352         s.size_ = size;
    353         memcpy(s.elements, elements + begin, size);
    354 
    355         return s;
    356     }
    357 
    358     void StringBuffer::setSize(size_t newSize) {
    359         DArray::setSize(newSize);
    360         if (capacity > 0) {
    361             elements[size_] = '\0';
    362         }
    363     }
    364 
    365     template<typename... Args>
    366     void StringBuffer::format(const char* fmt, Args&&... args) {
    367         int required = 1 + snprintf(nullptr, 0, fmt, args...);
    368         ensureCapacity(required);
    369         snprintf(elements + size_, required, fmt, args...);
    370         size_ += required - 1;
    371     }
    372 
    373     void print1(Formatter auto& fmt, const StringBuffer& s) {
    374         printp(fmt, s.cstr());
    375     }
    376 
    377     StringBuffer fileContentAsBuffer(const char* filename) {
    378         FILE* f = fopen(filename, "r");
    379         assert(f != NULL);
    380 
    381         fseek(f, 0, SEEK_END);
    382         int capacity = ftell(f);
    383         StringBuffer s(capacity);
    384         
    385         rewind(f);
    386         int read = fread(s.cstr(), sizeof(char), capacity, f);
    387         assert(read == capacity);
    388         
    389         s.setSize(capacity);
    390         return s;
    391     }
    392 
    393     int listIndex(int index, const int& size) {
    394         assert(index >= -size && index < size,
    395             "Index", index, "out of bounce");
    396 
    397         if (index < 0) {
    398             index += size;
    399         }
    400 
    401         return index;
    402     }
    403 
    404     template<typename T>
    405     void swap(T& a, T& b) {
    406         T t = a;
    407         a = b;
    408         b = t;
    409     }
    410 
    411     template<typename T>
    412     T min(T a, T b) {
    413         return a < b ? a : b;
    414     }
    415 
    416     template<typename T>
    417     T max(T a, T b) {
    418         return a > b ? a : b;
    419     }
    420 }
    421 
    422 #endif // OSH_H_IMPLEMENTATION