refactor: comnbine all in to one single header
This commit is contained in:
parent
1664f86179
commit
8a96704909
45
src/error.h
45
src/error.h
@ -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
|
10
src/nerr.h
10
src/nerr.h
@ -1,10 +0,0 @@
|
||||
#ifndef NEER_H
|
||||
#define NEER_H
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
#include "error.h"
|
||||
#include "option.h"
|
||||
#include "result.h"
|
||||
|
||||
#endif
|
92
src/option.h
92
src/option.h
@ -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
|
82
src/result.h
82
src/result.h
@ -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
204
src/ro.h
Normal 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
|
@ -1,15 +1,15 @@
|
||||
#include <string>
|
||||
#include "../src/nerr.h"
|
||||
#include "../src/ro.h"
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace nerr;
|
||||
using namespace ro;
|
||||
|
||||
#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();
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
catch(nerr::Error e)
|
||||
catch(ro::Error e)
|
||||
{
|
||||
std::cout << "FAILED" << std::endl;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
Result<string, Error> test_return()
|
||||
{
|
||||
return string("Error");
|
||||
}
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
test("Test Option", [](){
|
||||
@ -123,7 +118,6 @@ int main(int argc, char const *argv[])
|
||||
test("Result map", [](){
|
||||
auto err = ERR("Error");
|
||||
auto fn = [](string data){
|
||||
cout << data << endl;
|
||||
return 1;
|
||||
};
|
||||
Result<string, Error> ret = err;
|
||||
@ -140,7 +134,6 @@ int main(int argc, char const *argv[])
|
||||
|
||||
test("Result map err", [](){
|
||||
auto fn = [](int x){
|
||||
cout << "Error code is " << x << endl;
|
||||
return "Hello";
|
||||
};
|
||||
Result<bool, int> ret = true;
|
||||
@ -165,4 +158,5 @@ int main(int argc, char const *argv[])
|
||||
v = ret.map_or<int>(0, fn);
|
||||
assert(v == 3, "Value mismatch %d",v);
|
||||
});
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user