// @(#)root/io:$Id$
// Author: Markus Frank 28/10/04

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGenCollectionProxy
//
// Proxy around an arbitrary container, which implements basic
// functionality and iteration. The purpose of this implementation
// is to shield any generated dictionary implementation from the
// underlying streamer/proxy implementation and only expose
// the creation functions.
//
// In particular this is used to implement splitting and abstract
// element access of any container. Access to compiled code is necessary
// to implement the abstract iteration sequence and functionality like
// size(), clear(), resize(). resize() may be a void operation.
//
//////////////////////////////////////////////////////////////////////////

#include "TError.h"
#include "TClassEdit.h"
#include "TCollectionProxyFactory.h"
#include "TGenCollectionProxy.h"
#include "TGenCollectionStreamer.h"

#include "TEmulatedMapProxy.h"
#include "TEmulatedCollectionProxy.h"

// Do not clutter global namespace with shit....
namespace {
   static ROOT::ESTLType stl_type(const std::string& class_name)  {
      // return the STL type.
      int nested = 0;
      std::vector<std::string> inside;
      int num = TClassEdit::GetSplit(class_name.c_str(),inside,nested);
      if ( num > 1 )  {
         return (ROOT::ESTLType)TClassEdit::STLKind(inside[0].c_str());
      }
      return ROOT::kNotSTL;
   }

   static TEmulatedCollectionProxy* GenEmulation(const char* class_name, Bool_t silent)  {
      // Generate an emulated collection proxy.

      if ( class_name )  {
         std::string cl = class_name;
         if ( cl.find("stdext::hash_") != std::string::npos )
            cl.replace(3,10,"::");
         if ( cl.find("__gnu_cxx::hash_") != std::string::npos )
            cl.replace(0,16,"std::");
         TEmulatedCollectionProxy * result = 0;
         switch ( stl_type(cl) )  {
            case ROOT::kNotSTL:
               return 0;
            case ROOT::kSTLmap:
            case ROOT::kSTLmultimap:
               result = new TEmulatedMapProxy(class_name,silent);
               break;
            default:
               result = new TEmulatedCollectionProxy(class_name,silent);
         }
         if ( result->IsValid() ) {
            return result;
         }
      }
      return 0;
   }
}

TVirtualCollectionProxy*
TCollectionProxyFactory::GenEmulatedProxy(const char* class_name, Bool_t silent)
{
   // Generate emulated collection proxy for a given class.

   return GenEmulation(class_name, silent);
}

TClassStreamer*
TCollectionProxyFactory::GenEmulatedClassStreamer(const char* class_name, Bool_t silent)
{
   // Generate emulated class streamer for a given collection class.

   TCollectionClassStreamer* s = new TCollectionClassStreamer();
   s->AdoptStreamer(GenEmulation(class_name, silent));
   return s;
}

TMemberStreamer*
TCollectionProxyFactory::GenEmulatedMemberStreamer(const char* class_name, Bool_t silent)
{
   // Generate emulated member streamer for a given collection class.
   TCollectionMemberStreamer* s = new TCollectionMemberStreamer();
   s->AdoptStreamer(GenEmulation(class_name, silent));
   return s;
}

TCollectionProxyFactory::Proxy_t*
TCollectionProxyFactory::GenExplicitProxy( const ::ROOT::TCollectionProxyInfo &info, TClass *cl)
{
   // Generate proxy from static functions.
   return new TGenCollectionProxy(info,cl);
}

TGenCollectionStreamer*
TCollectionProxyFactory::GenExplicitStreamer( const ::ROOT::TCollectionProxyInfo &info, TClass *cl )
{
   // Generate streamer from static functions.
   TGenCollectionStreamer* ptr = new TGenCollectionStreamer(info,cl);
   return ptr;
}

TClassStreamer*
TCollectionProxyFactory::GenExplicitClassStreamer( const ::ROOT::TCollectionProxyInfo &info, TClass *cl )
{
   // Generate class streamer from static functions.
   TCollectionClassStreamer* s = new TCollectionClassStreamer();
   s->AdoptStreamer(GenExplicitStreamer(info,cl));
   return s;
}

TMemberStreamer*
TCollectionProxyFactory::GenExplicitMemberStreamer( const ::ROOT::TCollectionProxyInfo &info, TClass *cl)
{
   // Generate member streamer from static functions.
   TCollectionMemberStreamer* s = new TCollectionMemberStreamer();
   s->AdoptStreamer(GenExplicitStreamer(info,cl));
   return s;
}

void TCollectionStreamer::InvalidProxyError()   {
   // Issue Error about invalid proxy.
   Fatal("TCollectionStreamer>","No proxy available. Data streaming impossible.");
}

TCollectionStreamer::TCollectionStreamer() : fStreamer(0)
{
   // Initializing constructor.
}

