• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #include "dynamicproto.h"
3 
4 #include <google/protobuf/dynamic_message.h>
5 #include <google/protobuf/compiler/importer.h>
6 
7 #include <iostream>
8 #include <memory>
9 #include <exception>
10 
11 using namespace google::protobuf::compiler;
12 using namespace google::protobuf;
13 
14 namespace {
15 
16 class ErrorCollector : public MultiFileErrorCollector {
17  public:
AddError(const std::string & file_name,int line,int column,const std::string & message)18   void AddError(const std::string& file_name, int line, int column,
19                         const std::string& message) override {
20     std::cerr << "Error in: " << file_name << " line: " << line << " column: "
21               << column << " message: " << message << std::endl;
22   }
23 };
24 
25 DiskSourceTree source_tree;
26 ErrorCollector error_collector;
27 std::unique_ptr<Importer> importer;
28 DynamicMessageFactory factory; // This needs to be kept around
29 
30 } // namespace
31 
32 namespace dynamicproto {
33 
warnNotInitialized()34 void warnNotInitialized() {
35   std::cerr << "Warning: dynamicproto has not been initalized" << std::endl;
36 }
37 
init(const std::vector<std::string> & include_paths)38 void init(const std::vector<std::string>& include_paths) {
39   for (auto& path: include_paths) {
40     source_tree.MapPath("", path);
41   }
42   importer = std::unique_ptr<Importer>(new Importer(&source_tree,
43                                                     &error_collector));
44 }
45 
fileDescriptorDependencies(const FileDescriptor * fdesc,std::vector<const FileDescriptor * > & result)46 void fileDescriptorDependencies(const FileDescriptor* fdesc,
47                                 std::vector<const FileDescriptor*>& result) {
48   if(fdesc) {
49     size_t n = fdesc->dependency_count();
50     for (size_t i=0; i<n; ++i) {
51       fileDescriptorDependencies(fdesc->dependency(i), result);
52     }
53     result.push_back(fdesc);
54   }
55 }
56 
57 // Get a FileDescriptor for the file and all its dependencies,
58 //  the latter of which appear at the beginning of the vector.
59 std::vector<const FileDescriptor*>
fileDescriptors(const std::string & file_name)60 fileDescriptors(const std::string& file_name) {
61   std::vector<const FileDescriptor*> result;
62   if(importer) {
63     const FileDescriptor* fdesc = importer->Import(file_name);
64     fileDescriptorDependencies(fdesc, result);
65   }
66   else {
67     warnNotInitialized();
68   }
69   return result;
70 }
71 
72 // Find extensions of full_name in desc and add them to result.
extensionsOf(const FileDescriptor * desc,const std::string & full_name,std::vector<const FieldDescriptor * > & result)73 void extensionsOf(const FileDescriptor* desc, const std::string& full_name,
74                   std::vector<const FieldDescriptor*>& result) {
75   // TODO: look in all messages that may contain inner extensions
76   if(desc) {
77       int n = desc->extension_count();
78       for (int i=0;i<n;++i) {
79         auto e = desc->extension(i);
80         if(e->containing_type()->full_name()==full_name)
81           result.push_back(e);
82       }
83       n = desc->dependency_count();
84       for (int i=0;i<n;++i) {
85         extensionsOf(desc->dependency(i), full_name, result);
86       }
87   }
88 }
89 
enums(const FileDescriptor * extDesc)90 std::vector<const EnumDescriptor*> enums(const FileDescriptor* extDesc) {
91   std::vector<const EnumDescriptor*> result;
92   if(extDesc) {
93       int n = extDesc->enum_type_count();
94       for (int i=0;i<n;++i) {
95         auto e = extDesc->enum_type(i);
96         result.push_back(e);
97       }
98   }
99   return result;
100 }
101 
print(const EnumDescriptor * e,std::ostream & o)102 void print(const EnumDescriptor* e, std::ostream& o) {
103   o << "enum " << e->name() << " { ";
104   int n = e->value_count();
105   bool first = true;
106   for (int i=0; i<n; ++i) {
107     if(first)
108       first = false;
109     else
110       o << ", ";
111     o << e->value(i)->name() << "=" << (i+1);
112   }
113   o << "}";
114 }
115 
newMessage(const FileDescriptor * fdesc,const std::string & name)116 Message* newMessage(const FileDescriptor* fdesc, const std::string& name) {
117   auto desc = fdesc->FindMessageTypeByName(name);
118   if(desc) {
119     auto p = factory.GetPrototype(desc);
120     if(p)
121       return p->New();
122   }
123   size_t n = fdesc->dependency_count();
124   for (size_t i=0; i<n; ++i) {
125     auto m = newMessage(fdesc->dependency(i), name);
126     if(m) return m;
127   }
128   return nullptr;
129 }
130 
131 } // namespace dynamicproto
132