Concatenating Strings in a REALbasic Plugin
November 22nd, 2007 by Joe RanieriConcatenating strings in REALbasic itself is a very simple operation:
dim str as string = "foo" + "bar"
However, the plugins SDK provides no function for concatenating REALstrings together. There’s also no function we can load through REALLoadObjectMethod or REALLoadGlobalMethod. While it would be nice if it was provided, it’s rather easy to do yourself.
//! Creates a new string by concatenating `firstString` and `secondString`. REALstring ALConcatStrings(REALstring firstString, REALstring secondString) { REALstring convertedFirstString = NULL; REALstring convertedSecondString = NULL; bool needsUnlock = false; if(REALGetStringEncoding(firstString) == REALGetStringEncoding(secondString)) { // encodings are equal, so no need to convert anything convertedFirstString = firstString; convertedSecondString = secondString; } else { // if the two strings aren't in the same encoding, we need to change them both to UTF8 convertedFirstString = REALConvertString(firstString, kREALTextEncodingUTF8); convertedSecondString = REALConvertString(secondString, kREALTextEncodingUTF8); needsUnlock = true; } // the total length (in bytes) of the resulting string size_t totalLength = convertedFirstString->Length() + convertedSecondString->Length(); // ok, now we need to create a buffer for the total string contents char *buffer = (char *)malloc(totalLength); // copy in the first and second strings' data to the right spots memcpy(buffer, convertedFirstString->CString(), convertedFirstString->Length()); memcpy(buffer + convertedFirstString->Length(), convertedSecondString->CString(), convertedSecondString->Length()); // next we create a REALstring from it REALstring result = REALBuildString(buffer, totalLength, REALGetStringEncoding(convertedFirstString)); // free our buffer (REALbasic copies it on BuildString) free(buffer); // unlock our converted strings if we have to if(needsUnlock) { REALUnlockString(convertedFirstString); REALUnlockString(convertedSecondString); } // phew, that was easy enough! return result; }
I apologize for the awful formatting of this page! It looks decent in an RSS reader at least…
November 25th, 2007 at 4:26 am
I doubt that strncpy is the proper function to use here. Keep in mind that strings may contain binary data, with zero bytes inside. strncpy() would not copy them entirely. memcpy would be safer. Also, I wonder if the rules that RB uses to convert two differently-encoded strings are different from the way your code does it. At the very least, this should be pointed out to the user of such a plugin.
November 25th, 2007 at 4:43 am
D’oh. Thanks for pointing that out… That’s what I get for posting so late at night. I also changed the encoding handling to match REALbasic’s.
November 25th, 2007 at 11:10 am
calloc is a rather strange choice — you’re filling the entire buffer’s contents anyways, so you could skip the initialization to zero and save some cycles. Also, if you’re using the newer SDK, it’s preferred to use REALBuildStringWithEncoding (or the REALBuildString overload that assigns encoding) instead of separating the two calls. However, my recommendation is slightly different. Here’s how I’d do it (if you’re looking for speed, this reduces memory allocations, deallocations and copies):
1) Ensure the same encodings like you’re doing
2) Call REALGetStringContents on both strings to get a pointer and length for each buffer
3) Call REALBuildStringWithEncoding( nil, lhsLength + rhsLength, lhsEncoding ) — this will allocate a buffer large enough to hold both strings, but not copy any data in.
4) Call REALGetStringContents on the resulting string to get its void *
5) Call memcpy to move the lhs and rhs strings into the resulting void * at their appropriate locations.
It’s going to be quicker than what you were doing, but it comes with the caveat that step #3 is technically undocumented (though I doubt it’ll change since it’s worked this way for about 10 years now).
November 25th, 2007 at 11:17 am
Is your commenting about it count as documentation?
November 25th, 2007 at 10:11 pm
Never has in the past, so I don’t know why it would start now.
Of course, that doesn’t stop people from assuming my word is law. 