-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdmk_result.h
155 lines (132 loc) · 4.16 KB
/
dmk_result.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#pragma once
#include "dmk.h"
#include "dmk_string.h"
#include <string>
#include <memory>
#include <tuple>
#include <iostream>
namespace dmk
{
// boolean type with two state: true or error message (memory efficient - one pointer)
struct bool_result
{
public:
// default state - ok
bool_result( ) = default;
// copy
bool_result( const bool_result& other )
: m_error( other ? nullptr : new std::string( other.error( ) ) )
{
}
// allow moving
bool_result( bool_result&& ) = default;
// prevent assigning
bool_result& operator=( const bool_result& ) = delete;
bool_result& operator=( bool_result&& ) = delete;
// constructor(bool)
bool_result( bool ok ) DMK_NOEXCEPT : m_error( ok ? nullptr : new std::string( ) )
{
}
// constructor(string)
bool_result( const std::string& error ) : m_error( new std::string( error ) )
{
}
// constructor(string): move semantic
bool_result( std::string&& error ) DMK_NOEXCEPT_OP( DMK_NOEXCEPT_OP( std::move( error ) ) )
: m_error( new std::string( std::move( error ) ) )
{
}
// prevent automatic conversion int->bool, pointer->bool
bool_result( int value ) = delete;
bool_result( nullptr_t ) = delete;
// bool conversion: bool_result result; ... if(result) {...}
explicit operator bool( ) const
{
return !( bool )m_error;
}
// get error message (no copy, returns const reference)
const std::string& error( ) const
{
static std::string empty;
return m_error ? *m_error : empty;
}
private:
const std::unique_ptr<std::string> m_error;
};
// boolean type with optional message
struct result
{
public:
typedef std::tuple<const bool, const std::string> tuple;
public:
result( ) : m_ok( true )
{
}
result( bool ok ) : m_ok( ok )
{
}
result( bool ok, const u8string& message ) : m_ok( ok ), m_message( message )
{
}
result( bool ok, u8string&& message ) : m_ok( ok ), m_message( std::move( message ) )
{
}
result( const u8string& message ) : m_ok( false ), m_message( message )
{
}
result( u8string&& message ) : m_ok( false ), m_message( std::move( message ) )
{
}
result( const char* message ) : m_ok( false ), m_message( u8string( message ) )
{
}
template <typename... Args>
result( bool ok, const std::string& message, const Args&... args )
: m_ok( ok ), m_message( fmt::format( message, args... ) )
{
}
template <typename... Args>
result( bool ok, std::string&& message, const Args&... args )
: m_ok( ok ), m_message( fmt::format( std::move( message ), args... ) )
{
}
result( result&& ) = default;
result( const result& ) = default;
result& operator=( const result& ) = default;
result& operator=( result&& ) = default;
// bool conversion: bool_result result; ... if(result) {...}
explicit operator bool( ) const
{
return m_ok;
}
// get message (no copy, returns const reference)
const std::string& message( ) const
{
return m_message;
}
// get message (no copy, returns reference)
std::string& message( )
{
return m_message.str( );
}
result& operator<<( const result& right )
{
m_ok = m_ok && right.m_ok;
if ( !m_message.empty( ) )
{
m_message += "; ";
}
m_message += right.m_message;
return *this;
}
static result exit_code( int code )
{
if ( code == 0 )
return true;
return result( false, fmt::format( "ExitCode = {}", code ) );
}
private:
u8string m_message;
bool m_ok;
};
} // namespace dmk