Processing Wave Names/Paths and Lists of waves in XOP functions

Average rating
(0 votes)

This is of interest to XOP function writers who have to parse string inputs.

If you have a function in an XOP that takes as a parameter a string containing a wave name or a full path to a wave (data folder path:wave name), the ParseWavePath function will help you parse the input into C strings containing wave name and data folder name.

The ParseWaveListPaths takes a a semicolon- or comma-separated list of wavenames or full paths to waves and returns an array of waveHandles.

Yes, in most cases you should use operations, not functions, for processing lists of waves, in which case you can use OperationHandler to parse inputs, but sometimes a function is appropriate.

// typedefs for paramater string for data folder paths and wave names. Put these in a header file
typedef char DFPATH [MAXCMDLEN + 1];
typedef char WVNAME [MAX_OBJ_NAME + 1];
 
 
/*******************************************************************************************************
Takes a handle to a string containing either the name of an Igor Wave in the current data folder or the full path 
to an Igor Wave and copies the data folder path (if one is given) and the wave name into the given strings
Last Modified Mar 09 2010 by Jamie Boyd  */
void ParseWavePath (Handle fullPath, DFPATH dataFolderName, WVNAME waveName){
 
	// ignore leading and trailing spaces
	long startPos, stopPos, pathLen= GetHandleSize(fullPath);
	for (startPos = 0; (*(*fullPath + startPos) == ' ') && (startPos < pathLen); startPos++);
	for (stopPos = pathLen -1; (*(*fullPath + stopPos) == ' ') && (stopPos > startPos); stopPos--);
	pathLen = 1 + stopPos - startPos;
	// Find last colon, the break between the dataFolder and the waveName
	int waveNameBreak;
	for (waveNameBreak = stopPos;((*(*fullPath + waveNameBreak) != ':') && (waveNameBreak >= startPos)); waveNameBreak--);
		// If count down gets to startPos, then no colon, so no datafolder, just wavename	
		if (waveNameBreak < startPos){
			// copy wave name and teminate string
			memcpy (waveName, *fullPath + startPos, pathLen);
			waveName [pathLen] = 0;
			// no data folder, so make path ":" for current folder and terminate dataFolderName
			dataFolderName [0] = ':';
			dataFolderName [1] = 0;
		}else{ // there is a colon, so there is a datafolder 
			// copy data folder name and terminate string
			memcpy (dataFolderName, *fullPath + startPos, (waveNameBreak + 1 - startPos));
			dataFolderName [waveNameBreak + 1 - startPos] = 0;
			//copy wavename
			memcpy (waveName, *fullPath + waveNameBreak + 1, (pathLen - 1 - (waveNameBreak - startPos)));
			waveName [pathLen -1 - (waveNameBreak - startPos)] = 0;
		}
}
 
/*******************************************************************************************************
Takes a handle to a string containing a semicolon- or comma-separated list of names of Igor waves in the current datafolder
or full paths to Igor waves and returns a pointer to an array of Wave Handles corresponding to those waves.
Also sets the variable pointed to by nWavesPtr to the number of waves in the list
Last Modified Mar 09 2010 by Jamie Boyd  */
waveHndl* ParseWaveListPaths (Handle pathsList, int* nWavesPtr){
 
	int listLen = GetHandleSize (pathsList);
	// Count semicolons/commas to see how many waves we have.
	int nWaves = 1;
	// ignore trailing semicolon/comma if present
	if ((*(*pathsList + listLen -1) == ';')|| (*(*pathsList + listLen -1) == ','))
		listLen--;
	for (int iList =0; iList < listLen -1 ; iList++){
		if ((*(*pathsList + iList) == ';') || (*(*pathsList + iList) == ',')) nWaves ++;
	}
	// make array of waveHandles
	waveHndl* handleList = (waveHndl*)NewPtr (nWaves * sizeof(waveHndl));
	// make a handle and 2 strings to pass to parseWavePath
	Handle aPath=NewHandle ((MAXCMDLEN + 1) * sizeof (char));
	DFPATH dataFolderPath;
	DataFolderHandle pathDFHandle;
	WVNAME nameOfWave;
	int iWave =0;
	int startPos=0;
	int nameLen =0;
	// find each wave name/path by looking for semicolons/commas and parse it
	for (iWave =0, startPos=0; iWave < nWaves ; startPos += nameLen + 1, iWave++){
		// find next semicolon/comma, or end of list
		for (nameLen =0 ; (((*(*pathsList + startPos + nameLen) != ';') && (*(*pathsList + startPos + nameLen) != ',')) && (startPos + nameLen < listLen)) ; nameLen ++);
		// copy the wave name/path into a handle and Parse it into datafolder path and wavename
		SetHandleSize (aPath, (nameLen * sizeof (char)));
		if (aPath == NULL){
			handleList[iWave] = NULL; 
			continue;
		}
		memcpy ((void*)*aPath, (void*)(*pathsList + startPos), (nameLen * sizeof (char)));
		ParseWavePath (aPath, dataFolderPath, nameOfWave);
		// Make reference to dataFolder
		GetNamedDataFolder (NULL, dataFolderPath, &pathDFHandle);
		// get wave reference and add to handleList
		handleList[iWave] = FetchWaveFromDataFolder(pathDFHandle, nameOfWave);
	}
	// free aPath handle
	DisposeHandle (aPath);
	*nWavesPtr = nWaves;
	// return pointer to wave handles array
	return handleList;
}

Back to top