/*************************************************************************** * 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. * ***************************************************************************/ #include "parasolfilereader.h" PARASOLFileReader::~PARASOLFileReader() { // close the eventually opened file close_file(); } PARASOLFileReader::PARASOLFileReader( const string filename ) : filename(filename) { fp=NULL; if (filename=="") // default constructor product=UNDEFINED; else { if (exists_file(filename) ) { // a filename is given this->filename=filename; // set the product product=get_product(get_tail(filename)); } else { bad_file e(filename); throw e; } } } void PARASOLFileReader::read_record( const Record & record_code ) { // if the file pointer hasn't been opened yet, must do it bool is_file_already_opened = is_file_loaded(); if (!is_file_already_opened) open_file(); if (fp!=NULL) { // set the desired record to fill, and its format descriptor if (!is_record_loaded(record_code)) // need an initialization if this is the first time this record is read init_record(record_code); PARASOLFileRecord *record = get_record(record_code); RecordFormat *rec_format = const_cast(get_record_format(record_code)); int record_offset=get_record_offset(record_code); // the offset of the record in the leader file int entry_nb=0; // cross all record's entries and read them RecordFormat::iterator entry_format=rec_format->begin(); for (entry_format=rec_format->begin();entry_format!=rec_format->end();++entry_format) { read_entry(record,record_code,entry_nb,entry_format,record_offset); entry_nb++; } // end reading -> close the file if the opening has been done in this method if (!is_file_already_opened) close_file(); } } void PARASOLFileReader::read_entry(void * record, const Record & record_code, int &entry_idx, RecordFormat::iterator & entry_format, const int &record_offset) { // pointer to value to fill void * entry_value = NULL; //--read the entry characteristics (wether in a group or not, number of repetitions, size...) vector v_entry_block = get_entry_block(record_code, entry_idx); int rank = v_entry_block.size(); // number of imbricated blocks. At most 2 for L1 technological params int sz_dim1 = 1, sz_dim2 = 0; if (rank >= 1) sz_dim1 = v_entry_block[0].ntime; if (rank >= 2) sz_dim2 = v_entry_block[1].ntime; // cout<<"*********** Entry ***********"<name<type)< i_val; i_val.reserve(2); if (rank == 0) { // get the variable to fill with the read entry entry_value = static_cast(record)->get_entry(entry_idx); // read the offset of the value to read from the start of file value_offset = record_offset + get_entry_offset(record_code, entry_idx, i_val);// entry_offset+i*group_length; // cout<<"Value offset : "<(record)->get_entry(entry_idx, i_val); // read the offset of the value to read from the start of file value_offset = record_offset + get_entry_offset(record_code, entry_idx, i_val);// entry_offset+i*group_length; // cout<<"Value offset : "<(record)->get_entry(entry_idx, i_val); // read the offset of the value to read from the start of file value_offset = record_offset + get_entry_offset(record_code, entry_idx, i_val);// entry_offset+i*group_length; // cout<<"Value offset : "<len; // number of occurences of contigous values PARASOLDataType type=val_format->type; size_t size_type=PARASOLLeaderFormat::get_size_of(type); // read the entry value in the file int return_code = -1; fseek(fp, value_offset, SEEK_SET); return_code = fread(val, size_type, length, fp); // convention : PARASOL files are stored in big endian mode. So if the system is little endian, the read values need to be swapped if (MyTools::is_big_endian()) swap_endianess(val,type); //cout<name<<" *"<<*(int*)val<<"* *"<<*(unsigned int *)val<<"* *"<<(char*)val<<"*"<(*reinterpret_cast(val)); break; case UINT32 : case INT32 : MyTools::byte_swap(*reinterpret_cast(val)); break; case UINT16 : case INT16 : MyTools::byte_swap(*reinterpret_cast(val)); default : // no swap break; } } PARASOLProduct PARASOLFileReader::get_product( const string & filename ) { char x=filename[3]; char y=filename[5]; char z=filename[7]; PARASOLProduct ret=UNDEFINED; if (x == '1') ret=BASIC_1; else if (x=='2'){ if (y=='R') ret=RB_2; else if (y=='O') { if (z=='A') ret=OC_SURF_DIR_2; else if (z=='B') ret=OC_SURF_NON_DIR_2; else if (z=='C') ret=OC_AEROSOL_2; }// end_ocean else if (y=='L') { if (z=='A') ret=LS_SURF_DIR_2; else if (z=='C') ret=LS_AEROSOL_2; } // end_land } // end level 2 else if (x =='3') { if (y=='R') ret=RB_3; else if (y=='O') { if (z=='B') ret=OC_MARINE_3; else if (z=='C') ret=OC_AEROSOL_3; }// end_ocean else if (y=='L') { if (z=='A') ret=LS_DIR_SIGN_3; else if (z=='B') ret=LS_ALBEDO_3; else if (z=='C') ret=LS_ATMO_3; } // end_land } // end level 3 return ret; } void * PARASOLFileReader::custom_new( void * buf, const int & nb_data, const PARASOLDataType & type ) { try { if (type== UINT8) { buf=new unsigned char[nb_data]; } else if (type== INT8) { buf=new char[nb_data]; } else if (type== UINT16) { buf=new unsigned short[nb_data]; } else if (type== INT16) { buf=new short[nb_data]; } else if (type== UINT32) { buf=new unsigned long[nb_data]; } else if (type== INT32) { buf=new long[nb_data]; } else if (type==B2) { buf=new char[2*nb_data]; } else cerr<<" In "<<__FILE__<<" at "<<__LINE__<<" : Type not implemented"<(buf_start); return (void*)(&elt[inc]); } else if (type== UINT8) { unsigned char* elt=static_cast(buf_start); return (void*)(&elt[inc]); } else if (type== UINT16) { unsigned short* elt=static_cast(buf_start); return (void*)(&elt[inc]); } else if (type== INT16) { short* elt=static_cast(buf_start); return (void*)(&elt[inc]); } else if (type== UINT32) { unsigned int * elt=static_cast(buf_start); return (void*)(&elt[inc]); } else if (type== INT32) { int * elt=static_cast(buf_start); return (void*)(&elt[inc]); } else if (type==B2) { unsigned short* elt=static_cast(buf_start); return (void*)(&elt[inc]); } else { cerr<<" In "<<__FILE__<<" at "<<__LINE__<<" : Type not implemented "< & i_val) { // the offset of the entry from the current record start EntryFormat format = (*get_record_format(rec))[entry_idx]; int entry_offset = format.pos - 1; // -1 because start position are given from 1 in the DPC (and so on in the format) and in this code offsets are treated from 0 // check if the parametre is inside a repeated block( directionnal params, dqx, sequences..) size_t rank = i_val.size(); vector v_entry_block = get_entry_block(rec, entry_idx); if (v_entry_block.size() != rank) { string msg ("Ranks do not match" + MyTools::to_string(v_entry_block.size()) + " != " + MyTools::to_string(rank) ) ; g_exception e( __FILE__ , __LINE__ , msg ); throw e; } // compute absolute offset for (size_t idim = 0 ; idim < rank ; ++idim) entry_offset += i_val [idim] * v_entry_block[idim].size; return entry_offset; }