From 01aeacfde3e88e987f741ca0d2c6301700ef81fc Mon Sep 17 00:00:00 2001
From: Recolic <git@me.recolic.net>
Date: Tue, 31 Dec 2024 17:32:19 -0800
Subject: [PATCH] .

---
 standalone-toys/README.md                     |  13 +
 .../c-with-class.h                            |   0
 standalone-toys/rdebug.h                      |  79 ++++++
 standalone-toys/rlib.min.hpp                  | 243 ++++++++++++++++++
 4 files changed, 335 insertions(+)
 create mode 100644 standalone-toys/README.md
 rename c-with-class.h => standalone-toys/c-with-class.h (100%)
 create mode 100644 standalone-toys/rdebug.h
 create mode 100644 standalone-toys/rlib.min.hpp

diff --git a/standalone-toys/README.md b/standalone-toys/README.md
new file mode 100644
index 0000000..f951c64
--- /dev/null
+++ b/standalone-toys/README.md
@@ -0,0 +1,13 @@
+# Warning: This IS NOT single-file rlib header
+
+This directory contains useful standalone headers, for various c/cpp debugging.
+
+They **are not** part of rlib, and they are intended for situations while not practical to include a complete rlib.
+
+> DO NOT expect too much for these low-quality toys.
+
+|Header|Note|
+|------|----|
+|rdebug.h|Minimal C helper to print debug output|
+|c-with-class.h|Old fashioned trick used in some C homeworks|
+|rlib.min.hpp|Minimal io/string helper for solving OJ questions, or writing POC program|
diff --git a/c-with-class.h b/standalone-toys/c-with-class.h
similarity index 100%
rename from c-with-class.h
rename to standalone-toys/c-with-class.h
diff --git a/standalone-toys/rdebug.h b/standalone-toys/rdebug.h
new file mode 100644
index 0000000..c698284
--- /dev/null
+++ b/standalone-toys/rdebug.h
@@ -0,0 +1,79 @@
+/*
+Usage: Put this in /usr/bin/stdio.h
+
+#if __has_include("/home/recolic/sh/rdebug.h")
+#include "/home/recolic/sh/rdebug.h"
+#endif
+
+DO NOT modify this file directly. Please commit any change to ~/sh/rdebug.h
+version: 1.0.3
+
+changelog: 1.0.3: add print_time for c
+*/
+
+
+#ifndef RDB__H
+#define RDB__H
+#include <execinfo.h>
+#include <stdio.h>
+#include <stddef.h>
+#define RDEBUG(fmt, ...) fprintf(stderr, "RDEBUG: %s:%d(%s), " #fmt "\n" , __FILE__, __LINE__, __func__ __VA_OPT__(,) __VA_ARGS__ );
+
+#ifdef __cplusplus
+#include <ostream>
+#include <iomanip>
+#include <cstdint>
+
+[[maybe_unused]] inline
+#else
+__attribute__((unused)) static
+#endif
+void printbt() {
+    void *array[32];
+    int size;
+
+    // get void*'s for all entries on the stack
+    size = backtrace(array, 32);
+
+    // print out all the frames to stderr
+    backtrace_symbols_fd(array, size, 2);
+}
+
+
+#ifdef __cplusplus
+template <typename CharT>
+[[maybe_unused]] inline void print_buf(std::ostream& out, const char *title, const CharT *data, size_t dataLen) {
+    out << title << std::endl;
+    out << std::setfill('0');
+    for(size_t i = 0; i < dataLen; ++i) {
+        out << std::hex << std::setw(2) << (0x000000ff & (int32_t)(((const char *)data)[i]));
+        // format
+        out << (((i + 1) % 16 == 0) ? "\n" : " ");
+    }
+    out << std::endl;
+}
+inline void print_buf(std::ostream& out, const char *title, const std::string &data) {
+    return print_buf(out, title, data.data(), data.size());
+}
+#else
+__attribute__((unused)) static void print_buf(FILE *stream, const char *title, const unsigned char *buf, size_t buf_len)
+{
+    size_t i = 0;
+    fprintf(stream, "%s\n", title);
+    for(i = 0; i < buf_len; ++i)
+    fprintf(stream, "%02X%s", buf[i],
+             ( i + 1 ) % 16 == 0 ? "\r\n" : " " );
+    fprintf(stream, "\n");
+}
+#include <time.h>
+__attribute__((unused)) static void print_time(FILE *stream) {
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    // struct tm *my_tm = localtime(&ts.tv_sec);
+    fprintf(stream, "%lu.%lu\n", ts.tv_sec, ts.tv_nsec);
+}
+#endif
+
+#endif
+
+
diff --git a/standalone-toys/rlib.min.hpp b/standalone-toys/rlib.min.hpp
new file mode 100644
index 0000000..499f168
--- /dev/null
+++ b/standalone-toys/rlib.min.hpp
@@ -0,0 +1,243 @@
+/*
+ *
+ * string.hpp: string process utility.
+ * Recolic Keghart <root@recolic.net>
+ * MIT License
+ *
+ * Minified version: works on C++11.
+ *
+ */
+
+#ifndef R_STRING_HPP
+#define R_STRING_HPP
+
+#include <vector>
+#include <string>
+#include <stdexcept>
+
+namespace rlib {
+    class string : public std::string {
+    public:
+        using std::string::string;
+        string() : std::string() {}
+        string(const std::string &s) : std::string(s) {}
+        string(std::string &&s) : std::string(std::forward<std::string>(s)) {}
+
+    private:
+        template <typename T> struct as_helper {};
+        template <typename T>
+        T as(as_helper<T>) const {
+            if(empty()) return T();
+            return T(*this);
+        }
+        const char *as(as_helper<const char *>) const {
+            return this->c_str();
+        }
+        std::string as(as_helper<std::string>) const {
+            return std::move(*this);
+        }
+        rlib::string as(as_helper<rlib::string>) const {
+            return std::move(*this);
+        }
+        char as(as_helper<char>) const {
+            if(size() > 1)
+                throw std::invalid_argument("Can not convert rlib::string to char: size() > 1.");
+            return size() == 0 ? '\0' : *cbegin();
+        }
+        // unsigned-char conflicts with uint8_t. I'll regard it as uint8_t. ("8".as<unsigned char> == 8)
+        //unsigned char as(as_helper<unsigned char>) const {
+        //    return static_cast<unsigned char>(as<char>());
+        //}
+        bool as(as_helper<bool>) const {
+            if(*this == "true") {
+                return true;
+            }
+            else if(*this == "false") {
+                return false;
+            }
+            // Nothing is slower than throw(); Just test more cases...
+            else if(*this == "1" || *this == "True" || *this == "TRUE") {
+                return true;
+            }
+            else if(*this == "0" || *this == "False" || *this == "FALSE") {
+                return false;
+            }
+            throw std::invalid_argument("Can not convert rlib::string to bool. Not matching any template.");
+        }
+
+#define RLIB_IMPL_GEN_AS_NUMERIC(type, std_conv) \
+        type as(as_helper<type>) const { \
+            if(empty()) return 0; \
+            return std::std_conv(*this); \
+        }
+
+        RLIB_IMPL_GEN_AS_NUMERIC(int, stoi)
+        RLIB_IMPL_GEN_AS_NUMERIC(long, stol)
+        RLIB_IMPL_GEN_AS_NUMERIC(unsigned long, stoul)
+        RLIB_IMPL_GEN_AS_NUMERIC(unsigned long long, stoull)
+        RLIB_IMPL_GEN_AS_NUMERIC(long long, stoll)
+        RLIB_IMPL_GEN_AS_NUMERIC(float, stof)
+        RLIB_IMPL_GEN_AS_NUMERIC(double, stod)
+        RLIB_IMPL_GEN_AS_NUMERIC(long double, stold)
+
+#define RLIB_IMPL_GEN_AS_ALIAS(new_type, old_type) \
+        new_type as(as_helper<new_type>) const { \
+            return static_cast<new_type>(as<old_type>()); \
+        }
+
+        RLIB_IMPL_GEN_AS_ALIAS(unsigned int, unsigned long)
+        RLIB_IMPL_GEN_AS_ALIAS(unsigned short, unsigned long)
+        RLIB_IMPL_GEN_AS_ALIAS(uint8_t, unsigned long)
+
+        RLIB_IMPL_GEN_AS_ALIAS(short, int)
+        RLIB_IMPL_GEN_AS_ALIAS(int8_t, int)
+
+    public:
+        template <typename T>
+        T as() const {
+            return std::forward<T>(as(as_helper<T>()));
+        }
+
+        template <typename T>
+        std::vector<T> split_as(const char &divider = ' ') const {
+            const string &toSplit = *this;
+            std::vector<T> buf;
+            size_t curr = 0, prev = 0;
+            while((curr = toSplit.find(divider, curr)) != std::string::npos) {
+                buf.push_back(string(toSplit.substr(prev, curr - prev)).as<T>());
+                ++curr; // skip divider
+                prev = curr;
+            }
+            buf.push_back(string(toSplit.substr(prev)).as<T>());
+            return std::move(buf);
+        }
+        template <typename T>
+        std::vector<T> split_as(const std::string &divider) const {
+            const string &toSplit = *this;
+            std::vector<T> buf;
+            size_t curr = 0, prev = 0;
+            while((curr = toSplit.find(divider, curr)) != std::string::npos) {
+                buf.push_back(string(toSplit.substr(prev, curr - prev)).as<T>());
+                curr += divider.size(); // skip divider
+                prev = curr;
+            }
+            buf.push_back(string(toSplit.substr(prev)).as<T>());
+            return std::move(buf);
+        }
+
+        template <class ForwardIterable>
+        string &join(const ForwardIterable &buffer) {
+            join(buffer.cbegin(), buffer.cend());
+            return *this;
+        }
+        template <class ForwardIterator>
+        string &join(ForwardIterator begin, ForwardIterator end) {
+            const string &toJoin = *this;
+            std::string result;
+            for(ForwardIterator iter = begin; iter != end; ++iter) {
+                if(iter != begin)
+                    result += toJoin;
+                result += *iter;
+            }
+            return operator=(std::move(result));
+        }
+
+        string &strip() {
+            strip(" \t\r\n");
+            return *this;
+        }
+        template <typename CharOrStringOrView>
+        string &strip(const CharOrStringOrView &stripped) {
+            size_t len = size();
+            size_t begin = find_first_not_of(stripped);
+
+            if(begin == std::string::npos) {
+                clear();
+                return *this;
+            }
+            size_t end = find_last_not_of(stripped);
+
+            erase(end + 1, len - end - 1);
+            erase(0, begin);
+            return *this;
+        }
+
+        string &replace(const std::string &from, const std::string &to) {
+            size_t _;
+            replace(from, to, _);
+            return *this;
+        }
+        string &replace(const std::string &from, const std::string &to, size_t &out_times) {
+            if(from.empty())
+                return *this;
+            size_t start_pos = 0;
+            size_t times = 0;
+            while((start_pos = find(from, start_pos)) != std::string::npos)
+            {
+                ++times;
+                this->std::string::replace(start_pos, from.length(), to);
+                start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
+            }
+            out_times = times;
+            return *this;
+        }
+        string &replace_once(const std::string &from, const std::string &to) {
+            bool _;
+            replace_once(from, to, _);
+            return *this;
+        }
+        string &replace_once(const std::string &from, const std::string &to, bool &out_replaced) {
+            size_t start_pos = find(from);
+            if(start_pos == std::string::npos) {
+                out_replaced = false;
+            }
+            else {
+                this->std::string::replace(start_pos, from.length(), to);
+                out_replaced = true;
+            }
+            return *this;
+        }
+
+
+    };
+}
+
+#endif
+
+#include <iostream>
+#include <string>
+
+namespace rlib {
+    // This is my own hand-written library. I'm making it easy to use it directly.
+
+    inline rlib::string scanln(std::istream &is = std::cin, char delimiter = '\n') noexcept {
+        std::string line;
+        std::getline(is, line, delimiter);
+        return (line); // RVO
+    }
+
+    template <typename PrintFinalT>
+    void print(PrintFinalT reqArg)
+    {
+        std::cout << reqArg;
+    }
+    template <typename Required, typename... Optional>
+    void print(Required reqArgs, Optional... optiArgs)
+    {
+        std::cout << reqArgs << ' ';
+        print(optiArgs ...);
+    }
+    template <typename... Optional>
+    void println(Optional... optiArgs)
+    {
+        print(optiArgs ...);
+        println();
+    }
+    template <> 
+    inline void println()
+    {
+        //std::cout << rlib::endl;
+        std::cout << std::endl;
+    }
+}
+
-- 
GitLab