Sign in to follow this  
Programmer16

My std::string wrapper class : speed issues and code bloat

Recommended Posts

Programmer16    2321
For about the last half a hour to a hour, I've been working on a string class for use in my game engine. What I really want to know is if this is going to slow my code down much, and if I added to much to the class:
class StlString
{
	std::string m_String;
public:
	StlString()							{}
	
	StlString(const char* pString)		{ m_String = pString;				}
	StlString(std::string String)		{ m_String = String;				}
	StlString(const StlString& String)	{ m_String = String.GetString();	}

	const StlString& Format(const char* pString, ...)
	{
		char Buffer[1024];
		va_list VaList;

		va_start(VaList, pString);
		vsprintf(Buffer, pString, VaList);
		va_end(VaList);

		m_String = Buffer;
		return *this;
	}

	const StlString& Format(std::string String, ...)
	{
		char Buffer[1024];
		va_list VaList;

		va_start(VaList, String);
		vsprintf(Buffer, String.c_str(), VaList);
		va_end(VaList);

		m_String = Buffer;
		return *this;
	}

	const StlString& Format(const StlString& String, ...)
	{
		char Buffer[1024];
		va_list VaList;

		va_start(VaList, String);
		vsprintf(Buffer, String.c_str(), VaList);
		va_end(VaList);

		m_String = Buffer;
		return *this;
	}
	
	StlString& operator >>( char ch )
	{
		m_String += ch;
		return *this;
	}
	
	StlString& operator >>( unsigned char uch )
	{
		m_String += uch;
		return *this;
	}
	
	StlString& operator >>( signed char sch )
	{
		m_String += sch;
		return *this;
	}
	
	StlString& operator >>( const char* psz )
	{
		m_String += psz;
		return *this;
	}
	
	StlString& operator >>( const unsigned char* pusz )
	{
		m_String += (char*)pusz;
		return *this;
	}
	
	StlString& operator >>( const signed char* pssz )
	{
		m_String += (char*)pssz;
		return *this;
	}
	
	StlString& operator >>( short s )
	{
		Format("%s%i", m_String.c_str(), s);
		return *this;
	}
	
	StlString& operator >>( unsigned short us )
	{
		Format("%s%i", m_String.c_str(), us);
		return *this;
	}
	
	StlString& operator >>( int n )
	{
		Format("%s%i", m_String.c_str(), n);
		return *this;
	}
	
	StlString& operator >>( unsigned int un )
	{
		Format("%s%i", m_String.c_str(), un);
		return *this;
	}
	
	StlString& operator >>( long l )
	{
		Format("%s%i", m_String.c_str(), l);
		return *this;
	}
	
	StlString& operator >>( unsigned long ul )
	{
		Format("%s%i", m_String.c_str(), ul);
		return *this;
	}
	
	StlString& operator >>( float f )
	{
		Format("%s%f", m_String.c_str(), f);
		return *this;
	}

	StlString& operator >>(const StlString& NewString)
	{
		m_String = NewString.GetString();
		return *this;
	}

	const StlString& operator =(const char* pString)		{ m_String = pString;				return *this;	}
	const StlString& operator =(std::string String)			{ m_String = String;				return *this;	}
	const StlString& operator =(const StlString& String)	{ m_String = String.GetString();	return *this;	}
	const StlString& operator =(char ch)					{ m_String = ch;					return *this;	}
	const StlString& operator =(unsigned char uch)			{ m_String = uch;					return *this;	}
	const StlString& operator =(signed char sch)			{ m_String = sch;					return *this;	}
	const StlString& operator =(const unsigned char* pusz)	{ m_String = (char*)pusz;			return *this;   }
	const StlString& operator =(const signed char* pssz)	{ m_String = (char*)pssz;			return *this;	}
	const StlString& operator =(short s)					{ Format("%i", s);					return *this;	}
	const StlString& operator =(unsigned short us)			{ Format("%i", us);					return *this;	}
	const StlString& operator =(int n)						{ Format("%i", n);					return *this;	}
	const StlString& operator =(unsigned int un)			{ Format("%i", un);					return *this;	}
	const StlString& operator =(long l)						{ Format("%i", l);					return *this;	}
	const StlString& operator =(unsigned long ul)			{ Format("%i", ul);					return *this;	}
	const StlString& operator =(float fFloat)				{ Format("%f", fFloat);				return *this;	}

