]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/BASE/AliHLTDataDeflaterHuffman.cxx
minor coverity defect: added protection for self-assignment
[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);
9409b4b1 131 //cout << fHuffmanCoders[memberId]->GetName() << " value " << value << ": code lenght " << length << " " << v << endl;
6a1b3945 132 if (length>0) {
133 return OutputBits(v, length);
134 }
135 return false;
136}
137
138int AliHLTDataDeflaterHuffman::AddTrainingParameter(const char* name, unsigned bitLength)
139{
140 /// add a parameter definition for huffman training
141
142 /// returns index in the array
143 if (!fHuffmanCoderList) {
144 fHuffmanCoderList=new TList;
145 if (!fHuffmanCoderList) return -ENOMEM;
146 // always set ownership for the new list since it is supposed to
147 // contain only internal pointers
148 fHuffmanCoderList->SetOwner();
149 } else if (!fHuffmanCoderList->IsOwner()) {
150 // not sure about the pointers which are already in the list
151 if (fHuffmanCoderList->GetEntries()>0) {
152 HLTWarning("skip setting ownership because list contains already %d object(s), possible memory leak at cleanup");
153 } else {
154 fHuffmanCoderList->SetOwner();
155 }
156 }
157 AliHLTHuffman* pHuffman=new AliHLTHuffman(name, bitLength);
158 if (!pHuffman) return -ENOMEM;
159 fHuffmanCoderList->Add(pHuffman);
160
161 fHuffmanCoders.push_back(pHuffman);
162 return fHuffmanCoders.size()-1;
163}
164
165bool AliHLTDataDeflaterHuffman::AddTrainingValue( int memberId, AliHLTUInt64_t const & value )
166{
167 /// add a training value for the specified parameter
168 if (memberId>=(int)fHuffmanCoders.size()) {
169 return false;
170 }
171 return fHuffmanCoders[memberId]->AddTrainingValue(value);
172}
173
174const TList* AliHLTDataDeflaterHuffman::GenerateHuffmanTree()
175{
176 /// generate the huffman tree
177 for (unsigned i=0; i<fHuffmanCoders.size(); i++) {
178 if (!fHuffmanCoders[i]->GenerateHuffmanTree()) {
179 HLTError("failed to generate huffman tree for parameter %s", fHuffmanCoders[i]->GetName());
180 }
181 }
182 return fHuffmanCoderList;
183}
184
185void AliHLTDataDeflaterHuffman::Clear(Option_t * option)
186{
187 // internal cleanup
188
189 AliHLTDataDeflater::Clear(option);
190}
191
192void AliHLTDataDeflaterHuffman::Print(Option_t *option) const
193{
194 // print info
195 Print(cout, option);
196}
197
198void AliHLTDataDeflaterHuffman::Print(ostream& out, Option_t * /*option*/) const
199{
200 // print to stream
201 out << "AliHLTDataDeflaterHuffman:" << endl;
202 for (vector<AliHLTHuffman*>::const_iterator it=fHuffmanCoders.begin();
203 it!=fHuffmanCoders.end(); it++) {
204 (*it)->Print("short"); cout << endl;
205 }
206 if (fHuffmanCoders.size()==0 && fHuffmanCoderList && fHuffmanCoderList->GetEntries()>0) {
207 TIter next(fHuffmanCoderList);
208 TObject* pObj=NULL;
209 while ((pObj=next())) {
210 pObj->Print("short"); cout << endl;
211 }
212 }
213}
214
215TObject *AliHLTDataDeflaterHuffman::FindObject(const char *name) const
216{
217 /// find object: 'DeflaterConfiguration'
218 if (strcmp(name, "DeflaterConfiguration")==0) {
219 for (unsigned i=0; i<fHuffmanCoders.size(); i++) {
220 if (!fHuffmanCoders[i]->GenerateHuffmanTree()) {
221 HLTError("generation of huffman tree for parameter '%s' failed", fHuffmanCoders[i]->GetName());
9409b4b1 222 return NULL;
223 }
224 if (!fHuffmanCoders[i]->CheckConsistency()) {
225 HLTError("consistency check of huffman tree for parameter '%s' failed", fHuffmanCoders[i]->GetName());
6a1b3945 226 }
227 }
228
229 return fHuffmanCoderList;
230 }
231
232 return NULL;
233}
234
235void AliHLTDataDeflaterHuffman::SaveAs(const char *filename, Option_t *option) const
236{
237 /// save data according to option
238 TString remainingOptions;
239 bool bWriteHuffmanConf=false; // write the huffman configuration
240 TString strOption(option);
241 std::auto_ptr<TObjArray> tokens(strOption.Tokenize(" "));
242 if (tokens.get()) {
243 for (int i=0; i<tokens->GetEntriesFast(); i++) {
244 if (!tokens->At(i)) continue;
245 const char* key="";
246 TString arg=tokens->At(i)->GetName();
247
248 key="huffmanconf";
249 if (arg.BeginsWith(key)) {
250 bWriteHuffmanConf=true;
251 continue;
252 }
253
254 if (!remainingOptions.IsNull()) remainingOptions+=" ";
255 remainingOptions+=arg;
256 }
257 }
258
259 if (bWriteHuffmanConf) {
260 std::auto_ptr<TFile> output(TFile::Open(filename, "RECREATE"));
261 if (!output.get() || output->IsZombie()) {
262 HLTError("can not open file %s from writing", filename);
263 return;
264 }
265
266 if (!fHuffmanCoderList || fHuffmanCoderList->GetEntries()==0) {
267 HLTError("no huffman instances available for writing");
268 return;
269 }
270
271 for (unsigned i=0; i<fHuffmanCoders.size(); i++) {
272 if (!fHuffmanCoders[i]->GenerateHuffmanTree()) {
273 HLTError("generation of huffman tree for parameter '%s' failed", fHuffmanCoders[i]->GetName());
274 }
275 }
276
277 output->cd();
278 fHuffmanCoderList->Write("DeflaterConfiguration", TObject::kSingleKey);
279 output->Close();
280 }
281
282 return AliHLTDataDeflater::SaveAs(remainingOptions);
283}
284
285ostream& operator<<(ostream &out, const AliHLTDataDeflaterHuffman& me)
286{
287 me.Print(out);
288 return out;
289}
290