1 ////////////////////////////////////////////////////////////////////////////
3 // Copyright 2015 Realm Inc.
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
17 ////////////////////////////////////////////////////////////////////////////
19 #ifndef REALM_PROPERTY_HPP
20 #define REALM_PROPERTY_HPP
22 #include "util/tagged_bool.hpp"
24 #include <realm/util/features.h>
30 template<typename> class Optional;
37 template<typename> class BasicRowExpr;
38 using RowExpr = BasicRowExpr<Table>;
40 enum class PropertyType : unsigned char {
48 Object = 7, // currently must be either Array xor Nullable
49 LinkingObjects = 8, // currently must be Array and not Nullable
51 // deprecated and remains only for reading old files
54 // Flags which can be combined with any of the above types except as noted
58 Flags = Nullable | Array
62 using IsPrimary = util::TaggedBool<class IsPrimaryTag>;
63 using IsIndexed = util::TaggedBool<class IsIndexedTag>;
66 PropertyType type = PropertyType::Int;
67 std::string object_type;
68 std::string link_origin_property_name;
69 IsPrimary is_primary = false;
70 IsIndexed is_indexed = false;
72 size_t table_column = -1;
76 Property(std::string name, PropertyType type, IsPrimary primary = false, IsIndexed indexed = false);
78 Property(std::string name, PropertyType type, std::string object_type,
79 std::string link_origin_property_name = "");
81 Property(Property const&) = default;
82 Property(Property&&) = default;
83 Property& operator=(Property const&) = default;
84 Property& operator=(Property&&) = default;
86 bool requires_index() const { return is_primary || is_indexed; }
88 bool type_is_indexable() const;
89 bool type_is_nullable() const;
91 std::string type_string() const;
95 constexpr auto to_underlying(E e)
97 return static_cast<typename std::underlying_type<E>::type>(e);
100 inline constexpr PropertyType operator&(PropertyType a, PropertyType b)
102 return static_cast<PropertyType>(to_underlying(a) & to_underlying(b));
105 inline constexpr PropertyType operator|(PropertyType a, PropertyType b)
107 return static_cast<PropertyType>(to_underlying(a) | to_underlying(b));
110 inline constexpr PropertyType operator^(PropertyType a, PropertyType b)
112 return static_cast<PropertyType>(to_underlying(a) ^ to_underlying(b));
115 inline constexpr PropertyType operator~(PropertyType a)
117 return static_cast<PropertyType>(~to_underlying(a));
120 inline constexpr bool operator==(PropertyType a, PropertyType b)
122 return to_underlying(a & ~PropertyType::Flags) == to_underlying(b & ~PropertyType::Flags);
125 inline constexpr bool operator!=(PropertyType a, PropertyType b)
130 inline PropertyType& operator&=(PropertyType & a, PropertyType b)
136 inline PropertyType& operator|=(PropertyType & a, PropertyType b)
142 inline PropertyType& operator^=(PropertyType & a, PropertyType b)
148 inline constexpr bool is_array(PropertyType a)
150 return to_underlying(a & PropertyType::Array) == to_underlying(PropertyType::Array);
153 inline constexpr bool is_nullable(PropertyType a)
155 return to_underlying(a & PropertyType::Nullable) == to_underlying(PropertyType::Nullable);
158 template<typename Fn>
159 static auto switch_on_type(PropertyType type, Fn&& fn)
161 using PT = PropertyType;
162 bool is_optional = is_nullable(type);
163 switch (type & ~PropertyType::Flags) {
164 case PT::Int: return is_optional ? fn((util::Optional<int64_t>*)0) : fn((int64_t*)0);
165 case PT::Bool: return is_optional ? fn((util::Optional<bool>*)0) : fn((bool*)0);
166 case PT::Float: return is_optional ? fn((util::Optional<float>*)0) : fn((float*)0);
167 case PT::Double: return is_optional ? fn((util::Optional<double>*)0) : fn((double*)0);
168 case PT::String: return fn((StringData*)0);
169 case PT::Data: return fn((BinaryData*)0);
170 case PT::Date: return fn((Timestamp*)0);
171 case PT::Object: return fn((RowExpr*)0);
172 default: REALM_COMPILER_HINT_UNREACHABLE();
176 static const char *string_for_property_type(PropertyType type)
178 if (is_array(type)) {
179 if (type == PropertyType::LinkingObjects)
180 return "linking objects";
183 switch (type & ~PropertyType::Flags) {
184 case PropertyType::String: return "string";
185 case PropertyType::Int: return "int";
186 case PropertyType::Bool: return "bool";
187 case PropertyType::Date: return "date";
188 case PropertyType::Data: return "data";
189 case PropertyType::Double: return "double";
190 case PropertyType::Float: return "float";
191 case PropertyType::Object: return "object";
192 case PropertyType::Any: return "any";
193 case PropertyType::LinkingObjects: return "linking objects";
194 default: REALM_COMPILER_HINT_UNREACHABLE();
198 inline Property::Property(std::string name, PropertyType type,
199 IsPrimary primary, IsIndexed indexed)
200 : name(std::move(name))
202 , is_primary(primary)
203 , is_indexed(indexed)
207 inline Property::Property(std::string name, PropertyType type,
208 std::string object_type,
209 std::string link_origin_property_name)
210 : name(std::move(name))
212 , object_type(std::move(object_type))
213 , link_origin_property_name(std::move(link_origin_property_name))
217 inline bool Property::type_is_indexable() const
219 return type == PropertyType::Int
220 || type == PropertyType::Bool
221 || type == PropertyType::Date
222 || type == PropertyType::String;
225 inline bool Property::type_is_nullable() const
227 return !(is_array(type) && type == PropertyType::Object) && type != PropertyType::LinkingObjects;
230 inline std::string Property::type_string() const
232 if (is_array(type)) {
233 if (type == PropertyType::Object)
234 return "array<" + object_type + ">";
235 if (type == PropertyType::LinkingObjects)
236 return "linking objects<" + object_type + ">";
237 return std::string("array<") + string_for_property_type(type & ~PropertyType::Flags) + ">";
239 switch (auto base_type = (type & ~PropertyType::Flags)) {
240 case PropertyType::Object:
241 return "<" + object_type + ">";
242 case PropertyType::LinkingObjects:
243 return "linking objects<" + object_type + ">";
245 return string_for_property_type(base_type);
249 inline bool operator==(Property const& lft, Property const& rgt)
251 // note: not checking table_column
252 // ordered roughly by the cost of the check
253 return to_underlying(lft.type) == to_underlying(rgt.type)
254 && lft.is_primary == rgt.is_primary
255 && lft.requires_index() == rgt.requires_index()
256 && lft.name == rgt.name
257 && lft.object_type == rgt.object_type
258 && lft.link_origin_property_name == rgt.link_origin_property_name;
262 #endif // REALM_PROPERTY_HPP