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 <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);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user