1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy 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, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20#import "TMemoryBuffer.h" 21#import "TTransportError.h" 22 23 24#define GARBAGE_BUFFER_SIZE 4096 // 4KiB 25 26 27@interface TMemoryBuffer () 28 29@property(strong, nonatomic) NSMutableData *buffer; 30@property(assign, nonatomic) UInt32 bufferOffset; 31 32@end 33 34 35@implementation TMemoryBuffer 36 37-(id) init 38{ 39 if ((self = [super init])) { 40 _buffer = [NSMutableData new]; 41 _bufferOffset = 0; 42 } 43 return self; 44} 45 46-(id) initWithData:(NSData *)data 47{ 48 if (self = [super init]) { 49 _buffer = [data mutableCopy]; 50 _bufferOffset = 0; 51 } 52 return self; 53} 54 55-(id) initWithDataNoCopy:(NSMutableData *)data 56{ 57 if (self = [super init]) { 58 _buffer = data; 59 _bufferOffset = 0; 60 } 61 return self; 62} 63 64-(BOOL) readAll:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset length:(UInt32)length error:(NSError *__autoreleasing *)error 65{ 66 UInt32 got = [self readAvail:outBuffer offset:outBufferOffset maxLength:length error:error]; 67 if (got != length) { 68 69 // Report underflow only if readAvail didn't report error already 70 if (error && !*error) { 71 *error = [NSError errorWithDomain:TTransportErrorDomain 72 code:TTransportErrorEndOfFile 73 userInfo:nil]; 74 } 75 76 return NO; 77 } 78 79 return YES; 80} 81 82-(UInt32) readAvail:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset maxLength:(UInt32)maxLength error:(NSError *__autoreleasing *)error 83{ 84 UInt32 avail = (UInt32)_buffer.length - _bufferOffset; 85 if (avail == 0) { 86 return 0; 87 } 88 89 NSRange range; 90 range.location = _bufferOffset; 91 range.length = MIN(maxLength, avail); 92 93 [_buffer getBytes:outBuffer + outBufferOffset range:range]; 94 _bufferOffset += range.length; 95 96 if (_bufferOffset >= GARBAGE_BUFFER_SIZE) { 97 [_buffer replaceBytesInRange:NSMakeRange(0, _bufferOffset) withBytes:NULL length:0]; 98 _bufferOffset = 0; 99 } 100 101 return (UInt32)range.length; 102} 103 104-(BOOL) write:(const UInt8 *)inBuffer offset:(UInt32)inBufferOffset length:(UInt32)length error:(NSError *__autoreleasing *)error 105{ 106 [_buffer appendBytes:inBuffer + inBufferOffset length:length]; 107 108 return YES; 109} 110 111-(NSData *) buffer 112{ 113 return _buffer; 114} 115 116-(BOOL) flush:(NSError *__autoreleasing *)error 117{ 118 return YES; 119} 120 121@end 122