<commit_before>// Author: Enric Tejedor CERN  10/2017

/*************************************************************************
 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

// clang-format off
/** \class ROOT::RDF::RCsvDS
    \ingroup dataframe
    \brief RDataFrame data source class for reading CSV files.

The RCsvDS class implements a CSV file reader for RDataFrame.

A RDataFrame that reads from a CSV file can be constructed using the factory method
ROOT::RDF::MakeCsvDataFrame, which accepts three parameters:
1. Path to the CSV file.
2. Boolean that specifies whether the first row of the CSV file contains headers or
not (optional, default `true`). If `false`, header names will be automatically generated as Col0, Col1, ..., ColN.
3. Delimiter (optional, default ',').

The types of the columns in the CSV file are automatically inferred. The supported
types are:
- Integer: stored as a 64-bit long long int.
- Floating point number: stored with double precision.
- Boolean: matches the literals `true` and `false`.
- String: stored as an std::string, matches anything that does not fall into any of the
previous types.

These are some formatting rules expected by the RCsvDS implementation:
- All records must have the same number of fields, in the same order.
- Any field may be quoted.
~~~
    "1997","Ford","E350"
~~~
- Fields with embedded delimiters (e.g. comma) must be quoted.
~~~
    1997,Ford,E350,"Super, luxurious truck"
~~~
- Fields with double-quote characters must be quoted, and each of the embedded
double-quote characters must be represented by a pair of double-quote characters.
~~~
    1997,Ford,E350,"Super, ""luxurious"" truck"
~~~
- Fields with embedded line breaks are not supported, even when quoted.
~~~
    1997,Ford,E350,"Go get one now
    they are going fast"
~~~
- Spaces are considered part of a field and are not ignored.
~~~
    1997, Ford , E350
    not same as
    1997,Ford,E350
    but same as
    1997, "Ford" , E350
~~~
- If a header row is provided, it must contain column names for each of the fields.
~~~
    Year,Make,Model
    1997,Ford,E350
    2000,Mercury,Cougar
~~~

The current implementation of RCsvDS reads the entire CSV file content into memory before
RDataFrame starts processing it. Therefore, before creating a CSV RDataFrame, it is
important to check both how much memory is available and the size of the CSV file.
*/
// clang-format on

#include <ROOT/RDFUtils.hxx>
#include <ROOT/TSeq.hxx>
#include <ROOT/RCsvDS.hxx>
#include <ROOT/RMakeUnique.hxx>
#include <TError.h>

#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>

namespace ROOT {

namespace RDF {

std::string RCsvDS::AsString()
{
   return "CSV data source";
}

// Regular expressions for type inference
TRegexp RCsvDS::intRegex("^[-+]?[0-9]+$");
TRegexp RCsvDS::doubleRegex1("^[-+]?[0-9]+\\.[0-9]*$");
TRegexp RCsvDS::doubleRegex2("^[-+]?[0-9]*\\.[0-9]+$");
TRegexp RCsvDS::trueRegex("^true$");
TRegexp RCsvDS::falseRegex("^false$");

const std::map<RCsvDS::ColType_t, std::string>
   RCsvDS::fgColTypeMap({{'b', "bool"}, {'d', "double"}, {'l', "Long64_t"}, {'s', "std::string"}});

void RCsvDS::FillHeaders(const std::string &line)
{
   auto columns = ParseColumns(line);
   for (auto &col : columns) {
      fHeaders.emplace_back(col);
   }
}

void RCsvDS::FillRecord(const std::string &line, Record_t &record)
{
   std::istringstream lineStream(line);
   auto i = 0U;

   auto columns = ParseColumns(line);

   for (auto &col : columns) {
      auto colType = fColTypes[fHeaders[i]];

      switch (colType) {
      case 'd': {
         record.emplace_back(new double(std::stod(col)));
         break;
      }
      case 'l': {
         record.emplace_back(new Long64_t(std::stoll(col)));
         break;
      }
      case 'b': {
         auto b = new bool();
         record.emplace_back(b);
         std::istringstream is(col);
         is >> std::boolalpha >> *b;
         break;
      }
      case 's': {
         record.emplace_back(new std::string(col));
         break;
      }
      }
      ++i;
   }
}

void RCsvDS::GenerateHeaders(size_t size)
{
   for (size_t i = 0; i < size; ++i) {
      fHeaders.push_back("Col" + std::to_string(i));
   }
}

std::vector<void *> RCsvDS::GetColumnReadersImpl(std::string_view colName, const std::type_info &ti)
{
   const auto colType = GetType(colName);

   if ((colType == 'd' && typeid(double) != ti) || (colType == 'l' && typeid(Long64_t) != ti) ||
       (colType == 's' && typeid(std::string) != ti) || (colType == 'b' && typeid(bool) != ti)) {
      std::string err = "The type selected for column \"";
      err += colName;
      err += "\" does not correspond to column type, which is ";
      err += fgColTypeMap.at(colType);
      throw std::runtime_error(err);
   }

   const auto &colNames = GetColumnNames();
   const auto index = std::distance(colNames.begin(), std::find(colNames.begin(), colNames.end(), colName));
   std::vector<void *> ret(fNSlots);
   for (auto slot : ROOT::TSeqU(fNSlots)) {
      auto &val = fColAddresses[index][slot];
      if (ti == typeid(double)) {
         val = &fDoubleEvtValues[index][slot];
      } else if (ti == typeid(Long64_t)) {
         val = &fLong64EvtValues[index][slot];
      } else if (ti == typeid(std::string)) {
         val = &fStringEvtValues[index][slot];
      } else {
         val = &fBoolEvtValues[index][slot];
      }
      ret[slot] = &val;
   }
   return ret;
}

void RCsvDS::InferColTypes(std::vector<std::string> &columns)
{
   auto i = 0U;
   for (auto &col : columns) {
      InferType(col, i);
      ++i;
   }
}

void RCsvDS::InferType(const std::string &col, unsigned int idxCol)
{
   ColType_t type;
   int dummy;

   if (intRegex.Index(col, &dummy) != -1) {
      type = 'l'; // Long64_t
   } else if (doubleRegex1.Index(col, &dummy) != -1 || doubleRegex2.Index(col, &dummy) != -1) {
      type = 'd'; // double
   } else if (trueRegex.Index(col, &dummy) != -1 || falseRegex.Index(col, &dummy) != -1) {
      type = 'b'; // bool
   } else {       // everything else is a string
      type = 's'; // std::string
   }
   // TODO: Date

   fColTypes[fHeaders[idxCol]] = type;
   fColTypesList.push_back(type);
}

std::vector<std::string> RCsvDS::ParseColumns(const std::string &line)
{
   std::vector<std::string> columns;

   for (size_t i = 0; i < line.size(); ++i) {
      i = ParseValue(line, columns, i);
   }

   return columns;
}

size_t RCsvDS::ParseValue(const std::string &line, std::vector<std::string> &columns, size_t i)
{
   std::stringstream val;
   bool quoted = false;

   for (; i < line.size(); ++i) {
      if (line[i] == fDelimiter && !quoted) {
         break;
      } else if (line[i] == '"') {
         // Keep just one quote for escaped quotes, none for the normal quotes
         if (line[i + 1] != '"') {
            quoted = !quoted;
         } else {
            val << line[++i];
         }
      } else {
         val << line[i];
      }
   }

   columns.emplace_back(val.str());

   return i;
}

////////////////////////////////////////////////////////////////////////
/// Constructor to create a CSV RDataSource for RDataFrame.
/// \param[in] fileName Path of the CSV file.
/// \param[in] readHeaders `true` if the CSV file contains headers as first row, `false` otherwise
///                        (default `true`).
/// \param[in] delimiter Delimiter character (default ',').
RCsvDS::RCsvDS(std::string_view fileName, bool readHeaders, char delimiter, Long64_t linesChunkSize) // TODO: Let users specify types?
   : fReadHeaders(readHeaders),
     fStream(std::string(fileName)),
     fDelimiter(delimiter),
     fLinesChunkSize(linesChunkSize)
{
   std::string line;

   // Read the headers if present
   if (fReadHeaders) {
      if (std::getline(fStream, line)) {
         FillHeaders(line);
      } else {
         throw std::runtime_error("Error reading headers of CSV file ");
      }
   }

   fDataPos = fStream.tellg();
   if (std::getline(fStream, line)) {
      auto columns = ParseColumns(line);

      // Generate headers if not present
      if (!fReadHeaders) {
         GenerateHeaders(columns.size());
      }

      // Infer types of columns with first record
      InferColTypes(columns);

      // rewind one line
      fStream.seekg(fDataPos);
   }
}

void RCsvDS::FreeRecords()
{
   for (auto &record : fRecords) {
      for (size_t i = 0; i < record.size(); ++i) {
         void *p = record[i];
         const auto colType = fColTypes[fHeaders[i]];
         switch (colType) {
         case 'd': {
            delete static_cast<double *>(p);
            break;
         }
         case 'l': {
            delete static_cast<Long64_t *>(p);
            break;
         }
         case 'b': {
            delete static_cast<bool *>(p);
            break;
         }
         case 's': {
            delete static_cast<std::string *>(p);
            break;
         }
         }
      }
   }
   fRecords.clear();
}

////////////////////////////////////////////////////////////////////////
/// Destructor.
RCsvDS::~RCsvDS()
{
   FreeRecords();
}

void RCsvDS::Finalise()
{
   fStream.clear();
   fStream.seekg(fDataPos);
   fProcessedLines = 0ULL;
   fEntryRangesRequested = 0ULL;
   FreeRecords();
}

const std::vector<std::string> &RCsvDS::GetColumnNames() const
{
   return fHeaders;
}

std::vector<std::pair<ULong64_t, ULong64_t>> RCsvDS::GetEntryRanges()
{

   // Read records and store them in memory
   auto linesToRead = fLinesChunkSize;
   FreeRecords();

   std::string line;
   while ((-1LL == fLinesChunkSize || 0 != linesToRead--) && std::getline(fStream, line)) {
      fRecords.emplace_back();
      FillRecord(line, fRecords.back());
   }

   std::vector<std::pair<ULong64_t, ULong64_t>> entryRanges;
   const auto nRecords = fRecords.size();
   if (0 == nRecords)
      return entryRanges;

   const auto chunkSize = nRecords / fNSlots;
   const auto remainder = 1U == fNSlots ? 0 : nRecords % fNSlots;
   auto start = 0ULL == fEntryRangesRequested ? 0ULL : fProcessedLines;
   auto end = start;

   for (auto i : ROOT::TSeqU(fNSlots)) {
      start = end;
      end += chunkSize;
      entryRanges.emplace_back(start, end);
      (void)i;
   }
   entryRanges.back().second += remainder;

   fProcessedLines += nRecords;
   fEntryRangesRequested++;

   return entryRanges;
}

RCsvDS::ColType_t RCsvDS::GetType(std::string_view colName) const
{
   if (!HasColumn(colName)) {
      std::string msg = "The dataset does not have column ";
      msg += colName;
      throw std::runtime_error(msg);
   }

   return fColTypes.at(colName.data());
}

std::string RCsvDS::GetTypeName(std::string_view colName) const
{
   return fgColTypeMap.at(GetType(colName));
}

bool RCsvDS::HasColumn(std::string_view colName) const
{
   return fHeaders.end() != std::find(fHeaders.begin(), fHeaders.end(), colName);
}

bool RCsvDS::SetEntry(unsigned int slot, ULong64_t entry)
{
   // Here we need to normalise the entry to the number of lines we already processed.
   const auto offset = (fEntryRangesRequested - 1) * fLinesChunkSize;
   const auto recordPos = entry - offset;
   int colIndex = 0;
   for (auto &colType : fColTypesList) {
      auto dataPtr = fRecords[recordPos][colIndex];
      switch (colType) {
      case 'd': {
         fDoubleEvtValues[colIndex][slot] = *static_cast<double *>(dataPtr);
         break;
      }
      case 'l': {
         fLong64EvtValues[colIndex][slot] = *static_cast<Long64_t *>(dataPtr);
         break;
      }
      case 'b': {
         fBoolEvtValues[colIndex][slot] = *static_cast<bool *>(dataPtr);
         break;
      }
      case 's': {
         fStringEvtValues[colIndex][slot] = *static_cast<std::string *>(dataPtr);
         break;
      }
      }
      colIndex++;
   }
   return true;
}

void RCsvDS::SetNSlots(unsigned int nSlots)
{
   R__ASSERT(0U == fNSlots && "Setting the number of slots even if the number of slots is different from zero.");

   fNSlots = nSlots;

   const auto nColumns = fHeaders.size();
   // Initialise the entire set of addresses
   fColAddresses.resize(nColumns, std::vector<void *>(fNSlots, nullptr));

   // Initialize the per event data holders
   fDoubleEvtValues.resize(nColumns, std::vector<double>(fNSlots));
   fLong64EvtValues.resize(nColumns, std::vector<Long64_t>(fNSlots));
   fStringEvtValues.resize(nColumns, std::vector<std::string>(fNSlots));
   fBoolEvtValues.resize(nColumns, std::deque<bool>(fNSlots));
}

RDataFrame MakeCsvDataFrame(std::string_view fileName, bool readHeaders, char delimiter, Long64_t linesChunkSize)
{
   ROOT::RDataFrame tdf(std::make_unique<RCsvDS>(fileName, readHeaders, delimiter, linesChunkSize));
   return tdf;
}

} // ns RDF

} // ns ROOT
<commit_msg>[RDF] Make exception clear again<commit_after>// Author: Enric Tejedor CERN  10/2017

