blob: 048dade071d71fca7463f92a12b0f154c05e39d5 [file] [log] [blame]
/*
* Copyright (C) 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "code_writer.h"
#include <fstream>
#include <iostream>
#include <stdarg.h>
#include <vector>
#include <android-base/stringprintf.h>
namespace android {
namespace aidl {
std::string CodeWriter::ApplyIndent(const std::string& str) {
std::string output;
if (!start_of_line_ || str == "\n") {
output = str;
} else {
output = std::string(indent_level_ * 2, ' ') + str;
}
start_of_line_ = !output.empty() && output.back() == '\n';
return output;
}
bool CodeWriter::Write(const char* format, ...) {
va_list ap;
va_start(ap, format);
std::string formatted;
android::base::StringAppendV(&formatted, format, ap);
va_end(ap);
// extract lines. empty line is preserved.
std::vector<std::string> lines;
size_t pos = 0;
while (pos < formatted.size()) {
size_t line_end = formatted.find('\n', pos);
if (line_end != std::string::npos) {
lines.push_back(formatted.substr(pos, (line_end - pos) + 1));
pos = line_end + 1;
} else {
lines.push_back(formatted.substr(pos));
break;
}
}
std::string indented;
for (auto line : lines) {
indented.append(ApplyIndent(line));
}
return Output(indented);
}
class StringCodeWriter : public CodeWriter {
public:
explicit StringCodeWriter(std::string* output_buffer) : output_(output_buffer) {}
virtual ~StringCodeWriter() = default;
bool Output(const std::string& str) override {
output_->append(str);
return true;
}
bool Close() override { return true; }
private:
std::string* output_;
}; // class StringCodeWriter
class FileCodeWriter : public CodeWriter {
public:
explicit FileCodeWriter(const std::string& filename) : cout_(std::cout) {
if (filename == "-") {
to_stdout_ = true;
} else {
to_stdout_ = false;
fileout_.open(filename, std::ofstream::out |
std::ofstream::binary);
if (fileout_.fail()) {
std::cerr << "unable to open " << filename << " for write" << std::endl;
}
}
}
bool Output(const std::string& str) override {
if (to_stdout_) {
cout_ << str;
} else {
fileout_ << str;
}
return TestSuccess();
}
bool Close() override {
if (!to_stdout_) {
fileout_.close();
}
return TestSuccess();
}
bool TestSuccess() const {
return to_stdout_ ? true : !fileout_.fail();
}
private:
std::ostream& cout_;
std::ofstream fileout_;
bool to_stdout_;
}; // class StringCodeWriter
CodeWriterPtr GetFileWriter(const std::string& output_file) {
return CodeWriterPtr(new FileCodeWriter(output_file));
}
CodeWriterPtr GetStringWriter(std::string* output_buffer) {
return CodeWriterPtr(new StringCodeWriter(output_buffer));
}
} // namespace aidl
} // namespace android