1 /*
2  * Copyright (C) 2017 The Android Open Source Project
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 #ifndef AAPT_IO_UTIL_H
18 #define AAPT_IO_UTIL_H
19 
20 #include <string>
21 
22 #include "google/protobuf/message_lite.h"
23 #include "google/protobuf/io/coded_stream.h"
24 
25 #include "format/Archive.h"
26 #include "io/File.h"
27 #include "io/Io.h"
28 #include "process/IResourceTableConsumer.h"
29 
30 namespace aapt {
31 namespace io {
32 
33 bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, const std::string& out_path,
34                               uint32_t compression_flags, IArchiveWriter* writer);
35 
36 bool CopyFileToArchive(IAaptContext* context, IFile* file, const std::string& out_path,
37                        uint32_t compression_flags, IArchiveWriter* writer);
38 
39 bool CopyFileToArchivePreserveCompression(IAaptContext* context, IFile* file,
40                                           const std::string& out_path, IArchiveWriter* writer);
41 
42 bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* proto_msg,
43                         const std::string& out_path, uint32_t compression_flags,
44                         IArchiveWriter* writer);
45 
46 // Copies the data from in to out. Returns false if there was an error.
47 // If there was an error, check the individual streams' HadError/GetError methods.
48 bool Copy(OutputStream* out, InputStream* in);
49 bool Copy(OutputStream* out, const ::android::StringPiece& in);
50 bool Copy(::google::protobuf::io::ZeroCopyOutputStream* out, InputStream* in);
51 
52 class OutputStreamAdaptor : public io::OutputStream {
53  public:
OutputStreamAdaptor(::google::protobuf::io::ZeroCopyOutputStream * out)54   explicit OutputStreamAdaptor(::google::protobuf::io::ZeroCopyOutputStream* out) : out_(out) {
55   }
56 
Next(void ** data,size_t * size)57   bool Next(void** data, size_t* size) override {
58     int out_size;
59     bool result = out_->Next(data, &out_size);
60     *size = static_cast<size_t>(out_size);
61     if (!result) {
62       error_ocurred_ = true;
63     }
64     return result;
65   }
66 
BackUp(size_t count)67   void BackUp(size_t count) override {
68     out_->BackUp(static_cast<int>(count));
69   }
70 
ByteCount()71   size_t ByteCount() const override {
72     return static_cast<size_t>(out_->ByteCount());
73   }
74 
HadError()75   bool HadError() const override {
76     return error_ocurred_;
77   }
78 
79  private:
80   DISALLOW_COPY_AND_ASSIGN(OutputStreamAdaptor);
81 
82   ::google::protobuf::io::ZeroCopyOutputStream* out_;
83   bool error_ocurred_ = false;
84 };
85 
86 class ZeroCopyInputAdaptor : public ::google::protobuf::io::ZeroCopyInputStream {
87  public:
ZeroCopyInputAdaptor(io::InputStream * in)88   explicit ZeroCopyInputAdaptor(io::InputStream* in) : in_(in) {
89   }
90 
Next(const void ** data,int * size)91   bool Next(const void** data, int* size) override {
92     size_t out_size;
93     bool result = in_->Next(data, &out_size);
94     *size = static_cast<int>(out_size);
95     return result;
96   }
97 
BackUp(int count)98   void BackUp(int count) override {
99     in_->BackUp(static_cast<size_t>(count));
100   }
101 
Skip(int count)102   bool Skip(int count) override {
103     const void* data;
104     int size;
105     while (Next(&data, &size)) {
106       if (size > count) {
107         BackUp(size - count);
108         return true;
109       } else {
110         count -= size;
111       }
112     }
113     return false;
114   }
115 
ByteCount()116   ::google::protobuf::int64 ByteCount() const override {
117     return static_cast<::google::protobuf::int64>(in_->ByteCount());
118   }
119 
120  private:
121   DISALLOW_COPY_AND_ASSIGN(ZeroCopyInputAdaptor);
122 
123   io::InputStream* in_;
124 };
125 
126 class ProtoInputStreamReader {
127  public:
ProtoInputStreamReader(io::InputStream * in)128   explicit ProtoInputStreamReader(io::InputStream* in) : in_(in) { }
129 
130   /** Deserializes a MessageLite proto from the current position in the input stream.*/
ReadMessage(T * message_lite)131   template <typename T> bool ReadMessage(T *message_lite) {
132     ZeroCopyInputAdaptor adapter(in_);
133     google::protobuf::io::CodedInputStream coded_stream(&adapter);
134     coded_stream.SetTotalBytesLimit(std::numeric_limits<int32_t>::max(),
135                                     coded_stream.BytesUntilTotalBytesLimit());
136     return message_lite->ParseFromCodedStream(&coded_stream);
137   }
138 
139  private:
140   io::InputStream* in_;
141 };
142 
143 }  // namespace io
144 }  // namespace aapt
145 
146 #endif /* AAPT_IO_UTIL_H */
147