![]() |
![]() |
00001 #include "FileReaderDCC.h" 00002 #include <iostream> // cerr 00003 #include <errno.h> // errno 00004 #include <string.h> // bzero, memcpy 00005 #include <stdlib.h> // exit 00006 #include <sys/types.h> // open 00007 #include <sys/stat.h> // open 00008 #include <fcntl.h> // open 00009 #include <unistd.h> // read, close 00010 00011 FileReaderDCC::FileReaderDCC(void){ 00012 if( sizeof(unsigned long long)!=8 || sizeof(unsigned short)!=2 ) 00013 throw std::runtime_error(std::string("Wrong platform: sizeof(unsigned long long)!=8 || sizeof(unsigned short)!=2")); 00014 raw_event = new unsigned short [200000*40]; 00015 end = (file_buffer_end = file_buffer + sizeof(file_buffer)/sizeof(unsigned long long)); 00016 bzero(raw_event, sizeof(raw_event) ); 00017 bzero(file_buffer,sizeof(file_buffer)); 00018 word_0=0; word_1=0; word_2=0; 00019 eventStatus = 0; 00020 selectCriteria = Header|Trailer; 00021 rejectCriteria = DCCoversize|FFFF|Unknown; 00022 acceptCriteria = 0x3F; // Everything 00023 fd = 0; 00024 } 00025 00026 FileReaderDCC::~FileReaderDCC(void){ if( fd ) close(fd); } 00027 00028 int FileReaderDCC::open(const char *filename) throw (std::runtime_error) { 00029 if( fd ) close(fd); 00030 fd = ::open(filename,O_RDONLY|O_LARGEFILE); 00031 if( fd == -1 ) throw ( std::runtime_error(std::string("Error opening ").append(filename).append(" data file.")) ); 00032 return fd; 00033 } 00034 00035 size_t FileReaderDCC::read(const unsigned short* &buf) throw (std::runtime_error) { 00036 // Check for ubnormal situation 00037 if( end>file_buffer_end || end<file_buffer ) throw ( std::runtime_error("Error of reading") ); 00038 if( !fd ) throw ( std::runtime_error("Open some file first") ); 00039 00040 unsigned long long *start = end; 00041 unsigned short *event = raw_event; 00042 00043 eventStatus = 0; 00044 size_t dccWordCount = 0; 00045 end = 0; 00046 00047 while( !end && dccWordCount<50000*40 ){ 00048 unsigned long long *dccWord = start; 00049 unsigned long long preHeader = 0; 00050 00051 // Did we reach end of current buffer and want to read next block? 00052 // If it was first time and we don't have file buffer then we won't get inside 00053 while( dccWord<file_buffer_end && dccWordCount<50000 ){ 00054 word_0 = word_1; // delay by 2 DCC words 00055 word_1 = word_2; // delay by 1 DCC word 00056 word_2 = *dccWord;// current DCC word 00057 if( (word_1&0xF0000000000000FFLL)==0x500000000000005FLL && // let's call this a preHeader 00058 (word_2&0xFF000000000000FFLL)==0xD900000000000017LL ){ // and this is a header 00059 if( eventStatus&Header ){ // Second header 00060 word_2 = word_1; // Fall back to get rigth preHeader next time 00061 end = dccWord; // Even if we end with preHeader of next evet put it to the end of this event too 00062 break; 00063 } 00064 if( dccWordCount>1 ){ // Extra words between trailer and header 00065 if( (word_0&0xFFFFFFFFFFFF0000LL)==0xFFFFFFFFFFFF0000LL ) eventStatus |= FFFF; 00066 word_2 = word_1; // Fall back to get rigth preHeader next time 00067 end = dccWord; 00068 break; 00069 } 00070 eventStatus |= Header; 00071 if( event==raw_event ) preHeader = word_1; // If preHeader not yet in event then put it there 00072 start = dccWord; 00073 } 00074 if( (word_1&0xFF00000000000000LL)==0xEF00000000000000LL && 00075 (word_2&0xFF0000000000000FLL)==0xAF00000000000007LL ){ 00076 eventStatus |= Trailer; 00077 end = ++dccWord; 00078 break; 00079 } 00080 // Increase counters by one DCC word 00081 dccWord++; 00082 dccWordCount++; 00083 } 00084 00085 // If have DCC Header 00086 if( preHeader ){ 00087 // Need to account first word of DCC Header 00088 memcpy(event,&preHeader,sizeof(preHeader)); 00089 event += sizeof(preHeader)/sizeof(unsigned short); 00090 } 00091 00092 // Take care of the rest 00093 memcpy(event,start,(dccWord-start)*sizeof(unsigned long long)); 00094 event += (dccWord-start)*sizeof(unsigned long long)/sizeof(unsigned short); 00095 00096 // If reach max length 00097 if( dccWordCount==50000*40 ){ end = dccWord; break; } 00098 00099 if( !end ){ 00100 // Need to read next block for the rest of this event 00101 ssize_t length = ::read(fd,file_buffer,sizeof(file_buffer)); 00102 if( length==-1 ) throw ( std::runtime_error("Error of reading") ); 00103 if( length== 0 ){ 00104 eventStatus |= EndOfStream; 00105 end = (file_buffer_end = file_buffer + sizeof(file_buffer)/sizeof(unsigned long long)); 00106 break; 00107 } 00108 file_buffer_end = file_buffer + length/sizeof(unsigned long long); 00109 00110 // Will start from the beginning of new buffer next time we read it 00111 start = file_buffer; 00112 } 00113 } 00114 00115 if( !end ) eventStatus |= DCCoversize; 00116 if( !(eventStatus&Header) && !(eventStatus&Trailer) && !(eventStatus&FFFF) ) eventStatus |= Unknown; 00117 00118 buf = (const unsigned short*)raw_event; 00119 return (eventStatus&FFFF?event-raw_event-4:event-raw_event); 00120 } 00121 00122 size_t FileReaderDCC::next(const unsigned short* &buf) throw(std::runtime_error) { 00123 size_t size=0; 00124 do { 00125 if( (size = read(buf)) == 0 ) break; 00126 } while( rejectCriteria&eventStatus || !(acceptCriteria&eventStatus) || (selectCriteria?selectCriteria!=eventStatus:0) ); 00127 return size; 00128 }