File indexing completed on 2024-04-06 12:19:14
0001 #include "FileReaderDCC.h"
0002 #include <cerrno> // errno
0003 #include <cstdlib> // exit
0004 #include <cstring> // bzero, memcpy
0005 #include <fcntl.h> // open
0006 #include <iostream> // cerr
0007 #include <sys/stat.h> // open
0008 #include <sys/types.h> // open
0009 #include <unistd.h> // read, close
0010
0011 #ifndef O_LARGEFILE
0012 #define O_LARGEFILE 0
0013 #endif
0014
0015 FileReaderDCC::FileReaderDCC(void) {
0016 if (sizeof(unsigned long long) != 8 || sizeof(unsigned short) != 2)
0017 throw std::runtime_error(std::string("Wrong platform: sizeof(unsigned long long)!=8 || sizeof(unsigned short)!=2"));
0018 raw_event = new unsigned short[200000 * 40];
0019 end = (file_buffer_end = file_buffer + sizeof(file_buffer) / sizeof(unsigned long long));
0020 bzero(raw_event, sizeof(unsigned short) * 200000 * 40);
0021 bzero(file_buffer, sizeof(file_buffer));
0022 word_0 = 0;
0023 word_1 = 0;
0024 word_2 = 0;
0025 eventStatus = 0;
0026 selectCriteria = Header | Trailer;
0027 rejectCriteria = DCCoversize | FFFF | Unknown;
0028 acceptCriteria = 0x3F;
0029 fd = 0;
0030 }
0031
0032 FileReaderDCC::~FileReaderDCC(void) {
0033 if (fd)
0034 close(fd);
0035 }
0036
0037 int FileReaderDCC::open(const char *filename) {
0038 if (fd)
0039 close(fd);
0040 fd = ::open(filename, O_RDONLY | O_LARGEFILE);
0041 if (fd == -1)
0042 throw(std::runtime_error(std::string("Error opening ").append(filename).append(" data file.")));
0043 return fd;
0044 }
0045
0046 size_t FileReaderDCC::read(const unsigned short *&buf) {
0047
0048 if (end > file_buffer_end || end < file_buffer)
0049 throw(std::runtime_error("Error of reading"));
0050 if (!fd)
0051 throw(std::runtime_error("Open some file first"));
0052
0053 unsigned long long *start = end;
0054 unsigned short *event = raw_event;
0055
0056 eventStatus = 0;
0057 size_t dccWordCount = 0;
0058 end = nullptr;
0059
0060 while (!end && dccWordCount < 50000 * 40) {
0061 unsigned long long *dccWord = start;
0062 unsigned long long preHeader = 0;
0063
0064
0065
0066 while (dccWord < file_buffer_end && dccWordCount < 50000) {
0067 word_0 = word_1;
0068 word_1 = word_2;
0069 word_2 = *dccWord;
0070 if ((word_1 & 0xF0000000000000FFLL) == 0x500000000000005FLL &&
0071 (word_2 & 0xFF000000000000FFLL) == 0xD900000000000017LL)
0072 {
0073 if (eventStatus & Header)
0074 {
0075 word_2 = word_1;
0076 end = dccWord;
0077 break;
0078 }
0079 if (dccWordCount > 1)
0080 {
0081 if ((word_0 & 0xFFFFFFFFFFFF0000LL) == 0xFFFFFFFFFFFF0000LL)
0082 eventStatus |= FFFF;
0083 word_2 = word_1;
0084 end = dccWord;
0085 break;
0086 }
0087 eventStatus |= Header;
0088 if (event == raw_event)
0089 preHeader = word_1;
0090 start = dccWord;
0091 }
0092 if ((word_1 & 0xFF00000000000000LL) == 0xEF00000000000000LL &&
0093 (word_2 & 0xFF0000000000000FLL) == 0xAF00000000000007LL) {
0094 eventStatus |= Trailer;
0095 end = ++dccWord;
0096 break;
0097 }
0098
0099 dccWord++;
0100 dccWordCount++;
0101 }
0102
0103
0104 if (preHeader) {
0105
0106 memcpy(event, &preHeader, sizeof(preHeader));
0107 event += sizeof(preHeader) / sizeof(unsigned short);
0108 }
0109
0110
0111 memcpy(event, start, (dccWord - start) * sizeof(unsigned long long));
0112 event += (dccWord - start) * sizeof(unsigned long long) / sizeof(unsigned short);
0113
0114
0115 if (dccWordCount == 50000 * 40) {
0116 end = dccWord;
0117 break;
0118 }
0119
0120 if (!end) {
0121
0122 ssize_t length = ::read(fd, file_buffer, sizeof(file_buffer));
0123 if (length == -1)
0124 throw(std::runtime_error("Error of reading"));
0125 if (length == 0) {
0126 eventStatus |= EndOfStream;
0127 end = (file_buffer_end = file_buffer + sizeof(file_buffer) / sizeof(unsigned long long));
0128 break;
0129 }
0130 file_buffer_end = file_buffer + length / sizeof(unsigned long long);
0131
0132
0133 start = file_buffer;
0134 }
0135 }
0136
0137 if (!end)
0138 eventStatus |= DCCoversize;
0139 if (!(eventStatus & Header) && !(eventStatus & Trailer) && !(eventStatus & FFFF))
0140 eventStatus |= Unknown;
0141
0142 buf = (const unsigned short *)raw_event;
0143 return (eventStatus & FFFF ? event - raw_event - 4 : event - raw_event);
0144 }
0145
0146 size_t FileReaderDCC::next(const unsigned short *&buf) {
0147 size_t size = 0;
0148 do {
0149 if ((size = read(buf)) == 0)
0150 break;
0151 } while (rejectCriteria & eventStatus || !(acceptCriteria & eventStatus) ||
0152 (selectCriteria ? selectCriteria != eventStatus : 0));
0153 return size;
0154 }