refactor: comnbine all in to one single header

This commit is contained in:
DL 2024-02-28 09:35:14 +01:00
parent 1664f86179
commit 8a96704909
6 changed files with 209 additions and 240 deletions

View File

@ -1,45 +0,0 @@
#ifndef NEER_ERROR_H
#define NEER_ERROR_H
#include <stdexcept>
#include <string>
#include <memory>
#define ERR(fmt,...) Error(nerr::sfmt("%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__))
namespace nerr
{
template <typename... Args>
std::string sfmt(const std::string &format, Args... args)
{
int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
if (size_s <= 0)
{
throw std::runtime_error("Error during formatting string.");
}
auto size = static_cast<size_t>(size_s);
std::unique_ptr<char[]> buf(new char[size]);
std::snprintf(buf.get(), size, format.c_str(), args...);
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
}
class Error : public std::runtime_error
{
public:
Error(const std::string &s) : runtime_error(s){};
Error(const char *s) : runtime_error(s){};
Error(): runtime_error(""){};
inline friend bool operator==(const Error& l, const Error& r)
{
return std::string(l.what()) == std::string(r.what());
}
inline Error operator+(const Error& other)
{
return Error(std::string(this->what()) + "\n" + other.what());
}
};
}
#endif

View File

@ -1,10 +0,0 @@
#ifndef NEER_H
#define NEER_H
#include <string>
#include <functional>
#include "error.h"
#include "option.h"
#include "result.h"
#endif

View File

@ -1,92 +0,0 @@
#ifndef NEER_OPTION_H
#define NEER_OPTION_H
#define None(T) (nerr::Option<T>())
#define Some(v) (nerr::Option(v))
namespace nerr
{
template <typename T, typename E> class Result;
template <typename T>
class Option
{
public:
Option(T obj) : m_some(obj), m_notnull(true){};
Option() : m_notnull(false){};
Option<T>& operator=(const T& value) {insert(value); return *this;};
inline friend bool operator==(const Option<T>& l, const Option<T>& r) {
if(!l.m_notnull && !r.m_notnull)
{
return true;
}
if(l.m_notnull && r.m_notnull)
{
return l.m_some == r.m_some;
}
return false;
};
inline bool is_none(){return !m_notnull;};
inline bool is_some(){return m_notnull;};
inline T& unwrap()
{
if(m_notnull)
{
return m_some;
}
throw Error("Object is None");
}
inline T& get_or_insert(T value)
{
if(!m_notnull)
{
insert(value);
}
return m_some;
}
inline T& insert(T value)
{
m_some = value;
m_notnull = true;
return m_some;
}
template <typename E>
inline Result<T, E> ok_or(E err)
{
if(m_notnull)
{
return Result<T, E>(m_some);
}
return Result<T, E>(err);
}
template<typename U>
inline Option<U> map(const std::function<U(T)>& fn)
{
if(is_some())
{
return fn(m_some);
}
return Option<U>();
}
template<typename U>
inline U map_or(U defv, const std::function<U(T)>& fn)
{
if(is_some())
{
return fn(m_some);
}
return defv;
}
private:
T m_some;
bool m_notnull;
};
}
#endif

View File

@ -1,82 +0,0 @@
#ifndef NEER_RESULT_H
#define NEER_RESULT_H
//#define Ok(v) (nerr::Result(v))
//#define Err(e) (nerr::Result(e))
namespace nerr
{
//template <typename T> class Option;
template <typename T, typename E>
class Result
{
public:
Result(T obj) : m_result(obj) {};
Result(E err) { m_error.insert(err); };
Result(){};
inline Result<T,E>& operator=(const T& value) {m_result = value; m_error = None(E); return *this;};
inline Result<T,E>& operator=(const E& err) {m_error.insert(err); return *this;};
inline bool is_ok(){return m_error.is_none();};
inline bool is_err(){return m_error.is_some();};
inline T& unwrap()
{
if(is_ok())
{
return m_result;
}
throw m_error.unwrap();
}
inline T& expect(E e)
{
if(is_ok())
{
return m_result;
}
throw e + m_error.unwrap();
}
template<typename U>
inline Result<U,E> map(const std::function<U(T)>& fn)
{
if(is_ok())
{
return fn(m_result);
}
return m_error.unwrap();
}
template<typename E1>
inline Result<T,E1> map_err(const std::function<E1(E)>& fn)
{
if(!is_ok())
{
return fn(m_error.unwrap());
}
return m_result;
}
template<typename U>
inline U map_or(U defv, const std::function<U(T)>& fn)
{
if(is_ok())
{
return fn(m_result);
}
return defv;
}
Option<E> err() { return m_error; }
Option<T> ok() { return is_ok()?Option<T>(m_result): Option<T>(); }
private:
T m_result;
Option<E> m_error;
};
}
#endif

204
src/ro.h Normal file
View File

