added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / property.hpp
1 ////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2015 Realm Inc.
4 //
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
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17 ////////////////////////////////////////////////////////////////////////////
18
19 #ifndef REALM_PROPERTY_HPP
20 #define REALM_PROPERTY_HPP
21
22 #include "util/tagged_bool.hpp"
23
24 #include <realm/util/features.h>
25
26 #include <string>
27
28 namespace realm {
29 namespace util {
30     template<typename> class Optional;
31 }
32 class StringData;
33 class BinaryData;
34 class Timestamp;
35 class Table;
36
37 template<typename> class BasicRowExpr;
38 using RowExpr = BasicRowExpr<Table>;
39
40 enum class PropertyType : unsigned char {
41     Int    = 0,
42     Bool   = 1,
43     String = 2,
44     Data   = 3,
45     Date   = 4,
46     Float  = 5,
47     Double = 6,
48     Object = 7, // currently must be either Array xor Nullable
49     LinkingObjects = 8, // currently must be Array and not Nullable
50
51     // deprecated and remains only for reading old files
52     Any    = 9,
53
54     // Flags which can be combined with any of the above types except as noted
55     Required  = 0,
56     Nullable  = 64,
57     Array     = 128,
58     Flags     = Nullable | Array
59 };
60
61 struct Property {
62     using IsPrimary = util::TaggedBool<class IsPrimaryTag>;
63     using IsIndexed = util::TaggedBool<class IsIndexedTag>;
64
65     std::string name;
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;
71
72     size_t table_column = -1;
73
74     Property() = default;
75
76     Property(std::string name, PropertyType type, IsPrimary primary = false, IsIndexed indexed = false);
77
78     Property(std::string name, PropertyType type, std::string object_type,
79              std::string link_origin_property_name = "");
80
81     Property(Property const&) = default;
82     Property(Property&&) = default;
83     Property& operator=(Property const&) = default;
84     Property& operator=(Property&&) = default;
85
86     bool requires_index() const { return is_primary || is_indexed; }
87
88     bool type_is_indexable() const;
89     bool type_is_nullable() const;
90
91     std::string type_string() const;
92 };
93
94 template<typename E>
95 constexpr auto to_underlying(E e)
96 {
97     return static_cast<typename std::underlying_type<E>::type>(e);
98 }
99
100 inline constexpr PropertyType operator&(PropertyType a, PropertyType b)
101 {
102     return static_cast<PropertyType>(to_underlying(a) & to_underlying(b));
103 }
104
105 inline constexpr PropertyType operator|(PropertyType a, PropertyType b)
106 {
107     return static_cast<PropertyType>(to_underlying(a) | to_underlying(b));
108 }
109
110 inline constexpr PropertyType operator^(PropertyType a, PropertyType b)
111 {
112     return static_cast<PropertyType>(to_underlying(a) ^ to_underlying(b));
113 }
114
115 inline constexpr PropertyType operator~(PropertyType a)
116 {
117     return static_cast<PropertyType>(~to_underlying(a));
118 }
119
120 inline constexpr bool operator==(PropertyType a, PropertyType b)
121 {
122     return to_underlying(a & ~PropertyType::Flags) == to_underlying(b & ~PropertyType::Flags);
123 }
124
125 inline constexpr bool operator!=(PropertyType a, PropertyType b)
126 {
127     return !(a == b);
128 }
129
130 inline PropertyType& operator&=(PropertyType & a, PropertyType b)
131 {
132     a = a & b;
133     return a;
134 }
135
136 inline PropertyType& operator|=(PropertyType & a, PropertyType b)
137 {
138     a = a | b;
139     return a;
140 }
141
142 inline PropertyType& operator^=(PropertyType & a, PropertyType b)
143 {
144     a = a ^ b;
145     return a;
146 }
147
148 inline constexpr bool is_array(PropertyType a)
149 {
150     return to_underlying(a & PropertyType::Array) == to_underlying(PropertyType::Array);
151 }
152
153 inline constexpr bool is_nullable(PropertyType a)
154 {
155     return to_underlying(a & PropertyType::Nullable) == to_underlying(PropertyType::Nullable);
156 }
157
158 template<typename Fn>
159 static auto switch_on_type(PropertyType type, Fn&& fn)
160 {
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();
173     }
174 }
175
176 static const char *string_for_property_type(PropertyType type)
177 {
178     if (is_array(type)) {
179         if (type == PropertyType::LinkingObjects)
180             return "linking objects";
181         return "array";
182     }
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();
195     }
196 }
197
198 inline Property::Property(std::string name, PropertyType type,
199                           IsPrimary primary, IsIndexed indexed)
200 : name(std::move(name))
201 , type(type)
202 , is_primary(primary)
203 , is_indexed(indexed)
204 {
205 }
206
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))
211 , type(type)
212 , object_type(std::move(object_type))
213 , link_origin_property_name(std::move(link_origin_property_name))
214 {
215 }
216
217 inline bool Property::type_is_indexable() const
218 {
219     return type == PropertyType::Int
220         || type == PropertyType::Bool
221         || type == PropertyType::Date
222         || type == PropertyType::String;
223 }
224
225 inline bool Property::type_is_nullable() const
226 {
227     return !(is_array(type) && type == PropertyType::Object) && type != PropertyType::LinkingObjects;
228 }
229
230 inline std::string Property::type_string() const
231 {
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) + ">";
238     }
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 + ">";
244         default:
245             return string_for_property_type(base_type);
246     }
247 }
248
249 inline bool operator==(Property const& lft, Property const& rgt)
250 {
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;
259 }
260 } // namespace realm
261
262 #endif // REALM_PROPERTY_HPP