BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet 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 
28 namespace graphene { namespace db {
29 
31  {
32  static constexpr uint8_t instance_bits = 48;
33  static constexpr uint8_t type_and_instance_bits = 56;
34  static constexpr uint64_t one_byte_mask = 0x00ff;
35  static constexpr uint64_t max_instance = 0x0000ffffffffffff;
36 
37  object_id_type() = default;
38  object_id_type( uint8_t s, uint8_t t, uint64_t i ){ reset( s, t, i ); }
39 
40  void reset( uint8_t s, uint8_t t, uint64_t i )
41  {
42  FC_ASSERT( i >> instance_bits == 0, "instance overflow", ("instance",i) );
43  number = ( (uint64_t(s) << type_and_instance_bits) | (uint64_t(t) << instance_bits) ) | i;
44  }
45 
46  uint8_t space()const { return number >> type_and_instance_bits; }
47  uint8_t type()const { return (number >> instance_bits) & one_byte_mask; }
48  uint16_t space_type()const { return number >> instance_bits; }
49  uint64_t instance()const { return number & max_instance; }
50  bool is_null()const { return 0 == number; }
51  explicit operator uint64_t()const { return number; }
52 
53  friend bool operator == ( const object_id_type& a, const object_id_type& b ) { return a.number == b.number; }
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 
58  object_id_type& operator++() { ++number; return *this; }
59 
60  friend object_id_type operator+(const object_id_type& a, int64_t delta ) {
61  return object_id_type( a.space(), a.type(), a.instance() + delta );
62  }
63  friend size_t hash_value( const object_id_type& v ) { return std::hash<uint64_t>()(v.number); }
64 
65  template< typename T >
66  bool is() const
67  {
68  return space_type() == T::space_type;
69  }
70 
71 
72  template< typename T >
73  T as() const
74  {
75  return T( *this );
76  }
77 
78  explicit operator std::string() const
79  {
80  return fc::to_string(space()) + "." + fc::to_string(type()) + "." + fc::to_string(instance());
81  }
82 
83  uint64_t number = 0;
84  };
85 
86  class object;
87  class object_database;
88 
90  template<typename ObjectID>
91  struct object_downcast { using type = object; };
92  // This macro specializes the above template for a specific xyz_object type
93 #define MAP_OBJECT_ID_TO_TYPE(OBJECT) \
94  namespace graphene { namespace db { \
95  template<> \
96  struct object_downcast<const graphene::db::object_id<OBJECT::space_id, \
97  OBJECT::type_id>&> { using type = OBJECT; }; \
98  } }
99  template<typename ObjectID>
101 
102  template<uint8_t SpaceID, uint8_t TypeID>
103  struct object_id
104  {
105  static constexpr uint8_t type_bits = 8;
106  static constexpr uint8_t instance_bits = 48;
107  static constexpr uint64_t max_instance = 0x0000ffffffffffff;
108 
109  static constexpr uint8_t space_id = SpaceID;
110  static constexpr uint8_t type_id = TypeID;
111 
112  static constexpr uint16_t space_type = uint16_t(uint16_t(space_id) << type_bits) | uint16_t(type_id);
113 
114  static constexpr object_id max()
115  {
116  return object_id( max_instance );
117  }
118 
119  object_id() = default;
120  explicit object_id( const fc::unsigned_int& i ):instance(i)
121  {
122  validate();
123  }
124  explicit object_id( uint64_t i ):instance(i)
125  {
126  validate();
127  }
128  explicit object_id( const object_id_type& id ):instance(id.instance())
129  {
130  // Won't overflow, but need to check space and type
131  FC_ASSERT( id.is<std::remove_reference_t<decltype(*this)>>(), "space or type mismatch" );
132  }
133 
134  void validate()const
135  {
136  FC_ASSERT( (instance.value >> instance_bits) == 0, "instance overflow", ("instance",instance) );
137  }
138 
140  {
141  *this = object_id(o);
142  return *this;
143  }
144 
145  friend object_id operator+(const object_id& a, int64_t delta )
146  { return object_id( uint64_t(a.instance.value+delta) ); }
147 
148  explicit operator object_id_type()const { return object_id_type( SpaceID, TypeID, instance.value ); }
149  explicit operator uint64_t()const { return object_id_type( *this ).number; }
150 
151  template<typename DB>
152  auto operator()(const DB& db)const -> const decltype(db.get(*this))& { return db.get(*this); }
153 
154  friend bool operator == ( const object_id& a, const object_id& b ) { return a.instance == b.instance; }
155  friend bool operator != ( const object_id& a, const object_id& b ) { return a.instance != b.instance; }
156  friend bool operator == ( const object_id_type& a, const object_id& b ) { return a == object_id_type(b); }
157  friend bool operator != ( const object_id_type& a, const object_id& b ) { return a != object_id_type(b); }
158  friend bool operator == ( const object_id& a, const object_id_type& b ) { return object_id_type(a) == b; }
159  friend bool operator != ( const object_id& a, const object_id_type& b ) { return object_id_type(a) != b; }
160  friend bool operator == ( const object_id& a, const fc::unsigned_int& b ) { return a.instance == b; }
161  friend bool operator != ( const object_id& a, const fc::unsigned_int& b ) { return a.instance != b; }
162  friend bool operator == ( const fc::unsigned_int& a, const object_id& b ) { return a == b.instance; }
163  friend bool operator != ( const fc::unsigned_int& a, const object_id& b ) { return a != b.instance; }
164 
165  friend bool operator < ( const object_id& a, const object_id& b )
166  { return a.instance.value < b.instance.value; }
167  friend bool operator > ( const object_id& a, const object_id& b )
168  { return a.instance.value > b.instance.value; }
169 
170  friend size_t hash_value( const object_id& v ) { return std::hash<uint64_t>()(v.instance.value); }
171 
172  explicit operator std::string() const
173  {
175  }
176 
177  fc::unsigned_int instance; // default is 0
178  };
179 
180 } } // graphene::db
181 
183 
184 // REFLECT object_id manually because it has 2 template params
185 namespace fc {
186 template<uint8_t SpaceID, uint8_t TypeID>
187 struct get_typename<graphene::db::object_id<SpaceID,TypeID>>
188 {
189  static const char* name() {
190  return typeid(get_typename).name();
191  static std::string _str = string("graphene::db::object_id<") + fc::to_string(SpaceID) + ":"
192  + fc::to_string(TypeID) + ">";
193  return _str.c_str();
194  }
195 };
196 
197 template<uint8_t SpaceID, uint8_t TypeID>
198 struct reflector<graphene::db::object_id<SpaceID,TypeID> >
199 {
201  using is_defined = std::true_type;
207  local_member_count = 1,
208  total_member_count = 1
209  };
210  template<typename Visitor>
211  static inline void visit( const Visitor& visitor )
212  {
213  using member_type = decltype(((type*)nullptr)->instance);
214  visitor.TEMPLATE operator()<member_type,type,&type::instance>( "instance" );
215  }
216 };
217 namespace member_names {
218 template<uint8_t S, uint8_t T>
219 struct member_name<graphene::db::object_id<S,T>, 0> { static constexpr const char* value = "instance"; };
220 }
221 
222 
223  inline void to_variant( const graphene::db::object_id_type& var, fc::variant& vo, uint32_t max_depth = 1 )
224  {
225  vo = std::string( var );
226  }
227 
228  inline void from_variant( const fc::variant& var, graphene::db::object_id_type& vo, uint32_t max_depth = 1 )
229  { try {
230  const auto& s = var.get_string();
231  auto first_dot = s.find('.');
232  FC_ASSERT( first_dot != std::string::npos, "Missing the first dot" );
233  FC_ASSERT( first_dot != 0, "Missing the space part" );
234  auto second_dot = s.find('.',first_dot+1);
235  FC_ASSERT( second_dot != std::string::npos, "Missing the second dot" );
236  FC_ASSERT( second_dot != first_dot+1, "Missing the type part" );
237  auto space_id = fc::to_uint64( s.substr( 0, first_dot ) );
238  FC_ASSERT( space_id <= graphene::db::object_id_type::one_byte_mask, "space overflow" );
239  auto type_id = fc::to_uint64( s.substr( first_dot+1, (second_dot-first_dot)-1 ) );
240  FC_ASSERT( type_id <= graphene::db::object_id_type::one_byte_mask, "type overflow");
241  auto instance = fc::to_uint64(s.substr( second_dot+1 ));
242  vo.reset( static_cast<uint8_t>(space_id), static_cast<uint8_t>(type_id), instance );
243  } FC_CAPTURE_AND_RETHROW( (var) ) } // GCOVR_EXCL_LINE
244 
245  template<uint8_t SpaceID, uint8_t TypeID>
246  void to_variant( const graphene::db::object_id<SpaceID,TypeID>& var, fc::variant& vo, uint32_t max_depth = 1 )
247  {
248  vo = std::string( var );
249  }
250 
251  template<uint8_t SpaceID, uint8_t TypeID>
252  void from_variant( const fc::variant& var, graphene::db::object_id<SpaceID,TypeID>& vo, uint32_t max_depth = 1 )
253  { try {
254  const auto& s = var.get_string();
255  auto first_dot = s.find('.');
256  FC_ASSERT( first_dot != std::string::npos, "Missing the first dot" );
257  FC_ASSERT( first_dot != 0, "Missing the space part" );
258  auto second_dot = s.find('.',first_dot+1);
259  FC_ASSERT( second_dot != std::string::npos, "Missing the second dot" );
260  FC_ASSERT( second_dot != first_dot+1, "Missing the type part" );
261  FC_ASSERT( fc::to_uint64( s.substr( 0, first_dot ) ) == SpaceID &&
262  fc::to_uint64( s.substr( first_dot+1, (second_dot-first_dot)-1 ) ) == TypeID,
263  "Space.Type.0 (${SpaceID}.${TypeID}.0) doesn't match expected value ${var}",
264  ("TypeID",TypeID)("SpaceID",SpaceID)("var",var) );
265  graphene::db::object_id<SpaceID,TypeID> tmp { fc::to_uint64(s.substr( second_dot+1 )) };
266  vo = tmp;
267  } FC_CAPTURE_AND_RETHROW( (var) ) } // GCOVR_EXCL_LINE
268 
269 } // namespace fc
270 
271 namespace std {
272  template <> struct hash<graphene::db::object_id_type>
273  {
275  {
276  return std::hash<uint64_t>()(x.number);
277  }
278  };
279 }
graphene::db::object_id_type::as
T as() const
Definition: object_id.hpp:73
graphene::db::object_id::operator>
friend bool operator>(const object_id &a, const object_id &b)
Definition: object_id.hpp:167
graphene::db::object_id_type::operator!=
friend bool operator!=(const object_id_type &a, const object_id_type &b)
Definition: object_id.hpp:54
FC_CAPTURE_AND_RETHROW
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:479
graphene::db::object_id::operator!=
friend bool operator!=(const object_id &a, const object_id &b)
Definition: object_id.hpp:155
graphene::db::object_id_type::operator+
friend object_id_type operator+(const object_id_type &a, int64_t delta)
Definition: object_id.hpp:60
graphene::db::object_id::type_id
static constexpr uint8_t type_id
Definition: object_id.hpp:110
graphene::db::object_id::operator+
friend object_id operator+(const object_id &a, int64_t delta)
Definition: object_id.hpp:145
fc::typelist::list
The actual list type.
Definition: typelist.hpp:17
graphene::db::object_downcast_t
typename object_downcast< ObjectID >::type object_downcast_t
Definition: object_id.hpp:100
graphene::db::object_id::object_id
object_id(uint64_t i)
Definition: object_id.hpp:124
fc::to_string
std::string to_string(double)
Definition: string.cpp:73
graphene::db::object_id::operator=
object_id & operator=(const object_id_type &o)
Definition: object_id.hpp:139
graphene::db::object_id_type::operator++
object_id_type & operator++()
Definition: object_id.hpp:58
graphene::db::object_id::space_type
static constexpr uint16_t space_type
Definition: object_id.hpp:112
graphene::db::object_id::operator()
auto operator()(const DB &db) const -> const decltype(db.get(*this))&
Definition: object_id.hpp:152
graphene::db::object_downcast
This template is used to downcast a generic object type to a specific xyz_object type.
Definition: object_id.hpp:91
fc::get_typename< graphene::db::object_id< SpaceID, TypeID > >::name
static const char * name()
Definition: object_id.hpp:189
fc
Definition: api.hpp:15
graphene::db::object_id_type::operator>
friend bool operator>(const object_id_type &a, const object_id_type &b)
Definition: object_id.hpp:56
fc::variant::get_string
const std::string & get_string() const
Definition: variant.cpp:575
graphene::db::object_id::operator<
friend bool operator<(const object_id &a, const object_id &b)
Definition: object_id.hpp:165
graphene::db::object_id::instance
fc::unsigned_int instance
Definition: object_id.hpp:177
fc::from_variant
void from_variant(const variant &var, flat_set< T, A... > &vo, uint32_t _max_depth)
Definition: flat.hpp:116
graphene::db::object_id::type_bits
static constexpr uint8_t type_bits
Definition: object_id.hpp:105
graphene::db::object_id_type::max_instance
static constexpr uint64_t max_instance
Definition: object_id.hpp:35
graphene::db::object_id_type::reset
void reset(uint8_t s, uint8_t t, uint64_t i)
Definition: object_id.hpp:40
graphene::db::object_id::space_id
static constexpr uint8_t space_id
Definition: object_id.hpp:109
graphene::db::object_id_type::is
bool is() const
Definition: object_id.hpp:66
graphene::db::object_id_type::instance
uint64_t instance() const
Definition: object_id.hpp:49
graphene::db::object_id::max_instance
static constexpr uint64_t max_instance
Definition: object_id.hpp:107
graphene::db::object_id::object_id
object_id(const fc::unsigned_int &i)
Definition: object_id.hpp:120
fc::reflector::type
T type
Definition: reflect.hpp:140
graphene::db::object_id::hash_value
friend size_t hash_value(const object_id &v)
Definition: object_id.hpp:170
fc::unsigned_int
Definition: varint.hpp:6
graphene::db::object_id_type::operator==
friend bool operator==(const object_id_type &a, const object_id_type &b)
Definition: object_id.hpp:53
fc::get_typename
Definition: typename.hpp:20
fc::reflector< graphene::db::object_id< SpaceID, TypeID > >::visit
static void visit(const Visitor &visitor)
Definition: object_id.hpp:211
fc::member_names::member_name
A template which stores the name of the native member at a given index in a given class.
Definition: reflect.hpp:28
fc::reflector< graphene::db::object_id< SpaceID, TypeID > >::member_count_enum
member_count_enum
Definition: object_id.hpp:206
graphene::db::object_id_type::space_type
uint16_t space_type() const
Definition: object_id.hpp:48
graphene::db::object_id_type::space
uint8_t space() const
Definition: object_id.hpp:46
graphene::db::object_id_type::object_id_type
object_id_type()=default
fc::to_variant
void to_variant(const flat_set< T, A... > &var, variant &vo, uint32_t _max_depth)
Definition: flat.hpp:105
fc::to_uint64
uint64_t to_uint64(const std::string &)
Definition: string.cpp:47
fc::member_names::member_name::value
constexpr static const char * value
Definition: reflect.hpp:29
graphene::db::object_id_type::is_null
bool is_null() const
Definition: object_id.hpp:50
graphene::db::object_id::object_id
object_id()=default
graphene::db::object_database
maintains a set of indexed objects that can be modified with multi-level rollback support
Definition: object_database.hpp:39
fc::reflector< graphene::db::object_id< SpaceID, TypeID > >::is_defined
std::true_type is_defined
Definition: object_id.hpp:201
graphene::db::object_id_type::object_id_type
object_id_type(uint8_t s, uint8_t t, uint64_t i)
Definition: object_id.hpp:38
FC_ASSERT
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
graphene::db::object_id_type::one_byte_mask
static constexpr uint64_t one_byte_mask
Definition: object_id.hpp:34
fc::reflector::native_members
typelist::list<> native_members
A typelist with a field_reflection for each native member (non-inherited) of the struct.
Definition: reflect.hpp:143
fc::variant
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition: variant.hpp:198
fc::unsigned_int::value
uint64_t value
Definition: varint.hpp:17
graphene::db::object_id_type
Definition: object_id.hpp:30
exception.hpp
Defines exception's used by fc.
graphene::db::object_id_type::operator<
friend bool operator<(const object_id_type &a, const object_id_type &b)
Definition: object_id.hpp:55
graphene::db::object_id
Definition: object_id.hpp:103
graphene::db::object_id_type::hash_value
friend size_t hash_value(const object_id_type &v)
Definition: object_id.hpp:63
graphene::db::object_id_type::number
uint64_t number
Definition: object_id.hpp:83
std
Definition: zeroed_array.hpp:76
graphene::db::object_id::operator==
friend bool operator==(const object_id &a, const object_id &b)
Definition: object_id.hpp:154
graphene::db::object_id_type::instance_bits
static constexpr uint8_t instance_bits
Definition: object_id.hpp:32
fc::reflector
defines visit functions for T Unless this is specialized, visit() will not be defined for T.
Definition: reflect.hpp:25
graphene::db::object_id::validate
void validate() const
Definition: object_id.hpp:134
FC_REFLECT
#define FC_REFLECT(TYPE, MEMBERS)
Specializes fc::reflector for TYPE.
Definition: reflect.hpp:388
graphene::db::object_id_type::type_and_instance_bits
static constexpr uint8_t type_and_instance_bits
Definition: object_id.hpp:33
graphene::db::object_id::instance_bits
static constexpr uint8_t instance_bits
Definition: object_id.hpp:106
std::hash< graphene::db::object_id_type >::operator()
size_t operator()(const graphene::db::object_id_type &x) const
Definition: object_id.hpp:274
graphene::db::object_id_type::type
uint8_t type() const
Definition: object_id.hpp:47
varint.hpp
graphene::db::object_id::object_id
object_id(const object_id_type &id)
Definition: object_id.hpp:128
graphene
Definition: api.cpp:48
graphene::db::object_id::max
static constexpr object_id max()
Definition: object_id.hpp:114
graphene::db::object
base for all database objects
Definition: object.hpp:61