Commit a8454be0 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

linechart: implement csv data source

parent e3ea986b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -83,5 +83,6 @@ foreach(spec_test_path ${spec_test_files})
  get_filename_component(spec_test_srcdir ${spec_test_path} DIRECTORY)
  add_test(
      NAME ${spec_test_name}
      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
      COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_runner.sh ${CMAKE_CURRENT_BINARY_DIR}/plotfx ${spec_test_path} ${CMAKE_CURRENT_BINARY_DIR}/${spec_test_name}.png ${spec_test_srcdir}/${spec_test_name}.png)
endforeach()
+108 −1
Original line number Diff line number Diff line
@@ -28,11 +28,108 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "config_helpers.h"
#include "utils/fileutil.h"
#include "utils/csv.h"
#include <iostream>

namespace plotfx {

ReturnCode parseDataSeries(

ReturnCode parse_classlike(
    const plist::Property& prop,
    const std::string& fn,
    std::vector<std::string>* args) {
  if (prop.size() < 3) {
    return ERROR_INVALID_ARGUMENT;
  }

  if (!prop[0].is_literal || prop[0].data != fn) {
    return ERROR_INVALID_ARGUMENT;
  }

  if (!prop[1].is_literal || prop[1].data != "(") {
    return ERROR_INVALID_ARGUMENT;
  }

  size_t argidx = 2;
  for (; argidx < prop.size() - 1; ++argidx) {
    if (prop[argidx].is_literal && prop[argidx].data == ",") {
      continue;
    }

    if (prop[argidx].is_literal && prop[argidx].data == ")") {
      break;
    }

    args->emplace_back(prop[argidx].data);
    continue;
  }

  if (argidx >= prop.size()) {
    return ERROR_INVALID_ARGUMENT;
  }

  if (!prop[argidx].is_literal || prop[argidx].data != ")") {
    return ERROR_INVALID_ARGUMENT;
  }

  return OK;
}

ReturnCode parse_data_series_csv(
    const plist::Property& prop ,
    std::vector<double>* data) {
  std::vector<std::string> args;
  if (auto rc = parse_classlike(prop, "csv", &args); !rc) {
    return rc;
  }

  if (args.size() < 2) {
    return ERROR_INVALID_ARGUMENT; // FIXME
  }

  const auto& csv_path = args[0];
  const auto& csv_column = args[1];

  size_t csv_column_idx = 0;
  try {
    csv_column_idx = std::stoul(csv_column);
  } catch (... ) {
    return ERROR_INVALID_ARGUMENT; // FIXME
  }

  auto csv_data_str = FileUtil::read(csv_path).toString();
  auto csv_data = CSVData{};
  auto csv_opts = CSVParserConfig{};

  for (size_t i = 2; i < args.size(); ++i) {
    if (args[i] == "noheaders") {
      csv_opts.headers = false;
      continue;
    }
  }

  if (auto rc = parseCSV(csv_data_str, csv_opts, &csv_data); !rc) {
    return rc;
  }

  for (const auto& row : csv_data) {
    if (row.size() > csv_column_idx) {
      double value;
      try {
        value = std::stod(row[csv_column_idx]);
      } catch (... ) {
        return ERROR_INVALID_ARGUMENT; // FIXME
      }

      data->emplace_back(value);
    }
  }

  return OK;
}

ReturnCode parse_data_series_inline(
    const plist::Property& prop ,
    std::vector<double>* data) {
  for (const auto& v : prop.values) {
@@ -49,6 +146,16 @@ ReturnCode parseDataSeries(
  return OK;
}

ReturnCode parseDataSeries(
    const plist::Property& prop,
    std::vector<double>* data) {
  if (prop.size() > 0 && prop[0].is_literal && prop[0].data == "csv") {
    return parse_data_series_csv(prop, data);
  }

  return parse_data_series_inline(prop, data);
}

ReturnCode parseMeasureProp(
    const plist::Property& prop,
    Measure* value) {
+1 −1
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ int main(int argc, const char** argv) {
    return EXIT_FAILURE;
  }

  Layer frame{1200, 800};
  Layer frame{1200, 600};
  frame.clear(Colour{1, 1, 1, 1});
  if (auto rc = renderElements(elems, &frame); !rc.isSuccess()) {
    printError(rc);
+2 −2
Original line number Diff line number Diff line
@@ -43,9 +43,9 @@ namespace plot {
PlotConfig::PlotConfig() :
    margins({
        Measure(Unit::REM, 4.0f),
        Measure(Unit::REM, 5.0f),
        Measure(Unit::REM, 4.0f),
        Measure(Unit::REM, 4.0f),
        Measure(Unit::REM, 4.0f)}) {
        Measure(Unit::REM, 5.0f)}) {
  domain_y.padding = 0.1f;
}

+1 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ ReturnCode draw_lines(
  const auto& domain_x = plot.domain_x;
  const auto& domain_y = plot.domain_y;


  if (series.xs.size() != series.ys.size()) {
    // FIXME error msg
    return ERROR_INVALID_ARGUMENT;
Loading