RLMBSON.mm 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2020 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. #import "RLMBSON_Private.hpp"
  19. #import "RLMDecimal128_Private.hpp"
  20. #import "RLMObjectId_Private.hpp"
  21. #import "RLMUtil.hpp"
  22. #import <realm/object-store/util/bson/bson.hpp>
  23. using namespace realm;
  24. using namespace bson;
  25. #pragma mark NSNull
  26. @implementation NSNull (RLMBSON)
  27. - (RLMBSONType)bsonType {
  28. return RLMBSONTypeNull;
  29. }
  30. @end
  31. #pragma mark RLMObjectId
  32. @implementation RLMObjectId (RLMBSON)
  33. - (RLMBSONType)bsonType {
  34. return RLMBSONTypeObjectId;
  35. }
  36. @end
  37. #pragma mark RLMDecimal128
  38. @implementation RLMDecimal128 (RLMBSON)
  39. - (RLMBSONType)bsonType {
  40. return RLMBSONTypeDecimal128;
  41. }
  42. @end
  43. #pragma mark NSString
  44. @implementation NSString (RLMBSON)
  45. - (RLMBSONType)bsonType {
  46. return RLMBSONTypeString;
  47. }
  48. @end
  49. #pragma mark NSNumber
  50. @implementation NSNumber (RLMBSON)
  51. - (RLMBSONType)bsonType {
  52. char numberType = [self objCType][0];
  53. if (numberType == *@encode(bool) ||
  54. numberType == *@encode(char)) {
  55. return RLMBSONTypeBool;
  56. } else if (numberType == *@encode(int) ||
  57. numberType == *@encode(short) ||
  58. numberType == *@encode(unsigned short) ||
  59. numberType == *@encode(unsigned int)) {
  60. return RLMBSONTypeInt32;
  61. } else if (numberType == *@encode(long) ||
  62. numberType == *@encode(long long) ||
  63. numberType == *@encode(unsigned long) ||
  64. numberType == *@encode(unsigned long long)) {
  65. return RLMBSONTypeInt64;
  66. } else {
  67. return RLMBSONTypeDouble;
  68. }
  69. }
  70. @end
  71. #pragma mark NSMutableArray
  72. @implementation NSMutableArray (RLMBSON)
  73. - (RLMBSONType)bsonType {
  74. return RLMBSONTypeArray;
  75. }
  76. - (instancetype)initWithBsonArray:(BsonArray)bsonArray {
  77. if ((self = [self init])) {
  78. for (auto& entry : bsonArray) {
  79. [self addObject:RLMConvertBsonToRLMBSON(entry)];
  80. }
  81. return self;
  82. }
  83. return nil;
  84. }
  85. @end
  86. @implementation NSArray (RLMBSON)
  87. - (BsonArray)bsonArrayValue {
  88. BsonArray bsonArray;
  89. for (id value in self) {
  90. bsonArray.push_back(RLMConvertRLMBSONToBson(value));
  91. }
  92. return bsonArray;
  93. }
  94. - (RLMBSONType)bsonType {
  95. return RLMBSONTypeArray;
  96. }
  97. @end
  98. #pragma mark NSDictionary
  99. @implementation NSMutableDictionary (RLMBSON)
  100. - (RLMBSONType)bsonType {
  101. return RLMBSONTypeDocument;
  102. }
  103. - (BsonDocument)bsonDocumentValue {
  104. BsonDocument bsonDocument;
  105. for (NSString *value in self) {
  106. bsonDocument[value.UTF8String] = RLMConvertRLMBSONToBson(self[value]);
  107. }
  108. return bsonDocument;
  109. }
  110. - (instancetype)initWithBsonDocument:(BsonDocument)bsonDocument {
  111. if ((self = [self init])) {
  112. for (auto it = bsonDocument.begin(); it != bsonDocument.end(); ++it) {
  113. const auto& entry = (*it);
  114. [self setObject:RLMConvertBsonToRLMBSON(entry.second) forKey:@(entry.first.data())];
  115. }
  116. return self;
  117. }
  118. return nil;
  119. }
  120. @end
  121. @implementation NSDictionary (RLMBSON)
  122. - (RLMBSONType)bsonType {
  123. return RLMBSONTypeDocument;
  124. }
  125. - (BsonDocument)bsonDocumentValue {
  126. BsonDocument bsonDocument;
  127. for (NSString *value in self) {
  128. bsonDocument[value.UTF8String] = RLMConvertRLMBSONToBson(self[value]);
  129. }
  130. return bsonDocument;
  131. }
  132. @end
  133. #pragma mark NSData
  134. @implementation NSData (RLMBSON)
  135. - (RLMBSONType)bsonType {
  136. return RLMBSONTypeBinary;
  137. }
  138. - (instancetype)initWithBsonBinary:(std::vector<char>)bsonBinary {
  139. if ((self = [NSData dataWithBytes:bsonBinary.data() length:bsonBinary.size()])) {
  140. return self;
  141. }
  142. return nil;
  143. }
  144. @end
  145. #pragma mark NSDate
  146. @implementation NSDate (RLMBSON)
  147. - (RLMBSONType)bsonType {
  148. return RLMBSONTypeDatetime;
  149. }
  150. @end
  151. #pragma mark NSRegularExpression
  152. @implementation NSRegularExpression (RLMBSON)
  153. - (RLMBSONType)bsonType {
  154. return RLMBSONTypeRegularExpression;
  155. }
  156. - (RegularExpression)regularExpressionValue {
  157. using Option = RegularExpression::Option;
  158. std::string s;
  159. if ((_options & NSRegularExpressionCaseInsensitive) != 0) s += 'i';
  160. if ((_options & NSRegularExpressionUseUnixLineSeparators) != 0) s += 'm';
  161. if ((_options & NSRegularExpressionDotMatchesLineSeparators) != 0) s += 's';
  162. if ((_options & NSRegularExpressionUseUnicodeWordBoundaries) != 0) s += 'x';
  163. return RegularExpression(_pattern.UTF8String, s);
  164. }
  165. - (instancetype)initWithRegularExpression:(RegularExpression)regularExpression {
  166. if ((self = [self init])) {
  167. _pattern = @(regularExpression.pattern().data());
  168. switch (regularExpression.options()) {
  169. case realm::bson::RegularExpression::Option::None:
  170. _options = 0;
  171. break;
  172. case realm::bson::RegularExpression::Option::IgnoreCase:
  173. _options = NSRegularExpressionCaseInsensitive;
  174. break;
  175. case realm::bson::RegularExpression::Option::Multiline:
  176. _options = NSRegularExpressionUseUnixLineSeparators;
  177. break;
  178. case realm::bson::RegularExpression::Option::Dotall:
  179. _options = NSRegularExpressionDotMatchesLineSeparators;
  180. break;
  181. case realm::bson::RegularExpression::Option::Extended:
  182. _options = NSRegularExpressionUseUnicodeWordBoundaries;
  183. break;
  184. }
  185. return self;
  186. }
  187. return nil;
  188. }
  189. @end
  190. #pragma mark RLMMaxKey
  191. @implementation RLMMaxKey
  192. - (BOOL)isEqual:(id)other {
  193. return other == self || ([other class] == [self class]);
  194. }
  195. - (NSUInteger)hash {
  196. return 0;
  197. }
  198. @end
  199. #pragma mark RLMMaxKey
  200. @implementation RLMMinKey
  201. - (BOOL)isEqual:(id)other {
  202. return other == self || ([other class] == [self class]);
  203. }
  204. - (NSUInteger)hash {
  205. return 0;
  206. }
  207. @end
  208. @implementation RLMMaxKey (RLMBSON)
  209. - (RLMBSONType)bsonType {
  210. return RLMBSONTypeMaxKey;
  211. }
  212. @end
  213. @implementation RLMMinKey (RLMBSON)
  214. - (RLMBSONType)bsonType {
  215. return RLMBSONTypeMinKey;
  216. }
  217. @end
  218. #pragma mark RLMBSONToBson
  219. Bson RLMConvertRLMBSONToBson(id<RLMBSON> b) {
  220. switch ([b bsonType]) {
  221. case RLMBSONTypeString:
  222. return ((NSString *)b).UTF8String;
  223. case RLMBSONTypeInt32:
  224. return ((NSNumber *)b).intValue;
  225. case RLMBSONTypeInt64:
  226. return ((NSNumber *)b).longLongValue;
  227. case RLMBSONTypeObjectId:
  228. return [((RLMObjectId *)b) value];
  229. case RLMBSONTypeNull:
  230. return util::none;
  231. case RLMBSONTypeBool:
  232. return (bool)((NSNumber *)b).boolValue;
  233. case RLMBSONTypeDouble:
  234. return ((NSNumber *)b).doubleValue;
  235. case RLMBSONTypeBinary:
  236. return std::vector<char>((char*)((NSData *)b).bytes,
  237. ((char*)((NSData *)b).bytes) + (int)((NSData *)b).length);
  238. case RLMBSONTypeTimestamp:
  239. // This represents a value of `Timestamp` in a MongoDB Collection.
  240. return MongoTimestamp(((NSDate *)b).timeIntervalSince1970, 0);
  241. case RLMBSONTypeDatetime:
  242. // This represents a value of `Date` in a MongoDB Collection.
  243. return RLMTimestampForNSDate((NSDate *)b);
  244. case RLMBSONTypeDecimal128:
  245. return [((RLMDecimal128 *)b) decimal128Value];
  246. case RLMBSONTypeRegularExpression:
  247. return [((NSRegularExpression *)b) regularExpressionValue];
  248. case RLMBSONTypeMaxKey:
  249. return max_key;
  250. case RLMBSONTypeMinKey:
  251. return min_key;
  252. case RLMBSONTypeDocument:
  253. return [((NSDictionary *)b) bsonDocumentValue];
  254. case RLMBSONTypeArray:
  255. return [((NSArray *)b) bsonArrayValue];
  256. }
  257. }
  258. #pragma mark BsonToRLMBSON
  259. id<RLMBSON> RLMConvertBsonToRLMBSON(const Bson& b) {
  260. switch (b.type()) {
  261. case realm::bson::Bson::Type::Null:
  262. return [NSNull null];
  263. case realm::bson::Bson::Type::Int32:
  264. return @(static_cast<int32_t>(b));
  265. case realm::bson::Bson::Type::Int64:
  266. return @(static_cast<int64_t>(b));
  267. case realm::bson::Bson::Type::Bool:
  268. return @(static_cast<bool>(b));
  269. case realm::bson::Bson::Type::Double:
  270. return @(static_cast<double>(b));
  271. case realm::bson::Bson::Type::String:
  272. return RLMStringDataToNSString(static_cast<std::string>(b).c_str());
  273. case realm::bson::Bson::Type::Binary:
  274. return [[NSData alloc] initWithBsonBinary:static_cast<std::vector<char>>(b)];
  275. case realm::bson::Bson::Type::Timestamp:
  276. return [[NSDate alloc] initWithTimeIntervalSince1970:static_cast<MongoTimestamp>(b).seconds];
  277. case realm::bson::Bson::Type::Datetime:
  278. return [[NSDate alloc] initWithTimeIntervalSince1970:static_cast<Timestamp>(b).get_seconds()];
  279. case realm::bson::Bson::Type::ObjectId:
  280. return [[RLMObjectId alloc] initWithValue:static_cast<ObjectId>(b)];
  281. case realm::bson::Bson::Type::Decimal128:
  282. return [[RLMDecimal128 alloc] initWithDecimal128:static_cast<Decimal128>(b)];
  283. case realm::bson::Bson::Type::RegularExpression:
  284. return [[NSRegularExpression alloc] initWithRegularExpression:static_cast<RegularExpression>(b)];
  285. case realm::bson::Bson::Type::MaxKey:
  286. return [RLMMaxKey new];
  287. case realm::bson::Bson::Type::MinKey:
  288. return [RLMMinKey new];
  289. case realm::bson::Bson::Type::Document:
  290. return [[NSMutableDictionary alloc] initWithBsonDocument:static_cast<BsonDocument>(b)];
  291. case realm::bson::Bson::Type::Array:
  292. return [[NSMutableArray alloc] initWithBsonArray:static_cast<BsonArray>(b)];
  293. case realm::bson::Bson::Type::Uuid:
  294. REALM_COMPILER_HINT_UNREACHABLE();
  295. }
  296. return nil;
  297. }
  298. id<RLMBSON> RLMConvertBsonDocumentToRLMBSON(realm::util::Optional<BsonDocument> b) {
  299. return b ? RLMConvertBsonToRLMBSON(*b) : nil;
  300. }