// @(#)root/io:$Id$
// Author: Fons Rademakers   30/6/04

/*************************************************************************
 * 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.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TArchiveFile                                                         //
//                                                                      //
// This is an abstract class that describes an archive file containing  //
// multiple sub-files, like a ZIP or TAR archive.                       //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TArchiveFile.h"
#include "TPluginManager.h"
#include "TROOT.h"
#include "TObjArray.h"
#include "TObjString.h"
#include "TError.h"
#include "TUrl.h"
#include <stdlib.h>


ClassImp(TArchiveFile)

//______________________________________________________________________________
TArchiveFile::TArchiveFile(const char *archive, const char *member, TFile *file)
{
   // Specify the archive name and member name. The member can be a decimal
   // number which allows to access the n-th sub-file. This method is
   // normally only called via TFile.

   if (!file)
      Error("TArchiveFile", "must specify a valid TFile");

   fFile        = file;
   fArchiveName = archive;
   fMemberName  = member;
   fMemberIndex = -1;
   if (fMemberName.IsDigit())
      fMemberIndex = atoi(fMemberName);
   fMembers     = new TObjArray;
   fMembers->SetOwner();
   fCurMember   = 0;
}

//______________________________________________________________________________
TArchiveFile::~TArchiveFile()
{
   // Dtor.

   delete fMembers;
}

//______________________________________________________________________________
Long64_t TArchiveFile::GetMemberFilePosition() const
{
   // Return position in archive of current member.

   return fCurMember ? fCurMember->GetFilePosition() : 0;
}

//______________________________________________________________________________
Int_t TArchiveFile::GetNumberOfMembers() const
{
   // Returns number of members in archive.

   return fMembers->GetEntriesFast();
}

//______________________________________________________________________________
Int_t TArchiveFile::SetMember(const char *member)
{
   // Explicitely make the specified member the current member.
   // Returns -1 in case of error, 0 otherwise.

   fMemberName  = member;
   fMemberIndex = -1;

   return SetCurrentMember();
}

//______________________________________________________________________________
Int_t TArchiveFile::SetMember(Int_t idx)
{
   // Explicitely make the member with the specified index the current member.
   // Returns -1 in case of error, 0 otherwise.

   fMemberName  = "";
   fMemberIndex = idx;

   return SetCurrentMember();
}

//______________________________________________________________________________
TArchiveFile *TArchiveFile::Open(const char *url, TFile *file)
{
   // Return proper archive file handler depending on passed url.
   // The handler is loaded via the plugin manager and is triggered by
   // the extension of the archive file. In case no handler is found 0
   // is returned. The file argument is used to access the archive.
   // The archive should be specified as url with the member name as the
   // anchor, e.g. "root://pcsalo.cern.ch/alice/event_1.zip#tpc.root",
   // where tpc.root is the file in the archive to be opened.
   // Alternatively the sub-file can be specified via its index number,
   // e.g. "root://pcsalo.cern.ch/alice/event_1.zip#3".
   // This function is normally only called via TFile::Open().

   if (!file) {
      ::Error("TArchiveFile::Open", "must specify a valid TFile to access %s",
              url);
      return 0;
   }

   TString archive, member, type;

   if (!ParseUrl(url, archive, member, type))
      return 0;

   TArchiveFile *f = 0;
   TPluginHandler *h;
   if ((h = gROOT->GetPluginManager()->FindHandler("TArchiveFile", type))) {
      if (h->LoadPlugin() == -1)
         return 0;
      f = (TArchiveFile*) h->ExecPlugin(3, archive.Data(), member.Data(), file);
   }

   return f;
}

//______________________________________________________________________________
Bool_t TArchiveFile::ParseUrl(const char *url, TString &archive, TString &member,
                              TString &type)
{
   // Try to determine if url contains an anchor specifying an archive member.
   // Returns kFALSE in case of an error.

   TUrl u(url, kTRUE);

   archive = "";
   member  = "";
   type    = "";

   // get the options and see, if the archive was specified by an option
   // FIXME: hard coded for "zip" archive format
   TString urloptions = u.GetOptions();
   TObjArray *objOptions = urloptions.Tokenize("&");
   for (Int_t n = 0; n < objOptions->GetEntries(); n++) {

      TString loption = ((TObjString*)objOptions->At(n))->GetName();
      TObjArray *objTags = loption.Tokenize("=");
      if (objTags->GetEntries() == 2) {

         TString key   = ((TObjString*)objTags->At(0))->GetName();
         TString value = ((TObjString*)objTags->At(1))->GetName();

         if (!key.CompareTo("zip", TString::kIgnoreCase)) {
            archive = u.GetFile();
            member = value;
            type = "dummy.zip";
         }
      }
      delete objTags;
   }
   delete objOptions;

   if (member != "") {
      // member set by an option
      return kTRUE;
   }

   if (!strlen(u.GetAnchor())) {
      archive = u.GetFile();
      type    = archive;
      return kTRUE;
   }

   archive = u.GetFile();
   member  = u.GetAnchor();
   type    = archive;

   if (archive == "" || member == "") {
      archive = "";
      member  = "";
      type    = "";
      return kFALSE;
   }
   return kTRUE;
}


ClassImp(TArchiveMember)

//______________________________________________________________________________
TArchiveMember::TArchiveMember()
{
   // Default ctor.

   fName         = "";
   fComment      = "";
   fPosition     = 0;
   fFilePosition = 0;
   fCsize        = 0;
   fDsize        = 0;
   fDirectory    = kFALSE;
}

//______________________________________________________________________________
TArchiveMember::TArchiveMember(const char *name)
{
   // Create an archive member file.

   fName         = name;
   fComment      = "";
   fPosition     = 0;
   fFilePosition = 0;
   fCsize        = 0;
   fDsize        = 0;
   fDirectory    = kFALSE;
}

//______________________________________________________________________________
TArchiveMember::TArchiveMember(const TArchiveMember &member)
   : TObject(member)
{
   // Copy ctor.

   fName         = member.fName;
   fComment      = member.fComment;
   fModTime      = member.fModTime;
   fPosition     = member.fPosition;
   fFilePosition = member.fFilePosition;
   fCsize        = member.fCsize;
   fDsize        = member.fDsize;
   fDirectory    = member.fDirectory;
}

//______________________________________________________________________________
TArchiveMember &TArchiveMember::operator=(const TArchiveMember &rhs)
{
   // Assignment operator.

   if (this != &rhs) {
      TObject::operator=(rhs);
      fName         = rhs.fName;
      fComment      = rhs.fComment;
      fModTime      = rhs.fModTime;
      fPosition     = rhs.fPosition;
      fFilePosition = rhs.fFilePosition;
      fCsize        = rhs.fCsize;
      fDsize        = rhs.fDsize;
      fDirectory    = rhs.fDirectory;
   }
   return *this;
}
 TArchiveFile.cxx:1
 TArchiveFile.cxx:2
 TArchiveFile.cxx:3
 TArchiveFile.cxx:4
 TArchiveFile.cxx:5
 TArchiveFile.cxx:6
 TArchiveFile.cxx:7
 TArchiveFile.cxx:8
 TArchiveFile.cxx:9
 TArchiveFile.cxx:10
 TArchiveFile.cxx:11
 TArchiveFile.cxx:12
 TArchiveFile.cxx:13
 TArchiveFile.cxx:14
 TArchiveFile.cxx:15
 TArchiveFile.cxx:16
 TArchiveFile.cxx:17
 TArchiveFile.cxx:18
 TArchiveFile.cxx:19
 TArchiveFile.cxx:20
 TArchiveFile.cxx:21
 TArchiveFile.cxx:22
 TArchiveFile.cxx:23
 TArchiveFile.cxx:24
 TArchiveFile.cxx:25
 TArchiveFile.cxx:26
 TArchiveFile.cxx:27
 TArchiveFile.cxx:28
 TArchiveFile.cxx:29
 TArchiveFile.cxx:30
 TArchiveFile.cxx:31
 TArchiveFile.cxx:32
 TArchiveFile.cxx:33
 TArchiveFile.cxx:34
 TArchiveFile.cxx:35
 TArchiveFile.cxx:36
 TArchiveFile.cxx:37
 TArchiveFile.cxx:38
 TArchiveFile.cxx:39
 TArchiveFile.cxx:40
 TArchiveFile.cxx:41
 TArchiveFile.cxx:42
 TArchiveFile.cxx:43
 TArchiveFile.cxx:44
 TArchiveFile.cxx:45
 TArchiveFile.cxx:46
 TArchiveFile.cxx:47
 TArchiveFile.cxx:48
 TArchiveFile.cxx:49
 TArchiveFile.cxx:50
 TArchiveFile.cxx:51
 TArchiveFile.cxx:52
 TArchiveFile.cxx:53
 TArchiveFile.cxx:54
 TArchiveFile.cxx:55
 TArchiveFile.cxx:56
 TArchiveFile.cxx:57
 TArchiveFile.cxx:58
 TArchiveFile.cxx:59
 TArchiveFile.cxx:60
 TArchiveFile.cxx:61
 TArchiveFile.cxx:62
 TArchiveFile.cxx:63
 TArchiveFile.cxx:64
 TArchiveFile.cxx:65
 TArchiveFile.cxx:66
 TArchiveFile.cxx:67
 TArchiveFile.cxx:68
 TArchiveFile.cxx:69
 TArchiveFile.cxx:70
 TArchiveFile.cxx:71
 TArchiveFile.cxx:72
 TArchiveFile.cxx:73
 TArchiveFile.cxx:74
 TArchiveFile.cxx:75
 TArchiveFile.cxx:76
 TArchiveFile.cxx:77
 TArchiveFile.cxx:78
 TArchiveFile.cxx:79
 TArchiveFile.cxx:80
 TArchiveFile.cxx:81
 TArchiveFile.cxx:82
 TArchiveFile.cxx:83
 TArchiveFile.cxx:84
 TArchiveFile.cxx:85
 TArchiveFile.cxx:86
 TArchiveFile.cxx:87
 TArchiveFile.cxx:88
 TArchiveFile.cxx:89
 TArchiveFile.cxx:90
 TArchiveFile.cxx:91
 TArchiveFile.cxx:92
 TArchiveFile.cxx:93
 TArchiveFile.cxx:94
 TArchiveFile.cxx:95
 TArchiveFile.cxx:96
 TArchiveFile.cxx:97
 TArchiveFile.cxx:98
 TArchiveFile.cxx:99
 TArchiveFile.cxx:100
 TArchiveFile.cxx:101
 TArchiveFile.cxx:102
 TArchiveFile.cxx:103
 TArchiveFile.cxx:104
 TArchiveFile.cxx:105
 TArchiveFile.cxx:106
 TArchiveFile.cxx:107
 TArchiveFile.cxx:108
 TArchiveFile.cxx:109
 TArchiveFile.cxx:110
 TArchiveFile.cxx:111
 TArchiveFile.cxx:112
 TArchiveFile.cxx:113
 TArchiveFile.cxx:114
 TArchiveFile.cxx:115
 TArchiveFile.cxx:116
 TArchiveFile.cxx:117
 TArchiveFile.cxx:118
 TArchiveFile.cxx:119
 TArchiveFile.cxx:120
 TArchiveFile.cxx:121
 TArchiveFile.cxx:122
 TArchiveFile.cxx:123
 TArchiveFile.cxx:124
 TArchiveFile.cxx:125
 TArchiveFile.cxx:126
 TArchiveFile.cxx:127
 TArchiveFile.cxx:128
 TArchiveFile.cxx:129
 TArchiveFile.cxx:130
 TArchiveFile.cxx:131
 TArchiveFile.cxx:132
 TArchiveFile.cxx:133
 TArchiveFile.cxx:134
 TArchiveFile.cxx:135
 TArchiveFile.cxx:136
 TArchiveFile.cxx:137
 TArchiveFile.cxx:138
 TArchiveFile.cxx:139
 TArchiveFile.cxx:140
 TArchiveFile.cxx:141
 TArchiveFile.cxx:142
 TArchiveFile.cxx:143
 TArchiveFile.cxx:144
 TArchiveFile.cxx:145
 TArchiveFile.cxx:146
 TArchiveFile.cxx:147
 TArchiveFile.cxx:148
 TArchiveFile.cxx:149
 TArchiveFile.cxx:150
 TArchiveFile.cxx:151
 TArchiveFile.cxx:152
 TArchiveFile.cxx:153
 TArchiveFile.cxx:154
 TArchiveFile.cxx:155
 TArchiveFile.cxx:156
 TArchiveFile.cxx:157
 TArchiveFile.cxx:158
 TArchiveFile.cxx:159
 TArchiveFile.cxx:160
 TArchiveFile.cxx:161
 TArchiveFile.cxx:162
 TArchiveFile.cxx:163
 TArchiveFile.cxx:164
 TArchiveFile.cxx:165
 TArchiveFile.cxx:166
 TArchiveFile.cxx:167
 TArchiveFile.cxx:168
 TArchiveFile.cxx:169
 TArchiveFile.cxx:170
 TArchiveFile.cxx:171
 TArchiveFile.cxx:172
 TArchiveFile.cxx:173
 TArchiveFile.cxx:174
 TArchiveFile.cxx:175
 TArchiveFile.cxx:176
 TArchiveFile.cxx:177
 TArchiveFile.cxx:178
 TArchiveFile.cxx:179
 TArchiveFile.cxx:180
 TArchiveFile.cxx:181
 TArchiveFile.cxx:182
 TArchiveFile.cxx:183
 TArchiveFile.cxx:184
 TArchiveFile.cxx:185
 TArchiveFile.cxx:186
 TArchiveFile.cxx:187
 TArchiveFile.cxx:188
 TArchiveFile.cxx:189
 TArchiveFile.cxx:190
 TArchiveFile.cxx:191
 TArchiveFile.cxx:192
 TArchiveFile.cxx:193
 TArchiveFile.cxx:194
 TArchiveFile.cxx:195
 TArchiveFile.cxx:196
 TArchiveFile.cxx:197
 TArchiveFile.cxx:198
 TArchiveFile.cxx:199
 TArchiveFile.cxx:200
 TArchiveFile.cxx:201
 TArchiveFile.cxx:202
 TArchiveFile.cxx:203
 TArchiveFile.cxx:204
 TArchiveFile.cxx:205
 TArchiveFile.cxx:206
 TArchiveFile.cxx:207
 TArchiveFile.cxx:208
 TArchiveFile.cxx:209
 TArchiveFile.cxx:210
 TArchiveFile.cxx:211
 TArchiveFile.cxx:212
 TArchiveFile.cxx:213
 TArchiveFile.cxx:214
 TArchiveFile.cxx:215
 TArchiveFile.cxx:216
 TArchiveFile.cxx:217
 TArchiveFile.cxx:218
 TArchiveFile.cxx:219
 TArchiveFile.cxx:220
 TArchiveFile.cxx:221
 TArchiveFile.cxx:222
 TArchiveFile.cxx:223
 TArchiveFile.cxx:224
 TArchiveFile.cxx:225
 TArchiveFile.cxx:226
 TArchiveFile.cxx:227
 TArchiveFile.cxx:228
 TArchiveFile.cxx:229
 TArchiveFile.cxx:230
 TArchiveFile.cxx:231
 TArchiveFile.cxx:232
 TArchiveFile.cxx:233
 TArchiveFile.cxx:234
 TArchiveFile.cxx:235
 TArchiveFile.cxx:236
 TArchiveFile.cxx:237
 TArchiveFile.cxx:238
 TArchiveFile.cxx:239
 TArchiveFile.cxx:240
 TArchiveFile.cxx:241
 TArchiveFile.cxx:242
 TArchiveFile.cxx:243
 TArchiveFile.cxx:244
 TArchiveFile.cxx:245
 TArchiveFile.cxx:246
 TArchiveFile.cxx:247
 TArchiveFile.cxx:248
 TArchiveFile.cxx:249
 TArchiveFile.cxx:250
 TArchiveFile.cxx:251
 TArchiveFile.cxx:252
 TArchiveFile.cxx:253
 TArchiveFile.cxx:254
 TArchiveFile.cxx:255
 TArchiveFile.cxx:256
 TArchiveFile.cxx:257
 TArchiveFile.cxx:258
 TArchiveFile.cxx:259
 TArchiveFile.cxx:260
 TArchiveFile.cxx:261
 TArchiveFile.cxx:262