#ifdef _UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif
#include "QFramework/TQListUtils.h"
#include "QFramework/TQStringUtils.h"
#include "QFramework/TQHistogramUtils.h"
#include "QFramework/TQIterator.h"
#include "TObjString.h"
#include "QFramework/TQLibrary.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <algorithm>
#include <functional>
#include <array>
using std::vector;
using std::string;
void TQListUtils::print(TList * list, const TString& options) {
TQTaggable * opts = TQTaggable::parseFlags(options);
if (!opts) {
ERRORfunc("Failed to parse options '%s'", options.Data());
return;
}
print(list, *opts);
}
void TQListUtils::print(TList * list, TQTaggable& options) {
TString errMsg = "option";
if (!options.claimTags("[f:s!],[s:b!],!!", errMsg)) {
ERRORfunc("Failed to parse options '%s'", errMsg.Data());
return;
}
bool ownList = false;
if (list && options.getTagBoolDefault("s", false)) {
list = getListOfNames(list);
list->Sort();
ownList = true;
}
TQIterator itr(list, options.getTagStringDefault("f"), ownList);
while (itr.hasNext()) {
TString name = itr.readNext()->GetName();
std::cout << name.Data() << std::endl;
}
}
void TQListUtils::print(const std::vector<TString> & vec) {
for (size_t i = 0; i< vec.size() ; ++i) {
std::cout<< "["<<i<<"]"<<vec.at(i).Data()<<std::endl;
}
}
TList * TQListUtils::getListOfNames(TCollection * collection, bool ownCollection) {
TList * result = NULL;
TQIterator itr(collection, ownCollection);
while (itr.hasNext()) {
if (!result) {
result = new TList();
result->SetOwner(true);
}
result->Add(new TObjString(itr.readNext()->GetName()));
}
return result;
}
TList * TQListUtils::getMergedListOfNames(TCollection * c1, TCollection * c2, bool ownCollections) {
TList * l1 = getListOfNames(c1, ownCollections);
TList * l2 = getListOfNames(c2, ownCollections);
TList * result = NULL;
int n1 = 0;
int n2 = 0;
if (l1) {
n1 = l1->GetEntries();
l1->Sort();
}
if (l2) {
n2 = l2->GetEntries();
l2->Sort();
}
int i1 = 0;
int i2 = 0;
while (i1 < n1 || i2 < n2) {
TObject * obj1 = (i1 < n1) ? l1->At(i1) : NULL;
TObject * obj2 = (i2 < n2) ? l2->At(i2) : NULL;
TObject * obj = NULL;
if (obj1 && obj2) {
int compare = obj1->Compare(obj2);
if (compare <= 0) {
obj = obj1;
i1++;
}
if (compare >= 0) {
obj = obj2;
i2++;
}
} else if (obj1) {
obj = obj1;
i1++;
} else if (obj2) {
obj = obj2;
i2++;
}
if (!obj) {
continue;
}
if (!result) {
result = new TList();
result->SetOwner(true);
}
result->Add(new TObjString(obj->GetName()));
}
if (l1) {
delete l1;
}
if (l2) {
delete l2;
}
return result;
}
int TQListUtils::removeElements(TList * l, const TString& filter) {
TList * names = getListOfNames(l, false);
int n = 0;
TQIterator itr(names, filter, true);
while (itr.hasNext()) {
TString name = itr.readNext()->GetName();
TObject * obj = l->FindObject(name.Data());
if (!obj) {
continue;
}
l->Remove(obj);
n++;
if (l->IsOwner()) {
delete obj;
}
}
return n;
}
bool TQListUtils::reorder(TList * list, TList * order) {
if (!list || !order || !areIsomorphic(list, order)) {
return false;
}
bool isOwner = list->IsOwner();
list->SetOwner(false);
TQIterator itr(order);
while (itr.hasNext()) {
TString name = itr.readNext()->GetName();
TObject * obj = list->FindObject(name.Data());
if (!obj) {
return false;
}
list->Remove(obj);
list->AddLast(obj);
}
list->SetOwner(isOwner);
return true;
}
bool TQListUtils::isSubsetOf(TList * l1, TList * l2) {
TQIterator itr(l1);
while (itr.hasNext()) {
TString name = itr.readNext()->GetName();
if (!l2 || !l2->FindObject(name.Data())) {
return false;
}
}
return true;
}
bool TQListUtils::areIsomorphic(TList * l1, TList * l2) {
if (!l1 || !l2) {
return !l1 && !l2;
}
if (hasDuplicates(l1) || hasDuplicates(l2)) {
return false;
}
return isSubsetOf(l1, l2) && isSubsetOf(l2, l1);
}
bool TQListUtils::hasDuplicates(TList * list) {
TList found;
found.SetOwner(true);
TQIterator itr(list);
while (itr.hasNext()) {
TString name = itr.readNext()->GetName();
if (found.FindObject(name.Data())) {
return true;
} else {
found.Add(new TObjString(name.Data()));
}
}
return false;
}
bool TQListUtils::sortByStringLength(TList * , bool ) {
throw std::runtime_error("TQListUtils::sortByStringLength(TList*, bool) is not implemented, yet!");
return true;
}
bool TQListUtils::sortByName(TList * list) {
if(!list || list->GetEntries() < 2) return false;
bool owner = list->IsOwner();
list->SetOwner(false);
std::map<std::string,TObject*> map;
std::vector<std::string> names;
TQIterator itr(list);
while(itr.hasNext()){
TObject* obj = itr.readNext();
if(!obj) continue;
std::string s(obj->GetName());
names.push_back(s);
map[s] = obj;
TList* l = dynamic_cast<TList*>(obj);
if(l) sortByName(l);
}
std::sort(names.begin(),names.end());
for(const auto& name:names){
list->Remove(map[name]);
list->AddLast(map[name]);
}
list->SetOwner(owner);
return true;
}
int TQListUtils::addClones(TCollection* from, TCollection* to){
if(!to) return -1;
TQIterator itr(from);
size_t n=0;
while(itr.hasNext()){
n++;
TObject* obj = itr.readNext();
to->Add(obj->Clone());
}
return n;
}
int TQListUtils::moveListContents(TList* origin, TList* target){
if(!origin || !target) return 0;
TQIterator itr(origin);
int nMoved = 0;
while(itr.hasNext()){
TObject* obj = itr.readNext();
if(!obj) continue;
target->Add(obj);
nMoved++;
}
return nMoved;
}
TObject* TQListUtils::findInList(TList* l, const TString& name){
if(!l) return NULL;
TQIterator itr(l);
while(itr.hasNext()){
TObject* obj = itr.readNext();
if(!obj) continue;
if(TQStringUtils::matches(obj->GetName(),name))
return obj;
}
return NULL;
}
TQTaggable* TQListUtils::findInListByTag(TList* l, const TString& key, const TString& value){
if(!l) return NULL;
TQIterator itr(l);
while(itr.hasNext()){
TQTaggable* obj = dynamic_cast<TQTaggable*>(itr.readNext());
if(!obj) continue;
if(TQStringUtils::matches(obj->getTagStringDefault(key,""),value))
return obj;
}
return NULL;
}
int TQListUtils::getMaxNameLength(TCollection* c){
int max = -1;
TQIterator itr(c);
while(itr.hasNext()){
TObject* obj = itr.readNext();
max = std::max(max,TQStringUtils::getWidth(obj->GetName()));
}
return max;
}
void TQListUtils::printList(TCollection* c){
if(!c){
ERRORfunc("cannot print NULL list");
return;
}
std::cout << TQStringUtils::makeBoldWhite(c->GetName()) << " has " << c->GetEntries() << " entries:" << std::endl;
TQIterator itr(c);
while(itr.hasNext()){
TObject* obj = dynamic_cast<TObject*>(itr.readNext());
if(!obj){
std::cout << TQStringUtils::fixedWidth("TObject",20,false) << " " << TQStringUtils::fixedWidth("NULL",60,false) << std::endl;
continue;
}
std::cout << TQStringUtils::fixedWidth(obj->ClassName(),20,false) << " " << TQStringUtils::fixedWidth(obj->GetName(),60,false) << std::endl;
}
}
int TQListUtils::collectContentNames(TCollection* origin, TList* target, const TString& pattern){
if(!origin || !target) return 0;
TQIterator itr(origin);
int nMoved = 0;
while(itr.hasNext()){
TNamed* named = dynamic_cast<TNamed*>(itr.readNext());
if(!named) continue;
if(!TQStringUtils::matches(named->GetName(),pattern))
continue;
if(target->Contains(named->GetName()))
continue;
target->Add(new TObjString(named->GetName()));
nMoved++;
}
return nMoved;
}
int TQListUtils::setBranchStatus(TTree* tree, TCollection* list, int status){
TQIterator itr(list);
int count = 0;
while(itr.hasNext()){
TObject* bName = itr.readNext();
if(!bName) continue;
TString name(bName->GetName());
if (name.First('*') != kNPOS || tree->FindBranch(name)) tree->SetBranchStatus(name, status);
count++;
}
return count;
}
TString TQListUtils::makeCSV(const std::vector<TString>& vec) {
TString str = "";
for (size_t i=0; i<vec.size();++i) {
str+=vec.at(i)+", ";
}
TQStringUtils::removeTrailingText(str,", ");
return str;
}