diff --git a/src/epics/seq/CMakeLists.txt b/src/epics/seq/CMakeLists.txt index 536c25de35f433f12bc9ed1a494fce5a6fde83b3..b737c73d695781f486adff7d52bf8aa5437fca13 100644 --- a/src/epics/seq/CMakeLists.txt +++ b/src/epics/seq/CMakeLists.txt @@ -1,5 +1,6 @@ add_executable(test_sequencer_unit_tests test/test_main.cc + test/test_simple_range.cc test/test_fixed_size_string.cc test/test_fixed_size_vector.cc ) diff --git a/src/epics/seq/fixed_size_vector.hh b/src/epics/seq/fixed_size_vector.hh index 66d13e376ad6cb82a6e9100cd04fd498e8ab20a8..6c060a5eff4ee7e80b63ccb7b81ba71cafab4fda 100644 --- a/src/epics/seq/fixed_size_vector.hh +++ b/src/epics/seq/fixed_size_vector.hh @@ -168,7 +168,7 @@ namespace embedded const T& operator[]( size_type index ) const noexcept { - return *reinterpret_cast< T* >( &storage_[ index ] ); + return *reinterpret_cast< const T* >( &storage_[ index ] ); } void @@ -206,6 +206,30 @@ namespace embedded } } + T& + front() noexcept + { + return operator[](0); + } + + T& + back() noexcept + { + return operator[](entries_-1); + } + + const T& + front() const noexcept + { + return operator[](0); + } + + const T& + back() const noexcept + { + return operator[](entries_-1); + } + private: storage_type storage_[ max_size ]{}; size_type entries_{ 0 }; diff --git a/src/epics/seq/main.cc b/src/epics/seq/main.cc index 956b83e61baa7e2a8a782d7c800b0a741d847052..8ecf5d66a02ee4835504f0a523b8788219413a41 100644 --- a/src/epics/seq/main.cc +++ b/src/epics/seq/main.cc @@ -28,6 +28,8 @@ of this distribution. #include <sys/stat.h> #include <errno.h> #include <ctype.h> +#include <algorithm> +#include <iterator> #ifdef USE_SYSTEM_TIME #include <time.h> @@ -54,9 +56,11 @@ extern "C" { #include "asDbLib.h" #include "fixed_size_string.hh" +#include "fixed_size_vector.hh" +#include "simple_range.hh" using embedded::fixed_string; -//template <std::size_t Size> using fixed_string = embedded::fixed_string<Size>; +using embedded::fixed_size_vector; #ifdef CA_SDF #include <mutex> @@ -182,7 +186,7 @@ typedef struct SET_ERR_TABLE { double liveval; int sigNum; int chFlag; - int filtNum; + int filtNum{-1}; unsigned int sw[2]; } SET_ERR_TABLE; @@ -205,6 +209,15 @@ typedef struct CA_STARTUP_INFO { #endif +using table_range = embedded::range<SET_ERR_TABLE*>; + +template <std::size_t entry_count> +table_range +make_range(fixed_size_vector<SET_ERR_TABLE, entry_count>& cont) +{ + return embedded::make_range(&cont[0], &cont[0] + cont.size()); +} + // Gloabl variables **************************************************************************************** int chNum = 0; ///< Total number of channels held in the local lookup table. int chNotMon = 0; ///< Total number of channels not being monitored. @@ -222,24 +235,24 @@ char reloadtimechannel[256]; ///< Name of EPICS channel which contains the BURT struct timespec t; char logfilename[128]; -CDS_CD_TABLE cdTable[SDF_MAX_TSIZE]; ///< Table used to hold EPICS database info for monitoring settings. -CDS_CD_TABLE cdTableP[SDF_MAX_CHANS]; ///< Temp table filled on BURT read and set to EPICS channels. -FILTER_TABLE filterTable[SDF_MAX_FMSIZE]; ///< Table for holding filter module switch settings for comparisons. -SET_ERR_TABLE setErrTable[SDF_ERR_TSIZE]; ///< Table used to report settings diffs. -SET_ERR_TABLE unknownChans[SDF_ERR_TSIZE]; ///< Table used to report channels not found in local database. -SET_ERR_TABLE uninitChans[SDF_ERR_TSIZE]; ///< Table used to report channels not initialized by BURT safe.snap. -SET_ERR_TABLE unMonChans[SDF_MAX_TSIZE]; ///< Table used to report channels not being monitored. -SET_ERR_TABLE readErrTable[SDF_ERR_TSIZE]; ///< Table used to report file read errors.. -SET_ERR_TABLE cdTableList[SDF_MAX_TSIZE]; ///< Table used to report file read errors.. -time_t timeTable[SDF_MAX_CHANS]; ///< Holds timestamps for cdTableP +fixed_size_vector<CDS_CD_TABLE, SDF_MAX_TSIZE> cdTable; ///< Table used to hold EPICS database info for monitoring settings. +fixed_size_vector<CDS_CD_TABLE, SDF_MAX_CHANS> cdTableP; ///< Temp table filled on BURT read and set to EPICS channels. +fixed_size_vector<FILTER_TABLE, SDF_MAX_FMSIZE> filterTable; ///< Table for holding filter module switch settings for comparisons. +fixed_size_vector<SET_ERR_TABLE, SDF_ERR_TSIZE> setErrTable; ///< Table used to report settings diffs. +fixed_size_vector<SET_ERR_TABLE, SDF_ERR_TSIZE> unknownChans; ///< Table used to report channels not found in local database. +fixed_size_vector<SET_ERR_TABLE, SDF_ERR_TSIZE> uninitChans; ///< Table used to report channels not initialized by BURT safe.snap. +fixed_size_vector<SET_ERR_TABLE, SDF_MAX_TSIZE> unMonChans; ///< Table used to report channels not being monitored. +fixed_size_vector<SET_ERR_TABLE, SDF_ERR_TSIZE> readErrTable; ///< Table used to report file read errors.. +fixed_size_vector<SET_ERR_TABLE, SDF_MAX_TSIZE> cdTableList; ///< Table used to report file read errors.. +fixed_size_vector<time_t, SDF_MAX_CHANS> timeTable; ///< Holds timestamps for cdTableP -int filterMasks[SDF_MAX_FMSIZE]; ///< Filter monitor masks, as manipulated by the user +fixed_size_vector<int, SDF_MAX_FMSIZE> filterMasks; ///< Filter monitor masks, as manipulated by the user -dbAddr fmMaskChan[SDF_MAX_FMSIZE]; ///< We reflect the mask value into these channels -dbAddr fmMaskChanCtrl[SDF_MAX_FMSIZE]; ///< We signal bit changes to the masks on these channels +fixed_size_vector<dbAddr, SDF_MAX_FMSIZE> fmMaskChan; ///< We reflect the mask value into these channels +fixed_size_vector<dbAddr, SDF_MAX_FMSIZE> fmMaskChanCtrl; ///< We signal bit changes to the masks on these channels #ifdef CA_SDF -SET_ERR_TABLE disconnectChans[SDF_MAX_TSIZE]; +fixed_size_vector<SET_ERR_TABLE, SDF_MAX_TSIZE> disconnectChans; // caTable, caConnTAble, chConnNum, chEnumDetermined are protected by the caTableMutex EPICS_CA_TABLE caTable[SDF_MAX_TSIZE]; ///< Table used to hold the data returned by channel access @@ -286,27 +299,41 @@ int checkFileMod( char* , time_t* , int ); unsigned int filtCtrlBitConvert(unsigned int); void getSdfTime(char *, int size); void logFileEntry(const char *); -void getEpicsSettings(int, time_t *); -bool writeTable2File(char *burtdir, char *filename, int ftype, CDS_CD_TABLE *myTable); +void getEpicsSettings(); + +template <std::size_t entry_count> +bool writeTable2File(char *burtdir, char *filename, int ftype, fixed_size_vector<CDS_CD_TABLE, entry_count>& myTable); + int savesdffile(int,int,char *,char *,char *,char *,char *,dbAddr,dbAddr,dbAddr); int createSortTableEntries(int,int,const char *,int *,time_t*); -int reportSetErrors(char *,int,SET_ERR_TABLE *,int,int); -int spChecker(int,SET_ERR_TABLE *,int,char *,int,int *); -void newfilterstats(int); -int writeEpicsDb(int,CDS_CD_TABLE *,int); +template <std::size_t entry_count> +int reportSetErrors(char *,fixed_size_vector<SET_ERR_TABLE, entry_count>&,int,int); +template <std::size_t entry_count> +int spChecker(int,fixed_size_vector<SET_ERR_TABLE, entry_count>&,int,char *,int,int *); +void newfilterstats(); + +template <std::size_t entry_count> +int writeEpicsDb(fixed_size_vector<CDS_CD_TABLE, entry_count>&,int); int readConfig( char *,char *,int,char *); int parseLine(char *, int,char *,char *,char *,char *,char *,char *); -int modifyTable(int,SET_ERR_TABLE *); -int resetSelectedValues(int,SET_ERR_TABLE *); -void clearTableSelections(int,SET_ERR_TABLE *, int *); -void setAllTableSelections(int,SET_ERR_TABLE *, int *,int); -void changeSelectCB_uninit(int, SET_ERR_TABLE *, int *); -void decodeChangeSelect(int, int, int, SET_ERR_TABLE *, int *, void (*)(int, SET_ERR_TABLE *, int *)); +int modifyTable(table_range); +template <std::size_t entry_count> +int resetSelectedValues(fixed_size_vector<SET_ERR_TABLE, entry_count>&); +template <std::size_t entry_count> +void clearTableSelections(fixed_size_vector<SET_ERR_TABLE, entry_count>& dcsErrTable, int sc[]); +void setAllTableSelections(table_range, int *,int); +void changeSelectCB_uninit(SET_ERR_TABLE&, int *); +void decodeChangeSelect(int, int, table_range, int *, void (*)(SET_ERR_TABLE&, int *)); int appendAlarms2File(char *,char *,char *); void registerFilters(); -void setupFMArrays(char *,int*,dbAddr*,dbAddr*); -void resyncFMArrays(int *,dbAddr*); -void processFMChanCommands(int*,dbAddr*,dbAddr*,int*,int,SET_ERR_TABLE*); +void setupFMArrays(char *,fixed_size_vector<int, SDF_MAX_FMSIZE>&, + fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>&, + fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>&); +void resyncFMArrays(fixed_size_vector<int, SDF_MAX_FMSIZE>&,fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>&); +void processFMChanCommands(fixed_size_vector<int, SDF_MAX_FMSIZE>&, + fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>&, + fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>&, + int*,table_range); void countDisconnectedChannels(int); void saveStrSetPoint(int, const char*); void updateStrVarSetPoint(int); @@ -318,8 +345,8 @@ void nullCACallback(struct event_handler_args); bool getCAIndex(const char *, ADDRESS *); int canFindCAChannel(char *entry); -bool setCAValue(ADDRESS, SDF_TYPE, void *); -bool setCAValueLong(ADDRESS, PV_INT_TYPE *); +bool setCAValue(ADDRESS, SDF_TYPE, const void *); +bool setCAValueLong(ADDRESS, const PV_INT_TYPE *); bool syncEpicsDoubleValue(ADDRESS, double *, time_t *, int *); bool syncEpicsIntValue(ADDRESS, PV_INT_TYPE *, time_t *, int *); @@ -357,11 +384,11 @@ bool GET_ADDRESS(const char* name, ADDRESS* addr) { return getCAIndex(name, addr); } -bool PUT_VALUE(ADDRESS addr, SDF_TYPE type, void* pval) +bool PUT_VALUE(ADDRESS addr, SDF_TYPE type, const void* pval) { return setCAValue(addr, type, pval); } -bool PUT_VALUE_INT(ADDRESS addr, PV_INT_TYPE* val) +bool PUT_VALUE_INT(ADDRESS addr, const PV_INT_TYPE* val) { return setCAValueLong(addr, val); } @@ -393,11 +420,11 @@ bool GET_ADDRESS(const char* name, ADDRESS* addr) return dbNameToAddr(name, addr) == 0; } -bool PUT_VALUE(ADDRESS addr, SDF_TYPE type, void* pval) +bool PUT_VALUE(ADDRESS addr, SDF_TYPE type, const void* pval) { return dbPutField(&addr,(type==SDF_NUM ? DBR_DOUBLE : DBR_STRING),pval,1) == 0; } -bool PUT_VALUE_INT(ADDRESS addr, PV_INT_TYPE *val) +bool PUT_VALUE_INT(ADDRESS addr, const PV_INT_TYPE *val) { return dbPutField(&addr, DBR_LONG, val, 1) == 0; } @@ -584,12 +611,16 @@ int parseLine(char *s, int bufSize, char *str1, char *str2, char *str3, char *st /// @param[in] numEntries Number of entries in the table. /// @param[in] dcsErrtable Pointer to table /// @param[out] sc Pointer to change counters. -void clearTableSelections(int numEntries,SET_ERR_TABLE *dcsErrTable, int sc[]) +template <std::size_t entry_count> +void clearTableSelections(fixed_size_vector<SET_ERR_TABLE, entry_count>& dcsErrTable, int sc[]) { -int ii; + int ii; for(ii=0;ii<3;ii++) sc[ii] = 0; - for(ii=0;ii<numEntries;ii++) dcsErrTable[ii].chFlag = 0; - for(ii=0;ii<numEntries;ii++) dcsErrTable[ii].filtNum = -1; + for (auto& entry:dcsErrTable) + { + entry.chFlag = 0; + entry.filtNum = -1; + } } @@ -598,40 +629,43 @@ int ii; /// @param[in] dcsErrtable Pointer to table /// @param[out] sc Pointer to change counters. /// @param[in] selectOp Present selection. -void setAllTableSelections(int numEntries,SET_ERR_TABLE *dcsErrTable, int sc[],int selectOpt) +void setAllTableSelections(table_range dcsErrTable, int sc[],int selectOpt) { -int ii; -int filtNum = -1; -long status = 0; + int filtNum = -1; + long status = 0; + switch(selectOpt) { case 1: sc[0] = 0; - for(ii=0;ii<numEntries;ii++) { - dcsErrTable[ii].chFlag |= 2; + for (auto& entry:dcsErrTable) + { + entry.chFlag |= 2; sc[0] ++; - if(dcsErrTable[ii].chFlag & 4) { - dcsErrTable[ii].chFlag &= ~(4); + if(entry.chFlag & 4) { + entry.chFlag &= ~(4); sc[1] --; } } break; case 2: sc[1] = 0; - for(ii=0;ii<numEntries;ii++) { - dcsErrTable[ii].chFlag |= 4; + for (auto& entry:dcsErrTable) + { + entry.chFlag |= 4; sc[1] ++; - if(dcsErrTable[ii].chFlag & 2) { - dcsErrTable[ii].chFlag &= ~(2); + if(entry.chFlag & 2) { + entry.chFlag &= ~(2); sc[0] --; } } break; case 3: - sc[2] = numEntries; - for(ii=0;ii<numEntries;ii++) { - dcsErrTable[ii].chFlag |= 8; + sc[2] = std::distance(dcsErrTable.begin(), dcsErrTable.end()); + for (auto& entry:dcsErrTable) + { + entry.chFlag |= 8; - filtNum = dcsErrTable[ii].filtNum; + filtNum = entry.filtNum; if (filtNum >= 0) { if (filterMasks[filtNum] == filterTable[filtNum].mask) { filterMasks[filtNum] = ((ALL_SWSTAT_BITS & filterMasks[filtNum]) > 0 ? 0 : ~0); @@ -649,12 +683,12 @@ long status = 0; /// @param[in] index Number providing the index into the dcsErrTable /// @param[in] dcsErrTable Pointer to table /// @param[out] selectCounter Pointer to change counters -void changeSelectCB_uninit(int index, SET_ERR_TABLE *dcsErrTable, int selectCounter[]) +void changeSelectCB_uninit(SET_ERR_TABLE &errTableEntry, int selectCounter[]) { - int revertBit = dcsErrTable[index].chFlag & 2; - int acceptBit = dcsErrTable[index].chFlag & 4; - int monBit = dcsErrTable[index].chFlag & 8; - int otherBits = 0; //dcsErrTable[index].chFlag | ~(2 | 4 | 8); + int revertBit = errTableEntry.chFlag & 2; + int acceptBit = errTableEntry.chFlag & 4; + int monBit = errTableEntry.chFlag & 8; + int otherBits = 0; //errTableEntry.chFlag | ~(2 | 4 | 8); // revert is not defined on this table if (revertBit) { @@ -666,7 +700,7 @@ void changeSelectCB_uninit(int index, SET_ERR_TABLE *dcsErrTable, int selectCoun acceptBit = 4; selectCounter[1] ++; } - dcsErrTable[index].chFlag = revertBit | acceptBit | monBit | otherBits; + errTableEntry.chFlag = revertBit | acceptBit | monBit | otherBits; } /// Common routine to set/unset individual entries for table changes.. @@ -675,40 +709,42 @@ void changeSelectCB_uninit(int index, SET_ERR_TABLE *dcsErrTable, int selectCoun /// @param[in] totalItems Number items selected for change. /// @param[in] dcsErrtable Pointer to table /// @param[out] selectCounter Pointer to change counters. -void decodeChangeSelect(int selNum, int page, int totalItems, SET_ERR_TABLE *dcsErrTable, int selectCounter[], void (*cb)(int, SET_ERR_TABLE*, int*)) +void decodeChangeSelect(int selNum, int page, table_range dcsErrTable, int selectCounter[], void (*cb)(SET_ERR_TABLE&, int*)) { -int selectBit; -int selectLine; + int selectBit; + int selectLine; selectBit = selNum / 100; selectLine = selNum % 100 - 1; selNum += page * SDF_ERR_DSIZE; selectLine += page * SDF_ERR_DSIZE; - if(selectLine < totalItems) { + + auto selection = dcsErrTable.begin() + selectLine; + if(selection < dcsErrTable.end()) { switch (selectBit) { case 0: - dcsErrTable[selectLine].chFlag ^= 2; - if(dcsErrTable[selectLine].chFlag & 2) selectCounter[0] ++; + selection->chFlag ^= 2; + if(selection->chFlag & 2) selectCounter[0] ++; else selectCounter[0] --; - if(dcsErrTable[selectLine].chFlag & 4) { - dcsErrTable[selectLine].chFlag &= ~(4); + if(selection->chFlag & 4) { + selection->chFlag &= ~(4); selectCounter[1] --; } break; case 1: - dcsErrTable[selectLine].chFlag ^= 4; - if(dcsErrTable[selectLine].chFlag & 4) selectCounter[1] ++; + selection->chFlag ^= 4; + if(selection->chFlag & 4) selectCounter[1] ++; else selectCounter[1] --; - if(dcsErrTable[selectLine].chFlag & 2) { - dcsErrTable[selectLine].chFlag &= ~(2); + if(selection->chFlag & 2) { + selection->chFlag &= ~(2); selectCounter[0] --; } break; case 2: /* we only handle non-filter bank entries here */ - if (dcsErrTable[selectLine].filtNum < 0) { - dcsErrTable[selectLine].chFlag ^= 8; - if(dcsErrTable[selectLine].chFlag & 8) selectCounter[2] ++; + if (selection->filtNum < 0) { + selection->chFlag ^= 8; + if(selection->chFlag & 8) selectCounter[2] ++; else selectCounter[2] --; } break; @@ -716,7 +752,7 @@ int selectLine; break; } if (cb) - cb(selectLine, dcsErrTable, selectCounter); + cb(*selection, selectCounter); } } @@ -852,10 +888,10 @@ void createSwitchText(FILTER_TABLE *filter, StringLike& dest) { } /// Routine to check filter switch settings and provide info on switches not set as requested. -/// @param[in] fcount Number of filters in the control model. /// @param[in] monitorAll Global monitoring flag. /// @return Number of errant switch settings found. -int checkFilterSwitches(int fcount, SET_ERR_TABLE setErrTable[], int monitorAll, int displayall, int wcflag, char *wcstr, int *diffcntr) +template <std::size_t entry_count> +int checkFilterSwitches(fixed_size_vector<SET_ERR_TABLE, entry_count>& setErrTable, int monitorAll, int displayall, int wcflag, char *wcstr, int *diffcntr) { unsigned int refVal=0; unsigned int presentVal=0; @@ -863,7 +899,7 @@ unsigned int x=0,y=0; unsigned int mask = 0; unsigned int maskedRefVal = 0; unsigned int maskedSwReqVal = 0; -int ii=0,jj=0; +int jj=0; int errCnt = 0; fixed_string<64>swname[3]; fixed_string<64> tmpname; @@ -880,15 +916,17 @@ ADDRESS paddr1; ADDRESS paddr2; long status=0; - for(ii=0;ii<fcount;ii++) - { + auto filtNum = -1; + for (const auto& curFilt:filterTable) + { + ++filtNum; bzero(buffer, sizeof(struct buffer)*2); - swname[0] = filterTable[ii].fname; + swname[0] = curFilt.fname; swname[0] += "SW1S"; - swname[1] = filterTable[ii].fname; + swname[1] = curFilt.fname; swname[1] += "SW2S"; - swname[2] = filterTable[ii].fname; + swname[2] = curFilt.fname; swname[2] += "SWSTR"; GET_ADDRESS(swname[0],&paddr); GET_VALUE_INT(paddr,&(buffer[0].rval),&(buffer[0].t), 0); @@ -897,15 +935,17 @@ long status=0; for(jj=0;jj<2;jj++) { if(buffer[jj].rval > 0xffff || buffer[jj].rval < 0) // Switch setting overrange { - setErrTable[errCnt].chname = swname[jj]; - setErrTable[errCnt].burtset = " "; - setErrTable[errCnt].liveset.printf("0x%x", buffer[jj].rval); - setErrTable[errCnt].diff = "OVERRANGE"; - setErrTable[errCnt].liveval = 0.0; - setErrTable[errCnt].sigNum = filterTable[ii].sw[jj]; + setErrTable.emplace_back(); + auto& curErr = setErrTable.back(); + curErr.chname = swname[jj]; + curErr.burtset = " "; + curErr.liveset.printf("0x%x", buffer[jj].rval); + curErr.diff = "OVERRANGE"; + curErr.liveval = 0.0; + curErr.sigNum = curFilt.sw[jj]; // take the latest change time between the SW1S & SW2S channels mtime = (buffer[0].t >= buffer[1].t ? buffer[0].t : buffer[1].t); - setErrTable[errCnt].timeset = ctime(&mtime); + curErr.timeset = ctime(&mtime); buffer[jj].rval &= 0xffff; errCnt ++; } @@ -916,39 +956,41 @@ long status=0; x = refVal; GET_ADDRESS(swname[2],&paddr2); PUT_VALUE_STR(paddr2,swstrE); - setErrTable[errCnt].filtNum = -1; + //setErrTable[errCnt].filtNum = -1; - mask = (unsigned int)filterTable[ii].mask; + mask = (unsigned int)curFilt.mask; maskedRefVal = refVal & mask; - maskedSwReqVal = filterTable[ii].swreq & mask; - if(( maskedRefVal != maskedSwReqVal && errCnt < SDF_ERR_TSIZE && (mask || monitorAll) && filterTable[ii].init) ) + maskedSwReqVal = curFilt.swreq & mask; + if(( maskedRefVal != maskedSwReqVal && errCnt < SDF_ERR_TSIZE && (mask || monitorAll) && curFilt.init) ) *diffcntr += 1; - if(( maskedRefVal != maskedSwReqVal && errCnt < SDF_ERR_TSIZE && (mask || monitorAll) && filterTable[ii].init) || displayall) + if(( maskedRefVal != maskedSwReqVal && errCnt < SDF_ERR_TSIZE && (mask || monitorAll) && curFilt.init) || displayall) { filtStrBitConvert(1,refVal,swstrE); - filtStrBitConvert(1,filterTable[ii].swreq,swstrB); + filtStrBitConvert(1,curFilt.swreq,swstrB); x = maskedRefVal ^ maskedSwReqVal; filtStrBitConvert(1,x,swstrD); - tmpname = filterTable[ii].fname; + tmpname = curFilt.fname; if(!wcflag || (wcflag && (strstr(tmpname.c_str(),wcstr) != NULL))) { - setErrTable[errCnt].chname = tmpname; - setErrTable[errCnt].burtset = swstrB; - setErrTable[errCnt].liveset = swstrE; - setErrTable[errCnt].diff = swstrD; - - setErrTable[errCnt].liveval = 0.0; - setErrTable[errCnt].sigNum = filterTable[ii].sw[0] + (filterTable[ii].sw[1] * SDF_MAX_TSIZE); - setErrTable[errCnt].filtNum = ii; - setErrTable[errCnt].sw[0] = buffer[0].rval; - setErrTable[errCnt].sw[1] = buffer[1].rval; - if(filterTable[ii].mask & ALL_SWSTAT_BITS) setErrTable[errCnt].chFlag |= 0x1; - else setErrTable[errCnt].chFlag &= 0xe; - - // take the latest change time between the SW1S & SW2S channels - mtime = (buffer[0].t >= buffer[1].t ? buffer[0].t : buffer[1].t); - setErrTable[errCnt].timeset = ctime(&mtime); - errCnt ++; + setErrTable.emplace_back(); + auto& curErr = setErrTable.back(); + curErr.chname = tmpname; + curErr.burtset = swstrB; + curErr.liveset = swstrE; + curErr.diff = swstrD; + + curErr.liveval = 0.0; + curErr.sigNum = curFilt.sw[0] + (curFilt.sw[1] * SDF_MAX_TSIZE); + curErr.filtNum = filtNum; + curErr.sw[0] = buffer[0].rval; + curErr.sw[1] = buffer[1].rval; + if(curFilt.mask & ALL_SWSTAT_BITS) curErr.chFlag |= 0x1; + else curErr.chFlag &= 0xe; + + // take the latest change time between the SW1S & SW2S channels + mtime = (buffer[0].t >= buffer[1].t ? buffer[0].t : buffer[1].t); + curErr.timeset = ctime(&mtime); + errCnt ++; } } } @@ -1008,42 +1050,36 @@ void logFileEntry(const char *message) /// Function to read all settings, listed in main table, from the EPICS database. /// @param[in] numchans The number of channels listed in the main table. /// @param[out] times (Optional) An array of at least numchans time_t values to put change times in -void getEpicsSettings(int numchans, time_t *times) +void getEpicsSettings() { -int ii; -long status; -int chcount = 0; -double dval = 0; -ADDRESS geaddr; -bool statusR = false; -char sval[64]; -time_t *change_t = 0; - - for(ii=0;ii<numchans;ii++) - { - // Load main table settings into temp (cdTableP) - cdTableP[ii].chname = cdTable[ii].chname; - cdTableP[ii].datatype = cdTable[ii].datatype; - cdTableP[ii].mask = cdTable[ii].mask; - cdTableP[ii].initialized = cdTable[ii].initialized; - // Find address of channel - if(GET_ADDRESS(cdTableP[ii].chname,&geaddr)) { - change_t = ( times ? ×[ii] : 0 ); - if(cdTableP[ii].datatype == SDF_NUM) - { - statusR = GET_VALUE_NUM(geaddr,&dval,change_t, NULL); //&(cdTableP[ii].connected)); - if (statusR) cdTableP[ii].data.chval = (cdTable[ii].filterswitch ? (int)dval & 0xffff : dval); - } else { - statusR = GET_VALUE_STR(geaddr,sval,sizeof(sval),change_t, NULL); //&(cdTableP[ii].connected)); - if(statusR) sprintf(cdTableP[ii].data.strval,"%s",sval); - } - chcount ++; - } - } -} - -void encodeBURTString(char *src, char *dest, int dest_size) { - char *ch = 0; + cdTableP.clear(); + std::transform(cdTable.begin(), cdTable.end(), std::back_inserter( cdTableP), + [](const CDS_CD_TABLE& entry) -> CDS_CD_TABLE { + CDS_CD_TABLE result; + result.chname = entry.chname; + result.datatype = entry.datatype; + result.mask = entry.mask; + result.initialized = entry.initialized; + + ADDRESS geaddr; + if(GET_ADDRESS(result.chname,&geaddr)) { + time_t* change_t = nullptr; + if(result.datatype == SDF_NUM) + { + double dval; + if (GET_VALUE_NUM(geaddr,&dval,change_t, NULL)) { + result.data.chval = (entry.filterswitch ? (int) dval & 0xffff : dval); + } + } else { + GET_VALUE_STR(geaddr,result.data.strval, sizeof(result.data.strval),change_t, NULL); + } + } + return result; + }); +} + +void encodeBURTString(const char *src, char *dest, int dest_size) { + const char *ch = 0; int expand = 0; if (!src || !dest || dest_size < 1) return; @@ -1073,10 +1109,11 @@ void encodeBURTString(char *src, char *dest, int dest_size) { #define SDF_FILE_PARAMS_ONLY 1 #define SDF_FILE_BURT_ONLY 2 /// Common routine for saving table data to BURT files. +template <std::size_t entry_count> bool writeTable2File(char *burtdir, char *filename, ///< Name of file to write int ftype, ///< Type of file to write - CDS_CD_TABLE *myTable) ///< Table to be written. + fixed_size_vector<CDS_CD_TABLE, entry_count>& myTable) ///< Table to be written. { int ii; FILE *csFile=0; @@ -1113,18 +1150,18 @@ bool writeTable2File(char *burtdir, fprintf(csFile,"%s\n","Req File: autoBurt.req "); fprintf(csFile,"%s\n","--- End BURT header"); - for(ii=0;ii<chNum;ii++) + for (const auto& entry:myTable) { - if (myTable[ii].filterswitch) { - if ((myTable[ii].mask & ALL_SWSTAT_BITS)== ~0) { + if (entry.filterswitch) { + if ((entry.mask & ALL_SWSTAT_BITS)== ~0) { strcpy(monitorstring, "1"); - } else if ((myTable[ii].mask & ALL_SWSTAT_BITS) == 0) { + } else if ((entry.mask & ALL_SWSTAT_BITS) == 0) { strcpy(monitorstring, "0"); } else { - snprintf(monitorstring, sizeof(monitorstring), "0x%x", myTable[ii].mask); + snprintf(monitorstring, sizeof(monitorstring), "0x%x", entry.mask); } } else { - if (myTable[ii].mask) + if (entry.mask) strcpy(monitorstring,"1"); else strcpy(monitorstring,"0"); @@ -1133,28 +1170,28 @@ bool writeTable2File(char *burtdir, { case SDF_WITH_INIT_FLAG: if(myTable[ii].datatype == SDF_NUM) { - fprintf(csFile,"%s %d %.*e %s %d\n",myTable[ii].chname,1,precision,myTable[ii].data.chval,monitorstring,myTable[ii].initialized); + fprintf(csFile,"%s %d %.*e %s %d\n",entry.chname,1,precision,entry.data.chval,monitorstring,entry.initialized); } else { - encodeBURTString(myTable[ii].data.strval, burtString, sizeof(burtString)); - fprintf(csFile,"%s %d %s %s %d\n",myTable[ii].chname,1,burtString,monitorstring,myTable[ii].initialized); + encodeBURTString(entry.data.strval, burtString, sizeof(burtString)); + fprintf(csFile,"%s %d %s %s %d\n",entry.chname,1,burtString,monitorstring,entry.initialized); } break; case SDF_FILE_PARAMS_ONLY: - if(myTable[ii].initialized) { - if(myTable[ii].datatype == SDF_NUM) { - fprintf(csFile,"%s %d %.*e %s\n",myTable[ii].chname,1,precision,myTable[ii].data.chval,monitorstring); + if(entry.initialized) { + if(entry.datatype == SDF_NUM) { + fprintf(csFile,"%s %d %.*e %s\n",entry.chname,1,precision,entry.data.chval,monitorstring); } else { - encodeBURTString(myTable[ii].data.strval, burtString, sizeof(burtString)); - fprintf(csFile,"%s %d %s %s\n",myTable[ii].chname,1,burtString,monitorstring); + encodeBURTString(entry.data.strval, burtString, sizeof(burtString)); + fprintf(csFile,"%s %d %s %s\n",entry.chname,1,burtString,monitorstring); } } break; case SDF_FILE_BURT_ONLY: - if(myTable[ii].datatype == SDF_NUM) { - fprintf(csFile,"%s %d %.*e\n",myTable[ii].chname,1,precision,myTable[ii].data.chval); + if(entry.datatype == SDF_NUM) { + fprintf(csFile,"%s %d %.*e\n",entry.chname,1,precision,entry.data.chval); } else { - encodeBURTString(myTable[ii].data.strval, burtString, sizeof(burtString)); - fprintf(csFile,"%s %d %s \n",myTable[ii].chname,1,burtString); + encodeBURTString(entry.data.strval, burtString, sizeof(burtString)); + fprintf(csFile,"%s %d %s \n",entry.chname,1,burtString); } break; default: @@ -1288,7 +1325,7 @@ char shortfilename[64]; break; case SAVE_EPICS_AS_SDF: // printf("Save epics as sdf\n"); - getEpicsSettings(chNum, NULL); + getEpicsSettings(); if(!writeTable2File(sdfdir,filename,SDF_FILE_PARAMS_ONLY,cdTableP)) { sprintf(filemsg,"FAILED EPICS SAVE %s",filename); logFileEntry(filemsg); @@ -1308,6 +1345,8 @@ char shortfilename[64]; status = dbPutField(&staddr,DBR_STRING,timestring,1); status = dbPutField(&rladdr,DBR_STRING,timestring,1); return(0); + + // I can type above your caret } @@ -1522,9 +1561,9 @@ double liveval = 0.0; } /// Common routine to load monitoring tables into EPICS channels for MEDM screen. +template <std::size_t entry_count> int reportSetErrors(char *pref, ///< Channel name prefix from EPICS environment. - int numEntries, ///< Number of entries in table to be reported. - SET_ERR_TABLE setErrTable[], ///< Which table to report to EPICS channels. + fixed_size_vector<SET_ERR_TABLE , entry_count>& setErrTable, ///< Which table to report to EPICS channels. int page, ///< Which page of 40 to display. int linkInFilters) ///< Should the SDF_FM_LINE values be set. { @@ -1560,21 +1599,22 @@ int minusOne = -1; // Get the page number to display mypage = page; - // Calculat start index to the diff table. + // Calculate start index to the diff table. myindex = page * SDF_ERR_DSIZE; + int numEntries = setErrTable.size(); if(myindex == numEntries && numEntries > 0) { mypage --; myindex = mypage * SDF_ERR_DSIZE; } // If index is > number of entries in the table, then page back. - if(myindex > numEntries) { + if(myindex > numEntries) { mypage = numEntries / SDF_ERR_DSIZE; myindex = mypage * SDF_ERR_DSIZE; - } + } // Set the stop index to the diff table. rc = myindex + SDF_ERR_DSIZE; // If stop index beyond last diff table entry, set it to last entry. - if(rc > numEntries) rc = numEntries; + if(rc > numEntries) rc = numEntries; numDisp = rc - myindex; // Fill in table entries. @@ -1583,7 +1623,7 @@ int minusOne = -1; sprintf(s, "%s_%s_STAT%d", pref,"SDF_SP", lineNum); status = dbNameToAddr(s,&saddr); //sprintf(stmp, "%s%s", (setErrTable[ii].filtNum >= 0 ? "* " : ""), setErrTable[ii].chname); - status = dbPutField(&saddr,DBR_UCHAR,&setErrTable[ii].chname,flength); + status = dbPutField(&saddr,DBR_UCHAR,setErrTable[ii].chname.c_str(),flength); sprintf(s1, "%s_%s_STAT%d_BURT", pref,"SDF_SP", lineNum); status = dbNameToAddr(s1,&baddr); @@ -1618,7 +1658,7 @@ int minusOne = -1; } // Clear out empty table entries. - for(ii=numDisp;ii<40;ii++) + for(ii=numDisp;ii<SDF_ERR_DSIZE;ii++) { sprintf(s, "%s_%s_STAT%d", pref,"SDF_SP", ii); status = dbNameToAddr(s,&saddr); @@ -1667,12 +1707,13 @@ int minusOne = -1; // - Present Value // - Time the present setting was applied. /// Setpoint monitoring routine. -int spChecker(int monitorAll, SET_ERR_TABLE setErrTable[],int wcVal, char *wcstring, int listAll, int *totalDiffs) +template <std::size_t entry_count> +int spChecker(int monitorAll, fixed_size_vector<SET_ERR_TABLE, entry_count>& setErrTable,int wcVal, char *wcstring, int listAll, int *totalDiffs) { int errCntr = 0; ADDRESS paddr; long status=0; - int ii; + //int ii; double rval; fixed_string<128> sval; time_t mtime; @@ -1698,28 +1739,32 @@ int spChecker(int monitorAll, SET_ERR_TABLE setErrTable[],int wcVal, char *wcstr */ #endif // Check filter switch settings first - errCntr = checkFilterSwitches(fmNum,setErrTable,monitorAll,listAll,wcVal,wcstring,&filtDiffs); - *totalDiffs = filtDiffs; - if(chNum) { - for(ii=0;ii<chNum;ii++) { + setErrTable.clear(); + errCntr = checkFilterSwitches(setErrTable,monitorAll,listAll,wcVal,wcstring,&filtDiffs); + *totalDiffs = filtDiffs; + + int index = -1; + for (auto& curSP: cdTable) + { + ++index; if((errCntr < SDF_ERR_TSIZE) && // Within table max size - ((cdTable[ii].mask != 0) || (monitorAll)) && // Channel is to be monitored - cdTable[ii].initialized && // Channel was set in BURT - cdTable[ii].filterswitch == 0 || // Not a filter switch channel - (listAll && cdTable[ii].filterswitch == 0)) + ((curSP.mask != 0) || (monitorAll)) && // Channel is to be monitored + curSP.initialized && // Channel was set in BURT + curSP.filterswitch == 0 || // Not a filter switch channel + (listAll && curSP.filterswitch == 0)) { localErr = 0; mtime = 0; // Find address of channel - GET_ADDRESS(cdTable[ii].chname,&paddr); + GET_ADDRESS(curSP.chname,&paddr); // If this is a digital data type, then get as double. - if(cdTable[ii].datatype == SDF_NUM) + if(curSP.datatype == SDF_NUM) { - GET_VALUE_NUM(paddr,&rval,&mtime, NULL); //&(cdTable[ii].connected)); - if(cdTable[ii].data.chval != rval || listAll) + GET_VALUE_NUM(paddr,&rval,&mtime, NULL); //&(curSP.connected)); + if(curSP.data.chval != rval || listAll) { - sdfdiff = fabs(cdTable[ii].data.chval - rval); - burtset.printf("%.10lf",cdTable[ii].data.chval); + sdfdiff = fabs(curSP.data.chval - rval); + burtset.printf("%.10lf",curSP.data.chval); liveset.printf("%.10lf",rval); liveval = rval; diffB2L.printf("%.8le",sdfdiff); @@ -1727,11 +1772,11 @@ int spChecker(int monitorAll, SET_ERR_TABLE setErrTable[],int wcVal, char *wcstr } // If this is a string type, then get as string. } else { - updateStrVarSetPoint(ii); - GET_VALUE_STR(paddr,sval,&mtime, NULL); //&(cdTable[ii].connected)); - if(sval != cdTable[ii].data.strval || listAll) + updateStrVarSetPoint(index); + GET_VALUE_STR(paddr,sval,&mtime, NULL); //&(curSP.connected)); + if(sval != curSP.data.strval || listAll) { - burtset = cdTable[ii].data.strval; + burtset = curSP.data.strval; liveset = sval; liveval = 0.0; diffB2L.printf("%s"," "); @@ -1739,30 +1784,31 @@ int spChecker(int monitorAll, SET_ERR_TABLE setErrTable[],int wcVal, char *wcstr } } if(localErr) *totalDiffs += 1; - if(localErr && wcVal && (strstr(cdTable[ii].chname.c_str(),wcstring) == NULL)) + if(localErr && wcVal && (strstr(curSP.chname.c_str(),wcstring) == NULL)) localErr = 0; // If a diff was found, then write info the EPICS setpoint diff table. if(localErr) { - setErrTable[errCntr].chname = cdTable[ii].chname; + setErrTable.emplace_back(); + auto& curErr = setErrTable.back(); + curErr.chname = curSP.chname; - setErrTable[errCntr].burtset = burtset; + curErr.burtset = burtset; - setErrTable[errCntr].liveset = liveset; - setErrTable[errCntr].liveval = liveval; - setErrTable[errCntr].diff = diffB2L; - setErrTable[errCntr].sigNum = ii; - setErrTable[errCntr].filtNum = -1; + curErr.liveset = liveset; + curErr.liveval = liveval; + curErr.diff = diffB2L; + curErr.sigNum = index; + curErr.filtNum = -1; localtimestring = ctime(&mtime); - setErrTable[errCntr].timeset = localtimestring; - if(cdTable[ii].mask) setErrTable[errCntr].chFlag |= 1; - else setErrTable[errCntr].chFlag &= ~(1); + curErr.timeset = localtimestring; + if(curSP.mask) curErr.chFlag |= 1; + else curErr.chFlag &= ~(1); errCntr ++; } } } - } return(errCntr); } @@ -1772,29 +1818,30 @@ int spChecker(int monitorAll, SET_ERR_TABLE setErrTable[],int wcVal, char *wcstr /// @param modTable[in] An array of SET_ERR_TABLE entries that hold the current views state to be merged with cdTable /// /// @remark modifies cdTable -int modifyTable(int numEntries,SET_ERR_TABLE modTable[]) +int modifyTable(table_range modTable) { -int ii,jj; -int fmIndex = -1; -unsigned int sn,sn1; -int found = 0; - for(ii=0;ii<numEntries;ii++) + int jj; + int fmIndex = -1; + unsigned int sn,sn1; + int found = 0; + + for (const auto& entry:modTable) { // if accept or monitor is set - if(modTable[ii].chFlag > 3) + if(entry.chFlag > 3) { found = 0; for(jj=0;jj<chNum;jj++) { - if (cdTable[jj].chname == modTable[ii].chname) { - if ( CHFLAG_ACCEPT_BIT(modTable[ii].chFlag) ) { - if(cdTable[jj].datatype == SDF_NUM) cdTable[jj].data.chval = modTable[ii].liveval;/* atof(modTable[ii].liveset);*/ - else sprintf(cdTable[jj].data.strval,"%s",modTable[ii].liveset); + if (cdTable[jj].chname == entry.chname) { + if ( CHFLAG_ACCEPT_BIT(entry.chFlag) ) { + if(cdTable[jj].datatype == SDF_NUM) cdTable[jj].data.chval = entry.liveval;/* atof(entry.liveset);*/ + else sprintf(cdTable[jj].data.strval,"%s",entry.liveset); cdTable[jj].initialized = 1; found = 1; fmIndex = cdTable[jj].filterNum; } - if(CHFLAG_MONITOR_BIT(modTable[ii].chFlag)) { + if(CHFLAG_MONITOR_BIT(entry.chFlag)) { fmIndex = cdTable[jj].filterNum; if (fmIndex >= 0 && fmIndex < SDF_MAX_FMSIZE) { // filter module use the manualy modified state, cannot just toggle @@ -1807,21 +1854,21 @@ int found = 0; } } } - if(modTable[ii].filtNum >= 0 && !found) { - fmIndex = modTable[ii].filtNum; + if(entry.filtNum >= 0 && !found) { + fmIndex = entry.filtNum; // printf("This is a filter from diffs = %s\n",filterTable[fmIndex].fname); filterTable[fmIndex].newSet = 1; - sn = modTable[ii].sigNum; + sn = entry.sigNum; sn1 = sn / SDF_MAX_TSIZE; sn %= SDF_MAX_TSIZE; - if(CHFLAG_ACCEPT_BIT(modTable[ii].chFlag)) { - cdTable[sn].data.chval = modTable[ii].sw[0]; + if(CHFLAG_ACCEPT_BIT(entry.chFlag)) { + cdTable[sn].data.chval = entry.sw[0]; cdTable[sn].initialized = 1; - cdTable[sn1].data.chval = modTable[ii].sw[1]; + cdTable[sn1].data.chval = entry.sw[1]; cdTable[sn1].initialized = 1; filterTable[fmIndex].init = 1; } - if(CHFLAG_MONITOR_BIT(modTable[ii].chFlag)) { + if(CHFLAG_MONITOR_BIT(entry.chFlag)) { filterTable[fmIndex].mask = filterMasks[fmIndex]; cdTable[sn].mask = filterMasks[fmIndex]; cdTable[sn1].mask = filterMasks[fmIndex]; @@ -1829,23 +1876,23 @@ int found = 0; } } } - newfilterstats(fmNum); + newfilterstats(); return(0); } -int resetSelectedValues(int errNum, SET_ERR_TABLE modTable[]) +template <std::size_t entry_count> +int resetSelectedValues(fixed_size_vector<SET_ERR_TABLE, entry_count>& modTable) { long status; -int ii; int sn; int sn1 = 0; ADDRESS saddr; - for(ii=0;ii<errNum;ii++) + for(const auto& entry:modTable) { - if (modTable[ii].chFlag & 2) + if (entry.chFlag & 2) { - sn = modTable[ii].sigNum; + sn = entry.sigNum; if(sn > SDF_MAX_TSIZE) { sn1 = sn / SDF_MAX_TSIZE; sn %= SDF_MAX_TSIZE; @@ -1863,10 +1910,10 @@ ADDRESS saddr; } /// This function sets filter module request fields to aid in decoding errant filter module switch settings. -void newfilterstats(int numchans) { +void newfilterstats() { ADDRESS paddr; long status; - int ii; + FILE *log=0; fixed_string<128> chname; unsigned int mask = 0x1ffff; @@ -1876,28 +1923,28 @@ void newfilterstats(int numchans) { unsigned int tmpL = 0; printf("In newfilterstats\n"); - for(ii=0;ii<numchans;ii++) { - if(filterTable[ii].newSet) { + for(auto& filterEntry:filterTable) { + if(filterEntry.newSet) { counter ++; - filterTable[ii].newSet = 0; - filterTable[ii].init = 1; - rsw1 = filterTable[ii].sw[0]; - rsw2 = filterTable[ii].sw[1]; - filterTable[ii].mask = cdTable[rsw1].mask | cdTable[rsw2].mask;; - cdTable[rsw1].mask = filterTable[ii].mask; - cdTable[rsw2].mask = filterTable[ii].mask; + filterEntry.newSet = 0; + filterEntry.init = 1; + rsw1 = filterEntry.sw[0]; + rsw2 = filterEntry.sw[1]; + filterEntry.mask = cdTable[rsw1].mask | cdTable[rsw2].mask;; + cdTable[rsw1].mask = filterEntry.mask; + cdTable[rsw2].mask = filterEntry.mask; tmpreq = ((unsigned int)cdTable[rsw1].data.chval & 0xffff) + (((unsigned int)cdTable[rsw2].data.chval & 0xffff) << 16); - filterTable[ii].swreq = filtCtrlBitConvert(tmpreq); + filterEntry.swreq = filtCtrlBitConvert(tmpreq); // Find address of channel - chname = filterTable[ii].fname; + chname = filterEntry.fname; chname += "SWREQ"; if(GET_ADDRESS(chname,&paddr)) { - tmpL = (unsigned int)filterTable[ii].swreq; + tmpL = (unsigned int)filterEntry.swreq; PUT_VALUE_INT(paddr,&tmpL); } // Find address of channel - chname = filterTable[ii].fname; + chname = filterEntry.fname; chname += "SWMASK"; if(GET_ADDRESS(chname,&paddr)) { PUT_VALUE_INT(paddr,&mask); @@ -1909,54 +1956,43 @@ void newfilterstats(int numchans) { } /// This function writes BURT settings to EPICS records. -int writeEpicsDb(int numchans, ///< Number of channels to write - CDS_CD_TABLE myTable[], ///< Table with data to be written. +template <std::size_t entry_count> +int writeEpicsDb(fixed_size_vector<CDS_CD_TABLE, entry_count>& myTable, ///< Table with data to be written. int command) ///< Write request. { ADDRESS paddr; long status; int ii; - // chNotFound = 0; switch (command) { case SDF_LOAD_DB_ONLY: case SDF_LOAD_PARTIAL: - for(ii=0;ii<numchans;ii++) { - // Find address of channel - if (GET_ADDRESS(myTable[ii].chname,&paddr)) - { - if (myTable[ii].datatype == SDF_NUM) - { - PUT_VALUE(paddr,SDF_NUM,&(myTable[ii].data.chval)); - } else { - PUT_VALUE(paddr,SDF_STR,myTable[ii].data.strval); - } - } - else { // Write errors to chan not found table. - printf("CNF for %s = %d\n",myTable[ii].chname,status); - #if 0 - if(chNotFound < SDF_ERR_TSIZE) { - sprintf(unknownChans[chNotFound].chname,"%s",myTable[ii].chname); - sprintf(unknownChans[chNotFound].liveset,"%s"," "); - unknownChans[chNotFound].liveval = 0.0; - sprintf(unknownChans[chNotFound].timeset,"%s"," "); - sprintf(unknownChans[chNotFound].diff,"%s"," "); - unknownChans[chNotFound].chFlag = 0; - } - chNotFound ++; - #endif - } - } - - // Set the SDF_FILE_LOADED environment var to 1, - // signalling to the epipcs sequencer to - // trigger a BURT_RESTORE + for (const auto& entry:myTable) + { + // Find address of channel + if (GET_ADDRESS(entry.chname,&paddr)) { - set_sdf_file_loaded(1); + if (entry.datatype == SDF_NUM) + { + PUT_VALUE(paddr,SDF_NUM,&(entry.data.chval)); + } else { + PUT_VALUE(paddr,SDF_STR,entry.data.strval); + } } - break; + else { // Write errors to chan not found table. + printf("CNF for %s = %d\n",entry.chname,status); + } + } + // Set the SDF_FILE_LOADED environment var to 1, + // signalling to the epipcs sequencer to + // trigger a BURT_RESTORE + + { + set_sdf_file_loaded(1); + } + break; case SDF_READ_ONLY: // If request was only to re-read the BURT file, then don't want to apply new settings. // This is typically the case where only mask fields were changed in the BURT file to @@ -1965,23 +2001,24 @@ int writeEpicsDb(int numchans, ///< Number of channels to write break; case SDF_RESET: // Only want to set those channels marked by a mask back to their original BURT setting. - for(ii=0;ii<numchans;ii++) { - // FIXME: check does this make sense w/ a bitmask in mask? - // can filter modules get here? It seems that they will, so would we need - // to mask the value we set ? - if(myTable[ii].mask) { - //Find address of channel - if (GET_ADDRESS(myTable[ii].chname,&paddr)) - { - if (myTable[ii].datatype == SDF_NUM) - { - PUT_VALUE(paddr,SDF_NUM,&(myTable[ii].data.chval)); - } else { - PUT_VALUE(paddr,SDF_STR,myTable[ii].data.strval); - } - } - } - } + for (const auto& entry: myTable) + { + // FIXME: check does this make sense w/ a bitmask in mask? + // can filter modules get here? It seems that they will, so would we need + // to mask the value we set ? + if(entry.mask) { + //Find address of channel + if (GET_ADDRESS(entry.chname,&paddr)) + { + if (entry.datatype == SDF_NUM) + { + PUT_VALUE(paddr,SDF_NUM,&(entry.data.chval)); + } else { + PUT_VALUE(paddr,SDF_STR,entry.data.strval); + } + } + } + } break; default: printf("writeEpicsDb setting routine got unknown request \n"); @@ -2047,7 +2084,7 @@ int readConfig( char *pref, ///< EPICS channel prefix from EPICS environment. getSdfTime(timestring, 256); if(command == SDF_RESET) { - lderror = writeEpicsDb(chNum,cdTable,command); + lderror = writeEpicsDb(cdTable,command); } else { printf("PARTIAL %s\n",sdfile); cdf = fopen(sdfile,"r"); @@ -2253,9 +2290,9 @@ int readConfig( char *pref, ///< EPICS channel prefix from EPICS environment. fclose(cdf); fclose(adf); printf("Loading epics %d\n",chNumP); - lderror = writeEpicsDb(chNumP,cdTableP,command); + lderror = writeEpicsDb(cdTableP,command); sleep(2); - newfilterstats(fmNum); + newfilterstats(); fmtInit = 1; } @@ -2307,40 +2344,50 @@ void registerFilters() { /// Provide initial values to the filterMasks arrray and the SDF_FM_MASK and SDF_FM_MASK_CTRL variables /// -void setupFMArrays(char *pref, int *fmMasks, dbAddr *fmMaskAddr, dbAddr *fmCtrlAddr) { +void setupFMArrays(char *pref,fixed_size_vector<int, SDF_MAX_FMSIZE>& fmMasks, + fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>& fmMaskAddr, + fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>& fmCtrlAddr) { int ii = 0; int sw1 = 0; int sw2 = 0; - long status = 0; - char name[256]; - char ctrl[256]; + fixed_string<256> name; + fixed_string<256> ctrl; int zero = 0; - for (ii = 0; ii < SDF_MAX_FMSIZE; ++ii) { - sw1 = filterTable[ii].sw[0]; - sw2 = filterTable[ii].sw[1]; - fmMasks[ii] = filterTable[ii].mask = cdTable[sw1].mask | cdTable[sw2].mask; + fmMasks.clear(); + fmMaskAddr.clear(); + fmCtrlAddr.clear(); + for (ii = 0; ii < filterTable.size(); ++ii) + { + sw1 = filterTable[ii].sw[0]; + sw2 = filterTable[ii].sw[1]; + fmMasks[ii] = filterTable[ii].mask = cdTable[sw1].mask | cdTable[sw2].mask; - sprintf(name, "%s_SDF_FM_MASK_%d", pref, ii); - status = dbNameToAddr(name, &fmMaskAddr[ii]); - status = dbPutField(&fmMaskAddr[ii],DBR_LONG,&(fmMasks[ii]),1); + name.printf("%s_SDF_FM_MASK_%d", pref, ii); + fmMaskAddr.emplace_back(); + dbNameToAddr(name.c_str(), &fmMaskAddr[ii]); + dbPutField(&fmMaskAddr[ii],DBR_LONG,&(fmMasks[ii]),1); - sprintf(ctrl, "%s_SDF_FM_MASK_CTRL_%d", pref, ii); - status = dbNameToAddr(ctrl, &fmCtrlAddr[ii]); - status = dbPutField(&fmCtrlAddr[ii],DBR_LONG,&zero,1); + ctrl.printf("%s_SDF_FM_MASK_CTRL_%d", pref, ii); + fmCtrlAddr.emplace_back(); + dbNameToAddr(ctrl.c_str(), &fmCtrlAddr[ii]); + dbPutField(&fmCtrlAddr[ii],DBR_LONG,&zero,1); - } + } } /// Copy the filter mask information from cdTable into fmMasks /// -void resyncFMArrays(int *fmMasks, dbAddr *fmMaskAddr) { +void resyncFMArrays(fixed_size_vector<int, SDF_MAX_FMSIZE>&fmMasks, + fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>& fmMaskAddr) +{ int ii = 0; int sw1 = 0; int sw2 = 0; long status = 0; - for (ii = 0; ii < SDF_MAX_FMSIZE; ++ii) { + + for (ii = 0; ii < filterTable.size(); ++ii) { sw1 = filterTable[ii].sw[0]; sw2 = filterTable[ii].sw[1]; fmMasks[ii] = filterTable[ii].mask = (cdTable[sw1].mask | cdTable[sw2].mask) & ALL_SWSTAT_BITS; @@ -2364,7 +2411,11 @@ void resyncFMArrays(int *fmMasks, dbAddr *fmMaskAddr) { /// /// @remark Each of the input arrays is expected to have a length of SDF_MAX_FMSIZE /// with fmNum in actual use. -void processFMChanCommands(int *fMask, dbAddr *fmMaskAddr, dbAddr *fmCtrlAddr, int *selectCounter, int errCnt, SET_ERR_TABLE *setErrTable) { +void processFMChanCommands( + fixed_size_vector<int, SDF_MAX_FMSIZE>& fMask, + fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>& fmMaskAddr, + fixed_size_vector<dbAddr, SDF_MAX_FMSIZE>& fmCtrlAddr, + int *selectCounter, table_range setErrTable) { int ii = 0; int jj = 0; int refMask = 0; @@ -2376,7 +2427,8 @@ void processFMChanCommands(int *fMask, dbAddr *fmMaskAddr, dbAddr *fmCtrlAddr, i long nvals = 1; int foundCh = 0; - for (ii = 0; ii < SDF_MAX_FMSIZE && ii < fmNum; ++ii) { + //std::distance(setErrTable.begin(), setErrTable.end()); + for (ii = 0; ii < filterTable.size(); ++ii) { status = dbGetField(&fmCtrlAddr[ii], DBR_LONG, &ctrl, &ropts, &nvals, NULL); // only do work if there is a change @@ -2393,10 +2445,17 @@ void processFMChanCommands(int *fMask, dbAddr *fmMaskAddr, dbAddr *fmCtrlAddr, i foundCh = 0; /* if there is a change, update4 the selection count) */ if (differsPre != differsPost) { - for (jj = 0; jj < errCnt && setErrTable[jj].filtNum >= 0 && setErrTable[jj].filtNum != ii; ++jj) {} - if (jj < errCnt && setErrTable[jj].filtNum == ii) { - setErrTable[jj].chFlag ^= CHFLAG_MONITOR_BIT_VAL; - foundCh = setErrTable[jj].chFlag; + // search through setErrTable + //for (jj = 0; jj < errCnt && setErrTable[jj].filtNum >= 0 && setErrTable[jj].filtNum != ii; ++jj) {} + auto match = std::find_if(setErrTable.begin(), setErrTable.end(), [ii](const SET_ERR_TABLE& cur) -> bool { + return cur.filtNum == ii; + }); + // act on search + //if (jj < errCnt && setErrTable[jj].filtNum == ii) + if ( match != setErrTable.end()) + { + match->chFlag ^= CHFLAG_MONITOR_BIT_VAL; + foundCh = match->chFlag; selectCounter[2] += ( differsPre ? -1 : 1 ); } } @@ -2476,7 +2535,7 @@ bool getCAIndex(const char *entry, ADDRESS *addr) { return false; } -bool setCAValue(ADDRESS ii, SDF_TYPE type, void *data) +bool setCAValue(ADDRESS ii, SDF_TYPE type, const void *data) { bool result = false; int status = ECA_NORMAL; @@ -2492,12 +2551,12 @@ bool setCAValue(ADDRESS ii, SDF_TYPE type, void *data) return result; } -bool setCAValueLong(ADDRESS ii, PV_INT_TYPE *data) { +bool setCAValueLong(ADDRESS ii, const PV_INT_TYPE *data) { double tmp = 0.0; if (!data) return false; tmp = (double)*data; - return setCAValue(ii,SDF_NUM,(void*)&tmp); + return setCAValue(ii,SDF_NUM,(const void*)&tmp); } bool syncEpicsDoubleValue(ADDRESS index, double *dest, time_t *tp, int *connp) { @@ -3282,8 +3341,8 @@ int main(int argc,char *argv[]) char *fotonDiffFile = getenv("FOTON_DIFF_FILE"); char *logdir = getenv("LOG_DIR"); char myDiffCmd[256]; - SET_ERR_TABLE *currentTable = 0; - int currentTableCnt = 0; + table_range currentTable; + if(stat(logdir, &st) == -1) mkdir(logdir,0777); // strcat(sdf,"_safe"); @@ -3509,7 +3568,7 @@ int main(int argc,char *argv[]) status = checkFileMod( coeffFile, &coeffFileMt, 1 ); status = checkFileMod( fotonFile, &fotonFileMt, 1 ); - reportSetErrors(pref, 0,setErrTable,0,1); + reportSetErrors(pref,setErrTable,0,1); sleep(1); // Need to wait before first restore to allow sequencers time to do their initialization. cdSort = spChecker(monFlag,cdTableList,wcVal,wcstring,1,&status); @@ -3591,7 +3650,7 @@ int main(int argc,char *argv[]) setChans = chNum - fmNum; status = dbPutField(&fulldbcntaddr,DBR_LONG,&setChans,1); // Sort channels for data reporting via the MEDM table. - getEpicsSettings(chNum,NULL); + getEpicsSettings(); noMon = createSortTableEntries(chNum,0,"",&noInit,NULL); // Calculate and report number of channels NOT being monitored. status = dbPutField(&monchancntaddr,DBR_LONG,&chNotMon,1); @@ -3667,23 +3726,23 @@ int main(int argc,char *argv[]) case SDF_TABLE_DIFFS: // Need to clear selections when moving between tables. if(lastTable != SDF_TABLE_DIFFS) { - clearTableSelections(sperror,setErrTable, selectCounter); + clearTableSelections(setErrTable, selectCounter); resyncFMArrays(filterMasks,fmMaskChan); confirmVal = 0; } - pageDisp = reportSetErrors(pref, sperror,setErrTable,pageNum,1); - currentTable = setErrTable; - currentTableCnt = sperror; + pageDisp = reportSetErrors(pref, setErrTable,pageNum,1); + currentTable = make_range(setErrTable); + status = dbPutField(&sorttableentriesaddr,DBR_LONG,&sperror,1); status = dbGetField(&resetoneaddr,DBR_LONG,&resetNum,&ropts,&nvals,NULL); if(selectAll) { - setAllTableSelections(sperror,setErrTable, selectCounter,selectAll); + setAllTableSelections(make_range(setErrTable), selectCounter,selectAll); } if(resetNum) { - decodeChangeSelect(resetNum, pageDisp, sperror, setErrTable,selectCounter, NULL); + decodeChangeSelect(resetNum, pageDisp, make_range(setErrTable),selectCounter, NULL); } if(confirmVal) { - if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(sperror, setErrTable); + if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(setErrTable); if((selectCounter[1] || selectCounter[2]) && (confirmVal & 2)) { // Save present table as timenow. status = dbGetField(&loadedfile_addr,DBR_STRING,backupName,&ropts,&nvals,NULL); @@ -3691,7 +3750,7 @@ int main(int argc,char *argv[]) savesdffile(SAVE_TABLE_AS_SDF,SAVE_TIME_NOW,sdfDir,modelname,sdfile,saveasfilename,backupName, savefileaddr,savetimeaddr,reloadtimeaddr); // Overwrite the table with new values - status = modifyTable(sperror,setErrTable); + status = modifyTable(make_range(setErrTable)); // Overwrite file savesdffile(SAVE_TABLE_AS_SDF,SAVE_OVERWRITE,sdfDir,modelname,sdfile,saveasfilename, backupName,savefileaddr,savetimeaddr,reloadtimeaddr); @@ -3699,7 +3758,7 @@ int main(int argc,char *argv[]) status = checkFileMod( sdffileloaded, &sdfFileMt, 1 ); writeTable2File(sdfDir,bufile,SDF_WITH_INIT_FLAG,cdTable); } - clearTableSelections(sperror,setErrTable, selectCounter); + clearTableSelections(setErrTable, selectCounter); resyncFMArrays(filterMasks,fmMaskChan); confirmVal = 0; status = dbPutField(&confirmwordaddr,DBR_LONG,&confirmVal,1); @@ -3711,42 +3770,41 @@ int main(int argc,char *argv[]) case SDF_TABLE_NOT_FOUND: // Need to clear selections when moving between tables. if(lastTable != SDF_TABLE_NOT_FOUND) { - clearTableSelections(sperror,setErrTable, selectCounter); + clearTableSelections(setErrTable, selectCounter); resyncFMArrays(filterMasks,fmMaskChan); confirmVal = 0; } - pageDisp = reportSetErrors(pref, chNotFound,unknownChans,pageNum,1); - currentTable = unknownChans; - currentTableCnt = chNotFound; + pageDisp = reportSetErrors(pref, unknownChans,pageNum,1); + currentTable = make_range(unknownChans); + status = dbPutField(&sorttableentriesaddr,DBR_LONG,&chNotFound,1); /*if (resetNum > 200) { - decodeChangeSelect(resetNum, pageDisp, chNotFound, unknownChans,selectCounter, NULL); + decodeChangeSelect(resetNum, pageDisp, make_range(unknownChans),selectCounter, NULL); }*/ lastTable = SDF_TABLE_NOT_FOUND; break; case SDF_TABLE_NOT_INIT: if(lastTable != SDF_TABLE_NOT_INIT) { - clearTableSelections(sperror,setErrTable, selectCounter); + clearTableSelections(setErrTable, selectCounter); resyncFMArrays(filterMasks,fmMaskChan); confirmVal = 0; } if (!freezeTable) - getEpicsSettings(chNum,NULL); + getEpicsSettings(); noMon = createSortTableEntries(chNum,wcVal,wcstring,&noInit,NULL); - pageDisp = reportSetErrors(pref, noInit, uninitChans,pageNum,1); - currentTable = uninitChans; - currentTableCnt = noInit; + pageDisp = reportSetErrors(pref, uninitChans,pageNum,1); + currentTable = make_range(uninitChans); status = dbGetField(&resetoneaddr,DBR_LONG,&resetNum,&ropts,&nvals,NULL); if(selectAll == 2 || selectAll == 3) { - setAllTableSelections(noInit,uninitChans,selectCounter,selectAll); + setAllTableSelections(make_range(uninitChans),selectCounter,selectAll); if (selectAll == 3) - setAllTableSelections(noInit,uninitChans,selectCounter,2); + setAllTableSelections(make_range(uninitChans),selectCounter,2); } if(resetNum > 100) { - decodeChangeSelect(resetNum, pageDisp, noInit, uninitChans,selectCounter, changeSelectCB_uninit); + decodeChangeSelect(resetNum, pageDisp, make_range(uninitChans),selectCounter, changeSelectCB_uninit); } if(confirmVal) { - if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(noInit, uninitChans); + if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(uninitChans); if(selectCounter[1] && (confirmVal & 2)) { // Save present table as timenow. status = dbGetField(&loadedfile_addr,DBR_STRING,backupName,&ropts,&nvals,NULL); @@ -3754,7 +3812,7 @@ int main(int argc,char *argv[]) savesdffile(SAVE_TABLE_AS_SDF,SAVE_TIME_NOW,sdfDir,modelname,sdfile,saveasfilename,backupName, savefileaddr,savetimeaddr,reloadtimeaddr); // Overwrite the table with new values - status = modifyTable(noInit,uninitChans); + status = modifyTable(make_range(uninitChans)); // Overwrite file savesdffile(SAVE_TABLE_AS_SDF,SAVE_OVERWRITE,sdfDir,modelname,sdfile,saveasfilename, backupName,savefileaddr,savetimeaddr,reloadtimeaddr); @@ -3762,7 +3820,7 @@ int main(int argc,char *argv[]) status = checkFileMod( sdffileloaded, &sdfFileMt, 1 ); writeTable2File(sdfDir,bufile,SDF_WITH_INIT_FLAG,cdTable); } - clearTableSelections(chNotInit,uninitChans, selectCounter); + clearTableSelections(uninitChans, selectCounter); resyncFMArrays(filterMasks,fmMaskChan); confirmVal = 0; status = dbPutField(&confirmwordaddr,DBR_LONG,&confirmVal,1); @@ -3774,27 +3832,26 @@ int main(int argc,char *argv[]) case SDF_TABLE_NOT_MONITORED: D("In not mon\n"); if(lastTable != SDF_TABLE_NOT_MONITORED) { - clearTableSelections(noMon,unMonChans, selectCounter); + clearTableSelections(unMonChans, selectCounter); resyncFMArrays(filterMasks,fmMaskChan); confirmVal = 0; status = dbPutField(&confirmwordaddr,DBR_LONG,&confirmVal,1); } if (!freezeTable) - getEpicsSettings(chNum,NULL); //timeTable); + getEpicsSettings(); //timeTable); noMon = createSortTableEntries(chNum,wcVal,wcstring,&noInit,NULL);//timeTable); status = dbPutField(&monchancntaddr,DBR_LONG,&chNotMon,1); - pageDisp = reportSetErrors(pref, noMon, unMonChans,pageNum,1); - currentTable = unMonChans; - currentTableCnt = noMon; + pageDisp = reportSetErrors(pref, unMonChans,pageNum,1); + currentTable = make_range(unMonChans); status = dbGetField(&resetoneaddr,DBR_LONG,&resetNum,&ropts,&nvals,NULL); if(selectAll) { - setAllTableSelections(noMon,unMonChans,selectCounter,selectAll); + setAllTableSelections(make_range(unMonChans),selectCounter,selectAll); } if(resetNum) { - decodeChangeSelect(resetNum, pageDisp, noMon, unMonChans,selectCounter, NULL); + decodeChangeSelect(resetNum, pageDisp, make_range(unMonChans),selectCounter, NULL); } if(confirmVal) { - if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(noMon, unMonChans); + if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(unMonChans); if((selectCounter[1] || selectCounter[2]) && (confirmVal & 2)) { // Save present table as timenow. status = dbGetField(&loadedfile_addr,DBR_STRING,backupName,&ropts,&nvals,NULL); @@ -3802,7 +3859,7 @@ int main(int argc,char *argv[]) savesdffile(SAVE_TABLE_AS_SDF,SAVE_TIME_NOW,sdfDir,modelname,sdfile,saveasfilename,backupName, savefileaddr,savetimeaddr,reloadtimeaddr); // Overwrite the table with new values - status = modifyTable(noMon,unMonChans); + status = modifyTable(make_range(unMonChans)); // Overwrite file savesdffile(SAVE_TABLE_AS_SDF,SAVE_OVERWRITE,sdfDir,modelname,sdfile,saveasfilename, backupName,savefileaddr,savetimeaddr,reloadtimeaddr); @@ -3811,7 +3868,7 @@ int main(int argc,char *argv[]) writeTable2File(sdfDir,bufile,SDF_WITH_INIT_FLAG,cdTable); } // noMon = createSortTableEntries(chNum,wcVal,wcstring); - clearTableSelections(noMon,unMonChans, selectCounter); + clearTableSelections(unMonChans, selectCounter); resyncFMArrays(filterMasks,fmMaskChan); confirmVal = 0; status = dbPutField(&confirmwordaddr,DBR_LONG,&confirmVal,1); @@ -3822,24 +3879,23 @@ int main(int argc,char *argv[]) break; case SDF_TABLE_FULL: if(lastTable != SDF_TABLE_FULL) { - clearTableSelections(cdSort,cdTableList, selectCounter); + clearTableSelections(cdTableList, selectCounter); resyncFMArrays(filterMasks,fmMaskChan); confirmVal = 0; } if (!freezeTable) cdSort = spChecker(monFlag,cdTableList,wcVal,wcstring,1,&status); - pageDisp = reportSetErrors(pref, cdSort, cdTableList,pageNum,1); - currentTable = cdTableList; - currentTableCnt = cdSort; + pageDisp = reportSetErrors(pref, cdTableList,pageNum,1); + currentTable = make_range(cdTableList); status = dbGetField(&resetoneaddr,DBR_LONG,&resetNum,&ropts,&nvals,NULL); if(selectAll == 3) { - setAllTableSelections(cdSort,cdTableList,selectCounter,selectAll); + setAllTableSelections(make_range(cdTableList),selectCounter,selectAll); } if(resetNum) { - decodeChangeSelect(resetNum, pageDisp, cdSort, cdTableList,selectCounter, NULL); + decodeChangeSelect(resetNum, pageDisp, make_range(cdTableList),selectCounter, NULL); } if(confirmVal) { - if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(cdSort, cdTableList); + if(selectCounter[0] && (confirmVal & 2)) status = resetSelectedValues(cdTableList); if((selectCounter[1] || selectCounter[2]) && (confirmVal & 2)) { // Save present table as timenow. status = dbGetField(&loadedfile_addr,DBR_STRING,backupName,&ropts,&nvals,NULL); @@ -3847,7 +3903,7 @@ int main(int argc,char *argv[]) savesdffile(SAVE_TABLE_AS_SDF,SAVE_TIME_NOW,sdfDir,modelname,sdfile,saveasfilename, backupName,savefileaddr,savetimeaddr,reloadtimeaddr); // Overwrite the table with new values - status = modifyTable(cdSort,cdTableList); + status = modifyTable(make_range(cdTableList)); // Overwrite file savesdffile(SAVE_TABLE_AS_SDF,SAVE_OVERWRITE,sdfDir,modelname,sdfile,saveasfilename, backupName,savefileaddr,savetimeaddr,reloadtimeaddr); @@ -3855,7 +3911,7 @@ int main(int argc,char *argv[]) status = checkFileMod( sdffileloaded, &sdfFileMt, 1 ); writeTable2File(sdfDir,bufile,SDF_WITH_INIT_FLAG,cdTable); } - clearTableSelections(cdSort,cdTableList, selectCounter); + clearTableSelections(cdTableList, selectCounter); resyncFMArrays(filterMasks,fmMaskChan); confirmVal = 0; status = dbPutField(&confirmwordaddr,DBR_LONG,&confirmVal,1); @@ -3869,26 +3925,24 @@ int main(int argc,char *argv[]) #ifdef CA_SDF case SDF_TABLE_DISCONNECTED: if(lastTable != SDF_TABLE_DISCONNECTED) { - clearTableSelections(cdSort,cdTableList, selectCounter); + clearTableSelections(cdTableList, selectCounter); resyncFMArrays(filterMasks,fmMaskChan); confirmVal = 0; } noMon = createSortTableEntries(chNum,wcVal,wcstring,&noInit,NULL); - pageDisp = reportSetErrors(pref, chDisconnected, disconnectChans, pageNum,0); + pageDisp = reportSetErrors(pref, disconnectChans, pageNum,0); chDisconnectedCount = chDisconnected; - currentTable = disconnectChans; - currentTableCnt = chDisconnected; + currentTable = make_range(disconnectChans); status = dbPutField(&sorttableentriesaddr,DBR_LONG,&chDisconnected, 1); if (resetNum > 200) { - decodeChangeSelect(resetNum, pageDisp, chDisconnected, disconnectChans, selectCounter, NULL); + decodeChangeSelect(resetNum, pageDisp, make_range(disconnectChans), selectCounter, NULL); } break; #endif default: - pageDisp = reportSetErrors(pref, sperror,setErrTable,pageNum,1); + pageDisp = reportSetErrors(pref, setErrTable,pageNum,1); status = dbPutField(&sorttableentriesaddr,DBR_LONG,&sperror,1); - currentTable = setErrTable; - currentTableCnt = sperror; + currentTable = make_range(setErrTable); break; } if (selectAll) { @@ -3909,7 +3963,7 @@ int main(int argc,char *argv[]) } status = dbPutField(&(pagelockaddr[0]),DBR_LONG,&freezeTable,1); - processFMChanCommands(filterMasks, fmMaskChan,fmMaskChanCtrl,selectCounter, currentTableCnt, currentTable); + processFMChanCommands(filterMasks, fmMaskChan,fmMaskChanCtrl,selectCounter, currentTable); // Check file CRCs every 5 seconds. // DAQ and COEFF file checking was moved from skeleton.st to here RCG V2.9. diff --git a/src/epics/seq/simple_range.hh b/src/epics/seq/simple_range.hh new file mode 100644 index 0000000000000000000000000000000000000000..36cbb0aefb8bc0e0af4e61b4d3db54a1d575fec6 --- /dev/null +++ b/src/epics/seq/simple_range.hh @@ -0,0 +1,78 @@ +// +// Created by jonathan.hanks on 11/17/20. +// + +#ifndef DAQD_TRUNK_SIMPLE_RANGE_HH +#define DAQD_TRUNK_SIMPLE_RANGE_HH + +#include <type_traits> +#include <utility> + +namespace embedded +{ + /*! + * @brief a very simple range class, just tracks two iterators in one unit, [start, end) + * @tparam It the iterator type, which must be noexcept on copy and move + */ + template <typename It> + class range + { + static_assert(std::is_nothrow_copy_constructible<It>::value, "It must be no throw copy constructable"); + static_assert(std::is_nothrow_copy_assignable<It>::value, "It must be no throw copyable"); + static_assert(std::is_nothrow_move_constructible<It>::value, "It must be no throw move constructable"); + static_assert(std::is_nothrow_move_assignable<It>::value, "It must be no throw movable"); + public: + using iterator = It; + + range() noexcept: start_{}, end_{} {} + range(const range&) noexcept = default; + range(range&&) noexcept = default; + range(It it1, It it2) noexcept: start_{std::move(it1)}, end_{std::move(it2)} {} + range& operator=(const range&) noexcept = default; + range& operator=(range&&) noexcept = default; + + iterator + begin() noexcept + { + return start_; + } + + iterator + end() noexcept + { + return end_; + } + + const iterator + begin() const noexcept + { + return start_; + } + + const iterator + end() const noexcept + { + return end_; + } + + private: + It start_; + It end_; + }; + + /*! + * @brief Given two iterators of type It construct a range + * @tparam It + * @param start + * @param end + * @return the resulting range + */ + template <typename It> + range<It> + make_range(It start, It end) + { + return range<It>(std::move(start), std::move(end)); + } +} + +#endif //DAQD_TRUNK_SIMPLE_RANGE_HH diff --git a/src/epics/seq/test/test_fixed_size_vector.cc b/src/epics/seq/test/test_fixed_size_vector.cc index 0b5bf44f5a974ae930cbf811c8b545adc4364c6f..602dd286a92e73c2d5bf9caec2478218905d5df4 100644 --- a/src/epics/seq/test/test_fixed_size_vector.cc +++ b/src/epics/seq/test/test_fixed_size_vector.cc @@ -188,6 +188,31 @@ TEST_CASE( "We have defined enough to make the this usable by std::algorithms" ) REQUIRE( v0[ 4 ] == 5 ); } +TEST_CASE( "We can use front()/back() to reference the first/last elements when there are more than one.") +{ + embedded::fixed_size_vector<int, 20> v0; + v0.push_back(5); + REQUIRE( v0.front() == v0.back() ); + v0.front() = 42; + REQUIRE( v0[0] == 42 ); + v0.back() = 44; + REQUIRE( v0[0] == 44 ); + v0.push_back(10); + REQUIRE( v0.front() == 44 ); + REQUIRE( v0.back() == 10 ); + REQUIRE( v0[0] == v0.front() ); + REQUIRE( v0[1] == v0.back() ); +} + +TEST_CASE( "We can use front()/back() in a const setting as well") +{ + embedded::fixed_size_vector<int, 20> v0; + v0.push_back(5); + + const auto& vconst = v0; + REQUIRE( vconst.front() == vconst.back() ); +} + // static_assert(std::is_trivially_destructible<embedded::fixed_size_vector<int, // 20> >::value, "For trivial destructable types the fixed sized vector should // be trivially destructable"); diff --git a/src/epics/seq/test/test_simple_range.cc b/src/epics/seq/test/test_simple_range.cc new file mode 100644 index 0000000000000000000000000000000000000000..efe9d32164013a1b4315294b7d56b8453dfff966 --- /dev/null +++ b/src/epics/seq/test/test_simple_range.cc @@ -0,0 +1,18 @@ +// +// Created by jonathan.hanks on 11/17/20. +// +#include "catch.hpp" + +#include "simple_range.hh" + +#include <vector> + +TEST_CASE("You can create a simple range from two iterators") +{ + using it_type = typename std::vector<int>::iterator; + std::vector<int> backing_store{1,2,3,4,5,6,7,8,9,0}; + + embedded::range<it_type> rng = embedded::make_range(backing_store.begin() + 3, backing_store.begin() + 3 + 3); + REQUIRE( *rng.begin() == 4 ); + REQUIRE( *rng.end() == 7 ); +}