ALIROOT-5433 Transition to CDHv3 in HLT
[u/mrichter/AliRoot.git] / HLT / MUON / AliHLTMUONDataBlockWriter.h
1 #ifndef ALIHLTMUONDATABLOCKWRITER_H
2 #define ALIHLTMUONDATABLOCKWRITER_H
3 /**************************************************************************
4  * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
5  *                                                                        *
6  * Author: The ALICE Off-line Project.                                    *
7  * Contributors are mentioned in the code where appropriate.              *
8  *                                                                        *
9  * Permission to use, copy, modify and distribute this software and its   *
10  * documentation strictly for non-commercial purposes is hereby granted   *
11  * without fee, provided that the above copyright notice appears in all   *
12  * copies and that both the copyright notice and this permission notice   *
13  * appear in the supporting documentation. The authors make no claims     *
14  * about the suitability of this software for any purpose. It is          *
15  * provided "as is" without express or implied warranty.                  *
16  **************************************************************************/
17
18 // $Id$
19
20 /**
21  * @file   AliHLTMUONDataBlockWriter.h
22  * @author Artur Szostak <artursz@iafrica.com>
23  * @date   19 May 2007
24  * @brief  Definition of a writer class for internal dimuon HLT raw data blocks.
25  */
26
27 #include "AliHLTMUONDataTypes.h"
28 #include <cassert>
29
30 #include "AliHLTMUONTriggerRecordsBlockStruct.h"
31 #include "AliHLTMUONTrigRecsDebugBlockStruct.h"
32 #include "AliHLTMUONRecHitsBlockStruct.h"
33 #include "AliHLTMUONClustersBlockStruct.h"
34 #include "AliHLTMUONChannelsBlockStruct.h"
35 #include "AliHLTMUONMansoTracksBlockStruct.h"
36 #include "AliHLTMUONMansoCandidatesBlockStruct.h"
37 #include "AliHLTMUONTracksBlockStruct.h"
38 #include "AliHLTMUONSinglesDecisionBlockStruct.h"
39 #include "AliHLTMUONPairsDecisionBlockStruct.h"
40
41 /**
42  * A light weight class for writing an internal dimuon HLT data block.
43  * Suppose we are given a pointer 'buffer' to some empty memory buffer where we
44  * can store our new data block and the size of the data block is given by the
45  * variable 'size'. The data block is of type 'block_type', the data block entries
46  * are of type 'entries_type' and the data block type code is 'type_code'.
47  * The data block can be written in the following way:
48  * \code
49  *   void* buffer = somebuffer;
50  *   AliHLTUInt32_t size = somebuffer_size;
51  *   
52  *   // Initialise the data block writer.
53  *   AliHLTMUONDataBlockWriter<block_type, entries_type, type_code>
54  *   block(buffer, size);
55  *   
56  *   // Initialise the block header
57  *   if (not block.InitCommonHeader())
58  *   {
59  *      // handle error and exit...
60  *   }
61  *   
62  *   // Tell the writer how many entries we are going to use.
63  *   if (not block.SetNumberOfEntries(somevalue))
64  *   {
65  *      // handle error and exit...
66  *   }
67  *
68  *   // Add all the entries to the data block.
69  *   for (AliHLTUInt32_t i = 0; i < block.Nentries(); i++)
70  *   {
71  *      entries_type& entry = block[i];
72  *      // fill the new entry...
73  *      entry.somefield = somevalue;
74  *   }
75  * \endcode
76  * The slightly slower but safer method is to do the following:
77  * \code
78  *   AliHLTMUONDataBlockWriter<block_type, entries_type, type_code>
79  *   block(buffer, size);
80  *   if (not block.InitCommonHeader())
81  *   {
82  *      // handle error and exit...
83  *   }
84  *   
85  *   // For each new entry add it to the data block.
86  *   while (HaveMoreEntries())
87  *   {
88  *      entries_type* entry = block.AddEntry();
89  *      if (entry == NULL)
90  *      {
91  *         // handle buffer overflow and exit...
92  *      }
93  *      // fill the new entry...
94  *      entry->somefield = somevalue;
95  *   }
96  * \endcode
97  */
98 template <
99         class DataBlockType,
100         class DataElementType,
101         AliHLTMUONDataBlockType blockTypeCode
102 >
103 class AliHLTMUONDataBlockWriter
104 {
105 public:
106         typedef DataBlockType HeaderType;
107         typedef DataElementType ElementType;
108
109         /**
110          * Constructor that sets the internal pointer to the start of the buffer
111          * space to write to and the total size of the buffer in bytes.
112          * @param buffer  The pointer to the first byte of the memory buffer.
113          * @param size    The total size of the buffer in bytes.
114          */
115         AliHLTMUONDataBlockWriter(void* buffer, AliHLTUInt32_t size) :
116                 fSize(size),
117                 fMaxArraySize(size > sizeof(DataBlockType) ? size - sizeof(DataBlockType) : 0),
118                 fBlock(reinterpret_cast<DataBlockType*>(buffer)),
119                 fData(reinterpret_cast<DataElementType*>(
120                        reinterpret_cast<DataBlockType*>(buffer) + 1
121                       ))
122         {
123                 assert( buffer != NULL );
124         }
125         
126         /**
127          * Copy constructor that performs a shallow copy.
128          * Since this class does not take direct ownership of the buffer, never
129          * allocates or deallocates memory, this can be allowed.
130          */
131         AliHLTMUONDataBlockWriter(const AliHLTMUONDataBlockWriter& writer)
132         {
133                 fSize = writer.fSize;
134                 fMaxArraySize = writer.fMaxArraySize;
135                 fBlock = writer.fBlock;
136                 fData = writer.fData;
137         }
138         
139         /**
140          * Assignment operator performs a shallow copy.
141          * This is OK because this class does not take direct ownership of the
142          * output memory buffer.
143          */
144         AliHLTMUONDataBlockWriter& operator = (const AliHLTMUONDataBlockWriter& writer)
145         {
146                 fSize = writer.fSize;
147                 fMaxArraySize = writer.fMaxArraySize;
148                 fBlock = writer.fBlock;
149                 fData = writer.fData;
150                 return *this;
151         }
152
153         /**
154          * Initialises the common data block header by setting the type and record
155          * width fields. If the buffer size was to small to create the header then
156          * this method returns false, otherwise true on success.
157          */
158         bool InitCommonHeader() const
159         {
160                 // The block size must be at least sizeof(DataBlockType) bytes.
161                 if (fSize < sizeof(DataBlockType)) return false;
162
163                 // Now fill the fields in the header.
164                 fBlock->fHeader.fType = blockTypeCode;
165                 fBlock->fHeader.fRecordWidth = sizeof(DataElementType);
166                 fBlock->fHeader.fNrecords = 0;
167                 return true;
168         }
169         
170         /**
171          * Returns the common data block header.
172          */
173         const AliHLTMUONDataBlockHeader& CommonBlockHeader() const
174         {
175                 return fBlock->fHeader;
176         }
177         
178         /**
179          * Returns the whole data block header.
180          */
181         DataBlockType& BlockHeader()
182         {
183                 return *fBlock;
184         }
185         
186         const DataBlockType& BlockHeader() const
187         {
188                 return *fBlock;
189         }
190         
191         /**
192          * Returns a pointer to the next location where a data entry can be
193          * written and increments the number of entries.
194          * If the buffer is already full then NULL is returned and the number of
195          * entries is not changed.
196          */
197         DataElementType* AddEntry() const
198         {
199                 if ( (Nentries() + 1) * sizeof(DataElementType) > fMaxArraySize )
200                         return NULL;
201                 DataElementType* newentry = &fData[fBlock->fHeader.fNrecords];
202                 fBlock->fHeader.fNrecords++;
203                 return newentry;
204         }
205         
206         /**
207          * Sets the number of entries that will be filled into the buffer.
208          * If the number of entries is to many to fit into the buffer then this
209          * method returns false, otherwise true.
210          */
211         bool SetNumberOfEntries(AliHLTUInt32_t n) const
212         {
213                 if (n * sizeof(DataElementType) > fMaxArraySize) return false;
214                 fBlock->fHeader.fNrecords = n;
215                 return true;
216         }
217
218         /**
219          * Returns the total number of entries already added to the data block.
220          */
221         AliHLTUInt32_t Nentries() const { return fBlock->fHeader.fNrecords; }
222
223         /**
224          * Returns a pointer to the i'th entry.
225          * If the index 'i' is out of bounds then NULL is returned.
226          * This is a safe access method because it does bounds checking but is
227          * a little slower than the array operators.
228          * @param i  The index number of the entry to be returned.
229          * @return  A pointer to the entry or NULL.
230          */
231         DataElementType* Entry(AliHLTUInt32_t i)
232         {
233                 return (i < Nentries()) ? &fData[i] : NULL;
234         }
235         
236         const DataElementType* Entry(AliHLTUInt32_t i) const
237         {
238                 return (i < Nentries()) ? &fData[i] : NULL;
239         }
240
241         /**
242          * Array operator for accessing the data entries directly.
243          * The index variable 'i' is not checked (except in debug compilations)
244          * so one should make sure they are within the valid range.
245          */
246         DataElementType& operator [] (AliHLTUInt32_t i)
247         {
248                 assert( i < Nentries() );
249                 return fData[i];
250         }
251         
252         const DataElementType& operator [] (AliHLTUInt32_t i) const
253         {
254                 assert( i < Nentries() );
255                 return fData[i];
256         }
257
258         /**
259          * Returns a pointer to the array of elements in the data block.
260          * Care must be taken not to read beyond the array limits given by
261          * Nentries().
262          */
263         DataElementType* GetArray() { return fData; }
264         const DataElementType* GetArray() const { return fData; }
265         
266         /**
267          * Calculates the number of bytes used for the data block in the buffer.
268          * This value will only make sense if a call to InitCommonHeader() was
269          * made and it returned true.
270          */
271         AliHLTUInt32_t BytesUsed() const
272         {
273                 assert( sizeof(DataElementType) == fBlock->fHeader.fRecordWidth);
274                 return sizeof(DataBlockType) + Nentries() * sizeof(DataElementType);
275         }
276         
277         /**
278          * Calculates the maximum number of entries that will fit into the
279          * memory buffer.
280          */
281         AliHLTUInt32_t MaxNumberOfEntries() const
282         {
283                 return fMaxArraySize / sizeof(DataElementType);
284         }
285         
286         AliHLTUInt32_t BufferSize() { return fSize; }
287         
288 private:
289
290         AliHLTUInt32_t fSize;   // Size of the buffer in bytes.
291         AliHLTUInt32_t fMaxArraySize; // Maximum size of the fData array in bytes.
292         DataBlockType* fBlock; // Pointer to the start of the data block.
293         DataElementType* fData; // Pointer to the start of the data array.
294 };
295
296
297 // We now define the writer classes for the various data block types from the
298 // template class AliHLTMUONDataBlockWriter.
299
300 typedef AliHLTMUONDataBlockWriter<
301                 AliHLTMUONTriggerRecordsBlockStruct,
302                 AliHLTMUONTriggerRecordStruct,
303                 kTriggerRecordsDataBlock
304         > AliHLTMUONTriggerRecordsBlockWriter;
305
306 typedef AliHLTMUONDataBlockWriter<
307                 AliHLTMUONTrigRecsDebugBlockStruct,
308                 AliHLTMUONTrigRecInfoStruct,
309                 kTrigRecsDebugDataBlock
310         > AliHLTMUONTrigRecsDebugBlockWriter;
311
312 typedef AliHLTMUONDataBlockWriter<
313                 AliHLTMUONRecHitsBlockStruct,
314                 AliHLTMUONRecHitStruct,
315                 kRecHitsDataBlock
316         > AliHLTMUONRecHitsBlockWriter;
317
318 typedef AliHLTMUONDataBlockWriter<
319                 AliHLTMUONClustersBlockStruct,
320                 AliHLTMUONClusterStruct,
321                 kClustersDataBlock
322         > AliHLTMUONClustersBlockWriter;
323
324 typedef AliHLTMUONDataBlockWriter<
325                 AliHLTMUONChannelsBlockStruct,
326                 AliHLTMUONChannelStruct,
327                 kChannelsDataBlock
328         > AliHLTMUONChannelsBlockWriter;
329
330 typedef AliHLTMUONDataBlockWriter<
331                 AliHLTMUONMansoTracksBlockStruct,
332                 AliHLTMUONMansoTrackStruct,
333                 kMansoTracksDataBlock
334         > AliHLTMUONMansoTracksBlockWriter;
335
336 typedef AliHLTMUONDataBlockWriter<
337                 AliHLTMUONMansoCandidatesBlockStruct,
338                 AliHLTMUONMansoCandidateStruct,
339                 kMansoCandidatesDataBlock
340         > AliHLTMUONMansoCandidatesBlockWriter;
341
342 typedef AliHLTMUONDataBlockWriter<
343                 AliHLTMUONTracksBlockStruct,
344                 AliHLTMUONTrackStruct,
345                 kTracksDataBlock
346         > AliHLTMUONTracksBlockWriter;
347         
348 typedef AliHLTMUONDataBlockWriter<
349                 AliHLTMUONSinglesDecisionBlockStruct,
350                 AliHLTMUONTrackDecisionStruct,
351                 kSinglesDecisionDataBlock
352         > AliHLTMUONSinglesDecisionBlockWriter;
353         
354 typedef AliHLTMUONDataBlockWriter<
355                 AliHLTMUONPairsDecisionBlockStruct,
356                 AliHLTMUONPairDecisionStruct,
357                 kPairsDecisionDataBlock
358         > AliHLTMUONPairsDecisionBlockWriter;
359
360 #endif // ALIHLTMUONDATABLOCKWRITER_H