Usermode/libc++_extras - Work on a C++ printf implementation (no formatters written...
authorJohn Hodge <[email protected]>
Tue, 2 Sep 2014 05:24:25 +0000 (13:24 +0800)
committerJohn Hodge <[email protected]>
Tue, 2 Sep 2014 05:24:25 +0000 (13:24 +0800)
Usermode/Libraries/libc++_extras.so_src/Makefile [new file with mode: 0644]
Usermode/Libraries/libc++_extras.so_src/TEST_cprintf.cpp [new file with mode: 0644]
Usermode/Libraries/libc++_extras.so_src/include_exp/cxxextras_printf [new file with mode: 0644]

diff --git a/Usermode/Libraries/libc++_extras.so_src/Makefile b/Usermode/Libraries/libc++_extras.so_src/Makefile
new file mode 100644 (file)
index 0000000..a27ba3b
--- /dev/null
@@ -0,0 +1,20 @@
+# Acess2 Basic C Library
+# Makefile
+
+-include ../Makefile.cfg
+
+CPPFLAGS += 
+CXXFLAGS += -Wall -Werror -Wextra -std=c++11
+CFLAGS   += -Wall -Werror -Wextra
+ASFLAGS  +=
+LDFLAGS  += 
+LIBS     += -lc++
+
+include ../Makefile.tpl
+
+EXP_%.txt: TEST_%.native
+       ./$< > $@
+       rm $<
+
+%.native: %.cpp
+       $(NCXX) $< -o $@ -Wall -std=c++11 -I include_exp/
diff --git a/Usermode/Libraries/libc++_extras.so_src/TEST_cprintf.cpp b/Usermode/Libraries/libc++_extras.so_src/TEST_cprintf.cpp
new file mode 100644 (file)
index 0000000..6c02bd2
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ */
+#include <cxxextras_printf>
+#include <cstdio>
+
+int main()
+{
+       ::cxxextras::cprintf(
+               [](const char *str, size_t len){printf("%.*s", (unsigned int)len, str); return len;},
+               "%s %i %+#-010x",
+               "hello_world",
+               1337,
+               0x1234565);
+       return 0;
+}
+
diff --git a/Usermode/Libraries/libc++_extras.so_src/include_exp/cxxextras_printf b/Usermode/Libraries/libc++_extras.so_src/include_exp/cxxextras_printf
new file mode 100644 (file)
index 0000000..952c06a
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ */
+#ifndef _LIBCXXEXTRAS_PRINTF_
+#define _LIBCXXEXTRAS_PRINTF_
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstdio>
+#include <functional>
+
+namespace cxxextras {
+
+class cprintf_toomanyargs:
+       public ::std::exception
+{
+};
+class cprintf_toofewargs:
+       public ::std::exception
+{
+};
+class cprintf_badformat:
+       public ::std::exception
+{
+       const char *m_reason;
+public:
+       cprintf_badformat(const char *reason):
+               m_reason(reason)
+       {
+       }
+       const char* what() const noexcept override {
+               return m_reason;
+       }
+};
+
+namespace _bits {
+
+typedef ::std::function<size_t(const char*,size_t)>    t_cprintf_callback;
+
+enum e_cprintf_type
+{
+       TYPE_AUTO,
+       TYPE_BOOLEAN,
+       TYPE_BINARY,
+       TYPE_OCT,
+       TYPE_INT,
+       TYPE_INTU,
+       TYPE_INTS,
+       TYPE_HEXLC,
+       TYPE_HEXUC,
+       TYPE_STRING,
+};
+
+struct PrintfFlags
+{
+       unsigned int width;
+       unsigned int precision;
+       unsigned int flags;
+       
+       struct Left {};
+       constexpr PrintfFlags(PrintfFlags x, Left  _): width(x.width), precision(x.precision), flags(x.flags | 1) {}
+       struct Sign {};
+       constexpr PrintfFlags(PrintfFlags x, Sign  _): width(x.width), precision(x.precision), flags(x.flags | 2) {}
+       struct Space {};
+       constexpr PrintfFlags(PrintfFlags x, Space _): width(x.width), precision(x.precision), flags(x.flags | 4) {}
+       struct Alt {};
+       constexpr PrintfFlags(PrintfFlags x, Alt   _): width(x.width), precision(x.precision), flags(x.flags | 8) {}
+       struct Zero {};
+       constexpr PrintfFlags(PrintfFlags x, Zero  _): width(x.width), precision(x.precision), flags(x.flags | 16) {}
+       
+       struct ArgWidth {};
+       constexpr PrintfFlags(PrintfFlags x, ArgWidth _, unsigned int v): width(v), precision(x.precision), flags(x.flags) {}
+       struct ArgPrec {};
+       constexpr PrintfFlags(PrintfFlags x, ArgPrec  _, unsigned int v): width(x.width), precision(v), flags(x.flags) {}
+       
+       struct FAuto {};
+       constexpr PrintfFlags(PrintfFlags x, FAuto   _): width(x.width), precision(x.precision), flags(x.flags | 0x000) {}
+       struct FString {};
+       constexpr PrintfFlags(PrintfFlags x, FString _): width(x.width), precision(x.precision), flags(x.flags | 0x100) {}
+       struct FBool {};
+       constexpr PrintfFlags(PrintfFlags x, FBool   _): width(x.width), precision(x.precision), flags(x.flags | 0x200) {}
+       struct FBinary {};
+       constexpr PrintfFlags(PrintfFlags x, FBinary _): width(x.width), precision(x.precision), flags(x.flags | 0x300) {}
+       struct FOct {};
+       constexpr PrintfFlags(PrintfFlags x, FOct   _): width(x.width), precision(x.precision), flags(x.flags | 0x400) {}
+       struct FUDec {};
+       constexpr PrintfFlags(PrintfFlags x, FUDec  _): width(x.width), precision(x.precision), flags(x.flags | 0x500) {}
+       struct FSDec {};
+       constexpr PrintfFlags(PrintfFlags x, FSDec  _): width(x.width), precision(x.precision), flags(x.flags | 0x600) {}
+       struct FHexL {};
+       constexpr PrintfFlags(PrintfFlags x, FHexL  _): width(x.width), precision(x.precision), flags(x.flags | 0x700) {}
+       struct FHexU {};
+       constexpr PrintfFlags(PrintfFlags x, FHexU  _): width(x.width), precision(x.precision), flags(x.flags | 0x800) {}
+       
+       PrintfFlags():
+               width(0), precision(0), flags(0)
+       {
+       }
+};
+struct s_cprintf_fmt
+{
+       bool isValid = false;
+       unsigned int precision = 0;
+       unsigned int minLength = 0;
+       bool    padLeft = false;
+       bool    showSign = false;
+       bool    showSpace = false;
+       bool    altFormat = false;
+       bool    padZero = false;
+       enum e_cprintf_type     type;
+};
+
+constexpr bool isdigit_s(const char ch) {
+       return '0' <= ch && ch <= '9';
+}
+constexpr unsigned todigit(const char ch) {
+       return ch - '0';
+}
+       
+
+};     // namespace _bits
+
+template <typename Arg> size_t cprintf_val(_bits::t_cprintf_callback puts, const _bits::PrintfFlags &fmt, Arg arg);
+
+size_t cprintf_val(_bits::t_cprintf_callback puts, const _bits::PrintfFlags& fmt, const char* arg) {
+       unsigned int len;
+       for(len = 0; arg[len]; len ++)
+               ;
+       return puts(arg, len);
+}
+size_t cprintf_val(_bits::t_cprintf_callback puts, const _bits::PrintfFlags& fmt, int arg) {
+       size_t len = ::std::snprintf(nullptr, 0, "%i", arg);
+       char buf[len+1];
+       ::std::snprintf(buf, len+1, "%i", arg);
+       return puts(buf, len);
+}
+
+namespace _bits
+{
+namespace _printf
+{
+       size_t run(_bits::t_cprintf_callback puts, const char *fmt);
+       template <typename... Args> size_t run(_bits::t_cprintf_callback puts, const char * fmt, Args... args);
+
+       // --- Print formatted value
+       template <typename Fmt>
+       size_t run_fmt_done(_bits::t_cprintf_callback puts, const char * fmt, PrintfFlags item, Fmt fmtcode)
+       {
+               throw cprintf_toofewargs();
+       }
+       template <typename Fmt, typename Arg, typename... Args>
+       size_t run_fmt_done(_bits::t_cprintf_callback puts, const char * fmt, PrintfFlags item, Fmt fmtcode, Arg val,  Args... args)
+       {
+               return ::cxxextras::cprintf_val(puts, PrintfFlags(item, fmtcode), val) + run(puts, fmt+1, args...);
+       }
+       // --- Format code
+       template <typename ...Args>
+       size_t run_fmt_fmt(_bits::t_cprintf_callback puts, const char * fmt, PrintfFlags item, Args... args)
+       {
+               return *fmt == '\0' ? throw "ERROR: NUL byte in format specifier"
+                    : *fmt == '?' ? run_fmt_done(puts, fmt, item, PrintfFlags::FAuto(),  args...)
+                    : *fmt == 's' ? run_fmt_done(puts, fmt, item, PrintfFlags::FString(),args...)
+                    : *fmt == 'B' ? run_fmt_done(puts, fmt, item, PrintfFlags::FBool(),  args...)
+                    : *fmt == 'b' ? run_fmt_done(puts, fmt, item, PrintfFlags::FBinary(),args...)
+                    : *fmt == 'o' ? run_fmt_done(puts, fmt, item, PrintfFlags::FOct(),   args...)
+                    : *fmt == 'i' ? run_fmt_done(puts, fmt, item, PrintfFlags::FSDec(),  args...)
+                    : *fmt == 'u' ? run_fmt_done(puts, fmt, item, PrintfFlags::FUDec(),  args...)
+                    : *fmt == 'x' ? run_fmt_done(puts, fmt, item, PrintfFlags::FHexL(),  args...)
+                    : *fmt == 'X' ? run_fmt_done(puts, fmt, item, PrintfFlags::FHexU(),  args...)
+                    : throw cprintf_badformat("Unknown character in format string");
+       }
+       // --- Size modifier (not implemented, not needed?)
+       template <typename ...Args>
+       size_t run_fmt_size(_bits::t_cprintf_callback puts, const char * fmt, PrintfFlags item, Args... args)
+       {
+               // TODO: Size characters?
+               return run_fmt_fmt(puts, fmt, item, args...);
+       }
+       // --- Precision
+       template <typename ...Args>
+       size_t run_fmt_prec_val(_bits::t_cprintf_callback puts, const char * fmt, unsigned int val, PrintfFlags item, Args... args)
+       {
+               return _bits::isdigit_s(*fmt) ? run_fmt_prec_val(puts, fmt+1, val*10+_bits::todigit(*fmt), item, args...)
+                    : run_fmt_size(puts, fmt, PrintfFlags(item, PrintfFlags::ArgPrec(), val), args...);
+       }
+       template <typename ...Args>
+       size_t run_fmt_prec_arg(_bits::t_cprintf_callback puts, const char *fmt, PrintfFlags item, unsigned int size, Args... args)
+       {
+               return run_fmt_prec_opt(puts, fmt, PrintfFlags(item, PrintfFlags::ArgPrec(), size), args...);
+       }
+       template <typename Arg, typename ...Args>
+       size_t run_fmt_prec_arg(_bits::t_cprintf_callback puts, const char *fmt, PrintfFlags item, Arg size, Args... args)
+       {
+               throw cprintf_badformat("Invalid type for printf precision modifier");
+       }
+       size_t run_fmt_prec_arg(_bits::t_cprintf_callback puts, const char *fmt, PrintfFlags item)
+       {
+               throw cprintf_toofewargs();
+       }
+       template <typename ...Args>
+       size_t run_fmt_prec(_bits::t_cprintf_callback puts, const char * fmt, PrintfFlags item, Args... args)
+       {
+               return _bits::isdigit_s(*fmt) ? run_fmt_prec_val(puts, fmt+1, _bits::todigit(*fmt), item, args...)
+                    : *fmt == '*' ? run_fmt_prec_arg(puts, fmt+1, item, args...)
+                    : run_fmt_size(puts, fmt, item, args...);
+       }
+       template <typename ...Args>
+       size_t run_fmt_prec_opt(_bits::t_cprintf_callback puts, const char * fmt, PrintfFlags item, Args... args)
+       {
+               return *fmt == '.' ? run_fmt_prec(puts, fmt+1, item, args...)
+                    : run_fmt_size(puts, fmt, item, args...);
+       }
+       // --- Field Width ---  
+       template <typename ...Args>
+       size_t run_fmt_width_val(_bits::t_cprintf_callback puts, const char * fmt, unsigned int val, PrintfFlags item, Args... args)
+       {
+               return  _bits::isdigit_s(*fmt) ? run_fmt_width_val(puts, fmt+1, val*10+_bits::todigit(*fmt), item, args...)
+                     : run_fmt_prec_opt(puts, fmt, PrintfFlags(item, PrintfFlags::ArgWidth(), val), args...);
+       }
+       template <typename ...Args>
+       size_t run_fmt_width_arg(_bits::t_cprintf_callback puts, const char *fmt, PrintfFlags item, unsigned int size, Args... args)
+       {
+               return run_fmt_prec_opt(puts, fmt, PrintfFlags(item, PrintfFlags::ArgWidth(), size), args...);
+       }
+       template <typename Arg, typename ...Args>
+       size_t run_fmt_width_arg(_bits::t_cprintf_callback puts, const char *fmt, PrintfFlags item, Arg size, Args... args)
+       {
+               throw cprintf_badformat("Invalid type for printf width modifier");
+       }
+       size_t run_fmt_width_arg(_bits::t_cprintf_callback puts, const char *fmt, PrintfFlags item)
+       {
+               throw cprintf_toofewargs();
+       }
+       template <typename ...Args>
+       size_t run_fmt_width(_bits::t_cprintf_callback puts, const char * fmt, PrintfFlags item, Args... args)
+       {
+               return _bits::isdigit_s(*fmt) ? run_fmt_width_val(puts, fmt+1, _bits::todigit(*fmt), item, args...)
+                    : *fmt == '*' ? run_fmt_width_arg(puts, fmt+1, item, args...)
+                    : run_fmt_prec_opt(puts, fmt, item, args...);
+       }
+       // --- Flags
+       template <typename ...Args>
+       size_t run_fmt_flags(_bits::t_cprintf_callback puts, const char * fmt, PrintfFlags item, Args... args)
+       {
+               return
+                 *fmt == '-' ? run_fmt_flags(puts, fmt+1, PrintfFlags(item, PrintfFlags::Left()) , args...)
+               : *fmt == '+' ? run_fmt_flags(puts, fmt+1, PrintfFlags(item, PrintfFlags::Sign()) , args...)
+               : *fmt == ' ' ? run_fmt_flags(puts, fmt+1, PrintfFlags(item, PrintfFlags::Space()), args...)
+               : *fmt == '#' ? run_fmt_flags(puts, fmt+1, PrintfFlags(item, PrintfFlags::Alt())  , args...)
+               : *fmt == '0' ? run_fmt_flags(puts, fmt+1, PrintfFlags(item, PrintfFlags::Zero()) , args...)
+               : run_fmt_width(puts, fmt, item, args...);
+       }
+       // --- Literal '%'
+       template <typename ...Args>
+       size_t run_fmt_start(_bits::t_cprintf_callback puts, const char * fmt, Args... args)
+       {
+               //printf("> DEBUG: '%s'\n", fmt);
+               return *fmt == '%'
+                       ? (puts("%", 1), 1 + run(puts, fmt+1, args...))
+                       : run_fmt_flags(puts, fmt, PrintfFlags(), args...);
+       }
+       // --- Root
+       template <typename... Args>
+       size_t run(_bits::t_cprintf_callback puts, const char * fmt, Args... args)
+       {
+               int ofs;
+               for( ofs = 0; fmt[ofs] != '\0' && fmt[ofs] != '%'; ofs ++ )
+                       ;
+               if( fmt[ofs] != '%' )
+                       throw cprintf_toomanyargs();
+               if(ofs > 0) puts(fmt, ofs);
+               //printf("> DEBUG: run: '%s'\n", fmt+ofs);
+               return ofs + run_fmt_start(puts, fmt+ofs+1, args...);
+       }
+       size_t run(_bits::t_cprintf_callback puts, const char *fmt)
+       {
+               int ofs;
+               for( ofs = 0; fmt[ofs] != '\0' && fmt[ofs] != '%'; ofs ++ )
+                       ;
+               if( fmt[ofs] == '%' )
+                       throw cprintf_toofewargs();
+               if(ofs > 0) puts(fmt, ofs);
+               return ofs;
+       }
+
+}
+
+};     // namespace _bits
+
+template <typename ... Args>
+size_t cprintf(_bits::t_cprintf_callback puts, const char *fmt, Args... args)
+{
+       return _bits::_printf::run(puts, fmt, args...);
+}
+
+};
+
+#endif
+
+// vim: ft=cpp
+

UCC git Repository :: git.ucc.asn.au