626b62dc6020e5cb0ef3432810e7062d3b1d51e3
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTDataInflaterHuffman.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 //*                  for The ALICE HLT Project.                            *
9 //*                                                                        *
10 //* Permission to use, copy, modify and distribute this software and its   *
11 //* documentation strictly for non-commercial purposes is hereby granted   *
12 //* without fee, provided that the above copyright notice appears in all   *
13 //* copies and that both the copyright notice and this permission notice   *
14 //* appear in the supporting documentation. The authors make no claims     *
15 //* about the suitability of this software for any purpose. It is          *
16 //* provided "as is" without express or implied warranty.                  *
17 //**************************************************************************
18
19 /// @file   AliHLTDataInflaterHuffman.cxx
20 /// @author Matthias Richter
21 /// @date   2011-09-01
22 /// @brief  Data inflater implementation for huffman encoded data
23 /// @note   
24
25 #include "AliHLTDataInflaterHuffman.h"
26 #include "AliHLTHuffman.h"
27 #include "TList.h"
28
29 /** ROOT macro for the implementation of ROOT specific class methods */
30 ClassImp(AliHLTDataInflaterHuffman)
31
32 AliHLTDataInflaterHuffman::AliHLTDataInflaterHuffman()
33   : AliHLTDataInflater()
34   , fHuffmanCoders()
35   , fHuffmanCoderList(NULL)
36   , fCurrentParameter(-1)
37   , fLegacyMode(-1)
38   , fInput(0)
39   , fInputLength(0)
40 {
41   // see header file for class documentation
42   // or
43   // refer to README to build package
44   // or
45   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
46 }
47
48 AliHLTDataInflaterHuffman::~AliHLTDataInflaterHuffman()
49 {
50   // destructor
51   if (fHuffmanCoderList) delete fHuffmanCoderList;
52   fHuffmanCoderList=NULL;
53 }
54
55 int AliHLTDataInflaterHuffman::AddParameterDefinition(const char* name, unsigned bitLength)
56 {
57   /// search a parameter definition in the decoder configuration, and set the index
58   /// array, return reference id
59   /// TODO: this code is a copy of AliHLTDataDeflaterHuffman::AddParameterDefinition
60   /// make a common base class
61   if (!name) return -EINVAL;
62   if (!fHuffmanCoderList) return -ENODEV;
63   TObject* pObj=fHuffmanCoderList->FindObject(name);
64   if (!pObj) {
65     HLTError("can not find decoder of id '%s'", name);
66     return -ENOENT;
67   }
68   AliHLTHuffman* pHuffman=dynamic_cast<AliHLTHuffman*>(pObj);
69   if (!pHuffman) {
70     HLTError("object %s has wrong type, expected AliHLTHuffman", name);
71     return -EBADF;
72   }
73   if (pHuffman->GetMaxBits()!=bitLength) {
74     HLTError("mismatch in bitlengt: can not use decoder %s of length %d for encoding of %d bits", pHuffman->GetName(), pHuffman->GetMaxBits(), bitLength);
75     return -EPERM;
76   }
77
78   fHuffmanCoders.push_back(pHuffman);
79   return fHuffmanCoders.size()-1;
80 }
81
82 int AliHLTDataInflaterHuffman::InitDecoders(TList* decoderlist)
83 {
84   /// init list of decoders
85   /// expects to be an external pointer, valid throughout the livetime of
86   /// the instance
87   /// TODO: this code is a copy of AliHLTDataDeflaterHuffman::InitDecoders
88   /// make a common base class
89   if (!decoderlist) return -EINVAL;
90   if (!fHuffmanCoderList) {
91     fHuffmanCoderList=new TList;
92   } else {
93     if (fHuffmanCoderList->GetEntries()>0 && fHuffmanCoderList->IsOwner()) {
94       HLTWarning("list of decoders owns already %d object(s), but disabling ownership now because of new external pointers");
95     }
96   }
97   if (!fHuffmanCoderList) return -ENOMEM;
98   fHuffmanCoderList->SetOwner(kFALSE);
99   TIter next(decoderlist);
100   TObject* pObj=NULL;
101   while ((pObj=next())!=NULL) {
102     AliHLTHuffman* coder=NULL;
103     if ((coder=dynamic_cast<AliHLTHuffman*>(pObj))==NULL) continue;
104     if (fHuffmanCoderList->FindObject(pObj->GetName())) {
105       HLTError("duplicate entry of name '%s'", pObj->GetName());
106       return -EEXIST;
107     }
108     fHuffmanCoderList->Add(pObj);
109     coder->InitMaxCodeLength();
110   }
111
112   return fHuffmanCoderList->GetEntries();
113 }
114
115 bool AliHLTDataInflaterHuffman::NextValue(AliHLTUInt64_t& value, AliHLTUInt32_t& length)
116 {
117   /// overloaded from AliHLTDataInflater
118   /// functions reads the sequence of parameters as defined by the decoder
119   /// list, than it starts at the first parameter again
120   value=0;
121   length=0;
122   if (fLegacyMode!=0) {
123   if ((++fCurrentParameter)>=(int)fHuffmanCoders.size()) fCurrentParameter=0;
124   fLegacyMode=1;
125   }
126   if (fHuffmanCoders.size()==0 || fCurrentParameter<0) return false;
127   if (fInputLength<fHuffmanCoders[fCurrentParameter]->GetMaxCodeLength() ||
128       fHuffmanCoders[fCurrentParameter]->GetMaxCodeLength()==0)
129   {
130     AliHLTUInt64_t input=0;
131     AliHLTUInt32_t inputLength=64-fInputLength;
132     if (GetRemainingBitDataSizeBytes()<=sizeof(AliHLTUInt64_t)) {
133       inputLength=8*GetRemainingBitDataSizeBytes();
134       inputLength-=(7-GetCurrentBitInputPosition());
135     }
136     if (64-fInputLength<inputLength) inputLength=64-fInputLength;
137     if (!InputBits(input, inputLength)) return false;
138     input<<=(64-inputLength);
139     input>>=fInputLength;
140     fInput|=input;
141     fInputLength+=inputLength;
142   }
143   AliHLTUInt32_t codeLength=0;
144   if (!fHuffmanCoders[fCurrentParameter]->DecodeUp(fInput, value, length, codeLength)) return false;
145   if (fInputLength<codeLength) {
146     HLTError("huffman decoder '%s' pretends to have %d bit(s) decoded, but only %d available",
147              fHuffmanCoders[fCurrentParameter]->GetName(), codeLength, fInputLength);
148     return false;
149   }
150   fInput<<=codeLength;
151   fInputLength-=codeLength;
152
153   return true;
154 }
155
156 void AliHLTDataInflaterHuffman::Print(Option_t* option) const
157 {
158   /// Print info
159   for (vector<AliHLTHuffman*>::const_iterator coder=fHuffmanCoders.begin();
160        coder!=fHuffmanCoders.end(); coder++) {
161     if (!*coder) continue;
162     (*coder)->Print(option);
163   }
164 }
165
166 void AliHLTDataInflaterHuffman::Clear(Option_t * option)
167 {
168   /// clear the object
169   fCurrentParameter=-1;
170   fInput=0;
171   fInputLength=0;
172
173   if (strcmp(option, "all")==0) {
174     fHuffmanCoders.clear();
175     if (fHuffmanCoderList) delete fHuffmanCoderList;
176     fHuffmanCoderList=NULL;
177   }
178
179   AliHLTDataInflater::Clear(option);
180 }