<commit_before>/** Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 <NAME> et al.
 *
 * This file is part of Overpass_API.
 *
 * Overpass_API is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Overpass_API 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "../../expat/escape_json.h"
#include "output_csv.h"


bool Output_CSV::write_http_headers()
{
  std::cout<<"Content-type: text/csv\n";
  return true;
}


// Escape CSV output according to RFC 4180
std::string escape_csv(const std::string& input, const std::string& separator)
{
  std::string result;
  bool quotes_needed = false;

  for (int i = input.size() - 1; i >= 0; --i)
  {
    if (input[i] == '\n' || (separator.length() == 1 && input[i] == separator[0]))
      quotes_needed = true;
    else if (input[i] == '\"')
    {
      quotes_needed = true;
      if (result.empty())
        result = input.substr(0, i) + "\"" + input.substr(i);
      else
        result = result.substr(0, i) + "\"" + result.substr(i);
    }
  }

  if (!quotes_needed)
    return input;
  else if (result.empty())
    return std::string("\"") + input + "\"";
  else
    return std::string("\"") + result + "\"";
}


void Output_CSV::write_payload_header
    (const std::string& db_dir, const std::string& timestamp, const std::string& area_timestamp)
{
  if (csv_settings.with_headerline)
  {
    for (std::vector< std::pair< std::string, bool > >::const_iterator it = csv_settings.keyfields.begin();
        it != csv_settings.keyfields.end(); ++it)
    {
      std::cout<<(it->second ? "@" : "")<<escape_csv(it->first, csv_settings.separator);
      if (it + 1 != csv_settings.keyfields.end())
        std::cout<<csv_settings.separator;
    }
    std::cout<<'\n';
  }
}


void Output_CSV::write_footer()
{
  // Intentionally empty
}


void Output_CSV::display_remark(const std::string& text)
{
  // Intentionally empty
}


void Output_CSV::display_error(const std::string& text)
{
  // Intentionally empty
}


std::string Output_CSV::dump_config() const
{
  std::string result = "(";

  for (std::vector< std::pair< std::string, bool > >::const_iterator it = csv_settings.keyfields.begin();
      it != csv_settings.keyfields.end(); ++it)
  {
    if (it != csv_settings.keyfields.begin())
      result += ",";

    if (it->second)
      result += "::" + it->first;
    else
      result += "\"" + escape_cstr(it->first) + "\"";
  }

  if (csv_settings.separator != "\t")
    result += std::string(";") + (csv_settings.with_headerline ? "true" : "false") + ";\""
        + escape_cstr(csv_settings.separator) + "\"";
  else if (!csv_settings.with_headerline)
    result += ";false";

  return result + ")";
}

<commit_msg>csv output: show error messages<commit_after>/** Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 <NAME> et al.
 *
 * This file is part of Overpass_API.
 *
 * Overpass_API is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Overpass_API 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "../../expat/escape_json.h"
#include "output_csv.h"


bool Output_CSV::write_http_headers()
{
  std::cout<<"Content-type: text/csv\n";
  return true;
}


// Escape CSV output according to RFC 4180
std::string escape_csv(const std::string& input, const std::string& separator)
{
  std::string result;
  bool quotes_needed = false;

  for (int i = input.size() - 1; i >= 0; --i)
  {
    if (input[i] == '\n' || (separator.length() == 1 && input[i] == separator[0]))
      quotes_needed = true;
    else if (input[i] == '\"')
    {
      quotes_needed = true;
      if (result.empty())
        result = input.substr(0, i) + "\"" + input.substr(i);
      else
        result = result.substr(0, i) + "\"" + result.substr(i);
    }
  }

  if (!quotes_needed)
    return input;
  else if (result.empty())
    return std::string("\"") + input + "\"";
  else
    return std::string("\"") + result + "\"";
}


void Output_CSV::write_payload_header
    (const std::string& db_dir, const std::string& timestamp, const std::string& area_timestamp)
{
  if (csv_settings.with_headerline)
  {
    for (std::vector< std::pair< std::string, bool > >::const_iterator it = csv_settings.keyfields.begin();
        it != csv_settings.keyfields.end(); ++it)
    {
      std::cout<<(it->second ? "@" : "")<<escape_csv(it->first, csv_settings.separator);
      if (it + 1 != csv_settings.keyfields.end())
        std::cout<<csv_settings.separator;
    }
    std::cout<<'\n';
  }
}


void Output_CSV::write_footer()
{
  // Intentionally empty
}


void Output_CSV::display_remark(const std::string& text)
{
  std::cout << "\n\n" << text;
}


void Output_CSV::display_error(const std::string& text)
{
  std::cout << "\n\n" << text;
}


std::string Output_CSV::dump_config() const
{
  std::string result = "(";

  for (std::vector< std::pair< std::string, bool > >::const_iterator it = csv_settings.keyfields.begin();
      it != csv_settings.keyfields.end(); ++it)
  {
    if (it != csv_settings.keyfields.begin())
      result += ",";

    if (it->second)
      result += "::" + it->first;
    else
      result += "\"" + escape_cstr(it->first) + "\"";
  }

  if (csv_settings.separator != "\t")
    result += std::string(";") + (csv_settings.with_headerline ? "true" : "false") + ";\""
        + escape_cstr(csv_settings.separator) + "\"";
  else if (!csv_settings.with_headerline)
    result += ";false";

  return result + ")";
}


{'fraction_non_alphanumeric': 0.1645628078817734, 'fraction_numerical': 0.017241379310344827, 'mean_word_length': 3.392832995267072, 'pattern_counts': {'":': 2, '<': 43, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5003150', 'n_tokens_mistral': 2288, 'n_tokens_neox': 2116, 'n_words': 582}