Write a string vector to a text wave

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.

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

Unless you are running on OS 9, the handle locking part is obsolete and can be removed.
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 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.

Forum

Support

Gallery

Igor Pro 9

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More