xref: /aosp_15_r20/frameworks/base/tools/aapt2/io/Util.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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/Util.h"
18*d57664e9SAndroid Build Coastguard Worker 
19*d57664e9SAndroid Build Coastguard Worker #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
20*d57664e9SAndroid Build Coastguard Worker 
21*d57664e9SAndroid Build Coastguard Worker #include "trace/TraceBuffer.h"
22*d57664e9SAndroid Build Coastguard Worker 
23*d57664e9SAndroid Build Coastguard Worker using ::android::StringPiece;
24*d57664e9SAndroid Build Coastguard Worker using ::google::protobuf::io::ZeroCopyOutputStream;
25*d57664e9SAndroid Build Coastguard Worker 
26*d57664e9SAndroid Build Coastguard Worker namespace aapt {
27*d57664e9SAndroid Build Coastguard Worker namespace io {
28*d57664e9SAndroid Build Coastguard Worker 
CopyInputStreamToArchive(IAaptContext * context,android::InputStream * in,std::string_view out_path,uint32_t compression_flags,IArchiveWriter * writer)29*d57664e9SAndroid Build Coastguard Worker bool CopyInputStreamToArchive(IAaptContext* context, android::InputStream* in,
30*d57664e9SAndroid Build Coastguard Worker                               std::string_view out_path, uint32_t compression_flags,
31*d57664e9SAndroid Build Coastguard Worker                               IArchiveWriter* writer) {
32*d57664e9SAndroid Build Coastguard Worker   TRACE_CALL();
33*d57664e9SAndroid Build Coastguard Worker   if (context->IsVerbose()) {
34*d57664e9SAndroid Build Coastguard Worker     context->GetDiagnostics()->Note(android::DiagMessage()
35*d57664e9SAndroid Build Coastguard Worker                                     << "writing " << out_path << " to archive");
36*d57664e9SAndroid Build Coastguard Worker   }
37*d57664e9SAndroid Build Coastguard Worker 
38*d57664e9SAndroid Build Coastguard Worker   if (!writer->WriteFile(out_path, compression_flags, in)) {
39*d57664e9SAndroid Build Coastguard Worker     context->GetDiagnostics()->Error(android::DiagMessage()
40*d57664e9SAndroid Build Coastguard Worker                                      << "failed to write " << out_path
41*d57664e9SAndroid Build Coastguard Worker                                      << " to archive: " << writer->GetError());
42*d57664e9SAndroid Build Coastguard Worker     return false;
43*d57664e9SAndroid Build Coastguard Worker   }
44*d57664e9SAndroid Build Coastguard Worker   return true;
45*d57664e9SAndroid Build Coastguard Worker }
46*d57664e9SAndroid Build Coastguard Worker 
CopyFileToArchive(IAaptContext * context,io::IFile * file,std::string_view out_path,uint32_t compression_flags,IArchiveWriter * writer)47*d57664e9SAndroid Build Coastguard Worker bool CopyFileToArchive(IAaptContext* context, io::IFile* file, std::string_view out_path,
48*d57664e9SAndroid Build Coastguard Worker                        uint32_t compression_flags, IArchiveWriter* writer) {
49*d57664e9SAndroid Build Coastguard Worker   TRACE_CALL();
50*d57664e9SAndroid Build Coastguard Worker   std::unique_ptr<io::IData> data = file->OpenAsData();
51*d57664e9SAndroid Build Coastguard Worker   if (!data) {
52*d57664e9SAndroid Build Coastguard Worker     context->GetDiagnostics()->Error(android::DiagMessage(file->GetSource())
53*d57664e9SAndroid Build Coastguard Worker                                      << "failed to open file");
54*d57664e9SAndroid Build Coastguard Worker     return false;
55*d57664e9SAndroid Build Coastguard Worker   }
56*d57664e9SAndroid Build Coastguard Worker   return CopyInputStreamToArchive(context, data.get(), out_path, compression_flags, writer);
57*d57664e9SAndroid Build Coastguard Worker }
58*d57664e9SAndroid Build Coastguard Worker 
CopyFileToArchivePreserveCompression(IAaptContext * context,io::IFile * file,std::string_view out_path,IArchiveWriter * writer)59*d57664e9SAndroid Build Coastguard Worker bool CopyFileToArchivePreserveCompression(IAaptContext* context, io::IFile* file,
60*d57664e9SAndroid Build Coastguard Worker                                           std::string_view out_path, IArchiveWriter* writer) {
61*d57664e9SAndroid Build Coastguard Worker   uint32_t compression_flags = file->WasCompressed() ? ArchiveEntry::kCompress : 0u;
62*d57664e9SAndroid Build Coastguard Worker   return CopyFileToArchive(context, file, out_path, compression_flags, writer);
63*d57664e9SAndroid Build Coastguard Worker }
64*d57664e9SAndroid Build Coastguard Worker 
CopyProtoToArchive(IAaptContext * context,::google::protobuf::Message * proto_msg,std::string_view out_path,uint32_t compression_flags,IArchiveWriter * writer)65*d57664e9SAndroid Build Coastguard Worker bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::Message* proto_msg,
66*d57664e9SAndroid Build Coastguard Worker                         std::string_view out_path, uint32_t compression_flags,
67*d57664e9SAndroid Build Coastguard Worker                         IArchiveWriter* writer) {
68*d57664e9SAndroid Build Coastguard Worker   TRACE_CALL();
69*d57664e9SAndroid Build Coastguard Worker   if (context->IsVerbose()) {
70*d57664e9SAndroid Build Coastguard Worker     context->GetDiagnostics()->Note(android::DiagMessage()
71*d57664e9SAndroid Build Coastguard Worker                                     << "writing " << out_path << " to archive");
72*d57664e9SAndroid Build Coastguard Worker   }
73*d57664e9SAndroid Build Coastguard Worker 
74*d57664e9SAndroid Build Coastguard Worker   if (writer->StartEntry(out_path, compression_flags)) {
75*d57664e9SAndroid Build Coastguard Worker     // Make sure CopyingOutputStreamAdaptor is deleted before we call writer->FinishEntry().
76*d57664e9SAndroid Build Coastguard Worker     {
77*d57664e9SAndroid Build Coastguard Worker       // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream interface.
78*d57664e9SAndroid Build Coastguard Worker       ::google::protobuf::io::CopyingOutputStreamAdaptor adaptor(writer);
79*d57664e9SAndroid Build Coastguard Worker       if (!proto_msg->SerializeToZeroCopyStream(&adaptor)) {
80*d57664e9SAndroid Build Coastguard Worker         context->GetDiagnostics()->Error(android::DiagMessage()
81*d57664e9SAndroid Build Coastguard Worker                                          << "failed to write " << out_path << " to archive");
82*d57664e9SAndroid Build Coastguard Worker         return false;
83*d57664e9SAndroid Build Coastguard Worker       }
84*d57664e9SAndroid Build Coastguard Worker     }
85*d57664e9SAndroid Build Coastguard Worker 
86*d57664e9SAndroid Build Coastguard Worker     if (writer->FinishEntry()) {
87*d57664e9SAndroid Build Coastguard Worker       return true;
88*d57664e9SAndroid Build Coastguard Worker     }
89*d57664e9SAndroid Build Coastguard Worker   }
90*d57664e9SAndroid Build Coastguard Worker   context->GetDiagnostics()->Error(android::DiagMessage() << "failed to write " << out_path
91*d57664e9SAndroid Build Coastguard Worker                                                           << " to archive: " << writer->GetError());
92*d57664e9SAndroid Build Coastguard Worker   return false;
93*d57664e9SAndroid Build Coastguard Worker }
94*d57664e9SAndroid Build Coastguard Worker 
Copy(android::OutputStream * out,android::InputStream * in)95*d57664e9SAndroid Build Coastguard Worker bool Copy(android::OutputStream* out, android::InputStream* in) {
96*d57664e9SAndroid Build Coastguard Worker   TRACE_CALL();
97*d57664e9SAndroid Build Coastguard Worker   const void* in_buffer;
98*d57664e9SAndroid Build Coastguard Worker   size_t in_len;
99*d57664e9SAndroid Build Coastguard Worker   while (in->Next(&in_buffer, &in_len)) {
100*d57664e9SAndroid Build Coastguard Worker     void* out_buffer;
101*d57664e9SAndroid Build Coastguard Worker     size_t out_len;
102*d57664e9SAndroid Build Coastguard Worker     if (!out->Next(&out_buffer, &out_len)) {
103*d57664e9SAndroid Build Coastguard Worker       return !out->HadError();
104*d57664e9SAndroid Build Coastguard Worker     }
105*d57664e9SAndroid Build Coastguard Worker 
106*d57664e9SAndroid Build Coastguard Worker     const size_t bytes_to_copy = in_len < out_len ? in_len : out_len;
107*d57664e9SAndroid Build Coastguard Worker     memcpy(out_buffer, in_buffer, bytes_to_copy);
108*d57664e9SAndroid Build Coastguard Worker     out->BackUp(out_len - bytes_to_copy);
109*d57664e9SAndroid Build Coastguard Worker     in->BackUp(in_len - bytes_to_copy);
110*d57664e9SAndroid Build Coastguard Worker   }
111*d57664e9SAndroid Build Coastguard Worker   return !in->HadError();
112*d57664e9SAndroid Build Coastguard Worker }
113*d57664e9SAndroid Build Coastguard Worker 
Copy(android::OutputStream * out,StringPiece in)114*d57664e9SAndroid Build Coastguard Worker bool Copy(android::OutputStream* out, StringPiece in) {
115*d57664e9SAndroid Build Coastguard Worker   const char* in_buffer = in.data();
116*d57664e9SAndroid Build Coastguard Worker   size_t in_len = in.size();
117*d57664e9SAndroid Build Coastguard Worker   while (in_len != 0) {
118*d57664e9SAndroid Build Coastguard Worker     void* out_buffer;
119*d57664e9SAndroid Build Coastguard Worker     size_t out_len;
120*d57664e9SAndroid Build Coastguard Worker     if (!out->Next(&out_buffer, &out_len)) {
121*d57664e9SAndroid Build Coastguard Worker       return false;
122*d57664e9SAndroid Build Coastguard Worker     }
123*d57664e9SAndroid Build Coastguard Worker 
124*d57664e9SAndroid Build Coastguard Worker     const size_t bytes_to_copy = in_len < out_len ? in_len : out_len;
125*d57664e9SAndroid Build Coastguard Worker     memcpy(out_buffer, in_buffer, bytes_to_copy);
126*d57664e9SAndroid Build Coastguard Worker     out->BackUp(out_len - bytes_to_copy);
127*d57664e9SAndroid Build Coastguard Worker     in_buffer += bytes_to_copy;
128*d57664e9SAndroid Build Coastguard Worker     in_len -= bytes_to_copy;
129*d57664e9SAndroid Build Coastguard Worker   }
130*d57664e9SAndroid Build Coastguard Worker   return true;
131*d57664e9SAndroid Build Coastguard Worker }
132*d57664e9SAndroid Build Coastguard Worker 
Copy(ZeroCopyOutputStream * out,android::InputStream * in)133*d57664e9SAndroid Build Coastguard Worker bool Copy(ZeroCopyOutputStream* out, android::InputStream* in) {
134*d57664e9SAndroid Build Coastguard Worker   OutputStreamAdaptor adaptor(out);
135*d57664e9SAndroid Build Coastguard Worker   return Copy(&adaptor, in);
136*d57664e9SAndroid Build Coastguard Worker }
137*d57664e9SAndroid Build Coastguard Worker 
138*d57664e9SAndroid Build Coastguard Worker }  // namespace io
139*d57664e9SAndroid Build Coastguard Worker }  // namespace aapt
140