<commit_before>// @(#)root/meta:$
// Author: <NAME> 2014-05-02

/*************************************************************************
 * Copyright (C) 1995-2014, <NAME> and <NAME>.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/** \class TProtoClass
Persistent version of a TClass.
*/

#include "TProtoClass.h"

#include "TBaseClass.h"
#include "TClass.h"
#include "TClassEdit.h"
#include "TDataMember.h"
#include "TEnum.h"
#include "TInterpreter.h"
#include "TList.h"
#include "TListOfDataMembers.h"
#include "TListOfEnums.h"
#include "TRealData.h"
#include "TError.h"

#include <cassert>
#include <unordered_map>

////////////////////////////////////////////////////////////////////////////////
/// Initialize a TProtoClass from a TClass.

TProtoClass::TProtoClass(TClass* cl):
   TNamed(*cl), fBase(cl->GetListOfBases()),
   fEnums(cl->GetListOfEnums()), fSizeof(cl->Size()), fCheckSum(cl->fCheckSum),
   fCanSplit(cl->fCanSplit), fStreamerType(cl->fStreamerType), fProperty(cl->fProperty),
   fClassProperty(cl->fClassProperty)
{
   if (cl->Property() & kIsNamespace){
      //fData=new TListOfDataMembers();
      fEnums=nullptr;
      //fPRealData=nullptr;
      fOffsetStreamer=0;
      return;
   }
   TListOfEnums *enums = dynamic_cast<TListOfEnums*>(fEnums);
   if (enums && !enums->fIsLoaded) {
      // Make sure all the enum information is loaded
      enums->Load();
   }
   // initialize list of data members (fData)
   TList * dataMembers = cl->GetListOfDataMembers();
   if (dataMembers && dataMembers->GetSize() > 0) {
      fData.reserve(dataMembers->GetSize() );
      for (auto * obj : *dataMembers) {
         TDataMember * dm = dynamic_cast<TDataMember*>(obj);
         fData.push_back(dm);
      }
   }

   fPRealData.reserve(100);
   class DepClassDedup {
      std::vector<TString> &fDepClasses;
      std::unordered_map<std::string, int> fDepClassIdx;
   public:
      DepClassDedup(std::vector<TString> &depClasses): fDepClasses(depClasses)
      {
         R__ASSERT(fDepClasses.empty() && "Expected fDepClasses to be empty before fililng it!");
      }

      ~DepClassDedup()
      {
         if (fDepClasses.size() != fDepClassIdx.size())
            ::Error("TProtoClass::DepClassDedup::~DepClassDedup",
                    "Mismatching size of fDepClasses and index map! Please report.");
      }

      int GetIdx(const char *name) {
         auto itins = fDepClassIdx.insert({name, fDepClasses.size()});
         if (itins.second) {
            fDepClasses.emplace_back(name);
         }
         return itins.first->second;
      }
   } depClassDedup(fDepClasses);

   if (!cl->GetCollectionProxy()) {
      // Build the list of RealData before we access it:
      cl->BuildRealData(0, true /*isTransient*/);
      // The data members are ordered as follows:
      // - this class's data members,
      // - foreach base: base class's data members.
      for (auto realDataObj: *cl->GetListOfRealData()) {
         TRealData *rd = (TRealData*)realDataObj;
         TProtoRealData protoRealData(rd);

         if (TClass* clRD = rd->GetDataMember()->GetClass())
            protoRealData.fClassIndex = depClassDedup.GetIdx(clRD->GetName());

         protoRealData.SetFlag(TProtoRealData::kIsTransient, rd->TestBit(TRealData::kTransient));

         fPRealData.emplace_back(protoRealData);
      }

      // if (gDebug > 2) {
         // for (const auto &data : fPRealData) {
            // const auto classType = dataPtr->IsA();
            // const auto dataName = data.fName;
            // const auto dataClass = data.fClass;
            // Info("TProtoClass","Data is a protorealdata: %s - class %s - transient %d", dataName.Data(),dataClass.Data(),data.fIsTransient);
            //if (!dataClass.IsNull()
            // if (classType == TProtoRealData::Class())
            //    Info("TProtoClass","Data is a protorealdata: %s", dataPtrName);
            // if (classType == TObjString::Class())
            //    Info("TProtoClass","Data is a objectstring: %s", dataPtrName);
            // if (dataPtr->TestBit(TRealData::kTransient))
            //    Info("TProtoClass","And is transient");
         // }
      // }
   }

   cl->CalculateStreamerOffset();
   fOffsetStreamer = cl->fOffsetStreamer;
}


////////////////////////////////////////////////////////////////////////////////
/// Destructor.

TProtoClass::~TProtoClass()
{
   Delete();
}

////////////////////////////////////////////////////////////////////////////////
/// Delete the containers that are usually owned by their TClass.
/// if (fPRealData) fPRealData->Delete(opt);
/// delete fPRealData; fPRealData = 0;

