source: golgotha/src/i4/string/string.hh @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 12 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 11.5 KB
RevLine 
[80]1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9// String Classes
10//
11//   Strings are hidden behind the two classes :
12//
13//       i4_const_str   (constant strings.. cannot be changed)
14//   and i4_str         (modifiable strings)
15//
16//
17//   i4_strs can only be created from i4_const_strs or other i4_strs and i4_const_strs can
18//   only be created through the i4_string_manager.  All strings gotten from i4_string_manager
19//   are loaded from an external file.  This ensures that all strings are stored external and
20//   UNICODE or wide-chars can be added in without any code changes outside this module.
21//   Because for most applications only one string manager is needed I have created a global
22//   one called i4_string_man. 
23//
24//   To see if a string is available from the string manager the call
25//
26//   const i4_const_str *s=&i4_string_man.get(str);
27//
28//   is made.  If s->null()==i4_T then the string was not loaded.
29//   Since this is a common operation the short-named function i4gets is provided
30//   (see end of this file).
31//
32//
33//   example :
34//
35//   resource.res
36//   ---------------
37//   hello "Hello World"
38//
39//   ---------------
40//
41//
42//   i4gets("hello") ->  i4_const_str("Hello World")
43//
44//
45//   So, you might ask, how do I create a string quick and dirty for debugging purposes?
46//
47//   You have to do it the hard way for now.......
48
49#ifndef __STRING_HPP_
50#define __STRING_HPP_
51
52#include "arch.hh"
53#include "init/init.hh"
54#include "error/error.hh"
55#include "memory/malloc.hh"
56
57#include <stdlib.h>
58#include <string.h>
59
60class i4_char
61{
62protected:
63  w8 ch;
64public:
65  i4_char(w8 ch) : ch(ch) {}
66  w16 value() const { return ch; }
67  i4_bool is_space() const { return (i4_bool)(ch==' ' || ch=='\r' || ch=='\n' || ch=='\t'); }
68  i4_bool is_slash() const { return (i4_bool)(ch=='/'); }
69  i4_bool is_backslash() const { return (i4_bool)(ch=='\\'); }
70  i4_bool is_period() const { return (i4_bool)(ch=='.'); }
71
72  i4_char to_lower() const
73  { return (ch>='A' && ch<='Z') ? i4_char(ch-'A'+'a') : i4_char(ch); }
74
75  i4_char to_upper() const
76  { return (ch>='a' && ch<='z') ? i4_char(ch-'a'+'A') : i4_char(ch); }
77
78  i4_bool operator==(const i4_char &b) const { return (ch == b.ch); }
79  i4_bool operator!=(const i4_char &b) const { return (ch != b.ch); }
80  i4_bool operator>(const i4_char &b) const { return  (ch > b.ch); }
81  i4_bool operator<(const i4_char &b) const { return  (ch < b.ch); }
82  i4_bool operator>=(const i4_char &b) const { return (ch >= b.ch); }
83  i4_bool operator<=(const i4_char &b) const { return (ch <= b.ch); }
84
85  // this should only be called if you know the string you are looking at has ascii chars in it
86  w8 ascii_value() const { return ch; }
87};
88
89
90class i4_str;
91class i4_string_manager_class;
92class i4_file_class;
93
94
95class i4_const_str
96{
97protected:
98  typedef char char_type;
99
100  char_type *ptr;
101  w16   len;
102
103  i4_const_str() : ptr(0), len(0) {}
104
105  friend class i4_string_manager_class;
106
107public:
108  i4_const_str(const char *ptr) : ptr((char *)ptr)
109  {
110    if (ptr)
111      len=strlen(ptr);
112    else
113      len=0;
114  }
115
116  i4_const_str(char *ptr, w16 len) : ptr(ptr), len(len) {}
117
118  i4_const_str(const i4_const_str &str) : ptr(str.ptr), len(str.len) {}
119
120
121  class iterator
122  {
123    friend class i4_const_str;
124    friend class i4_str;
125  protected:
126    char_type *node;
127
128  public:
129    iterator() : node(0) {}
130    iterator(const iterator &p) : node(p.node) {}
131    iterator(char_type *p) : node(p) {}
132
133    int operator==(const iterator &p) const { return (node == p.node); }
134    int operator!=(const iterator &p) const { return (node != p.node); }
135   
136    iterator& operator++() {     node++;  return *this; }
137    iterator& operator++(int) { node++; return *this; }
138    iterator& operator--()  {     node--;  return *this; }
139    iterator operator+(const sw32 other)    {  return iterator(node+other); }
140    iterator operator+=(const sw32 len) {   node+=len;   return *this;}
141
142   
143    i4_char get() const { return i4_char(*node); }
144
145    i4_char operator* () const { return get(); }
146    i4_str *read_string();
147    w32     read_ascii(char *buffer, w32 buffer_size);  // returns bytes read
148    sw32    read_number();
149    double  read_float();
150  };
151 
152
153  const iterator end()   const { return ptr+len; }
154  const iterator begin() const { return ptr; }
155
156  // number of characters in string
157  w32 length() const { return len; }
158
159  // ascii length includes null-terminator and be eventaully be longer than length()+1
160  // when kanji support is added and escape characters are used
161  w32 ascii_length() const { return len+1; }
162
163  sw32 ptr_diff(const iterator first, const iterator last) const
164  { return last.node-first.node; }
165
166  i4_bool operator== (const i4_const_str &other) const
167  {
168    if (len!=other.len)
169      return 0;
170    else return ::strncmp(other.ptr,ptr,len)==0;
171  }
172
173  i4_bool operator!= (const i4_const_str &other) const { return !(other==*this); }
174  int strncmp(const i4_const_str &other, w32 max_cmp) const
175  {
176    return ::strncmp(ptr,other.ptr,max_cmp);
177  }
178 
179  i4_bool null() const { return (i4_bool)(ptr==0); }
180
181  // max_length is the maximum expanded length sprintf will create
182  // sprintf uses it's own internal string as the format, and returns the
183  // result of the sprintf operation as a new i4_str
184  // example : i4_str *new_str=i4gets("format_str").sprintf(100,some_number);
185  i4_str *sprintf(w32 max_length, ...) const;
186  i4_str *vsprintf(w32 max_length, va_list &ap) const;
187
188  iterator strstr(const i4_const_str &needle_to_find) const;
189};
190
191
192class i4_str : public i4_const_str
193{
194  friend i4_str *i4_from_ascii(const char *buf);
195protected:
196  w16 buf_len;
197
198  i4_str(w16 _buf_len) { alloc(_buf_len); }
199
200  void alloc(w16 _buf_len); 
201  void init_from_string(const i4_const_str &str, w16 _buf_len);
202
203public:
204  class iterator : public i4_const_str::iterator
205  {
206  protected:
207  public:
208    iterator(const iterator &p) : i4_const_str::iterator(p) {}
209    iterator(char_type *p) : i4_const_str::iterator((char_type *)p) {}
210    void set(i4_char ch) { *((char *)node)=(char_type)ch.value(); }
211
212  };
213 
214  i4_str(const i4_str &str) : i4_const_str(0) { init_from_string(str, (w16)str.length()); }
215  i4_str(const i4_const_str &str) : i4_const_str(0) { init_from_string(str, (w16)str.length()); }
216  i4_str(const i4_const_str &str, w16 _len) : i4_const_str(0) { init_from_string(str, _len); }
217
218  // copies from start to end-1 characters (does not include end)
219  i4_str(const i4_const_str::iterator start, const i4_const_str::iterator end, w16 buf_len);
220 
221  void insert(i4_str::iterator p, const i4_const_str &other);   // insert other before p
222  void insert(i4_str::iterator p, const i4_char ch);            // insert ch before p
223
224  void remove(i4_str::iterator start, i4_str::iterator last);
225
226  void to_upper();   // converts all the chars in this string to upper case
227  void to_lower();   // converts all the chars in this string to lower case
228
229  const iterator end()   const { return ptr+len; }
230  const iterator begin() const { return ptr; }
231
232  void set_length(int l) { len=l; }
233
234  ~i4_str();
235};
236
237
238class i4_linear_allocator;
239class i4_grow_heap_class;
240class i4_string_manager_class : public i4_init_class
241
242
243private:
244  i4_grow_heap_class *string_heap;
245
246  char  *alloc_str(char *string);
247  void add_node(char *token, char *string);
248  void add_array_node(char *token, char **array, w32 total);
249
250  friend class i4_string_manager_saver_class;
251
252  class node
253  {
254  public:
255    typedef i4_linear_allocator node_allocator;
256    static node_allocator *nodes;
257    static w32 nodes_ref;           // number of string managers using 'nodes'
258
259    char *str_token;
260    i4_const_str value;
261    node *left,*right;
262
263#ifndef i4_NEW_CHECK
264    void *operator new(size_t size);
265    void operator delete(void *ptr);
266#endif
267
268    node(char *token, const i4_const_str &value) : str_token(token), value(value)
269    {
270      left=0;
271      right=0;
272    }
273   
274    ~node();
275  };
276  node *root;
277
278#ifdef __MAC__
279  node *new_node(char *token, const i4_const_str &value)
280  {
281    node *p = (node *)node::nodes->alloc();
282    p->str_token = token;
283    p->value = value;
284    p->left = 0;
285    p->right = 0;
286
287    return p;
288  }
289 
290  void delete_node(node *n)
291  {
292    if (n->left)
293      delete_node(n->left);
294
295    if (n->right)
296      delete_node(n->right);
297
298    node::nodes->free(n);
299  }
300#else
301  node *new_node(char *token, const i4_const_str &value) { return new node(token,value); }
302  void delete_node(node *n) { delete n; }
303#endif
304
305  class array_node
306  {
307  public:
308    typedef i4_linear_allocator node_allocator;
309    static node_allocator *nodes;
310
311    char *str_token;
312    char **value;
313    array_node *left,*right;
314
315
316
317#ifndef i4_NEW_CHECK
318    void *operator new(size_t size);
319    void operator delete(void *ptr);
320#endif
321
322    array_node(char *token, char **value) : str_token(token),value(value)
323    {
324      left=0;
325      right=0;
326    }
327
328    ~array_node();
329  } *array_root;
330 
331#ifdef __MAC__
332  array_node *new_array_node(char *token, char **value)
333  {
334    array_node *p = (array_node *)array_node::nodes->alloc();
335    p->str_token = token;
336    p->value = value;
337    p->left = 0;
338    p->right = 0;
339
340    return p;
341  }
342 
343  void delete_array_node(array_node *n)
344  {
345    if (n->left)
346      delete_array_node(n->left);
347
348    if (n->right)
349      delete_array_node(n->right);
350
351    array_node::nodes->free(n);
352  }
353#else
354  array_node *new_array_node(char *token, char **value)
355  {
356    return new array_node(token,value);
357  }
358  void delete_array_node(array_node *n) { delete n; }
359#endif
360
361  void get_token(char *&s, char *&buf, w32 &line_on, char *error_prefix);
362  void expand_macro(char *&s, char *&buf, w32 &line_on, char *error_prefix);
363  void read_array(char *&s,
364                  char **array,
365                  w32 &total,
366                  w32 &line_on,
367                  char *error_prefix,
368                  char *token_buf);
369
370  void get_char(char *&s, char *&buf, w32 &line_on, char *error_prefix);
371
372  void show_node(node *who);
373  void show_nodes();
374
375public:
376  i4_string_manager_class();
377  ~i4_string_manager_class();
378 
379  int init_type() { return I4_INIT_TYPE_STRING_MANAGER; }
380  void init();
381  void uninit();
382
383  i4_bool       load(char *filename);
384  i4_bool       load(const i4_const_str &filename);
385  i4_bool       load_buffer(void *internal_buffer, char *error_prefix);
386
387  const i4_const_str &get(const char *internal_name);
388  const i4_const_str &get(const i4_const_str &internal_name);
389
390  i4_const_str *get_array(const char *internal_name);
391  i4_const_str *get_array(const i4_const_str &internal_name);
392};
393
394// "the" main string manager for a program
395extern i4_string_manager_class i4_string_man;
396
397const i4_const_str &i4gets(char *str, i4_bool barf_on_error=i4_T);
398int i4getn(char *str, i4_bool barf_on_error=i4_T);
399
400// converts an i4_const_str to an 8 bit ascii string (where possible)
401extern char *i4_os_string(const i4_const_str &name, char *buffer, int buflen);
402
403// converts from an ascii string to an i4_str
404extern i4_str *i4_from_ascii(const char *buf);
405
406#endif
407
Note: See TracBrowser for help on using the repository browser.