fvfile_block.cpp

00001
00002 /***************************************************************************
00003  *  fvfile_block.cpp - FireVision file block
00004  *
00005  *  Created: Fri Mar 28 11:52:45 2008
00006  *  Copyright  2008  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023
00024 #include <fvutils/fileformat/fvfile_block.h>
00025
00026 #include <cstdlib>
00027 #include <cstring>
00028
00029 
00030 /** @class FireVisionDataFileBlock <fvutils/fileformat/fvfile_block.h>
00031  * FireVision File Format data block.
00032  * This class describes one data block inside a FVFF file.
00033  * @author Tim Niemueller
00034  */
00035 
00036 /** @var void * FireVisionDataFileBlock::_data
00037  * Pointer to the internal data segment.
00038  * Never free or modify the pointer, but only deal with the data it points to.
00039  */
00040 /** @var size_t FireVisionDataFileBlock::_data_size
00041  * Size of _data in bytes.
00042  */
00043 /** @var void * FireVisionDataFileBlock::_spec_header
00044  * Pointer to the content specific block header.
00045  * Never free or modify the pointer, but only deal with the data it points to.
00046  */
00047 
00048 /** Constructor.
00049  * @param type block type, content specific
00050  * @param data_size size of the data segment
00051  * @param spec_header content-specific header
00052  * @param spec_header_size size of spec_header in bytes
00053  */
00054 FireVisionDataFileBlock::FireVisionDataFileBlock(unsigned int type, size_t data_size,
00055                                                  void *spec_header, size_t spec_header_size)
00056 {
00057   constructor(type, data_size, spec_header, spec_header_size);
00058 }
00059
00060 
00061 /** Constructor.
00062  * @param type block type, content specific
00063  * @param data_size size of the data segment
00064  * @param spec_header_size a specific header of the given size is created internally
00065  */
00066 FireVisionDataFileBlock::FireVisionDataFileBlock(unsigned int type, size_t data_size,
00067                                                  size_t spec_header_size)
00068 {
00069   constructor(type, data_size, NULL, spec_header_size);
00070 }
00071
00072 
00073 /** Constructor.
00074  * Specific header is assumed to be unused.
00075  * @param type block type, content specific
00076  * @param data_size size of the data segment
00077  */
00078 FireVisionDataFileBlock::FireVisionDataFileBlock(unsigned int type, size_t data_size)
00079 {
00080   constructor(type, data_size, NULL, 0);
00081 }
00082
00083 
00084 /** Shallow copy constructor.
00085  * This creates a shallow copy of the given block. "Shallow" means that the data is not
00086  * copied but referenced. This instance is only valid as long as the original instance
00087  * still exists.
00088  * @param block block to copy
00089  */
00090 FireVisionDataFileBlock::FireVisionDataFileBlock(FireVisionDataFileBlock *block)
00091 {
00092   _data_size         = block->_data_size;
00093   __spec_header_size = block->__spec_header_size;
00094   __block_size       = block->__block_size;
00095   __block_memptr     = block->__block_memptr;
00096   __block_header     = (fvff_block_header_t *)__block_memptr;
00097   _spec_header       = (char *)__block_memptr + sizeof(fvff_block_header_t);
00098   _data              = (char *)__block_memptr + sizeof(fvff_block_header_t) + __spec_header_size;
00099   __block_owner      = false;
00100 }
00101
00102 
00103 /** Internal constructor.
00104  * @param type block type, content specific
00105  * @param data_size size of the data segment
00106  * @param spec_header content-specific header
00107  * @param spec_header_size size of spec_header in bytes
00108  */
00109 void
00110 FireVisionDataFileBlock::constructor(unsigned int type, size_t data_size,
00111                                      void *spec_header, size_t spec_header_size)
00112 {
00113   _data_size         = data_size;
00114   __spec_header_size = spec_header_size;
00115   __block_size       = _data_size + sizeof(fvff_block_header_t) + spec_header_size;
00116
00117   __block_memptr = calloc(1, __block_size);
00118   __block_owner  = true;
00119   __block_header = (fvff_block_header_t *)__block_memptr;
00120   _spec_header   = (char *)__block_memptr + sizeof(fvff_block_header_t);
00121   _data          = (char *)__block_memptr + sizeof(fvff_block_header_t) + spec_header_size;
00122
00123   if ( (spec_header != NULL) && (spec_header_size > 0) ) {
00124     memcpy((char *)__block_memptr + sizeof(fvff_block_header_t), spec_header, spec_header_size);
00125   }
00126
00127   __block_header->type = type;
00128   __block_header->size = _data_size;
00129   __block_header->spec_head_size = spec_header_size;
00130 }
00131
00132 
00133 /** Set content-specific header.
00134  * If necessary this re-creates internal buffers. To avoid this use the three-parameter
00135  * ctor to have it account for the expected header size.
00136  * @param spec_header content-specific header
00137  * @param spec_header_size size of spec_header in bytes
00138  */
00139 void
00140 FireVisionDataFileBlock::set_spec_header(void *spec_header, size_t spec_header_size)
00141 {
00142   if( spec_header_size != __spec_header_size ) {
00143     // we need to re-create the memory and copy old data
00144     __spec_header_size = spec_header_size;
00145     __block_size       = _data_size + sizeof(fvff_block_header_t) + spec_header_size;
00146
00147     void *newblock = calloc(1, __block_size);
00148
00149     memcpy(newblock, __block_memptr, sizeof(fvff_block_header_t));
00150     memcpy((char *)newblock + sizeof(fvff_block_header_t) + spec_header_size, _data, _data_size);
00151
00152     free(__block_memptr);
00153     __block_memptr = newblock;
00154     __block_header = (fvff_block_header_t *)__block_memptr;
00155     _spec_header = (char *)__block_memptr + sizeof(fvff_block_header_t);
00156     _data = (char *)__block_memptr + sizeof(fvff_block_header_t) + spec_header_size;
00157
00158     __block_header->spec_head_size = spec_header_size;
00159   }
00160
00161   if ( (spec_header != NULL) && (spec_header_size > 0) ) {
00162     memcpy((char *)__block_memptr + sizeof(fvff_block_header_t), spec_header, spec_header_size);
00163   }
00164 }
00165
00166 
00167 /** Destructor. */
00168 FireVisionDataFileBlock::~FireVisionDataFileBlock()
00169 {
00170   if ( __block_owner) {
00171     free(__block_memptr);
00172   }
00173 }
00174
00175 
00176 /** Get block type.
00177  * @return block type ID, content specific
00178  */
00179 unsigned int
00180 FireVisionDataFileBlock::type() const
00181 {
00182   return __block_header->type;
00183 }
00184
00185 
00186 /** Pointer to the whole block.
00187  * @return pointer to whole block, including headers
00188  */
00189 void *
00190 FireVisionDataFileBlock::block_memptr() const
00191 {
00192   return __block_memptr;
00193 }
00194
00195 
00196 /** Size of blocks.
00197  * @return size of blocks in bytes.
00198  */
00199 size_t
00200 FireVisionDataFileBlock::block_size() const
00201 {
00202   return __block_size;
00203 }
00204
00205 
00206 /** Get data pointer.
00207  * @return pointer to the data segment of the block
00208  */
00209 void *
00210 FireVisionDataFileBlock::data_ptr() const
00211 {
00212   return _data;
00213 }
00214
00215 
00216 /** Size of data chunk.
00217  * @return size of data in bytes.
00218  */
00219 size_t
00220 FireVisionDataFileBlock::data_size() const
00221 {
00222   return _data_size;
00223 }