/*************************************************************************** * Copyright (C) 2005 by Nicolas PASCAL * * nicolas.pascal@icare.univ-lille1.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef PARASOLFILEREADER_H #define PARASOLFILEREADER_H #include "file_tools.h" #include "file_exceptions.h" #include "parasolfilerecord.h" #include "parasolfileformat.h" #include #include using namespace std; /** *@struct EntryBlock defines a group of parametres that are repeated several times in a record * Ex : the directionnal parametres in L1 products, the sequences and the images in the technological parameters */ typedef struct EntryBlock { /* number of time the group is repeated */ int ntime; /* size in bytes of the group */ int size; EntryBlock (int ntime = -1, int size = -1) : ntime(ntime), size(size) {}; friend ostream &operator<< (std::ostream &stream, const EntryBlock &obj) { stream << "{ntime = " << obj.ntime << " ; size = " << obj.size << "}" ; return stream; } } EntryBlock; /** This class contains the methods used to read the PARASOL that are common to the leader and the data files. @author Nicolas PASCAL */ class PARASOLFileReader{ friend class PARASOLFileData; protected: string filename; PARASOLProduct product; FILE* fp; /** * @brief read the whole data of a record * @param record_code code of the record to load */ virtual void read_record(const Record &record_code); /** * @brief read the values of an entry. * @param entry the variable where to put the read value(s) * @param entry_nb the number of the entry. Updated by the method * @param record_code the code of the current processed record * @param entry_format the entry record format descriptor (a RecordFormat::iterator) Updated by the method * @param record_offset the start offset of the read record. */ void read_entry( void* record, const Record & record_code, int &entry_nb, RecordFormat::iterator & entry_format, const int & record_offset); /** * @brief read ONE value in the PARASOL file * @param val the variable where to put the read value * @param val_format a RecordFormat element describing the value format * @param previous_value_offset the file offset of the nearest preceeding value. * @return the number of bytes read */ const size_t read_value(void* val, const RecordFormat::iterator &val_format, const int &previous_value_offset); /** * @brief swap the given value endianess. * @param val the value to be swapped * @param type the type code of this value */ void swap_endianess(void * val, const PARASOLDataType &type); // ***** methods that must implement the inherited class ***** // /** * @brief check if a record has been read. * @return true if the record has already been read */ virtual const bool is_record_loaded(const Record &rec)=0; /** * @brief Free the objects used to store the values read in the file records */ virtual void free_records()=0; /** * @brief Initialize a record class * @param rec the record code * @return the initialized object (or NULL in case of problem) */ virtual PARASOLFileRecord* init_record(const Record &rec)=0; /** * @brief access to ones record file offset * If the record isn't in the leader leader file, it returns -1 * @param rec the record code * @return the record's offset in the leader file */ virtual const int get_record_offset(const Record &rec)=0; /** * @brief return the offset of a record entry, in record unit. It means that the first entry (ie the record number) has an entry_offset of 0 * @param record_idx the record code * @param entry_idx the index of the entry to find the offset, start at 0. The record number has an entry_index of 0 * @param entry_group_idx (optional) for an entry that is in a repeated group, the index of the repetition. It is an abstraction, but for example, it is the index a direction for a directional parameter, starting at 0. * @param val_idx (optional) an index to select a particular value * @return the offset of the entry in the record, in bytes */ // virtual const int get_entry_offset(const Record rec, const int entry_idx, const int record_idx=-1, const int entry_group_idx=-1, const int val_idx=-1)=0; /** * @brief access to the offset of an entry, relative to the record start * TODO example * @param rec the concerned record * @param entry_idx index of the entry, start at 0, record_number is index 0 * @param i_val indices of the value, for parametres repeated many times in a record * @return the offset, from the record start */ virtual const int get_entry_offset(const Record rec, const int entry_idx, const vector & i_val); /** * @brief returns the number of times an entry group is repeated in the data record. If the entry is not repeated in a record, returns 1 * @throw bad_parametre_idx if the entry idx is invalid for the current product * @param entry_idx index of the entry (product specific) * @return the number of times the group is repeated */ // virtual const int get_entry_group_nb_val(const Record rec, const int entry_idx) const =0; /** * @brief return the block describing the given entry : the number of times the entry is repeated and the size in bytes of the group * @param rec current record * @param entry_idx indice of the entry * @return the block(s) of the entry. If the entry is composed of a unique value, returns an empty vector */ virtual vector get_entry_block (const Record rec, const int entry_idx) const = 0; /** * @brief access to the RecordFormat object that describes the name, type, offset and length of each record entry * @param rec the record code * @return the RecordFormat corresponding to @a record code */ virtual const RecordFormat* get_record_format(const Record &rec)=0; /** * @brief access to one record entry * @param rec the record code * @return the entry corresponding to @a record code */ virtual PARASOLFileRecord* get_record(const Record &rec)=0; /** * @brief check if the file to read has been laded * @return true of loaded */ const bool is_file_loaded(){ return (fp!=NULL); }; void open_file(); void close_file(); /** * @brief fill a buffer used to read the file with fill values * It uses a memset to do that * @param buf the buffer * @param nb_val the number of values of the buffer * @param type the data type */ static void fill_buffer_default(void* buf,const int &nb_val,const PARASOLDataType &type); public: PARASOLFileReader(const string filename=""); virtual ~PARASOLFileReader(); /** * @brief access to the product using parsing the name * @param filename the PARASOL file name (without the path) * @return the product */ static PARASOLProduct get_product(const string &filename) ; /** * @brief allocate a buffer to read data from a PARASOL data file. * @warning the buffer is allocated using the new[] operator (and not malloc !!!). So It must be freed with delete[]. * @param buf the buffer to be allocated * @param nb_data the buffer's length * @param type the buffer's data type (using PARASOLDataType) * @return the allocated buffer or NULL if not enough memory */ static void* custom_new(void* buf, const int& nb_data, const PARASOLDataType &type); /** * @brief find the element of a buffer at index inc, for buffer of type void*. * It is a method equivalent to buf_start[inc] for void* typed buffer * @param buf_start the buffer start pointer * @param inc the increment * @param type the buffer's type code * @return a pointer to the element */ static void* inc_ptr(void* buf_start, const int& inc, const PARASOLDataType &type); }; #endif