Skip to content
Snippets Groups Projects
Commit 8b33268a authored by Studer Gabriel's avatar Studer Gabriel
Browse files

Bugfix regarding StringRef

StringRefs only contain pointers onto data managed by std::strings.
If those strings are copied or deleted, the StringRefs might point
into nirvana
parent 3a1378c6
No related branches found
No related tags found
No related merge requests found
...@@ -33,7 +33,7 @@ namespace ost { namespace io { ...@@ -33,7 +33,7 @@ namespace ost { namespace io {
StarParser::StarParser(std::istream& stream, bool items_as_row): StarParser::StarParser(std::istream& stream, bool items_as_row):
filename_("<stream>"), line_num_(0), filename_("<stream>"), line_num_(0),
has_current_line_(false), current_line_(), has_current_line_(false), current_line_(),
items_row_header_(), file_open_(true), items_row_columns_(), items_row_header_(), file_open_(true),
items_row_values_() items_row_values_()
{ {
items_as_row_ = items_as_row; items_as_row_ = items_as_row;
...@@ -48,7 +48,7 @@ StarParser::StarParser(std::istream& stream, bool items_as_row): ...@@ -48,7 +48,7 @@ StarParser::StarParser(std::istream& stream, bool items_as_row):
StarParser::StarParser(const String& filename, bool items_as_row): StarParser::StarParser(const String& filename, bool items_as_row):
fstream_(filename.c_str()), filename_(filename), fstream_(filename.c_str()), filename_(filename),
line_num_(0), has_current_line_(false), current_line_(), line_num_(0), has_current_line_(false), current_line_(),
items_row_header_(), file_open_(true), items_row_columns_(), items_row_header_(), file_open_(true),
items_row_values_() items_row_values_()
{ {
items_as_row_=items_as_row; items_as_row_=items_as_row;
...@@ -292,7 +292,6 @@ void StarParser::ParseLoop() ...@@ -292,7 +292,6 @@ void StarParser::ParseLoop()
} }
} }
bool process_rows=this->OnBeginLoop(header); bool process_rows=this->OnBeginLoop(header);
std::vector<StringRef> columns;
std::vector<String> tmp_values; std::vector<String> tmp_values;
// optimized for the common case where all values are present on the same // optimized for the common case where all values are present on the same
// line. // line.
...@@ -310,12 +309,9 @@ void StarParser::ParseLoop() ...@@ -310,12 +309,9 @@ void StarParser::ParseLoop()
if (process_rows) { if (process_rows) {
tmp_values.push_back(String()); tmp_values.push_back(String());
this->ParseMultilineValue(tmp_values.back()); this->ParseMultilineValue(tmp_values.back());
columns.push_back(StringRef(tmp_values.back().data(), if (tmp_values.size()==header.GetSize()) {
tmp_values.back().length()).trim()); this->CallOnDataRow(header, tmp_values);
if (columns.size()==header.GetSize()) {
this->OnDataRow(header, columns);
tmp_values.clear(); tmp_values.clear();
columns.clear();
} }
} else { } else {
String s; String s;
...@@ -334,19 +330,14 @@ void StarParser::ParseLoop() ...@@ -334,19 +330,14 @@ void StarParser::ParseLoop()
} }
default: default:
if (process_rows) { if (process_rows) {
int before=columns.size(); std::vector<StringRef> split_elements;
StarParser::SplitLine(tline, columns, false); StarParser::SplitLine(tline, split_elements);
if (columns.size()==header.GetSize()) { for(uint i = 0; i < split_elements.size(); ++i) {
this->OnDataRow(header, columns); tmp_values.push_back(split_elements[i].str());
}
if (tmp_values.size()==header.GetSize()) {
this->CallOnDataRow(header, tmp_values);
tmp_values.clear(); tmp_values.clear();
columns.clear();
} else {
tmp_values.push_back(tline.str());
const char* d=tmp_values.back().c_str();
for (size_t i=before; i<columns.size(); ++i) {
columns[i]=StringRef(d+(columns[i].begin()-tline.begin()),
columns[i].size());
}
} }
} }
this->ConsumeLine(); this->ConsumeLine();
...@@ -362,11 +353,10 @@ void StarParser::ParseLastDataItemRow() ...@@ -362,11 +353,10 @@ void StarParser::ParseLastDataItemRow()
{ {
if (items_row_header_.GetCategory().size() > 0) { if (items_row_header_.GetCategory().size() > 0) {
if (this->OnBeginLoop(items_row_header_)) { if (this->OnBeginLoop(items_row_header_)) {
this->OnDataRow(items_row_header_, items_row_columns_); this->CallOnDataRow(items_row_header_, items_row_values_);
this->OnEndLoop(); this->OnEndLoop();
} }
items_row_values_.clear(); items_row_values_.clear();
items_row_columns_.clear();
items_row_header_.Clear(); items_row_header_.Clear();
} }
} }
...@@ -385,8 +375,7 @@ void StarParser::ParseDataItemOrRow(StarDataItem& item) ...@@ -385,8 +375,7 @@ void StarParser::ParseDataItemOrRow(StarDataItem& item)
// row // row
items_row_header_.Add(item.GetName()); items_row_header_.Add(item.GetName());
items_row_values_.push_back(item.GetValue().str()); items_row_values_.push_back(item.GetValue().str());
items_row_columns_.push_back(StringRef(items_row_values_.back().data(),
items_row_values_.back().length()).trim());
} else { } else {
this->OnDataItem(item); this->OnDataItem(item);
} }
...@@ -579,4 +568,16 @@ void StarParser::Parse() ...@@ -579,4 +568,16 @@ void StarParser::Parse()
} }
} }
void StarParser::CallOnDataRow(const StarLoopDesc& header,
const std::vector<String>& columns) {
std::vector<StringRef> string_refs;
string_refs.reserve(columns.size());
for(uint i = 0; i < columns.size(); ++i) {
string_refs.push_back(StringRef(columns[i].data(),
columns[i].length()).trim());
}
this->OnDataRow(header, string_refs);
}
}} }}
...@@ -73,6 +73,8 @@ public: ...@@ -73,6 +73,8 @@ public:
category_=category.str(); category_=category.str();
} }
void Add(const StringRef& name) void Add(const StringRef& name)
{ {
index_map_.insert(std::make_pair(name.str(), index_map_.size())); index_map_.insert(std::make_pair(name.str(), index_map_.size()));
...@@ -262,6 +264,15 @@ private: ...@@ -262,6 +264,15 @@ private:
has_current_line_=false; has_current_line_=false;
} }
// the reason for having this function are problems when generating
// StringRefs that contain pointers to strings in a vector.
// When the vector grows, the memory of the strings might get
// reallocated and the StringRefs point into nothing.
// This function Prepares the stringrefs given a constant
// vector and calls OnDataRow to minimize the change in interface.
void CallOnDataRow(const StarLoopDesc& header,
const std::vector<String>& columns);
void ParseDataItemIdent(const StringRef ident, void ParseDataItemIdent(const StringRef ident,
StringRef& cat, StringRef& name); StringRef& cat, StringRef& name);
void ParseGlobal(); void ParseGlobal();
...@@ -278,7 +289,6 @@ private: ...@@ -278,7 +289,6 @@ private:
bool items_as_row_; bool items_as_row_;
StarLoopDesc items_row_header_; StarLoopDesc items_row_header_;
bool file_open_; bool file_open_;
std::vector<StringRef> items_row_columns_;
std::vector<String> items_row_values_; std::vector<String> items_row_values_;
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment