Skip to content

Commit

Permalink
Modernize some constructions
Browse files Browse the repository at this point in the history
  • Loading branch information
brunexgeek committed Jan 26, 2024
1 parent 7647ab6 commit 5259c0f
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 125 deletions.
2 changes: 1 addition & 1 deletion compiler/cpp/code.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
#include <stdexcept>
#include <forward_list>

#ifndef PROTOGEN_$4$
#ifndef PROTOGEN$4$
#error Missing include of protogen $1$ header
#endif
------
Expand Down
73 changes: 33 additions & 40 deletions compiler/cpp/cppgen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/

#include <algorithm>
#include <unordered_set>
#include <vector>
#include <cmake.hh>
#include <auto-code.hh>
#include <auto-protogen.hh>
Expand Down Expand Up @@ -45,8 +47,6 @@ struct GeneratorContext
bool cpp_enable_errors;
bool cpp_use_lists;
std::string custom_parent;
std::string version;
std::string versionNo;

GeneratorContext( Printer &printer, Proto3 &root ) : printer(printer), root(root),
number_names(false), obfuscate_strings(false),
Expand Down Expand Up @@ -115,15 +115,19 @@ static std::string nativeType( const Field &field )
return "uint8_t";
else
if (field.type.id == protogen::TYPE_MESSAGE)
{
if (field.type.ref == nullptr)
throw protogen::exception("Message type reference is null");
return nativePackage(field.type.ref->package) + "::" + field.type.ref->name;
}
else
throw protogen::exception("Invalid field type");
}

