Added Android code
[wl-app.git] / iOS / Pods / FirebaseMessaging / Firebase / Messaging / FIRMessagingCodedInputStream.m
1 /*
2  * Copyright 2017 Google
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #import "FIRMessagingCodedInputStream.h"
18 #import "FIRMessagingDefines.h"
19
20 typedef struct {
21   const void *bytes;
22   size_t bufferSize;
23   size_t bufferPos;
24 } BufferState;
25
26 static BOOL CheckSize(BufferState *state, size_t size) {
27   size_t newSize = state->bufferPos + size;
28   if (newSize > state->bufferSize) {
29     return NO;
30   }
31   return YES;
32 }
33
34 static BOOL ReadRawByte(BufferState *state, int8_t *output) {
35   _FIRMessagingDevAssert(output != NULL && state != NULL, @"Invalid parameters");
36
37   if (CheckSize(state, sizeof(int8_t))) {
38     *output = ((int8_t *)state->bytes)[state->bufferPos++];
39     return YES;
40   }
41   return NO;
42 }
43
44 static BOOL ReadRawVarInt32(BufferState *state, int32_t *output) {
45   _FIRMessagingDevAssert(output != NULL && state != NULL, @"Invalid parameters");
46
47   int8_t tmp = 0;
48   if (!ReadRawByte(state, &tmp)) {
49     return NO;
50   }
51   if (tmp >= 0) {
52     *output = tmp;
53     return YES;
54   }
55   int32_t result = tmp & 0x7f;
56   if (!ReadRawByte(state, &tmp)) {
57     return NO;
58   }
59   if (tmp >= 0) {
60     result |= tmp << 7;
61   } else {
62     result |= (tmp & 0x7f) << 7;
63     if (!ReadRawByte(state, &tmp)) {
64       return NO;
65     }
66     if (tmp >= 0) {
67       result |= tmp << 14;
68     } else {
69       result |= (tmp & 0x7f) << 14;
70       if (!ReadRawByte(state, &tmp)) {
71         return NO;
72       }
73       if (tmp >= 0) {
74         result |= tmp << 21;
75       } else {
76         result |= (tmp & 0x7f) << 21;
77         if (!ReadRawByte(state, &tmp)) {
78           return NO;
79         }
80         result |= tmp << 28;
81         if (tmp < 0) {
82           // Discard upper 32 bits.
83           for (int i = 0; i < 5; ++i) {
84             if (!ReadRawByte(state, &tmp)) {
85               return NO;
86             }
87             if (tmp >= 0) {
88               *output = result;
89               return YES;
90             }
91           }
92           return NO;
93         }
94       }
95     }
96   }
97   *output = result;
98   return YES;
99 }
100
101 @interface FIRMessagingCodedInputStream()
102
103 @property(nonatomic, readwrite, strong) NSData *buffer;
104 @property(nonatomic, readwrite, assign) BufferState state;
105
106 @end
107
108 @implementation FIRMessagingCodedInputStream;
109
110 - (instancetype)initWithData:(NSData *)data {
111   self = [super init];
112   if (self) {
113     _buffer = data;
114     _state.bytes = _buffer.bytes;
115     _state.bufferSize = _buffer.length;
116   }
117   return self;
118 }
119
120 - (size_t)offset {
121   return _state.bufferPos;
122 }
123
124 - (BOOL)readTag:(int8_t *)tag {
125   return ReadRawByte(&_state, tag);
126 }
127
128 - (BOOL)readLength:(int32_t *)length {
129   return ReadRawVarInt32(&_state, length);
130 }
131
132 - (NSData *)readDataWithLength:(uint32_t)length {
133   if (!CheckSize(&_state, length)) {
134     return nil;
135   }
136   const void *bytesToRead = _state.bytes + _state.bufferPos;
137   NSData *result = [NSData dataWithBytes:bytesToRead length:length];
138   _state.bufferPos += length;
139   return result;
140 }
141
142 @end