summaryrefslogtreecommitdiffstats
path: root/src/table_handler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/table_handler.cpp')
-rw-r--r--src/table_handler.cpp141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/table_handler.cpp b/src/table_handler.cpp
new file mode 100644
index 0000000..7d3c185
--- /dev/null
+++ b/src/table_handler.cpp
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "table_handler.hpp"
+
+namespace ixion {
+
+table_handler::entry::entry() :
+ name(empty_string_id), range(abs_range_t::invalid), totals_row_count(0) {}
+
+table_handler::~table_handler() {}
+
+abs_range_t table_handler::get_range(
+ const abs_address_t& pos, string_id_t column_first, string_id_t column_last,
+ table_areas_t areas) const
+{
+ entries_type::const_iterator it = m_entries.begin(), it_end = m_entries.end();
+ for (; it != it_end; ++it)
+ {
+ const entry& e = *it->second;
+ if (!e.range.contains(pos))
+ continue;
+
+ return get_column_range(e, column_first, column_last, areas);
+ }
+
+ return abs_range_t(abs_range_t::invalid);
+}
+
+abs_range_t table_handler::get_range(
+ string_id_t table, string_id_t column_first, string_id_t column_last,
+ table_areas_t areas) const
+{
+ entries_type::const_iterator it = m_entries.find(table);
+ if (it == m_entries.end())
+ // Table name not found.
+ return abs_range_t(abs_range_t::invalid);
+
+ const entry& e = *it->second;
+ return get_column_range(e, column_first, column_last, areas);
+}
+
+void table_handler::insert(std::unique_ptr<entry>& p)
+{
+ if (!p)
+ return;
+
+ string_id_t name = p->name;
+ m_entries.insert(
+ entries_type::value_type(
+ name, std::unique_ptr<entry>(p.release())));
+}
+
+void adjust_table_area(abs_range_t& range, const table_handler::entry& e, table_areas_t areas)
+{
+ bool headers = (areas & table_area_headers);
+ bool data = (areas & table_area_data);
+ bool totals = (areas & table_area_totals);
+
+ if (headers)
+ {
+ if (data)
+ {
+ if (totals)
+ {
+ // All areas.
+ return;
+ }
+
+ // Headers + data areas
+ range.last.row -= e.totals_row_count;
+ return;
+ }
+
+ // Headers only.
+ range.last.row = range.first.row;
+ return;
+ }
+
+ // No header row.
+ --range.first.row;
+
+ if (data)
+ {
+ if (totals)
+ {
+ // Data + totals areas
+ return;
+ }
+
+ // Data area only.
+ range.last.row -= e.totals_row_count;
+ return;
+ }
+
+ // Totals area only.
+ if (e.totals_row_count <= 0)
+ {
+ range = abs_range_t(abs_range_t::invalid);
+ return;
+ }
+
+ range.first.row = range.last.row;
+ range.first.row -= e.totals_row_count - 1;
+}
+
+abs_range_t table_handler::get_column_range(
+ const entry& e, string_id_t column_first, string_id_t column_last, table_areas_t areas) const
+{
+ if (column_first == empty_string_id)
+ {
+ // Area specifiers only.
+ abs_range_t ret = e.range;
+ adjust_table_area(ret, e, areas);
+ return ret;
+ }
+
+ for (size_t i = 0, n = e.columns.size(); i < n; ++i)
+ {
+ if (e.columns[i] == column_first)
+ {
+ // Matching column name found.
+ abs_range_t ret = e.range;
+ col_t col = e.range.first.column + i;
+ ret.first.column = col;
+ ret.last.column = col;
+ adjust_table_area(ret, e, areas);
+ return ret;
+ }
+ }
+
+ return abs_range_t(abs_range_t::invalid);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */