<commit_before>#include <iostream>

#include "TFile.h"
#include "TTree.h"
#include "TVirtualStreamerInfo.h"
#include "TStreamerElement.h"
#include "TClonesArray.h"
#include "TTreeGeneratorBase.h"
#include "TFormLeafInfo.h"

class MemberStructure {
public:
  std::string type;
  bool pointer;
  std::string variable;
  std::string variableWithArray;
  std::string comment;

  MemberStructure(std::string type, bool pointer, std::string variable, std::string variableWithArray, std::string comment) :
    type(type), pointer(pointer), variable(variable), variableWithArray(variableWithArray), comment(comment) { }

  std::string cpp(int indent) {
    std::string out = std::string(indent, ' ');
    out += type + " ";
    if (pointer)
      out += "*";
    out += variableWithArray + ";";
    if (!comment.empty())
      out += "    //" + comment;
    return out;
  }
};

class ClassStructure {
public:
  std::string fullName;
  std::vector<std::string> splitName;
  TClass *tclass;
  int version;
  std::vector<MemberStructure> bases;
  std::vector<MemberStructure> members;
  ClassStructure(TClass *tclass, int version) : fullName(tclass->GetName()), splitName(splitCppNamespace(tclass->GetName())), tclass(tclass), version(version) { }

  std::vector<std::string> splitCppNamespace(std::string className) {
    std::string delim("::");
    std::vector<std::string> out;
    std::size_t start = 0;
    std::size_t end = 0;
    while ((end = className.find(delim, start)) != std::string::npos) {
      out.push_back(className.substr(start, end - start));
      start = end + 2;
    }
    out.push_back(className.substr(start));
    return out;
  }

  std::string cpp(int indent) {
    std::string out;
    std::string ind = std::string(indent, ' ');

    if (!members.empty()) {
      out += ind + "class ";
      out += splitName.back();
      if (!bases.empty()) {
        out += " : public";
        for (int i = 0;  i < bases.size();  i++)
          if (i == 0)
            out += " " + bases[i].type;
          else
            out += ", " + bases[i].type;
      }
      out += " {\n" + ind + "  public:\n";

      for (int i = 0;  i < members.size();  i++)
        out += ind + members[i].cpp(indent + 2) + "\n";

      out += ind + "    " + splitName.back() + "() {\n";
      for (int i = 0;  i < members.size();  i++)
        if (members[i].pointer  ||  members[i].type == std::string("Char_t*"))
          out += ind + "      " + members[i].variable + " = nullptr;\n";
      out += ind + "    }\n";

      out += ind + "    virtual ~" + splitName.back() + "() {\n";
      for (int i = 0;  i < members.size();  i++)
        if (members[i].pointer  ||  members[i].type == std::string("Char_t*"))
          out += ind + "      " + members[i].variable + " = nullptr;\n";
      out += ind + "    }\n";

      out += ind + "    ClassDef(" + splitName.back() + "," + std::to_string(version) + ")\n" + ind + "};\n";
    }
    return out;
  }
};

void classesFromBranch(TBranch *tbranch, TClass *tclass, std::vector<ClassStructure> &classes, int prefix, std::set<std::string> &includes);

