Skip to content

Commit

Permalink
reduce string construction
Browse files Browse the repository at this point in the history
Squash 41fdc3a (cp 39db917), 4b4813e (cp f968c5b), 1d34eba
* get_trim_line() only as needed; remember it
* std::string fields
* Nix orig_line; use intact lines[l]
* Fix bug that flagged tab delimiters as invalid chars in userlog errors for invalid fields
  • Loading branch information
yakra committed Mar 29, 2024
1 parent 44d62f0 commit f5a4e85
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 78 deletions.
10 changes: 5 additions & 5 deletions siteupdate/cplusplus/classes/Route/Route.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,16 +248,16 @@ void Route::con_mismatch()
(con_route->banner.size() ? con_route->banner : "(blank)"));
}

void Route::mark_label_in_use(char* label)
void Route::mark_label_in_use(std::string& label)
{ unused_alt_labels.erase(label);
labels_in_use.insert(label);
labels_in_use.insert(move(label));
}

void Route::mark_labels_in_use(char* label1, char* label2)
void Route::mark_labels_in_use(std::string& label1, std::string& label2)
{ unused_alt_labels.erase(label1);
unused_alt_labels.erase(label2);
labels_in_use.insert(label1);
labels_in_use.insert(label2);
labels_in_use.insert(move(label1));
labels_in_use.insert(move(label2));
}

// sort routes by most recent update for use at end of user logs
Expand Down
4 changes: 2 additions & 2 deletions siteupdate/cplusplus/classes/Route/Route.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ class Route
//std::string list_line(int, int);
void write_nmp_merged();
void store_traveled_segments(TravelerList*, std::ofstream&, std::string&, unsigned int, unsigned int);
void mark_label_in_use(char*);
void mark_labels_in_use(char*, char*);
void mark_label_in_use(std::string&);
void mark_labels_in_use(std::string&, std::string&);
void con_mismatch();
size_t index();
Waypoint* con_beg();
Expand Down
53 changes: 34 additions & 19 deletions siteupdate/cplusplus/classes/TravelerList/TravelerList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,27 +102,41 @@ TravelerList::TravelerList(std::string& travname, ErrorList* el)