/*************************************************************************
 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

// clang-format off
/** \class ROOT::RDF::RCsvDS
    \ingroup dataframe
    \brief RDataFrame data source class for reading CSV files.

The RCsvDS class implements a CSV file reader for RDataFrame.

A RDataFrame that reads from a CSV file can be constructed using the factory method
ROOT::RDF::MakeCsvDataFrame, which accepts three parameters:
1. Path to the CSV file.
2. Boolean that specifies whether the first row of the CSV file contains headers or
not (optional, default `true`). If `false`, header names will be automatically generated as Col0, Col1, ..., ColN.
3. Delimiter (optional, default ',').

The types of the columns in the CSV file are automatically inferred. The supported
types are:
- Integer: stored as a 64-bit long long int.
- Floating point number: stored with double precision.
- Boolean: matches the literals `true` and `false`.
- String: stored as an std::string, matches anything that does not fall into any of the
previous types.

These are some formatting rules expected by the RCsvDS implementation:
- All records must have the same number of fields, in the same order.
- Any field may be quoted.
~~~
    "1997","Ford","E350"
~~~
- Fields with embedded delimiters (e.g. comma) must be quoted.
~~~
    1997,Ford,E350,"Super, luxurious truck"
~~~
- Fields with double-quote characters must be quoted, and each of the embedded
double-quote characters must be represented by a pair of double-quote characters.
~~~
    1997,Ford,E350,"Super, ""luxurious"" truck"
~~~
- Fields with embedded line breaks are not supported, even when quoted.
~~~
    1997,Ford,E350,"Go get one now
    they are going fast"
~~~
- Spaces are considered part of a field and are not ignored.
~~~
    1997, Ford , E350
    not same as
    1997,Ford,E350
    but same as
    1997, "Ford" , E350
~~~
- If a header row is provided, it must contain column names for each of the fields.
~~~
    Year,Make,Model
    1997,Ford,E350
    2000,Mercury,Cougar
~~~

The current implementation of RCsvDS reads the entire CSV file content into memory before
RDataFrame starts processing it. Therefore, before creating a CSV RDataFrame, it is
important to check both how much memory is available and the size of the CSV file.
*/
// clang-format on

#include <ROOT/RDFUtils.hxx>
#include <ROOT/TSeq.hxx>
#include <ROOT/RCsvDS.hxx>
#include <ROOT/RMakeUnique.hxx>
#include <TError.h>

#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>

