Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
variant.cpp
Go to the documentation of this file.
1#include <fc/variant.hpp>
4#include <string.h>
6#include <fc/crypto/hex.hpp>
7#include <boost/scoped_array.hpp>
9#include <fc/io/json.hpp>
10#include <fc/utf8.hpp>
11#include <algorithm>
12
13namespace fc
14{
19{
20 char* data = reinterpret_cast<char*>(v);
21 data[ sizeof(variant) -1 ] = t;
22}
23
28
33
35{
36 *reinterpret_cast<uint64_t*>(this) = val;
38}
39
41{
42 *reinterpret_cast<int64_t*>(this) = val;
44}
45
47{
48 *reinterpret_cast<uint64_t*>(this) = val;
50}
51
53{
54 *reinterpret_cast<int64_t*>(this) = val;
56}
57
59{
60 *reinterpret_cast<uint64_t*>(this) = val;
62}
63
65{
66 *reinterpret_cast<int64_t*>(this) = val;
68}
69
71{
72 *reinterpret_cast<uint64_t*>(this) = val;
74}
75
77{
78 *reinterpret_cast<int64_t*>(this) = val;
80}
81
82variant::variant( float val )
83{
84 *reinterpret_cast<double*>(this) = val;
86}
87
88variant::variant( double val )
89{
90 *reinterpret_cast<double*>(this) = val;
92}
93
95{
96 *reinterpret_cast<bool*>(this) = val;
98}
99
101{
102 *reinterpret_cast<string**>(this) = new string( str );
104}
105
106variant::variant( const char* str )
107{
108 *reinterpret_cast<string**>(this) = new string( str );
110}
111
112// TODO: do a proper conversion to utf8
113variant::variant( wchar_t* str )
114{
115 size_t len = wcslen(str);
116 boost::scoped_array<char> buffer(new char[len]);
117 for (unsigned i = 0; i < len; ++i)
118 buffer[i] = (char)str[i];
119 *reinterpret_cast<string**>(this) = new string(buffer.get(), len);
121}
122
123// TODO: do a proper conversion to utf8
124variant::variant( const wchar_t* str )
125{
126 size_t len = wcslen(str);
127 boost::scoped_array<char> buffer(new char[len]);
128 for (unsigned i = 0; i < len; ++i)
129 buffer[i] = (char)str[i];
130 *reinterpret_cast<string**>(this) = new string(buffer.get(), len);
132}
133
135{
136 *reinterpret_cast<string**>(this) = new string( fc::move(val) );
138}
140{
141 *reinterpret_cast<blob**>(this) = new blob( fc::move(val) );
143}
144
146{
147 *reinterpret_cast<variant_object**>(this) = new variant_object(fc::move(obj));
149}
151{
152 *reinterpret_cast<variant_object**>(this) = new variant_object(fc::move(obj));
154}
155
157{
158 *reinterpret_cast<variants**>(this) = new variants(fc::move(arr));
160}
161
162
165typedef const blob* const_blob_ptr;
166typedef const string* const_string_ptr;
167
169{
170 switch( get_type() )
171 {
172 case object_type:
173 delete *reinterpret_cast<variant_object**>(this);
174 break;
175 case array_type:
176 delete *reinterpret_cast<variants**>(this);
177 break;
178 case string_type:
179 delete *reinterpret_cast<string**>(this);
180 break;
181 case blob_type:
182 delete *reinterpret_cast<blob**>(this);
183 break;
184 default:
185 break;
186 }
188}
189
191{
192 switch( v.get_type() )
193 {
194 case object_type:
195 *reinterpret_cast<variant_object**>(this) =
196 new variant_object(**reinterpret_cast<const const_variant_object_ptr*>(&v));
198 return;
199 case array_type:
200 *reinterpret_cast<variants**>(this) =
201 new variants(**reinterpret_cast<const const_variants_ptr*>(&v));
203 return;
204 case string_type:
205 *reinterpret_cast<string**>(this) =
206 new string(**reinterpret_cast<const const_string_ptr*>(&v) );
208 return;
209 case blob_type:
210 *reinterpret_cast<blob**>(this) =
211 new blob(**reinterpret_cast<const const_blob_ptr*>(&v) );
213 return;
214 default:
215 memcpy( this, &v, sizeof(v) );
216 }
217}
218
220{
221 memcpy( this, &v, sizeof(v) );
223}
224
226{
227 clear();
228}
229
231{
232 if( this == &v ) return *this;
233 clear();
234 memcpy( (char*)this, (char*)&v, sizeof(v) );
236 return *this;
237}
238
240{
241 if( this == &v )
242 return *this;
243
244 clear();
245 switch( v.get_type() )
246 {
247 case object_type:
248 *reinterpret_cast<variant_object**>(this) =
249 new variant_object((**reinterpret_cast<const const_variant_object_ptr*>(&v)));
250 break;
251 case array_type:
252 *reinterpret_cast<variants**>(this) =
253 new variants((**reinterpret_cast<const const_variants_ptr*>(&v)));
254 break;
255 case string_type:
256 *reinterpret_cast<string**>(this) = new string((**reinterpret_cast<const const_string_ptr*>(&v)) );
257 break;
258 case blob_type:
259 *reinterpret_cast<blob**>(this) = new blob((**reinterpret_cast<const const_blob_ptr*>(&v)) );
260 break;
261 default:
262 memcpy( this, &v, sizeof(v) );
263 }
264 set_variant_type( this, v.get_type() );
265 return *this;
266}
267
268void variant::visit( const visitor& v )const
269{
270 switch( get_type() )
271 {
272 case null_type:
273 v.handle();
274 return;
275 case int64_type:
276 v.handle( *reinterpret_cast<const int64_t*>(this) );
277 return;
278 case uint64_type:
279 v.handle( *reinterpret_cast<const uint64_t*>(this) );
280 return;
281 case double_type:
282 v.handle( *reinterpret_cast<const double*>(this) );
283 return;
284 case bool_type:
285 v.handle( *reinterpret_cast<const bool*>(this) );
286 return;
287 case string_type:
288 v.handle( **reinterpret_cast<const const_string_ptr*>(this) );
289 return;
290 case array_type:
291 v.handle( **reinterpret_cast<const const_variants_ptr*>(this) );
292 return;
293 case object_type:
294 v.handle( **reinterpret_cast<const const_variant_object_ptr*>(this) );
295 return;
296 case blob_type:
297 v.handle( **reinterpret_cast<const const_blob_ptr*>(this) );
298 return;
299 default:
300 FC_THROW_EXCEPTION( assert_exception, "Invalid Type / Corrupted Memory" );
301 }
302}
303
305{
306 return (type_id)reinterpret_cast<const char*>(this)[sizeof(*this)-1];
307}
308
310{
311 return get_type() == null_type;
312}
313
315{
316 return get_type() == string_type;
317}
319{
320 return get_type() == bool_type;
321}
323{
324 return get_type() == double_type;
325}
327{
328 return get_type() == uint64_type;
329}
331{
332 return get_type() == int64_type;
333}
334
336{
337 switch( get_type() )
338 {
339 case int64_type:
340 case uint64_type:
341 case bool_type:
342 return true;
343 default:
344 return false;
345 }
346 return false;
347}
349{
350 switch( get_type() )
351 {
352 case int64_type:
353 case uint64_type:
354 case double_type:
355 case bool_type:
356 return true;
357 default:
358 return false;
359 }
360 return false;
361}
362
364{
365 return get_type() == object_type;
366}
367
369{
370 return get_type() == array_type;
371}
373{
374 return get_type() == blob_type;
375}
376
378{
379 switch( get_type() )
380 {
381 case string_type:
382 return to_int64(**reinterpret_cast<const const_string_ptr*>(this));
383 case double_type:
384 return int64_t(*reinterpret_cast<const double*>(this));
385 case int64_type:
386 return *reinterpret_cast<const int64_t*>(this);
387 case uint64_type:
388 return int64_t(*reinterpret_cast<const uint64_t*>(this));
389 case bool_type:
390 return *reinterpret_cast<const bool*>(this);
391 case null_type:
392 return 0;
393 default:
394 FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to int64", ("type", get_type()) );
395 }
396}
397
399{ try {
400 switch( get_type() )
401 {
402 case string_type:
403 return to_uint64(**reinterpret_cast<const const_string_ptr*>(this));
404 case double_type:
405 return static_cast<uint64_t>(*reinterpret_cast<const double*>(this));
406 case int64_type:
407 return static_cast<uint64_t>(*reinterpret_cast<const int64_t*>(this));
408 case uint64_type:
409 return *reinterpret_cast<const uint64_t*>(this);
410 case bool_type:
411 return static_cast<uint64_t>(*reinterpret_cast<const bool*>(this));
412 case null_type:
413 return 0;
414 default:
415 FC_THROW_EXCEPTION( bad_cast_exception,"Invalid cast from ${type} to uint64", ("type",get_type()));
416 }
417} FC_CAPTURE_AND_RETHROW( (*this) ) }
418
419
421{
422 switch( get_type() )
423 {
424 case string_type:
425 return to_double(**reinterpret_cast<const const_string_ptr*>(this));
426 case double_type:
427 return *reinterpret_cast<const double*>(this);
428 case int64_type:
429 return static_cast<double>(*reinterpret_cast<const int64_t*>(this));
430 case uint64_type:
431 return static_cast<double>(*reinterpret_cast<const uint64_t*>(this));
432 case bool_type:
433 return *reinterpret_cast<const bool*>(this);
434 case null_type:
435 return 0;
436 default:
437 FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to double", ("type",get_type()) );
438 }
439}
440
442{
443 switch( get_type() )
444 {
445 case string_type:
446 {
447 const string& s = **reinterpret_cast<const const_string_ptr*>(this);
448 if( s == "true" )
449 return true;
450 if( s == "false" )
451 return false;
452 FC_THROW_EXCEPTION( bad_cast_exception, "Cannot convert string to bool (only \"true\" or \"false\" can be converted)" );
453 }
454 case double_type:
455 return *reinterpret_cast<const double*>(this) != 0.0;
456 case int64_type:
457 return *reinterpret_cast<const int64_t*>(this) != 0;
458 case uint64_type:
459 return *reinterpret_cast<const uint64_t*>(this) != 0;
460 case bool_type:
461 return *reinterpret_cast<const bool*>(this);
462 case null_type:
463 return false;
464 default:
465 FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to bool" , ("type",get_type()));
466 }
467}
468
470{
471 switch( get_type() )
472 {
473 case string_type:
474 return **reinterpret_cast<const const_string_ptr*>(this);
475 case double_type:
476 return to_string(*reinterpret_cast<const double*>(this));
477 case int64_type:
478 return to_string(*reinterpret_cast<const int64_t*>(this));
479 case uint64_type:
480 return to_string(*reinterpret_cast<const uint64_t*>(this));
481 case bool_type:
482 return *reinterpret_cast<const bool*>(this) ? "true" : "false";
483 case blob_type:
484 if( get_blob().data.size() )
485 return base64_encode( get_blob().data.data(), get_blob().data.size() ) + "=";
486 return string();
487 case null_type:
488 return string();
489 default:
490 FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to string", ("type", get_type() ) );
491 }
492}
493
494
497{
498 if( get_type() == array_type )
499 return **reinterpret_cast<variants**>(this);
500
501 FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Array", ("type",get_type()) );
502}
504{
505 if( get_type() == blob_type )
506 return **reinterpret_cast<blob**>(this);
507
508 FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Blob", ("type",get_type()) );
509}
511{
512 if( get_type() == blob_type )
513 return **reinterpret_cast<const const_blob_ptr*>(this);
514
515 FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Blob", ("type",get_type()) );
516}
517
519{
520 switch( get_type() )
521 {
522 case null_type: return blob();
523 case blob_type: return get_blob();
524 case string_type:
525 {
526 const string& str = get_string();
527 if( str.size() == 0 ) return blob();
528 if( str.back() == '=' )
529 {
530 std::string b64 = base64_decode( get_string() );
531 return blob( { std::vector<char>( b64.begin(), b64.end() ) } );
532 }
533 return blob( { std::vector<char>( str.begin(), str.end() ) } );
534 }
535 case object_type:
536 case array_type:
537 FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Blob", ("type",get_type()) );
538 default:
539 return blob( { std::vector<char>( (char*)&_data, (char*)&_data + sizeof(_data) ) } );
540 }
541}
542
543
546{
547 if( get_type() == array_type )
548 return **reinterpret_cast<const const_variants_ptr*>(this);
549 FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Array", ("type",get_type()) );
550}
551
552
555{
556 if( get_type() == object_type )
557 return **reinterpret_cast<variant_object**>(this);
558 FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from ${type} to Object", ("type",get_type()) );
559}
560
561const variant& variant::operator[]( const char* key )const
562{
563 return get_object()[key];
564}
565const variant& variant::operator[]( size_t pos )const
566{
567 return get_array()[pos];
568}
570size_t variant::size()const
571{
572 return get_array().size();
573}
574
576{
577 switch( get_type() )
578 {
579 case null_type:
580 case int64_type:
581 case uint64_type:
582 case double_type:
583 case bool_type:
584 return sizeof(*this);
585 case string_type:
586 return as_string().length() + sizeof(string) + sizeof(*this);
587 case array_type:
588 {
589 const auto& arr = get_array();
590 auto arr_size = arr.size();
591 size_t sum = sizeof(*this) + sizeof(variants);
592 for (size_t iter = 0; iter < arr_size; ++iter) {
593 sum += arr[iter].estimated_size();
594 }
595 return sum;
596 }
597 case object_type:
598 return get_object().estimated_size() + sizeof(*this);
599 case blob_type:
600 return sizeof(blob) + get_blob().data.size() + sizeof(*this);
601 default:
602 FC_THROW_EXCEPTION( assert_exception, "Invalid Type / Corrupted Memory" );
603 }
604}
605
606const string& variant::get_string()const
607{
608 if( get_type() == string_type )
609 return **reinterpret_cast<const const_string_ptr*>(this);
610 FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from type '${type}' to string", ("type",get_type()) );
611}
612
615{
616 if( get_type() == object_type )
617 return **reinterpret_cast<const const_variant_object_ptr*>(this);
618 FC_THROW_EXCEPTION( bad_cast_exception, "Invalid cast from type '${type}' to Object", ("type",get_type()) );
619}
620
621void from_variant( const variant& var, variants& vo )
622{
623 vo = var.get_array();
624}
625
626//void from_variant( const variant& var, variant_object& vo )
627//{
628// vo = var.get_object();
629//}
630
631void from_variant( const variant& var, variant& vo ) { vo = var; }
632
633void to_variant( const uint8_t& var, variant& vo ) { vo = uint64_t(var); }
634// TODO: warn on overflow?
635void from_variant( const variant& var, uint8_t& vo ){ vo = static_cast<uint8_t>(var.as_uint64()); }
636
637void to_variant( const int8_t& var, variant& vo ) { vo = int64_t(var); }
638// TODO: warn on overflow?
639void from_variant( const variant& var, int8_t& vo ){ vo = static_cast<int8_t>(var.as_int64()); }
640
641void to_variant( const uint16_t& var, variant& vo ) { vo = uint64_t(var); }
642// TODO: warn on overflow?
643void from_variant( const variant& var, uint16_t& vo ){ vo = static_cast<uint16_t>(var.as_uint64()); }
644
645void to_variant( const int16_t& var, variant& vo ) { vo = int64_t(var); }
646// TODO: warn on overflow?
647void from_variant( const variant& var, int16_t& vo ){ vo = static_cast<int16_t>(var.as_int64()); }
648
649void to_variant( const uint32_t& var, variant& vo ) { vo = uint64_t(var); }
650void from_variant( const variant& var, uint32_t& vo )
651{
652 vo = static_cast<uint32_t>(var.as_uint64());
653}
654
655void to_variant( const int32_t& var, variant& vo ) {
656 vo = int64_t(var);
657}
658
659void from_variant( const variant& var, int32_t& vo )
660{
661 vo = static_cast<int32_t>(var.as_int64());
662}
663
664void to_variant( const unsigned __int128& var, variant& vo ) {
665 vo = boost::multiprecision::uint128_t( var ).str();
666}
667
668void from_variant( const variant& var, unsigned __int128& vo )
669{
670 if( var.is_uint64() ) {
671 vo = var.as_uint64();
672 } else if( var.is_string() ) {
673 vo = static_cast<unsigned __int128>( boost::multiprecision::uint128_t(var.as_string()) );
674 } else {
675 FC_THROW_EXCEPTION( bad_cast_exception, "Cannot convert variant of type '${type}' into a uint128_t", ("type", var.get_type()) );
676 }
677}
678
679void to_variant( const __int128& var, variant& vo ) {
680 vo = boost::multiprecision::int128_t( var ).str();
681}
682
683void from_variant( const variant& var, __int128& vo )
684{
685 if( var.is_int64() ) {
686 vo = var.as_int64();
687 } else if( var.is_string() ) {
688 vo = static_cast<__int128>( boost::multiprecision::int128_t(var.as_string()) );
689 } else {
690 FC_THROW_EXCEPTION( bad_cast_exception, "Cannot convert variant of type '${type}' into a int128_t", ("type", var.get_type()) );
691 }
692}
693
694void from_variant( const variant& var, int64_t& vo )
695{
696 vo = var.as_int64();
697}
698
699void from_variant( const variant& var, uint64_t& vo )
700{
701 vo = var.as_uint64();
702}
703
704void from_variant( const variant& var, bool& vo )
705{
706 vo = var.as_bool();
707}
708
709void from_variant( const variant& var, double& vo )
710{
711 vo = var.as_double();
712}
713
714void from_variant( const variant& var, float& vo )
715{
716 vo = static_cast<float>(var.as_double());
717}
718
719void to_variant( const std::string& s, variant& v )
720{
721 v = variant( fc::string(s) );
722}
723
724void from_variant( const variant& var, string& vo )
725{
726 vo = var.as_string();
727}
728
729void to_variant( const std::vector<char>& var, variant& vo )
730{
731 FC_ASSERT( var.size() <= MAX_SIZE_OF_BYTE_ARRAYS );
732 if( var.size() )
733 vo = variant(to_hex(var.data(),var.size()));
734 else vo = "";
735}
736void from_variant( const variant& var, std::vector<char>& vo )
737{
738 const auto& str = var.get_string();
739 FC_ASSERT( str.size() <= 2*MAX_SIZE_OF_BYTE_ARRAYS ); // Doubled because hex strings needs two characters per byte
740 FC_ASSERT( str.size() % 2 == 0, "the length of hex string should be even number" );
741 vo.resize( str.size() / 2 );
742 if( vo.size() ) {
743 size_t r = from_hex( str, vo.data(), vo.size() );
744 FC_ASSERT( r == vo.size() );
745 }
746}
747
748void to_variant( const UInt<8>& n, variant& v ) { v = uint64_t(n); }
749// TODO: warn on overflow?
750void from_variant( const variant& v, UInt<8>& n ) { n = static_cast<uint8_t>(v.as_uint64()); }
751
752void to_variant( const UInt<16>& n, variant& v ) { v = uint64_t(n); }
753// TODO: warn on overflow?
754void from_variant( const variant& v, UInt<16>& n ) { n = static_cast<uint16_t>(v.as_uint64()); }
755
756void to_variant( const UInt<32>& n, variant& v ) { v = uint64_t(n); }
757// TODO: warn on overflow?
758void from_variant( const variant& v, UInt<32>& n ) { n = static_cast<uint32_t>(v.as_uint64()); }
759
760void to_variant( const UInt<64>& n, variant& v ) { v = uint64_t(n); }
761void from_variant( const variant& v, UInt<64>& n ) { n = v.as_uint64(); }
762
763constexpr size_t minimize_max_size = 1024;
764
765// same behavior as std::string::substr only removes invalid utf8, and lower ascii
766void clean_append( string& app, const std::string_view& s, size_t pos = 0, size_t len = string::npos ) {
767 std::string_view sub = s.substr( pos, len );
768 app.reserve( app.size() + sub.size() );
769 const bool escape_control_chars = false;
770 app += escape_string( sub, nullptr, escape_control_chars );
771}
772
773string format_string( const string& frmt, const variant_object& args, bool minimize )
774{
775 std::string result;
776 const string& format = ( minimize && frmt.size() > minimize_max_size ) ?
777 frmt.substr( 0, minimize_max_size ) + "..." : frmt;
778
779 const auto arg_num = (args.size() == 0) ? 1 : args.size();
780 const auto max_format_size = std::max(minimize_max_size, format.size());
781 // limit each arg size when minimize is set
782 const auto minimize_sub_max_size = minimize ? ( max_format_size - format.size() ) / arg_num : minimize_max_size;
783 // reserve space for each argument replaced by ...
784 result.reserve( max_format_size + 3 * args.size());
785 size_t prev = 0;
786 size_t next = format.find( '$' );
787 while( prev != string::npos && prev < format.size() ) {
788 if( next != string::npos ) {
789 clean_append( result, format, prev, next - prev );
790 } else {
791 clean_append( result, format, prev );
792 }
793
794 // if we got to the end, return it.
795 if( next == string::npos ) {
796 return result;
797 } else if( minimize && result.size() > minimize_max_size ) {
798 result += "...";
799 return result;
800 }
801
802 // if we are not at the end, then update the start
803 prev = next + 1;
804
805 if( format[prev] == '{' ) {
806 // if the next char is a open, then find close
807 next = format.find( '}', prev );
808 // if we found close...
809 if( next != string::npos ) {
810 // the key is between prev and next
811 string key = format.substr( prev + 1, (next - prev - 1) );
812
813 auto val = args.find( key );
814 bool replaced = true;
815 if( val != args.end() ) {
816 if( val->value().is_object() || val->value().is_array() ) {
817 if( minimize && (result.size() >= minimize_max_size)) {
818 replaced = false;
819 } else {
820 const auto max_length = minimize ? minimize_sub_max_size : std::numeric_limits<uint64_t>::max();
821 try {
822 // clean_append not needed as to_string is valid utf8
823 result += json::to_string( val->value(), fc::time_point::maximum(),
825 } catch (...) {
826 replaced = false;
827 }
828 }
829 } else if( val->value().is_blob() ) {
830 if( minimize && val->value().get_blob().data.size() > minimize_sub_max_size ) {
831 replaced = false;
832 } else {
833 clean_append( result, val->value().as_string() );
834 }
835 } else if( val->value().is_string() ) {
836 if( minimize && val->value().get_string().size() > minimize_sub_max_size ) {
837 auto sz = std::min( minimize_sub_max_size, minimize_max_size - result.size() );
838 clean_append( result, val->value().get_string(), 0, sz );
839 result += "...";
840 } else {
841 clean_append( result, val->value().get_string() );
842 }
843 } else {
844 clean_append( result, val->value().as_string() );
845 }
846 } else {
847 replaced = false;
848 }
849 if( !replaced ) {
850 result += "${";
851 clean_append( result, key );
852 result += "}";
853 }
854 prev = next + 1;
855 // find the next $
856 next = format.find( '$', prev );
857 } else {
858 // we didn't find it.. continue to while...
859 }
860 } else {
861 clean_append( result, format, prev, 1 );
862 ++prev;
863 next = format.find( '$', prev );
864 }
865 }
866 return result;
867}
868
869 #ifdef __APPLE__
870 #elif !defined(_MSC_VER)
871 void to_variant( long long int s, variant& v ) { v = variant( int64_t(s) ); }
872 void to_variant( unsigned long long int s, variant& v ) { v = variant( uint64_t(s)); }
873 #endif
874
875 bool operator == ( const variant& a, const variant& b )
876 {
877 if( a.is_string() || b.is_string() ) return a.as_string() == b.as_string();
878 if( a.is_double() || b.is_double() ) return a.as_double() == b.as_double();
879 if( a.is_int64() || b.is_int64() ) return a.as_int64() == b.as_int64();
880 if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() == b.as_uint64();
881 if( a.is_array() || b.is_array() ) return a.get_array() == b.get_array();
882 return false;
883 }
884
885 bool operator != ( const variant& a, const variant& b )
886 {
887 return !( a == b );
888 }
889
890 bool operator ! ( const variant& a )
891 {
892 return !a.as_bool();
893 }
894
895 bool operator < ( const variant& a, const variant& b )
896 {
897 if( a.is_string() || b.is_string() ) return a.as_string() < b.as_string();
898 if( a.is_double() || b.is_double() ) return a.as_double() < b.as_double();
899 if( a.is_int64() || b.is_int64() ) return a.as_int64() < b.as_int64();
900 if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() < b.as_uint64();
901 FC_ASSERT( false, "Invalid operation" );
902 }
903
904 bool operator > ( const variant& a, const variant& b )
905 {
906 if( a.is_string() || b.is_string() ) return a.as_string() > b.as_string();
907 if( a.is_double() || b.is_double() ) return a.as_double() > b.as_double();
908 if( a.is_int64() || b.is_int64() ) return a.as_int64() > b.as_int64();
909 if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() > b.as_uint64();
910 FC_ASSERT( false, "Invalid operation" );
911 }
912
913 bool operator <= ( const variant& a, const variant& b )
914 {
915 if( a.is_string() || b.is_string() ) return a.as_string() <= b.as_string();
916 if( a.is_double() || b.is_double() ) return a.as_double() <= b.as_double();
917 if( a.is_int64() || b.is_int64() ) return a.as_int64() <= b.as_int64();
918 if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() <= b.as_uint64();
919 FC_ASSERT( false, "Invalid operation" );
920 }
921
922
923 variant operator + ( const variant& a, const variant& b )
924 {
925 if( a.is_array() && b.is_array() )
926 {
927 const variants& aa = a.get_array();
928 const variants& ba = b.get_array();
929 variants result;
930 result.reserve( std::max(aa.size(),ba.size()) );
931 auto num = std::max(aa.size(),ba.size());
932 for( unsigned i = 0; i < num; ++i )
933 {
934 if( aa.size() > i && ba.size() > i )
935 result[i] = aa[i] + ba[i];
936 else if( aa.size() > i )
937 result[i] = aa[i];
938 else
939 result[i] = ba[i];
940 }
941 return result;
942 }
943 if( a.is_string() || b.is_string() ) return a.as_string() + b.as_string();
944 if( a.is_double() || b.is_double() ) return a.as_double() + b.as_double();
945 if( a.is_int64() || b.is_int64() ) return a.as_int64() + b.as_int64();
946 if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() + b.as_uint64();
947 FC_ASSERT( false, "invalid operation ${a} + ${b}", ("a",a)("b",b) );
948 }
949
950 variant operator - ( const variant& a, const variant& b )
951 {
952 if( a.is_array() && b.is_array() )
953 {
954 const variants& aa = a.get_array();
955 const variants& ba = b.get_array();
956 variants result;
957 result.reserve( std::max(aa.size(),ba.size()) );
958 auto num = std::max(aa.size(),ba.size());
959 for( unsigned i = 0; i < num; --i )
960 {
961 if( aa.size() > i && ba.size() > i )
962 result[i] = aa[i] - ba[i];
963 else if( aa.size() > i )
964 result[i] = aa[i];
965 else
966 result[i] = ba[i];
967 }
968 return result;
969 }
970 if( a.is_string() || b.is_string() ) return a.as_string() - b.as_string();
971 if( a.is_double() || b.is_double() ) return a.as_double() - b.as_double();
972 if( a.is_int64() || b.is_int64() ) return a.as_int64() - b.as_int64();
973 if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() - b.as_uint64();
974 FC_ASSERT( false, "invalid operation ${a} + ${b}", ("a",a)("b",b) );
975 }
976 variant operator * ( const variant& a, const variant& b )
977 {
978 if( a.is_double() || b.is_double() ) return a.as_double() * b.as_double();
979 if( a.is_int64() || b.is_int64() ) return a.as_int64() * b.as_int64();
980 if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() * b.as_uint64();
981 if( a.is_array() && b.is_array() )
982 {
983 const variants& aa = a.get_array();
984 const variants& ba = b.get_array();
985 variants result;
986 result.reserve( std::max(aa.size(),ba.size()) );
987 auto num = std::max(aa.size(),ba.size());
988 for( unsigned i = 0; i < num; ++i )
989 {
990 if( aa.size() > i && ba.size() > i )
991 result[i] = aa[i] * ba[i];
992 else if( aa.size() > i )
993 result[i] = aa[i];
994 else
995 result[i] = ba[i];
996 }
997 return result;
998 }
999 FC_ASSERT( false, "invalid operation ${a} * ${b}", ("a",a)("b",b) );
1000 }
1002 {
1003 if( a.is_double() || b.is_double() ) return a.as_double() / b.as_double();
1004 if( a.is_int64() || b.is_int64() ) return a.as_int64() / b.as_int64();
1005 if( a.is_uint64() || b.is_uint64() ) return a.as_uint64() / b.as_uint64();
1006 if( a.is_array() && b.is_array() )
1007 {
1008 const variants& aa = a.get_array();
1009 const variants& ba = b.get_array();
1010 variants result;
1011 result.reserve( std::max(aa.size(),ba.size()) );
1012 auto num = std::max(aa.size(),ba.size());
1013 for( unsigned i = 0; i < num; ++i )
1014 {
1015 if( aa.size() > i && ba.size() > i )
1016 result[i] = aa[i] / ba[i];
1017 else if( aa.size() > i )
1018 result[i] = aa[i];
1019 else
1020 result[i] = ba[i];
1021 }
1022 return result;
1023 }
1024 FC_ASSERT( false, "invalid operation ${a} / ${b}", ("a",a)("b",b) );
1025 }
1026} // namespace fc
const mie::Vuint & r
Definition bn.cpp:28
static string to_string(const variant &v, const yield_function_t &yield, const output_formatting format=output_formatting::stringify_large_ints_and_doubles)
Definition json.cpp:674
An order-preserving dictionary of variants.
static constexpr time_point maximum()
Definition time.hpp:46
virtual void handle() const =0
handles null_type variants
An order-preserving dictionary of variants.
size_t size() const
size_t estimated_size() const
iterator end() const
iterator find(const string &key) const
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition variant.hpp:191
blob as_blob() const
Definition variant.cpp:518
variant & operator=(variant &&v)
Definition variant.cpp:230
bool is_array() const
Definition variant.cpp:368
variant_object & get_object()
Definition variant.cpp:554
void clear()
Definition variant.cpp:168
const string & get_string() const
Definition variant.cpp:606
bool is_int64() const
Definition variant.cpp:330
void visit(const visitor &v) const
Definition variant.cpp:268
uint64_t as_uint64() const
Definition variant.cpp:398
bool is_null() const
Definition variant.cpp:309
bool is_integer() const
Definition variant.cpp:335
bool is_numeric() const
Definition variant.cpp:348
double as_double() const
Definition variant.cpp:420
size_t size() const
Definition variant.cpp:570
bool as_bool() const
Definition variant.cpp:441
bool is_bool() const
Definition variant.cpp:318
blob & get_blob()
Definition variant.cpp:503
bool is_object() const
Definition variant.cpp:363
variant()
Constructs a null_type variant.
Definition variant.cpp:24
int64_t as_int64() const
Definition variant.cpp:377
size_t estimated_size() const
Definition variant.cpp:575
bool is_uint64() const
Definition variant.cpp:326
bool is_string() const
Definition variant.cpp:314
string as_string() const
Definition variant.cpp:469
bool is_double() const
Definition variant.cpp:322
bool is_blob() const
Definition variant.cpp:372
variants & get_array()
Definition variant.cpp:496
type_id get_type() const
Definition variant.cpp:304
const variant & operator[](const char *) const
Definition variant.cpp:561
Defines exception's used by fc.
#define FC_CAPTURE_AND_RETHROW(...)
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
namespace sysio::chain
Definition authority.cpp:3
std::string string
Definition string.hpp:10
void set_variant_type(variant *v, variant::type_id t)
Definition variant.cpp:18
bool operator<(const array< T, N > &a, const array< T, N > &b)
Definition array.hpp:94
const variant_object * const_variant_object_ptr
Definition variant.cpp:163
auto operator+(const fwd< T, S, A > &x, U &&u) -> typename detail::add< T, U >::type
Definition fwd_impl.hpp:42
auto operator-(const fwd< T, S, A > &x, U &&u) -> typename detail::sub< T, U >::type
Definition fwd_impl.hpp:45
std::string base64_encode(unsigned char const *bytes_to_encode, unsigned int in_len)
Definition base64.cpp:92
const string * const_string_ptr
Definition variant.cpp:166
bool operator!(const fc::variant &a)
Definition variant.cpp:890
bool operator<=(const variant &a, const variant &b)
Definition variant.cpp:913
bool operator>(const array< T, N > &a, const array< T, N > &b)
Definition array.hpp:98
fc::string to_string(double)
Definition string.cpp:131
void clean_append(string &app, const std::string_view &s, size_t pos=0, size_t len=string::npos)
Definition variant.cpp:766
bool operator!=(const array< T, N > &a, const array< T, N > &b)
Definition array.hpp:102
uint8_t from_hex(char c)
Definition hex.cpp:6
bool operator==(const array< T, N > &a, const array< T, N > &b)
Definition array.hpp:91
std::vector< fc::variant > variants
Definition variant.hpp:173
constexpr size_t minimize_max_size
Definition variant.cpp:763
fc::variant operator*(const fc::variant &a, const fc::variant &b)
Definition variant.cpp:976
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< Size, Size, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > UInt
Definition variant.hpp:54
fc::string to_hex(const char *d, uint32_t s)
Definition hex.cpp:17
const variants * const_variants_ptr
Definition variant.cpp:164
double to_double(const fc::string &)
Definition string.cpp:118
uint64_t to_uint64(const fc::string &)
Definition string.cpp:105
fc::variant operator/(const fc::variant &a, const fc::variant &b)
Definition variant.cpp:1001
void from_variant(const fc::variant &v, sysio::chain::chain_id_type &cid)
fc::string format_string(const fc::string &, const variant_object &, bool minimize=false)
Definition variant.cpp:773
const blob * const_blob_ptr
Definition variant.cpp:165
void to_variant(const sysio::chain::shared_public_key &var, fc::variant &vo)
Definition authority.cpp:4
std::string base64_decode(const std::string &encoded_string)
Definition base64.cpp:152
std::string escape_string(const std::string_view &str, const json::yield_function_t &yield, bool escape_control_chars=true)
Definition json.cpp:495
decltype(nullptr) nullptr_t
Definition utility.hpp:28
int64_t to_int64(const fc::string &)
Definition string.cpp:92
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
signed short int16_t
Definition stdint.h:122
unsigned short uint16_t
Definition stdint.h:125
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
signed int int32_t
Definition stdint.h:123
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
signed char int8_t
Definition stdint.h:121
std::vector< char > data
Definition variant.hpp:44
size_t size() const
Definition zm.h:519
#define MAX_SIZE_OF_BYTE_ARRAYS
Definition utility.hpp:19
void sub(const Operand &op, uint32 imm)
uint8_t key[16]
Definition yubico_otp.c:41
cmd_format format
char * s
size_t len
memcpy((char *) pInfo->slotDescription, s, l)