/**
* Translates protobuf3 types to C++ types.
*/
static std::string fieldNativeType( GeneratorContext &ctx, const Field &field, bool useLists )
static std::string fieldNativeType( const Field &field, bool useLists )
{
std::string valueType;

Expand Down Expand Up @@ -156,8 +160,8 @@ static std::string fieldNativeType( GeneratorContext &ctx, const Field &field, b
return valueType;
else
{
std::string output = "protogen_";
output += ctx.version;
std::string output = "protogen";
output += PROTOGEN_VERSION_NAMING;
output += "::field<";
output += valueType;
output += '>';
Expand Down Expand Up @@ -194,7 +198,7 @@ static void generateModel( GeneratorContext &ctx, const Message &message )
ctx.printer("\tstruct $1$_type\n\t{\n", message.name);
for (auto field : message.fields)
{
ctx.printer("\t\t$1$ $2$;\n", fieldNativeType(ctx, field, ctx.cpp_use_lists), fieldStorage(field) );
ctx.printer("\t\t$1$ $2$;\n", fieldNativeType(field, ctx.cpp_use_lists), fieldStorage(field) );
}
ctx.printer("\t};\n");

Expand Down Expand Up @@ -321,46 +325,43 @@ static std::string makeGuard( const std::string &fileName )
return out;
}

typedef std::vector<protogen::Message *> MessageList;
typedef std::vector<std::shared_ptr<protogen::Message>> MessageList;
typedef std::unordered_set<std::shared_ptr<protogen::Message>> MessageSet;

static bool contains( const MessageList &items, const protogen::Message *message )
static bool contains( const MessageList &items, const std::shared_ptr<protogen::Message> &message )
{
for (auto mi = items.begin(); mi != items.end(); ++mi)
if (*mi == message) return true;
for (const auto &current : items)
if (current == message)
return true;
return false;
}


static void sort( MessageList &items, MessageList &pending, protogen::Message *message )
static void sort( MessageList &output, MessageSet &pending, std::shared_ptr<protogen::Message> message )
{
if (contains(pending, message)) return; // circular reference
if (contains(items, message)) return; // already processed
if (pending.count(message) > 0)
throw exception("circular reference with '" + message->name + "'");
if (contains(output, message))
return; // already processed

pending.push_back(message);

for (auto fi = message->fields.begin(); fi != message->fields.end(); ++fi)
pending.insert(message);
for (auto &field : message->fields)
{
if (fi->type.ref == nullptr) continue;
if (!contains(items, fi->type.ref)) sort(items, pending, fi->type.ref);
if (field.type.ref != nullptr && !contains(output, field.type.ref))
sort(output, pending, field.type.ref);
}
pending.erase(message);

items.push_back(message);

auto it = std::find(pending.begin(), pending.end(), message);
if (it != pending.end()) pending.erase(it);
output.push_back(message);
}


static void sort( GeneratorContext &ctx )
{
std::vector<protogen::Message *> items;
std::vector<protogen::Message *> pending;
for (auto mi = ctx.root.messages.begin(); mi != ctx.root.messages.end(); ++mi)
{
sort(items, pending, *mi);
}
std::vector<std::shared_ptr<protogen::Message>> messages;
std::unordered_set<std::shared_ptr<protogen::Message>> pending;
for (auto &message : ctx.root.messages)
sort(messages, pending, message);

ctx.root.messages.swap(items);
ctx.root.messages.swap(messages);
}

static void generateInclusions( GeneratorContext &ctx )
Expand All @@ -371,16 +372,8 @@ static void generateInclusions( GeneratorContext &ctx )

static void generateModel( GeneratorContext &ctx )
{
char version[12] = { 0 };
SNPRINTF(version, sizeof(version) - 1, "%02X%02X%02X",
(int) PROTOGEN_MAJOR, (int) PROTOGEN_MINOR, (int) PROTOGEN_PATCH);
ctx.versionNo = version;
SNPRINTF(version, sizeof(version) - 1, "%d_%d_%d",
(int) PROTOGEN_MAJOR, (int) PROTOGEN_MINOR, (int) PROTOGEN_PATCH);
ctx.version = version;

std::string guard = makeGuard(ctx.root.fileName);
ctx.printer(CODE_HEADER, PROTOGEN_VERSION, ctx.root.fileName, guard, ctx.version);
ctx.printer(CODE_HEADER, PROTOGEN_VERSION, ctx.root.fileName, guard, PROTOGEN_VERSION_NAMING);

sort(ctx);

Expand Down
2 changes: 1 addition & 1 deletion compiler/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ int main( int argc, char **argv )
protogen::Proto3 proto;
try
{
protogen::Proto3::parse(proto, input, fullPath);
proto.parse(input, fullPath);
protogen::CppGenerator gen;
gen.generate(proto, *output);
} catch (protogen::exception &ex)
Expand Down
56 changes: 21 additions & 35 deletions compiler/proto3.cc
Original file line number Diff line number Diff line change
Expand Up @@ -509,17 +509,6 @@ std::ostream &operator<<( std::ostream &out, protogen::Proto3 &proto );

namespace protogen {


TypeInfo::TypeInfo() : id(TYPE_DOUBLE), ref(nullptr), repeated(false)
{
}


Field::Field() : index(0)
{
}


std::string Message::qualifiedName() const
{
if (package.empty()) return name;
Expand Down Expand Up @@ -593,7 +582,7 @@ static void parseStandardOption( ProtoContext &ctx, OptionMap &entries )
}


static Message *findMessage( ProtoContext &ctx, const std::string &name )
static std::shared_ptr<Message> findMessage( ProtoContext &ctx, const std::string &name )
{
for (auto it = ctx.tree.messages.begin(); it != ctx.tree.messages.end(); ++it)
if ((*it)->qualifiedName() == name) return *it;
Expand Down Expand Up @@ -650,13 +639,19 @@ static void parseField( ProtoContext &ctx, Message &message )
throw exception("Missing field type", TOKEN_POSITION(ctx.tokens.current));

// name
if (ctx.tokens.next().code != TOKEN_NAME) throw exception("Missing field name", TOKEN_POSITION(ctx.tokens.current));
if (ctx.tokens.next().code != TOKEN_NAME)
throw exception("Missing field name", TOKEN_POSITION(ctx.tokens.current));
field.name = ctx.tokens.current.value;
// equal symbol
if (ctx.tokens.next().code != TOKEN_EQUAL) throw exception("Expected '='", TOKEN_POSITION(ctx.tokens.current));
if (ctx.tokens.next().code != TOKEN_EQUAL)
throw exception("Expected '='", TOKEN_POSITION(ctx.tokens.current));
// index
if (ctx.tokens.next().code != TOKEN_INTEGER) throw exception("Missing field index", TOKEN_POSITION(ctx.tokens.current));
if (ctx.tokens.next().code != TOKEN_INTEGER)
throw exception("Missing field index", TOKEN_POSITION(ctx.tokens.current));
field.index = (int) strtol(ctx.tokens.current.value.c_str(), nullptr, 10);
// https://protobuf.dev/programming-guides/proto3/#assigning
if (field.index <= 0 || field.index >= 0x1FFFFFFF || field.index == 0x4E1F || field.index == 0x4A38)
throw exception("Invalid field index", TOKEN_POSITION(ctx.tokens.current));

ctx.tokens.next();

Expand Down Expand Up @@ -710,10 +705,7 @@ static void parseMessage( ProtoContext &ctx )
{
if (ctx.tokens.current.code == TOKEN_MESSAGE && ctx.tokens.next().code == TOKEN_NAME)
{
Message *message = new(std::nothrow) Message();
if (message == nullptr)
throw exception("Out of memory");
//splitPackage(message.package, ctx.package);
auto message = std::make_shared<Message>();
message->package = ctx.package;
message->name = ctx.tokens.current.value;
if (ctx.tokens.next().code != TOKEN_BEGIN)
Expand Down Expand Up @@ -790,14 +782,7 @@ static void parseProto( ProtoContext &ctx )
} while (ctx.tokens.current.code != 0);
}


Proto3::~Proto3()
{
for (auto it = messages.begin(); it != messages.end(); ++it) delete *it;
}


void Proto3::parse( Proto3 &tree, std::istream &input, const std::string &fileName )
void Proto3::parse( std::istream &input, const std::string &fileName )
{
std::ios_base::fmtflags flags = input.flags();
std::noskipws(input);
Expand All @@ -807,8 +792,8 @@ void Proto3::parse( Proto3 &tree, std::istream &input, const std::string &fileNa
InputStream< std::istream_iterator<char> > is(begin, end);
Tokenizer< std::istream_iterator<char> > tok(is);

ProtoContext ctx(tok, tree, is);
tree.fileName = fileName;
ProtoContext ctx(tok, *this, is);
this->fileName = fileName;

try
{
Expand All @@ -821,15 +806,16 @@ void Proto3::parse( Proto3 &tree, std::istream &input, const std::string &fileNa
}

// check if we have unresolved types
for (auto mit = tree.messages.begin(); mit != tree.messages.end(); ++mit)
for (auto &message : this->messages)
{
for (auto fit = (*mit)->fields.begin(); fit != (*mit)->fields.end(); ++fit)
for (auto &field : message->fields)
{
if (fit->type.ref != nullptr || fit->type.id != TYPE_MESSAGE) continue;
if (field.type.id != TYPE_MESSAGE || field.type.ref != nullptr)
continue;

fit->type.ref = findMessage(ctx, fit->type.qname);
if (fit->type.ref == nullptr)
throw exception("Unable to find message '" + fit->type.qname + "'");
field.type.ref = findMessage(ctx, field.type.qname);
if (field.type.ref == nullptr)
throw exception("Unable to find message '" + field.type.qname + "'");
}
}
}
Expand Down
Loading

0 comments on commit 5259c0f

Please sign in to comment.