]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/BASE/AliHLTDataDeflaterHuffman.cxx
adding huffnam coding base class and data deflater using it (Thorsten)
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTDataDeflaterHuffman.cxx
CommitLineData
6a1b3945 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: Thorsten Kollegger <kollegge@ikf.uni-frankfurt.de> *
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 AliHLTDataDeflaterHuffman.cxx
20/// @author Thorsten Kollegger, Matthias Richter
21/// @date 2011-08-10
22/// @brief Deflater implementation using huffman code
23
24#include "AliHLTDataDeflaterHuffman.h"
25#include "AliHLTHuffman.h"
26#include "TObjArray.h"
27#include "TList.h"
28#include "TString.h"
29#include "TFile.h"
30#include <memory>
31#include <algorithm>
32#include <iostream>
33
34/** ROOT macro for the implementation of ROOT specific class methods */
35ClassImp(AliHLTDataDeflaterHuffman)
36
37AliHLTDataDeflaterHuffman::AliHLTDataDeflaterHuffman(bool bTrainingMode)
38 : AliHLTDataDeflater()
39 , fHuffmanCoders()
40 , fHuffmanCoderList(NULL)
41 , fTrainingMode(bTrainingMode)
42{
43 // see header file for class documentation
44 // or
45 // refer to README to build package
46 // or
47 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
48 if (bTrainingMode) {
49 HLTInfo("using DataDeflaterHuffman in training mode");
50 }
51}
52
53AliHLTDataDeflaterHuffman::~AliHLTDataDeflaterHuffman()
54{
55 // destructor
56 if (fHuffmanCoderList) delete fHuffmanCoderList;
57 fHuffmanCoderList=NULL;
58
59 Clear();
60}
61
62int AliHLTDataDeflaterHuffman::AddParameterDefinition(const char* name, unsigned bitLength)
63{
64 /// search a parameter definition in the decoder configuration, and set the index
65 /// array, return reference id
66 if (IsTrainingMode())
67 return AddTrainingParameter(name, bitLength);
68
69 if (!name) return -EINVAL;
70 if (!fHuffmanCoderList) return -ENODEV;
71 TObject* pObj=fHuffmanCoderList->FindObject(name);
72 if (!pObj) {
73 HLTError("can not find decoder of id '%s'", name);
74 return -ENOENT;
75 }
76 AliHLTHuffman* pHuffman=dynamic_cast<AliHLTHuffman*>(pObj);
77 if (!pHuffman) {
78 HLTError("object %s has wrong type, expected AliHLTHuffman", name);
79 return -EBADF;
80 }
81 if (pHuffman->GetMaxBits()!=bitLength) {
82 HLTError("mismatch in bitlengt: can not use decoder %s of length %d for encoding of %d bits", pHuffman->GetName(), pHuffman->GetMaxBits(), bitLength);
83 return -EPERM;
84 }
85
86 fHuffmanCoders.push_back(pHuffman);
87 return fHuffmanCoders.size()-1;
88}
89
90int AliHLTDataDeflaterHuffman::InitDecoders(TList* decoderlist)
91{
92 /// init list of decoders
93 /// expects to be an external pointer, valid throughout the livetime of
94 /// the instance
95 if (!decoderlist) return -EINVAL;
96 if (!fHuffmanCoderList) {
97 fHuffmanCoderList=new TList;
98 } else {
99 if (fHuffmanCoderList->GetEntries()>0 && fHuffmanCoderList->IsOwner()) {
100 HLTWarning("list of decoders owns already %d object(s), but disabling ownership now because of new external pointers");
101 }
102 }
103 if (!fHuffmanCoderList) return -ENOMEM;
104 fHuffmanCoderList->SetOwner(kFALSE);
105 TIter next(decoderlist);
106 TObject* pObj=NULL;
107 while ((pObj=next())!=NULL) {
108 if (dynamic_cast<AliHLTHuffman*>(pObj)==NULL) continue;
109 if (fHuffmanCoderList->FindObject(pObj->GetName())) {
110 HLTError("duplicate entry of name '%s'", pObj->GetName());
111 return -EEXIST;
112 }
113 fHuffmanCoderList->Add(pObj);
114 }
115
116 return fHuffmanCoderList->GetEntries();
117}
118
119bool AliHLTDataDeflaterHuffman::OutputParameterBits( int memberId, AliHLTUInt64_t const & value )
120{
121 // write huffman encoded bit pattern of a member to the current byte and position
122 if (IsTrainingMode())
123 return AddTrainingValue(memberId, value);
124
125 if (memberId>=(int)fHuffmanCoders.size()) {
126 return false;
127 }
128
129 AliHLTUInt64_t length = 0;
130 const std::bitset<64>& v=fHuffmanCoders[memberId]->Encode((value>fHuffmanCoders[memberId]->GetMaxValue())?fHuffmanCoders[memberId]->GetMaxValue():value, length);
131 if (length>0) {
132 return OutputBits(v, length);
133 }
134 return false;
135}
136
137int AliHLTDataDeflaterHuffman::AddTrainingParameter(const char* name, unsigned bitLength)
138{
139 /// add a parameter definition for huffman training
140
141 /// returns index in the array
142 if (!fHuffmanCoderList) {
143 fHuffmanCoderList=new TList;
144 if (!fHuffmanCoderList) return -ENOMEM;
145 // always set ownership for the new list since it is supposed to
146 // contain only internal pointers
147 fHuffmanCoderList->SetOwner();
148 } else if (!fHuffmanCoderList->IsOwner()) {
149 // not sure about the pointers which are already in the list
150 if (fHuffmanCoderList->GetEntries()>0) {
151 HLTWarning("skip setting ownership because list contains already %d object(s), possible memory leak at cleanup");
152 } else {
153 fHuffmanCoderList->SetOwner();
154 }
155 }
156 AliHLTHuffman* pHuffman=new AliHLTHuffman(name, bitLength);
157 if (!pHuffman) return -ENOMEM;
158 fHuffmanCoderList->Add(pHuffman);
159
160 fHuffmanCoders.push_back(pHuffman);
161 return fHuffmanCoders.size()-1;
162}
163
164bool AliHLTDataDeflaterHuffman::AddTrainingValue( int memberId, AliHLTUInt64_t const & value )
165{
166 /// add a training value for the specified parameter
167 if (memberId>=(int)fHuffmanCoders.size()) {
168 return false;
169 }
170 return fHuffmanCoders[memberId]->AddTrainingValue(value);
171}
172
173const TList* AliHLTDataDeflaterHuffman::GenerateHuffmanTree()
174{
175 /// generate the huffman tree
176 for (unsigned i=0; i<fHuffmanCoders.size(); i++) {
177 if (!fHuffmanCoders[i]->GenerateHuffmanTree()) {
178 HLTError("failed to generate huffman tree for parameter %s", fHuffmanCoders[i]->GetName());
179 }
180 }
181 return fHuffmanCoderList;
182}
183
184void AliHLTDataDeflaterHuffman::Clear(Option_t * option)
185{
186 // internal cleanup
187
188 AliHLTDataDeflater::Clear(option);
189}
190
191void AliHLTDataDeflaterHuffman::Print(Option_t *option) const
192{
193 // print info
194 Print(cout, option);
195}
196
197void AliHLTDataDeflaterHuffman::Print(ostream& out, Option_t * /*option*/) const
198{
199 // print to stream
200 out << "AliHLTDataDeflaterHuffman:" << endl;
201 for (vector<AliHLTHuffman*>::const_iterator it=fHuffmanCoders.begin();
202 it!=fHuffmanCoders.end(); it++) {
203 (*it)->Print("short"); cout << endl;
204 }
205 if (fHuffmanCoders.size()==0 && fHuffmanCoderList && fHuffmanCoderList->GetEntries()>0) {
206 TIter next(fHuffmanCoderList);
207 TObject* pObj=NULL;
208 while ((pObj=next())) {
209 pObj->Print("short"); cout << endl;
210 }
211 }
212}
213
214TObject *AliHLTDataDeflaterHuffman::FindObject(const char *name) const
215{
216 /// find object: 'DeflaterConfiguration'
217 if (strcmp(name, "DeflaterConfiguration")==0) {
218 for (unsigned i=0; i<fHuffmanCoders.size(); i++) {
219 if (!fHuffmanCoders[i]->GenerateHuffmanTree()) {
220 HLTError("generation of huffman tree for parameter '%s' failed", fHuffmanCoders[i]->GetName());
221 }
222 }
223
224 return fHuffmanCoderList;
225 }
226
227 return NULL;
228}
229
230void AliHLTDataDeflaterHuffman::SaveAs(const char *filename, Option_t *option) const
231{
232 /// save data according to option
233 TString remainingOptions;
234 bool bWriteHuffmanConf=false; // write the huffman configuration
235 TString strOption(option);
236 std::auto_ptr<TObjArray> tokens(strOption.Tokenize(" "));
237 if (tokens.get()) {
238 for (int i=0; i<tokens->GetEntriesFast(); i++) {
239 if (!tokens->At(i)) continue;
240 const char* key="";
241 TString arg=tokens->At(i)->GetName();
242
243 key="huffmanconf";
244 if (arg.BeginsWith(key)) {
245 bWriteHuffmanConf=true;
246 continue;
247 }
248
249 if (!remainingOptions.IsNull()) remainingOptions+=" ";
250 remainingOptions+=arg;
251 }
252 }
253
254 if (bWriteHuffmanConf) {
255 std::auto_ptr<TFile> output(TFile::Open(filename, "RECREATE"));
256 if (!output.get() || output->IsZombie()) {
257 HLTError("can not open file %s from writing", filename);
258 return;
259 }
260
261 if (!fHuffmanCoderList || fHuffmanCoderList->GetEntries()==0) {
262 HLTError("no huffman instances available for writing");
263 return;
264 }
265
266 for (unsigned i=0; i<fHuffmanCoders.size(); i++) {
267 if (!fHuffmanCoders[i]->GenerateHuffmanTree()) {
268 HLTError("generation of huffman tree for parameter '%s' failed", fHuffmanCoders[i]->GetName());
269 }
270 }
271
272 output->cd();
273 fHuffmanCoderList->Write("DeflaterConfiguration", TObject::kSingleKey);
274 output->Close();
275 }
276
277 return AliHLTDataDeflater::SaveAs(remainingOptions);
278}
279
280ostream& operator<<(ostream &out, const AliHLTDataDeflaterHuffman& me)
281{
282 me.Print(out);
283 return out;
284}
285