TCollectionStreamer::TCollectionStreamer(const TCollectionStreamer& c) : fStreamer(0)
{
   // Copy constructor.
   if ( c.fStreamer )  {
      fStreamer = dynamic_cast<TGenCollectionProxy*>(c.fStreamer->Generate());
      R__ASSERT(fStreamer != 0);
      return;
   }
   InvalidProxyError();
}

TCollectionStreamer::~TCollectionStreamer()
{
   // Standard destructor.
   if ( fStreamer )  {
      delete fStreamer;
   }
}

void TCollectionStreamer::AdoptStreamer(TGenCollectionProxy* streamer)
{
   // Attach worker proxy.
   if ( fStreamer )  {
      delete fStreamer;
   }
   fStreamer = streamer;
}

void TCollectionStreamer::Streamer(TBuffer &buff, void *pObj, int /* siz */, TClass* onFileClass )
{
   // Streamer for I/O handling.
   if ( fStreamer )  {
      TVirtualCollectionProxy::TPushPop env(fStreamer, pObj);
      fStreamer->SetOnFileClass( onFileClass );
      fStreamer->Streamer(buff);

      return;
   }
   InvalidProxyError();
}
 TCollectionProxyFactory.cxx:1
 TCollectionProxyFactory.cxx:2
 TCollectionProxyFactory.cxx:3
 TCollectionProxyFactory.cxx:4
 TCollectionProxyFactory.cxx:5
 TCollectionProxyFactory.cxx:6
 TCollectionProxyFactory.cxx:7
 TCollectionProxyFactory.cxx:8
 TCollectionProxyFactory.cxx:9
 TCollectionProxyFactory.cxx:10
 TCollectionProxyFactory.cxx:11
 TCollectionProxyFactory.cxx:12
 TCollectionProxyFactory.cxx:13
 TCollectionProxyFactory.cxx:14
 TCollectionProxyFactory.cxx:15
 TCollectionProxyFactory.cxx:16
 TCollectionProxyFactory.cxx:17
 TCollectionProxyFactory.cxx:18
 TCollectionProxyFactory.cxx:19
 TCollectionProxyFactory.cxx:20
 TCollectionProxyFactory.cxx:21
 TCollectionProxyFactory.cxx:22
 TCollectionProxyFactory.cxx:23
 TCollectionProxyFactory.cxx:24
 TCollectionProxyFactory.cxx:25
 TCollectionProxyFactory.cxx:26
 TCollectionProxyFactory.cxx:27
 TCollectionProxyFactory.cxx:28
 TCollectionProxyFactory.cxx:29
 TCollectionProxyFactory.cxx:30
 TCollectionProxyFactory.cxx:31
 TCollectionProxyFactory.cxx:32
 TCollectionProxyFactory.cxx:33
 TCollectionProxyFactory.cxx:34
 TCollectionProxyFactory.cxx:35
 TCollectionProxyFactory.cxx:36
 TCollectionProxyFactory.cxx:37
 TCollectionProxyFactory.cxx:38
 TCollectionProxyFactory.cxx:39
 TCollectionProxyFactory.cxx:40
 TCollectionProxyFactory.cxx:41
 TCollectionProxyFactory.cxx:42
 TCollectionProxyFactory.cxx:43
 TCollectionProxyFactory.cxx:44
 TCollectionProxyFactory.cxx:45
 TCollectionProxyFactory.cxx:46
 TCollectionProxyFactory.cxx:47
 TCollectionProxyFactory.cxx:48
 TCollectionProxyFactory.cxx:49
 TCollectionProxyFactory.cxx:50
 TCollectionProxyFactory.cxx:51
 TCollectionProxyFactory.cxx:52
 TCollectionProxyFactory.cxx:53
 TCollectionProxyFactory.cxx:54
 TCollectionProxyFactory.cxx:55
 TCollectionProxyFactory.cxx:56
 TCollectionProxyFactory.cxx:57
 TCollectionProxyFactory.cxx:58
 TCollectionProxyFactory.cxx:59
 TCollectionProxyFactory.cxx:60
 TCollectionProxyFactory.cxx:61
 TCollectionProxyFactory.cxx:62
 TCollectionProxyFactory.cxx:63
 TCollectionProxyFactory.cxx:64
 TCollectionProxyFactory.cxx:65
 TCollectionProxyFactory.cxx:66
 TCollectionProxyFactory.cxx:67
 TCollectionProxyFactory.cxx:68
 TCollectionProxyFactory.cxx:69
 TCollectionProxyFactory.cxx:70
 TCollectionProxyFactory.cxx:71
 TCollectionProxyFactory.cxx:72
 TCollectionProxyFactory.cxx:73
 TCollectionProxyFactory.cxx:74
 TCollectionProxyFactory.cxx:75
 TCollectionProxyFactory.cxx:76
 TCollectionProxyFactory.cxx:77
 TCollectionProxyFactory.cxx:78
 TCollectionProxyFactory.cxx:79
 TCollectionProxyFactory.cxx:80
 TCollectionProxyFactory.cxx:81
 TCollectionProxyFactory.cxx:82
 TCollectionProxyFactory.cxx:83
 TCollectionProxyFactory.cxx:84
 TCollectionProxyFactory.cxx:85
 TCollectionProxyFactory.cxx:86
 TCollectionProxyFactory.cxx:87
 TCollectionProxyFactory.cxx:88
 TCollectionProxyFactory.cxx:89
 TCollectionProxyFactory.cxx:90
 TCollectionProxyFactory.cxx:91
 TCollectionProxyFactory.cxx:92
 TCollectionProxyFactory.cxx:93
 TCollectionProxyFactory.cxx:94
 TCollectionProxyFactory.cxx:95
 TCollectionProxyFactory.cxx:96
 TCollectionProxyFactory.cxx:97
 TCollectionProxyFactory.cxx:98
 TCollectionProxyFactory.cxx:99
 TCollectionProxyFactory.cxx:100
 TCollectionProxyFactory.cxx:101
 TCollectionProxyFactory.cxx:102
 TCollectionProxyFactory.cxx:103
 TCollectionProxyFactory.cxx:104
 TCollectionProxyFactory.cxx:105
 TCollectionProxyFactory.cxx:106
 TCollectionProxyFactory.cxx:107
 TCollectionProxyFactory.cxx:108
 TCollectionProxyFactory.cxx:109
 TCollectionProxyFactory.cxx:110
 TCollectionProxyFactory.cxx:111
 TCollectionProxyFactory.cxx:112
 TCollectionProxyFactory.cxx:113
 TCollectionProxyFactory.cxx:114
 TCollectionProxyFactory.cxx:115
 TCollectionProxyFactory.cxx:116
 TCollectionProxyFactory.cxx:117
 TCollectionProxyFactory.cxx:118
 TCollectionProxyFactory.cxx:119
 TCollectionProxyFactory.cxx:120
 TCollectionProxyFactory.cxx:121
 TCollectionProxyFactory.cxx:122
 TCollectionProxyFactory.cxx:123
 TCollectionProxyFactory.cxx:124
 TCollectionProxyFactory.cxx:125
 TCollectionProxyFactory.cxx:126
 TCollectionProxyFactory.cxx:127
 TCollectionProxyFactory.cxx:128
 TCollectionProxyFactory.cxx:129
 TCollectionProxyFactory.cxx:130
 TCollectionProxyFactory.cxx:131
 TCollectionProxyFactory.cxx:132
 TCollectionProxyFactory.cxx:133
 TCollectionProxyFactory.cxx:134
 TCollectionProxyFactory.cxx:135
 TCollectionProxyFactory.cxx:136
 TCollectionProxyFactory.cxx:137
 TCollectionProxyFactory.cxx:138
 TCollectionProxyFactory.cxx:139
 TCollectionProxyFactory.cxx:140
 TCollectionProxyFactory.cxx:141
 TCollectionProxyFactory.cxx:142
 TCollectionProxyFactory.cxx:143
 TCollectionProxyFactory.cxx:144
 TCollectionProxyFactory.cxx:145
 TCollectionProxyFactory.cxx:146
 TCollectionProxyFactory.cxx:147
 TCollectionProxyFactory.cxx:148
 TCollectionProxyFactory.cxx:149
 TCollectionProxyFactory.cxx:150
 TCollectionProxyFactory.cxx:151
 TCollectionProxyFactory.cxx:152
 TCollectionProxyFactory.cxx:153
 TCollectionProxyFactory.cxx:154
 TCollectionProxyFactory.cxx:155
 TCollectionProxyFactory.cxx:156
 TCollectionProxyFactory.cxx:157
 TCollectionProxyFactory.cxx:158
 TCollectionProxyFactory.cxx:159
 TCollectionProxyFactory.cxx:160
 TCollectionProxyFactory.cxx:161
 TCollectionProxyFactory.cxx:162
 TCollectionProxyFactory.cxx:163
 TCollectionProxyFactory.cxx:164
 TCollectionProxyFactory.cxx:165
 TCollectionProxyFactory.cxx:166
 TCollectionProxyFactory.cxx:167
 TCollectionProxyFactory.cxx:168
 TCollectionProxyFactory.cxx:169
 TCollectionProxyFactory.cxx:170
 TCollectionProxyFactory.cxx:171
 TCollectionProxyFactory.cxx:172
 TCollectionProxyFactory.cxx:173
 TCollectionProxyFactory.cxx:174
 TCollectionProxyFactory.cxx:175
 TCollectionProxyFactory.cxx:176
 TCollectionProxyFactory.cxx:177
 TCollectionProxyFactory.cxx:178
 TCollectionProxyFactory.cxx:179
 TCollectionProxyFactory.cxx:180
 TCollectionProxyFactory.cxx:181
 TCollectionProxyFactory.cxx:182
 TCollectionProxyFactory.cxx:183
 TCollectionProxyFactory.cxx:184
 TCollectionProxyFactory.cxx:185
 TCollectionProxyFactory.cxx:186
 TCollectionProxyFactory.cxx:187
 TCollectionProxyFactory.cxx:188