Skip to content

Commit

Permalink
splitting up encoding decoding logic
Browse files Browse the repository at this point in the history
seperating the protobin and xml encoding decoding will make it easier to maintain them
  • Loading branch information
AsherGlick committed Sep 21, 2023
1 parent c0c8b44 commit a7ed26b
Show file tree
Hide file tree
Showing 5 changed files with 423 additions and 331 deletions.
201 changes: 201 additions & 0 deletions xml_converter/src/packaging_protobin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
#include "packaging_protobin.hpp"

#include <fstream>
#include <map>
#include <set>
#include <string>
#include <vector>

#include "category_gen.hpp"
#include "parseable.hpp"
#include "string_helper.hpp"
#include "waypoint.pb.h"

using namespace std;

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////// SERIALIZE ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
void parse_waypoint_categories(
string full_category_name,
::waypoint::Category proto_category,
map<string, Category>* marker_categories,
vector<Parseable*>* parsed_pois) {
full_category_name += proto_category.name();
Category* this_category = &(*marker_categories)[full_category_name];
this_category->parse_protobuf(proto_category);

for (int i = 0; i < proto_category.icon_size(); i++) {
Icon* icon = new Icon();
icon->parse_protobuf(proto_category.icon(i));
// TODO: The field category in Icon is being deprciated
// This overwrites any icon.category with its position in the heirarchy
icon->category.category = full_category_name;
parsed_pois->push_back(icon);
}
for (int i = 0; i < proto_category.trail_size(); i++) {
Trail* trail = new Trail();
trail->parse_protobuf(proto_category.trail(i));
// TODO: The field category in Trail is being deprciated
// This overwrites any trail.category with its position in the heirarchy
trail->category.category = full_category_name;
parsed_pois->push_back(trail);
}

for (int i = 0; i < proto_category.children_size(); i++) {
parse_waypoint_categories(full_category_name + ".", proto_category.children(i), &(this_category->children), parsed_pois);
}
}

////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
void read_protobuf_file(string proto_filepath, map<string, Category>* marker_categories, vector<Parseable*>* parsed_pois) {
fstream infile;
waypoint::Waypoint proto_message;

infile.open(proto_filepath, ios::in | ios::binary);
proto_message.ParseFromIstream(&infile);
for (int i = 0; i < proto_message.category_size(); i++) {
parse_waypoint_categories("", proto_message.category(i), marker_categories, parsed_pois);
}
}

////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// DESERIALIZE //////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Adds the name of a category and all of it's parents to a set
// eg.
// {
// "mypath",
// "mypath.easypath",
// "mypath.easypath.trail",
// "mypath.hardpath",
// "mypath.hardpath.trail",
// }
////////////////////////////////////////////////////////////////////////////////
void populate_categories_to_retain(string category_name, set<string>* categories_to_retain) {
string name;
vector<string> split_categories = split(category_name, ".");
for (unsigned int j = 0; j < split_categories.size(); j++) {
name += split_categories[j];
categories_to_retain->insert(name);
name += ".";
}
}

////////////////////////////////////////////////////////////////////////////////
// Iterates through all children of a Category and removes the categories and
// POIs that do not belong on a particular map
////////////////////////////////////////////////////////////////////////////////
void remove_waypoint_elements(waypoint::Category* proto_category, set<string> categories_to_retain, string parent_name, int map_id) {
int keep = 0;
for (int i = 0; i < proto_category->icon_size(); i++) {
if (proto_category->icon(i).map_id() == map_id) {
if (keep < i) {
proto_category->mutable_icon()->SwapElements(i, keep);
}
++keep;
}
}
proto_category->mutable_icon()->DeleteSubrange(keep, proto_category->icon_size() - keep);

keep = 0;
for (int i = 0; i < proto_category->trail_size(); i++) {
if (proto_category->trail(i).map_id() == map_id) {
if (keep < i) {
proto_category->mutable_trail()->SwapElements(i, keep);
}
++keep;
}
}
proto_category->mutable_trail()->DeleteSubrange(keep, proto_category->trail_size() - keep);

keep = 0;
for (int i = 0; i < proto_category->children_size(); i++) {
string name = parent_name + "." + proto_category->children(i).name();
auto pos = categories_to_retain.find(name);
if (pos != categories_to_retain.end()) {
remove_waypoint_elements(proto_category->mutable_children(i), categories_to_retain, name, map_id);
if (keep < i) {
proto_category->mutable_children()->SwapElements(i, keep);
}
++keep;
}
}
proto_category->mutable_children()->DeleteSubrange(keep, proto_category->children_size() - keep);
}