// process lines
for (unsigned int l = 0; l < lines.size()-1; l++)
{ std::string orig_line(lines[l]);
// strip whitespace from beginning
while (lines[l][0] == ' ' || lines[l][0] == '\t') lines[l]++;
{ // strip whitespace from beginning
char *c = lines[l];
while (*c == ' ' || *c == '\t') c++;
char* beg = c;
// ignore whitespace or "comment" lines
if (lines[l][0] == 0 || lines[l][0] == '#')
{ splist << orig_line << endlines[l];
if (*c == 0 || *c == '#')
{ splist << lines[l] << endlines[l];
continue;
}
// strip whitespace from end // first, seek to end of this line from beginning of next
char * endchar = lines[l+1]-2; // -2 skips over the 0 inserted while separating listdata into lines
while (*endchar == 0) endchar--; // skip back more for CRLF cases, and lines followed by blank lines
while (*endchar == ' ' || *endchar == '\t') *endchar-- = 0;
std::string trim_line(lines[l]);
// process fields in line
std::vector<char*> fields;
size_t spn = 0;
for (char* c = lines[l]; *c; c += spn)
{ for (spn = strcspn(c, " \t"); c[spn] == ' ' || c[spn] == '\t'; spn++) c[spn] = 0;
if (*c == '#') break;
else fields.push_back(c);
// split line into fields
std::vector<std::string> fields;
for (size_t spn; *c; c += spn)
{ if (*c == '#') break;
spn = strcspn(c, " \t");
fields.emplace_back(c,spn);
while (c[spn] == ' ' || c[spn] == '\t') spn++;
}
// strip whitespace from end
while ( strchr(" \t", fields.back().back()) ) fields.back().pop_back();

// lambda for whitespace-trimmed .list line used in userlog error reports & warnings
// calculate once, then it's available for re-use
char* trim_line = 0;
auto get_trim_line = [&]()
{ if (!trim_line)
{ char* end = lines[l+1]-2; // -2 skips over 0 inserted while separating listdata into lines
while (*end == 0) end--; // skip back more for CRLF cases & lines followed by blank lines
while (*end == ' ' || *end == '\t') end--; // strip whitespace @ end
size_t size = end-beg+1; // +1 because end points to final good char
trim_line = (char*)malloc(size+1); // +1 because need room for null terminator
strncpy(trim_line, beg, size);
trim_line[size] = 0;
}
return trim_line;
};
#define UPDATE_NOTE(R) if (R->last_update) \
{ updated_routes.insert(R); \
log << " Route updated " << R->last_update[0] << ": " << R->readable_name() << '\n'; \
Expand All @@ -136,10 +150,11 @@ TravelerList::TravelerList(std::string& travname, ErrorList* el)
#include "mark_connected_route_segments.cpp"
}
else { log << "Incorrect format line (4 or 6 fields expected, found "
<< fields.size() << "): " << trim_line << '\n';
splist << orig_line << endlines[l];
<< fields.size() << "): " << get_trim_line() << '\n';
splist << lines[l] << endlines[l];
}
#undef UPDATE_NOTE
free(trim_line);
}
delete[] listdata;
log << "Processed " << list_entries << " good lines marking " << clinched_segments.size() << " segments traveled.\n";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// find the route that matches and when we do, match labels
std::string lookup = std::string(fields[0]) + ' ' + fields[1];
std::string lookup = fields[0] + ' ' + fields[1];
upper(lookup.data());
// look for region/route combo, first in pri_list_hash
std::unordered_map<std::string,Route*>::iterator rit = Route::pri_list_hash.find(lookup);
Expand All @@ -8,34 +8,36 @@ if (rit == Route::pri_list_hash.end())
{ rit = Route::alt_list_hash.find(lookup);
if (rit == Route::alt_list_hash.end())
{ bool invalid_char = 0;
for (char& c : trim_line)
if (iscntrl(c))
{ c = '?';
for (char* c = get_trim_line(); *c; c++)
if (iscntrl(*c) && *c != '\t')
{ *c = '?';
invalid_char = 1;
}
log << "Unknown region/highway combo in line: " << trim_line;
if (invalid_char) log << " [contains invalid character(s)]";
log << '\n';
splist << orig_line << endlines[l];
splist << lines[l] << endlines[l];
free(trim_line);
continue;
}
else log << "Note: deprecated route name " << fields[1]
<< " -> canonical name " << rit->second->list_entry_name() << " in line: " << trim_line << '\n';
<< " -> canonical name " << rit->second->list_entry_name() << " in line: " << get_trim_line() << '\n';
}
Route* r = rit->second;
if (r->system->devel())
{ log << "Ignoring line matching highway in system in development: " << trim_line << '\n';
splist << orig_line << endlines[l];
{ log << "Ignoring line matching highway in system in development: " << get_trim_line() << '\n';
splist << lines[l] << endlines[l];
free(trim_line);
continue;
}
// r is a route match, and we need to find
// waypoint indices, ignoring case and leading
// '+' or '*' when matching
unsigned int index1, index2;
while (*fields[2] == '*' || *fields[2] == '+') fields[2]++;
while (*fields[3] == '*' || *fields[3] == '+') fields[3]++;
upper(fields[2]);
upper(fields[3]);
while (fields[2][0] == '*' || fields[2][0] == '+') fields[2].assign(fields[2].data()+1);
while (fields[3][0] == '*' || fields[3][0] == '+') fields[3].assign(fields[3].data()+1);
upper(fields[2].data());
upper(fields[3].data());
// look for point indices for labels, first in pri_label_hash
std::unordered_map<std::string,unsigned int>::iterator lit1 = r->pri_label_hash.find(fields[2]);
std::unordered_map<std::string,unsigned int>::iterator lit2 = r->pri_label_hash.find(fields[3]);
Expand All @@ -45,13 +47,13 @@ if (lit2 == r->pri_label_hash.end()) lit2 = r->alt_label_hash.find(fields[3]);
// if we did not find matches for both labels...
if (lit1 == r->alt_label_hash.end() || lit2 == r->alt_label_hash.end())
{ bool invalid_char = 0;
for (char& c : trim_line)
if (iscntrl(c))
{ c = '?';
for (char* c = get_trim_line(); *c; c++)
if (iscntrl(*c) && *c != '\t')
{ *c = '?';
invalid_char = 1;
}
for (char* c = fields[2]; *c; c++) if (iscntrl(*c)) *c = '?';
for (char* c = fields[3]; *c; c++) if (iscntrl(*c)) *c = '?';
for (char& c : fields[2]) if (iscntrl(c)) c = '?';
for (char& c : fields[3]) if (iscntrl(c)) c = '?';
if (lit1 == lit2)
log << "Waypoint labels " << fields[2] << " and " << fields[3] << " not found in line: " << trim_line;
else { log << "Waypoint label ";
Expand All @@ -60,8 +62,9 @@ if (lit1 == r->alt_label_hash.end() || lit2 == r->alt_label_hash.end())
}
if (invalid_char) log << " [contains invalid character(s)]";
log << '\n';
splist << orig_line << endlines[l];
splist << lines[l] << endlines[l];
UPDATE_NOTE(r)
free(trim_line);
continue;
}
// are either of the labels used duplicates?
Expand All @@ -75,19 +78,20 @@ if (r->duplicate_labels.count(fields[3]))
duplicate = 1;
}
if (duplicate)
{ splist << orig_line << endlines[l];
{ splist << lines[l] << endlines[l];
log << " Please report this error in the Travel Mapping forum.\n Unable to parse line: "
<< trim_line << '\n';
<< get_trim_line() << '\n';
r->system->mark_route_in_use(lookup);
r->mtx.lock();
r->mark_labels_in_use(fields[2], fields[3]);
r->mtx.unlock();
free(trim_line);
continue;
}
// if both labels reference the same waypoint...
if (lit1->second == lit2->second)
{ log << "Equivalent waypoint labels mark zero distance traveled in line: " << trim_line << '\n';
splist << orig_line << endlines[l];
{ log << "Equivalent waypoint labels mark zero distance traveled in line: " << get_trim_line() << '\n';
splist << lines[l] << endlines[l];
UPDATE_NOTE(r)
}
// otherwise both labels are valid; mark in use & proceed
Expand Down Expand Up @@ -116,5 +120,5 @@ else { list_entries++;
#undef r1
#undef r2
}
else splist << orig_line << endlines[l];
else splist << lines[l] << endlines[l];
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
std::string lookup1 = std::string(fields[0]) + ' ' + fields[1];
std::string lookup2 = std::string(fields[3]) + ' ' + fields[4];
std::string lookup1 = fields[0] + ' ' + fields[1];
std::string lookup2 = fields[3] + ' ' + fields[4];
upper(lookup1.data());
upper(lookup2.data());
// look for region/route combos, first in pri_list_hash
Expand All @@ -10,19 +10,19 @@ if (rit1 == Route::pri_list_hash.end())
{ rit1 = Route::alt_list_hash.find(lookup1);
if (rit1 != Route::alt_list_hash.end())
log << "Note: deprecated route name \"" << fields[0] << ' ' << fields[1]
<< "\" -> canonical name \"" << rit1->second->readable_name() << "\" in line: " << trim_line << '\n';
<< "\" -> canonical name \"" << rit1->second->readable_name() << "\" in line: " << get_trim_line() << '\n';
}
if (rit2 == Route::pri_list_hash.end())
{ rit2 = Route::alt_list_hash.find(lookup2);
if (rit2 != Route::alt_list_hash.end())
log << "Note: deprecated route name \"" << fields[3] << ' ' << fields[4]
<< "\" -> canonical name \"" << rit2->second->readable_name() << "\" in line: " << trim_line << '\n';
<< "\" -> canonical name \"" << rit2->second->readable_name() << "\" in line: " << get_trim_line() << '\n';
}
if (rit1 == Route::alt_list_hash.end() || rit2 == Route::alt_list_hash.end())
{ bool invalid_char = 0;
for (char& c : trim_line)
if (iscntrl(c))
{ c = '?';
for (char* c = get_trim_line(); *c; c++)
if (iscntrl(*c) && *c != '\t')
{ *c = '?';
invalid_char = 1;
}
for (char& c : lookup1) if (iscntrl(c)) c = '?';
Expand All @@ -35,30 +35,33 @@ if (rit1 == Route::alt_list_hash.end() || rit2 == Route::alt_list_hash.end())
}
if (invalid_char) log << " [contains invalid character(s)]";
log << '\n';
splist << orig_line << endlines[l];
splist << lines[l] << endlines[l];
free(trim_line);
continue;
}
Route* r1 = rit1->second;
Route* r2 = rit2->second;
if (r1->con_route != r2->con_route)
{ log << lookup1 << " and " << lookup2 << " not in same connected route in line: " << trim_line << '\n';
splist << orig_line << endlines[l];
{ log << lookup1 << " and " << lookup2 << " not in same connected route in line: " << get_trim_line() << '\n';
splist << lines[l] << endlines[l];
UPDATE_NOTE(r1->con_route->roots.front()) if (r1->con_route->roots.size() > 1) UPDATE_NOTE(r1->con_route->roots.back())
UPDATE_NOTE(r2->con_route->roots.front()) if (r2->con_route->roots.size() > 1) UPDATE_NOTE(r2->con_route->roots.back())
free(trim_line);
continue;
}
if (r1->system->devel())
{ log << "Ignoring line matching highway in system in development: " << trim_line << '\n';
splist << orig_line << endlines[l];
{ log << "Ignoring line matching highway in system in development: " << get_trim_line() << '\n';
splist << lines[l] << endlines[l];
free(trim_line);
continue;
}
// r1 and r2 are route matches, and we need to find
// waypoint indices, ignoring case and leading
// '+' or '*' when matching
while (*fields[2] == '*' || *fields[2] == '+') fields[2]++;
while (*fields[5] == '*' || *fields[5] == '+') fields[5]++;
upper(fields[2]);
upper(fields[5]);
while (fields[2][0] == '*' || fields[2][0] == '+') fields[2].assign(fields[2].data()+1);
while (fields[5][0] == '*' || fields[5][0] == '+') fields[5].assign(fields[5].data()+1);
upper(fields[2].data());
upper(fields[5].data());
// look for point indices for labels, first in pri_label_hash
std::unordered_map<std::string,unsigned int>::iterator lit1 = r1->pri_label_hash.find(fields[2]);
std::unordered_map<std::string,unsigned int>::iterator lit2 = r2->pri_label_hash.find(fields[5]);
Expand All @@ -68,13 +71,13 @@ if (lit2 == r2->pri_label_hash.end()) lit2 = r2->alt_label_hash.find(fields[5]);
// if we did not find matches for both labels...
if (lit1 == r1->alt_label_hash.end() || lit2 == r2->alt_label_hash.end())
{ bool invalid_char = 0;
for (char& c : trim_line)
if (iscntrl(c))
{ c = '?';
for (char* c = get_trim_line(); *c; c++)
if (iscntrl(*c) && *c != '\t')
{ *c = '?';
invalid_char = 1;
}
for (char* c = fields[2]; *c; c++) if (iscntrl(*c)) *c = '?';
for (char* c = fields[5]; *c; c++) if (iscntrl(*c)) *c = '?';
for (char& c : fields[2]) if (iscntrl(c)) c = '?';
for (char& c : fields[5]) if (iscntrl(c)) c = '?';
if (lit1 == r1->alt_label_hash.end() && lit2 == r2->alt_label_hash.end())
log << "Waypoint labels " << fields[2] << " and " << fields[5] << " not found in line: " << trim_line;
else { log << "Waypoint ";
Expand All @@ -85,9 +88,10 @@ if (lit1 == r1->alt_label_hash.end() || lit2 == r2->alt_label_hash.end())
}
if (invalid_char) log << " [contains invalid character(s)]";
log << '\n';
splist << orig_line << endlines[l];
splist << lines[l] << endlines[l];
if (lit1 == r1->alt_label_hash.end() && lit1 != lit2) UPDATE_NOTE(r1)
if (lit2 == r2->alt_label_hash.end()) /*^diff rtes^*/ UPDATE_NOTE(r2)
free(trim_line);
continue;
}
// are either of the labels used duplicates?
Expand All @@ -101,12 +105,13 @@ if (r2->duplicate_labels.count(fields[5]))
duplicate = 1;
}
if (duplicate)
{ splist << orig_line << endlines[l];
{ splist << lines[l] << endlines[l];
log << " Please report this error in the Travel Mapping forum.\n"
<< " Unable to parse line: " << trim_line << '\n';
<< " Unable to parse line: " << get_trim_line() << '\n';
r1->system->mark_routes_in_use(lookup1, lookup2);
r1->mtx.lock(); r1->mark_label_in_use(fields[2]); r1->mtx.unlock();
r2->mtx.lock(); r2->mark_label_in_use(fields[5]); r2->mtx.unlock();
free(trim_line);
continue;
}
bool reverse = 0;
Expand All @@ -116,9 +121,10 @@ unsigned int index2 = lit2->second;
if (r1 == r2)
{ // if both labels reference the same waypoint...
if (index1 == index2)
{ log << "Equivalent waypoint labels mark zero distance traveled in line: " << trim_line << '\n';
splist << orig_line << endlines[l];
{ log << "Equivalent waypoint labels mark zero distance traveled in line: " << get_trim_line() << '\n';
splist << lines[l] << endlines[l];
UPDATE_NOTE(r1)
free(trim_line);
continue;
}
r1->mtx.lock();
Expand All @@ -138,7 +144,7 @@ else { // user log warning for DISCONNECTED_ROUTE errors
log << r->code << (r == regions.back() ? ':' : '/');
log << " DISCONNECTED_ROUTE error in " << r1->con_route->readable_name()
<< ".\n Please report this error in the Travel Mapping forum"
<< ".\n Travels may potentially be shown incorrectly for line: " << trim_line << '\n';
<< ".\n Travels may potentially be shown incorrectly for line: " << get_trim_line() << '\n';
}
// Is .list entry forward or backward?
if (r1->rootOrder > r2->rootOrder)
Expand Down Expand Up @@ -179,4 +185,4 @@ if (Args::splitregion == r1->region->code || Args::splitregion == r2->region->co
{
#include "splitregion.cpp"
}
else splist << orig_line << endlines[l];
else splist << lines[l] << endlines[l];
2 changes: 1 addition & 1 deletion siteupdate/cplusplus/classes/TravelerList/splitregion.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Waypoint *w1, *w2;
// comment out original line and indent new line below
splist << "##### " << orig_line << newline << " ";
splist << "##### " << lines[l] << newline << " ";

// 1st waypoint
if (Args::splitregion != r1->region->code)
Expand Down

0 comments on commit f5a4e85

Please sign in to comment.