]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/splines/util_str.h
initial
[xonotic/netradiant.git] / libs / splines / util_str.h
1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 //need to rewrite this
23
24 #ifndef __UTIL_STR_H__
25 #define __UTIL_STR_H__
26
27 #include <assert.h>
28 #include <string.h>
29 #include <stdio.h>
30
31 #ifdef _WIN32
32 #pragma warning(disable : 4710)     // function 'blah' not inlined
33 #endif
34
35 void TestStringClass ();
36
37 class strdata
38    {
39    public:
40       strdata () : len( 0 ), refcount ( 0 ), data ( NULL ), alloced ( 0 ) {}
41       ~strdata () 
42          {
43          if ( data )
44             delete [] data;
45          }
46
47       void AddRef () { refcount++; }
48       bool DelRef () // True if killed
49          {
50          refcount--;
51          if ( refcount < 0 )
52             {
53             delete this;
54             return true;
55             }
56          
57          return false;
58          }
59
60       int len;
61       int refcount;
62       char *data;
63       int alloced;
64    };
65
66 class idStr {
67 protected:
68         strdata *m_data;
69         void EnsureAlloced ( int, bool keepold = true );
70         void EnsureDataWritable ();
71
72 public:
73         ~idStr();
74         idStr();
75         idStr( const char *text );
76         idStr( const idStr& string );
77         idStr( const idStr string, int start, int end );
78         idStr( const char ch );
79         idStr( const int num );
80         idStr( const float num );
81         idStr( const unsigned num );
82         int     length( void ) const;
83         int     allocated( void ) const;
84         const char * c_str( void ) const;
85
86         void            append( const char *text );
87         void            append( const idStr& text );
88         char            operator[]( int index ) const;
89         char&           operator[]( int index );
90
91         void            operator=( const idStr& text );
92         void            operator=( const char *text );
93
94         friend  idStr           operator+( const idStr& a, const idStr& b );
95         friend  idStr           operator+( const idStr& a, const char *b );
96         friend  idStr           operator+( const char *a, const idStr& b );
97
98     friend      idStr           operator+( const idStr& a, const float b );
99     friend      idStr           operator+( const idStr& a, const int b );
100     friend      idStr           operator+( const idStr& a, const unsigned b );
101     friend      idStr           operator+( const idStr& a, const bool b );
102     friend      idStr           operator+( const idStr& a, const char b );
103
104         idStr&          operator+=( const idStr& a );
105         idStr&          operator+=( const char *a );
106         idStr&          operator+=( const float a );
107         idStr&          operator+=( const char a );
108         idStr&          operator+=( const int a );
109         idStr&          operator+=( const unsigned a );
110         idStr&          operator+=( const bool a );
111
112         friend  bool            operator==(     const idStr& a, const idStr& b );
113         friend  bool            operator==(     const idStr& a, const char *b );
114         friend  bool            operator==(     const char *a, const idStr& b );
115
116         friend  bool            operator!=(     const idStr& a, const idStr& b );
117         friend  bool            operator!=(     const idStr& a, const char *b );
118         friend  bool            operator!=(     const char *a, const idStr& b );
119
120         operator const char * () const;
121         operator const char * ();
122
123     int      icmpn( const char *text, int n ) const;
124         int      icmpn( const idStr& text, int n ) const;
125         int      icmp( const char *text ) const;
126         int      icmp( const idStr& text ) const;
127         int      cmpn( const char *text, int n ) const;
128         int      cmpn( const idStr& text, int n ) const;
129         int      cmp( const char *text ) const;
130         int      cmp( const idStr& text ) const;
131
132         void     tolower( void );
133         void     toupper( void );
134
135         static   char     *tolower( char *s1 );
136         static   char     *toupper( char *s1 );
137
138         static   int      icmpn( const char *s1, const char *s2, int n );
139         static   int      icmp( const char *s1, const char *s2 );
140         static   int      cmpn( const char *s1, const char *s2, int n );
141         static   int      cmp( const char *s1, const char *s2 );
142
143         static   void     snprintf ( char *dst, int size, const char *fmt, ... );
144
145         static   bool      isNumeric( const char *str );
146     bool    isNumeric( void ) const;
147
148         void     CapLength ( int );
149
150         void     BackSlashesToSlashes ();
151
152 };
153
154 inline idStr::~idStr()
155         {
156    if ( m_data )
157       {
158       m_data->DelRef ();
159       m_data = NULL;
160       }
161         }
162
163 inline idStr::idStr() : m_data ( NULL )
164         {
165    EnsureAlloced ( 1 );
166         m_data->data[ 0 ] = 0;
167         }
168
169 inline idStr::idStr
170         (
171         const char *text
172    ) : m_data ( NULL )
173
174         {
175    int len;
176
177         assert( text );
178
179         if ( text )
180                 {
181       len = strlen( text );
182                 EnsureAlloced ( len + 1 );
183                 strcpy( m_data->data, text );
184       m_data->len = len;
185                 }
186         else
187                 {
188       EnsureAlloced ( 1 );
189                 m_data->data[ 0 ] = 0;
190                 m_data->len = 0;
191                 }
192         }
193
194 inline idStr::idStr
195         (
196         const idStr& text
197    ) : m_data ( NULL )
198
199         {
200    m_data = text.m_data;
201    m_data->AddRef ();
202    }
203
204 inline idStr::idStr
205         (
206         const idStr text, 
207         int start,
208         int end
209    ) : m_data ( NULL )
210
211         {
212         int i;
213    int len;
214
215         if ( end > text.length() )
216                 {
217                 end = text.length();
218                 }
219
220         if ( start > text.length() )
221                 {
222                 start = text.length();
223                 }
224
225         len = end - start;
226         if ( len < 0 )
227                 {
228                 len = 0;
229                 }
230
231    EnsureAlloced ( len + 1 );
232
233         for( i = 0; i < len; i++ )
234                 {
235                 m_data->data[ i ] = text[ start + i ];
236                 }
237
238         m_data->data[ len ] = 0;
239    m_data->len = len;
240         }
241
242 inline idStr::idStr
243    (
244    const char ch
245    ) : m_data ( NULL )
246
247    {
248    EnsureAlloced ( 2 );
249
250    m_data->data[ 0 ] = ch;
251    m_data->data[ 1 ] = 0;
252    m_data->len = 1;
253    }
254
255 inline idStr::idStr
256    (
257    const float num
258    ) : m_data ( NULL )
259
260    {
261    char text[ 32 ];
262    int len;
263
264    sprintf( text, "%.3f", num );
265    len = strlen( text );
266    EnsureAlloced( len + 1 );
267    strcpy( m_data->data, text );
268    m_data->len = len;
269    }
270
271 inline idStr::idStr
272    (
273    const int num
274    ) : m_data ( NULL )
275
276    {
277    char text[ 32 ];
278    int len;
279
280    sprintf( text, "%d", num );
281    len = strlen( text );
282    EnsureAlloced( len + 1 );
283    strcpy( m_data->data, text );
284    m_data->len = len;
285    }
286
287 inline idStr::idStr
288    (
289    const unsigned num
290    ) : m_data ( NULL )
291
292    {
293    char text[ 32 ];
294    int len;
295
296    sprintf( text, "%u", num );
297    len = strlen( text );
298    EnsureAlloced( len + 1 );
299    strcpy( m_data->data, text );
300    m_data->len = len;
301    }
302
303 inline int idStr::length( void ) const
304         {
305    return ( m_data != NULL ) ? m_data->len : 0;
306         }
307
308 inline int idStr::allocated( void ) const
309         {
310    return ( m_data != NULL ) ? m_data->alloced + sizeof( *m_data ) : 0;
311         }
312
313 inline const char *idStr::c_str( void ) const
314         {
315         assert( m_data );
316
317         return m_data->data;
318         }
319
320 inline void idStr::append
321         (
322         const char *text
323         )
324
325         {
326    int len;
327
328         assert( text );
329
330         if ( text )
331                 {
332                 len = length() + strlen( text );
333                 EnsureAlloced( len + 1 );
334
335       strcat( m_data->data, text );
336       m_data->len = len;
337                 }
338         }
339
340 inline void idStr::append
341         (
342         const idStr& text
343         )
344
345         {
346    int len;
347
348    len = length() + text.length();
349    EnsureAlloced ( len + 1 );
350
351    strcat ( m_data->data, text.c_str () );
352    m_data->len = len;
353         }
354
355 inline char idStr::operator[]( int index ) const
356         {
357    assert ( m_data );
358    
359    if ( !m_data )
360       return 0;
361
362         // don't include the '/0' in the test, because technically, it's out of bounds
363         assert( ( index >= 0 ) && ( index < m_data->len ) );
364
365         // In release mode, give them a null character
366         // don't include the '/0' in the test, because technically, it's out of bounds
367         if ( ( index < 0 ) || ( index >= m_data->len ) )
368                 {
369                 return 0;
370                 }
371
372         return m_data->data[ index ];
373         }
374
375 inline char& idStr::operator[]
376         (
377         int index
378         )
379
380         {
381         // Used for result for invalid indices
382         static char dummy = 0;
383    assert ( m_data );
384
385    // We don't know if they'll write to it or not
386    // if it's not a const object
387    EnsureDataWritable ();
388
389    if ( !m_data )
390       return dummy;
391
392         // don't include the '/0' in the test, because technically, it's out of bounds
393         assert( ( index >= 0 ) && ( index < m_data->len ) );
394
395         // In release mode, let them change a safe variable
396         // don't include the '/0' in the test, because technically, it's out of bounds
397         if ( ( index < 0 ) || ( index >= m_data->len ) )
398                 {
399                 return dummy;
400                 }
401
402         return m_data->data[ index ];
403         }
404
405 inline void idStr::operator=
406         (
407         const idStr& text
408         )
409
410         {
411    // adding the reference before deleting our current reference prevents
412    // us from deleting our string if we are copying from ourself
413    text.m_data->AddRef();
414    m_data->DelRef();
415    m_data = text.m_data;
416    }
417
418 inline void idStr::operator=
419         (
420         const char *text
421         )
422
423         {
424    int len;
425
426         assert( text );
427
428         if ( !text )
429                 {
430                 // safe behaviour if NULL
431                 EnsureAlloced ( 1, false );
432       m_data->data[0] = 0;
433       m_data->len = 0;
434       return;
435                 }
436
437    if ( !m_data )
438       {
439       len = strlen ( text );
440       EnsureAlloced( len + 1, false );
441       strcpy ( m_data->data, text );
442       m_data->len = len;
443       return;
444       }
445
446    if ( text == m_data->data )
447       return; // Copying same thing.  Punt.
448
449    // If we alias and I don't do this, I could corrupt other strings...  This 
450    // will get called with EnsureAlloced anyway
451    EnsureDataWritable ();
452
453    // Now we need to check if we're aliasing..
454    if ( text >= m_data->data && text <= m_data->data + m_data->len )
455       {
456       // Great, we're aliasing.  We're copying from inside ourselves.
457       // This means that I don't have to ensure that anything is alloced,
458       // though I'll assert just in case.
459       int diff = text - m_data->data;
460       int i;
461
462       assert ( strlen ( text ) < (unsigned) m_data->len );
463       
464       for ( i = 0; text[i]; i++ )
465          {
466          m_data->data[i] = text[i];
467          }
468
469       m_data->data[i] = 0;
470
471       m_data->len -= diff;
472
473       return;
474       }
475
476         len = strlen( text );
477    EnsureAlloced ( len + 1, false );
478         strcpy( m_data->data, text );
479    m_data->len = len;
480         }
481
482 inline idStr operator+
483         (
484         const idStr& a,
485         const idStr& b
486         )
487
488         {
489         idStr result( a );
490
491         result.append( b );
492
493         return result;
494         }
495
496 inline idStr operator+
497         (
498         const idStr& a,
499         const char *b
500         )
501
502         {
503         idStr result( a );
504
505         result.append( b );
506
507         return result;
508         }
509
510 inline idStr operator+
511         (
512         const char *a,
513         const idStr& b
514         )
515
516         {
517         idStr result( a );
518
519         result.append( b );
520
521         return result;
522         }
523
524 inline idStr operator+
525    (
526    const idStr& a,
527    const bool b
528    )
529
530    {
531         idStr result( a );
532
533    result.append( b ? "true" : "false" );
534
535         return result;
536    }
537
538 inline idStr operator+
539         (
540    const idStr& a,
541         const char b
542         )
543
544         {
545    char text[ 2 ];
546
547    text[ 0 ] = b;
548    text[ 1 ] = 0;
549
550         return a + text;
551         }
552
553 inline idStr& idStr::operator+=
554         (
555         const idStr& a
556         )
557
558         {
559         append( a );
560         return *this;
561         }
562
563 inline idStr& idStr::operator+=
564         (
565         const char *a
566         )
567
568         {
569         append( a );
570         return *this;
571         }
572
573 inline idStr& idStr::operator+=
574         (
575         const char a
576         )
577
578         {
579    char text[ 2 ];
580
581    text[ 0 ] = a;
582    text[ 1 ] = 0;
583         append( text );
584
585    return *this;
586         }
587
588 inline idStr& idStr::operator+=
589         (
590         const bool a
591         )
592
593         {
594    append( a ? "true" : "false" );
595         return *this;
596         }
597
598 inline bool operator==
599         (
600         const idStr& a,
601         const idStr& b
602         )
603
604         {
605         return ( !strcmp( a.c_str(), b.c_str() ) );
606         }
607
608 inline bool operator==
609         (
610         const idStr& a,
611         const char *b
612         )
613
614         {
615         assert( b );
616         if ( !b )
617                 {
618                 return false;
619                 }
620         return ( !strcmp( a.c_str(), b ) );
621         }
622
623 inline bool operator==
624         (
625         const char *a,
626         const idStr& b
627         )
628
629         {
630         assert( a );
631         if ( !a )
632                 {
633                 return false;
634                 }
635         return ( !strcmp( a, b.c_str() ) );
636         }
637
638 inline bool operator!=
639         (
640         const idStr& a,
641         const idStr& b
642         )
643
644         {
645         return !( a == b );
646         }
647
648 inline bool operator!=
649         (
650         const idStr& a,
651         const char *b
652         )
653
654         {
655         return !( a == b );
656         }
657
658 inline bool operator!=
659         (
660         const char *a,
661         const idStr& b
662         )
663
664         {
665         return !( a == b );
666         }
667
668 inline int idStr::icmpn
669    (
670    const char *text, 
671    int n
672    ) const
673
674    {
675         assert( m_data );
676         assert( text );
677
678    return idStr::icmpn( m_data->data, text, n );
679    }
680
681 inline int idStr::icmpn
682    (
683    const idStr& text, 
684    int n
685    ) const
686
687    {
688         assert( m_data );
689         assert( text.m_data );
690
691    return idStr::icmpn( m_data->data, text.m_data->data, n );
692    }
693
694 inline int idStr::icmp
695    (
696    const char *text
697    ) const
698
699    {
700         assert( m_data );
701         assert( text );
702
703    return idStr::icmp( m_data->data, text );
704    }
705
706 inline int idStr::icmp
707    (
708    const idStr& text
709    ) const
710
711    {
712         assert( c_str () );
713         assert( text.c_str () );
714
715    return idStr::icmp( c_str () , text.c_str () );
716    }
717
718 inline int idStr::cmp
719    (
720    const char *text
721    ) const
722
723    {
724         assert( m_data );
725         assert( text );
726
727    return idStr::cmp( m_data->data, text );
728    }
729
730 inline int idStr::cmp
731    (
732    const idStr& text
733    ) const
734
735    {
736         assert( c_str () );
737         assert( text.c_str () );
738
739    return idStr::cmp( c_str () , text.c_str () );
740    }
741
742 inline int idStr::cmpn
743    (
744    const char *text, 
745    int n
746    ) const
747
748    {
749         assert( c_str () );
750         assert( text );
751
752    return idStr::cmpn( c_str () , text, n );
753    }
754
755 inline int idStr::cmpn
756    (
757    const idStr& text, 
758    int n
759    ) const
760
761    {
762         assert( c_str () );
763         assert( text.c_str ()  );
764
765    return idStr::cmpn( c_str () , text.c_str () , n );
766    }
767
768 inline void idStr::tolower
769    (
770    void
771    )
772
773    {
774    assert( m_data );
775
776    EnsureDataWritable ();
777
778    idStr::tolower( m_data->data );
779    }
780
781 inline void idStr::toupper
782    (
783    void
784    )
785
786    {
787    assert( m_data );
788
789    EnsureDataWritable ();
790
791    idStr::toupper( m_data->data );
792    }
793
794 inline bool idStr::isNumeric
795    (
796    void
797    ) const
798
799    {
800    assert( m_data );
801    return idStr::isNumeric( m_data->data );
802    }
803
804 inline idStr::operator const char *() {
805         return c_str();
806 }
807
808 inline idStr::operator const char *
809    (
810    void
811    ) const
812
813    {
814    return c_str ();
815    }
816
817 #endif