void TProtoClass::Delete(Option_t* opt /*= ""*/) {
   if (fBase) fBase->Delete(opt);
   delete fBase; fBase = 0;

   for (auto dm: fData) {
      delete dm;
   }

   if (fEnums) fEnums->Delete(opt);
   delete fEnums; fEnums = 0;

   if (gErrorIgnoreLevel==-2) printf("Delete the protoClass %s \n",GetName());
}

////////////////////////////////////////////////////////////////////////////////
/// Move data from this TProtoClass into cl.
/// Returns 'false' if nothing was done.  This can happen in the case where
/// there is more than one dictionary for the same entity.  Note having
/// duplicate dictionary is acceptable for namespace or STL collections.

Bool_t TProtoClass::FillTClass(TClass* cl) {
   if (cl->fRealData || cl->fBase.load() || cl->fData.load() || cl->fEnums.load() || cl->fCanSplit >= 0 ||
       cl->fProperty != (-1)) {

      if (cl->fState == TClass::kHasTClassInit)
         // The class has dictionary, has gone through some initialization and is now being requested
         // to be filled by a TProtoClass.
         // This can be due to:
         //   (a) A duplicate dictionary for a class (with or without a rootpcm associated with)
         //   (b) The TClass was created before the registration of the rootpcm ** and ** it was
         //       attempted to be used before this registration

         // This is technically an error
         // but we either already warned that there is a 2nd dictionary for the class (in TClassTable::Add)
         // or this is the same (but now emptied) TProtoClass instance as before.
         // We return false, since we are doing no actual change to the TClass instance and thus
         // if a caller was hoping for 'improvement' in the state of the TClass instance, it did not
         // happen.
         return kFALSE;

      if (cl->GetCollectionType() != ROOT::kNotSTL) {
         // We are in the case of collection, duplicate dictionary are allowed
         // (and even somewhat excepted since they can be auto asked for).
         // They do not always have a TProtoClass for them.  In particular
         // the one that are pre-generated in the ROOT build (in what was once
         // called the cintdlls) do not have a pcms, neither does vector<string>
         // which is part of libCore proper.
         if (gDebug > 0)
            Info("FillTClass", "Returning w/o doing anything. %s is a STL collection.",cl->GetName());
         return kFALSE;
      }
      if (cl->fProperty != -1 && (cl->fProperty & kIsNamespace)) {<commit_msg>[NFC] typo<commit_after>// @(#)root/meta:$
// Author: <NAME> 2014-05-02

/*************************************************************************
 * Copyright (C) 1995-2014, <NAME> and <NAME>.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/** \class TProtoClass
Persistent version of a TClass.
*/

#include "TProtoClass.h"

#include "TBaseClass.h"
#include "TClass.h"
#include "TClassEdit.h"
#include "TDataMember.h"
#include "TEnum.h"
#include "TInterpreter.h"
#include "TList.h"
#include "TListOfDataMembers.h"
#include "TListOfEnums.h"
#include "TRealData.h"
#include "TError.h"

#include <cassert>
#include <unordered_map>

////////////////////////////////////////////////////////////////////////////////
/// Initialize a TProtoClass from a TClass.

TProtoClass::TProtoClass(TClass* cl):
   TNamed(*cl), fBase(cl->GetListOfBases()),
   fEnums(cl->GetListOfEnums()), fSizeof(cl->Size()), fCheckSum(cl->fCheckSum),
   fCanSplit(cl->fCanSplit), fStreamerType(cl->fStreamerType), fProperty(cl->fProperty),
   fClassProperty(cl->fClassProperty)
{
   if (cl->Property() & kIsNamespace){
      //fData=new TListOfDataMembers();
      fEnums=nullptr;
      //fPRealData=nullptr;
      fOffsetStreamer=0;
      return;
   }
   TListOfEnums *enums = dynamic_cast<TListOfEnums*>(fEnums);
   if (enums && !enums->fIsLoaded) {
      // Make sure all the enum information is loaded
      enums->Load();
   }
   // initialize list of data members (fData)
   TList * dataMembers = cl->GetListOfDataMembers();
   if (dataMembers && dataMembers->GetSize() > 0) {
      fData.reserve(dataMembers->GetSize() );
      for (auto * obj : *dataMembers) {
         TDataMember * dm = dynamic_cast<TDataMember*>(obj);
         fData.push_back(dm);
      }
   }

   fPRealData.reserve(100);
   class DepClassDedup {
      std::vector<TString> &fDepClasses;
      std::unordered_map<std::string, int> fDepClassIdx;
   public:
      DepClassDedup(std::vector<TString> &depClasses): fDepClasses(depClasses)
      {
         R__ASSERT(fDepClasses.empty() && "Expected fDepClasses to be empty before fililng it!");
      }

      ~DepClassDedup()
      {
         if (fDepClasses.size() != fDepClassIdx.size())
            ::Error("TProtoClass::DepClassDedup::~DepClassDedup",
                    "Mismatching size of fDepClasses and index map! Please report.");
      }

      int GetIdx(const char *name) {
         auto itins = fDepClassIdx.insert({name, fDepClasses.size()});
         if (itins.second) {
            fDepClasses.emplace_back(name);
         }
         return itins.first->second;
      }
   } depClassDedup(fDepClasses);

   if (!cl->GetCollectionProxy()) {
      // Build the list of RealData before we access it:
      cl->BuildRealData(0, true /*isTransient*/);
      // The data members are ordered as follows:
      // - this class's data members,
      // - foreach base: base class's data members.
      for (auto realDataObj: *cl->GetListOfRealData()) {
         TRealData *rd = (TRealData*)realDataObj;
         TProtoRealData protoRealData(rd);

         if (TClass* clRD = rd->GetDataMember()->GetClass())
            protoRealData.fClassIndex = depClassDedup.GetIdx(clRD->GetName());

         protoRealData.SetFlag(TProtoRealData::kIsTransient, rd->TestBit(TRealData::kTransient));

         fPRealData.emplace_back(protoRealData);
      }

      // if (gDebug > 2) {
         // for (const auto &data : fPRealData) {
            // const auto classType = dataPtr->IsA();
            // const auto dataName = data.fName;
            // const auto dataClass = data.fClass;
            // Info("TProtoClass","Data is a protorealdata: %s - class %s - transient %d", dataName.Data(),dataClass.Data(),data.fIsTransient);
            //if (!dataClass.IsNull()
            // if (classType == TProtoRealData::Class())
            //    Info("TProtoClass","Data is a protorealdata: %s", dataPtrName);
            // if (classType == TObjString::Class())
            //    Info("TProtoClass","Data is a objectstring: %s", dataPtrName);
            // if (dataPtr->TestBit(TRealData::kTransient))
            //    Info("TProtoClass","And is transient");
         // }
      // }
   }

   cl->CalculateStreamerOffset();
   fOffsetStreamer = cl->fOffsetStreamer;
}


////////////////////////////////////////////////////////////////////////////////
/// Destructor.

TProtoClass::~TProtoClass()
{
   Delete();
}

////////////////////////////////////////////////////////////////////////////////
/// Delete the containers that are usually owned by their TClass.
/// if (fPRealData) fPRealData->Delete(opt);
/// delete fPRealData; fPRealData = 0;

void TProtoClass::Delete(Option_t* opt /*= ""*/) {
   if (fBase) fBase->Delete(opt);
   delete fBase; fBase = 0;

   for (auto dm: fData) {
      delete dm;
   }

   if (fEnums) fEnums->Delete(opt);
   delete fEnums; fEnums = 0;

   if (gErrorIgnoreLevel==-2) printf("Delete the protoClass %s \n",GetName());
}

////////////////////////////////////////////////////////////////////////////////
/// Move data from this TProtoClass into cl.
/// Returns 'false' if nothing was done.  This can happen in the case where
/// there is more than one dictionary for the same entity.  Note having
/// duplicate dictionary is acceptable for namespace or STL collections.

Bool_t TProtoClass::FillTClass(TClass* cl) {
   if (cl->fRealData || cl->fBase.load() || cl->fData.load() || cl->fEnums.load() || cl->fCanSplit >= 0 ||
       cl->fProperty != (-1)) {

      if (cl->fState == TClass::kHasTClassInit)
         // The class has dictionary, has gone through some initialization and is now being requested
         // to be filled by a TProtoClass.
         // This can be due to:
         //   (a) A duplicate dictionary for a class (with or without a rootpcm associated with)
         //   (b) The TClass was created before the registration of the rootpcm ** and ** it was
         //       attempted to be used before this registration

         // This is technically an error
         // but we either already warned that there is a 2nd dictionary for the class (in TClassTable::Add)
         // or this is the same (but now emptied) TProtoClass instance as before.
         // We return false, since we are doing no actual change to the TClass instance and thus
         // if a caller was hoping for 'improvement' in the state of the TClass instance, it did not
         // happen.
         return kFALSE;

      if (cl->GetCollectionType() != ROOT::kNotSTL) {
         // We are in the case of collection, duplicate dictionary are allowed
         // (and even somewhat expected since they can be auto asked for).
         // They do not always have a TProtoClass for them.  In particular
         // the one that are pre-generated in the ROOT build (in what was once
         // called the cintdlls) do not have a pcms, neither does vector<string>
         // which is part of libCore proper.
         if (gDebug > 0)
            Info("FillTClass", "Returning w/o doing anything. %s is a STL collection.",cl->GetName());
         return kFALSE;
      }
      if (cl->fProperty != -1 && (cl->fProperty & kIsNamespace)) {
{'fraction_non_alphanumeric': 0.18186663113716608, 'fraction_numerical': 0.0042635400706148826, 'mean_word_length': 2.1751269035532994, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 113, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1854900', 'n_tokens_mistral': 4405, 'n_tokens_neox': 4283, 'n_words': 1205}