RLMBSON.mm 11 KB

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