void write_protobuf_file(string proto_directory, map<string, Category>* marker_categories, vector<Parseable*>* parsed_pois) {
waypoint::Waypoint proto_pois;
// Collects a set of map ids from Icon and Trail data
std::set<int> map_ids;
ofstream trail_data_file;
map<string, vector<Parseable*>> map_of_pois;
for (const auto& parsed_poi : *parsed_pois) {
if (parsed_poi->classname() == "POI") {
Icon* icon = dynamic_cast<Icon*>(parsed_poi);
map_ids.insert(icon->map_id);
map_of_pois[icon->category.category].push_back(icon);
}
else if (parsed_poi->classname() == "Trail") {
Trail* trail = dynamic_cast<Trail*>(parsed_poi);
map_ids.insert(trail->map_id);
map_of_pois[trail->category.category].push_back(trail);
}
}

// Creates a Waypoint message that contains all categories
waypoint::Waypoint all_categories;
for (const auto& category : *marker_categories) {
waypoint::Category proto_category = category.second.as_protobuf("", &map_of_pois);
all_categories.add_category()->CopyFrom(proto_category);
}

waypoint::Waypoint output_message;
std::set<string> categories_to_retain;
for (int map_id : map_ids) {
ofstream outfile;
string output_filepath = proto_directory + "/" + to_string(map_id) + ".data";
outfile.open(output_filepath, ios::out | ios::binary);
output_message.MergeFrom(all_categories);

for (const auto& parsed_poi : *parsed_pois) {
if (parsed_poi->classname() == "POI") {
Icon* icon = dynamic_cast<Icon*>(parsed_poi);
if (icon->map_id == map_id) {
populate_categories_to_retain(icon->category.category, &categories_to_retain);
}
}
else if (parsed_poi->classname() == "Trail") {
Trail* trail = dynamic_cast<Trail*>(parsed_poi);
if (trail->map_id == map_id) {
populate_categories_to_retain(trail->category.category, &categories_to_retain);
}
}
}
// In the XML, MarkerCategories have a tree hierarchy while POIS have a
// flat hierarchy. In Waypoint, POIs are elements of the category they
// belong to. We are removing instead of inserting because
// each parent category contains the data for all of its children. It
// would be impractical to include all of the data from each category
// except for the children and then iterating over all the children.
// This pruning method is slower but ensures that information is kept.
for (int i = 0; i < output_message.category_size(); i++) {
remove_waypoint_elements(output_message.mutable_category(i), categories_to_retain, output_message.category(i).name(), map_id);
if (output_message.mutable_category(i)->children_size() == 0) {
output_message.mutable_category(i)->Clear();
}
}
output_message.SerializeToOstream(&outfile);
outfile.close();
output_message.Clear();
categories_to_retain.clear();
}
}
20 changes: 20 additions & 0 deletions xml_converter/src/packaging_protobin.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include <fstream>
#include <map>
#include <string>
#include <vector>

#include "category_gen.hpp"
#include "parseable.hpp"
#include "waypoint.pb.h"

void read_protobuf_file(
std::string proto_filepath,
std::map<std::string, Category>* marker_categories,
std::vector<Parseable*>* parsed_pois);

void write_protobuf_file(
std::string proto_directory,
std::map<std::string, Category>* marker_categories,
std::vector<Parseable*>* parsed_pois);
Loading

0 comments on commit a7ed26b

Please sign in to comment.