BitShares-Core  5.0.0
BitShares blockchain implementation and command-line interface software
object_id.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #pragma once
26 #include <fc/io/varint.hpp>
27 #include <memory>
28 #define GRAPHENE_DB_MAX_INSTANCE_ID (uint64_t(-1)>>16)
29 
30 namespace graphene { namespace db {
31  using std::shared_ptr;
32  using std::unique_ptr;
33  using std::vector;
34  using fc::flat_map;
35  using fc::variant;
36  using fc::unsigned_int;
37 
39  {
40  object_id_type( uint8_t s, uint8_t t, uint64_t i )
41  {
42  FC_ASSERT( i >> 48 == 0, "instance overflow", ("instance",i) );
43  number = (uint64_t(s)<<56) | (uint64_t(t)<<48) | i;
44  }
46 
47  uint8_t space()const { return number >> 56; }
48  uint8_t type()const { return number >> 48 & 0x00ff; }
49  uint16_t space_type()const { return number >> 48; }
50  uint64_t instance()const { return number & GRAPHENE_DB_MAX_INSTANCE_ID; }
51  bool is_null()const { return number == 0; }
52  explicit operator uint64_t()const { return number; }
53 
54  friend bool operator == ( const object_id_type& a, const object_id_type& b ) { return a.number == b.number; }
55  friend bool operator != ( const object_id_type& a, const object_id_type& b ) { return a.number != b.number; }
56  friend bool operator < ( const object_id_type& a, const object_id_type& b ) { return a.number < b.number; }
57  friend bool operator > ( const object_id_type& a, const object_id_type& b ) { return a.number > b.number; }
58 
59  object_id_type& operator++(int) { ++number; return *this; }
60  object_id_type& operator++() { ++number; return *this; }
61 
62  friend object_id_type operator+(const object_id_type& a, int delta ) {
63  return object_id_type( a.space(), a.type(), a.instance() + delta );
64  }
65  friend object_id_type operator+(const object_id_type& a, int64_t delta ) {
66  return object_id_type( a.space(), a.type(), a.instance() + delta );
67  }
68  friend size_t hash_value( object_id_type v ) { return std::hash<uint64_t>()(v.number); }
69 
70  template< typename T >
71  bool is() const
72  {
73  return (number >> 48) == ((T::space_id << 8) | (T::type_id));
74  }
75 
76  template< typename T >
77  T as() const
78  {
79  FC_ASSERT( is<T>() );
80  return T( *this );
81  }
82 
83  explicit operator std::string() const
84  {
85  return fc::to_string(space()) + "." + fc::to_string(type()) + "." + fc::to_string(instance());
86  }
87 
88  uint64_t number;
89  };
90 
91  class object;
92  class object_database;
93 
95  template<typename ObjectID>
96  struct object_downcast { using type = object; };
97  // This macro specializes the above template for a specific xyz_object type
98 #define MAP_OBJECT_ID_TO_TYPE(OBJECT) \
99  namespace graphene { namespace db { \
100  template<> \
101  struct object_downcast<graphene::db::object_id<OBJECT::space_id, \
102  OBJECT::type_id>> { using type = OBJECT; }; \
103  } }
104  template<typename ObjectID>
106 
107  template<uint8_t SpaceID, uint8_t TypeID>
108  struct object_id
109  {
110  static constexpr uint8_t space_id = SpaceID;
111  static constexpr uint8_t type_id = TypeID;
112 
113  object_id() = default;
115  explicit object_id( uint64_t i ):instance(i)
116  {
117  FC_ASSERT( (i >> 48) == 0 );
118  }
120  {
121  }
122 
123  friend object_id operator+(const object_id a, int64_t delta ) { return object_id( uint64_t(a.instance.value+delta) ); }
124  friend object_id operator+(const object_id a, int delta ) { return object_id( uint64_t(a.instance.value+delta) ); }
125 
126  operator object_id_type()const { return object_id_type( SpaceID, TypeID, instance.value ); }
127  explicit operator uint64_t()const { return object_id_type( *this ).number; }
128 
129  template<typename DB>
130  auto operator()(const DB& db)const -> const decltype(db.get(*this))& { return db.get(*this); }
131 
132  friend bool operator == ( const object_id& a, const object_id& b ) { return a.instance == b.instance; }
133  friend bool operator != ( const object_id& a, const object_id& b ) { return a.instance != b.instance; }
134  friend bool operator == ( const object_id_type& a, const object_id& b ) { return a == object_id_type(b); }
135  friend bool operator != ( const object_id_type& a, const object_id& b ) { return a != object_id_type(b); }
136  friend bool operator == ( const object_id& a, const object_id_type& b ) { return object_id_type(a) == b; }
137  friend bool operator != ( const object_id& a, const object_id_type& b ) { return object_id_type(a) != b; }
138  friend bool operator == ( const object_id& a, const fc::unsigned_int& b ) { return a.instance == b; }
139  friend bool operator != ( const object_id& a, const fc::unsigned_int& b ) { return a.instance != b; }
140  friend bool operator == ( const fc::unsigned_int& a, const object_id& b ) { return a == b.instance; }
141  friend bool operator != ( const fc::unsigned_int& a, const object_id& b ) { return a != b.instance; }
142 
143  friend bool operator < ( const object_id& a, const object_id& b ) { return a.instance.value < b.instance.value; }
144  friend bool operator > ( const object_id& a, const object_id& b ) { return a.instance.value > b.instance.value; }
145 
146  friend size_t hash_value( object_id v ) { return std::hash<uint64_t>()(v.instance.value); }
147 
149  };
150 
151 } } // graphene::db
152 
154 
155 // REFLECT object_id manually because it has 2 template params
156 namespace fc {
157 template<uint8_t SpaceID, uint8_t TypeID>
158 struct get_typename<graphene::db::object_id<SpaceID,TypeID>>
159 {
160  static const char* name() {
161  return typeid(get_typename).name();
162  static std::string _str = string("graphene::db::object_id<")+fc::to_string(SpaceID) + ":" + fc::to_string(TypeID)+">";
163  return _str.c_str();
164  }
165 };
166 
167 template<uint8_t SpaceID, uint8_t TypeID>
168 struct reflector<graphene::db::object_id<SpaceID,TypeID> >
169 {
171  typedef std::true_type is_defined;
177  local_member_count = 1,
178  total_member_count = 1
179  };
180  template<typename Visitor>
181  static inline void visit( const Visitor& visitor )
182  {
183  typedef decltype(((type*)nullptr)->instance) member_type;
184  visitor.TEMPLATE operator()<member_type,type,&type::instance>( "instance" );
185  }
186 };
187 namespace member_names {
188 template<uint8_t S, uint8_t T>
189 struct member_name<graphene::db::object_id<S,T>, 0> { static constexpr const char* value = "instance"; };
190 }
191 
192 
193  inline void to_variant( const graphene::db::object_id_type& var, fc::variant& vo, uint32_t max_depth = 1 )
194  {
195  vo = std::string( var );
196  }
197 
198  inline void from_variant( const fc::variant& var, graphene::db::object_id_type& vo, uint32_t max_depth = 1 )
199  { try {
200  vo.number = 0;
201  const auto& s = var.get_string();
202  auto first_dot = s.find('.');
203  auto second_dot = s.find('.',first_dot+1);
204  FC_ASSERT( first_dot != second_dot );
205  FC_ASSERT( first_dot != 0 && first_dot != std::string::npos );
206  vo.number = fc::to_uint64(s.substr( second_dot+1 ));
208  auto space_id = fc::to_uint64( s.substr( 0, first_dot ) );
209  FC_ASSERT( space_id <= 0xff );
210  auto type_id = fc::to_uint64( s.substr( first_dot+1, second_dot-first_dot-1 ) );
211  FC_ASSERT( type_id <= 0xff );
212  vo.number |= (space_id << 56) | (type_id << 48);
213  } FC_CAPTURE_AND_RETHROW( (var) ) }
214  template<uint8_t SpaceID, uint8_t TypeID>
215  void to_variant( const graphene::db::object_id<SpaceID,TypeID>& var, fc::variant& vo, uint32_t max_depth = 1 )
216  {
217  vo = fc::to_string(SpaceID) + "." + fc::to_string(TypeID) + "." + fc::to_string(var.instance.value);
218  }
219  template<uint8_t SpaceID, uint8_t TypeID>
220  void from_variant( const fc::variant& var, graphene::db::object_id<SpaceID,TypeID>& vo, uint32_t max_depth = 1 )
221  { try {
222  const auto& s = var.get_string();
223  auto first_dot = s.find('.');
224  auto second_dot = s.find('.',first_dot+1);
225  FC_ASSERT( first_dot != second_dot );
226  FC_ASSERT( first_dot != 0 && first_dot != std::string::npos );
227  FC_ASSERT( fc::to_uint64( s.substr( 0, first_dot ) ) == SpaceID &&
228  fc::to_uint64( s.substr( first_dot+1, second_dot-first_dot-1 ) ) == TypeID,
229  "Space.Type.0 (${SpaceID}.${TypeID}.0) doesn't match expected value ${var}", ("TypeID",TypeID)("SpaceID",SpaceID)("var",var) );
230  vo.instance = fc::to_uint64(s.substr( second_dot+1 ));
231  } FC_CAPTURE_AND_RETHROW( (var) ) }
232 
233 } // namespace fc
234 
235 namespace std {
236  template <> struct hash<graphene::db::object_id_type>
237  {
239  {
240  return std::hash<uint64_t>()(x.number);
241  }
242  };
243 }
const std::string & get_string() const
Definition: variant.cpp:575
object_id(unsigned_int i)
Definition: object_id.hpp:114
#define FC_REFLECT(TYPE, MEMBERS)
Specializes fc::reflector for TYPE.
Definition: reflect.hpp:386
auto operator()(const DB &db) const -> const decltype(db.get(*this))&
Definition: object_id.hpp:130
friend object_id operator+(const object_id a, int delta)
Definition: object_id.hpp:124
friend bool operator>(const object_id_type &a, const object_id_type &b)
Definition: object_id.hpp:57
size_t operator()(const graphene::db::object_id_type &x) const
Definition: object_id.hpp:238
Definition: api.cpp:56
friend object_id_type operator+(const object_id_type &a, int64_t delta)
Definition: object_id.hpp:65
friend size_t hash_value(object_id v)
Definition: object_id.hpp:146
object_id_type & operator++(int)
Definition: object_id.hpp:59
#define GRAPHENE_DB_MAX_INSTANCE_ID
Definition: object_id.hpp:28
friend size_t hash_value(object_id_type v)
Definition: object_id.hpp:68
uint64_t instance() const
Definition: object_id.hpp:50
object_id(object_id_type id)
Definition: object_id.hpp:119
friend bool operator==(const object_id_type &a, const object_id_type &b)
Definition: object_id.hpp:54
friend object_id operator+(const object_id a, int64_t delta)
Definition: object_id.hpp:123
void to_variant(const graphene::db::object_id< SpaceID, TypeID > &var, fc::variant &vo, uint32_t max_depth=1)
Definition: object_id.hpp:215
This template is used to downcast a generic object type to a specific xyz_object type.
Definition: object_id.hpp:96
defines visit functions for T Unless this is specialized, visit() will not be defined for T...
Definition: reflect.hpp:25
maintains a set of indexed objects that can be modified with multi-level rollback support ...
object_id_type(uint8_t s, uint8_t t, uint64_t i)
Definition: object_id.hpp:40
void from_variant(const fc::variant &var, graphene::db::object_id< SpaceID, TypeID > &vo, uint32_t max_depth=1)
Definition: object_id.hpp:220
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:478
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object&#39;s.
Definition: variant.hpp:198
uint8_t space() const
Definition: object_id.hpp:47
uint64_t to_uint64(const std::string &)
Definition: string.cpp:47
The actual list type.
Definition: typelist.hpp:17
Defines exception&#39;s used by fc.
typename object_downcast< ObjectID >::type object_downcast_t
Definition: object_id.hpp:105
std::string to_string(double)
Definition: string.cpp:73
graphene::db::object_id< SpaceID, TypeID > type
Definition: object_id.hpp:170
Definition: api.hpp:15
friend bool operator<(const object_id_type &a, const object_id_type &b)
Definition: object_id.hpp:56
uint64_t value
Definition: varint.hpp:17
friend object_id_type operator+(const object_id_type &a, int delta)
Definition: object_id.hpp:62
friend bool operator!=(const object_id_type &a, const object_id_type &b)
Definition: object_id.hpp:55
base for all database objects
Definition: object.hpp:62
uint16_t space_type() const
Definition: object_id.hpp:49
object_id_type & operator++()
Definition: object_id.hpp:60
A template which stores the name of the native member at a given index in a given class...
Definition: reflect.hpp:28