Skip to main content
GameDev.net gamedev.net
🔒 Locked

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

Started by Programmer16 Oct 15, 2004 at 12:32 AM 4 replies 1.8k views
Original Post
Programmer16
Programmer16
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!
JohnBolton
JohnBolton
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?
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Fruny
Fruny
I completely agree with JohnBolton.

If you want a printf-like formatting utility, you can find one here.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Doc
Doc
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]
Programmer16
Programmer16
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!
MaulingMonkey
MaulingMonkey
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)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.