<commit_before>///
/// \file AliFemto/AliFemtoConfigObject.cxx
///

#include "AliFemtoConfigObject.h"

#include <TObjString.h>
#include <TObjArray.h>
#include <TCollection.h>

#include <regex>
#include <cctype>
#include <sstream>
#include <iostream>
#include <exception>
#include <functional>
#include <numeric>

/// \cond CLASSIMP
ClassImp(AliFemtoConfigObject);
/// \endcond


AliFemtoConfigObject::AliFemtoConfigObject(const TObject *obj)
: AliFemtoConfigObject(*obj)
{
  // std::cout << "[AliFemtoConfigObject::AliFemtoConfigObject(const TObject*)] " << obj << "\n";
}

AliFemtoConfigObject::AliFemtoConfigObject(const TObject &obj)
: TObject(obj)
, fPainter(nullptr)
{

  if (const auto *config = dynamic_cast<const AliFemtoConfigObject*>(&obj)) {
    *this = *config;
  }
  else if (const auto *str_ptr = dynamic_cast<const TObjString*>(&obj)) {
    fTypeTag = kSTRING;
    new (&fValueString) StringValue_t (str_ptr->GetString().Data());
  }
  else {
    throw std::runtime_error(std::string("Unexpected TObject initalization with point to ") + obj.ClassName());
  }
}

bool
AliFemtoConfigObject::operator==(const AliFemtoConfigObject &rhs) const
{
  if (this == &rhs) {
    return true;
  }

  if (fTypeTag != rhs.fTypeTag) {
    return false;
  }

  switch (fTypeTag) {
    case kEMPTY: return true;
    case kBOOL: return fValueBool == rhs.fValueBool;
    case kINT: return fValueInt == rhs.fValueInt;
    case kFLOAT: return fValueFloat == rhs.fValueFloat;
    case kSTRING: return fValueString == rhs.fValueString;
    case kARRAY: return fValueArray == rhs.fValueArray;
    case kMAP: return fValueMap == rhs.fValueMap;
    case kRANGE: return fValueRange == rhs.fValueRange;
    case kRANGELIST: return fValueRangeList == rhs.fValueRangeList;
  }

  return false;
}

// template<>
// struct AliFemtoConfigObject::enum_from_type< bool >
// {
//    static const TypeTagEnum_t value;
//   };

//  const AliFemtoConfigObject::TypeTagEnum_t AliFemtoConfigObject::enum_from_type< AliFemtoConfigObject::BoolValue_t >::value = static_cast<AliFemtoConfigObject::TypeTagEnum_t>(1);

