/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 * @(#)root/roofitcore:$Id$
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California          *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// BEGIN_HTML
// RooNameSet is a utility class that stores the names the objects
// in a RooArget. This allows to preserve the contents of a RooArgSet
// in a specific use contents beyond the lifespan of the object in
// the RooArgSet. A new RooArgSet can be created from a RooNameSet
// by offering it a list of new RooAbsArg objects. 
// END_HTML
//

#include <cstring>
#include <algorithm>
#include <cassert>

#include "RooFit.h"
#include "Riostream.h"

#include "TObjString.h"
#include "TClass.h"
#include "RooNameSet.h"
#include "RooArgSet.h"
#include "RooArgList.h"

ClassImp(RooNameSet)
;

//_____________________________________________________________________________
void RooNameSet::strdup(Int_t& dstlen, char* &dstbuf, const char* src)
{
  // copy src to dst, keep dstlen up to date, make sure zero length strings
  // do not take memory
  dstlen = src ? std::strlen(src) : 0;
  if (dstlen) ++dstlen;
  char *buf = dstlen ? new char[dstlen] : 0;
  if (buf) std::strcpy(buf, src);
  delete[] dstbuf;
  dstbuf = buf;
}

//_____________________________________________________________________________
RooNameSet::RooNameSet() : _len(0), _nameList(0)
{
  // Default constructor
}

//_____________________________________________________________________________
RooNameSet::RooNameSet(const RooArgSet& argSet) : _len(0), _nameList(0)
{
  // Construct from RooArgSet
  refill(argSet);
}

//_____________________________________________________________________________
RooNameSet::RooNameSet(const RooNameSet& other) :
  TObject(other), RooPrintable(other), _len(0), _nameList(0)
{
  // Copy constructor
  strdup(_len, _nameList, other._nameList);
}

//_____________________________________________________________________________
RooNameSet::~RooNameSet() 
{
  // Destructor
  delete[] _nameList;
}

//_____________________________________________________________________________
RooNameSet& RooNameSet::operator=(const RooNameSet& other) 
{
  // Assignment operator

  // Check comparison against self
  if (&other == this || _nameList == other._nameList) return *this;

  strdup(_len, _nameList, other._nameList);

  return *this;
}

//_____________________________________________________________________________
Bool_t RooNameSet::operator==(const RooNameSet& other) const
{
  // Comparison operator

  // Check comparison against self
  if (&other == this || _nameList == other._nameList) return kTRUE;

  return _nameList && other._nameList &&
    0 == std::strcmp(_nameList, other._nameList);
}

//_____________________________________________________________________________
Bool_t RooNameSet::operator<(const RooNameSet& other) const 
{
  if (&other == this) return kFALSE;
  if (!_nameList) return other._nameList;
  if (!other._nameList) return kFALSE;
  return std::strcmp(_nameList, other._nameList) < 0;
}

//_____________________________________________________________________________
void RooNameSet::extendBuffer(Int_t inc)
{
  if (!inc) return;
  assert(inc > 0 || _len >= -inc);
  int newsz = _len + inc;
  if (newsz <= 1 || !_len) newsz = 0;
  char* newbuf = newsz ? new char[newsz] : 0;
  if (newbuf && _nameList) {
    std::strncpy(newbuf, _nameList, std::min(_len, newsz));
    newbuf[newsz - 1] = 0;
  }
  delete[] _nameList;
  _nameList = newbuf;
  _len = newsz;
}

//_____________________________________________________________________________
void RooNameSet::setNameList(const char* givenList) 
{
  strdup(_len, _nameList, givenList);
}

//_____________________________________________________________________________
void RooNameSet::refill(const RooArgSet& argSet) 
{
  // Refill internal contents from names in given argSet
  delete[] _nameList;
  _nameList = 0;
  _len = 0;
  if (0 == argSet.getSize()) return;

  RooArgList tmp(argSet);
  tmp.sort();
  // figure out the length of the array we need
  RooAbsArg* arg = 0;
  for (RooFIter it = tmp.fwdIterator(); 0 != (arg = it.next());
      _len += 1 + std::strlen(arg->GetName())) { }
  if (_len <= 1) _len = 0;
  // allocate it
  _nameList = _len ? new char[_len] : 0;
  if (_nameList) {
    // copy in the names of the objects
    char *p = _nameList;
    for (RooFIter it = tmp.fwdIterator(); 0 != (arg = it.next()); ) {
      const char *name = arg->GetName();
      std::strcpy(p, name);
      while (*p) ++p;
      *p++ = ':';
    }
    // zero-terminate properly
    *--p = 0;
  }
}

//_____________________________________________________________________________
RooArgSet* RooNameSet::select(const RooArgSet& list) const 
{
  // Construct a RooArgSet of objects in input 'list'
  // whose names match to those in the internal name
  // list of RooNameSet

  RooArgSet* output = new RooArgSet;
  if (!_nameList || !std::strlen(_nameList)) return output;

  // need to copy _nameList because std::strtok modifies the string
  char* tmp = 0;
  int dummy = 0;
  strdup(dummy, tmp, _nameList);

  char* token = std::strtok(tmp, ":"); 
  while (token) {
    RooAbsArg* arg = list.find(token);
    if (arg) output->add(*arg);
    token = std::strtok(0, ":");
  }
  delete[] tmp;

  return output;
}

//_____________________________________________________________________________
void RooNameSet::printName(std::ostream& os) const 
{
  // Print name of nameset
  os << GetName();
}

//_____________________________________________________________________________
void RooNameSet::printTitle(std::ostream& os) const 
{
  // Print title of nameset
  os << GetTitle();
}

//_____________________________________________________________________________
void RooNameSet::printClassName(std::ostream& os) const 
{
  // Print class name of nameset
  os << IsA()->GetName();
}

//_____________________________________________________________________________
void RooNameSet::printValue(std::ostream& os) const 
{
  // Print value of nameset, i.e the list of names
  os << content();
}
 RooNameSet.cxx:1
 RooNameSet.cxx:2
 RooNameSet.cxx:3
 RooNameSet.cxx:4
 RooNameSet.cxx:5
 RooNameSet.cxx:6
 RooNameSet.cxx:7
 RooNameSet.cxx:8
 RooNameSet.cxx:9
 RooNameSet.cxx:10
 RooNameSet.cxx:11
 RooNameSet.cxx:12
 RooNameSet.cxx:13
 RooNameSet.cxx:14
 RooNameSet.cxx:15
 RooNameSet.cxx:16
 RooNameSet.cxx:17
 RooNameSet.cxx:18
 RooNameSet.cxx:19
 RooNameSet.cxx:20
 RooNameSet.cxx:21
 RooNameSet.cxx:22
 RooNameSet.cxx:23
 RooNameSet.cxx:24
 RooNameSet.cxx:25
 RooNameSet.cxx:26
 RooNameSet.cxx:27
 RooNameSet.cxx:28
 RooNameSet.cxx:29
 RooNameSet.cxx:30
 RooNameSet.cxx:31
 RooNameSet.cxx:32
 RooNameSet.cxx:33
 RooNameSet.cxx:34
 RooNameSet.cxx:35
 RooNameSet.cxx:36
 RooNameSet.cxx:37
 RooNameSet.cxx:38
 RooNameSet.cxx:39
 RooNameSet.cxx:40
 RooNameSet.cxx:41
 RooNameSet.cxx:42
 RooNameSet.cxx:43
 RooNameSet.cxx:44
 RooNameSet.cxx:45
 RooNameSet.cxx:46
 RooNameSet.cxx:47
 RooNameSet.cxx:48
 RooNameSet.cxx:49
 RooNameSet.cxx:50
 RooNameSet.cxx:51
 RooNameSet.cxx:52
 RooNameSet.cxx:53
 RooNameSet.cxx:54
 RooNameSet.cxx:55
 RooNameSet.cxx:56
 RooNameSet.cxx:57
 RooNameSet.cxx:58
 RooNameSet.cxx:59
 RooNameSet.cxx:60
 RooNameSet.cxx:61
 RooNameSet.cxx:62
 RooNameSet.cxx:63
 RooNameSet.cxx:64
 RooNameSet.cxx:65
 RooNameSet.cxx:66
 RooNameSet.cxx:67
 RooNameSet.cxx:68
 RooNameSet.cxx:69
 RooNameSet.cxx:70
 RooNameSet.cxx:71
 RooNameSet.cxx:72
 RooNameSet.cxx:73
 RooNameSet.cxx:74
 RooNameSet.cxx:75
 RooNameSet.cxx:76
 RooNameSet.cxx:77
 RooNameSet.cxx:78
 RooNameSet.cxx:79
 RooNameSet.cxx:80
 RooNameSet.cxx:81
 RooNameSet.cxx:82
 RooNameSet.cxx:83
 RooNameSet.cxx:84
 RooNameSet.cxx:85
 RooNameSet.cxx:86
 RooNameSet.cxx:87
 RooNameSet.cxx:88
 RooNameSet.cxx:89
 RooNameSet.cxx:90
 RooNameSet.cxx:91
 RooNameSet.cxx:92
 RooNameSet.cxx:93
 RooNameSet.cxx:94
 RooNameSet.cxx:95
 RooNameSet.cxx:96
 RooNameSet.cxx:97
 RooNameSet.cxx:98
 RooNameSet.cxx:99
 RooNameSet.cxx:100
 RooNameSet.cxx:101
 RooNameSet.cxx:102
 RooNameSet.cxx:103
 RooNameSet.cxx:104
 RooNameSet.cxx:105
 RooNameSet.cxx:106
 RooNameSet.cxx:107
 RooNameSet.cxx:108
 RooNameSet.cxx:109
 RooNameSet.cxx:110
 RooNameSet.cxx:111
 RooNameSet.cxx:112
 RooNameSet.cxx:113
 RooNameSet.cxx:114
 RooNameSet.cxx:115
 RooNameSet.cxx:116
 RooNameSet.cxx:117
 RooNameSet.cxx:118
 RooNameSet.cxx:119
 RooNameSet.cxx:120
 RooNameSet.cxx:121
 RooNameSet.cxx:122
 RooNameSet.cxx:123
 RooNameSet.cxx:124
 RooNameSet.cxx:125
 RooNameSet.cxx:126
 RooNameSet.cxx:127
 RooNameSet.cxx:128
 RooNameSet.cxx:129
 RooNameSet.cxx:130
 RooNameSet.cxx:131
 RooNameSet.cxx:132
 RooNameSet.cxx:133
 RooNameSet.cxx:134
 RooNameSet.cxx:135
 RooNameSet.cxx:136
 RooNameSet.cxx:137
 RooNameSet.cxx:138
 RooNameSet.cxx:139
 RooNameSet.cxx:140
 RooNameSet.cxx:141
 RooNameSet.cxx:142
 RooNameSet.cxx:143
 RooNameSet.cxx:144
 RooNameSet.cxx:145
 RooNameSet.cxx:146
 RooNameSet.cxx:147
 RooNameSet.cxx:148
 RooNameSet.cxx:149
 RooNameSet.cxx:150
 RooNameSet.cxx:151
 RooNameSet.cxx:152
 RooNameSet.cxx:153
 RooNameSet.cxx:154
 RooNameSet.cxx:155
 RooNameSet.cxx:156
 RooNameSet.cxx:157
 RooNameSet.cxx:158
 RooNameSet.cxx:159
 RooNameSet.cxx:160
 RooNameSet.cxx:161
 RooNameSet.cxx:162
 RooNameSet.cxx:163
 RooNameSet.cxx:164
 RooNameSet.cxx:165
 RooNameSet.cxx:166
 RooNameSet.cxx:167
 RooNameSet.cxx:168
 RooNameSet.cxx:169
 RooNameSet.cxx:170
 RooNameSet.cxx:171
 RooNameSet.cxx:172
 RooNameSet.cxx:173
 RooNameSet.cxx:174
 RooNameSet.cxx:175
 RooNameSet.cxx:176
 RooNameSet.cxx:177
 RooNameSet.cxx:178
 RooNameSet.cxx:179
 RooNameSet.cxx:180
 RooNameSet.cxx:181
 RooNameSet.cxx:182
 RooNameSet.cxx:183
 RooNameSet.cxx:184
 RooNameSet.cxx:185
 RooNameSet.cxx:186
 RooNameSet.cxx:187
 RooNameSet.cxx:188
 RooNameSet.cxx:189
 RooNameSet.cxx:190
 RooNameSet.cxx:191
 RooNameSet.cxx:192
 RooNameSet.cxx:193
 RooNameSet.cxx:194
 RooNameSet.cxx:195
 RooNameSet.cxx:196
 RooNameSet.cxx:197
 RooNameSet.cxx:198
 RooNameSet.cxx:199
 RooNameSet.cxx:200
 RooNameSet.cxx:201
 RooNameSet.cxx:202
 RooNameSet.cxx:203
 RooNameSet.cxx:204
 RooNameSet.cxx:205
 RooNameSet.cxx:206
 RooNameSet.cxx:207
 RooNameSet.cxx:208
 RooNameSet.cxx:209
 RooNameSet.cxx:210
 RooNameSet.cxx:211
 RooNameSet.cxx:212
 RooNameSet.cxx:213
 RooNameSet.cxx:214
 RooNameSet.cxx:215
 RooNameSet.cxx:216
 RooNameSet.cxx:217
 RooNameSet.cxx:218
 RooNameSet.cxx:219
 RooNameSet.cxx:220
 RooNameSet.cxx:221
 RooNameSet.cxx:222
 RooNameSet.cxx:223
 RooNameSet.cxx:224
 RooNameSet.cxx:225
 RooNameSet.cxx:226