static inline Table* find_table(std::vector<Table*> vec, std::string name)
{
- if(name.empty())
+ if (name.empty())
return nullptr;
for( auto *t : vec)
- if(!name.compare(t->get_name()))
+ if (!name.compare(t->get_name()))
return t;
return nullptr;
for( Option* o : options)
delete o;
+ for( Option* a : append_options)
+ delete a;
+
delete comments;
}
{
Table* t = find_table(tables, table_name);
- if(t)
+ if (t)
return t;
t = new Table(table_name, depth + 1);
return true;
}
+void Table::append_option(std::string opt_name, int value)
+{
+ if (!has_option(opt_name, value))
+ {
+ Option *a = new Option(opt_name, value, 0);
+ append_options.push_back(a);
+ }
+}
+
+void Table::append_option(std::string opt_name, bool value)
+{
+ if (!has_option(opt_name, value))
+ {
+ Option *a = new Option(opt_name, value, 0);
+ append_options.push_back(a);
+ }
+}
+
+void Table::append_option(std::string opt_name, std::string value)
+{
+ if (!has_option(opt_name, value))
+ {
+ Option *a = new Option(opt_name, value, 0);
+ append_options.push_back(a);
+ }
+}
bool Table::add_list(std::string list_name, std::string next_elem)
{
for (auto l : lists)
- if(l->get_name() == list_name)
+ if (l->get_name() == list_name)
return l->add_value(next_elem);
Variable *var = new Variable(list_name, depth + 1);
if (!opt_name.compare(o->get_name()))
return true;
+ for (Option* a : append_options)
+ if (!opt_name.compare(a->get_name()))
+ return true;
+
return false;
}
if ( (*o) == opt)
return true;
+ for (Option* a : append_options)
+ if ( (*a) == opt)
+ return true;
+
return false;
}
for(int i = 0; i < t.depth; i++)
whitespace += " ";
- if(!t.name.empty())
+ if (!t.name.empty())
out << whitespace << t.name << " =" << std::endl;
out << whitespace << '{' << std::endl;
out << (*sub_t) << ",\n";
}
+ out << whitespace << "}";
+
+ // Now, print all options which need to be appended/overwrite earlier options
+ if (!t.append_options.empty())
+ {
+ out << "\n";
+
+ for (Option* a : t.append_options)
+ out << (*a) << "\n";
+ }
- // don't add a comma if the depth is zero
- if(t.depth == 0)
- out << "}";
- else
- out << whitespace << "}";
-
return out;
}
void add_comment(std::string comment);
bool has_option(const std::string);
+ /* emit options after table has finished printing. */
+ /* These options will be appended to the previous table as supposed */
+ /* to overwriting the entire table */
+ void append_option(std::string opt_name, int val);
+ void append_option(std::string opt_name, bool val);
+ void append_option(std::string opt_name, std::string val);
+
friend std::ostream &operator<<( std::ostream&, const Table &);
private:
std::vector<Table*> tables;
std::vector<Option*> options;
std::vector<Variable*> lists;
+ std::vector<Option*> append_options;
bool has_option(std::string name, int val);
{
std::stack<Table*> empty;
open_tables.swap(empty);
+ std::stack<unsigned> empty_two;
+ top_level_tables.swap(empty_two);
curr_data_bad = false;
}
}
open_tables.push(t);
+
+ // ignore the initial table
+ if(open_tables.size() > 1)
+ top_level_tables.push(open_tables.size());
}
void TableApi::open_table(std::string table_name)
if (open_tables.size() == 0)
DataApi::developer_error("No open tables to close!!");
else
+ {
+ if ( !top_level_tables.empty() )
+ if ( open_tables.size() == top_level_tables.top() )
+ top_level_tables.pop();
+
open_tables.pop();
+ }
+
}
bool TableApi::add_option(const std::string name, const char* const v)
{ return add_option(name, std::string(v)); }
+void TableApi::create_append_data(std::string& fqn, Table* &t)
+{
+ unsigned start = 0;
+
+ if (!top_level_tables.empty())
+ start = top_level_tables.top();
+
+ // I need to iterate over the stack of open tables. However,
+ // stack's don't allow iteration without popping. So, rather
+ // than change the underlying stack data structure, I am going
+ // to just copy the entire data structure. Innedficciant, but
+ // not pressed for speed here.
+ std::stack<Table*> copy(open_tables);
+
+ while(!copy.empty() && copy.size() >= start)
+ {
+ fqn = copy.top()->get_name() + "." + fqn;
+ t = copy.top();
+ copy.pop();
+ }
+}
+
+void TableApi::append_option(const std::string option_name, const std::string val)
+{
+ if(open_tables.size() == 0)
+ {
+ DataApi::developer_error("Must open table before adding an option!!: " +
+ option_name + " = " + val);
+ return;
+ }
+
+ Table* t = nullptr;
+ std::string opt_name = option_name;
+ create_append_data(opt_name, t);
+
+ if ( t != nullptr)
+ t->append_option(opt_name, val);
+ else
+ DataApi::developer_error("Snort2lua cannot find a Table to append the option: "
+ + option_name + " = " + val);
+}
+
+void TableApi::append_option(const std::string option_name, const int val)
+{
+ if(open_tables.size() == 0)
+ {
+ DataApi::developer_error("Must open table before adding an option!!: " +
+ option_name + " = " + std::to_string(val));
+ return;
+ }
+
+ Table* t = nullptr;
+ std::string opt_name = option_name;
+ create_append_data(opt_name, t);
+
+ if ( t != nullptr)
+ t->append_option(opt_name, val);
+ else
+ DataApi::developer_error("Snort2lua cannot find a Table to append the option: "
+ + opt_name + " = " + std::to_string(val));
+}
+
+void TableApi::append_option(const std::string option_name, const bool val)
+{
+ if(open_tables.size() == 0)
+ {
+ DataApi::developer_error("Must open table before adding an option!!: " +
+ option_name + " = " + std::to_string(val));
+ return;
+ }
+
+ Table* t = nullptr;
+ std::string opt_name = option_name;
+ create_append_data(opt_name, t);
+
+ if ( t != nullptr)
+ t->append_option(opt_name, val);
+ else
+ DataApi::developer_error("Snort2lua cannot find a Table to append the option: "
+ + opt_name + " = " + std::to_string(val));
+}
+
+void TableApi::append_option(const std::string name, const char* const v)
+{ append_option(name, std::string(v)); }
+
+
bool TableApi::add_list(std::string list_name, std::string next_elem)
{
if(open_tables.size() == 0)
*/
// add an string, bool, or int option to the table. --> table = { name = var |'var'};
-bool add_option(const std::string name, const std::string val);
-bool add_option(const std::string name, const int val);
-bool add_option(const std::string name, const bool val);
-bool add_option(const std::string name, const char* const v);
+bool add_option(const std::string opt_name, const std::string val);
+bool add_option(const std::string opt_name, const int val);
+bool add_option(const std::string opt_name, const bool val);
+bool add_option(const std::string opt_name, const char* const v);
+
+// sometimes, you may need to create a default option, before overwriting that
+// option later. For instance, if you have a default table, and then you
+// need to overwrite a single option in that default table, you can use these
+// methods to overwrite that option.
+void append_option(const std::string opt_name, const std::string val);
+void append_option(const std::string opt_name, const int val);
+void append_option(const std::string opt_name, const bool val);
+void append_option(const std::string opt_name, const char* const v);
+
// add an option with a list of variables --> table = { name = 'elem1 elem2 ...' }
// corresponds to Parameter::PT_MULTI
bool add_list(std::string list_name, std::string next_elem);
// return true if this name exists as an option name for the selected table
bool option_exists(const std::string name);
-
private:
-std::vector<Table*> tables;
+void create_append_data(std::string& fqn, Table* &t);
-// various convenience pointers and holders
+// Data
+std::vector<Table*> tables;
std::stack<Table*> open_tables;
+std::stack<unsigned> top_level_tables;
bool curr_data_bad;
+
+
};