blob: 048dade071d71fca7463f92a12b0f154c05e39d5 [file] [log] [blame]
Christopher Wileyfdeb0f42015-09-11 15:38:22 -07001/*
2 * Copyright (C) 2015, 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#include "code_writer.h"
18
Jiyong Parka755dc72018-06-29 13:52:24 +090019#include <fstream>
Christopher Wiley413e0422015-09-18 10:54:51 -070020#include <iostream>
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070021#include <stdarg.h>
Jiyong Parka755dc72018-06-29 13:52:24 +090022#include <vector>
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070023
Elliott Hughes0a620672015-12-04 13:53:18 -080024#include <android-base/stringprintf.h>
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070025
26namespace android {
27namespace aidl {
28
Jiyong Parka755dc72018-06-29 13:52:24 +090029std::string CodeWriter::ApplyIndent(const std::string& str) {
30 std::string output;
31 if (!start_of_line_ || str == "\n") {
32 output = str;
33 } else {
34 output = std::string(indent_level_ * 2, ' ') + str;
35 }
36 start_of_line_ = !output.empty() && output.back() == '\n';
37 return output;
38}
39
40bool CodeWriter::Write(const char* format, ...) {
41 va_list ap;
42 va_start(ap, format);
43 std::string formatted;
44 android::base::StringAppendV(&formatted, format, ap);
45 va_end(ap);
46
47 // extract lines. empty line is preserved.
48 std::vector<std::string> lines;
49 size_t pos = 0;
50 while (pos < formatted.size()) {
51 size_t line_end = formatted.find('\n', pos);
52 if (line_end != std::string::npos) {
53 lines.push_back(formatted.substr(pos, (line_end - pos) + 1));
54 pos = line_end + 1;
55 } else {
56 lines.push_back(formatted.substr(pos));
57 break;
58 }
59 }
60
61 std::string indented;
62 for (auto line : lines) {
63 indented.append(ApplyIndent(line));
64 }
65 return Output(indented);
66}
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070067
68class StringCodeWriter : public CodeWriter {
69 public:
Chih-Hung Hsiehe4fecc72016-04-25 12:04:59 -070070 explicit StringCodeWriter(std::string* output_buffer) : output_(output_buffer) {}
Christopher Wiley9d6e0b22015-11-13 12:18:16 -080071 virtual ~StringCodeWriter() = default;
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070072
Jiyong Parka755dc72018-06-29 13:52:24 +090073 bool Output(const std::string& str) override {
74 output_->append(str);
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070075 return true;
76 }
77
Christopher Wiley9d6e0b22015-11-13 12:18:16 -080078 bool Close() override { return true; }
79
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070080 private:
81 std::string* output_;
82}; // class StringCodeWriter
83
84class FileCodeWriter : public CodeWriter {
85 public:
Jiyong Parka755dc72018-06-29 13:52:24 +090086 explicit FileCodeWriter(const std::string& filename) : cout_(std::cout) {
87 if (filename == "-") {
88 to_stdout_ = true;
89 } else {
90 to_stdout_ = false;
91 fileout_.open(filename, std::ofstream::out |
92 std::ofstream::binary);
93 if (fileout_.fail()) {
94 std::cerr << "unable to open " << filename << " for write" << std::endl;
95 }
Christopher Wiley413e0422015-09-18 10:54:51 -070096 }
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070097 }
98
Jiyong Parka755dc72018-06-29 13:52:24 +090099 bool Output(const std::string& str) override {
100 if (to_stdout_) {
101 cout_ << str;
102 } else {
103 fileout_ << str;
104 }
105 return TestSuccess();
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700106 }
107
Christopher Wiley9d6e0b22015-11-13 12:18:16 -0800108 bool Close() override {
Jiyong Parka755dc72018-06-29 13:52:24 +0900109 if (!to_stdout_) {
110 fileout_.close();
Christopher Wiley9d6e0b22015-11-13 12:18:16 -0800111 }
Jiyong Parka755dc72018-06-29 13:52:24 +0900112 return TestSuccess();
113 }
114
115 bool TestSuccess() const {
116 return to_stdout_ ? true : !fileout_.fail();
Christopher Wiley9d6e0b22015-11-13 12:18:16 -0800117 }
118
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700119 private:
Jiyong Parka755dc72018-06-29 13:52:24 +0900120 std::ostream& cout_;
121 std::ofstream fileout_;
122 bool to_stdout_;
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700123}; // class StringCodeWriter
124
Christopher Wiley413e0422015-09-18 10:54:51 -0700125CodeWriterPtr GetFileWriter(const std::string& output_file) {
Jiyong Parka755dc72018-06-29 13:52:24 +0900126 return CodeWriterPtr(new FileCodeWriter(output_file));
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700127}
128
Christopher Wiley413e0422015-09-18 10:54:51 -0700129CodeWriterPtr GetStringWriter(std::string* output_buffer) {
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700130 return CodeWriterPtr(new StringCodeWriter(output_buffer));
131}
132
133} // namespace aidl
134} // namespace android