namespace ROOT {

namespace RDF {

std::string RCsvDS::AsString()
{
   return "CSV data source";
}

// Regular expressions for type inference
TRegexp RCsvDS::intRegex("^[-+]?[0-9]+$");
TRegexp RCsvDS::doubleRegex1("^[-+]?[0-9]+\\.[0-9]*$");
TRegexp RCsvDS::doubleRegex2("^[-+]?[0-9]*\\.[0-9]+$");
TRegexp RCsvDS::trueRegex("^true$");
TRegexp RCsvDS::falseRegex("^false$");

const std::map<RCsvDS::ColType_t, std::string>
   RCsvDS::fgColTypeMap({{'b', "bool"}, {'d', "double"}, {'l', "Long64_t"}, {'s', "std::string"}});

void RCsvDS::FillHeaders(const std::string &line)
{
   auto columns = ParseColumns(line);
   for (auto &col : columns) {
      fHeaders.emplace_back(col);
   }
}

void RCsvDS::FillRecord(const std::string &line, Record_t &record)
{
   std::istringstream lineStream(line);
   auto i = 0U;

   auto columns = ParseColumns(line);

   for (auto &col : columns) {
      auto colType = fColTypes[fHeaders[i]];

      switch (colType) {
      case 'd': {
         record.emplace_back(new double(std::stod(col)));
         break;
      }
      case 'l': {
         record.emplace_back(new Long64_t(std::stoll(col)));
         break;
      }
      case 'b': {
         auto b = new bool();
         record.emplace_back(b);
         std::istringstream is(col);
         is >> std::boolalpha >> *b;
         break;
      }
      case 's': {
         record.emplace_back(new std::string(col));
         break;
      }
      }
      ++i;
   }
}

void RCsvDS::GenerateHeaders(size_t size)
{
   for (size_t i = 0; i < size; ++i) {
      fHeaders.push_back("Col" + std::to_string(i));
   }
}

std::vector<void *> RCsvDS::GetColumnReadersImpl(std::string_view colName, const std::type_info &ti)
{
   const auto colType = GetType(colName);

   if ((colType == 'd' && typeid(double) != ti) || (colType == 'l' && typeid(Long64_t) != ti) ||
       (colType == 's' && typeid(std::string) != ti) || (colType == 'b' && typeid(bool) != ti)) {
      std::string err = "The type selected for column \"";
      err += colName;
      err += "\" does not correspond to column type, which is ";
      err += fgColTypeMap.at(colType);
      throw std::runtime_error(err);
   }

   const auto &colNames = GetColumnNames();
   const auto index = std::distance(colNames.begin(), std::find(colNames.begin(), colNames.end(), colName));
   std::vector<void *> ret(fNSlots);
   for (auto slot : ROOT::TSeqU(fNSlots)) {
      auto &val = fColAddresses[index][slot];
      if (ti == typeid(double)) {
         val = &fDoubleEvtValues[index][slot];
      } else if (ti == typeid(Long64_t)) {
         val = &fLong64EvtValues[index][slot];
      } else if (ti == typeid(std::string)) {
         val = &fStringEvtValues[index][slot];
      } else {
         val = &fBoolEvtValues[index][slot];
      }
      ret[slot] = &val;
   }
   return ret;
}

void RCsvDS::InferColTypes(std::vector<std::string> &columns)
{
   auto i = 0U;
   for (auto &col : columns) {
      InferType(col, i);
      ++i;
   }
}

void RCsvDS::InferType(const std::string &col, unsigned int idxCol)
{
   ColType_t type;
   int dummy;

   if (intRegex.Index(col, &dummy) != -1) {
      type = 'l'; // Long64_t
   } else if (doubleRegex1.Index(col, &dummy) != -1 || doubleRegex2.Index(col, &dummy) != -1) {
      type = 'd'; // double
   } else if (trueRegex.Index(col, &dummy) != -1 || falseRegex.Index(col, &dummy) != -1) {
      type = 'b'; // bool
   } else {       // everything else is a string
      type = 's'; // std::string
   }
   // TODO: Date

   fColTypes[fHeaders[idxCol]] = type;
   fColTypesList.push_back(type);
}

std::vector<std::string> RCsvDS::ParseColumns(const std::string &line)
{
   std::vector<std::string> columns;

   for (size_t i = 0; i < line.size(); ++i) {
      i = ParseValue(line, columns, i);
   }

   return columns;
}

size_t RCsvDS::ParseValue(const std::string &line, std::vector<std::string> &columns, size_t i)
{
   std::stringstream val;
   bool quoted = false;

   for (; i < line.size(); ++i) {
      if (line[i] == fDelimiter && !quoted) {
         break;
      } else if (line[i] == '"') {
         // Keep just one quote for escaped quotes, none for the normal quotes
         if (line[i + 1] != '"') {
            quoted = !quoted;
         } else {
            val << line[++i];
         }
      } else {
         val << line[i];
      }
   }

   columns.emplace_back(val.str());

   return i;
}

////////////////////////////////////////////////////////////////////////
/// Constructor to create a CSV RDataSource for RDataFrame.
/// \param[in] fileName Path of the CSV file.
/// \param[in] readHeaders `true` if the CSV file contains headers as first row, `false` otherwise
///                        (default `true`).
/// \param[in] delimiter Delimiter character (default ',').
RCsvDS::RCsvDS(std::string_view fileName, bool readHeaders, char delimiter, Long64_t linesChunkSize) // TODO: Let users specify types?
   : fReadHeaders(readHeaders),
     fStream(std::string(fileName)),
     fDelimiter(delimiter),
     fLinesChunkSize(linesChunkSize)
{
   std::string line;

   // Read the headers if present
   if (fReadHeaders) {
      if (std::getline(fStream, line)) {
         FillHeaders(line);
      } else {
         std::string msg = "Error reading headers of CSV file ";
         msg += fileName;
         throw std::runtime_error(msg);
      }
   }

   fDataPos = fStream.tellg();
   if (std::getline(fStream, line)) {
      auto columns = ParseColumns(line);

      // Generate headers if not present
      if (!fReadHeaders) {
         GenerateHeaders(columns.size());
      }

      // Infer types of columns with first record
      InferColTypes(columns);

      // rewind one line
      fStream.seekg(fDataPos);
   }
}

void RCsvDS::FreeRecords()
{
   for (auto &record : fRecords) {
      for (size_t i = 0; i < record.size(); ++i) {
         void *p = record[i];
         const auto colType = fColTypes[fHeaders[i]];
         switch (colType) {
         case 'd': {
            delete static_cast<double *>(p);
            break;
         }
         case 'l': {
            delete static_cast<Long64_t *>(p);
            break;
         }
         case 'b': {
            delete static_cast<bool *>(p);
            break;
         }
         case 's': {
            delete static_cast<std::string *>(p);
            break;
         }
         }
      }
   }
   fRecords.clear();
}

////////////////////////////////////////////////////////////////////////
/// Destructor.
RCsvDS::~RCsvDS()
{
   FreeRecords();
}

void RCsvDS::Finalise()
{
   fStream.clear();
   fStream.seekg(fDataPos);
   fProcessedLines = 0ULL;
   fEntryRangesRequested = 0ULL;
   FreeRecords();
}

const std::vector<std::string> &RCsvDS::GetColumnNames() const
{
   return fHeaders;
}

std::vector<std::pair<ULong64_t, ULong64_t>> RCsvDS::GetEntryRanges()
{

   // Read records and store them in memory
   auto linesToRead = fLinesChunkSize;
   FreeRecords();

   std::string line;
   while ((-1LL == fLinesChunkSize || 0 != linesToRead--) && std::getline(fStream, line)) {
      fRecords.emplace_back();
      FillRecord(line, fRecords.back());
   }

   std::vector<std::pair<ULong64_t, ULong64_t>> entryRanges;
   const auto nRecords = fRecords.size();
   if (0 == nRecords)
      return entryRanges;

   const auto chunkSize = nRecords / fNSlots;
   const auto remainder = 1U == fNSlots ? 0 : nRecords % fNSlots;
   auto start = 0ULL == fEntryRangesRequested ? 0ULL : fProcessedLines;
   auto end = start;

   for (auto i : ROOT::TSeqU(fNSlots)) {
      start = end;
      end += chunkSize;
      entryRanges.emplace_back(start, end);
      (void)i;
   }
   entryRanges.back().second += remainder;

   fProcessedLines += nRecords;
   fEntryRangesRequested++;

   return entryRanges;
}

RCsvDS::ColType_t RCsvDS::GetType(std::string_view colName) const
{
   if (!HasColumn(colName)) {
      std::string msg = "The dataset does not have column ";
      msg += colName;
      throw std::runtime_error(msg);
   }

   return fColTypes.at(colName.data());
}

std::string RCsvDS::GetTypeName(std::string_view colName) const
{
   return fgColTypeMap.at(GetType(colName));
}

bool RCsvDS::HasColumn(std::string_view colName) const
{
   return fHeaders.end() != std::find(fHeaders.begin(), fHeaders.end(), colName);
}

bool RCsvDS::SetEntry(unsigned int slot, ULong64_t entry)
{
   // Here we need to normalise the entry to the number of lines we already processed.
   const auto offset = (fEntryRangesRequested - 1) * fLinesChunkSize;
   const auto recordPos = entry - offset;
   int colIndex = 0;
   for (auto &colType : fColTypesList) {
      auto dataPtr = fRecords[recordPos][colIndex];
      switch (colType) {
      case 'd': {
         fDoubleEvtValues[colIndex][slot] = *static_cast<double *>(dataPtr);
         break;
      }
      case 'l': {
         fLong64EvtValues[colIndex][slot] = *static_cast<Long64_t *>(dataPtr);
         break;
      }
      case 'b': {
         fBoolEvtValues[colIndex][slot] = *static_cast<bool *>(dataPtr);
         break;
      }
      case 's': {
         fStringEvtValues[colIndex][slot] = *static_cast<std::string *>(dataPtr);
         break;
      }
      }
      colIndex++;
   }
   return true;
}

void RCsvDS::SetNSlots(unsigned int nSlots)
{
   R__ASSERT(0U == fNSlots && "Setting the number of slots even if the number of slots is different from zero.");

   fNSlots = nSlots;

   const auto nColumns = fHeaders.size();
   // Initialise the entire set of addresses
   fColAddresses.resize(nColumns, std::vector<void *>(fNSlots, nullptr));

   // Initialize the per event data holders
   fDoubleEvtValues.resize(nColumns, std::vector<double>(fNSlots));
   fLong64EvtValues.resize(nColumns, std::vector<Long64_t>(fNSlots));
   fStringEvtValues.resize(nColumns, std::vector<std::string>(fNSlots));
   fBoolEvtValues.resize(nColumns, std::deque<bool>(fNSlots));
}

RDataFrame MakeCsvDataFrame(std::string_view fileName, bool readHeaders, char delimiter, Long64_t linesChunkSize)
{
   ROOT::RDataFrame tdf(std::make_unique<RCsvDS>(fileName, readHeaders, delimiter, linesChunkSize));
   return tdf;
}

} // ns RDF

} // ns ROOT
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: parawin.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 21:43:02 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SC_PARAWIN_HXX
#define SC_PARAWIN_HXX

#ifndef SC_FUNCUTL_HXX
#include "funcutl.hxx"
#endif

#ifndef SC_SCGLOB_HXX
#include "global.hxx"       // ScAddress
#endif

#ifndef _STDCTRL_HXX //autogen
#include <svtools/stdctrl.hxx>
#endif
#ifndef _LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif

#ifndef _SV_GROUP_HXX //autogen
#include <vcl/group.hxx>
#endif

#ifndef _SVEDIT_HXX //autogen
#include <svtools/svmedit.hxx>
#endif

#ifndef _SV_TABPAGE_HXX //autogen
#include <vcl/tabpage.hxx>
#endif

#ifndef _SVSTDARR_STRINGS

#define _SVSTDARR_STRINGS
#include <svtools/svstdarr.hxx>

#endif

#ifndef _SV_TABCTRL_HXX //autogen
#include <vcl/tabctrl.hxx>
#endif

class ScFuncDesc;

//============================================================================
#define NOT_FOUND 0xffff
//============================================================================

class ScParaWin : public TabPage
{
private:

        Link            aScrollLink;
        Link            aFxLink;
        Link            aArgModifiedLink;

        const ScFuncDesc*   pFuncDesc;
        ScAnyRefDlg*    pMyParent;
        USHORT          nArgs;
        Font            aFntBold;
        Font            aFntLight;

        FixedInfo       aFtEditDesc;
        FixedText       aFtArgName;
        FixedInfo       aFtArgDesc;

        ImageButton     aBtnFx1;
        FixedText       aFtArg1;
        ArgEdit         aEdArg1;
        ScRefButton     aRefBtn1;
        ImageButton     aBtnFx2;
        FixedText       aFtArg2;
        ArgEdit         aEdArg2;
        ScRefButton     aRefBtn2;
        ImageButton     aBtnFx3;
        FixedText       aFtArg3;
        ArgEdit         aEdArg3;
        ScRefButton     aRefBtn3;
        ImageButton     aBtnFx4;
        FixedText       aFtArg4;
        ArgEdit         aEdArg4;
        ScRefButton     aRefBtn4;
        ScrollBar       aSlider;
        BOOL            bRefMode;

        USHORT          nEdFocus;
        USHORT          nActiveLine;

        ArgInput        aArgInput[4];
        String          aDefaultString;
        SvStrings       aParaArray;
        DECL_LINK( ScrollHdl, ScrollBar* );
        DECL_LINK( ModifyHdl, ArgInput* );
        DECL_LINK( GetEdFocusHdl, ArgInput* );
        DECL_LINK( GetFxFocusHdl, ArgInput* );
        DECL_LINK( GetFxHdl, ArgInput* );

protected:

        virtual void    SliderMoved();
        virtual void    ArgumentModified();
        virtual void    FxClick();

        void            InitArgInput( USHORT nPos, FixedText& rFtArg, ImageButton& rBtnFx,
                                        ArgEdit& rEdArg, ScRefButton& rRefBtn);

        void            DelParaArray();
        void            SetArgumentDesc(const String& aText);
        void            SetArgumentText(const String& aText);

        void            SetArgName      (USHORT no,const String &aArg);
        void            SetArgNameFont  (USHORT no,const Font&);
        void            SetArgVal       (USHORT no,const String &aArg);

        void            HideParaLine(USHORT no);
        void            ShowParaLine(USHORT no);
        void            UpdateArgDesc( USHORT nArg );
        void            UpdateArgInput( USHORT nOffset, USHORT i );

public:
                        ScParaWin(ScAnyRefDlg* pParent,Point aPos);
                        ~ScParaWin();

        void            SetFunctionDesc(const ScFuncDesc* pFDesc);
        void            SetArgCount(USHORT nArgs, USHORT nOffset);
        void            SetEditDesc(const String& aText);
        void            UpdateParas();
        void            ClearAll();

        BOOL            IsRefMode() {return bRefMode;}
        void            SetRefMode(BOOL bFlag) {bRefMode=bFlag;}

        USHORT          GetActiveLine();
        void            SetActiveLine(USHORT no);
        ScRefEdit*      GetActiveEdit();
        String          GetActiveArgName();

        String          GetArgument(USHORT no);
        void            SetArgument(USHORT no, const String& aString);
        void            SetArgumentFonts(const Font&aBoldFont,const Font&aLightFont);

        void            SetEdFocus(USHORT nEditLine); //Sichtbare Editzeilen
        USHORT          GetSliderPos();
        void            SetSliderPos(USHORT nSliderPos);

        void            SetScrollHdl( const Link& rLink ) { aScrollLink = rLink; }
        const Link&     GetScrollHdl() const { return aScrollLink; }

