Unverified Commit e376ca04 authored by Giuseppe Carboni's avatar Giuseppe Carboni Committed by GitHub
Browse files

Fix #906, various enhancements for Schedule parsing (#907)

This additions modify the IRATools::getNextToken function in the following way:
- a std::vector<char> can be passed as delimiter (function override). The function checks if any of them is present in the string and behaves according to the old implementation;
- the behavior has been enhanced so that a boolean (which defaults to false) tells the function to keep cycling through the string if multiple occurrencies of one of the delimiters is found one after the other. This allows the function to behave in the same manner whether a string contains one or more '\t' characters or a series of whitespaces ' '.
The Schedule class has been modified according to these additions so that it can now parse a schedule with multiple tabs as well as whitespaces as token separators. A test has been introduced in such a way that checks if the 2 schedule.tmpl and schedule_ws.tmpl files produce the same output when checked with the `testSched` executable.
ScheduleChecker now also checks whether the caller user is the same as the PROJECT keyword. This alerts the observers that copied a schedule from a previous project to be aware that DISCOS will reject the given schedule when trying to launch it, saving time.
parent 0415ea13
Loading
Loading
Loading
Loading
+15 −2
Original line number Original line Diff line number Diff line
@@ -354,10 +354,23 @@ public:
	 * @param start position inside the string from which to start the next token, if a new token has been found
	 * @param start position inside the string from which to start the next token, if a new token has been found
	 *                it points to the character immediately after the localized token
	 *                it points to the character immediately after the localized token
	 * @param delimiter this is the character that separates the token
	 * @param delimiter this is the character that separates the token
	 * @param it returns the next token in the string
	 * @param ret it returns the next token in the string
	 * @param stopAtFirst immediately returns (true) if the first character found is one of the delimiters, otherwise it goes further inside str
	 * @return true if a token has been found
	 * @return true if a token has been found
	 */
	 */
	static bool getNextToken(const IRA::CString& str,int &start,char delimiter,IRA::CString &ret);
	static bool getNextToken(const IRA::CString& str,int &start,const char& delimiter,IRA::CString &ret, const bool& stopAtFirst=true);

	/**
	 * Use this function to divide a string into  separated tokens. Multiple token delimiters can be specified.
	 * @param str string to be divided into tokens
	 * @param start position inside the string from which to start the next token, if a new token has been found
	 *                it points to the character immediately after the localized token
	 * @param delimiters vector that contains characters that separate the token
	 * @param ret it returns the next token in the string
	 * @param stopAtFirst immediately returns (true) if the first character found is one of the delimiters, otherwise it goes further inside str
	 * @return true if a token has been found
	 */
	static bool getNextToken(const IRA::CString& str,int &start,const std::vector<char>& delimiters,IRA::CString &ret, const bool& stopAtFirst=true);
	
	
	/**
	/**
	 * Computes the normalized (+/-PI) difference between two angles expressed in radians(a-b). For example 359°-1°=-2°,1°-359°=2°, 179°-360°=179° and so on.
	 * Computes the normalized (+/-PI) difference between two angles expressed in radians(a-b). For example 359°-1°=-2°,1°-359°=2°, 179°-360°=179° and so on.
+82 −75
Original line number Original line Diff line number Diff line
@@ -397,7 +397,12 @@ bool CIRATools::skyFrequency(const double& bf,const double& bbw,const double& rf
	}*/
	}*/
}
}


bool CIRATools::getNextToken(const IRA::CString& str,int &start,char delimiter,IRA::CString &ret)
bool CIRATools::getNextToken(const IRA::CString& str,int &start,const char& delimiter,IRA::CString &ret, const bool& stopAtFirst)
{
		return getNextToken(str, start, std::vector<char>{ delimiter }, ret, stopAtFirst);
}

