home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume33 / problem1.1 / part04 / classes.C next >
Encoding:
C/C++ Source or Header  |  1992-11-13  |  7.4 KB  |  320 lines

  1. /*
  2. ** classes.C - contains definitions of the member functions which
  3. **             aren\'t defined in the relevant class declarations.
  4. **
  5. ** classes.C classes.C 1.11   Delta\'d: 12:59:54 10/31/92   Mike Lijewski, CNSF
  6. **
  7. ** Copyright \(c\) 1991, 1992 Cornell University
  8. ** All rights reserved.
  9. **
  10. ** Redistribution and use in source and binary forms are permitted
  11. ** provided that: \(1\) source distributions retain this entire copyright
  12. ** notice and comment, and \(2\) distributions including binaries display
  13. ** the following acknowledgement:  ``This product includes software
  14. ** developed by Cornell University\'\' in the documentation or other
  15. ** materials provided with the distribution and in all advertising
  16. ** materials mentioning features or use of this software. Neither the
  17. ** name of the University nor the names of its contributors may be used
  18. ** to endorse or promote products derived from this software without
  19. ** specific prior written permission.
  20. **
  21. ** THIS SOFTWARE IS PROVIDED ``AS IS\'\' AND WITHOUT ANY EXPRESS OR
  22. ** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  23. ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  24. */
  25.  
  26. #include <new.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29.  
  30. #include "classes.h"
  31. #include "utilities.h"
  32.  
  33. typedef void (*PEHF)();
  34.  
  35. StringRep::StringRep()
  36. {
  37.     rep = ::new char[1];
  38.     len = 0;
  39.     *rep = '\0';
  40.     count = 1;
  41. }
  42.  
  43. StringRep::StringRep(const char *s)
  44. {
  45.     len = ::strlen(s);
  46.     rep = ::new char[len + 1];
  47.     ::strcpy(rep, s);
  48.     count = 1;
  49. }
  50.  
  51. StringRep::StringRep(const char *s, int slen)
  52. {
  53.     rep = ::new char[slen + 1];
  54.     ::strncpy(rep, s, slen);
  55.     rep[slen] = 0;  // force stringification
  56.     len = ::strlen(s);
  57.     count = 1;
  58. }
  59.  
  60. String StringRep::operator+(const String& s) const
  61. {
  62.     size_t slen  = s.length() + length();
  63.     char *buf    = ::new char[slen + 1];
  64.     ::strcpy(buf, rep);
  65.     ::strcat(buf, s.p->rep);
  66.     return String(&buf, slen);
  67. }
  68.  
  69. /*
  70. ** The definition of the head of the freelist that StringRep::operator new\(\)
  71. ** uses to dole out StringReps efficiently.
  72. */
  73.  
  74. StringRep *StringRep::freeList;
  75.  
  76. void* StringRep::operator new(size_t size)
  77. {
  78.     if (size != sizeof(StringRep)) return ::new char[size];
  79.     StringRep *s = freeList;
  80.     if (s)
  81.         freeList = s->next;
  82.     else
  83.     {
  84.         StringRep *block = (StringRep*)::new char[chunksize*sizeof(StringRep)];
  85.         if (block == 0)
  86.         {
  87.             PEHF newHandler = set_new_handler(0);
  88.             set_new_handler(newHandler);
  89.             if (newHandler)
  90.                 newHandler();
  91.             else
  92.                 return 0;
  93.         }
  94.         for (int i = 0; i < chunksize - 1; i++)
  95.             block[i].next = (StringRep *)&block[i + 1];
  96.         block[chunksize - 1].next = 0;
  97.         s = block;
  98.         freeList = &block[1];
  99.     }
  100.     return s;
  101. }
  102.  
  103. void StringRep::operator delete(void *object)
  104. {
  105.     StringRep *s = (StringRep *)object;
  106.     s->next = freeList;
  107.     freeList = s;
  108. }
  109.  
  110. String::~String() { if (--p->count <= 0) delete p; }
  111.  
  112. String& String::operator=(const String& rhs)
  113. {
  114.     rhs.p->count++;
  115.     if (--p->count <= 0) delete p;
  116.     p = rhs.p;
  117.     return *this;
  118. }
  119.  
  120. void String::operator+=(const String& rhs)
  121. {
  122.     size_t slen = p->length() + rhs.length();
  123.     char *buf   = ::new char[slen + 1];
  124.     (void)strcpy(buf, p->rep);
  125.     (void)strcat(buf, rhs.p->rep);
  126.     if (p->count == 1)
  127.     {
  128.         DELETE p->rep;
  129.         p->rep = buf;
  130.         p->len = slen;
  131.     }
  132.     else
  133.         operator=(String(&buf, slen));
  134. }
  135.  
  136. void String::operator+=(const char *rhs)
  137. {
  138.     size_t slen = p->length() + ::strlen(rhs);
  139.     char *buf = ::new char[slen + 1];
  140.     ::strcpy(buf, p->rep);
  141.     ::strcat(buf, rhs);
  142.     if (p->count == 1)
  143.     {
  144.         DELETE p->rep;
  145.         p->rep = buf;
  146.         p->len = slen;
  147.     }
  148.     else
  149.         operator=(String(&buf, slen));
  150. }
  151.  
  152. void String::range_error(int index)
  153. {
  154.     ::error("range error: %d out of bounds", index);
  155.     exit(1);
  156. }
  157.  
  158. SBHelper String::operator[](int index)
  159. {
  160.     if (index < 0 || index >= length()) range_error(index);
  161.     return SBHelper(*this, index);
  162. }
  163.  
  164. char SBHelper::operator=(char c)
  165. {
  166.     if (str.p->count == 1)
  167.         //
  168.         // Only one reference to our String.  Just assign the character to
  169.         // the appropriate place.  Note that String::operator\[\] does the
  170.         // range checking.
  171.         //
  172.         str.p->rep[index] = c;
  173.     else
  174.     {
  175.         // We have to uniquify our str.
  176.         str = String(str.p->rep);
  177.         str.p->rep[index] = c;
  178.     }
  179.     return c;
  180. }
  181.  
  182. DLink::DLink(char **line) : _line(line) { _next = _prev = 0; }
  183.  
  184. //
  185. // Update the line in DLink with a new version.  The new
  186. // line should have been been allocated via new\(\).
  187. // 
  188. void DLink::update(char **new_line) { _line = String(new_line); }
  189.  
  190. DList::DList()
  191. {
  192.     _head   = _tail = 0;
  193.     _next   = _prev = 0;
  194.     _firstLine = _lastLine = _currLine = 0;
  195.     _nelems    = _saved_x  = _saved_y  = 0;
  196. }
  197.  
  198. //
  199. // Adds the DLink to the listing maintained by DList.
  200. //
  201.  
  202. void DList::add(DLink *link)
  203. {
  204.     if (nelems())
  205.     {
  206.         _tail->_next = link;
  207.         _tail->_next->_prev = tail();
  208.         _tail = link;
  209.         _nelems++;
  210.     }
  211.     else
  212.     {
  213.         _head = _tail = link;
  214.         _nelems = 1;
  215.     }
  216. }
  217.  
  218. //
  219. // Delete the current listing line in the window
  220. // and update our view.  The width of our view
  221. // always decreases by one.  If the calling procedure
  222. // adds more lines to the screen, they\'ll have to reset
  223. // lastLine\(\) and/or firstLine\(\), but currLine doesn\'t need to change.
  224. //
  225.  
  226. void DList::deleteLine()
  227. {
  228.     DLink *line = currLine();
  229.  
  230.     if (atBegOfList())
  231.     {
  232.         //
  233.         // that is, firstLine\(\) == head\(\)
  234.         //
  235.         _head = _firstLine = _currLine = head()->next();
  236.         _head->_prev = 0;
  237.     }
  238.     else if (atWindowTop())
  239.     {
  240.         //
  241.         // but firstLine\(\) != head\(\)
  242.         //
  243.         _firstLine = _currLine = line->next();
  244.         line->_next->_prev = line->prev();
  245.         line->_prev->_next = line->next();
  246.     }
  247.     else if (atEndOfList())
  248.     {
  249.         //
  250.         // lastLine\(\) == tail\(\)
  251.         //
  252.         _tail = _lastLine = _currLine = line->prev();
  253.         _tail->_next = 0;
  254.     }
  255.     else
  256.     {
  257.         _currLine = line->next();
  258.         line->_next->_prev = line->prev();
  259.         line->_prev->_next = line->next();
  260.     }
  261.  
  262.     _nelems--;
  263.     delete line;
  264. }
  265.  
  266. DList::~DList()
  267. {
  268.     if (nelems())
  269.     {
  270.         DLink *tmp = tail(), *prev = tail()->prev();
  271.         while(tmp)
  272.         {
  273.             delete tmp;
  274.             if ((tmp = prev) != 0) prev = tmp->prev();
  275.         }
  276.         delete tmp;
  277.     }
  278. }
  279.  
  280. //
  281. // The definition of the head of the freelist that DLink::operator new\(\)
  282. // uses to dole out dirLines efficiently.
  283. //
  284. DLink *DLink::freeList;
  285.  
  286. void *DLink::operator new(size_t)
  287. {
  288.     DLink *line = freeList;
  289.     if (line)
  290.         freeList = line->next();
  291.     else
  292.     {
  293.         DLink *block = (DLink *) ::new char[chunksize * sizeof(DLink)];
  294.         if (block == 0)
  295.         {
  296.             PEHF newHandler = set_new_handler(0);
  297.             set_new_handler(newHandler);
  298.             if (newHandler)
  299.                 newHandler();
  300.             else
  301.                 return 0;
  302.         }
  303.         for (int i = 0; i < chunksize - 1; i++)
  304.             block[i]._next = (DLink *)&block[i + 1];
  305.         block[chunksize - 1]._next = 0;
  306.         line = block;
  307.         freeList = &block[1];
  308.     }
  309.     return line;
  310. }
  311.  
  312. void DLink::operator delete(void *object)
  313. {
  314.     DLink *line = (DLink *)object;
  315.     line->_next = freeList;
  316.     freeList = line;
  317. }
  318.  
  319.  
  320.