Write a string vector to a text wave

Average rating
(0 votes)

This function lets you put std::vector objects directly into textwaves. The memcpy's might look scary but they are incredibly fast.
The wave referenced in waveHandle must be created in the appropriate size prior to calling this function.
If you want a 1D textwave, the wave's size must be stringVector.size(). I used a 2D wave with stringVector.size()/2 rows and 2 columns.

int stringVectorToTextWave(std::vector<std::string> &stringVector, waveHndl &waveHandle){
 
	std::vector<long int> stringSizes;
	char buf[1000];
	int lockStateWave, ret, i;
 
	long int offset;
	long int totalSize=0;
 
        if(stringVector.size() == 0){
             return -1;
        }
 
	// number of 32-bit integers (aka long int) is one more compared to the number of strings
	const long int numEntriesPlusOne = stringVector.size()+1;
 
	std::vector<std::string>::const_iterator it;
	for(it = stringVector.begin(); it != stringVector.end(); it++){
                try{
		   stringSizes.push_back(it->size());
                }
                catch(...){
                    return NOMEM;
                 }
		totalSize += it->size();
	}
 
	totalSize += numEntriesPlusOne*sizeof(long);
 
	Handle textHandle = NewHandle(totalSize);
	if(MemError() || textHandle == NULL){
		return NOMEM;
	}
 
	//sprintf(buf,"totalSize of strings %d",GetHandleSize(textHandle));
	//XOPNotice(buf);
 
	for(i=0; i < numEntriesPlusOne; i++){
 
		if(i == 0){// position of the first string
			offset = numEntriesPlusOne*sizeof(long);
		}
		else{ // and of all the others
			offset+=stringSizes[i-1];
		}
		//sprintf(buf,"offset=%d, offsetPosition=%d*sizeof(long)",offset,i);
		//XOPNotice(buf);
 
		// write offsets
		memcpy(*textHandle+i*sizeof(long),&offset,sizeof(long));
 
		if(i < stringVector.size()){
 
			//sprintf(buf,"string=%s, stringPosition=%d",stringVector[i].c_str(),offset);
	                //XOPNotice(buf);
 
			// write strings
			memcpy(*textHandle+offset,stringVector[i].c_str(),stringSizes[i]);
		}
	}
 
	// mode = 2 defines the format of the handle contents to
	// offsetToFirstString
	// offsetToSecondString
	// ...
	// offsetToPositionAfterLastString
	// firstString
	//...
	int mode=2;
 
        // Locking is only needed on MacOS9
	// acquire waveHandle lock
	lockStateWave=MoveLockHandle(waveHandle);
	ret = SetTextWaveData(waveHandle,mode,textHandle);
 
	//sprintf(buf,"SetTextWaveData returned %d",ret);
	//XOPNotice(buf);
 
	// release waveHandle lock
	HSetState(waveHandle, lockStateWave);
	DisposeHandle(textHandle);
 
	return ret;
}

Very nice function. Unless

Very nice function.

Unless you are running on OS 9, the handle locking part is obsolete and can be removed.

Is there something

Is there something missing?

In the manual it says that "SetTextWaveData can not change the number of points in the text wave. Therefore the data in textDataH must be consistent with the number of points in waveH". Shouldn't this mean that you have to check/redimension the size of the waveHandle to make sure it is the same size as the data you're just about to put in it?

Actually you are right. The

Actually you are right. The wave must already be in the appropriate size. Thanks for poiting that out. I avoided redimensioning here because it is really slow compared to creating it in the correct size.

Back to top