1fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley/*
2fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley * Copyright (C) 2015, The Android Open Source Project
3fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley *
4fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley * Licensed under the Apache License, Version 2.0 (the "License");
5fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley * you may not use this file except in compliance with the License.
6fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley * You may obtain a copy of the License at
7fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley *
8fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley *     http://www.apache.org/licenses/LICENSE-2.0
9fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley *
10fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley * Unless required by applicable law or agreed to in writing, software
11fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley * distributed under the License is distributed on an "AS IS" BASIS,
12fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley * See the License for the specific language governing permissions and
14fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley * limitations under the License.
15fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley */
16fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
17fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley#include "code_writer.h"
18fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
19413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley#include <iostream>
20fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley#include <stdarg.h>
21fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
220a62067f35e957493bc37c4b42dfdcfc16353831Elliott Hughes#include <android-base/stringprintf.h>
23fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
24413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wileyusing std::cerr;
25413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wileyusing std::endl;
26413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley
27fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wileynamespace android {
28fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wileynamespace aidl {
29fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
30fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wileynamespace {
31fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
32fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wileyclass StringCodeWriter : public CodeWriter {
33fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley public:
34e4fecc7754e3829f09abefcc35630ef0b110b01eChih-Hung Hsieh  explicit StringCodeWriter(std::string* output_buffer) : output_(output_buffer) {}
359d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  virtual ~StringCodeWriter() = default;
36fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
37fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley  bool Write(const char* format, ...) override {
38fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley    va_list ap;
39fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley    va_start(ap, format);
40fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley    android::base::StringAppendV(output_, format, ap);
41fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley    va_end(ap);
42fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley    return true;
43fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley  }
44fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
459d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  bool Close() override { return true; }
469d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley
47fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley private:
48fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley  std::string* output_;
49fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley};  // class StringCodeWriter
50fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
51fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wileyclass FileCodeWriter : public CodeWriter {
52fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley public:
53413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley  FileCodeWriter(FILE* output_file, bool close_on_destruction)
54413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley      : output_(output_file),
55413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley        close_on_destruction_(close_on_destruction) {}
569d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  virtual ~FileCodeWriter() {
579d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley    if (close_on_destruction_ && output_ != nullptr) {
58413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley      fclose(output_);
59413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley    }
60fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley  }
61fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
62fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley  bool Write(const char* format, ...) override {
63fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley    bool success;
64fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley    va_list ap;
65fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley    va_start(ap, format);
66fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley    success = vfprintf(output_, format, ap) >= 0;
67fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley    va_end(ap);
689d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley    no_error_ = no_error_ && success;
69fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley    return success;
70fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley  }
71fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
729d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  bool Close() override {
739d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley    if (output_ != nullptr) {
749d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley      no_error_ = fclose(output_) == 0 && no_error_;
759d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley      output_ = nullptr;
769d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley    }
779d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley    return no_error_;
789d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  }
799d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley
80fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley private:
819d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  bool no_error_ = true;
82fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley  FILE* output_;
83413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley  bool close_on_destruction_;
84fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley};  // class StringCodeWriter
85fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
86fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley}  // namespace
87fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
88413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher WileyCodeWriterPtr GetFileWriter(const std::string& output_file) {
89413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley  CodeWriterPtr result;
90413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley  FILE* to = nullptr;
91413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley  bool close_on_destruction = true;
92413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley  if (output_file == "-") {
93413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley    to = stdout;
94413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley    close_on_destruction = false;
95413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley  } else {
96413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley    // open file in binary mode to ensure that the tool produces the
97413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley    // same output on all platforms !!
98413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley    to = fopen(output_file.c_str(), "wb");
99413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley  }
100413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley
101413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley  if (to != nullptr) {
102413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley    result.reset(new FileCodeWriter(to, close_on_destruction));
103413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley  } else {
104413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley    cerr << "unable to open " << output_file << " for write" << endl;
105413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley  }
106413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley
107413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher Wiley  return result;
108fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley}
109fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
110413e0426eebdb41d8e9344bd2a6a0ef79369de25Christopher WileyCodeWriterPtr GetStringWriter(std::string* output_buffer) {
111fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley  return CodeWriterPtr(new StringCodeWriter(output_buffer));
112fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley}
113fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley
114fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley}  // namespace aidl
115fdeb0f4b96b6c39b1b9ed3358634f180f9e6df06Christopher Wiley}  // namespace android
116