-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathvalue.cpp
107 lines (88 loc) · 2.88 KB
/
value.cpp
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
#include "value.h"
#include <boost/algorithm/string/replace.hpp>
#include <sstream>
namespace runtime
{
std::ostream& operator<<( std::ostream& os, const value_t& v )
{
struct Visitor
{
void operator()( float_t v ) const { os << v << 'f'; }
void operator()( int_t v ) const { os << v << 'i'; }
void operator()( str_t v ) const
{
boost::replace_all( v, "\n", "\\n" );
boost::replace_all( v, "\t", "\\t" );
boost::replace_all( v, "\r", "\\r" );
os << '"' << v << '"';
}
std::ostream& os;
};
boost::apply_visitor( Visitor{ os }, v );
return os;
}
float_t ForceFloat( const value_t& v )
{
struct Impl
{
float_t operator()( float_t v ) const { return v; }
float_t operator()( int_t v ) const { return static_cast<float_t>(v); }
float_t operator()( const str_t& v ) const { throw std::runtime_error( "Cannot be string" ); }
};
return boost::apply_visitor( Impl{}, v );
}
int_t ForceInt( const value_t& v )
{
struct Impl
{
int_t operator()( float_t v ) const { return static_cast<int_t>(v); }
int_t operator()( int_t v ) const { return v; }
int_t operator()( const str_t& v ) const { throw std::runtime_error( "Cannot be string" ); }
};
return boost::apply_visitor( Impl{}, v );
}
const str_t& ForceStr( const value_t& v )
{
struct Impl
{
const str_t& operator()( float_t v ) const { throw std::runtime_error( "Must be string" ); }
const str_t& operator()( int_t v ) const { throw std::runtime_error( "Must be string" ); }
const str_t& operator()( const str_t& v ) const { return v; }
};
return boost::apply_visitor( Impl{}, v );
}
value_t AddImpl( const value_t& op1, const value_t& op2 )
{
const str_t* pS1 = boost::get<str_t>( &op1 );
const str_t* pS2 = boost::get<str_t>( &op2 );
//Strings may also be concatenated (put or joined together) through
//the use of the "+" operator.
return pS1 && pS2 ?
value_t{ *pS1 + *pS2 } :
value_t{ ForceFloat( op1 ) + ForceFloat( op2 ) };
}
int_t LessEqImpl( const value_t& op1, const value_t& op2 )
{
return int_t{ ForceFloat( op1 ) <= ForceFloat( op2 ) };
}
bool ToBoolImpl( const value_t& v )
{
struct Impl
{
bool operator()( float_t v ) const { return v != 0; }
bool operator()( int_t v ) const { return v != 0; }
bool operator()( const str_t& v ) const { return !v.empty(); }
};
return boost::apply_visitor( Impl{}, v );
}
str_t ToStrImpl( const value_t& v )
{
struct Impl
{
str_t operator()( float_t v ) const { std::ostringstream os; os << v; return os.str(); }
str_t operator()( int_t v ) const { return std::to_string( v ); }
str_t operator()( const str_t& v ) const { return v; }
};
return boost::apply_visitor( Impl{}, v );
}
}