]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - libs/str.h
Merge branch 'master' into divVerent/farplanedist-sky-fix
[xonotic/netradiant.git] / libs / str.h
index 0ee38f812953384144f9031c457405e34e0891e7..9090bf2d6e4587b797c1fbfa7a87d8a0fc63e1b3 100644 (file)
 
 #include <string.h>
 #include <ctype.h>
-#include <stdarg.h>
 
-#ifdef __APPLE__
-  #ifdef NULL
-       #undef NULL
-       #define NULL 0
-  #endif
-#endif
+#include <stdio.h>
+#include <stdarg.h>
 
+#include <cstdio>
 
-#ifdef _WIN32
+#ifdef _MSC_VER
 #define strcasecmp strcmpi
+#if _MSC_VER < 1400
+#define vsnprintf std::vsnprintf
+#endif
+#else
+#include <cstddef>
 #endif
 
 // NOTE TTimo __StrDup was initially implemented in pakstuff.cpp
 
 #define __StrDup Q_StrDup
 
-inline char* Q_StrDup( char* _pStr ) {
-       const char* pStr = _pStr;
-       if ( pStr == NULL ) {
-               pStr = "";
-       }
-
-       return strcpy( new char[ strlen( pStr ) + 1 ], pStr );
-}
-
-inline char* Q_StrDup( const char* pStr ) {
-       if ( pStr == NULL ) {
+inline char* Q_StrDup( const char* pStr ){
+       if ( pStr == 0 ) {
                pStr = "";
        }
 
        return strcpy( new char[strlen( pStr ) + 1], pStr );
 }
 
-#if defined ( __linux__ ) || defined ( __APPLE__ )
+#if !defined( WIN32 )
 #define strcmpi strcasecmp
 #define stricmp strcasecmp
 #define strnicmp strncasecmp
@@ -105,7 +97,7 @@ inline char* strupr( char* string ){
 }
 #endif
 
-static char *g_pStrWork = NULL;
+static char *g_pStrWork = 0;
 
 class Str
 {
@@ -132,7 +124,7 @@ Str( const char *p ){
 
 Str( const unsigned char *p ){
        m_bIgnoreCase = true;
-       m_pStr = __StrDup( (const char *)p );
+       m_pStr = __StrDup( reinterpret_cast<const char *>( p ) );
 }
 
 Str( const char c ){
@@ -146,6 +138,10 @@ const char* GetBuffer() const {
        return m_pStr;
 }
 
+char* GetBuffer(){
+       return m_pStr;
+}
+
 Str( const Str &s ){
        m_bIgnoreCase = true;
        m_pStr = __StrDup( s.GetBuffer() );
@@ -153,10 +149,10 @@ Str( const Str &s ){
 
 void Deallocate(){
        delete []m_pStr;
-       m_pStr = NULL;
+       m_pStr = 0;
 }
 
-void Allocate( int n ){
+void Allocate( std::size_t n ){
        Deallocate();
        m_pStr = new char[n];
 }
@@ -166,13 +162,13 @@ void MakeEmpty(){
        m_pStr = __StrDup( "" );
 }
 
-virtual ~Str(){
+~Str(){
        Deallocate();
        // NOTE TTimo: someone explain this g_pStrWork to me?
        if ( g_pStrWork ) {
                delete []g_pStrWork;
        }
-       g_pStrWork = NULL;
+       g_pStrWork = 0;
 }
 
 void MakeLower(){
@@ -189,21 +185,21 @@ void MakeUpper(){
 
 void TrimRight(){
        char* lpsz = m_pStr;
-       char* lpszLast = NULL;
+       char* lpszLast = 0;
        while ( *lpsz != '\0' )
        {
                if ( isspace( *lpsz ) ) {
-                       if ( lpszLast == NULL ) {
+                       if ( lpszLast == 0 ) {
                                lpszLast = lpsz;
                        }
                }
                else{
-                       lpszLast = NULL;
+                       lpszLast = 0;
                }
                lpsz++;
        }
 
-       if ( lpszLast != NULL ) {
+       if ( lpszLast != 0 ) {
                // truncate at trailing space start
                *lpszLast = '\0';
        }
@@ -216,29 +212,25 @@ void TrimLeft(){
                lpsz++;
 
        // fix up data and length
-       int nDataLength = GetLength() - ( lpsz - m_pStr );
+       std::size_t nDataLength = GetLength() - ( lpsz - m_pStr );
        memmove( m_pStr, lpsz, ( nDataLength + 1 ) );
 }
 
-int Find( const char *p ){
-       char *pf = strstr( m_pStr, p );
-       return ( pf ) ? ( pf - m_pStr ) : -1;
+char* Find( const char *p ){
+       return strstr( m_pStr, p );
 }
 
 // search starting at a given offset
-int Find( const char *p, int offset ){
-       char *pf = strstr( m_pStr + offset, p );
-       return ( pf ) ? ( pf - m_pStr ) : -1;
+char* Find( const char *p, std::size_t offset ){
+       return strstr( m_pStr + offset, p );
 }
 
-int Find( const char ch ){
-       char *pf = strchr( m_pStr, ch );
-       return ( pf ) ? ( pf - m_pStr ) : -1;
+char* Find( const char ch ){
+       return strchr( m_pStr, ch );
 }
 
-int ReverseFind( const char ch ){
-       char *pf = strrchr( m_pStr, ch );
-       return ( pf ) ? ( pf - m_pStr ) : -1;
+char* ReverseFind( const char ch ){
+       return strrchr( m_pStr, ch );
 }
 
 int Compare( const char* str ) const {
@@ -249,11 +241,11 @@ int CompareNoCase( const char* str ) const {
        return strcasecmp( m_pStr, str );
 }
 
-int GetLength(){
+std::size_t GetLength(){
        return ( m_pStr ) ? strlen( m_pStr ) : 0;
 }
 
-const char* Left( int n ){
+const char* Left( std::size_t n ){
        delete []g_pStrWork;
        if ( n > 0 ) {
                g_pStrWork = new char[n + 1];
@@ -262,17 +254,18 @@ const char* Left( int n ){
        }
        else
        {
+               g_pStrWork = "";
                g_pStrWork = new char[1];
                g_pStrWork[0] = '\0';
        }
        return g_pStrWork;
 }
 
-const char* Right( int n ){
+const char* Right( std::size_t n ){
        delete []g_pStrWork;
        if ( n > 0 ) {
                g_pStrWork = new char[n + 1];
-               int nStart = GetLength() - n;
+               std::size_t nStart = GetLength() - n;
                strncpy( g_pStrWork, &m_pStr[nStart], n );
                g_pStrWork[n] = '\0';
        }
@@ -284,11 +277,11 @@ const char* Right( int n ){
        return g_pStrWork;
 }
 
-const char* Mid( int nFirst ) const {
+const char* Mid( std::size_t nFirst ) const {
        return Mid( nFirst, strlen( m_pStr ) - nFirst );
 }
 
-const char* Mid( int first, int n ) const {
+const char* Mid( std::size_t first, std::size_t n ) const {
        delete []g_pStrWork;
        if ( n > 0 ) {
                g_pStrWork = new char[n + 1];
@@ -297,13 +290,14 @@ const char* Mid( int first, int n ) const {
        }
        else
        {
+               g_pStrWork = "";
                g_pStrWork = new char[1];
                g_pStrWork[0] = '\0';
        }
        return g_pStrWork;
 }
 
-#ifdef __G_LIB_H__
+#if 0 // defined(__G_LIB_H__)
 void Format( const char* fmt, ... ){
        va_list args;
        char *buffer;
@@ -318,38 +312,38 @@ void Format( const char* fmt, ... ){
 }
 #else
 void Format( const char* fmt, ... ){
-       va_list args;
-       m_pStr = new char[1024];
+       char buffer[1024];
 
-       va_start( args, fmt );
-       vsprintf( m_pStr, fmt, args );
-       va_end( args );
+       {
+               va_list args;
+               va_start( args, fmt );
+               vsnprintf( buffer, 1023, fmt, args );
+               va_end( args );
+       }
+
+       delete[] m_pStr;
+       m_pStr = __StrDup( buffer );
 }
 #endif
 
-void SetAt( int n, char ch ){
-       if ( n >= 0 && n < GetLength() ) {
+void SetAt( std::size_t n, char ch ){
+       if ( n < GetLength() ) {
                m_pStr[n] = ch;
        }
 }
 
 // NOTE: unlike CString, this looses the pointer
-void ReleaseBuffer( int n = -1 ){
-       if ( n == -1 ) {
-               n = GetLength();
-       }
-
+void ReleaseBuffer( std::size_t n ){
        char* tmp = m_pStr;
        tmp[n] = '\0';
        m_pStr = __StrDup( tmp );
        delete []tmp;
 }
+void ReleaseBuffer(){
+       ReleaseBuffer( GetLength() );
+}
 
-char* GetBufferSetLength( int n ){
-       if ( n < 0 ) {
-               n = 0;
-       }
-
+char* GetBufferSetLength( std::size_t n ){
        char *p = new char[n + 1];
        strncpy( p, m_pStr, n );
        p[n] = '\0';
@@ -366,15 +360,11 @@ operator void*() {
 operator char*() {
        return m_pStr;
 }
-operator const char*(){
-       return reinterpret_cast<const char*>( m_pStr );
-}
+operator const char*() const { return reinterpret_cast<const char*>( m_pStr ); }
 operator unsigned char*() {
        return reinterpret_cast<unsigned char*>( m_pStr );
 }
-operator const unsigned char*() {
-       return reinterpret_cast<const unsigned char*>( m_pStr );
-}
+operator const unsigned char*() const { return reinterpret_cast<const unsigned char*>( m_pStr ); }
 Str& operator =( const Str& rhs ){
        if ( &rhs != this ) {
                delete[] m_pStr;
@@ -392,7 +382,7 @@ Str& operator =( const char* pStr ){
 }
 
 Str& operator +=( const char ch ){
-       int len = GetLength();
+       std::size_t len = GetLength();
        char *p = new char[len + 1 + 1];
 
        if ( m_pStr ) {
@@ -437,11 +427,46 @@ bool operator <( const char* pStr ) const { return ( m_bIgnoreCase ) ? stricmp(
 bool operator >( const Str& rhs ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, rhs.m_pStr ) > 0 : strcmp( m_pStr, rhs.m_pStr ) > 0; }
 bool operator >( char* pStr ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, pStr ) > 0 : strcmp( m_pStr, pStr ) > 0; }
 bool operator >( const char* pStr ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, pStr ) > 0 : strcmp( m_pStr, pStr ) > 0; }
-char& operator []( int nIndex ) { return m_pStr[nIndex]; }
-char& operator []( int nIndex ) const { return m_pStr[nIndex]; }
-const char GetAt( int nIndex ) { return m_pStr[nIndex]; }
+char& operator []( std::size_t nIndex ) { return m_pStr[nIndex]; }
+const char& operator []( std::size_t nIndex ) const { return m_pStr[nIndex]; }
+const char GetAt( std::size_t nIndex ) { return m_pStr[nIndex]; }
 };
 
 
+template<typename TextOutputStreamType>
+inline TextOutputStreamType& ostream_write( TextOutputStreamType& ostream, const Str& str ){
+       return ostream << str.GetBuffer();
+}
+
+
+inline void AddSlash( Str& strPath ){
+       if ( strPath.GetLength() > 0 ) {
+               if ( ( strPath.GetAt( strPath.GetLength() - 1 ) != '/' ) &&
+                        ( strPath.GetAt( strPath.GetLength() - 1 ) != '\\' ) ) {
+                       strPath += '/';
+               }
+       }
+}
+
+inline bool ExtractPath_and_Filename( const char* pPath, Str& strPath, Str& strFilename ){
+       Str strPathName;
+       strPathName = pPath;
+       const char* substr = strPathName.ReverseFind( '\\' );
+       if ( substr == 0 ) {
+               // TTimo: try forward slash, some are using forward
+               substr = strPathName.ReverseFind( '/' );
+       }
+       if ( substr != 0 ) {
+               std::size_t nSlash = substr - strPathName.GetBuffer();
+               strPath = strPathName.Left( nSlash + 1 );
+               strFilename = strPathName.Right( strPathName.GetLength() - nSlash - 1 );
+       }
+       else{
+               strFilename = pPath;
+       }
+       return true;
+}
+
+
 
 #endif