]>
Commit | Line | Data |
---|---|---|
9409b4b1 | 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) | |
70d61ae2 | 37 | , fLegacyMode(-1) |
9409b4b1 | 38 | { |
39 | // see header file for class documentation | |
40 | // or | |
41 | // refer to README to build package | |
42 | // or | |
43 | // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt | |
44 | } | |
45 | ||
46 | AliHLTDataInflaterHuffman::~AliHLTDataInflaterHuffman() | |
47 | { | |
48 | // destructor | |
49 | } | |
50 | ||
51 | int AliHLTDataInflaterHuffman::AddParameterDefinition(const char* name, unsigned bitLength) | |
52 | { | |
53 | /// search a parameter definition in the decoder configuration, and set the index | |
54 | /// array, return reference id | |
55 | /// TODO: this code is a copy of AliHLTDataDeflaterHuffman::AddParameterDefinition | |
56 | /// make a common base class | |
57 | if (!name) return -EINVAL; | |
58 | if (!fHuffmanCoderList) return -ENODEV; | |
59 | TObject* pObj=fHuffmanCoderList->FindObject(name); | |
60 | if (!pObj) { | |
61 | HLTError("can not find decoder of id '%s'", name); | |
62 | return -ENOENT; | |
63 | } | |
64 | AliHLTHuffman* pHuffman=dynamic_cast<AliHLTHuffman*>(pObj); | |
65 | if (!pHuffman) { | |
66 | HLTError("object %s has wrong type, expected AliHLTHuffman", name); | |
67 | return -EBADF; | |
68 | } | |
69 | if (pHuffman->GetMaxBits()!=bitLength) { | |
70 | HLTError("mismatch in bitlengt: can not use decoder %s of length %d for encoding of %d bits", pHuffman->GetName(), pHuffman->GetMaxBits(), bitLength); | |
71 | return -EPERM; | |
72 | } | |
73 | ||
74 | fHuffmanCoders.push_back(pHuffman); | |
75 | return fHuffmanCoders.size()-1; | |
76 | } | |
77 | ||
78 | int AliHLTDataInflaterHuffman::InitDecoders(TList* decoderlist) | |
79 | { | |
80 | /// init list of decoders | |
81 | /// expects to be an external pointer, valid throughout the livetime of | |
82 | /// the instance | |
83 | /// TODO: this code is a copy of AliHLTDataDeflaterHuffman::InitDecoders | |
84 | /// make a common base class | |
85 | if (!decoderlist) return -EINVAL; | |
86 | if (!fHuffmanCoderList) { | |
87 | fHuffmanCoderList=new TList; | |
88 | } else { | |
89 | if (fHuffmanCoderList->GetEntries()>0 && fHuffmanCoderList->IsOwner()) { | |
90 | HLTWarning("list of decoders owns already %d object(s), but disabling ownership now because of new external pointers"); | |
91 | } | |
92 | } | |
93 | if (!fHuffmanCoderList) return -ENOMEM; | |
94 | fHuffmanCoderList->SetOwner(kFALSE); | |
95 | TIter next(decoderlist); | |
96 | TObject* pObj=NULL; | |
97 | while ((pObj=next())!=NULL) { | |
98 | if (dynamic_cast<AliHLTHuffman*>(pObj)==NULL) continue; | |
99 | if (fHuffmanCoderList->FindObject(pObj->GetName())) { | |
100 | HLTError("duplicate entry of name '%s'", pObj->GetName()); | |
101 | return -EEXIST; | |
102 | } | |
103 | fHuffmanCoderList->Add(pObj); | |
104 | } | |
105 | ||
106 | return fHuffmanCoderList->GetEntries(); | |
107 | } | |
108 | ||
109 | bool AliHLTDataInflaterHuffman::NextValue(AliHLTUInt64_t& value, AliHLTUInt32_t& length) | |
110 | { | |
111 | /// overloaded from AliHLTDataInflater | |
112 | /// functions reads the sequence of parameters as defined by the decoder | |
113 | /// list, than it starts at the first parameter again | |
114 | value=0; | |
115 | length=0; | |
116 | AliHLTUInt64_t input=0; | |
117 | AliHLTUInt32_t inputLength=64; | |
118 | if (GetRemainingBitDataSizeBytes()<=sizeof(AliHLTUInt64_t)) { | |
119 | inputLength=8*GetRemainingBitDataSizeBytes(); | |
120 | inputLength-=(7-GetCurrentBitInputPosition()); | |
121 | } | |
122 | if (!InputBits(input, inputLength)) return false; | |
70d61ae2 | 123 | if (fLegacyMode!=0) { |
9409b4b1 | 124 | if ((++fCurrentParameter)>=(int)fHuffmanCoders.size()) fCurrentParameter=0; |
70d61ae2 | 125 | fLegacyMode=1; |
126 | } | |
127 | if (fHuffmanCoders.size()==0 || fCurrentParameter<0) return false; | |
9409b4b1 | 128 | // the huffman code is decoded from bit 0 corresponding to the top node and then to |
129 | // the left. The bitstream stores the reversed huffman code from MSB to LSB to ensure | |
130 | // a continous bit stream, that's why then input word needs to be reversed before | |
131 | // decoding. | |
132 | // TODO: introducing DecodeReverse into AliHLTHuffman can speed up the reading | |
133 | std::bitset<64> bits; | |
134 | for (unsigned bit=0; bit<inputLength; bit++) {bits[inputLength-1-bit]=input&0x1;input>>=1;} | |
135 | AliHLTUInt32_t codeLength=0; | |
136 | if (!fHuffmanCoders[fCurrentParameter]->Decode(bits, value, length, codeLength)) return false; | |
137 | if (inputLength<codeLength) { | |
138 | HLTError("huffman decoder '%s' pretends to have %d bit(s) decoded, but only %d available", | |
139 | fHuffmanCoders[fCurrentParameter]->GetName(), codeLength, inputLength); | |
140 | return false; | |
141 | } | |
142 | inputLength-=codeLength; | |
143 | RewindBitPosition(inputLength); | |
144 | ||
145 | return true; | |
146 | } |