int main(int argc, char **argv) {
  TTree *ttree;

  // TFile *tfile = TFile::Open("test_Event/Event.root");
  // tfile->GetObject("T", ttree);

  // TFile *tfile = TFile::Open("Event-0.root");
  // tfile->GetObject("t4", ttree);

  TFile *tfile = TFile::Open("test_Bacon/Output.root");
  tfile->GetObject("Events", ttree);

  std::set<std::string> includes;
  std::vector<ClassStructure> classes;

  TIter listOfBranches = ttree->GetListOfBranches();
  for (TBranch *tbranch = (TBranch*)listOfBranches.Next();  tbranch != nullptr;  tbranch = (TBranch*)listOfBranches.Next()) {
    TClass *tclass = TClass::GetClass(tbranch->GetClassName());
    if (tclass != nullptr  &&  tbranch->GetListOfBranches()->GetEntries() > 0)
      classesFromBranch(tbranch, tclass, classes, 0, includes);
  }

  for (std::set<std::string>::iterator iter = includes.begin();  iter != includes.end();  ++iter)
    std::cout << *iter << std::endl;

  std::cout << std::endl;
  
  for (std::vector<ClassStructure>::iterator iter = classes.begin();  iter != classes.end();  ++iter) {
    int i = 0;
    for (;  i < iter->splitName.size() - 1;  i++)
      std::cout << std::string(i * 2, ' ') << "namespace " << iter->splitName[i] << " {" << std::endl;
    std::cout << std::string(i * 2, ' ') << "class " << iter->splitName.back() << ";" << std::endl;
    i--;
    for (;  i >= 0;  i--)
      std::cout << std::string(i * 2, ' ') << "}" << std::endl;
  }

  std::cout << std::endl;

  for (std::vector<ClassStructure>::iterator iter = classes.begin();  iter != classes.end();  ++iter) {
    int i = 0;
    for (;  i < iter->splitName.size() - 1;  i++)
      std::cout << std::string(i * 2, ' ') << "namespace " << iter->splitName[i] << " {" << std::endl;
    std::cout << iter->cpp(i * 2) << std::endl;
    i--;
    for (;  i >= 0;  i--)
      std::cout << std::string(i * 2, ' ') << "}" << std::endl;
  }

  for (std::vector<ClassStructure>::iterator iter = classes.begin();  iter != classes.end();  ++iter) {
    int i = 0;
    for (;  i < iter->splitName.size() - 1;  i++)
      std::cout << std::string(i * 2, ' ') << "namespace " << iter->splitName[i] << " {" << std::endl;
    std::cout << std::string(i * 2, ' ') << "ClassImp(" << iter->splitName.back() << ")" << std::endl;
    i--;
    for (;  i >= 0;  i--)
      std::cout << std::string(i * 2, ' ') << "}" << std::endl;
  }

  return 0;
}

