暫無描述

FIRInstanceIDStringEncoding.m 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #import "FIRInstanceIDDefines.h"
  2. //
  3. // FIRInstanceIDStringEncoding.m
  4. //
  5. // Copyright 2009 Google Inc.
  6. //
  7. // Licensed under the Apache License, Version 2.0 (the "License"); you may not
  8. // use this file except in compliance with the License. You may obtain a copy
  9. // of the License at
  10. //
  11. // http://www.apache.org/licenses/LICENSE-2.0
  12. //
  13. // Unless required by applicable law or agreed to in writing, software
  14. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. // License for the specific language governing permissions and limitations under
  17. // the License.
  18. //
  19. // This is a copy of GTMStringEncoding. FIRInstanceID wants to avoid
  20. // a CocoaPods GTM dependency. Hence we use our own version of StringEncoding.
  21. #import "FIRInstanceIDStringEncoding.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. _FIRInstanceIDDevAssert(outPos == outLen, @"Underflowed output buffer");
  121. [outData setLength:outPos];
  122. return [[NSString alloc] initWithData:outData encoding:NSASCIIStringEncoding];
  123. }
  124. - (NSData *)decode:(NSString *)inString {
  125. char *inBuf = (char *)[inString cStringUsingEncoding:NSASCIIStringEncoding];
  126. if (!inBuf) {
  127. // Unable to convert buffer to ASCII
  128. return nil;
  129. }
  130. NSUInteger inLen = strlen(inBuf);
  131. NSUInteger outLen = inLen * shift_ / 8;
  132. NSMutableData *outData = [NSMutableData dataWithLength:outLen];
  133. unsigned char *outBuf = (unsigned char *)[outData mutableBytes];
  134. NSUInteger outPos = 0;
  135. int buffer = 0;
  136. int bitsLeft = 0;
  137. BOOL expectPad = NO;
  138. for (NSUInteger i = 0; i < inLen; i++) {
  139. int val = reverseCharMap_[(int)inBuf[i]];
  140. switch (val) {
  141. case kIgnoreChar:
  142. break;
  143. case kPaddingChar:
  144. expectPad = YES;
  145. break;
  146. case kUnknownChar:
  147. // Unexpected data at input pos |i|
  148. return nil;
  149. default:
  150. if (expectPad) {
  151. // Expected further padding characters
  152. return nil;
  153. }
  154. buffer <<= shift_;
  155. buffer |= val & mask_;
  156. bitsLeft += shift_;
  157. if (bitsLeft >= 8) {
  158. outBuf[outPos++] = (unsigned char)(buffer >> (bitsLeft - 8));
  159. bitsLeft -= 8;
  160. }
  161. break;
  162. }
  163. }
  164. if (bitsLeft && buffer & ((1 << bitsLeft) - 1)) {
  165. // Incomplete trailing data
  166. return nil;
  167. }
  168. // Shorten buffer if needed due to padding chars
  169. _FIRInstanceIDDevAssert(outPos <= outLen, @"Overflowed buffer");
  170. [outData setLength:outPos];
  171. return outData;
  172. }
  173. @end