diff options
Diffstat (limited to 'includes')
-rw-r--r-- | includes/BString.h | 97 | ||||
-rw-r--r-- | includes/Exceptions.h | 30 | ||||
-rw-r--r-- | includes/Local.h | 37 | ||||
-rw-r--r-- | includes/Main.h | 118 | ||||
-rw-r--r-- | includes/Printer.h | 45 |
5 files changed, 327 insertions, 0 deletions
diff --git a/includes/BString.h b/includes/BString.h new file mode 100644 index 0000000..5356310 --- /dev/null +++ b/includes/BString.h @@ -0,0 +1,97 @@ +#pragma once + +#include <stdarg.h> +#include <string.h> +#include <stdint.h> +#include <malloc.h> +#include <stdlib.h> +#include <string> + +namespace Balau { + +class String : private std::string { + public: + String() : std::string() { } + String(const char * str) : std::string(str) { } + String(const char * str, size_t n) : std::string(str, n) { } + String(char c) { set("%c", c); } + String(int32_t i) { set("%i", i); } + String(uint32_t i) { set("%u", i); } + String(int64_t i) { set("%lli", i); } + String(uint64_t i) { set("%llu", i); } + String(double d) { set("%g", d); } + String(const String & s) : std::string(s) { } + String(const std::string & s) : std::string(s) { } + + void set(const char * fmt, va_list); + void set(const char * fmt, ...) { va_list ap; va_start(ap, fmt); set(fmt, ap); va_end(ap); } + void set(const String & fmt, ...) { va_list ap; va_start(ap, fmt); set(fmt.to_charp(), ap); va_end(ap); } + + int scanf(const char * fmt, va_list ap) const { return ::vsscanf(c_str(), fmt, ap); } + int scanf(const char * fmt, ...) const { va_list ap; va_start(ap, fmt); int r = scanf(fmt, ap); va_end(ap); return r; } + int scanf(const String & fmt, ...) const { va_list ap; va_start(ap, fmt); int r = scanf(fmt.to_charp(), ap); va_end(ap); return r; } + + const char * to_charp(size_t begin = 0) const { return c_str() + begin; } + String extract(size_t begin = 0, size_t size = static_cast<size_t>(-1)) const { return substr(begin, size); } + char * strdup(size_t begin = 0, size_t size = static_cast<size_t>(-1)) const { + if (begin == 0) + return ::strdup(to_charp()); + else + return ::strdup(extract(begin, size).to_charp()); + } + + int to_int(int base = 0) const { return strtol(to_charp(), NULL, base); } + double to_double() const { return strtod(to_charp(), NULL); } + + size_t strlen() const { return std::string::length(); } + ssize_t strchr(char c, size_t begin = 0) const { return find(c, begin); } + ssize_t strrchr(char c) const { return rfind(c); } + ssize_t strstr(const String & s, size_t begin = 0) const { return find(std::string(s), begin); } + ssize_t strstr(const char * s, size_t begin = 0) const { return find(std::string(s), begin); } + int strchrcnt(char) const; + + String ltrim() const { String c = *this; return c.do_ltrim(); } + String rtrim() const { String c = *this; return c.do_rtrim(); } + String trim() const { String c = *this; return c.do_trim(); } + String upper() const { String c = *this; return c.do_upper(); } + String lower() const { String c = *this; return c.do_lower(); } + String iconv(const String & from, const String & to) const { String c = *this; c.do_iconv(from.to_charp(), to.to_charp()); return c; } + String iconv(const char * from, const char * to) const { String c = *this; c.do_iconv(from, to); return c; } + + String & do_ltrim(); + String & do_rtrim(); + String & do_trim() { return do_ltrim().do_rtrim(); } + String & do_upper(); + String & do_lower(); + String & do_iconv(const String & from, const String & to) { return do_iconv(from.to_charp(), to.to_charp()); } + String & do_iconv(const char * from, const char * to); + + String & operator=(const String & v) { *((std::string *) this) = std::string::assign(v); return *this; } + String & operator=(const char * v) { *((std::string *) this) = std::string::assign(v); return *this; } + + String operator+(const String & v) const { String r = *this; r += v; return r; } + String operator+(const char * v) const { String r = *this; r += v; return r; } + String & operator+=(const String & v) { *this = append(v); return *this; } + String & operator+=(const char * v) { *this = append(v); return *this; } + + int compare(const String & v) const { return std::string::compare(v); } + int compare(const char * v) const { return std::string::compare(v); } + + bool operator==(const String & v) const { return compare(v) == 0; } + bool operator==(const char * v) const { return compare(v) == 0; } + bool operator!=(const String & v) const { return compare(v) != 0; } + bool operator!=(const char * v) const { return compare(v) != 0; } + bool operator<(const String & v) const { return compare(v) < 0; } + bool operator<(const char * v) const { return compare(v) < 0; } + bool operator<=(const String & v) const { return compare(v) <= 0; } + bool operator<=(const char * v) const { return compare(v) <= 0; } + bool operator>(const String & v) const { return compare(v) > 0; } + bool operator>(const char * v) const { return compare(v) > 0; } + bool operator>=(const String & v) const { return compare(v) >= 0; } + bool operator>=(const char * v) const { return compare(v) >= 0; } + + const char & operator[](size_t i) const { return at(i); } + char & operator[](size_t i) { return at(i); } +}; + +}; diff --git a/includes/Exceptions.h b/includes/Exceptions.h new file mode 100644 index 0000000..39f3239 --- /dev/null +++ b/includes/Exceptions.h @@ -0,0 +1,30 @@ +#pragma once + +#include <BString.h> + +namespace Balau { + +class GeneralException { + public: + GeneralException(const char * msg) : m_msg(::strdup(msg)) { } + GeneralException(const String & msg) : m_msg(msg.strdup()) { } + GeneralException(const GeneralException & e) : m_msg(strdup(e.m_msg)) { } + ~GeneralException() { if (m_msg) free(m_msg); } + const char * getMsg() const { return m_msg; } + + protected: + GeneralException() : m_msg(0) { } + void setMsg(char * msg) { if (m_msg) free(m_msg); m_msg = msg; } + private: + char * m_msg; +}; + +static inline void AssertHelper(const String & msg) throw(GeneralException) { throw GeneralException(msg); } + +}; + +#define Assert(c) if (!(c)) { \ + Balau::String msg; \ + msg.set("Assertion " #c " failed at %s:%i", __FILE__, __LINE__); \ + Balau::AssertHelper(msg); \ +} diff --git a/includes/Local.h b/includes/Local.h new file mode 100644 index 0000000..f3b7250 --- /dev/null +++ b/includes/Local.h @@ -0,0 +1,37 @@ +#pragma once + +#include <Main.h> + +namespace Balau { + +class TLSManager { + public: + virtual void * getTLS(); + virtual void * setTLS(void * val); +}; + +extern TLSManager * tlsManager; + +class Local : public AtStart { + public: + static int getSize() { return s_size; } + protected: + Local() : AtStart(0) { } + void * getGlobal() { return m_globals[m_idx]; } + void * getLocal() { return reinterpret_cast<void **>(getTLS())[m_idx]; } + void * get() { if (getTLS()) { void * l = getLocal(); return l ? l : getGlobal(); } else return getGlobal(); } + void setGlobal(void * obj) { m_globals[m_idx] = obj; } + void setLocal(void * obj) { void * r = getTLS(); reinterpret_cast<void **>(r)[m_idx] = obj; } + void set(void * obj) { void * r = getTLS(); if (r) setGlobal(obj); else setLocal(obj); } + int getIndex() { return m_idx; } + private: + static void * create() { void * r = malloc(s_size * sizeof(void *)); setTLS(r); return r; } + static void * getTLS() { return tlsManager->getTLS(); } + static void * setTLS(void * val) { return tlsManager->setTLS(val); } + virtual void doStart(); + int m_idx; + static int s_size; + static void ** m_globals; +}; + +}; diff --git a/includes/Main.h b/includes/Main.h new file mode 100644 index 0000000..eee7ff7 --- /dev/null +++ b/includes/Main.h @@ -0,0 +1,118 @@ +#pragma once + +#include <Exceptions.h> + +namespace Balau { + +class AtStart { + protected: + AtStart(int priority = 0); + virtual void doStart() = 0; + private: + const int m_priority; + AtStart * m_next; + static AtStart * s_head; + friend class Main; +}; + +class AtExit { + protected: + AtExit(int priority = 0); + virtual void doExit() = 0; + private: + const int m_priority; + AtExit * m_next; + static AtExit * s_head; + friend class Main; +}; + +class Exit : public GeneralException { + public: + Exit(int code = -1) : GeneralException(), m_code(code) { String s; s.set("Application exitting with code = %i", code); setMsg(s.strdup()); } + int getCode() { return m_code; } + private: + int m_code; +}; + +}; + +#include <Printer.h> + +namespace Balau { + +class Main { + public: + enum Status { + UNKNOWN = 0, + STARTING, + RUNNING, + STOPPING, + STOPPED, + }; + Main() : m_status(UNKNOWN) { application = this; } + virtual int startup() throw (GeneralException) = 0; + static Status status() { return application->m_status; } + int bootstrap(int _argc, char ** _argv) { + int r; + m_status = STARTING; + + argc = _argc; + argv = _argv; + enve = NULL; + + for (AtStart * ptr = AtStart::s_head; ptr; ptr = ptr->m_next) + ptr->doStart(); + + try { + m_status = RUNNING; + r = startup(); + m_status = STOPPING; + } + catch (Exit e) { + m_status = STOPPING; + r = e.getCode(); + } + catch (GeneralException e) { + m_status = STOPPING; + Printer::log(M_ERROR | M_ALERT, "The application caused an exception: %s", e.getMsg()); + r = -1; + } + catch (...) { + m_status = STOPPING; + Printer::log(M_ERROR | M_ALERT, "The application caused an unknown exception"); + r = -1; + } + m_status = STOPPING; + + for (AtExit * ptr = AtExit::s_head; ptr; ptr = ptr->m_next) + ptr->doExit(); + + m_status = STOPPED; + return r; + } + protected: + int argc; + char ** argv; + char ** enve; + private: + Status m_status; + static Main * application; +}; + +#define BALAU_STARTUP \ +\ +class Application : public Balau::Main { \ + public: \ + virtual int startup() throw (Balau::GeneralException); \ +}; \ +\ +static Application application; \ +\ +extern "C" { \ + int main(int argc, char ** argv) { \ + setlocale(LC_ALL, ""); \ + return application.bootstrap(argc, argv); \ + } \ +} + +}; diff --git a/includes/Printer.h b/includes/Printer.h new file mode 100644 index 0000000..b55df22 --- /dev/null +++ b/includes/Printer.h @@ -0,0 +1,45 @@ +#pragma once + +#include <BString.h> + +namespace Balau { + +enum { + M_DEBUG = 1, + M_INFO = 2, + M_STATUS = 4, + M_WARNING = 8, + M_ERROR = 16, + M_ALERT = 32, + + M_ALL = M_DEBUG | M_INFO | M_STATUS | M_WARNING | M_ERROR | M_ALERT, + M_MAX = M_ALERT, +}; + +class Printer { + protected: + virtual void _print(const char * fmt, va_list ap); + + private: + void _log(uint32_t level, const char * fmt, va_list ap); + static Printer * getPrinter(); + + public: + Printer(); + + void setLocal(); + + static void log(uint32_t level, const String & fmt, ...) { va_list ap; va_start(ap, fmt); log(level, fmt.to_charp(), ap); va_end(ap); } + static void log(uint32_t level, const char * fmt, ...) { va_list ap; va_start(ap, fmt); log(level, fmt, ap); va_end(ap); } + static void log(uint32_t level, const char * fmt, va_list ap) { getPrinter()->_log(level, fmt, ap); } + static void print(const String & fmt, ...) { va_list ap; va_start(ap, fmt); print(fmt.to_charp(), ap); va_end(ap); } + static void print(const char * fmt, ...) { va_list ap; va_start(ap, fmt); print(fmt, ap); va_end(ap); } + static void print(const char * fmt, va_list ap) { getPrinter()->_print(fmt, ap); } + + void enable(uint32_t levels = M_ALL) { m_verbosity |= levels; } + void disable(uint32_t levels = M_ALL) { m_verbosity &= ~levels; } + + uint32_t m_verbosity; +}; + +}; |