RLMDecimal128.mm 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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 "RLMDecimal128_Private.hpp"
  19. #import "RLMUtil.hpp"
  20. #import <realm/decimal128.hpp>
  21. // Swift's obj-c bridging does not support making an obj-c defined class conform
  22. // to Decodable, so we need a Swift-defined subclass for that. This means that
  23. // when Realm Swift is being used, we need to produce objects of that type rather
  24. // than our obj-c defined type. objc_runtime_visible marks the type as being
  25. // visbile only to the obj-c runtime and not the linker, which means that it'll
  26. // be `nil` at runtime rather than being a linker error if it's not defined, and
  27. // valid if it happens to be defined by some other library (i.e. Realm Swift).
  28. //
  29. // At the point where the objects are being allocated we generally don't have
  30. // any good way of knowing whether or not it's going to end up being used by
  31. // Swift, so we just switch to the subclass unconditionally if the subclass
  32. // exists. This shouldn't have any impact on obj-c code other than a small
  33. // performance hit.
  34. [[clang::objc_runtime_visible]]
  35. @interface RealmSwiftDecimal128 : RLMDecimal128
  36. @end
  37. @implementation RLMDecimal128 {
  38. realm::Decimal128 _value;
  39. }
  40. - (instancetype)init {
  41. if (self = [super init]) {
  42. if (auto cls = [RealmSwiftDecimal128 class]; cls && cls != self.class) {
  43. object_setClass(self, cls);
  44. }
  45. }
  46. return self;
  47. }
  48. - (instancetype)initWithDecimal128:(realm::Decimal128)value {
  49. if ((self = [self init])) {
  50. _value = value;
  51. }
  52. return self;
  53. }
  54. - (instancetype)initWithValue:(id)value {
  55. if ((self = [self init])) {
  56. _value = RLMObjcToDecimal128(value);
  57. }
  58. return self;
  59. }
  60. - (instancetype)initWithNumber:(NSNumber *)number {
  61. if ((self = [self init])) {
  62. _value = RLMObjcToDecimal128(number);
  63. }
  64. return self;
  65. }
  66. - (instancetype)initWithString:(NSString *)string error:(NSError **)error {
  67. if ((self = [self init])) {
  68. try {
  69. _value = realm::Decimal128(string.UTF8String);
  70. }
  71. catch (std::exception const& e) {
  72. if (error) {
  73. *error = RLMMakeError(RLMErrorInvalidInput, e);
  74. }
  75. return nil;
  76. }
  77. }
  78. return self;
  79. }
  80. + (instancetype)decimalWithNumber:(NSNumber *)number {
  81. return [[self alloc] initWithNumber:number];
  82. }
  83. + (instancetype)decimalWithNSDecimal:(NSDecimalNumber *)number {
  84. return [[self alloc] initWithString:number.stringValue error:nil];
  85. }
  86. - (realm::Decimal128)decimal128Value {
  87. return _value;
  88. }
  89. - (BOOL)isEqual:(id)object {
  90. if (auto decimal128 = RLMDynamicCast<RLMDecimal128>(object)) {
  91. return _value == decimal128->_value;
  92. }
  93. if (auto number = RLMDynamicCast<NSNumber>(object)) {
  94. return _value == RLMObjcToDecimal128(number);
  95. }
  96. return NO;
  97. }
  98. - (NSUInteger)hash {
  99. return std::hash<realm::Decimal128>()(_value);
  100. }
  101. - (NSString *)description {
  102. return self.stringValue;
  103. }
  104. - (NSComparisonResult)compare:(RLMDecimal128 *)other {
  105. return static_cast<NSComparisonResult>(_value.compare(other->_value));
  106. }
  107. - (double)doubleValue {
  108. return [NSDecimalNumber decimalNumberWithDecimal:self.decimalValue].doubleValue;
  109. }
  110. - (NSDecimal)decimalValue {
  111. NSDecimal ret;
  112. [[[NSScanner alloc] initWithString:@(_value.to_string().c_str())] scanDecimal:&ret];
  113. return ret;
  114. }
  115. - (NSString *)stringValue {
  116. return @(_value.to_string().c_str());
  117. }
  118. - (BOOL)isNaN {
  119. return _value.is_nan();
  120. }
  121. - (RLMDecimal128 *)magnitude {
  122. auto result = realm::Decimal128(abs(self.doubleValue));
  123. return [[RLMDecimal128 alloc] initWithDecimal128:result];
  124. }
  125. - (void)negate {
  126. _value = realm::Decimal128(-self.doubleValue);
  127. }
  128. + (RLMDecimal128 *)minimumDecimalNumber {
  129. return [[RLMDecimal128 alloc] initWithDecimal128:std::numeric_limits<realm::Decimal128>::lowest()];
  130. }
  131. + (RLMDecimal128 *)maximumDecimalNumber {
  132. return [[RLMDecimal128 alloc] initWithDecimal128:std::numeric_limits<realm::Decimal128>::max()];
  133. }
  134. - (RLMDecimal128 *)decimalNumberByAdding:(RLMDecimal128 *)decimalNumber {
  135. auto rhs = RLMObjcToDecimal128(decimalNumber);
  136. return [[RLMDecimal128 alloc] initWithDecimal128:_value+rhs];
  137. }
  138. - (RLMDecimal128 *)decimalNumberByDividingBy:(RLMDecimal128 *)decimalNumber {
  139. auto rhs = RLMObjcToDecimal128(decimalNumber);
  140. return [[RLMDecimal128 alloc] initWithDecimal128:_value/rhs];
  141. }
  142. - (RLMDecimal128 *)decimalNumberBySubtracting:(RLMDecimal128 *)decimalNumber {
  143. auto rhs = RLMObjcToDecimal128(decimalNumber);
  144. return [[RLMDecimal128 alloc] initWithDecimal128:_value-rhs];
  145. }
  146. - (RLMDecimal128 *)decimalNumberByMultiplyingBy:(RLMDecimal128 *)decimalNumber {
  147. auto rhs = RLMObjcToDecimal128(decimalNumber);
  148. return [[RLMDecimal128 alloc] initWithDecimal128:_value*rhs];
  149. }
  150. - (BOOL)isGreaterThan:(RLMDecimal128 *)decimalNumber {
  151. auto rhs = RLMObjcToDecimal128(decimalNumber);
  152. return _value > rhs;
  153. }
  154. - (BOOL)isGreaterThanOrEqualTo:(RLMDecimal128 *)decimalNumber {
  155. auto rhs = RLMObjcToDecimal128(decimalNumber);
  156. return _value >= rhs;
  157. }
  158. - (BOOL)isLessThan:(RLMDecimal128 *)decimalNumber {
  159. auto rhs = RLMObjcToDecimal128(decimalNumber);
  160. return _value < rhs;
  161. }
  162. - (BOOL)isLessThanOrEqualTo:(RLMDecimal128 *)decimalNumber {
  163. auto rhs = RLMObjcToDecimal128(decimalNumber);
  164. return _value <= rhs;
  165. }
  166. @end