        void            SetArgModifiedHdl( const Link& rLink ) { aArgModifiedLink = rLink; }
        const Link&     GetArgModifiedHdl() const { return aArgModifiedLink; }

        void            SetFxHdl( const Link& rLink ) { aFxLink = rLink; }
        const Link&     GetFxHdl() const { return aFxLink; }
};

#endif // SC_PARAWIN_HXX

<commit_msg>INTEGRATION: CWS odff02 (1.3.666); FILE MERGED 2008/02/28 16:19:48 er 1.3.666.1: #i86514# preparation for additional functions and parameters not yet implemented but to be added as string resources, suppress in UI<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: parawin.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-07 11:21:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SC_PARAWIN_HXX
#define SC_PARAWIN_HXX

#ifndef SC_FUNCUTL_HXX
#include "funcutl.hxx"
#endif

#ifndef SC_SCGLOB_HXX
#include "global.hxx"       // ScAddress
#endif

#ifndef _STDCTRL_HXX //autogen
#include <svtools/stdctrl.hxx>
#endif
#ifndef _LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif

#ifndef _SV_GROUP_HXX //autogen
#include <vcl/group.hxx>
#endif

#ifndef _SVEDIT_HXX //autogen
#include <svtools/svmedit.hxx>
#endif

#ifndef _SV_TABPAGE_HXX //autogen
#include <vcl/tabpage.hxx>
#endif

#ifndef _SVSTDARR_STRINGS

#define _SVSTDARR_STRINGS
#include <svtools/svstdarr.hxx>

#endif

#ifndef _SV_TABCTRL_HXX //autogen
#include <vcl/tabctrl.hxx>
#endif

#include <vector>

class ScFuncDesc;

//============================================================================
#define NOT_FOUND 0xffff
//============================================================================

class ScParaWin : public TabPage
{
private:

        Link            aScrollLink;
        Link            aFxLink;
        Link            aArgModifiedLink;

        ::std::vector<USHORT>   aVisibleArgMapping;
        const ScFuncDesc*   pFuncDesc;
        ScAnyRefDlg*    pMyParent;
        USHORT          nArgs;      // unsuppressed arguments
        Font            aFntBold;
        Font            aFntLight;

        FixedInfo       aFtEditDesc;
        FixedText       aFtArgName;
        FixedInfo       aFtArgDesc;

        ImageButton     aBtnFx1;
        FixedText       aFtArg1;
        ArgEdit         aEdArg1;
        ScRefButton     aRefBtn1;
        ImageButton     aBtnFx2;
        FixedText       aFtArg2;
        ArgEdit         aEdArg2;
        ScRefButton     aRefBtn2;
        ImageButton     aBtnFx3;
        FixedText       aFtArg3;
        ArgEdit         aEdArg3;
        ScRefButton     aRefBtn3;
        ImageButton     aBtnFx4;
        FixedText       aFtArg4;
        ArgEdit         aEdArg4;
        ScRefButton     aRefBtn4;
        ScrollBar       aSlider;
        BOOL            bRefMode;

        USHORT          nEdFocus;
        USHORT          nActiveLine;

        ArgInput        aArgInput[4];
        String          aDefaultString;
        SvStrings       aParaArray;
        DECL_LINK( ScrollHdl, ScrollBar* );
        DECL_LINK( ModifyHdl, ArgInput* );
        DECL_LINK( GetEdFocusHdl, ArgInput* );
        DECL_LINK( GetFxFocusHdl, ArgInput* );
        DECL_LINK( GetFxHdl, ArgInput* );

protected:

        virtual void    SliderMoved();
        virtual void    ArgumentModified();
        virtual void    FxClick();

        void            InitArgInput( USHORT nPos, FixedText& rFtArg, ImageButton& rBtnFx,
                                        ArgEdit& rEdArg, ScRefButton& rRefBtn);

        void            DelParaArray();
        void            SetArgumentDesc(const String& aText);
        void            SetArgumentText(const String& aText);

        void            SetArgName      (USHORT no,const String &aArg);
        void            SetArgNameFont  (USHORT no,const Font&);
        void            SetArgVal       (USHORT no,const String &aArg);

        void            HideParaLine(USHORT no);
        void            ShowParaLine(USHORT no);
        void            UpdateArgDesc( USHORT nArg );
        void            UpdateArgInput( USHORT nOffset, USHORT i );

public:
                        ScParaWin(ScAnyRefDlg* pParent,Point aPos);
                        ~ScParaWin();

        void            SetFunctionDesc(const ScFuncDesc* pFDesc);
        void            SetArgumentOffset(USHORT nOffset);
        void            SetEditDesc(const String& aText);
        void            UpdateParas();
        void            ClearAll();

        BOOL            IsRefMode() {return bRefMode;}
        void            SetRefMode(BOOL bFlag) {bRefMode=bFlag;}

        USHORT          GetActiveLine();
        void            SetActiveLine(USHORT no);
        ScRefEdit*      GetActiveEdit();
        String          GetActiveArgName();

        String          GetArgument(USHORT no);
        void            SetArgument(USHORT no, const String& aString);
        void            SetArgumentFonts(const Font&aBoldFont,const Font&aLightFont);

        void            SetEdFocus(USHORT nEditLine); //Sichtbare Editzeilen
        USHORT          GetSliderPos();
        void            SetSliderPos(USHORT nSliderPos);

        void            SetScrollHdl( const Link& rLink ) { aScrollLink = rLink; }
        const Link&     GetScrollHdl() const { return aScrollLink; }

        void            SetArgModifiedHdl( const Link& rLink ) { aArgModifiedLink = rLink; }
        const Link&     GetArgModifiedHdl() const { return aArgModifiedLink; }

        void            SetFxHdl( const Link& rLink ) { aFxLink = rLink; }
        const Link&     GetFxHdl() const { return aFxLink; }
};

#endif // SC_PARAWIN_HXX

<|endoftext|>