TString
AliFemtoConfigObject::Stringify(bool pretty, int deep) const
{
#define INDENTSTEP 4
  switch (fTypeTag) {
    case kEMPTY: return "";
    case kBOOL: return fValueBool ? "true" : "false";
    case kINT: return TString::Format("%lld", fValueInt);
    case kFLOAT: return TString::Format("%g", fValueFloat);
    case kSTRING: return TString::Format("'%s'", fValueString.c_str());
    case kRANGE: return TString::Format("%g:%g", fValueRange.first, fValueRange.second);
    case kARRAY: {
      TString result = "[";
      auto it = fValueArray.cbegin(),
          end = fValueArray.cend();
      if (it != end) {
        result += it->Stringify(pretty);
      }
      for (++it; it != end; ++it) {
        result += ", " + it->Stringify(pretty);
      }
      result += ']';
      return result;
    }
    case kRANGELIST: {
      TString result = '(';
      auto it = fValueRangeList.cbegin(),
          end = fValueRangeList.cend();
      if (it != end) {
        result += TString::Format("%g:%g", it->first, it->second);
      }
      for (++it; it != end; ++it) {
        if (it->first == std::prev(it)->second) {
          result += TString::Format(":%g", it->second);
        } else {
          result += TString::Format(", %g:%g", it->first, it->second);
        }
      }
      result += ')';
      return result;
    }
    case kMAP: {
      // an experimental drawing-scheme
      const static bool STRINGIFY_COMPACT = false;

      auto it = fValueMap.cbegin();

      auto stringify_pair = [=] (const auto &pair) {
        auto &key_str = pair.first;
        auto value_str = (pretty)
                       ? pair.second.Stringify(pretty, deep+1)
                       : pair.second.Stringify();
        return key_str + ": " + value_str;
      };

      if (fValueMap.size() == 0) {
        return "{}";
      } else if (fValueMap.size() == 1 and !it->second.is_map()) {
        return "{" + stringify_pair(*it) + "}";
      }

      TString result = '{';
      if (!STRINGIFY_COMPACT)
      if (pretty) {
        result += '\n';
      }

      bool prefix_needs_update = true;
      TString prefix;

      if (pretty and STRINGIFY_COMPACT) {
        prefix = " ";
      } else
      if (pretty) {
        prefix = "\n" + TString(' ', (deep+1)*INDENTSTEP);
      }

      for (const auto &pair : fValueMap) {
        result += prefix + stringify_pair(pair);

        if (prefix_needs_update) {
          prefix = (pretty)
                 ? ((STRINGIFY_COMPACT) ? "\n" + TString(' ', deep*INDENTSTEP) + ", "
                                        : "," + prefix)
                 : ", ";
          prefix_needs_update = false;
        }
      }

      if (pretty) {
        result += "\n" + TString(' ',deep*INDENTSTEP);
      }
      result += '}';
      return result;
    }
  }
  return "";
}


