bool SkypekitTestEngine::CustomCommand(const Sid::String &cmd, Sid::String &result_str) {
	TI_FUNCLOG;
	result_str = "Hi! I got your ";
	result_str += cmd;
	TI_DBG("CustomCommand: got %s, answer: %s", cmd.data(), result_str.data());
	return true;
}
bool iMX27RtpInterface::CustomCommand(const Sid::String& cmd, Sid::String& result_str) {
	RTP_FUNCLOG;
	result_str = "Hi! I got your ";
	result_str += cmd;
	RTP_DBG("CustomCommand: got %s, answer: %s", cmd.data(), result_str.data());
	return true;
}
void checkFrom(char c, const Sid::String& expected)
{
    Sid::String from = Sid::String::from(c);
    CPPUNIT_ASSERT_PRINTF(from == expected,
                            "from((char)%c) yielded unexpected result \"%s\"\n",
                            c,
                            from.isNull() ? "(NULL)" : from.data());
}
void checkFrom(uint64 n, const Sid::String& expected)
{
    Sid::String from = Sid::String::from(n);
    CPPUNIT_ASSERT_PRINTF(from == expected,
                            "from((uint64)%llu) yielded unexpected result \"%s\"\n",
                            n, 
                            from.isNull() ? "(NULL)" : from.data());
}
void checkFrom(bool b, const Sid::String& expected)
{
    Sid::String from = Sid::String::from(b);
    CPPUNIT_ASSERT_PRINTF(from == expected,
                            "from((bool)%s) yielded unexpected result \"%s\"\n",
                            b ? "true" : "false",
                            from.isNull() ? "(NULL)" : from.data());
}
int main(int argc, const char **argv) {
	OptionsParser parser;
	if (parser.ParseOptions(argc, argv) < 0 || parser.m_Help) {
		parser.Usage(argv[0]);
		return -1;
	}

	Sid::SkypePCMInterfaceServer *pcmif_server = new Sid::SkypePCMInterfaceServer();
	Sid::SkypePCMCallbackInterfaceClient *pcmif_cb_client = new Sid::SkypePCMCallbackInterfaceClient();

	SkypePCMInterface* pcmif = SkypePCMInterfaceGet(pcmif_cb_client);
	pcmif_server->set_if(pcmif);


	Sid::String fromskypekitkey;
	Sid::String toskypekitkey;

	fromskypekitkey.Format( "%spcm_from_skypekit_key", parser.m_IpcPrefix);
	toskypekitkey.Format( "%spcm_to_skypekit_key", parser.m_IpcPrefix);

	pcmif_server->Connect(fromskypekitkey.data(), 0);
	pcmif_cb_client->Connect(toskypekitkey.data(), 500);

	if(parser.m_OutFile)
	{
	  Sid::String cmd;
	  Sid::String response;
	  cmd.Format("OUT:%s",parser.m_OutFile);
	  pcmif->CustomCommand(cmd, response);
	}
	if(parser.m_InFile)
	{
	  Sid::String cmd;
	  Sid::String response;
	  cmd.Format("IN:%s",parser.m_InFile);
	  pcmif->CustomCommand(cmd,response);
	}
	if(parser.m_Loop)
	{
	  Sid::String cmd = "LOOP:1";
	  Sid::String response;
	  pcmif->CustomCommand("LOOP:1", response);
	}
	
	Sid::Protocol::Status status;
	do {
		status =pcmif_server->ProcessCommands();
	} while (status == Sid::Protocol::OK);

	SkypePCMInterfaceRelease(pcmif);
	pcmif_server->Disconnect();
	pcmif_cb_client->Disconnect();

	delete pcmif_server;
	delete pcmif_cb_client;

	printf("PCMServerTransport disconnected, exiting from pcmtesthost\n");
}
void checkFrom(unsigned int u, unsigned int base, const Sid::String& expected)
{
    Sid::String from = Sid::String::from(u, base);
    CPPUNIT_ASSERT_PRINTF(from == expected,
                            "from((unsigned int)%u, (unsigned int)%u) yielded unexpected result \"%s\"\n",
                            u,
                            base,
                            from.isNull() ? "(NULL)" : from.data());
}
void checkConversion(const Sid::String& test, const char* expected)
{
    const char* origData = test.data();
    CPPUNIT_ASSERT_PRINTF(!strcmp(test, expected),
    			"operator const char* did not yield \"%s\" as "
    			"expected, got \"%s\" instead.\n",
    			test.isNull() ? "(NULL)" : (const char*)test,
    			expected);
    CPPUNIT_ASSERT_MESSAGE("operator const char*() causes object to relinquish its reference!",
                            origData == test.data());
}
void StringListTestCase::appendEmptyStringTest()
{
	Sid::List_String test1;
	Sid::String string;
	CPPUNIT_ASSERT(string.isNull());

	test1.append(string);

	CPPUNIT_ASSERT(test1.size() == 1);
	CPPUNIT_ASSERT(!test1[0].isNull());
	CPPUNIT_ASSERT(test1[0] == "");
}
void checkToBool(const Sid::String& test, bool expected)
{
    const char* origData = test.data();
    bool res = test.toBool();
    CPPUNIT_ASSERT_PRINTF(res == expected,
                            "toBool() yielded unexpected result for value "
                            "\"%s\", should have been %s\n",
                            test.isNull() ? "(NULL)" : test.data(),
                            expected ? "true" : "false");
    CPPUNIT_ASSERT_MESSAGE("toBool() causes object to relinquish its reference!",
                            origData == test.data());
}
void checkHexRepresentation(const Sid::String& test, const Sid::String& expected)
{
    const char* origData = test.data();
    Sid::String res = test.getHexRepresentation();
    CPPUNIT_ASSERT_PRINTF(res == expected,
                            "getHexRepresentation() yielded unexpected result for value "
                            "\"%s\", should have been \"%s\", instead got \"%s\"\n",
                            test.isNull() ? "(NULL)" : test.data(),
                            expected.isNull() ? "(NULL)" : expected.data(),
                            res.isNull() ? "(NULL)" : res.data());    
    CPPUNIT_ASSERT_MESSAGE("getHexRepresentation() causes object to relinquish its reference!",
                            origData == test.data());
}
void checkToUInt64(const Sid::String& test, uint64 expected)
{
    const char* origData = test.data();
    uint64 res = test.toUInt64();
    CPPUNIT_ASSERT_PRINTF(res == expected,
                            "toUInt64() yielded unexpected result for value "
                            "\"%s\", should have been %ull, instead got %ull\n",
                            test.isNull() ? "(NULL)" : test.data(),
                            expected,
                            res);
    CPPUNIT_ASSERT_MESSAGE("toUInt64() causes object to relinquish its reference!",
                            origData == test.data());
}
void checkFind(const Sid::String& test, 
    			char toFind,
    			int expected)
{
    int res = test.find(toFind);
    CPPUNIT_ASSERT_PRINTF(res == expected,
    						"find(%u) yielded unexpected result %d for string:\n"
    						"%s\n"
    						"expected %d\n",
    						toFind,
    						res,
    						test.isNull() ? "(NULL)" : test.data(),
    						expected);
}
void checkToBinary(const Sid::String& test, const char* expected, size_t expectedSize)
{
    const char* origData = test.data();
    char* res = new char[test.size()+1];
    size_t size = test.toBinary(res);
    CPPUNIT_ASSERT_PRINTF(size == expectedSize,
                            "toBinary() yielded a result that was too long, "
                            "expected %u, got %u\n",
                            expectedSize,
                            size);
    CPPUNIT_ASSERT_PRINTF(!memcmp(expected, res, size),
                            "%s",
                            "toBinary() yielded unexpected result\n");
    CPPUNIT_ASSERT_MESSAGE("toBinary() causes object to relinquish its reference!",
                            origData == test.data());
}
void StringTestCase::testHash()
{
    CPPUNIT_ASSERT(Sid::String().hash() == 0);
    CPPUNIT_ASSERT(Sid::String().hash(16) == 0);
    CPPUNIT_ASSERT(Sid::String("").hash() == 0);
    CPPUNIT_ASSERT(Sid::String("").hash(16) == 0);
    CPPUNIT_ASSERT(Sid::String("fOo").hash(1024) != Sid::String("Foo").hash(1024));
    {
        Sid::String test = Sid::String::from("\xff\xf0\x00\x90",4);
        Sid::String test2 = Sid::String::from("\xfb\xf0\x00\x90",4);
    	// !bwc! This hash seems to fare poorly with small differences, this is the
    	// smallest modulus (that is a power of two) that yields different results.
    	// The 19 least significant bits are identical. Might be worth considering
    	// updating the hash function with something a little nicer.
    	CPPUNIT_ASSERT(test.hash(0x080000) != test2.hash(0x080000));
    }
}
void checkFrom(int n, const Sid::String& expected)
{
    Sid::String from=Sid::String::from(n);
    CPPUNIT_ASSERT_PRINTF(from == expected,
    			"from((int)%d) did not yield expected result:\n"
    			"got  %s\n",
    			expected.data());
}
void checkKeyValue(const Sid::String& key,
    		const Sid::String& value,
    		const Sid::String& expected)
{
    const char* keyData = key.data();
    const char* valueData = value.data();
    Sid::String keyValue=Sid::String::keyValue(key, value);
    CPPUNIT_ASSERT_PRINTF(keyValue == expected,
    			"keyValue(\"%s\", \"%s\") did not yield \"%s\","
    			" instead got \"%s\"\n",
    			key.isNull() ? "(NULL)" : key.data(),
    			value.isNull() ? "(NULL)" : value.data(),
    			expected.isNull() ? "(NULL)" : expected.data(), 
    			keyValue.isNull() ? "(NULL)" : keyValue.data());
    CPPUNIT_ASSERT_MESSAGE("keyValue() causes key to relinquish its reference!",
                            keyData == key.data());
    CPPUNIT_ASSERT_MESSAGE("keyValue() causes value to relinquish its reference!",
                            valueData == value.data());
}
void checkAppend(const Sid::String& lhs, 
                    const char* rhs, 
                    const Sid::String& expected)
{
    Sid::String test(lhs);
    CPPUNIT_ASSERT(test == lhs);
    test += rhs;
    CPPUNIT_ASSERT_PRINTF(test == expected,
                            "operator+=(const char*) yielded unexpected"
                            " result:\n"
                            "lhs was  \"%s\"\n"
                            "rhs was  \"%s\"\n"
                            "expected \"%s\"\n"
                            "got      \"%s\"\n",
                            lhs.isNull() ? "(NULL)" : lhs.data(),
                            rhs ?  rhs : "(NULL)",
                            expected.isNull() ? "(NULL)" : expected.data(),
                            test.isNull() ? "(NULL)" : test.data());

    checkAppend(lhs, Sid::String(rhs), expected);
}
void checkNotStartWith(const Sid::String& test, const Sid::String& prefix)
{
    const char* origData = test.data();
    CPPUNIT_ASSERT_PRINTF(!test.startWith(prefix),
    			"startsWith() did not return false for "
    			"\n%s\n%s\n",
    			prefix.isNull() ? "(NULL)" : prefix.data(),
    			test.isNull() ? "(NULL)" : test.data());
    CPPUNIT_ASSERT_MESSAGE("startWith() causes object to relinquish its reference!",
                            origData == test.data());
}
void checkUnescaping(const Sid::String& test, const Sid::String& expected)
{
    const char* origData = test.data();
    Sid::String unescaped=test.unescape();
    CPPUNIT_ASSERT_PRINTF(unescaped == expected,
    			"Unescaping \"%s\" did not yield \"%s\" as "
    			"expected, instead yielded \"%s\"\n",
    			!test.isNull() ? test.data() : "(NULL)",
    			!expected.isNull() ? expected.data() : "(NULL)",
    			!unescaped.isNull() ? unescaped.data() : "(NULL)");
    CPPUNIT_ASSERT_MESSAGE("unescape() causes object to relinquish its reference!",
                            origData == test.data());
}
void checkAssignment(const Sid::String& test,
                        const Sid::String& rhs,
                        const Sid::String& expected)
{
    Sid::String copy(test);
    const char* rhsData = rhs.data();
    copy = rhs;
    CPPUNIT_ASSERT_PRINTF(copy == expected,
                            "Assignment operator yielded unexpected result:\n"
                            "\"%s\" (lhs)\n"
                            "\"%s\" (rhs)\n"
                            "\"%s\" (expected)\n"
                            "\"%s\" (got)\n",
                            test.isNull() ? "(NULL)" : test.data(),
                            rhs.isNull() ? "(NULL)" : rhs.data(),
                            expected.isNull() ? "(NULL)" : rhs.data(),
                            copy.isNull() ? "(NULL)" : copy.data());
    CPPUNIT_ASSERT_MESSAGE("Assignment operator caused rhs to relinquish its reference!",
                            rhs.data() == rhsData);
}
void checkAppend(const Sid::String& lhs, 
                    const Sid::String& rhs, 
                    const Sid::String& expected)
{
    const char* origData = rhs.data();
    Sid::String test(lhs);
    test += rhs;
    CPPUNIT_ASSERT_PRINTF(test == expected,
                            "operator+=(const Sid::String&) yielded unexpected"
                            " result:\n"
                            "lhs was  \"%s\"\n"
                            "rhs was  \"%s\"\n"
                            "expected \"%s\"\n"
                            "got      \"%s\"\n",
                            lhs.isNull() ? "(NULL)" : lhs.data(),
                            rhs.isNull() ? "(NULL)" : rhs.data(),
                            expected.isNull() ? "(NULL)" : expected.data(),
                            test.isNull() ? "(NULL)" : test.data());
    CPPUNIT_ASSERT_MESSAGE("operator+=() causes rhs to relinquish its reference!",
                            origData == rhs.data());
}
void checkToBinary(const Sid::String& test, const char* expected, size_t expectedSize, const Sid::String& hex)
{
    const char* origData = test.data();
    checkToBinary(test, expected, expectedSize);
    Sid::String expHex(hex);
    Sid::String resHex = test.getHexRepresentation();
    CPPUNIT_ASSERT_PRINTF(expHex == resHex,
                            "getHexRepresentation() yielded unexpected "
                            "result:\n"
                            "\"%s\" (expected)\n"
                            "\"%s\" (result)\n",
                            expHex.isNull() ? "(NULL)" : expHex.data(),
                            resHex.isNull() ? "(NULL)" : resHex.data());

    CPPUNIT_ASSERT_MESSAGE("toBinary() causes object to relinquish its reference!",
                            origData == test.data());
}
void StringTestCase::substrTest()
{
    // Sunny day
    {
    	Sid::String str("foobajooba");
    	Sid::String sub = str.substr(0,0);

    	CPPUNIT_ASSERT_PRINTF( sub == "f",
    				"Basic substr logic is broken (input was %s, 0, 0)\nSubstring was %s\n",
    				str.data(),
    				sub.data());

    	sub = str.substr(0, 9);
    	CPPUNIT_ASSERT_PRINTF( sub == "foobajooba",
    				"Basic substr logic is broken (input was %s, 0, 9)\nSubstring was %s\n",
    				str.data(),
    				sub.data());

    	sub = str.substr(0, 8);
    	CPPUNIT_ASSERT_PRINTF( sub == "foobajoob",
    				"Basic substr logic is broken (input was %s, 0, 8)\nSubstring was %s\n",
    				str.data(),
    				sub.data());

    	sub = str.substr(1, 9);
    	CPPUNIT_ASSERT_PRINTF( sub == "oobajooba",
    				"Basic substr logic is broken (input was %s, 1, 9)\nSubstring was %s\n",
    				str.data(),
    				sub.data());

    	sub = str.substr(1, 8);
    	CPPUNIT_ASSERT_PRINTF( sub == "oobajoob",
    				"Basic substr logic is broken (input was %s, 1, 8)\nSubstring was %s\n",
    				str.data(),
    				sub.data());
    }

    // Null string
    {
    	Sid::String str;
    	Sid::String sub = str.substr(0,0);
    	CPPUNIT_ASSERT_MESSAGE("Substring (0,0) of a null string somehow is not null. Fascinating!\n",
    				sub.isNull());

    	sub = str.substr(0, -1);
    	CPPUNIT_ASSERT_MESSAGE( "Substring (0,-1) of a null string somehow is not null. Fascinating!\n",
    				sub.isNull());
    }

    // Empty string
    {
    	Sid::String str("");
    	Sid::String sub = str.substr(0,0);
    	CPPUNIT_ASSERT_MESSAGE("Substring (0,0) of an empty string somehow is not empty. Fascinating!\n",
    				sub.isEmpty() && !sub.isNull());

    	sub = str.substr(0, -1);
    	CPPUNIT_ASSERT_MESSAGE( "Substring (0,-1) of an empty string somehow is not empty. Fascinating!\n",
    				sub.isEmpty() && !sub.isNull());
    }

    // boundary fixup
    {
    	Sid::String str("foobajooba");
    	Sid::String sub = str.substr(0, -1);
    	CPPUNIT_ASSERT_PRINTF( sub == "foobajoob",
    				"Negative index code is somehow broken (input was %s, 0, -1)\nSubstring was %s\n",
    				str.data(), 
    				sub.data());

    	sub = str.substr(0, -9);

    	CPPUNIT_ASSERT_PRINTF( sub == "f",
    				"Negative index code is somehow broken (input was %s, 0, -9)\nSubstring was %s\n",
    				str.data(), 
    				sub.data());

    	sub = str.substr(0, -9999999);
    	CPPUNIT_ASSERT_PRINTF( sub == "f",
    			"Negative index modulus code is somehow broken (input was %s, 0, -9999999)\nSubstring was %s\n",
    			str.data(), 
    			sub.data());

    	sub = str.substr(-5, 2);
    	CPPUNIT_ASSERT_PRINTF( sub == "foo",
    				"Negative leading bound fixup seems to not be working (input was %s, -5, 2)\nSubstring was %s\n",
    				str.data(),
    				sub.data());

    	sub = str.substr(5, 2);
    	CPPUNIT_ASSERT_PRINTF( sub == "obaj",
    				"Bound swapping fixup seems to not be working (input was %s, 5, 2)\nSubstring was %s\n",
    				str.data(),
    				sub.data());

    	sub = str.substr(5, 900);
    	CPPUNIT_ASSERT_PRINTF( sub == "jooba",
    				"Large upper bound fixup seems to not be working (input was %s, 5, 900)\nSubstring was %s\n",
    				str.data(),
    				sub.data());

    	sub = str.substr(9, 900);
    	CPPUNIT_ASSERT_PRINTF( sub == "a",
    				"Large upper bound fixup seems to not be working (input was %s, 9, 900)\nSubstring was %s\n",
    				str.data(),
    				sub.data());

    	sub = str.substr(10, 9);
    	CPPUNIT_ASSERT_PRINTF( sub == "foobajooba",
    				"Large lower bound fixup seems to not be working (input was %s, 10, 900)\nSubstring was %s\n",
    				str.data(),
    				sub.data());

    	sub = str.substr(400, 9);
    	CPPUNIT_ASSERT_PRINTF( sub == "foobajooba",
    				"Large lower bound fixup seems to not be working (input was %s, 400, 900)\nSubstring was %s\n",
    				str.data(),
    				sub.data());
    }

}
void StringTestCase::escapingAndUnescapingTest()
{
    checkEscaping(Sid::String(), Sid::String());
    checkEscaping(Sid::String(4), "");
    checkEscaping("", "");
    checkEscaping(",", "\\,");
    checkEscaping("\"", "\\\"");
    checkEscaping("\\", "\\\\");
    checkEscaping("foobar", "foobar");
    checkEscaping("foo,bar", "foo\\,bar");
    checkEscaping("foo\"bar", "foo\\\"bar");
    checkEscaping("foo\\bar", "foo\\\\bar");
    checkEscaping(",,", "\\,\\,");
    checkEscaping("\"\"", "\\\"\\\"");
    checkEscaping("\\\\", "\\\\\\\\");

    checkUnescaping("\\", "");
    checkUnescaping("foo\\bar", "foobar");
    checkUnescaping("\\foobar", "foobar");
    checkUnescaping("foobar\\", "foobar");

    // .bwc. This code came from an #ifdef SE_STRING_TEST_PROGRAM block in
    // skype_string.cpp.
    int i;
    Sid::String strings[] = {
    	"Hello World!",
    	"Hel,lo\\ World!",
    	"Hel\"lo Wo\\9rld!",
    	"Hel,lo Wo\\0rld!",
    	Sid::String()
    };
    for (i = 0; !strings[i].isNull(); i++) {
    	Sid::String escaped = strings[i].escape();
    	Sid::String unescaped = escaped.unescape();
    	CPPUNIT_ASSERT_PRINTF( !strcmp((const char*)strings[i], (const char*)unescaped),
    				"String Failed:\n%s\n%s\n%s\n\n", 
    				(const char*)strings[i], 
    				(const char*)escaped, 
    				(const char*)unescaped);
    }

    // 0x5c = '\\', 0x30 = '0', 0x00 = 0, 0x22 = '"'
    const char bins[] = {
    	'1', '2', '3', '4', '5', '6', '7', '8' ,
    	'1', '2', 0x5c, 0x30, '5', '6', '7', '8' ,
    	'1', '2', 0x5c, 0x30, 0x5c, 0x5c, 0x5c, '8' ,
    	'1', '2', 0x5c, 0x30, '5', '6', '7', '8' ,
    	'1', '2', 0x00, '4', '5', '6', '7', '8' ,
    	'1', 0x5c, 0x00, 0x5c, '5', '6', 0x5c, 0x5c ,
    	'1', 0x5c, 0x00, 0x00, '5', 0x00, 0x5c, '8' ,
    	0x00, '2', 0x5c, 0x30, '5', 0x22, 0x22, '8' ,
    	0x5c, '2', 0x5c, 0x30, '5', 0x22, 0x22, 0x00 ,
    	0x00, 0x00, 0x5c, 0x30, '5', 0x22, 0x22, 0x5c ,
    	'E'
    };
    size_t bins_len = 8;
    for (i = 0; bins[i] != 'E'; i += bins_len) {
    	Sid::String escaped = Sid::String::from((char*)(bins + i), bins_len);
    	char *unescaped = (char *)malloc(escaped.length());
    	size_t unescaped_len = escaped.toBinary(unescaped);
    	//printf("%d, escaped.length()=%d unescaped_len=%d\n", i/bins_len, escaped.length(), unescaped_len);
    	CPPUNIT_ASSERT_PRINTF ( !memcmp((char*)(bins + i), unescaped, bins_len) && (unescaped_len == bins_len),
    				"Binary Failed: index %d\n", 
    				i/bins_len);
    	//printf("%s\n", (const char*)escaped.getHexRepresentation());
    	free(unescaped);
    }

    {
    	Sid::String test("foo");
    	test.markAsBinary();
    	CPPUNIT_ASSERT_PRINTF(test.isBinary(), 
    				"%s", "markAsBinary() seems "
    						"to have no effect.\n");
    }
}
void StringTestCase::testOwnership()
{
    // Test shallow copy semantics
    {
        Sid::String orig("foo bar");
        Sid::String shallowCopy(orig);
        CPPUNIT_ASSERT_MESSAGE("Shallow copy semantics for copy c'tor not working!",
                                    orig.data() == shallowCopy.data());
        Sid::String assigned;
        assigned = orig;
        CPPUNIT_ASSERT_MESSAGE("Shallow copy semantics for assignment operator"
                                    " not working!",
                                    orig.data() == assigned.data());
    }

    // Test copy-on-write semantics
    {
        Sid::String orig("foo bar");
        {
            Sid::String copy(orig);
            copy+=" baz";
            CPPUNIT_ASSERT_MESSAGE("Copy-on-write semantics not working for "
                                    "operator+=(const char*).",
                                    copy != orig);
        }
        {
            Sid::String copy(orig);
            copy+=Sid::String("baz");
            CPPUNIT_ASSERT_MESSAGE("Copy-on-write semantics not working for "
                                    "operator+=(const Sid::String&).",
                                    copy != orig);
        }
        {
            Sid::String copy(orig);
            copy=Sid::String("baz");
            CPPUNIT_ASSERT_MESSAGE("Copy-on-write semantics not working for "
                                    "operator=(const Sid::String&).",
                                    copy != orig);
        }
        {
            Sid::String copy(orig);
            copy="baz";
            CPPUNIT_ASSERT_MESSAGE("Copy-on-write semantics not working for "
                                    "operator=(const char*).",
                                    copy != orig);
        }
    }
    
    // Test deepCopy()
    {
        Sid::String orig("foobar");
        const char* origData = orig.data();
        Sid::String dCopy = orig.deepCopy();
        CPPUNIT_ASSERT_MESSAGE("deepCopy() yielded a shallow copy!",
                                orig.data() != dCopy.data());
        CPPUNIT_ASSERT_MESSAGE("deepCopy() caused original to relinquish its reference!",
                                orig.data() == origData);
        Sid::String copy(orig);
        CPPUNIT_ASSERT_MESSAGE("deepCopy() caused original to relinquish its reference!",
                                orig.data() == origData);
    }

}
void checkTrim(const Sid::String& test,
    	const Sid::String& toTrim,
    	const Sid::String& expected)
{
    const char* origData = test.data();
    Sid::String trimmed = test.trim(toTrim);
    CPPUNIT_ASSERT_PRINTF(trimmed == expected,
    			"trim(\"%s\") did not yield expected result:\n"
    			"%s (prefix to remove)\n"
    			"%*s (expected result)\n"
    			"%s (string to trim)\n"
    			"%*s (instead got)\n",
    			toTrim.isNull() ? "(NULL)" : toTrim.data(),
    			toTrim.isNull() ? "(NULL)" : toTrim.data(),
    			test.size(),
    			expected.isNull() ? "(NULL)" : expected.data(),
    			test.isNull() ? "(NULL)" : test.data(),
    			test.size(),
    			trimmed.isNull() ? "(NULL)" : trimmed.data());
    CPPUNIT_ASSERT_MESSAGE("trim() causes object to relinquish its reference!",
                            origData == test.data());
}
void checkRight(const Sid::String& test, 
    	unsigned int len,
    	const Sid::String& expected)
{
    const char* origData = test.data();
    Sid::String right = test.right(len);
    CPPUNIT_ASSERT_PRINTF(right == expected,
    			"right(%d) did not yield expected result for:\n"
    			"%s\n%*s (got)\n%*s (expected)\n",
    			len,
    			test.isNull() ? "(NULL)" : test.data(),
    			test.size(),
    			right.isNull() ? "(NULL)" : right.data(),
    			test.size(),
    			expected.isNull() ? "(NULL)" : expected.data());
    CPPUNIT_ASSERT_MESSAGE("right() causes object to relinquish its reference!",
                            origData == test.data());
}