<commit_before>/******************************************************************************\
* File:          lexer.cpp
* Purpose:       Implementation of lexer classes
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/stc/stc.h> // for wxSTC_KEYWORDSET_MAX
#include <wx/tokenzr.h>
#include <wx/extension/lexer.h>
#include <wx/extension/lexers.h>
#include <wx/extension/util.h> // for wxExAlignText

wxExLexer::wxExLexer(const wxXmlNode* node)
{
  m_CommentBegin.clear();
  m_CommentBegin2.clear();
  m_CommentEnd.clear();
  m_CommentEnd2.clear();
  m_Colourings.clear();
  m_Extensions.clear();
  m_Properties.clear();
  m_Keywords.clear();
  m_KeywordsSet.clear();
  m_ScintillaLexer.clear();

  if (node != NULL)
  {
    Set(node);
  }
}

const wxString wxExLexer::GetFormattedText(
  const wxString& lines,
  const wxString& header,
  bool fill_out_with_space,
  bool fill_out) const
{
  wxString text = lines, header_to_use = header;
  size_t nCharIndex;

  wxString out;

  // Process text between the carriage return line feeds.
  while ((nCharIndex = text.find("\n")) != wxString::npos)
  {
    out << wxExAlignText(
      text.substr(0, nCharIndex),
      header_to_use,
      fill_out_with_space,
      fill_out,
      *this);

    text = text.substr(nCharIndex + 1);
    header_to_use = wxString(' ', header.size());
  }

  if (!text.empty())
  {
    out << wxExAlignText(
      text,
      header_to_use,
      fill_out_with_space,
      fill_out,
      *this);
  }

  return out;
}

const wxString wxExLexer::GetKeywordsString(int keyword_set) const
{
  if (keyword_set == -1)
  {
    return GetKeywordsStringSet(m_Keywords);
  }
  else
  {
    std::map< int, std::set<wxString> >::const_iterator it =
      m_KeywordsSet.find(keyword_set);

    if (it != m_KeywordsSet.end())
    {
      return GetKeywordsStringSet(it->second);
    }
  }

  return wxEmptyString;
}

const wxString wxExLexer::GetKeywordsStringSet(
  const std::set<wxString>& kset) const
{
  wxString keywords;

  for (
    std::set<wxString>::const_iterator it = kset.begin();
    it != kset.end();
    ++it)
  {
    keywords += *it + " ";
  }

  return keywords.Trim(); // remove the ending space
}

bool wxExLexer::IsKeyword(const wxString& word) const
{
  std::set<wxString>::const_iterator it = m_Keywords.find(word);
  return (it != m_Keywords.end());
}

bool wxExLexer::KeywordStartsWith(const wxString& word) const
{
  std::set<wxString>::const_iterator it = m_Keywords.lower_bound(word.Lower());
  return
    it != m_Keywords.end() &&
    it->StartsWith(word.Lower());
}

const wxString wxExLexer::MakeComment(
  const wxString& text,
  bool fill_out_with_space,
  bool fill_out) const
{
  wxString out;

  text.find("\n") != wxString::npos ?
    out << GetFormattedText(text, wxEmptyString, fill_out_with_space, fill_out):
    out << wxExAlignText(text, wxEmptyString, fill_out_with_space, fill_out, *this);

  return out;
}

const wxString wxExLexer::MakeComment(
  const wxString& prefix,
  const wxString& text) const
{
  wxString out;

  text.find("\n") != wxString::npos ?
    out << GetFormattedText(text, prefix, true, true):
    out << wxExAlignText(text, prefix, true, true, *this);

  return out;
}

const wxString wxExLexer::MakeSingleLineComment(
  const wxString& text,
  bool fill_out_with_space,
  bool fill_out) const
{
  if (m_CommentBegin.empty() && m_CommentEnd.empty())
  {
    return text;
  }

  // First set the fill_out_character.
  wxUniChar fill_out_character;

  if (fill_out_with_space || m_ScintillaLexer == "hypertext")
  {
    fill_out_character = ' ';
  }
  else
  {
    if (text.empty())
    {
      if (m_CommentBegin == m_CommentEnd)
           fill_out_character = '-';
      else fill_out_character = m_CommentBegin[m_CommentBegin.size() - 1];
    }
    else   fill_out_character = ' ';
  }

  wxString out = m_CommentBegin + fill_out_character + text;

  // Fill out characters.
  if (fill_out)
  {
    // To prevent filling out spaces
    if (fill_out_character != ' ' || !m_CommentEnd.empty())
    {
      const int fill_chars = UsableCharactersPerLine() - text.size();

      if (fill_chars > 0)
      {
        const wxString fill_out(fill_out_character, fill_chars);
        out += fill_out;
      }
    }
  }

  if (!m_CommentEnd.empty()) out += fill_out_character + m_CommentEnd;

  return out;
}

void wxExLexer::Set(const wxXmlNode* node)
{
  m_ScintillaLexer = node->GetAttribute("name", "");
  m_Extensions = node->GetAttribute(
    "extensions",
    "*." + m_ScintillaLexer);

  if (node->GetAttribute("match", "") != "")
  {
    m_Colourings =
      wxExLexers::Get()->AutoMatch(node->GetAttribute("match", ""));
  }

  if (m_ScintillaLexer == "hypertext")
  {
    // As our lexers.xml files cannot use xml comments,
    // add them here.
    m_CommentBegin = "<!--";
    m_CommentEnd = "-->";
  }

  wxXmlNode *child = node->GetChildren();

  while (child)
  {
    if (child->GetName() == "colourings")
    {
      const std::vector<wxString> v =
        wxExLexers::Get()->ParseTagColourings(child);

      m_Colourings.insert(
        m_Colourings.end(),
        v.begin(), v.end());
    }
    else if (child->GetName() == "keywords")
    {
      if (!SetKeywords(child->GetNodeContent().Strip(wxString::both)))
      {
        wxLogError(
          _("Keywords could not be set on line: %d"),
          child->GetLineNumber());
      }
    }
    else if (child->GetName() == "properties")
    {
      m_Properties = wxExLexers::Get()->ParseTagProperties(child);
    }
    else if (child->GetName() == "comments")
    {
      m_CommentBegin = child->GetAttribute("begin1", "");
      m_CommentEnd = child->GetAttribute("end1", "");
      m_CommentBegin2 = child->GetAttribute("begin2", "");
      m_CommentEnd2 = child->GetAttribute("end2", "");
    }
    else if (child->GetName() == "comment")
    {
      // Ignore comments.
    }
    else
    {
      wxLogError(_("Undefined lexer tag: %s on line: %d"),
        child->GetName().c_str(),
        child->GetLineNumber());
    }

    child = child->GetNext();
  }
}

bool wxExLexer::SetKeywords(const wxString& value)
{
  if (!m_Keywords.empty())
  {
    m_Keywords.clear();
  }

  if (!m_KeywordsSet.empty())
  {
    m_KeywordsSet.clear();
  }

  std::set<wxString> keywords_set;

  wxStringTokenizer tkz(value, "\r\n ");

  int setno = 0;

  while (tkz.HasMoreTokens())
  {
    const wxString line = tkz.GetNextToken();
    wxStringTokenizer fields(line, ":");

    wxString keyword;

    if (fields.CountTokens() > 1)
    {
      keyword = fields.GetNextToken();

      const int new_setno = atoi(fields.GetNextToken().c_str());

      if (new_setno >= wxSTC_KEYWORDSET_MAX)
      {
        return false;
      }

      if (new_setno != setno)
      {
        if (!keywords_set.empty())
        {
          m_KeywordsSet.insert(make_pair(setno, keywords_set));
          keywords_set.clear();
        }

        setno = new_setno;
      }

      keywords_set.insert(keyword);
    }
    else
    {
      keyword = line;
      keywords_set.insert(line);
    }

    m_Keywords.insert(keyword);
  }

  m_KeywordsSet.insert(make_pair(setno, keywords_set));

  return true;
}

int wxExLexer::UsableCharactersPerLine() const
{
  // We always use lines with 80 characters. We adjust this here for
  // the space the beginning and end of the comment characters occupy.
  return 80
    - ((m_CommentBegin.size() != 0) ? m_CommentBegin.size() + 1 : 0)
    - ((m_CommentEnd.size() != 0) ? m_CommentEnd.size() + 1 : 0);
}
<commit_msg>assert when lexer is empty<commit_after>/******************************************************************************\
* File:          lexer.cpp
* Purpose:       Implementation of lexer classes
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/stc/stc.h> // for wxSTC_KEYWORDSET_MAX
#include <wx/tokenzr.h>
#include <wx/extension/lexer.h>
#include <wx/extension/lexers.h>
#include <wx/extension/util.h> // for wxExAlignText

wxExLexer::wxExLexer(const wxXmlNode* node)
{
  m_CommentBegin.clear();
  m_CommentBegin2.clear();
  m_CommentEnd.clear();
  m_CommentEnd2.clear();
  m_Colourings.clear();
  m_Extensions.clear();
  m_Properties.clear();
  m_Keywords.clear();
  m_KeywordsSet.clear();
  m_ScintillaLexer.clear();

  if (node != NULL)
  {
    Set(node);
  }
}

const wxString wxExLexer::GetFormattedText(
  const wxString& lines,
  const wxString& header,
  bool fill_out_with_space,
  bool fill_out) const
{
  wxString text = lines, header_to_use = header;
  size_t nCharIndex;

  wxString out;

  // Process text between the carriage return line feeds.
  while ((nCharIndex = text.find("\n")) != wxString::npos)
  {
    out << wxExAlignText(
      text.substr(0, nCharIndex),
      header_to_use,
      fill_out_with_space,
      fill_out,
      *this);

    text = text.substr(nCharIndex + 1);
    header_to_use = wxString(' ', header.size());
  }

  if (!text.empty())
  {
    out << wxExAlignText(
      text,
      header_to_use,
      fill_out_with_space,
      fill_out,
      *this);
  }

  return out;
}

const wxString wxExLexer::GetKeywordsString(int keyword_set) const
{
  if (keyword_set == -1)
  {
    return GetKeywordsStringSet(m_Keywords);
  }
  else
  {
    std::map< int, std::set<wxString> >::const_iterator it =
      m_KeywordsSet.find(keyword_set);

    if (it != m_KeywordsSet.end())
    {
      return GetKeywordsStringSet(it->second);
    }
  }

  return wxEmptyString;
}

const wxString wxExLexer::GetKeywordsStringSet(
  const std::set<wxString>& kset) const
{
  wxString keywords;

  for (
    std::set<wxString>::const_iterator it = kset.begin();
    it != kset.end();
    ++it)
  {
    keywords += *it + " ";
  }

  return keywords.Trim(); // remove the ending space
}

bool wxExLexer::IsKeyword(const wxString& word) const
{
  std::set<wxString>::const_iterator it = m_Keywords.find(word);
  return (it != m_Keywords.end());
}

bool wxExLexer::KeywordStartsWith(const wxString& word) const
{
  std::set<wxString>::const_iterator it = m_Keywords.lower_bound(word.Lower());
  return
    it != m_Keywords.end() &&
    it->StartsWith(word.Lower());
}

const wxString wxExLexer::MakeComment(
  const wxString& text,
  bool fill_out_with_space,
  bool fill_out) const
{
  wxString out;

  text.find("\n") != wxString::npos ?
    out << GetFormattedText(text, wxEmptyString, fill_out_with_space, fill_out):
    out << wxExAlignText(text, wxEmptyString, fill_out_with_space, fill_out, *this);

  return out;
}

const wxString wxExLexer::MakeComment(
  const wxString& prefix,
  const wxString& text) const
{
  wxString out;

  text.find("\n") != wxString::npos ?
    out << GetFormattedText(text, prefix, true, true):
    out << wxExAlignText(text, prefix, true, true, *this);

  return out;
}

const wxString wxExLexer::MakeSingleLineComment(
  const wxString& text,
  bool fill_out_with_space,
  bool fill_out) const
{
  if (m_CommentBegin.empty() && m_CommentEnd.empty())
  {
    return text;
  }

  // First set the fill_out_character.
  wxUniChar fill_out_character;

  if (fill_out_with_space || m_ScintillaLexer == "hypertext")
  {
    fill_out_character = ' ';
  }
  else
  {
    if (text.empty())
    {
      if (m_CommentBegin == m_CommentEnd)
           fill_out_character = '-';
      else fill_out_character = m_CommentBegin[m_CommentBegin.size() - 1];
    }
    else   fill_out_character = ' ';
  }

  wxString out = m_CommentBegin + fill_out_character + text;

  // Fill out characters.
  if (fill_out)
  {
    // To prevent filling out spaces
    if (fill_out_character != ' ' || !m_CommentEnd.empty())
    {
      const int fill_chars = UsableCharactersPerLine() - text.size();

      if (fill_chars > 0)
      {
        const wxString fill_out(fill_out_character, fill_chars);
        out += fill_out;
      }
    }
  }

  if (!m_CommentEnd.empty()) out += fill_out_character + m_CommentEnd;

  return out;
}

void wxExLexer::Set(const wxXmlNode* node)
{
  m_ScintillaLexer = node->GetAttribute("name", "");

  wxASSERT(!m_ScintillaLexer.empty());

  m_Extensions = node->GetAttribute(
    "extensions",
    "*." + m_ScintillaLexer);

  if (node->GetAttribute("match", "") != "")
  {
    m_Colourings =
      wxExLexers::Get()->AutoMatch(node->GetAttribute("match", ""));
  }

  if (m_ScintillaLexer == "hypertext")
  {
    // As our lexers.xml files cannot use xml comments,
    // add them here.
    m_CommentBegin = "<!--";
    m_CommentEnd = "-->";
  }

  wxXmlNode *child = node->GetChildren();

  while (child)
  {
    if (child->GetName() == "colourings")
    {
      const std::vector<wxString> v =
        wxExLexers::Get()->ParseTagColourings(child);

      m_Colourings.insert(
        m_Colourings.end(),
        v.begin(), v.end());
    }
    else if (child->GetName() == "keywords")
    {
      if (!SetKeywords(child->GetNodeContent().Strip(wxString::both)))
      {
        wxLogError(
          _("Keywords could not be set on line: %d"),
          child->GetLineNumber());
      }
    }
    else if (child->GetName() == "properties")
    {
      m_Properties = wxExLexers::Get()->ParseTagProperties(child);
    }
    else if (child->GetName() == "comments")
    {
      m_CommentBegin = child->GetAttribute("begin1", "");
      m_CommentEnd = child->GetAttribute("end1", "");
      m_CommentBegin2 = child->GetAttribute("begin2", "");
      m_CommentEnd2 = child->GetAttribute("end2", "");
    }
    else if (child->GetName() == "comment")
    {
      // Ignore comments.
    }
    else
    {
      wxLogError(_("Undefined lexer tag: %s on line: %d"),
        child->GetName().c_str(),
        child->GetLineNumber());
    }

    child = child->GetNext();
  }
}

bool wxExLexer::SetKeywords(const wxString& value)
{
  if (!m_Keywords.empty())
  {
    m_Keywords.clear();
  }

  if (!m_KeywordsSet.empty())
  {
    m_KeywordsSet.clear();
  }

  std::set<wxString> keywords_set;

  wxStringTokenizer tkz(value, "\r\n ");

  int setno = 0;

  while (tkz.HasMoreTokens())
  {
    const wxString line = tkz.GetNextToken();
    wxStringTokenizer fields(line, ":");

    wxString keyword;

    if (fields.CountTokens() > 1)
    {
      keyword = fields.GetNextToken();

      const int new_setno = atoi(fields.GetNextToken().c_str());

      if (new_setno >= wxSTC_KEYWORDSET_MAX)
      {
        return false;
      }

      if (new_setno != setno)
      {
        if (!keywords_set.empty())
        {
          m_KeywordsSet.insert(make_pair(setno, keywords_set));
          keywords_set.clear();
        }

        setno = new_setno;
      }

      keywords_set.insert(keyword);
    }
    else
    {
      keyword = line;
      keywords_set.insert(line);
    }

    m_Keywords.insert(keyword);
  }

  m_KeywordsSet.insert(make_pair(setno, keywords_set));

  return true;
}

int wxExLexer::UsableCharactersPerLine() const
{
  // We always use lines with 80 characters. We adjust this here for
  // the space the beginning and end of the comment characters occupy.
  return 80
    - ((m_CommentBegin.size() != 0) ? m_CommentBegin.size() + 1 : 0)
    - ((m_CommentEnd.size() != 0) ? m_CommentEnd.size() + 1 : 0);
}
<|endoftext|>


<commit_before>/******************************************************************************\
* File:          shell.cpp
* Purpose:       Implementation of class wxExSTCShell
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/tokenzr.h>
#include <wx/extension/shell.h>
#include <wx/extension/app.h>

#if wxUSE_GUI

using namespace std;

BEGIN_EVENT_TABLE(wxExSTCShell, wxExSTC)
  EVT_KEY_DOWN(wxExSTCShell::OnKey)
  EVT_MENU(wxID_PASTE, wxExSTCShell::OnCommand)
END_EVENT_TABLE()

wxExSTCShell::wxExSTCShell(
  wxWindow* parent,
  const wxString& prompt,
  const wxString& command_end,
  bool echo,
  int commands_save_in_config,
  long menu_flags)
  : wxExSTC(parent, menu_flags)
  , m_Command(wxEmptyString)
  , m_CommandEnd((command_end == wxEmptyString ? GetEOL(): command_end))
  , m_CommandStartPosition(0)
  , m_Echo(echo)
  // take a char that is not likely to appear inside commands
  , m_CommandsInConfigDelimiter(wxChar(0x03))
  , m_CommandsSaveInConfig(commands_save_in_config)
  , m_Prompt(prompt)
{
  // Override defaults from config.
  SetEdgeMode(wxSTC_EDGE_NONE);
  ResetMargins(false); // do not reset divider margin

  // Start with a prompt.
  Prompt();

  if (m_CommandsSaveInConfig == -1)
  {
    // Fill the list with an empty command.
    KeepCommand();
  }
  else
  {
    // Get all previous commands.
    wxStringTokenizer tkz(wxExApp::GetConfig("Shell"),
      m_CommandsInConfigDelimiter);

    while (tkz.HasMoreTokens())
    {
      const wxString val = tkz.GetNextToken();
      m_Commands.push_front(val);
    }

    // Take care that m_CommandsIterator is valid.
    if (!m_Commands.empty())
    {
      m_CommandsIterator = m_Commands.end();
    }
    else
    {
      KeepCommand();
    }
  }
}

wxExSTCShell::~wxExSTCShell()
{
  if (m_CommandsSaveInConfig > 0)
  {
    wxString values;
    int items = 0;

    for (
      list < wxString >::reverse_iterator it = m_Commands.rbegin();
      it != m_Commands.rend() && items < m_CommandsSaveInConfig;
      it++)
    {
      values += *it + m_CommandsInConfigDelimiter;
      items++;
    }

    wxExApp::SetConfig("Shell", values);
  }
}

const wxString wxExSTCShell::GetHistory() const
{
  wxString commands;

  for (
    list < wxString >::const_iterator it = m_Commands.begin();
    it != m_Commands.end();
    it++)
  {
    commands += *it + "\n";
  }

  return commands;
}

void wxExSTCShell::KeepCommand()
{
  m_Commands.remove(m_Command);
  m_Commands.push_back(m_Command);

  if (m_Commands.size() == 1)
  {
    m_CommandsIterator = m_Commands.end();
  }
}

void wxExSTCShell::OnCommand(wxCommandEvent& command)
{
  switch (command.GetId())
  {
    case wxID_PASTE:
      // Take care that we cannot paste somewhere inside.
      if (GetCurrentPos() < m_CommandStartPosition)
      {
        DocumentEnd();
      }

      Paste();
      break;

    default: command.Skip();
      break;
  }
}

void wxExSTCShell::OnKey(wxKeyEvent& event)
{
  const int key = event.GetKeyCode();

  // Enter key pressed, we might have entered a command.
  if (key == WXK_RETURN)
  {
    // First get the command.
    SetTargetStart(GetTextLength());
    SetTargetEnd(0);
    SetSearchFlags(wxSTC_FIND_REGEXP);

    if (SearchInTarget("^" + m_Prompt + ".*") != -1)
    {
      m_Command = GetText().substr(
        GetTargetStart() + m_Prompt.length(),
        GetTextLength() - 1);
      m_Command.Trim();
    }

    if (m_Command.empty())
    {
      Prompt();
    }
    else if (
      m_CommandEnd == GetEOL() ||
      m_Command.EndsWith(m_CommandEnd))
    {
      // We have a command.
      EmptyUndoBuffer();

      // History command.
      if (m_Command == wxString("history") +
         (m_CommandEnd == GetEOL() ? wxString(wxEmptyString): m_CommandEnd))
      {
        KeepCommand();
        ShowHistory();
        Prompt();
      }
      // !.. command, get it from history.
      else if (m_Command.StartsWith("!"))
      {
        if (SetCommandFromHistory(m_Command.substr(1)))
        {
          AppendText(GetEOL() + m_Command);

          // We don't keep the command, so commands are not rearranged and
          // repeatingly calling !5 always gives the same command, just as bash does.

          wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_SHELL_COMMAND);
          event.SetString(m_Command);
          wxPostEvent(GetParent(), event);
        }
        else
        {
          Prompt(m_Command + ": " + _("event not found"));
        }
      }
      // Other command, send to parent.
      else
      {
        KeepCommand();
        wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_SHELL_COMMAND);
        event.SetString(m_Command);
        wxPostEvent(GetParent(), event);
      }

      m_Command.clear();
    }
    else
    {
      if (m_Echo) event.Skip();
    }

    if (m_Commands.size() > 1)
    {
      m_CommandsIterator = m_Commands.end();
    }
  }
  // Up or down key pressed, and at the end of document.
  else if ((key == WXK_UP || key == WXK_DOWN) &&
            GetCurrentPos() == GetTextLength())
  {
    // There is always an empty command in the list.
    if (m_Commands.size() > 1)
    {
      ShowCommand(key);
    }
  }
  // Home key pressed.
  else if (key == WXK_HOME)
  {
    Home();

    const wxString line = GetLine(GetCurrentLine());

    if (line.StartsWith(m_Prompt))
    {
      GotoPos(GetCurrentPos() + m_Prompt.length());
    }
  }
  // Ctrl-Q pressed, used to stop processing.
  else if (event.GetModifiers() == wxMOD_CONTROL && key == 'Q')
  {
    wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_SHELL_COMMAND_STOP);
    wxPostEvent(GetParent(), event);
  }
  // Ctrl-V pressed, used for pasting as well.
  else if (event.GetModifiers() == wxMOD_CONTROL && key == 'V')
  {
    if (GetCurrentPos() < m_CommandStartPosition) DocumentEnd();
    if (m_Echo) event.Skip();
  }
  // Backspace or delete key pressed.
  else if (key == WXK_BACK || key == WXK_DELETE)
  {
    if (GetCurrentPos() <= m_CommandStartPosition)
    {
      // Ignore, so do nothing.
    }
    else
    {
      // Allow.
      if (m_Echo) event.Skip();
    }
  }
  // The rest.
  else
  {
    // If we enter regular text and not already building a command, first goto end.
    if (event.GetModifiers() == wxMOD_NONE &&
        key < WXK_START &&
        GetCurrentPos() < m_CommandStartPosition)
    {
      DocumentEnd();
    }

    if (m_Commands.size() > 1)
    {
      m_CommandsIterator = m_Commands.end();
    }

    if (m_Echo) event.Skip();
  }
}

void wxExSTCShell::Prompt(const wxString& text, bool add_eol)
{
  if (!text.empty())
  {
    AppendText(text);
  }

  if (GetTextLength() > 0 && add_eol)
  {
    AppendText(GetEOL());
  }

  AppendText(m_Prompt);

  DocumentEnd();

  m_CommandStartPosition = GetCurrentPos();

  EmptyUndoBuffer();
}

bool wxExSTCShell::SetCommandFromHistory(const wxString& short_command)
{
  const int no_asked_for = atoi(short_command.c_str());

  if (no_asked_for > 0)
  {
    int no = 0;

    for (
      list < wxString >::const_iterator it = m_Commands.begin();
      it != m_Commands.end();
      it++)
    {
      if (no == no_asked_for)
      {
        m_Command = *it;
        return true;
      }

      no++;
    }
  }
  else
  {
    wxString short_command_check;

    if (m_CommandEnd == GetEOL())
    {
      short_command_check = short_command;
    }
    else
    {
      short_command_check =
        short_command.substr(
          0,
          short_command.length() - m_CommandEnd.length());
    }

    // using a const_reverse_iterator here does not compile under MSW
    for (
      list < wxString >::reverse_iterator it = m_Commands.rbegin();
      it != m_Commands.rend();
      it++)
    {
      const wxString command = *it;

      if (command.StartsWith(short_command_check))
      {
        m_Command = command;
        return true;
      }
    }
  }

  return false;
}

void wxExSTCShell::ShowCommand(int key)
{
  SetTargetStart(GetTextLength());
  SetTargetEnd(0);
  SetSearchFlags(wxSTC_FIND_REGEXP);

  if (SearchInTarget("^" + m_Prompt + ".*") != -1)
  {
    SetTargetEnd(GetTextLength());

    if (key == WXK_UP)
    {
      if (m_CommandsIterator != m_Commands.begin())
      {
        m_CommandsIterator--;
      }
    }
    else
    {
      if (m_CommandsIterator != m_Commands.end())
      {
        m_CommandsIterator++;
      }
    }

    if (m_CommandsIterator != m_Commands.end())
    {
      ReplaceTarget(m_Prompt + *m_CommandsIterator);
    }
    else
    {
      ReplaceTarget(m_Prompt);
    }

    DocumentEnd();
  }
}

void wxExSTCShell::ShowHistory()
{
  int command_no = 1;

  for (
    list < wxString >::iterator it = m_Commands.begin();
    it != m_Commands.end();
    it++)
  {
    const wxString command = *it;

    if (!command.empty())
    {
      AppendText(wxString::Format("\n%d %s",
        command_no++,
        command.c_str()));
    }
  }
}

#endif // wxUSE_GUI
<commit_msg>added GetEOL before event not found message<commit_after>/******************************************************************************\
* File:          shell.cpp
* Purpose:       Implementation of class wxExSTCShell
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/tokenzr.h>
#include <wx/extension/shell.h>
#include <wx/extension/app.h>

#if wxUSE_GUI

using namespace std;

BEGIN_EVENT_TABLE(wxExSTCShell, wxExSTC)
  EVT_KEY_DOWN(wxExSTCShell::OnKey)
  EVT_MENU(wxID_PASTE, wxExSTCShell::OnCommand)
END_EVENT_TABLE()

wxExSTCShell::wxExSTCShell(
  wxWindow* parent,
  const wxString& prompt,
  const wxString& command_end,
  bool echo,
  int commands_save_in_config,
  long menu_flags)
  : wxExSTC(parent, menu_flags)
  , m_Command(wxEmptyString)
  , m_CommandEnd((command_end == wxEmptyString ? GetEOL(): command_end))
  , m_CommandStartPosition(0)
  , m_Echo(echo)
  // take a char that is not likely to appear inside commands
  , m_CommandsInConfigDelimiter(wxChar(0x03))
  , m_CommandsSaveInConfig(commands_save_in_config)
  , m_Prompt(prompt)
{
  // Override defaults from config.
  SetEdgeMode(wxSTC_EDGE_NONE);
  ResetMargins(false); // do not reset divider margin

  // Start with a prompt.
  Prompt();

  if (m_CommandsSaveInConfig == -1)
  {
    // Fill the list with an empty command.
    KeepCommand();
  }
  else
  {
    // Get all previous commands.
    wxStringTokenizer tkz(wxExApp::GetConfig("Shell"),
      m_CommandsInConfigDelimiter);

    while (tkz.HasMoreTokens())
    {
      const wxString val = tkz.GetNextToken();
      m_Commands.push_front(val);
    }

    // Take care that m_CommandsIterator is valid.
    if (!m_Commands.empty())
    {
      m_CommandsIterator = m_Commands.end();
    }
    else
    {
      KeepCommand();
    }
  }
}

wxExSTCShell::~wxExSTCShell()
{
  if (m_CommandsSaveInConfig > 0)
  {
    wxString values;
    int items = 0;

    for (
      list < wxString >::reverse_iterator it = m_Commands.rbegin();
      it != m_Commands.rend() && items < m_CommandsSaveInConfig;
      it++)
    {
      values += *it + m_CommandsInConfigDelimiter;
      items++;
    }

    wxExApp::SetConfig("Shell", values);
  }
}

const wxString wxExSTCShell::GetHistory() const
{
  wxString commands;

  for (
    list < wxString >::const_iterator it = m_Commands.begin();
    it != m_Commands.end();
    it++)
  {
    commands += *it + "\n";
  }

  return commands;
}

void wxExSTCShell::KeepCommand()
{
  m_Commands.remove(m_Command);
  m_Commands.push_back(m_Command);

  if (m_Commands.size() == 1)
  {
    m_CommandsIterator = m_Commands.end();
  }
}

void wxExSTCShell::OnCommand(wxCommandEvent& command)
{
  switch (command.GetId())
  {
    case wxID_PASTE:
      // Take care that we cannot paste somewhere inside.
      if (GetCurrentPos() < m_CommandStartPosition)
      {
        DocumentEnd();
      }

      Paste();
      break;

    default: command.Skip();
      break;
  }
}

void wxExSTCShell::OnKey(wxKeyEvent& event)
{
  const int key = event.GetKeyCode();

  // Enter key pressed, we might have entered a command.
  if (key == WXK_RETURN)
  {
    // First get the command.
    SetTargetStart(GetTextLength());
    SetTargetEnd(0);
    SetSearchFlags(wxSTC_FIND_REGEXP);

    if (SearchInTarget("^" + m_Prompt + ".*") != -1)
    {
      m_Command = GetText().substr(
        GetTargetStart() + m_Prompt.length(),
        GetTextLength() - 1);
      m_Command.Trim();
    }

    if (m_Command.empty())
    {
      Prompt();
    }
    else if (
      m_CommandEnd == GetEOL() ||
      m_Command.EndsWith(m_CommandEnd))
    {
      // We have a command.
      EmptyUndoBuffer();

      // History command.
      if (m_Command == wxString("history") +
         (m_CommandEnd == GetEOL() ? wxString(wxEmptyString): m_CommandEnd))
      {
        KeepCommand();
        ShowHistory();
        Prompt();
      }
      // !.. command, get it from history.
      else if (m_Command.StartsWith("!"))
      {
        if (SetCommandFromHistory(m_Command.substr(1)))
        {
          AppendText(GetEOL() + m_Command);

          // We don't keep the command, so commands are not rearranged and
          // repeatingly calling !5 always gives the same command, just as bash does.

          wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_SHELL_COMMAND);
          event.SetString(m_Command);
          wxPostEvent(GetParent(), event);
        }
        else
        {
          Prompt(GetEOL() + m_Command + ": " + _("event not found"));
        }
      }
      // Other command, send to parent.
      else
      {
        KeepCommand();
        wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_SHELL_COMMAND);
        event.SetString(m_Command);
        wxPostEvent(GetParent(), event);
      }

      m_Command.clear();
    }
    else
    {
      if (m_Echo) event.Skip();
    }

    if (m_Commands.size() > 1)
    {
      m_CommandsIterator = m_Commands.end();
    }
  }
  // Up or down key pressed, and at the end of document.
  else if ((key == WXK_UP || key == WXK_DOWN) &&
            GetCurrentPos() == GetTextLength())
  {
    // There is always an empty command in the list.
    if (m_Commands.size() > 1)
    {
      ShowCommand(key);
    }
  }
  // Home key pressed.
  else if (key == WXK_HOME)
  {
    Home();

    const wxString line = GetLine(GetCurrentLine());

    if (line.StartsWith(m_Prompt))
    {
      GotoPos(GetCurrentPos() + m_Prompt.length());
    }
  }
  // Ctrl-Q pressed, used to stop processing.
  else if (event.GetModifiers() == wxMOD_CONTROL && key == 'Q')
  {
    wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_SHELL_COMMAND_STOP);
    wxPostEvent(GetParent(), event);
  }
  // Ctrl-V pressed, used for pasting as well.
  else if (event.GetModifiers() == wxMOD_CONTROL && key == 'V')
  {
    if (GetCurrentPos() < m_CommandStartPosition) DocumentEnd();
    if (m_Echo) event.Skip();
  }
  // Backspace or delete key pressed.
  else if (key == WXK_BACK || key == WXK_DELETE)
  {
    if (GetCurrentPos() <= m_CommandStartPosition)
    {
      // Ignore, so do nothing.
    }
    else
    {
      // Allow.
      if (m_Echo) event.Skip();
    }
  }
  // The rest.
  else
  {
    // If we enter regular text and not already building a command, first goto end.
    if (event.GetModifiers() == wxMOD_NONE &&
        key < WXK_START &&
        GetCurrentPos() < m_CommandStartPosition)
    {
      DocumentEnd();
    }

    if (m_Commands.size() > 1)
    {
      m_CommandsIterator = m_Commands.end();
    }

    if (m_Echo) event.Skip();
  }
}

void wxExSTCShell::Prompt(const wxString& text, bool add_eol)
{
  if (!text.empty())
  {
    AppendText(text);
  }

  if (GetTextLength() > 0 && add_eol)
  {
    AppendText(GetEOL());
  }

  AppendText(m_Prompt);

  DocumentEnd();

  m_CommandStartPosition = GetCurrentPos();

  EmptyUndoBuffer();
}

bool wxExSTCShell::SetCommandFromHistory(const wxString& short_command)
{
  const int no_asked_for = atoi(short_command.c_str());

  if (no_asked_for > 0)
  {
    int no = 0;

    for (
      list < wxString >::const_iterator it = m_Commands.begin();
      it != m_Commands.end();
      it++)
    {
      if (no == no_asked_for)
      {
        m_Command = *it;
        return true;
      }

      no++;
    }
  }
  else
  {
    wxString short_command_check;

    if (m_CommandEnd == GetEOL())
    {
      short_command_check = short_command;
    }
    else
    {
      short_command_check =
        short_command.substr(
          0,
          short_command.length() - m_CommandEnd.length());
    }

    // using a const_reverse_iterator here does not compile under MSW
    for (
      list < wxString >::reverse_iterator it = m_Commands.rbegin();
      it != m_Commands.rend();
      it++)
    {
      const wxString command = *it;

      if (command.StartsWith(short_command_check))
      {
        m_Command = command;
        return true;
      }
    }
  }

  return false;
}

void wxExSTCShell::ShowCommand(int key)
{
  SetTargetStart(GetTextLength());
  SetTargetEnd(0);
  SetSearchFlags(wxSTC_FIND_REGEXP);

  if (SearchInTarget("^" + m_Prompt + ".*") != -1)
  {
    SetTargetEnd(GetTextLength());

    if (key == WXK_UP)
    {
      if (m_CommandsIterator != m_Commands.begin())
      {
        m_CommandsIterator--;
      }
    }
    else
    {
      if (m_CommandsIterator != m_Commands.end())
      {
        m_CommandsIterator++;
      }
    }

    if (m_CommandsIterator != m_Commands.end())
    {
      ReplaceTarget(m_Prompt + *m_CommandsIterator);
    }
    else
    {
      ReplaceTarget(m_Prompt);
    }

    DocumentEnd();
  }
}

void wxExSTCShell::ShowHistory()
{
  int command_no = 1;

  for (
    list < wxString >::iterator it = m_Commands.begin();
    it != m_Commands.end();
    it++)
  {
    const wxString command = *it;

    if (!command.empty())
    {
      AppendText(wxString::Format("\n%d %s",
        command_no++,
        command.c_str()));
    }
  }
}

#endif // wxUSE_GUI
<|endoftext|>


<commit_before>/// \file
/// \ingroup tutorial_fit
/// \notebook -js
/// Estimate the error in the integral of a fitted function
/// taking into account the errors in the parameters resulting from the fit.
/// The error is estimated also using the correlations values obtained from
/// the fit
///
/// run the macro doing:
///
/// ~~~ {.cpp}
///  .x ErrorIntegral.C
/// ~~~
///
/// \macro_image
/// \macro_output
/// \macro_code
///
/// \author Lorenzo Moneta

#include "TF1.h"
#include "TH1D.h"
#include "TVirtualFitter.h"
#include "TMath.h"
#include <assert.h>
#include <iostream>
#include <cmath>

//#define HAVE_OLD_ROOT_VERSION

TF1 * fitFunc;  // fit function pointer

const int NPAR = 2; // number of function parameters;

//____________________________________________________________________
double f(double * x, double * p) {
   // function used to fit the data
   return p[1]*TMath::Sin( p[0] * x[0] );
}

// when TF1::IntegralError was not available

#ifdef HAVE_OLD_ROOT_VERSION
//____________________________________________________________________
   double df_dPar(double * x, double * p) {
      // derivative of the function w.r..t parameters
      // use calculated derivatives from TF1::GradientPar

      double grad[NPAR];
      // p is used to specify for which parameter the derivative is computed
      int ipar = int(p[0] );
      assert (ipar >=0 && ipar < NPAR );

      assert(fitFunc);
      fitFunc->GradientPar(x, grad);

      return grad[ipar];
   }

//____________________________________________________________________
   double IntegralError(int npar, double * c, double * errPar,
      double * covMatrix = 0) {
      // calculate the error on the integral given the parameter error and
      // the integrals of the gradient functions c[]

      double err2 = 0;
      for (int i = 0; i < npar; ++i) {
         if (covMatrix == 0) { // assume error are uncorrelated
            err2 += c[i] * c[i] * errPar[i] * errPar[i];
         } else {
            double s = 0;
            for (int j = 0; j < npar; ++j) {
               s += covMatrix[i*npar + j] * c[j];
            }
            err2 += c[i] * s;
         }
      }

      return TMath::Sqrt(err2);
   }
#endif

//____________________________________________________________________
void ErrorIntegral() {
   fitFunc = new TF1("f",f,0,1,NPAR);
   TH1D * h1     = new TH1D("h1","h1",50,0,1);

   double  par[NPAR] = { 3.14, 1.};
   fitFunc->SetParameters(par);

   h1->FillRandom("f",1000); // fill histogram sampling fitFunc
   fitFunc->SetParameter(0,3.);  // vary a little the parameters
   h1->Fit(fitFunc);             // fit the histogram

   h1->Draw();

   /* calculate the integral*/
   double integral = fitFunc->Integral(0,1);

   TVirtualFitter * fitter = TVirtualFitter::GetFitter();
   assert(fitter != 0);
   double * covMatrix = fitter->GetCovarianceMatrix();

