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