AliFemtoConfigObject*
AliFemtoConfigObject::pop(Int_t idx)
{
  AliFemtoConfigObject *result = nullptr;
  if (is_array()) {
    auto N = static_cast<Int_t>(fValueArray.size());<commit_msg>AliFemtoConfigObject - Removed c++14-only code<commit_after>///
/// \file AliFemto/AliFemtoConfigObject.cxx
///

#include "AliFemtoConfigObject.h"

#include <TObjString.h>
#include <TObjArray.h>
#include <TCollection.h>

#include <regex>
#include <cctype>
#include <sstream>
#include <iostream>
#include <exception>
#include <functional>
#include <numeric>

/// \cond CLASSIMP
ClassImp(AliFemtoConfigObject);
/// \endcond


AliFemtoConfigObject::AliFemtoConfigObject(const TObject *obj)
: AliFemtoConfigObject(*obj)
{
  // std::cout << "[AliFemtoConfigObject::AliFemtoConfigObject(const TObject*)] " << obj << "\n";
}

AliFemtoConfigObject::AliFemtoConfigObject(const TObject &obj)
: TObject(obj)
, fPainter(nullptr)
{

  if (const auto *config = dynamic_cast<const AliFemtoConfigObject*>(&obj)) {
    *this = *config;
  }
  else if (const auto *str_ptr = dynamic_cast<const TObjString*>(&obj)) {
    fTypeTag = kSTRING;
    new (&fValueString) StringValue_t (str_ptr->GetString().Data());
  }
  else {
    throw std::runtime_error(std::string("Unexpected TObject initalization with point to ") + obj.ClassName());
  }
}

bool
AliFemtoConfigObject::operator==(const AliFemtoConfigObject &rhs) const
{
  if (this == &rhs) {
    return true;
  }

  if (fTypeTag != rhs.fTypeTag) {
    return false;
  }

  switch (fTypeTag) {
    case kEMPTY: return true;
    case kBOOL: return fValueBool == rhs.fValueBool;
    case kINT: return fValueInt == rhs.fValueInt;
    case kFLOAT: return fValueFloat == rhs.fValueFloat;
    case kSTRING: return fValueString == rhs.fValueString;
    case kARRAY: return fValueArray == rhs.fValueArray;
    case kMAP: return fValueMap == rhs.fValueMap;
    case kRANGE: return fValueRange == rhs.fValueRange;
    case kRANGELIST: return fValueRangeList == rhs.fValueRangeList;
  }

  return false;
}

// template<>
// struct AliFemtoConfigObject::enum_from_type< bool >
// {
//    static const TypeTagEnum_t value;
//   };

//  const AliFemtoConfigObject::TypeTagEnum_t AliFemtoConfigObject::enum_from_type< AliFemtoConfigObject::BoolValue_t >::value = static_cast<AliFemtoConfigObject::TypeTagEnum_t>(1);

TString
AliFemtoConfigObject::Stringify(bool pretty, int deep) const
{
#define INDENTSTEP 4
  switch (fTypeTag) {
    case kEMPTY: return "";
    case kBOOL: return fValueBool ? "true" : "false";
    case kINT: return TString::Format("%lld", fValueInt);
    case kFLOAT: return TString::Format("%g", fValueFloat);
    case kSTRING: return TString::Format("'%s'", fValueString.c_str());
    case kRANGE: return TString::Format("%g:%g", fValueRange.first, fValueRange.second);
    case kARRAY: {
      TString result = "[";
      auto it = fValueArray.cbegin(),
          end = fValueArray.cend();
      if (it != end) {
        result += it->Stringify(pretty);
      }
      for (++it; it != end; ++it) {
        result += ", " + it->Stringify(pretty);
      }
      result += ']';
      return result;
    }
    case kRANGELIST: {
      TString result = '(';
      auto it = fValueRangeList.cbegin(),
          end = fValueRangeList.cend();
      if (it != end) {
        result += TString::Format("%g:%g", it->first, it->second);
      }
      for (++it; it != end; ++it) {
        if (it->first == std::prev(it)->second) {
          result += TString::Format(":%g", it->second);
        } else {
          result += TString::Format(", %g:%g", it->first, it->second);
        }
      }
      result += ')';
      return result;
    }
    case kMAP: {
      // an experimental drawing-scheme
      const static bool STRINGIFY_COMPACT = false;

      auto it = fValueMap.cbegin();

      auto stringify_pair = [=] (const auto &pair) {
      };

      if (fValueMap.size() == 0) {
        return "{}";
      } else if (fValueMap.size() == 1 and !it->second.is_map()) {
        return "{" + it->first + ": " + it->second.Stringify(pretty, deep+1) + "}";
      }

      TString result = '{';
      if (!STRINGIFY_COMPACT)
      if (pretty) {
        result += '\n';
      }

      bool prefix_needs_update = true;
      TString prefix;

      if (pretty and STRINGIFY_COMPACT) {
        prefix = " ";
      } else
      if (pretty) {
        prefix = "\n" + TString(' ', (deep+1)*INDENTSTEP);
      }

      for (const auto &pair : fValueMap) {
        auto &key_str = pair.first;
        auto value_str = pair.second.Stringify(pretty, deep+1);
        result += prefix + key_str + ": " + value_str;

        if (prefix_needs_update) {
          prefix = (pretty)
                 ? ((STRINGIFY_COMPACT) ? "\n" + TString(' ', deep*INDENTSTEP) + ", "
                                        : "," + prefix)
                 : ", ";
          prefix_needs_update = false;
        }
      }

      if (pretty) {
        result += "\n" + TString(' ',deep*INDENTSTEP);
      }
      result += '}';
      return result;
    }
  }
  return "";
}


AliFemtoConfigObject*
AliFemtoConfigObject::pop(Int_t idx)
{
  AliFemtoConfigObject *result = nullptr;
  if (is_array()) {
    auto N = static_cast<Int_t>(fValueArray.size());
{'fraction_non_alphanumeric': 0.151494230200217, 'fraction_numerical': 0.001479435841798994, 'mean_word_length': 2.7667161961367013, 'pattern_counts': {'":': 5, '<': 49, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5389458', 'n_tokens_mistral': 3435, 'n_tokens_neox': 3389, 'n_words': 716}