#ifdef HAVE_OLD_ROOT_VERSION

   /* calculate now the error (needs the derivatives of the function
   w..r.t the parameters)*/
   TF1 * deriv_par0 = new TF1("dfdp0",df_dPar,0,1,1);
   deriv_par0->SetParameter(0,0);

   TF1 * deriv_par1 = new TF1("dfdp1",df_dPar,0,1,1);
   deriv_par1->SetParameter(0,1.);

   double c[2];

   c[0] = deriv_par0->Integral(0,1);
   c[1] = deriv_par1->Integral(0,1);

   double * epar = fitFunc->GetParErrors();

   /* without correlations*/
   double sigma_integral_0 = IntegralError(2,c,epar);

   /*with correlations*/
   double sigma_integral = IntegralError(2,c,epar,covMatrix);

#else

   /* using new function in TF1 (from 12/6/2007)*/
   double sigma_integral = fitFunc->IntegralError(0,1);

#endif

   std::cout << "Integral = " << integral << " +/- " << sigma_integral
             << std::endl;

   // estimated integral  and error analytically

   double * p = fitFunc->GetParameters();
   double ic  = p[1]* (1-std::cos(p[0]) )/p[0];
   double c0c = p[1] * (std::cos(p[0]) + p[0]*std::sin(p[0]) -1.)/p[0]/p[0];
   double c1c = (1-std::cos(p[0]) )/p[0];

   // estimated error with correlations
   double sic = std::sqrt( c0c*c0c * covMatrix[0] + c1c*c1c * covMatrix[3]
      + 2.* c0c*c1c * covMatrix[1]);

   if ( std::fabs(sigma_integral-sic) > 1.E-6*sic )
      std::cout << " ERROR: test failed : different analytical  integral : "
                << ic << " +/- " << sic << std::endl;
}
<commit_msg>Remove confusing old ifdef<commit_after>/// \file
/// \ingroup tutorial_fit
/// \notebook -js
/// Estimate the error in the integral of a fitted function
/// taking into account the errors in the parameters resulting from the fit.
/// The error is estimated also using the correlations values obtained from
/// the fit
///
/// run the macro doing:
///
/// ~~~ {.cpp}
///  .x ErrorIntegral.C
/// ~~~
///
/// \macro_image
/// \macro_output
/// \macro_code
///
/// \author Lorenzo Moneta

