1/*
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
19#include <iostream>
20#include <stdarg.h>
21
22#include <android-base/stringprintf.h>
23
24using std::cerr;
25using std::endl;
26
27namespace android {
28namespace aidl {
29
30namespace {
31
32class StringCodeWriter : public CodeWriter {
33 public:
34  StringCodeWriter(std::string* output_buffer) : output_(output_buffer) {}
35  virtual ~StringCodeWriter() = default;
36
37  bool Write(const char* format, ...) override {
38    va_list ap;
39    va_start(ap, format);
40    android::base::StringAppendV(output_, format, ap);
41    va_end(ap);
42    return true;
43  }
44
45  bool Close() override { return true; }
46
47 private:
48  std::string* output_;
49};  // class StringCodeWriter
50
51class FileCodeWriter : public CodeWriter {
52 public:
53  FileCodeWriter(FILE* output_file, bool close_on_destruction)
54      : output_(output_file),
55        close_on_destruction_(close_on_destruction) {}
56  virtual ~FileCodeWriter() {
57    if (close_on_destruction_ && output_ != nullptr) {
58      fclose(output_);
59    }
60  }
61
62  bool Write(const char* format, ...) override {
63    bool success;
64    va_list ap;
65    va_start(ap, format);
66    success = vfprintf(output_, format, ap) >= 0;
67    va_end(ap);
68    no_error_ = no_error_ && success;
69    return success;
70  }
71
72  bool Close() override {
73    if (output_ != nullptr) {
74      no_error_ = fclose(output_) == 0 && no_error_;
75      output_ = nullptr;
76    }
77    return no_error_;
78  }
79
80 private:
81  bool no_error_ = true;
82  FILE* output_;
83  bool close_on_destruction_;
84};  // class StringCodeWriter
85
86}  // namespace
87
88CodeWriterPtr GetFileWriter(const std::string& output_file) {
89  CodeWriterPtr result;
90  FILE* to = nullptr;
91  bool close_on_destruction = true;
92  if (output_file == "-") {
93    to = stdout;
94    close_on_destruction = false;
95  } else {
96    // open file in binary mode to ensure that the tool produces the
97    // same output on all platforms !!
98    to = fopen(output_file.c_str(), "wb");
99  }
100
101  if (to != nullptr) {
102    result.reset(new FileCodeWriter(to, close_on_destruction));
103  } else {
104    cerr << "unable to open " << output_file << " for write" << endl;
105  }
106
107  return result;
108}
109
110CodeWriterPtr GetStringWriter(std::string* output_buffer) {
111  return CodeWriterPtr(new StringCodeWriter(output_buffer));
112}
113
114}  // namespace aidl
115}  // namespace android
116