Ingen beskrivning

FIRInstanceIDStringEncoding.m 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. //
  2. // FIRInstanceIDStringEncoding.m
  3. //
  4. // Copyright 2009 Google Inc.
  5. //
  6. // Licensed under the Apache License, Version 2.0 (the "License"); you may not
  7. // use this file except in compliance with the License. You may obtain a copy
  8. // of the License at
  9. //
  10. // http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  14. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  15. // License for the specific language governing permissions and limitations under
  16. // the License.
  17. //
  18. // This is a copy of GTMStringEncoding. FIRInstanceID wants to avoid
  19. // a CocoaPods GTM dependency. Hence we use our own version of StringEncoding.
  20. #import "FIRInstanceIDStringEncoding.h"
  21. #import "FIRInstanceIDLogger.h"
  22. enum { kUnknownChar = -1, kPaddingChar = -2, kIgnoreChar = -3 };
  23. @implementation FIRInstanceIDStringEncoding
  24. + (id)rfc4648Base64WebsafeStringEncoding {
  25. FIRInstanceIDStringEncoding *ret = [self
  26. stringEncodingWithString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"];
  27. [ret setPaddingChar:'='];
  28. [ret setDoPad:YES];
  29. return ret;
  30. }
  31. static inline int lcm(int a, int b) {
  32. for (int aa = a, bb = b;;) {
  33. if (aa == bb)
  34. return aa;
  35. else if (aa < bb)
  36. aa += a;
  37. else
  38. bb += b;
  39. }
  40. }
  41. + (id)stringEncodingWithString:(NSString *)string {
  42. return [[FIRInstanceIDStringEncoding alloc] initWithString:string];
  43. }
  44. - (id)initWithString:(NSString *)string {
  45. if ((self = [super init])) {
  46. charMapData_ = [string dataUsingEncoding:NSASCIIStringEncoding];
  47. if (!charMapData_) {
  48. // Unable to convert string to ASCII
  49. return nil;
  50. }
  51. charMap_ = (char *)[charMapData_ bytes];
  52. NSUInteger length = [charMapData_ length];
  53. if (length < 2 || length > 128 || length & (length - 1)) {
  54. // Length not a power of 2 between 2 and 128
  55. return nil;
  56. }
  57. memset(reverseCharMap_, kUnknownChar, sizeof(reverseCharMap_));
  58. for (unsigned int i = 0; i < length; i++) {
  59. if (reverseCharMap_[(int)charMap_[i]] != kUnknownChar) {
  60. // Duplicate character at |i|
  61. return nil;
  62. }
  63. reverseCharMap_[(int)charMap_[i]] = i;
  64. }
  65. for (NSUInteger i = 1; i < length; i <<= 1) shift_++;
  66. mask_ = (1 << shift_) - 1;
  67. padLen_ = lcm(8, shift_) / shift_;
  68. }
  69. return self;
  70. }
  71. - (NSString *)description {
  72. return [NSString stringWithFormat:@"<Base%d StringEncoder: %@>", 1 << shift_, charMapData_];
  73. }
  74. - (BOOL)doPad {
  75. return doPad_;
  76. }
  77. - (void)setDoPad:(BOOL)doPad {
  78. doPad_ = doPad;
  79. }
  80. - (void)setPaddingChar:(char)c {
  81. paddingChar_ = c;
  82. reverseCharMap_[(int)c] = kPaddingChar;
  83. }
  84. - (NSString *)encode:(NSData *)inData {
  85. NSUInteger inLen = [inData length];
  86. if (inLen <= 0) {
  87. // Empty input
  88. return @"";
  89. }
  90. unsigned char *inBuf = (unsigned char *)[inData bytes];
  91. NSUInteger inPos = 0;
  92. NSUInteger outLen = (inLen * 8 + shift_ - 1) / shift_;
  93. if (doPad_) {
  94. outLen = ((outLen + padLen_ - 1) / padLen_) * padLen_;
  95. }
  96. NSMutableData *outData = [NSMutableData dataWithLength:outLen];
  97. unsigned char *outBuf = (unsigned char *)[outData mutableBytes];
  98. NSUInteger outPos = 0;
  99. unsigned int buffer = inBuf[inPos++];
  100. int bitsLeft = 8;
  101. while (bitsLeft > 0 || inPos < inLen) {
  102. if (bitsLeft < shift_) {
  103. if (inPos < inLen) {
  104. buffer <<= 8;
  105. buffer |= (inBuf[inPos++] & 0xff);
  106. bitsLeft += 8;
  107. } else {
  108. int pad = shift_ - bitsLeft;
  109. buffer <<= pad;
  110. bitsLeft += pad;
  111. }
  112. }
  113. unsigned int idx = (buffer >> (bitsLeft - shift_)) & mask_;
  114. bitsLeft -= shift_;
  115. outBuf[outPos++] = charMap_[idx];
  116. }
  117. if (doPad_) {
  118. while (outPos < outLen) outBuf[outPos++] = paddingChar_;
  119. }
  120. if (outPos != outLen) {
  121. FIRInstanceIDLoggerError(kFIRInstanceIDStringEncodingBufferUnderflow,
  122. @"Underflowed output buffer");
  123. return nil;
  124. }
  125. [outData setLength:outPos];
  126. return [[NSString alloc] initWithData:outData encoding:NSASCIIStringEncoding];
  127. }
  128. - (NSData *)decode:(NSString *)inString {
  129. char *inBuf = (char *)[inString cStringUsingEncoding:NSASCIIStringEncoding];
  130. if (!inBuf) {
  131. // Unable to convert buffer to ASCII
  132. return nil;
  133. }
  134. NSUInteger inLen = strlen(inBuf);
  135. NSUInteger outLen = inLen * shift_ / 8;
  136. NSMutableData *outData = [NSMutableData dataWithLength:outLen];
  137. unsigned char *outBuf = (unsigned char *)[outData mutableBytes];
  138. NSUInteger outPos = 0;
  139. int buffer = 0;
  140. int bitsLeft = 0;
  141. BOOL expectPad = NO;
  142. for (NSUInteger i = 0; i < inLen; i++) {
  143. int val = reverseCharMap_[(int)inBuf[i]];
  144. switch (val) {
  145. case kIgnoreChar:
  146. break;
  147. case kPaddingChar:
  148. expectPad = YES;
  149. break;
  150. case kUnknownChar:
  151. // Unexpected data at input pos |i|
  152. return nil;
  153. default:
  154. if (expectPad) {
  155. // Expected further padding characters
  156. return nil;
  157. }
  158. buffer <<= shift_;
  159. buffer |= val & mask_;
  160. bitsLeft += shift_;
  161. if (bitsLeft >= 8) {
  162. outBuf[outPos++] = (unsigned char)(buffer >> (bitsLeft - 8));
  163. bitsLeft -= 8;
  164. }
  165. break;
  166. }
  167. }
  168. if (bitsLeft && buffer & ((1 << bitsLeft) - 1)) {
  169. // Incomplete trailing data
  170. return nil;
  171. }
  172. // Shorten buffer if needed due to padding chars
  173. if (outPos > outLen) {
  174. FIRInstanceIDLoggerError(kFIRInstanceIDStringEncodingBufferOverflow, @"Overflowed buffer");
  175. }
  176. [outData setLength:outPos];
  177. return outData;
  178. }
  179. @end