@ -0,0 +1,204 @@
#ifndef RO_H
#define RO_H
#include <stdexcept>
#include <string>
#include <memory>
#include <functional>
#define None(T) (ro::Option<T>())
#define Some(v) (ro::Option(v))
#define ERR(fmt,...) Error(ro::sfmt("%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__))
#define Err(e) (ro::Result(e))
#define Ok(v) (ro::Result(v))
namespace ro
{
template <typename... Args>
std::string sfmt(const std::string &format, Args... args)
{
int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
if (size_s <= 0)
{
throw std::runtime_error("Error during formatting string.");
}
auto size = static_cast<size_t>(size_s);
std::unique_ptr<char[]> buf(new char[size]);
std::snprintf(buf.get(), size, format.c_str(), args...);
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
}
class Error : public std::runtime_error
{
public:
Error(const std::string &s) : runtime_error(s){};
Error(const char *s) : runtime_error(s){};
Error(): runtime_error(""){};
inline friend bool operator==(const Error& l, const Error& r)
{
return std::string(l.what()) == std::string(r.what());
}
inline Error operator+(const Error& other)
{
return Error(std::string(this->what()) + "\n" + other.what());
}
};
template <typename T, typename E> class Result;
template <typename T>
class Option
{
public:
Option(T obj) : m_some(obj), m_notnull(true){};
Option() : m_notnull(false){};
Option<T>& operator=(const T& value) {insert(value); return *this;};
inline friend bool operator==(const Option<T>& l, const Option<T>& r) {
if(!l.m_notnull && !r.m_notnull)
{
return true;
}
if(l.m_notnull && r.m_notnull)
{
return l.m_some == r.m_some;
}
return false;
};
inline bool is_none(){return !m_notnull;};
inline bool is_some(){return m_notnull;};
inline T& unwrap()
{
if(m_notnull)
{
return m_some;
}
throw Error("Object is None");
}
inline T& get_or_insert(T value)
{
if(!m_notnull)
{
insert(value);
}
return m_some;
}
inline T& insert(T value)
{
m_some = value;
m_notnull = true;
return m_some;
}
template <typename E>
inline Result<T, E> ok_or(E err)
{
if(m_notnull)
{
return Result<T, E>(m_some);
}
return Result<T, E>(err);
}
template<typename U>
inline Option<U> map(const std::function<U(T)>& fn)
{
if(is_some())
{
return fn(m_some);
}
return Option<U>();
}
template<typename U>
inline U map_or(U defv, const std::function<U(T)>& fn)
{
if(is_some())
{
return fn(m_some);
}
return defv;
}
private:
T m_some;
bool m_notnull;
};
template <typename T, typename E>
class Result
{
public:
Result(T obj) : m_result(obj) {};
Result(E err) { m_error.insert(err); };
Result(){};
inline Result<T,E>& operator=(const T& value) {m_result = value; m_error = None(E); return *this;};
inline Result<T,E>& operator=(const E& err) {m_error.insert(err); return *this;};
inline bool is_ok(){return m_error.is_none();};
inline bool is_err(){return m_error.is_some();};
inline T& unwrap()
{
if(is_ok())
{
return m_result;
}
throw m_error.unwrap();
}
inline T& expect(E e)
{
if(is_ok())
{
return m_result;
}
throw e + m_error.unwrap();
}
template<typename U>
inline Result<U,E> map(const std::function<U(T)>& fn)
{
if(is_ok())
{
return fn(m_result);
}
return m_error.unwrap();
}
template<typename E1>
inline Result<T,E1> map_err(const std::function<E1(E)>& fn)
{
if(!is_ok())
{
return fn(m_error.unwrap());
}
return m_result;
}
template<typename U>
inline U map_or(U defv, const std::function<U(T)>& fn)
{
if(is_ok())
{
return fn(m_result);
}
return defv;
}
Option<E> err() { return m_error; }
Option<T> ok() { return is_ok()?Option<T>(m_result): Option<T>(); }
private:
T m_result;
Option<E> m_error;
};
}
#endif

View File

@ -1,15 +1,15 @@
#include <string> #include <string>
#include "../src/nerr.h" #include "../src/ro.h"
#include <functional> #include <functional>
#include <iostream> #include <iostream>
using namespace std; using namespace std;
using namespace nerr; using namespace ro;
#define assert(v,fmt,...) if(!(v)) { \ #define assert(v,fmt,...) if(!(v)) { \
throw Error(nerr::sfmt("ASSERT ERROR %s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__)); \ throw Error(ro::sfmt("ASSERT ERROR %s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__)); \
} }
@ -20,18 +20,13 @@ void test(const char* desc, const std::function<void()>& lambda)
lambda(); lambda();
std::cout << "OK" << std::endl; std::cout << "OK" << std::endl;
} }
catch(nerr::Error e) catch(ro::Error e)
{ {
std::cout << "FAILED" << std::endl; std::cout << "FAILED" << std::endl;
std::cout << e.what() << std::endl; std::cout << e.what() << std::endl;
} }
} }
Result<string, Error> test_return()
{
return string("Error");
}
int main(int argc, char const *argv[]) int main(int argc, char const *argv[])
{ {
test("Test Option", [](){ test("Test Option", [](){
@ -123,7 +118,6 @@ int main(int argc, char const *argv[])
test("Result map", [](){ test("Result map", [](){
auto err = ERR("Error"); auto err = ERR("Error");
auto fn = [](string data){ auto fn = [](string data){
cout << data << endl;
return 1; return 1;
}; };
Result<string, Error> ret = err; Result<string, Error> ret = err;
@ -140,7 +134,6 @@ int main(int argc, char const *argv[])
test("Result map err", [](){ test("Result map err", [](){
auto fn = [](int x){ auto fn = [](int x){
cout << "Error code is " << x << endl;
return "Hello"; return "Hello";
}; };
Result<bool, int> ret = true; Result<bool, int> ret = true;
@ -165,4 +158,5 @@ int main(int argc, char const *argv[])
v = ret.map_or<int>(0, fn); v = ret.map_or<int>(0, fn);
assert(v == 3, "Value mismatch %d",v); assert(v == 3, "Value mismatch %d",v);
}); });
} }