#include "TF1.h"
#include "TH1D.h"
#include "TVirtualFitter.h"
#include "TMath.h"
#include <assert.h>
#include <iostream>
#include <cmath>

TF1 * fitFunc;  // fit function pointer

const int NPAR = 2; // number of function parameters;

//____________________________________________________________________
double f(double * x, double * p) {
   // function used to fit the data
   return p[1]*TMath::Sin( p[0] * x[0] );
}

//____________________________________________________________________
void ErrorIntegral() {
   fitFunc = new TF1("f",f,0,1,NPAR);
   TH1D * h1     = new TH1D("h1","h1",50,0,1);

   double  par[NPAR] = { 3.14, 1.};
   fitFunc->SetParameters(par);

   h1->FillRandom("f",1000); // fill histogram sampling fitFunc
   fitFunc->SetParameter(0,3.);  // vary a little the parameters
   h1->Fit(fitFunc);             // fit the histogram

   h1->Draw();

   /* calculate the integral*/
   double integral = fitFunc->Integral(0,1);

   TVirtualFitter * fitter = TVirtualFitter::GetFitter();
   assert(fitter != 0);
   double * covMatrix = fitter->GetCovarianceMatrix();

   /* using new function in TF1 (from 12/6/2007)*/
   double sigma_integral = fitFunc->IntegralError(0,1);

   std::cout << "Integral = " << integral << " +/- " << sigma_integral
             << std::endl;

   // estimated integral  and error analytically

   double * p = fitFunc->GetParameters();
   double ic  = p[1]* (1-std::cos(p[0]) )/p[0];
   double c0c = p[1] * (std::cos(p[0]) + p[0]*std::sin(p[0]) -1.)/p[0]/p[0];
   double c1c = (1-std::cos(p[0]) )/p[0];

   // estimated error with correlations
   double sic = std::sqrt( c0c*c0c * covMatrix[0] + c1c*c1c * covMatrix[3]
      + 2.* c0c*c1c * covMatrix[1]);

   if ( std::fabs(sigma_integral-sic) > 1.E-6*sic )
      std::cout << " ERROR: test failed : different analytical  integral : "
                << ic << " +/- " << sic << std::endl;
}
<|endoftext|>


