home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume33 / problem / part04 / classes.C next >
Encoding:
C/C++ Source or Header  |  1992-10-19  |  7.2 KB  |  313 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.9   Delta\'d: 12:28:24 9/23/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. String StringRep::operator+(const String& s) const
  52. {
  53.     size_t slen  = s.length() + length();
  54.     char *buf    = ::new char[slen + 1];
  55.     ::strcpy(buf, rep);
  56.     ::strcat(buf, s.p->rep);
  57.     return String(&buf, slen);
  58. }
  59.  
  60. /*
  61. ** The definition of the head of the freelist that StringRep::operator new\(\)
  62. ** uses to dole out StringReps efficiently.
  63. */
  64.  
  65. StringRep *StringRep::freeList;
  66.  
  67. void* StringRep::operator new(size_t size)
  68. {
  69.     if (size != sizeof(StringRep)) return ::new char[size];
  70.     StringRep *s = freeList;
  71.     if (s)
  72.         freeList = s->next;
  73.     else
  74.     {
  75.         StringRep *block = (StringRep*)::new char[chunksize*sizeof(StringRep)];
  76.         if (block == 0)
  77.         {
  78.             PEHF newHandler = set_new_handler(0);
  79.             set_new_handler(newHandler);
  80.             if (newHandler)
  81.                 newHandler();
  82.             else
  83.                 return 0;
  84.         }
  85.         for (int i = 0; i < chunksize - 1; i++)
  86.             block[i].next = (StringRep *)&block[i + 1];
  87.         block[chunksize - 1].next = 0;
  88.         s = block;
  89.         freeList = &block[1];
  90.     }
  91.     return s;
  92. }
  93.  
  94. void StringRep::operator delete(void *object)
  95. {
  96.     StringRep *s = (StringRep *)object;
  97.     s->next = freeList;
  98.     freeList = s;
  99. }
  100.  
  101. String::~String() { if (--p->count <= 0) delete p; }
  102.  
  103. String& String::operator=(const String& rhs)
  104. {
  105.     rhs.p->count++;
  106.     if (--p->count <= 0) delete p;
  107.     p = rhs.p;
  108.     return *this;
  109. }
  110.  
  111. void String::operator+=(const String& rhs)
  112. {
  113.     size_t slen = p->length() + rhs.length();
  114.     char *buf   = ::new char[slen + 1];
  115.     (void)strcpy(buf, p->rep);
  116.     (void)strcat(buf, rhs.p->rep);
  117.     if (p->count == 1)
  118.     {
  119.         DELETE p->rep;
  120.         p->rep = buf;
  121.         p->len = slen;
  122.     }
  123.     else
  124.         operator=(String(&buf, slen));
  125. }
  126.  
  127. void String::operator+=(const char *rhs)
  128. {
  129.     size_t slen = p->length() + ::strlen(rhs);
  130.     char *buf = ::new char[slen + 1];
  131.     ::strcpy(buf, p->rep);
  132.     ::strcat(buf, rhs);
  133.     if (p->count == 1)
  134.     {
  135.         DELETE p->rep;
  136.         p->rep = buf;
  137.         p->len = slen;
  138.     }
  139.     else
  140.         operator=(String(&buf, slen));
  141. }
  142.  
  143. void String::range_error(int index)
  144. {
  145.     ::error("range error: %d out of bounds", index);
  146.     exit(1);
  147. }
  148.  
  149. SBHelper String::operator[](int index)
  150. {
  151.     if (index < 0 || index >= length()) range_error(index);
  152.     return SBHelper(*this, index);
  153. }
  154.  
  155. SBHelper::SBHelper(String& s, int i) : str(s), index(i) { };
  156.  
  157. char SBHelper::operator=(char c)
  158. {
  159.     if (str.p->count == 1)
  160.         //
  161.         // Only one reference to our String.  Just assign the character to
  162.         // the appropriate place.  Note that String::operator\[\] does the
  163.         // range checking.
  164.         //
  165.         str.p->rep[index] = c;
  166.     else
  167.     {
  168.         // We have to uniquify our str.
  169.         str = String(str.p->rep);
  170.         str.p->rep[index] = c;
  171.     }
  172.     return c;
  173. }
  174.  
  175. DLink::DLink(char **line) : _line(line) { _next = _prev = 0; }
  176.  
  177. //
  178. // Update the line in DLink with a new version.  The new
  179. // line should have been been allocated via new\(\).
  180. // 
  181. void DLink::update(char **new_line) { _line = String(new_line); }
  182.  
  183. DList::DList()
  184. {
  185.     _head   = _tail = 0;
  186.     _next   = _prev = 0;
  187.     _firstLine = _lastLine = _currLine = 0;
  188.     _nelems    = _saved_x  = _saved_y  = 0;
  189. }
  190.  
  191. //
  192. // Adds the DLink to the listing maintained by DList.
  193. //
  194.  
  195. void DList::add(DLink *link)
  196. {
  197.     if (nelems())
  198.     {
  199.         _tail->_next = link;
  200.         _tail->_next->_prev = tail();
  201.         _tail = link;
  202.         _nelems++;
  203.     }
  204.     else
  205.     {
  206.         _head = _tail = link;
  207.         _nelems = 1;
  208.     }
  209. }
  210.  
  211. //
  212. // Delete the current listing line in the window
  213. // and update our view.  The width of our view
  214. // always decreases by one.  If the calling procedure
  215. // adds more lines to the screen, they\'ll have to reset
  216. // lastLine\(\) and/or firstLine\(\), but currLine doesn\'t need to change.
  217. //
  218.  
  219. void DList::deleteLine()
  220. {
  221.     DLink *line = currLine();
  222.  
  223.     if (atBegOfList())
  224.     {
  225.         //
  226.         // that is, firstLine\(\) == head\(\)
  227.         //
  228.         _head = _firstLine = _currLine = head()->next();
  229.         _head->_prev = 0;
  230.     }
  231.     else if (atWindowTop())
  232.     {
  233.         //
  234.         // but firstLine\(\) != head\(\)
  235.         //
  236.         _firstLine = _currLine = line->next();
  237.         line->_next->_prev = line->prev();
  238.         line->_prev->_next = line->next();
  239.     }
  240.     else if (atEndOfList())
  241.     {
  242.         //
  243.         // lastLine\(\) == tail\(\)
  244.         //
  245.         _tail = _lastLine = _currLine = line->prev();
  246.         _tail->_next = 0;
  247.     }
  248.     else
  249.     {
  250.         _currLine = line->next();
  251.         line->_next->_prev = line->prev();
  252.         line->_prev->_next = line->next();
  253.     }
  254.  
  255.     _nelems--;
  256.     delete line;
  257. }
  258.  
  259. DList::~DList()
  260. {
  261.     if (nelems())
  262.     {
  263.         DLink *tmp = tail(), *prev = tail()->prev();
  264.         while(tmp)
  265.         {
  266.             delete tmp;
  267.             if ((tmp = prev) != 0) prev = tmp->prev();
  268.         }
  269.         delete tmp;
  270.     }
  271. }
  272.  
  273. //
  274. // The definition of the head of the freelist that DLink::operator new\(\)
  275. // uses to dole out dirLines efficiently.
  276. //
  277. DLink *DLink::freeList;
  278.  
  279. void *DLink::operator new(size_t)
  280. {
  281.     DLink *line = freeList;
  282.     if (line)
  283.         freeList = line->next();
  284.     else
  285.     {
  286.         DLink *block = (DLink *) ::new char[chunksize * sizeof(DLink)];
  287.         if (block == 0)
  288.         {
  289.             PEHF newHandler = set_new_handler(0);
  290.             set_new_handler(newHandler);
  291.             if (newHandler)
  292.                 newHandler();
  293.             else
  294.                 return 0;
  295.         }
  296.         for (int i = 0; i < chunksize - 1; i++)
  297.             block[i]._next = (DLink *)&block[i + 1];
  298.         block[chunksize - 1]._next = 0;
  299.         line = block;
  300.         freeList = &block[1];
  301.     }
  302.     return line;
  303. }
  304.  
  305. void DLink::operator delete(void *object)
  306. {
  307.     DLink *line = (DLink *)object;
  308.     line->_next = freeList;
  309.     freeList = line;
  310. }
  311.  
  312.  
  313.