RCTFollyConvert.mm 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #import "RCTFollyConvert.h"
  8. #import <objc/runtime.h>
  9. namespace facebook {
  10. namespace react {
  11. id convertFollyDynamicToId(const folly::dynamic &dyn)
  12. {
  13. // I could imagine an implementation which avoids copies by wrapping the
  14. // dynamic in a derived class of NSDictionary. We can do that if profiling
  15. // implies it will help.
  16. switch (dyn.type()) {
  17. case folly::dynamic::NULLT:
  18. return (id)kCFNull;
  19. case folly::dynamic::BOOL:
  20. return dyn.getBool() ? @YES : @NO;
  21. case folly::dynamic::INT64:
  22. return @(dyn.getInt());
  23. case folly::dynamic::DOUBLE:
  24. return @(dyn.getDouble());
  25. case folly::dynamic::STRING:
  26. return [[NSString alloc] initWithBytes:dyn.c_str() length:dyn.size() encoding:NSUTF8StringEncoding];
  27. case folly::dynamic::ARRAY: {
  28. NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:dyn.size()];
  29. for (auto &elem : dyn) {
  30. [array addObject:convertFollyDynamicToId(elem)];
  31. }
  32. return array;
  33. }
  34. case folly::dynamic::OBJECT: {
  35. NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:dyn.size()];
  36. for (auto &elem : dyn.items()) {
  37. dict[convertFollyDynamicToId(elem.first)] = convertFollyDynamicToId(elem.second);
  38. }
  39. return dict;
  40. }
  41. }
  42. }
  43. folly::dynamic convertIdToFollyDynamic(id json)
  44. {
  45. if (json == nil || json == (id)kCFNull) {
  46. return nullptr;
  47. } else if ([json isKindOfClass:[NSNumber class]]) {
  48. const char *objCType = [json objCType];
  49. switch (objCType[0]) {
  50. // This is a c++ bool or C99 _Bool. On some platforms, BOOL is a bool.
  51. case _C_BOOL:
  52. return (bool)[json boolValue];
  53. case _C_CHR:
  54. // On some platforms, objc BOOL is a signed char, but it
  55. // might also be a small number. Use the same hack JSC uses
  56. // to distinguish them:
  57. // https://phabricator.intern.facebook.com/diffusion/FBS/browse/master/fbobjc/xplat/third-party/jsc/safari-600-1-4-17/JavaScriptCore/API/JSValue.mm;b8ee03916489f8b12143cd5c0bca546da5014fc9$901
  58. if ([json isKindOfClass:[@YES class]]) {
  59. return (bool)[json boolValue];
  60. } else {
  61. return [json longLongValue];
  62. }
  63. case _C_UCHR:
  64. case _C_SHT:
  65. case _C_USHT:
  66. case _C_INT:
  67. case _C_UINT:
  68. case _C_LNG:
  69. case _C_ULNG:
  70. case _C_LNG_LNG:
  71. case _C_ULNG_LNG:
  72. return [json longLongValue];
  73. case _C_FLT:
  74. case _C_DBL:
  75. return [json doubleValue];
  76. // default:
  77. // fall through
  78. }
  79. } else if ([json isKindOfClass:[NSString class]]) {
  80. NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding];
  81. return std::string(reinterpret_cast<const char *>(data.bytes), data.length);
  82. } else if ([json isKindOfClass:[NSArray class]]) {
  83. folly::dynamic array = folly::dynamic::array;
  84. for (id element in json) {
  85. array.push_back(convertIdToFollyDynamic(element));
  86. }
  87. return array;
  88. } else if ([json isKindOfClass:[NSDictionary class]]) {
  89. __block folly::dynamic object = folly::dynamic::object();
  90. [json enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, __unused BOOL *stop) {
  91. object.insert(convertIdToFollyDynamic(key), convertIdToFollyDynamic(value));
  92. }];
  93. return object;
  94. }
  95. return nil;
  96. }
  97. }
  98. }