1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker *
4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker *
8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker *
10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker */
16*d57664e9SAndroid Build Coastguard Worker
17*d57664e9SAndroid Build Coastguard Worker #include "io/StringStream.h"
18*d57664e9SAndroid Build Coastguard Worker
19*d57664e9SAndroid Build Coastguard Worker using ::android::StringPiece;
20*d57664e9SAndroid Build Coastguard Worker
21*d57664e9SAndroid Build Coastguard Worker namespace aapt {
22*d57664e9SAndroid Build Coastguard Worker namespace io {
23*d57664e9SAndroid Build Coastguard Worker
StringInputStream(StringPiece str)24*d57664e9SAndroid Build Coastguard Worker StringInputStream::StringInputStream(StringPiece str) : str_(str), offset_(0u) {
25*d57664e9SAndroid Build Coastguard Worker }
26*d57664e9SAndroid Build Coastguard Worker
Next(const void ** data,size_t * size)27*d57664e9SAndroid Build Coastguard Worker bool StringInputStream::Next(const void** data, size_t* size) {
28*d57664e9SAndroid Build Coastguard Worker if (offset_ == str_.size()) {
29*d57664e9SAndroid Build Coastguard Worker return false;
30*d57664e9SAndroid Build Coastguard Worker }
31*d57664e9SAndroid Build Coastguard Worker
32*d57664e9SAndroid Build Coastguard Worker *data = str_.data() + offset_;
33*d57664e9SAndroid Build Coastguard Worker *size = str_.size() - offset_;
34*d57664e9SAndroid Build Coastguard Worker offset_ = str_.size();
35*d57664e9SAndroid Build Coastguard Worker return true;
36*d57664e9SAndroid Build Coastguard Worker }
37*d57664e9SAndroid Build Coastguard Worker
BackUp(size_t count)38*d57664e9SAndroid Build Coastguard Worker void StringInputStream::BackUp(size_t count) {
39*d57664e9SAndroid Build Coastguard Worker if (count > offset_) {
40*d57664e9SAndroid Build Coastguard Worker offset_ = 0u;
41*d57664e9SAndroid Build Coastguard Worker } else {
42*d57664e9SAndroid Build Coastguard Worker offset_ -= count;
43*d57664e9SAndroid Build Coastguard Worker }
44*d57664e9SAndroid Build Coastguard Worker }
45*d57664e9SAndroid Build Coastguard Worker
ByteCount() const46*d57664e9SAndroid Build Coastguard Worker size_t StringInputStream::ByteCount() const {
47*d57664e9SAndroid Build Coastguard Worker return offset_;
48*d57664e9SAndroid Build Coastguard Worker }
49*d57664e9SAndroid Build Coastguard Worker
TotalSize() const50*d57664e9SAndroid Build Coastguard Worker size_t StringInputStream::TotalSize() const {
51*d57664e9SAndroid Build Coastguard Worker return str_.size();
52*d57664e9SAndroid Build Coastguard Worker }
53*d57664e9SAndroid Build Coastguard Worker
ReadFullyAtOffset(void * data,size_t byte_count,off64_t offset)54*d57664e9SAndroid Build Coastguard Worker bool StringInputStream::ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) {
55*d57664e9SAndroid Build Coastguard Worker if (byte_count == 0) {
56*d57664e9SAndroid Build Coastguard Worker return true;
57*d57664e9SAndroid Build Coastguard Worker }
58*d57664e9SAndroid Build Coastguard Worker if (offset < 0) {
59*d57664e9SAndroid Build Coastguard Worker return false;
60*d57664e9SAndroid Build Coastguard Worker }
61*d57664e9SAndroid Build Coastguard Worker if (offset > std::numeric_limits<off64_t>::max() - byte_count) {
62*d57664e9SAndroid Build Coastguard Worker return false;
63*d57664e9SAndroid Build Coastguard Worker }
64*d57664e9SAndroid Build Coastguard Worker if (offset + byte_count > str_.size()) {
65*d57664e9SAndroid Build Coastguard Worker return false;
66*d57664e9SAndroid Build Coastguard Worker }
67*d57664e9SAndroid Build Coastguard Worker memcpy(data, str_.data() + offset, byte_count);
68*d57664e9SAndroid Build Coastguard Worker return true;
69*d57664e9SAndroid Build Coastguard Worker }
70*d57664e9SAndroid Build Coastguard Worker
StringOutputStream(std::string * str,size_t buffer_capacity)71*d57664e9SAndroid Build Coastguard Worker StringOutputStream::StringOutputStream(std::string* str, size_t buffer_capacity)
72*d57664e9SAndroid Build Coastguard Worker : str_(str),
73*d57664e9SAndroid Build Coastguard Worker buffer_capacity_(buffer_capacity),
74*d57664e9SAndroid Build Coastguard Worker buffer_offset_(0u),
75*d57664e9SAndroid Build Coastguard Worker buffer_(new char[buffer_capacity]) {
76*d57664e9SAndroid Build Coastguard Worker }
77*d57664e9SAndroid Build Coastguard Worker
~StringOutputStream()78*d57664e9SAndroid Build Coastguard Worker StringOutputStream::~StringOutputStream() {
79*d57664e9SAndroid Build Coastguard Worker Flush();
80*d57664e9SAndroid Build Coastguard Worker }
81*d57664e9SAndroid Build Coastguard Worker
Next(void ** data,size_t * size)82*d57664e9SAndroid Build Coastguard Worker bool StringOutputStream::Next(void** data, size_t* size) {
83*d57664e9SAndroid Build Coastguard Worker if (buffer_offset_ == buffer_capacity_) {
84*d57664e9SAndroid Build Coastguard Worker FlushImpl();
85*d57664e9SAndroid Build Coastguard Worker }
86*d57664e9SAndroid Build Coastguard Worker
87*d57664e9SAndroid Build Coastguard Worker *data = buffer_.get() + buffer_offset_;
88*d57664e9SAndroid Build Coastguard Worker *size = buffer_capacity_ - buffer_offset_;
89*d57664e9SAndroid Build Coastguard Worker buffer_offset_ = buffer_capacity_;
90*d57664e9SAndroid Build Coastguard Worker return true;
91*d57664e9SAndroid Build Coastguard Worker }
92*d57664e9SAndroid Build Coastguard Worker
BackUp(size_t count)93*d57664e9SAndroid Build Coastguard Worker void StringOutputStream::BackUp(size_t count) {
94*d57664e9SAndroid Build Coastguard Worker if (count > buffer_offset_) {
95*d57664e9SAndroid Build Coastguard Worker buffer_offset_ = 0u;
96*d57664e9SAndroid Build Coastguard Worker } else {
97*d57664e9SAndroid Build Coastguard Worker buffer_offset_ -= count;
98*d57664e9SAndroid Build Coastguard Worker }
99*d57664e9SAndroid Build Coastguard Worker }
100*d57664e9SAndroid Build Coastguard Worker
ByteCount() const101*d57664e9SAndroid Build Coastguard Worker size_t StringOutputStream::ByteCount() const {
102*d57664e9SAndroid Build Coastguard Worker return str_->size() + buffer_offset_;
103*d57664e9SAndroid Build Coastguard Worker }
104*d57664e9SAndroid Build Coastguard Worker
Flush()105*d57664e9SAndroid Build Coastguard Worker void StringOutputStream::Flush() {
106*d57664e9SAndroid Build Coastguard Worker if (buffer_offset_ != 0u) {
107*d57664e9SAndroid Build Coastguard Worker FlushImpl();
108*d57664e9SAndroid Build Coastguard Worker }
109*d57664e9SAndroid Build Coastguard Worker }
110*d57664e9SAndroid Build Coastguard Worker
FlushImpl()111*d57664e9SAndroid Build Coastguard Worker void StringOutputStream::FlushImpl() {
112*d57664e9SAndroid Build Coastguard Worker str_->append(buffer_.get(), buffer_offset_);
113*d57664e9SAndroid Build Coastguard Worker buffer_offset_ = 0u;
114*d57664e9SAndroid Build Coastguard Worker }
115*d57664e9SAndroid Build Coastguard Worker
116*d57664e9SAndroid Build Coastguard Worker } // namespace io
117*d57664e9SAndroid Build Coastguard Worker } // namespace aapt
118