bool CIRATools::getNextToken(const IRA::CString& str,int &start,const std::vector<char>& delimiters,IRA::CString &ret, const bool& stopAtFirst)
{
{
		int i;
		int i;
		bool ok=false;
		bool ok=false;
@@ -406,22 +411,24 @@ bool CIRATools::getNextToken(const IRA::CString& str,int &start,char delimiter,I
		token=new char[i+1];
		token=new char[i+1];
		i=0;
		i=0;
		while (str[start]!=0) {
		while (str[start]!=0) {
			char c = str[start];
			ok=true;
			ok=true;
			if ((str[start]==delimiter)) {
			start++;
			start++;
			if (std::any_of(delimiters.begin(), delimiters.end(), [c](char d){ return c == d; })) {
				// We still have not found any meaningful character, stop if stopAtFirst or continue skipping a delimiter
				if(!stopAtFirst && i==0)
					continue;
				break;
				break;
			}
			}
			else {
			else {
				token[i]=str[start];
				token[i]=c;
				start++;
				i++;
				i++;
			}
			}
		}
		}
		token[i]=0;
		token[i]=0;
		ret=IRA::CString(token);
		ret=IRA::CString(token);
		delete []token;
		delete []token;
		if (!ok) return false;
		return ok;
		else return true;
}
}


double CIRATools::differenceBetweenAnglesRad(const double& a,const double& b)
double CIRATools::differenceBetweenAnglesRad(const double& a,const double& b)
+1 −1
Original line number Original line Diff line number Diff line
@@ -24,7 +24,7 @@
#include "Configuration.h"
#include "Configuration.h"


#define _SCHED_NULLTARGET "NULL"
#define _SCHED_NULLTARGET "NULL"
#define SEPARATOR '\t'
#define SEPARATORS std::vector<char>{'\t', ' '}
#define MAX_SCHED_NAME_LEN 37
#define MAX_SCHED_NAME_LEN 37


/**
/**
+4 −1
Original line number Original line Diff line number Diff line
@@ -38,13 +38,16 @@ RESTRICT_PERMS=_tp_agc
# C programs (public and local)
# C programs (public and local)
# -----------------------------
# -----------------------------
EXECUTABLES     = scheduleChecker
EXECUTABLES     = scheduleChecker
EXECUTABLES_L   = testSched testLSTtoUT
EXECUTABLES_L   = testSched testSchedules testLSTtoUT


#
#
# <brief description of xxxxx program>
# <brief description of xxxxx program>
testSched_OBJECTS   = testSchedule Schedule SubScanBinder Schedule_ScanList Configuration
testSched_OBJECTS   = testSchedule Schedule SubScanBinder Schedule_ScanList Configuration
testSched_LIBS      = IRALibrary ComponentErrors
testSched_LIBS      = IRALibrary ComponentErrors


testSchedules_OBJECTS   = testSchedules Schedule SubScanBinder Schedule_ScanList Configuration
testSchedules_LIBS      = IRALibrary ComponentErrors boost_system boost_filesystem

testLSTtoUT_OBJECTS = testLST2UT
testLSTtoUT_OBJECTS = testLST2UT
testLSTtoUT_LIBS = IRALibrary ComponentErrors
testLSTtoUT_LIBS = IRALibrary ComponentErrors


+19 −19
Original line number Original line Diff line number Diff line
@@ -920,48 +920,48 @@ bool CSchedule::parseLine(const IRA::CString& line,const DWORD& lnNumber,IRA::CS
{
{
	int start=0;
	int start=0;
	IRA::CString ret;
	IRA::CString ret;
	if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,ret)) {
	if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,ret,false)) {
		return false;
		return false;
	}
	}
	else { // token could be extracted
	else { // token could be extracted
		ret.MakeUpper();
		ret.MakeUpper();
		if (ret==PROJECT) {
		if (ret==PROJECT) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,m_projectName)) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,m_projectName,false)) {
				errorMsg="cannot parse project name";
				errorMsg="cannot parse project name";
				return false;
				return false;
			}
			}
			else return true;
			else return true;
		}
		}
		else if (ret==OBSERVER) {
		else if (ret==OBSERVER) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,m_observer)) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,m_observer,false)) {
				errorMsg="cannot parse observer name";
				errorMsg="cannot parse observer name";
				return false;
				return false;
			}
			}
			else return true;			
			else return true;			
		}
		}
		else if (ret==SCANLIST) {
		else if (ret==SCANLIST) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,m_scanList)) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,m_scanList,false)) {
				errorMsg="cannot parse scan list file name";
				errorMsg="cannot parse scan list file name";
				return false;
				return false;
			}
			}
			else return true;
			else return true;
		}
		}
		else if (ret==PROCLIST) {
		else if (ret==PROCLIST) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,m_configList)) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,m_configList,false)) {
				errorMsg="cannot parse procedure list file name";
				errorMsg="cannot parse procedure list file name";
				return false;
				return false;
			}
			}
			else return true;
			else return true;
		}
		}
		else if (ret==BACKENDLIST) {
		else if (ret==BACKENDLIST) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,m_backendList)) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,m_backendList,false)) {
				errorMsg="cannot parse backend configurations file name";
				errorMsg="cannot parse backend configurations file name";
				return false;
				return false;
			}
			}
			else return true;
			else return true;
		}
		}
		else if (ret==SCANLAYOUT) {
		else if (ret==SCANLAYOUT) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,m_layoutFile)) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,m_layoutFile,false)) {
				errorMsg="cannot parse scan layouts  file name";
				errorMsg="cannot parse scan layouts  file name";
				return false;
				return false;
			}
			}
@@ -969,14 +969,14 @@ bool CSchedule::parseLine(const IRA::CString& line,const DWORD& lnNumber,IRA::CS
		}
		}
		else if (ret==MODE) {
		else if (ret==MODE) {
			IRA::CString mode,rep,startTime;
			IRA::CString mode,rep,startTime;
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,mode)) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,mode,false)) {
				errorMsg="cannot parse schedule mode";
				errorMsg="cannot parse schedule mode";
				return false;
				return false;
			}
			}
			else {
			else {
				m_modeDone=true;
				m_modeDone=true;
				if (mode==LSTMODE) {
				if (mode==LSTMODE) {
					if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,rep)) {
					if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,rep,false)) {
						errorMsg="cannot parse repetitions number for  LST mode";
						errorMsg="cannot parse repetitions number for  LST mode";
						return false;
						return false;
					}
					}
@@ -989,7 +989,7 @@ bool CSchedule::parseLine(const IRA::CString& line,const DWORD& lnNumber,IRA::CS
					}
					}
				}
				}
				else if (mode==SEQMODE) {
				else if (mode==SEQMODE) {
					if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,startTime)) {
					if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,startTime,false)) {
						m_mode=SEQ; //if it has not an extra argument the sequential is pure
						m_mode=SEQ; //if it has not an extra argument the sequential is pure
						return true;
						return true;
					}
					}
@@ -1011,11 +1011,11 @@ bool CSchedule::parseLine(const IRA::CString& line,const DWORD& lnNumber,IRA::CS
		}
		}
		else if (ret==ELEVATIONLIMITS) {
		else if (ret==ELEVATIONLIMITS) {
			IRA::CString minEl,maxEl;
			IRA::CString minEl,maxEl;
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,minEl)) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,minEl,false)) {
				errorMsg="elevation lower limit missing or not correct";
				errorMsg="elevation lower limit missing or not correct";
				return false;
				return false;
			}
			}
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,maxEl)) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,maxEl,false)) {
				errorMsg="elevation upper limit missing or not correct";
				errorMsg="elevation upper limit missing or not correct";
				return false;
				return false;
			}
			}
@@ -1039,7 +1039,7 @@ bool CSchedule::parseLine(const IRA::CString& line,const DWORD& lnNumber,IRA::CS
		}
		}
		else if (ret==SCANTAG) {
		else if (ret==SCANTAG) {
			IRA::CString scanTag;
			IRA::CString scanTag;
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,scanTag)) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,scanTag,false)) {
				errorMsg="cannot parse scan tag";
				errorMsg="cannot parse scan tag";
				return false;
				return false;
			}			
			}			
@@ -1049,7 +1049,7 @@ bool CSchedule::parseLine(const IRA::CString& line,const DWORD& lnNumber,IRA::CS
			return true;
			return true;
		}
		}
		else if (ret==INITPROC) {
		else if (ret==INITPROC) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,m_initProc)) {
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,m_initProc,false)) {
				errorMsg="cannot parse schedule initialization procedure";
				errorMsg="cannot parse schedule initialization procedure";
				return false;
				return false;
			}
			}
@@ -1080,7 +1080,7 @@ bool CSchedule::parseScans(const IRA::CString& line,const DWORD& lnNumber,IRA::C
	//ACS::Time ut;
	//ACS::Time ut;
	TRecord *p;
	TRecord *p;
	start=0;
	start=0;
	if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,ret)) {
	if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,ret,false)) {
		errorMsg="schedule format error";
		errorMsg="schedule format error";
		return false;
		return false;
	}
	}
@@ -1088,7 +1088,7 @@ bool CSchedule::parseScans(const IRA::CString& line,const DWORD& lnNumber,IRA::C
		ret.MakeUpper();
		ret.MakeUpper();
		if (ret==SCAN_START) {  //process scan definition
		if (ret==SCAN_START) {  //process scan definition
			m_currentScanDef.valid=false;
			m_currentScanDef.valid=false;
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,ret)) { // scan id
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,ret,false)) { // scan id
				errorMsg="scan identifier cannot be found";
				errorMsg="scan identifier cannot be found";
				return false;
				return false;
			}
			}
@@ -1104,14 +1104,14 @@ bool CSchedule::parseScans(const IRA::CString& line,const DWORD& lnNumber,IRA::C
				}
				}
				m_currentScanDef.id=tempId;
				m_currentScanDef.id=tempId;
			}
			}
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,ret)) { //suffix
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,ret,false)) { //suffix
				errorMsg="scan suffix cannot be found";
				errorMsg="scan suffix cannot be found";
				return false;
				return false;
			}
			}
			else {
			else {
				m_currentScanDef.suffix=ret;
				m_currentScanDef.suffix=ret;
			}
			}
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATOR,ret)) { //backend:datawriter
			if (!IRA::CIRATools::getNextToken(line,start,SEPARATORS,ret,false)) { //backend:datawriter
				errorMsg="backend/datawriter cannot be found";
				errorMsg="backend/datawriter cannot be found";
				return false;
				return false;
			}
			}
@@ -1131,7 +1131,7 @@ bool CSchedule::parseScans(const IRA::CString& line,const DWORD& lnNumber,IRA::C
					m_currentScanDef.writerInstance=_SCHED_NULLTARGET;
					m_currentScanDef.writerInstance=_SCHED_NULLTARGET;
				}
				}
			}
			}
			if (IRA::CIRATools::getNextToken(line,start,SEPARATOR,ret)) { //layout...not mandatory
			if (IRA::CIRATools::getNextToken(line,start,SEPARATORS,ret,false)) { //layout...not mandatory
				if (m_layoutFile=="") {  // if the layout file has not been given
				if (m_layoutFile=="") {  // if the layout file has not been given
					errorMsg="scan layout without providing the scan layouts file";
					errorMsg="scan layout without providing the scan layouts file";
					return false;
					return false;
Loading