<commit_before>#include "Sensor.h"
#include <hidapi.h>

namespace sensor {
    Result<double> readTemp() {
        hid_device *handle = hid_open(0x16c0, 0x0480, nullptr);
        if (!handle) {
            return jsz::Error(1, __PRETTY_FUNCTION__, "No sensor found!");
        }

        unsigned char buf[65];
	int num = 0;
	for (int i = 0; i < 3; i++) {
	        num = hid_read(handle, buf, 64);
       		if (num < 0) {
       	     		return jsz::Error(2, __PRETTY_FUNCTION__, "Could not read from sensor!");
       	 	}
	}
        if (num == 64) {
            short temp = *(short *) &buf[4]; //holy fuck!
            return double(temp);
        }

        return jsz::Error(3, __PRETTY_FUNCTION__, "Sensor returned unexpected data!");
    }
}
<commit_msg>comment<commit_after>#include "Sensor.h"
#include <hidapi.h>

namespace sensor {
    Result<double> readTemp() {
        hid_device *handle = hid_open(0x16c0, 0x0480, nullptr);
        if (!handle) {
            return jsz::Error(1, __PRETTY_FUNCTION__, "No sensor found!");
        }

        unsigned char buf[65];
	int num = 0;

	//we perform the read 3 times as the sensor sometimes won't wake up on the first try.
	for (int i = 0; i < 3; i++) {
	        num = hid_read(handle, buf, 64);
       		if (num < 0) {
       	     		return jsz::Error(2, __PRETTY_FUNCTION__, "Could not read from sensor!");
       	 	}
	}

        if (num == 64) {
            short temp = *(short *) &buf[4]; //holy fuck!
            return double(temp);
        }

        return jsz::Error(3, __PRETTY_FUNCTION__, "Sensor returned unexpected data!");
    }
}
<|endoftext|>


<commit_before>#ifndef ELEMENT_KEY_OF_HPP_
#define ELEMENT_KEY_OF_HPP_

namespace clotho {
namespace powersets {

template < class E >
struct element_key_of {
    typedef E key_type;

    key_type operator()( const E & e ) {
        return e;
    }
};

}   // namespace powersets
}   // namespace cl

#endif  // ELEMENT_KEY_OF_HPP_
<commit_msg>Added static method for getting a key from an object<commit_after>#ifndef ELEMENT_KEY_OF_HPP_
#define ELEMENT_KEY_OF_HPP_

namespace clotho {
namespace powersets {

template < class E >
struct element_key_of {
    typedef E key_type;

    key_type operator()( const E & e ) {
        return e;
    }

    static key_type get_key( const E & e ) {
        return e;
    }
};

}   // namespace powersets
}   // namespace cl

#endif  // ELEMENT_KEY_OF_HPP_
<|endoftext|>


<commit_before>namespace mant {
  class Printable {
    public:
      virtual std::string toString() const noexcept = 0;
  };
}

inline std::string to_string(
    const std::shared_ptr<Printable> printable) noexcept;

//
// Implementation
//

inline std::string to_string(
    const std::shared_ptr<Printable> printable) noexcept {
  return printable->toString();
}<commit_msg>Fixed namespace<commit_after>namespace mant {
  class Printable {
    public:
      virtual std::string toString() const noexcept = 0;
  };

  inline std::string to_string(
      const std::shared_ptr<Printable> printable) noexcept;

  //
  // Implementation
  //

  inline std::string to_string(
      const std::shared_ptr<Printable> printable) noexcept {
    return printable->toString();
  }
}<|endoftext|>