CBStr: a BSTR wrapper-class with string manipulation members
After doing a great deal of frustrated hair-pulling I finally got around to implementing this class, CBstr. It is a C++ class derived from the MS VC++ _bstr_t COM support class with the added benefit of a barrow-load of string manipulation methods. The original idea came after seeing Alex Stockton's NoMFC::CString class at www.WorldofATL.com. This class was used as the template for the public interface.
The class uses the same public "interface" as the NoMFC::CString Class with a couple of minor differences and as a result has all the functionality of the "real" (MFC) CString class with a few extra's. And because it is derived from _bstr_t
Because the class is derived from _bstr_t it is very easy to use instead of that class, especially where string manipulation of any kind is required. If you are not planning on using the string-manipulation functionality I would suggest sticking with the _bstr_t class for reduced class size.
To use the class simply #include the CBstrImpl.h header file supplied in the Zip, and have this and CBStr.h in your include path.
A demo program (and my test rig) follows and is included in the zip file. This exercises all of the functionality of of the class, but for more information I would suggest looking at the documentation of the MFC CString class - it doesn't seem woth copying it out ;-)
This code has been tested with Visual C++ 5.0 Service Pack 3, it has not been tested with Visual C++ 6.0
Example code
// Main.cpp
//
// Test harness to execise the CBstr class
// derived from _bstr_t and based on the
// NoMFC::CString class from www.worldofatl.com
//
// If anyone can figure out why the ostream::operator<< refuses to
// use the implicit cast to const char* or char* then please email me
// at gary.olliffe@parallax.co.uk
//
//
#include "CBstrImpl.h"
#include <iostream>
using std::cout;
const TCHAR* Test(const TCHAR* psz);
// This test only works in ANSI (not UNICODE) builds
// due to lack of _T() and stream insertion operator
int main()
{
// Create a proper BSTR
BSTR bstr = ::SysAllocString(L"Hello World");
// Create two objects of out new class
CBstr newstr(bstr, true); //Take a copy of bstr
CBstr newstr2(bstr, false); //attach to bstr
// test the MakeUpper method
newstr2.MakeUpper();
// Extract the BSTR (this gives a reference
// to the encapulated BSTR, not a copy)
BSTR ptrcopy = newstr2;
// Take a copy of the encapsulated BSTR
BSTR deepcopy = newstr2.copy();
// Test cast to char *
char * ansistr = newstr2;
// Test cast to const char *
const char* ansicstr = newstr2;
// output results
cout << ansistr << "\n" << ansicstr;
cout << newstr2;
// Create another string for testing
CBstr str("twenty");
// Call a method that takes a const char* parameter
Test(str);
// create another CBstr from the first
CBstr str2(str);
// output results
cout << (const char*)str << "\n";
cout << (const char*)str2 << "\n";
// test the format method
str.Format("sder %d %s", 1, "ss");
cout << (const char*)str << "\n";
// test the length() method
CBstr s("abcdef");
cout << s.length() << "\n"; // == 6
// test the isempty() method
CBstr s2;
cout << s2.IsEmpty() << "\n"; // == true
// test the Empty method
CBstr s3("abc");
s3.Empty();
cout << s3.length() << "\n"; // == 0
// Test GetAt() method
CBstr s4("abcdef");
cout << s4.GetAt(2) << "\n"; // == 'c'
// Test the operator[]
CBstr s5("abc");
cout << s5[1] << "\n"; // == 'b'
s5.SetAt(1, 'X');
cout << s5[1] << "\n"; // == 'X'
// test assignment operators
CBstr s6, s7; // Empty CBstr objects
s6 = "cat"; // s6 == "cat"
cout << (const char*)s6 << "\n";
s7 = s6; // s6 and s7 each == "cat"
cout << (const char*)s7 << "\n";
// test operator+()
s6 = "the " + s6; // Or expressions
cout << (const char*)s6 << "\n";
// example for CBstr::operator +
CBstr s8("abc");
CBstr s9("def");
cout << (const char*)(s8 + s9 ) << "\n"; // == "abcdef"
CBstr s10;
s10 = CBstr("abc") + "def" ; // == "abcdef"
cout << (const char*)s10 << "\n";
// example for CBstr::operator +=
CBstr s11("abc");
cout << (const char*)( s11 += "def") << "\n"; // == "abcdef"
// example for CBstr Comparison Operators
CBstr s12("abc");
CBstr s13("abd");
if (s12 < s13)
cout << "s12 < 13" << "\n"; // == true Operator is overloaded for both.
if ("ABC" < s12)
cout << "ABC < s12" << "\n"; // == true CBstr and char*
if (s13 > "abe")
cout << "s13 > abe" << "\n"; // == false
if (s13 == "abd")
cout << "s13 == abd" << "\n"; // == true
// example for CBstr::Compare
CBstr s14( "abc" );
CBstr s15( "abd" );
cout << s14.Compare(s15) << "\n"; // == -1 // Compare with another CBstr.
cout << s14.Compare("abe") << "\n"; // == -1 // Compare with LPTSTR string.
// example for CBstr::CompareNoCase
CBstr s16( "abc" );
CBstr s17( "ABD" );
cout << s16.CompareNoCase( s17 ) << "\n"; // == -1 // Compare with a CBstr.
cout << s16.Compare( "ABE" ) << "\n"; // == 1 // Compare with LPTSTR string.
// example for CBstr::Mid
CBstr s18("abcdef");
cout << (const char*)s18.Mid(2, 3) << "\n"; // == _T("cde")
// example for CBstr::Left
CBstr s19( _T("abcdef") );
cout << (const char*)s19.Left(2) << "\n"; // == _T("ab")
// example for CBstr::Right
CBstr s20( _T("abcdef") );
cout << (const char*)s20.Right(2) << "\n"; // == _T("ef")
// example for CBstr::SpanIncluding
CBstr s21( "cabbage" );
CBstr s22 = s21.SpanIncluding( "abc" );
cout << (const char*)s22 << "\n"; // == "cabba"
s22 = s21.SpanIncluding( "xyz" );
cout << s22.IsEmpty( ) << "\n"; // == true
// example for CBstr::MakeUpper
CBstr s23( "abc" );
s23.MakeUpper();
cout << (const char*)s23 << "\n"; // == "ABC"
// example for CBstr::MakeLower
CBstr s24( "ABC" );
s24.MakeLower();
cout << (const char*)s24 << "\n"; // == "abc"
// example for CBstr::MakeReverse
CBstr s25( "abc" );
s25.MakeReverse();
cout << (const char*)s25 << "\n"; // == "cba"
// example for CBstr::Find
CBstr s26( "abcdef" );
cout << s26.Find( 'c' ) << "\n"; // == 2
cout << s26.Find( "de" ) << "\n"; // == 3
// example for CBstr::ReverseFind
CBstr s27( "abcabc" );
cout << s27.ReverseFind( 'b' ) << "\n"; // == 4
// example for CBstr::FindOneOf
CBstr s28( "abcdef" );
cout << s28.FindOneOf( "xd" ) << "\n"; // == 3 // 'd' is first match
return 0;
}

Comments
There are no comments yet. Be the first to comment!