void classesFromBranch(TBranch *tbranch, TClass *tclass, std::vector<ClassStructure> &classes, int prefix, std::set<std::string> &includes) {
  std::string className = tclass->GetName();

  if (className == std::string("TObject"))
    includes.insert("#include \"TObject.h\"");
  else if (className == std::string("TRef"))
    includes.insert("#include \"TRef.h\"");
  else if (className == std::string("TRefArray"))
    includes.insert("#include \"TRefArray.h\"");
  else if (className == std::string("TH1"))
    includes.insert("#include \"TH1.h\"");
  else if (className == std::string("TBits")) {
    includes.insert("#include \"TBits.h\"");
  }
  else {
    bool seen = false;
    for (int i = 0;  i < classes.size();  i++)
      if (classes[i].fullName == className)
        seen = true;

    if (!seen) {
      TVirtualStreamerInfo *tVirtualStreamerInfo = tclass->GetStreamerInfo();
      int version = tVirtualStreamerInfo->GetClassVersion();

      ClassStructure classStructure(tclass, version);

      TIter listOfBranches = tbranch->GetListOfBranches();
      TIter elements = tVirtualStreamerInfo->GetElements();

      TStreamerElement *tStreamerElement;
      TBranch *subbranch;
      while (true) {
        tStreamerElement = (TStreamerElement*)elements.Next();
        subbranch = (TBranch*)listOfBranches.Next();
        if (tStreamerElement == nullptr  ||  subbranch == nullptr) break;

        std::string streamerName = tStreamerElement->GetName();
        std::string branchName = subbranch->GetName();
        if (branchName.find(streamerName) == std::string::npos)
          subbranch = (TBranch*)listOfBranches.Next();
        if (subbranch == nullptr) break;

        std::string variable = tStreamerElement->GetName();
        std::string variableWithArray = subbranch->GetName();
        variableWithArray = variableWithArray.substr(prefix, std::string::npos);
        variableWithArray = variableWithArray.substr(0, variableWithArray.find('.'));

        std::string comment = tStreamerElement->GetTitle();

        std::string type;
        Bool_t pointer = false;
        switch (tStreamerElement->GetType()) {

        case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBool:
          pointer = true;
        case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBool:
        case TVirtualStreamerInfo::kBool:<commit_msg>baconhep is looking right<commit_after>#include <iostream>

#include "TFile.h"
#include "TTree.h"
#include "TVirtualStreamerInfo.h"
#include "TStreamerElement.h"
#include "TClonesArray.h"
#include "TTreeGeneratorBase.h"
#include "TFormLeafInfo.h"

class MemberStructure {
public:
  std::string type;
  bool pointer;
  std::string variable;
  std::string variableWithArray;
  std::string comment;

  MemberStructure(std::string type, bool pointer, std::string variable, std::string variableWithArray, std::string comment) :
    type(type), pointer(pointer), variable(variable), variableWithArray(variableWithArray), comment(comment) { }

  std::string cpp(int indent) {
    std::string out = std::string(indent, ' ');
    out += type + " ";
    if (pointer)
      out += "*";
    out += variableWithArray + ";";
    if (!comment.empty())
      out += "    //" + comment;
    return out;
  }
};

class ClassStructure {
public:
  std::string fullName;
  std::vector<std::string> splitName;
  TClass *tclass;
  int version;
  std::vector<MemberStructure> bases;
  std::vector<MemberStructure> members;
  ClassStructure(TClass *tclass, int version) : fullName(tclass->GetName()), splitName(splitCppNamespace(tclass->GetName())), tclass(tclass), version(version) { }

  std::vector<std::string> splitCppNamespace(std::string className) {
    std::string delim("::");
    std::vector<std::string> out;
    std::size_t start = 0;
    std::size_t end = 0;
    while ((end = className.find(delim, start)) != std::string::npos) {
      out.push_back(className.substr(start, end - start));
      start = end + 2;
    }
    out.push_back(className.substr(start));
    return out;
  }

  std::string cpp(int indent) {
    std::string out;
    std::string ind = std::string(indent, ' ');

    if (!members.empty()) {
      out += ind + "class ";
      out += splitName.back();
      if (!bases.empty()) {
        out += " : public";
        for (int i = 0;  i < bases.size();  i++)
          if (i == 0)
            out += " " + bases[i].type;
          else
            out += ", " + bases[i].type;
      }
      out += " {\n" + ind + "  public:\n";

      for (int i = 0;  i < members.size();  i++)
        out += ind + members[i].cpp(indent + 2) + "\n";

      out += ind + "    " + splitName.back() + "() {\n";
      for (int i = 0;  i < members.size();  i++)
        if (members[i].pointer  ||  members[i].type == std::string("Char_t*"))
          out += ind + "      " + members[i].variable + " = nullptr;\n";
      out += ind + "    }\n";

      out += ind + "    virtual ~" + splitName.back() + "() {\n";
      for (int i = 0;  i < members.size();  i++)
        if (members[i].pointer  ||  members[i].type == std::string("Char_t*"))
          out += ind + "      " + members[i].variable + " = nullptr;\n";
      out += ind + "    }\n";

      out += ind + "    ClassDef(" + splitName.back() + "," + std::to_string(version) + ")\n" + ind + "};";
    }
    return out;
  }
};

void classesFromBranch(TBranch *tbranch, TClass *tclass, std::vector<ClassStructure> &classes, int prefix, std::set<std::string> &includes);

int main(int argc, char **argv) {
  TTree *ttree;

  // TFile *tfile = TFile::Open("test_Event/Event.root");
  // tfile->GetObject("T", ttree);

  // TFile *tfile = TFile::Open("Event-0.root");
  // tfile->GetObject("t4", ttree);

  TFile *tfile = TFile::Open("test_Bacon/Output.root");
  tfile->GetObject("Events", ttree);

  std::set<std::string> includes;
  std::vector<ClassStructure> classes;

  TIter listOfBranches = ttree->GetListOfBranches();
  for (TBranch *tbranch = (TBranch*)listOfBranches.Next();  tbranch != nullptr;  tbranch = (TBranch*)listOfBranches.Next()) {
    TClass *tclass = TClass::GetClass(tbranch->GetClassName());
    if (tclass != nullptr  &&  tbranch->GetListOfBranches()->GetEntries() > 0)
      classesFromBranch(tbranch, tclass, classes, 0, includes);
  }

  for (std::set<std::string>::iterator iter = includes.begin();  iter != includes.end();  ++iter)
    std::cout << *iter << std::endl;

  std::cout << std::endl;
  
  for (std::vector<ClassStructure>::iterator iter = classes.begin();  iter != classes.end();  ++iter) {
    int i = 0;
    for (;  i < iter->splitName.size() - 1;  i++)
      std::cout << std::string(i * 2, ' ') << "namespace " << iter->splitName[i] << " {" << std::endl;
    std::cout << std::string(i * 2, ' ') << "class " << iter->splitName.back() << ";" << std::endl;
    i--;
    for (;  i >= 0;  i--)
      std::cout << std::string(i * 2, ' ') << "}" << std::endl;
  }

  std::cout << std::endl;

  for (std::vector<ClassStructure>::iterator iter = classes.begin();  iter != classes.end();  ++iter) {
    int i = 0;
    for (;  i < iter->splitName.size() - 1;  i++)
      std::cout << std::string(i * 2, ' ') << "namespace " << iter->splitName[i] << " {" << std::endl;
    std::cout << iter->cpp(i * 2) << std::endl;
    i--;
    for (;  i >= 0;  i--)
      std::cout << std::string(i * 2, ' ') << "}" << std::endl;
  }

  for (std::vector<ClassStructure>::iterator iter = classes.begin();  iter != classes.end();  ++iter) {
    int i = 0;
    for (;  i < iter->splitName.size() - 1;  i++)
      std::cout << std::string(i * 2, ' ') << "namespace " << iter->splitName[i] << " {" << std::endl;
    std::cout << std::string(i * 2, ' ') << "ClassImp(" << iter->splitName.back() << ")" << std::endl;
    i--;
    for (;  i >= 0;  i--)
      std::cout << std::string(i * 2, ' ') << "}" << std::endl;
  }

  return 0;
}

void classesFromBranch(TBranch *tbranch, TClass *tclass, std::vector<ClassStructure> &classes, int prefix, std::set<std::string> &includes) {
  std::string className = tclass->GetName();

  if (className == std::string("TObject"))
    includes.insert("#include \"TObject.h\"");
  else if (className == std::string("TRef"))
    includes.insert("#include \"TRef.h\"");
  else if (className == std::string("TRefArray"))
    includes.insert("#include \"TRefArray.h\"");
  else if (className == std::string("TH1"))
    includes.insert("#include \"TH1.h\"");
  else if (className == std::string("TBits")) {
    includes.insert("#include \"TBits.h\"");
  }
  else {
    bool seen = false;
    for (int i = 0;  i < classes.size();  i++)
      if (classes[i].fullName == className)
        seen = true;

    if (!seen) {
      TVirtualStreamerInfo *tVirtualStreamerInfo = tclass->GetStreamerInfo();
      int version = tVirtualStreamerInfo->GetClassVersion();

      ClassStructure classStructure(tclass, version);

      if (tVirtualStreamerInfo->GetElements()->GetEntries() == 1  &&
          ((TStreamerElement*)(tVirtualStreamerInfo->GetElements()->First()))->IsBase()  &&
          std::string(tVirtualStreamerInfo->GetElements()->First()->GetName()) == std::string("TObjArray")) {

        TVirtualStreamerInfo *substreamer = ((TBranchElement*)tbranch)->GetInfo();

        if (std::string(substreamer->GetName()) == std::string("TClonesArray")) {
          ROOT::Internal::TTreeGeneratorBase ttreeGenerator(tbranch->GetTree(), "");
          TString className = ttreeGenerator.GetContainedClassName((TBranchElement*)tbranch, (TStreamerElement*)(substreamer->GetElements()->First()), true);

          classesFromBranch(tbranch, TClass::GetClass(className), classes, prefix + std::string(tbranch->GetName()).size() + 1, includes);
        }
      }

      TIter elements = tVirtualStreamerInfo->GetElements();
      for (TStreamerElement *tStreamerElement = (TStreamerElement*)elements.Next();  tStreamerElement != nullptr;  tStreamerElement = (TStreamerElement*)elements.Next()) {
        std::string streamerName = tStreamerElement->GetName();

        TIter listOfBranches = tbranch->GetListOfBranches();
        TBranch *subbranch;
        for (subbranch = (TBranch*)listOfBranches.Next();  subbranch != nullptr;  subbranch = (TBranch*)listOfBranches.Next())
          if (std::string(subbranch->GetName()).find(streamerName) != std::string::npos)
            break;
        if (subbranch == nullptr)
          continue;

        std::string branchName = subbranch->GetName();

        std::string variable = tStreamerElement->GetName();
        std::string variableWithArray = subbranch->GetName();
        variableWithArray = variableWithArray.substr(prefix, std::string::npos);
        variableWithArray = variableWithArray.substr(0, variableWithArray.find('.'));

        std::string comment = tStreamerElement->GetTitle();

        std::string type;
        Bool_t pointer = false;
        switch (tStreamerElement->GetType()) {

        case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBool:
          pointer = true;
        case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBool:
        case TVirtualStreamerInfo::kBool:
{'fraction_non_alphanumeric': 0.1929295366795367, 'fraction_numerical': 0.004464285714285714, 'mean_word_length': 3.2934472934472936, 'pattern_counts': {'":': 2, '<': 211, '<?xml version=': 0, '>': 116, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '4911273', 'n_tokens_mistral': 5503, 'n_tokens_neox': 5391, 'n_words': 1107}