home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / graphtal / rcstring.c < prev    next >
C/C++ Source or Header  |  1992-10-26  |  5KB  |  254 lines

  1. /*
  2.  * rcString.C - reference counted string class.
  3.  *
  4.  * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
  5.  *                     Igor Metz (metz@iam.unibe.ch)
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified, and redistributed
  9.  * provided that this copyright notice is preserved on all copies.
  10.  *
  11.  * You may not distribute this software, in whole or in part, as part of
  12.  * any commercial product without the express consent of the authors.
  13.  *
  14.  * There is no warranty or other guarantee of fitness of this software
  15.  * for any purpose.  It is provided solely "as is".
  16.  *
  17.  */
  18.  
  19. #include <iostream.h>
  20. #include "rcString.h"
  21. #include "Error.h"
  22.  
  23. //___________________________________________________________ rcStringRep
  24. //
  25. // reference counted rcString representation
  26.  
  27. class rcStringRep 
  28. {
  29.   friend class rcString;
  30.  
  31. public:
  32.   rcStringRep(char);
  33.   rcStringRep(const char*);
  34.   ~rcStringRep();
  35.   
  36. private:
  37.   char* str;
  38.   int len;
  39.   int count;
  40.  
  41. private:
  42.   rcStringRep(_Char_p_*);
  43.   void ref();
  44.   void deref();
  45. };
  46.  
  47. inline rcStringRep::rcStringRep(char c) {
  48.   str = new char[2]; str[0] = c; str[1] = '\0'; 
  49.   count = len = 1;
  50. }
  51.  
  52. inline rcStringRep::rcStringRep(const char* s) {
  53.   len = strlen(s);
  54.   str = new char[len+1];
  55.   strcpy(str, s);
  56.   count = 1;
  57. }
  58.  
  59. inline rcStringRep::~rcStringRep() {
  60.   delete [] str; 
  61. }
  62.  
  63. inline rcStringRep::rcStringRep(_Char_p_* r) { 
  64.   str = *r; count = 1; len = strlen(str); 
  65. }
  66.  
  67. inline void rcStringRep::ref() {
  68.   count++;
  69. }
  70.  
  71. inline void rcStringRep::deref() {
  72.   if (--count <= 0) delete this;
  73. }
  74.  
  75. //___________________________________________________________ rcString
  76.  
  77. // constructors and destructors
  78.  
  79. rcString::rcString() {
  80.   rep = new rcStringRep(""); 
  81. }
  82.  
  83. rcString::rcString(char c) {
  84.   rep = new rcStringRep(c); 
  85. }
  86.  
  87. rcString::rcString(const char* s) { 
  88.   rep = new rcStringRep(s); 
  89. }
  90.  
  91. rcString::rcString(const rcString &s) { 
  92.   s.rep->ref(); rep = s.rep; 
  93. }
  94.  
  95. rcString::rcString(_Char_p_* r) { 
  96.   rep = new rcStringRep(r); 
  97. }
  98.  
  99. rcString::~rcString() { 
  100.   rep->deref(); 
  101. }
  102.  
  103. // status reports
  104.  
  105. unsigned rcString::length() const {
  106.   return rep->len; 
  107. }
  108.  
  109. int rcString::empty() const { 
  110.   return rep->len == 0; 
  111. }
  112.  
  113. const char* rcString::chars() const {
  114.   return rep->str; 
  115. }
  116.  
  117. rcString::operator const char*() const {
  118.   return rep->str; 
  119. }
  120.  
  121. // element extraction and substring
  122.  
  123. char& rcString::operator[](unsigned i)
  124. {
  125.   if (i>=length())
  126.     Error(ERR_PANIC, "rcString::operator[] index out of range");
  127.   /*
  128.    * Copy on write!
  129.    */
  130.   if (rep->count > 1) {
  131.     rep->deref();
  132.     rep = new rcStringRep(rep->str);
  133.   }
  134.  
  135.   return rep->str[i];
  136. }
  137.  
  138. char rcString::operator[](unsigned i) const
  139. {
  140.   if (i>=length())
  141.     Error(ERR_PANIC, "rcString::operator[] index out of range");
  142.  
  143.   return rep->str[i];
  144. }
  145.  
  146. rcString rcString::operator()(unsigned i, unsigned j)
  147. {
  148.   if (j<i || i>=length() || j>=length())
  149.     Error(ERR_PANIC, "rcString::operator() index out of range");
  150.  
  151.   char* buf = new char[j-i+1];
  152.   strncpy(buf, rep->str+i, j-i);
  153.   buf[j-i] = '\0';
  154.  
  155.   return rcString(&buf);
  156. }
  157.  
  158. // assignment
  159.  
  160. const rcString& rcString::operator=(char c)
  161. {
  162.   rep->deref();
  163.   rep = new rcStringRep(c);
  164.  
  165.   return *this;
  166. }
  167.  
  168. const rcString& rcString::operator=(const char* s)
  169. {
  170.   rep->deref();
  171.   rep = new rcStringRep(s);
  172.  
  173.   return *this;
  174. }
  175.  
  176. const rcString& rcString::operator=(const rcString& s)
  177. {
  178.   s.rep->ref();
  179.   rep->deref();
  180.   rep = s.rep;
  181.  
  182.   return *this;
  183. }
  184.  
  185. // comparison operators
  186.  
  187. int rcString::operator==(const rcString& s) const { 
  188.   return (strcmp(rep->str, s.rep->str) == 0); 
  189. }
  190.  
  191. int rcString::operator==(const char* s) const { 
  192.   return (strcmp(rep->str, s) == 0); 
  193. }
  194.  
  195. int rcString::operator!=(const rcString& s) const { 
  196.   return (strcmp(rep->str, s.rep->str) != 0); 
  197. }
  198.  
  199. int rcString::operator!=(const char* s) const { 
  200.   return (strcmp(rep->str, s) != 0); 
  201. }
  202.  
  203. int rcString::operator<(const rcString& s) const { 
  204.   return (strcmp(rep->str, s.rep->str) < 0); 
  205. }
  206.  
  207. int rcString::operator<=(const rcString& s) const { 
  208.   return (strcmp(rep->str, s.rep->str) <= 0); 
  209. }
  210.  
  211. int rcString::operator>(const rcString& s) const { 
  212.   return (strcmp(rep->str, s.rep->str) > 0); 
  213. }
  214.  
  215. int rcString::operator>=(const rcString& s) const { 
  216.   return (strcmp(rep->str, s.rep->str) >= 0); 
  217. }
  218.  
  219. // concatenation
  220.  
  221. rcString operator+(const rcString& x, const char* y)
  222. {
  223.   char* buf = new char[x.length() + strlen(y) + 1];
  224.   strcpy(buf, x.chars());
  225.   strcat(buf, y);
  226.  
  227.   return rcString(&buf); // call the private constructor
  228. }  
  229.  
  230. rcString operator+(const char* x, const rcString& y)
  231. {
  232.   char* buf = new char[strlen(x) + y.length() + 1];
  233.   strcpy(buf, x);
  234.   strcat(buf, y.chars());
  235.  
  236.   return rcString(&buf); // call the private constructor
  237. }  
  238.  
  239. rcString operator+(const rcString& x, const rcString& y)
  240. {
  241.   char* buf = new char[x.length() + y.length() + 1];
  242.   strcpy(buf, x.chars());
  243.   strcat(buf, y.chars());
  244.  
  245.   return rcString(&buf); // call the private constructor
  246. }  
  247.   
  248. // stream operators
  249.  
  250. ostream& operator<<(ostream& os, const rcString& s)
  251.   return os << s.chars();
  252. }
  253.