summaryrefslogtreecommitdiff
path: root/tools/intergen/cppgen/src/cppgen/cpp_file.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tools/intergen/cppgen/src/cppgen/cpp_file.cc')
-rw-r--r--tools/intergen/cppgen/src/cppgen/cpp_file.cc225
1 files changed, 225 insertions, 0 deletions
diff --git a/tools/intergen/cppgen/src/cppgen/cpp_file.cc b/tools/intergen/cppgen/src/cppgen/cpp_file.cc
new file mode 100644
index 000000000..b346e16df
--- /dev/null
+++ b/tools/intergen/cppgen/src/cppgen/cpp_file.cc
@@ -0,0 +1,225 @@
+/**
+ * Copyright (c) 2014, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cppgen/cpp_file.h"
+
+#include <cassert>
+#include <ostream>
+
+#include "cppgen/naming_convention.h"
+#include "model/interface.h"
+#include "model/type.h"
+#include "utils/safeformat.h"
+
+using std::ostream;
+using std::endl;
+using typesafe_format::strmfmt;
+
+namespace codegen {
+
+namespace {
+const char* kAutoGeneratedComment = "// This file is generated, do not edit";
+
+// This class is used to find and automatically include appropriate
+// header file where given type is defined
+class IncludeTypeHelper: public TypeCodeGenerator {
+ public:
+ // Constructs include helper and immediately includes
+ // appropriate header file for passed |type|
+ // into |cpp_file|
+ IncludeTypeHelper(CppFile* cpp_file, const Type* type);
+ private:
+ // Methods
+ // Returns interface name where given |type| is defined
+ // Accepts Enum, Struct or Typedef types.
+ template<class T>
+ std::string GetTypeInterfaceName(const T* type);
+ // TypeCodeGenerator interface
+ virtual void GenerateCodeForArray(const Array* array);
+ virtual void GenerateCodeForMap(const Map* map);
+ virtual void GenerateCodeForEnum(const Enum* enm);
+ virtual void GenerateCodeForNullable(const NullableType* nullable);
+ virtual void GenerateCodeForStruct(const Struct* strct);
+ virtual void GenerateCodeForTypedef(const Typedef* tdef);
+ private:
+ // Fields
+ CppFile* cpp_file_;
+};
+
+IncludeTypeHelper::IncludeTypeHelper(CppFile* cpp_file, const Type* type)
+ : cpp_file_(cpp_file) {
+ type->Apply(this);
+}
+
+template<class T>
+std::string IncludeTypeHelper::GetTypeInterfaceName(const T* type) {
+ return LowercaseIntefaceName(type->interface());
+}
+
+void IncludeTypeHelper::GenerateCodeForArray(const Array* array) {
+ array->type()->Apply(this);
+}
+
+void IncludeTypeHelper::GenerateCodeForMap(const Map* map) {
+ map->type()->Apply(this);
+}
+
+void IncludeTypeHelper::GenerateCodeForEnum(const Enum *enm) {
+ cpp_file_->Include(CppFile::Header(
+ GetTypeInterfaceName(enm) + "/enums.h",
+ true));
+}
+
+void IncludeTypeHelper::GenerateCodeForNullable(const NullableType* nullable) {
+ nullable->type()->Apply(this);
+}
+
+void IncludeTypeHelper::GenerateCodeForStruct(const Struct* strct) {
+ cpp_file_->Include(CppFile::Header(
+ GetTypeInterfaceName(strct) + "/types.h",
+ true));
+}
+
+void IncludeTypeHelper::GenerateCodeForTypedef(const Typedef* tdef) {
+ cpp_file_->Include(CppFile::Header(
+ GetTypeInterfaceName(tdef) + "/types.h",
+ true));
+}
+
+}
+
+CppFile::CppFile(const std::string& file_name, const std::string& module_name,
+ bool write_guards)
+ : write_guards_(write_guards),
+ file_name_(file_name),
+ module_name_(module_name) {
+}
+
+CppFile::~CppFile() {
+}
+
+const std::string& CppFile::file_name() const {
+ return file_name_;
+}
+
+void CppFile::Include(const Header& header) {
+ headers_.insert(header);
+}
+
+void CppFile::IncludeType(const Type& type) {
+ IncludeTypeHelper(this, &type);
+}
+
+void CppFile::Write(std::ostream* os) {
+ std::string guard_name =
+ WordList::FromUnknown(module_name_+"_"+file_name_).ToUpperCase() + "_";
+ *os << kAutoGeneratedComment << endl;
+ if (write_guards_) {
+ *os << "#ifndef " << guard_name << endl;
+ *os << "#define " << guard_name << endl;
+ }
+ for (std::set<Header>::iterator i = headers_.begin(), end = headers_.end();
+ i != end; ++i) {
+ if (i->is_local()) {
+ strmfmt(*os, "#include \"{0}\"", i->name()) << endl;
+ } else {
+ strmfmt(*os, "#include <{0}>", i->name()) << endl;
+ }
+ }
+ global_namespace_.Write(os);
+ if (write_guards_) {
+ *os << "#endif // " << guard_name << endl;
+ }
+}
+
+bool CppFile::Header::is_local() const {
+ return local_;
+}
+
+const std::string& CppFile::Header::name() const {
+ return name_;
+}
+
+CppFile::Header::Header(const std::string& name, bool local)
+ : name_(name),
+ local_(local) {
+}
+
+bool CppFile::Header::operator <(const Header& that) const {
+ if (this->local_ != that.local_) {
+ return int(this->local_) < int(that.local_);
+ }
+ return this->name_ < that.name_;
+}
+
+Namespace& CppFile::global_namespace() {
+ return global_namespace_;
+}
+
+Namespace& CppFile::module_namespace() {
+ return
+ module_name_.empty() ?
+ global_namespace() : global_namespace().nested("rpc").nested(module_name_);
+}
+
+Namespace& CppFile::types_ns() {
+ return module_namespace();
+}
+
+Namespace& CppFile::requests_ns() {
+ return module_namespace().nested("request");
+}
+
+Namespace& CppFile::responses_ns() {
+ return module_namespace().nested("response");
+}
+
+Namespace& CppFile::notifications_ns() {
+ return module_namespace().nested("notification");
+}
+
+Namespace& CppFile::NamespaceByMessageType(FunctionMessage::MessageType type) {
+ switch(type) {
+ case FunctionMessage::kRequest:
+ return requests_ns();
+ case FunctionMessage::kResponse:
+ return responses_ns();
+ case FunctionMessage::kNotification:
+ return notifications_ns();
+ default:
+ assert(!"Invalid message type");
+ return global_namespace();
+ }
+}
+
+} // namespace codegen
+