// @(#)root/io:$Id$
// Author: Philippe Canal 05/2010

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

#ifndef ROOT_TStreamerInfoActions
#define ROOT_TStreamerInfoActions

#include <vector>

#include "TStreamerInfo.h"
#include <assert.h>

namespace TStreamerInfoActions {

   class TConfiguration {
      // Base class of the Configurations.
   protected:
   public:
      typedef TStreamerInfo::TCompInfo_t TCompInfo_t;
      TVirtualStreamerInfo *fInfo;    // TStreamerInfo form which the action is derived
      UInt_t                fElemId;  // Identifier of the TStreamerElement
      TCompInfo_t          *fCompInfo;// Access to compiled information (for legacy code)
      Int_t                 fOffset;  // Offset within the object
      UInt_t                fLength;  // Number of element in a fixed length array.
   public:
      TConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset) : fInfo(info), fElemId(id), fCompInfo(compinfo), fOffset(offset),fLength(1) {};
      TConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length) : fInfo(info), fElemId(id), fCompInfo(compinfo), fOffset(offset),fLength(length) {};
      virtual ~TConfiguration() {};

      virtual void AddToOffset(Int_t delta);

      virtual TConfiguration *Copy() { return new TConfiguration(*this); }

      virtual void Print() const;
      virtual void PrintDebug(TBuffer &buffer, void *object) const;
   };

   class TLoopConfiguration {
      // Base class of the Configurations for the member wise looping routines.
   public:
      TLoopConfiguration() {};
      // virtual void PrintDebug(TBuffer &buffer, void *object) const;
      virtual ~TLoopConfiguration() {};
      virtual void Print() const;
      virtual void *GetFirstAddress(void *start, const void *end) const = 0;
      virtual TLoopConfiguration* Copy() = 0; // { return new TLoopConfiguration(*this); }
   };

   typedef TVirtualCollectionProxy::Next_t Next_t;

   typedef Int_t (*TStreamerInfoAction_t)(TBuffer &buf, void *obj, const TConfiguration *conf);
   typedef Int_t (*TStreamerInfoVecPtrLoopAction_t)(TBuffer &buf, void *iter, const void *end, const TConfiguration *conf);
   typedef Int_t (*TStreamerInfoLoopAction_t)(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf);

   class TConfiguredAction : public TObject {
   public:
      union {
         TStreamerInfoAction_t           fAction;
         TStreamerInfoVecPtrLoopAction_t fVecPtrLoopAction;
         TStreamerInfoLoopAction_t       fLoopAction;
      };
      TConfiguration              *fConfiguration;
   private:
      // assignment operator must be the default because the 'copy' constructor is actually a move constructor and must be used.
   public:
      TConfiguredAction() : fAction(0), fConfiguration(0) {}
      TConfiguredAction(const TConfiguredAction &rval) : TObject(rval), fAction(rval.fAction), fConfiguration(rval.fConfiguration)
      {
         // WARNING: Technically this is a move constructor ...
         const_cast<TConfiguredAction&>(rval).fConfiguration = 0;
      }
      TConfiguredAction &operator=(const TConfiguredAction &rval)
      {
         // WARNING: Technically this is a move assignment!.

         TConfiguredAction tmp(rval); // this does a move.
         TObject::operator=(tmp);     // we are missing TObject::Swap
         std::swap(fAction,tmp.fAction);
         std::swap(fConfiguration,tmp.fConfiguration);
         return *this;
      };

      TConfiguredAction(TStreamerInfoAction_t action, TConfiguration *conf) : fAction(action), fConfiguration(conf)
      {
         // Usual constructor.
      }
      TConfiguredAction(TStreamerInfoVecPtrLoopAction_t action, TConfiguration *conf) : fVecPtrLoopAction(action), fConfiguration(conf)
      {
         // Usual constructor.
      }
      TConfiguredAction(TStreamerInfoLoopAction_t action, TConfiguration *conf) : fLoopAction(action), fConfiguration(conf)
      {
         // Usual constructor.
      }
      ~TConfiguredAction() {
         // Usual destructor.
         // Idea: the configuration ownership might be moved to a single list so that
         // we can shared them between the optimized and non-optimized list of actions.
         delete fConfiguration;
      }
      void PrintDebug(TBuffer &buffer, void *object) const;

      inline Int_t operator()(TBuffer &buffer, void *object) const {
         return fAction(buffer, object, fConfiguration);
      }

      inline Int_t operator()(TBuffer &buffer, void *start_collection, const void *end_collection) const {
         return fVecPtrLoopAction(buffer, start_collection, end_collection, fConfiguration);
      }

      inline Int_t operator()(TBuffer &buffer, void *start_collection, const void *end_collection, const TLoopConfiguration *loopconf) const {
         return fLoopAction(buffer, start_collection, end_collection, loopconf, fConfiguration);
      }

      ClassDef(TConfiguredAction,0); // A configured action
   };

   typedef std::vector<TConfiguredAction> ActionContainer_t;
   class TActionSequence : public TObject {
      TActionSequence() {};
   public:
      TActionSequence(TVirtualStreamerInfo *info, UInt_t maxdata) : fStreamerInfo(info), fLoopConfig(0) { fActions.reserve(maxdata); };
      ~TActionSequence() {
         delete fLoopConfig;
      }

      template <typename action_t>
      void AddAction( action_t action, TConfiguration *conf ) {
         fActions.push_back( TConfiguredAction(action, conf) );
      }
      void AddAction(const TConfiguredAction &action ) {
         fActions.push_back( action );
      }

      TVirtualStreamerInfo *fStreamerInfo; // StreamerInfo used to derive these actions.
      TLoopConfiguration   *fLoopConfig;   // If this is a bundle of memberwise streaming action, this configures the looping
      ActionContainer_t     fActions;

      void AddToOffset(Int_t delta);

      TActionSequence *CreateCopy();
      static TActionSequence *CreateReadMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy);
      static TActionSequence *CreateWriteMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy);
      TActionSequence *CreateSubSequence(const std::vector<Int_t> &element_ids, size_t offset);

      void Print(Option_t * = "") const;

      ClassDef(TActionSequence,0);
   };

}

#endif // ROOT_TStreamerInfoActions


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