	const StlString& operator +=(const char* pString)		{ m_String += pString;						return *this;	}
	const StlString& operator +=(std::string String)		{ m_String += String;						return *this;	}
	const StlString& operator +=(const StlString& String)	{ m_String += String.GetString();			return *this;	}
	const StlString& operator +=(char ch)					{ m_String += ch;							return *this;	}
	const StlString& operator +=(unsigned char uch)			{ m_String += uch;							return *this;	}
	const StlString& operator +=(signed char sch)			{ m_String += sch;							return *this;	}
	const StlString& operator +=(const unsigned char* pusz)	{ m_String += (char*)pusz;					return *this;   }
	const StlString& operator +=(const signed char* pssz)	{ m_String += (char*)pssz;					return *this;	}
	const StlString& operator +=(short s)					{ Format("%s%i", m_String.c_str(), s);		return *this;	}
	const StlString& operator +=(unsigned short us)			{ Format("%s%i", m_String.c_str(), us);		return *this;	}
	const StlString& operator +=(int n)						{ Format("%s%i", m_String.c_str(), n);		return *this;	}
	const StlString& operator +=(unsigned int un)			{ Format("%s%i", m_String.c_str(), un);		return *this;	}
	const StlString& operator +=(long l)					{ Format("%s%i", m_String.c_str(), l);		return *this;	}
	const StlString& operator +=(unsigned long ul)			{ Format("%s%i", m_String.c_str(), ul);		return *this;	}
	const StlString& operator +=(float fFloat)				{ Format("%s%f", m_String.c_str(), fFloat);	return *this;	}
	
	StlString operator +(const char* pString) const			{ return StlString(m_String + pString);												}
	StlString operator +(std::string String) const			{ return StlString(m_String + String);												}
	StlString operator +(const StlString& String) const		{ return StlString(m_String + String.GetString());									}
	StlString operator +(char ch)							{ return StlString(m_String + ch);													}
	StlString operator +(unsigned char uch)					{ return StlString(m_String + (char*)uch);													}
	StlString operator +(signed char sch)					{ return StlString(m_String + (char*)sch);													}
	StlString operator +(const unsigned char* pusz)			{ return StlString(m_String + (char*)pusz);		    								}
	StlString operator +(const signed char* pssz)			{ return StlString(m_String + (char*)pssz);											}
	StlString operator +(short s)							{ StlString NewString; return NewString.Format("%s%i", m_String.c_str(), s);		}
	StlString operator +(unsigned short us)					{ StlString NewString; return NewString.Format("%s%i", m_String.c_str(), us);		}
	StlString operator +(int n)								{ StlString NewString; return NewString.Format("%s%i", m_String.c_str(), n);		}
	StlString operator +(unsigned int un)					{ StlString NewString; return NewString.Format("%s%i", m_String.c_str(), un);		}
	StlString operator +(long l)							{ StlString NewString; return NewString.Format("%s%i", m_String.c_str(), l);		}
	StlString operator +(unsigned long ul)					{ StlString NewString; return NewString.Format("%s%i", m_String.c_str(), ul);		}
	StlString operator +(float fFloat)						{ StlString NewString; return NewString.Format("%s%f", m_String.c_str(), fFloat);	}

	std::string GetString() const										{ return m_String;																}
	const char*	c_str() const											{ return m_String.c_str();														}
	void GetWideVersion(WCHAR* pBuffer, unsigned int nBufferSize) const	{ MultiByteToWideChar(CP_ACP, 0, m_String.c_str(), -1, pBuffer, nBufferSize);	}
	int ConvertToInt()													{ return atoi(m_String.c_str());												}
};


Thanks!

Share this post


Link to post
Share on other sites
JohnBolton    1372
The problem is not slowness or code bloat. The problem is that you are wrapping std::string just so you can add the ability to do sprintf. My suggestion is to stick with std:string and do one of the following instead:

1. Implement this function: std::string Format( char const * format, ... ).
2. Implement something similar to std::ostringstream.
3. Use std::ostringstream.
4. Rather than StlString containing a std::string, it could be derived from std::string. That would eliminate the need to reimplement all of std::string's public member functions. However, I would still consider 1, 2, or 3 before doing this.

As a side note, you have a buffer-overflow problem. What happens if the formatted string is longer than 1023 characters?

Share this post


Link to post
Share on other sites
Doc    586
Consider boost::format. I would've posted the link but I just realised Fruny beat me to it.

Damn you Fruny! How can I hope to increase my rating with you around! [razz]

Share this post


Link to post
Share on other sites
Programmer16    2321
I should have mentioned that I'm not finished with it. I'm still going to add features for parsing and loading, etc.

About the buffer overflow, I can't figure out a way around using a set buffer size, other than the function passing in an integer (which would be better than a buffer overflow, and better than assuming a size).

Thanks!

Share this post


Link to post
Share on other sites
MaulingMonkey    1730
Instead of this horrible, easily buffer-overflown, non-typesafe class you've hobbled together, use boost::format or some other allready existing formatting utility.

Simple examples:


#include <boost/format.hpp>
#include <iostream>
#include <string>
using namespace boost;
using namespace std;

int main ( int argc , char ** argv )
{
string thingilike = "pie";
cout << format("I like %1%") % thingilike << endl;
string rockthebigone = str( format("Rock %1% big %2%") % "the" % "one" );
cout << rockthebigone << endl;
}


Not only is it like printf - it's typesafe, it's class-safe, it will throw an exception if it has the wrong number of arguments supplied, it's more versitile, it's sexier, it's 1337, it's awesometastic, and it's part of boost.

Look at the examples on the linked page for more uses.

(just underscoring the point)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this