string.hh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  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. // String Classes
  9. //
  10. // Strings are hidden behind the two classes :
  11. //
  12. // i4_const_str (constant strings.. cannot be changed)
  13. // and i4_str (modifiable strings)
  14. //
  15. //
  16. // i4_strs can only be created from i4_const_strs or other i4_strs and i4_const_strs can
  17. // only be created through the i4_string_manager. All strings gotten from i4_string_manager
  18. // are loaded from an external file. This ensures that all strings are stored external and
  19. // UNICODE or wide-chars can be added in without any code changes outside this module.
  20. // Because for most applications only one string manager is needed I have created a global
  21. // one called i4_string_man.
  22. //
  23. // To see if a string is available from the string manager the call
  24. //
  25. // const i4_const_str *s=&i4_string_man.get(str);
  26. //
  27. // is made. If s->null()==i4_T then the string was not loaded.
  28. // Since this is a common operation the short-named function i4gets is provided
  29. // (see end of this file).
  30. //
  31. //
  32. // example :
  33. //
  34. // resource.res
  35. // ---------------
  36. // hello "Hello World"
  37. //
  38. // ---------------
  39. //
  40. //
  41. // i4gets("hello") -> i4_const_str("Hello World")
  42. //
  43. //
  44. // So, you might ask, how do I create a string quick and dirty for debugging purposes?
  45. //
  46. // You have to do it the hard way for now.......
  47. #ifndef __STRING_HPP_
  48. #define __STRING_HPP_
  49. #include "arch.hh"
  50. #include "init/init.hh"
  51. #include "error/error.hh"
  52. #include "memory/malloc.hh"
  53. #include <stdlib.h>
  54. #include <string.h>
  55. class i4_char
  56. {
  57. protected:
  58. w8 ch;
  59. public:
  60. i4_char(w8 ch) : ch(ch) {}
  61. w16 value() const { return ch; }
  62. i4_bool is_space() const { return (i4_bool)(ch==' ' || ch=='\r' || ch=='\n' || ch=='\t'); }
  63. i4_bool is_slash() const { return (i4_bool)(ch=='/'); }
  64. i4_bool is_backslash() const { return (i4_bool)(ch=='\\'); }
  65. i4_bool is_period() const { return (i4_bool)(ch=='.'); }
  66. i4_char to_lower() const
  67. { return (ch>='A' && ch<='Z') ? i4_char(ch-'A'+'a') : i4_char(ch); }
  68. i4_char to_upper() const
  69. { return (ch>='a' && ch<='z') ? i4_char(ch-'a'+'A') : i4_char(ch); }
  70. i4_bool operator==(const i4_char &b) const { return (ch == b.ch); }
  71. i4_bool operator!=(const i4_char &b) const { return (ch != b.ch); }
  72. i4_bool operator>(const i4_char &b) const { return (ch > b.ch); }
  73. i4_bool operator<(const i4_char &b) const { return (ch < b.ch); }
  74. i4_bool operator>=(const i4_char &b) const { return (ch >= b.ch); }
  75. i4_bool operator<=(const i4_char &b) const { return (ch <= b.ch); }
  76. // this should only be called if you know the string you are looking at has ascii chars in it
  77. w8 ascii_value() const { return ch; }
  78. };
  79. class i4_str;
  80. class i4_string_manager_class;
  81. class i4_file_class;
  82. class i4_const_str
  83. {
  84. protected:
  85. typedef char char_type;
  86. char_type *ptr;
  87. w16 len;
  88. i4_const_str() : ptr(0), len(0) {}
  89. friend class i4_string_manager_class;
  90. public:
  91. i4_const_str(const char *ptr) : ptr((char *)ptr)
  92. {
  93. if (ptr)
  94. len=strlen(ptr);
  95. else
  96. len=0;
  97. }
  98. i4_const_str(char *ptr, w16 len) : ptr(ptr), len(len) {}
  99. i4_const_str(const i4_const_str &str) : ptr(str.ptr), len(str.len) {}
  100. class iterator
  101. {
  102. friend class i4_const_str;
  103. friend class i4_str;
  104. protected:
  105. char_type *node;
  106. public:
  107. iterator() : node(0) {}
  108. iterator(const iterator &p) : node(p.node) {}
  109. iterator(char_type *p) : node(p) {}
  110. int operator==(const iterator &p) const { return (node == p.node); }
  111. int operator!=(const iterator &p) const { return (node != p.node); }
  112. iterator& operator++() { node++; return *this; }
  113. iterator& operator++(int) { node++; return *this; }
  114. iterator& operator--() { node--; return *this; }
  115. iterator operator+(const sw32 other) { return iterator(node+other); }
  116. iterator operator+=(const sw32 len) { node+=len; return *this;}
  117. i4_char get() const { return i4_char(*node); }
  118. i4_char operator* () const { return get(); }
  119. i4_str *read_string();
  120. w32 read_ascii(char *buffer, w32 buffer_size); // returns bytes read
  121. sw32 read_number();
  122. double read_float();
  123. };
  124. const iterator end() const { return ptr+len; }
  125. const iterator begin() const { return ptr; }
  126. // number of characters in string
  127. w32 length() const { return len; }
  128. // ascii length includes null-terminator and be eventaully be longer than length()+1
  129. // when kanji support is added and escape characters are used
  130. w32 ascii_length() const { return len+1; }
  131. sw32 ptr_diff(const iterator first, const iterator last) const
  132. { return last.node-first.node; }
  133. i4_bool operator== (const i4_const_str &other) const
  134. {
  135. if (len!=other.len)
  136. return 0;
  137. else return ::strncmp(other.ptr,ptr,len)==0;
  138. }
  139. i4_bool operator!= (const i4_const_str &other) const { return !(other==*this); }
  140. int strncmp(const i4_const_str &other, w32 max_cmp) const
  141. {
  142. return ::strncmp(ptr,other.ptr,max_cmp);
  143. }
  144. i4_bool null() const { return (i4_bool)(ptr==0); }
  145. // max_length is the maximum expanded length sprintf will create
  146. // sprintf uses it's own internal string as the format, and returns the
  147. // result of the sprintf operation as a new i4_str
  148. // example : i4_str *new_str=i4gets("format_str").sprintf(100,some_number);
  149. i4_str *sprintf(w32 max_length, ...) const;
  150. i4_str *vsprintf(w32 max_length, va_list &ap) const;
  151. iterator strstr(const i4_const_str &needle_to_find) const;
  152. };
  153. class i4_str : public i4_const_str
  154. {
  155. friend i4_str *i4_from_ascii(const char *buf);
  156. protected:
  157. w16 buf_len;
  158. i4_str(w16 _buf_len) { alloc(_buf_len); }
  159. void alloc(w16 _buf_len);
  160. void init_from_string(const i4_const_str &str, w16 _buf_len);
  161. public:
  162. class iterator : public i4_const_str::iterator
  163. {
  164. protected:
  165. public:
  166. iterator(const iterator &p) : i4_const_str::iterator(p) {}
  167. iterator(char_type *p) : i4_const_str::iterator((char_type *)p) {}
  168. void set(i4_char ch) { *((char *)node)=(char_type)ch.value(); }
  169. };
  170. i4_str(const i4_str &str) : i4_const_str(0) { init_from_string(str, (w16)str.length()); }
  171. i4_str(const i4_const_str &str) : i4_const_str(0) { init_from_string(str, (w16)str.length()); }
  172. i4_str(const i4_const_str &str, w16 _len) : i4_const_str(0) { init_from_string(str, _len); }
  173. // copies from start to end-1 characters (does not include end)
  174. i4_str(const i4_const_str::iterator start, const i4_const_str::iterator end, w16 buf_len);
  175. void insert(i4_str::iterator p, const i4_const_str &other); // insert other before p
  176. void insert(i4_str::iterator p, const i4_char ch); // insert ch before p
  177. void remove(i4_str::iterator start, i4_str::iterator last);
  178. void to_upper(); // converts all the chars in this string to upper case
  179. void to_lower(); // converts all the chars in this string to lower case
  180. const iterator end() const { return ptr+len; }
  181. const iterator begin() const { return ptr; }
  182. void set_length(int l) { len=l; }
  183. ~i4_str();
  184. };
  185. class i4_linear_allocator;
  186. class i4_grow_heap_class;
  187. class i4_string_manager_class : public i4_init_class
  188. {
  189. private:
  190. i4_grow_heap_class *string_heap;
  191. char *alloc_str(char *string);
  192. void add_node(char *token, char *string);
  193. void add_array_node(char *token, char **array, w32 total);
  194. friend class i4_string_manager_saver_class;
  195. class node
  196. {
  197. public:
  198. typedef i4_linear_allocator node_allocator;
  199. static node_allocator *nodes;
  200. static w32 nodes_ref; // number of string managers using 'nodes'
  201. char *str_token;
  202. i4_const_str value;
  203. node *left,*right;
  204. #ifndef i4_NEW_CHECK
  205. void *operator new(size_t size);
  206. void operator delete(void *ptr);
  207. #endif
  208. node(char *token, const i4_const_str &value) : str_token(token), value(value)
  209. {
  210. left=0;
  211. right=0;
  212. }
  213. ~node();
  214. };
  215. node *root;
  216. #ifdef __MAC__
  217. node *new_node(char *token, const i4_const_str &value)
  218. {
  219. node *p = (node *)node::nodes->alloc();
  220. p->str_token = token;
  221. p->value = value;
  222. p->left = 0;
  223. p->right = 0;
  224. return p;
  225. }
  226. void delete_node(node *n)
  227. {
  228. if (n->left)
  229. delete_node(n->left);
  230. if (n->right)
  231. delete_node(n->right);
  232. node::nodes->free(n);
  233. }
  234. #else
  235. node *new_node(char *token, const i4_const_str &value) { return new node(token,value); }
  236. void delete_node(node *n) { delete n; }
  237. #endif
  238. class array_node
  239. {
  240. public:
  241. typedef i4_linear_allocator node_allocator;
  242. static node_allocator *nodes;
  243. char *str_token;
  244. char **value;
  245. array_node *left,*right;
  246. #ifndef i4_NEW_CHECK
  247. void *operator new(size_t size);
  248. void operator delete(void *ptr);
  249. #endif
  250. array_node(char *token, char **value) : str_token(token),value(value)
  251. {
  252. left=0;
  253. right=0;
  254. }
  255. ~array_node();
  256. } *array_root;
  257. #ifdef __MAC__
  258. array_node *new_array_node(char *token, char **value)
  259. {
  260. array_node *p = (array_node *)array_node::nodes->alloc();
  261. p->str_token = token;
  262. p->value = value;
  263. p->left = 0;
  264. p->right = 0;
  265. return p;
  266. }
  267. void delete_array_node(array_node *n)
  268. {
  269. if (n->left)
  270. delete_array_node(n->left);
  271. if (n->right)
  272. delete_array_node(n->right);
  273. array_node::nodes->free(n);
  274. }
  275. #else
  276. array_node *new_array_node(char *token, char **value)
  277. {
  278. return new array_node(token,value);
  279. }
  280. void delete_array_node(array_node *n) { delete n; }
  281. #endif
  282. void get_token(char *&s, char *&buf, w32 &line_on, char *error_prefix);
  283. void expand_macro(char *&s, char *&buf, w32 &line_on, char *error_prefix);
  284. void read_array(char *&s,
  285. char **array,
  286. w32 &total,
  287. w32 &line_on,
  288. char *error_prefix,
  289. char *token_buf);
  290. void get_char(char *&s, char *&buf, w32 &line_on, char *error_prefix);
  291. void show_node(node *who);
  292. void show_nodes();
  293. public:
  294. i4_string_manager_class();
  295. ~i4_string_manager_class();
  296. int init_type() { return I4_INIT_TYPE_STRING_MANAGER; }
  297. void init();
  298. void uninit();
  299. i4_bool load(char *filename);
  300. i4_bool load(const i4_const_str &filename);
  301. i4_bool load_buffer(void *internal_buffer, char *error_prefix);
  302. const i4_const_str &get(const char *internal_name);
  303. const i4_const_str &get(const i4_const_str &internal_name);
  304. i4_const_str *get_array(const char *internal_name);
  305. i4_const_str *get_array(const i4_const_str &internal_name);
  306. };
  307. // "the" main string manager for a program
  308. extern i4_string_manager_class i4_string_man;
  309. const i4_const_str &i4gets(char *str, i4_bool barf_on_error=i4_T);
  310. int i4getn(char *str, i4_bool barf_on_error=i4_T);
  311. // converts an i4_const_str to an 8 bit ascii string (where possible)
  312. extern char *i4_os_string(const i4_const_str &name, char *buffer, int buflen);
  313. // converts from an ascii string to an i4_str
  314. extern i4_str *i4_from_ascii(const char *buf);
  315. #endif