home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_11_11 / splash / splash.h < prev    next >
Text File  |  1993-01-15  |  23KB  |  856 lines

  1. /*
  2.  * Version 1.8
  3.  * Written by Jim Morris,  jegm@sgi.com
  4.  * Kudos to Larry Wall for inventing Perl
  5.  * Copyrights only exist on the regex stuff, and all have been left intact.
  6.  * The only thing I ask is that you let me know of any nifty fixes or
  7.  * additions.
  8.  * 
  9.  * Credits:
  10.  * I'd like to thank Michael Golan <mg@Princeton.EDU> for his critiques
  11.  * and clever suggestions. Some of which have actually been implemented
  12.  */
  13.  
  14. #ifndef    _SPLASH_H
  15. #define    _SPLASH_H
  16.  
  17. #include <string.h>
  18. #include "regexp.h"
  19.  
  20. #if    DEBUG
  21. #include    <stdio.h>
  22. #endif
  23.  
  24. #define    INLINE    inline
  25.  
  26. //************************************************************
  27. // This is the base class for SPList, it handles the underlying
  28. // dynamic array mechanism
  29. //************************************************************
  30.  
  31. template<class T>
  32. class SPListBase
  33. {
  34. private:
  35.     enum{ALLOCINC=20};
  36.     T *a;
  37.     int cnt;
  38.     int first;
  39.     int allocated;
  40.     int allocinc;
  41.     void grow(int amnt= 0, int newcnt= -1);
  42.  
  43. protected:
  44.     void compact(const int i);
  45.  
  46. public:
  47. #ifdef    USLCOMPILER
  48.     // USL 3.0 bug with enums losing the value
  49.     SPListBase(int n= 20)
  50. #else
  51.     SPListBase(int n= ALLOCINC)
  52. #endif
  53.     {
  54.     a= new T[n];
  55.     cnt= 0;
  56.         first= n>>1;
  57.     allocated= n;
  58.     allocinc= n;
  59. #    ifdef    DEBUG
  60.     fprintf(stderr, "SPListBase(int %d) a= %p\n", allocinc, a);
  61. #    endif
  62.     }
  63.  
  64.     SPListBase(const SPListBase<T>& n);
  65.     SPListBase<T>& SPListBase<T>::operator=(const SPListBase<T>& n);
  66.     virtual ~SPListBase(){
  67. #       ifdef    DEBUG
  68.     fprintf(stderr, "~SPListBase() a= %p, allocinc= %d\n", a, allocinc);
  69. #       endif
  70.     delete [] a;
  71.     }
  72.  
  73.     INLINE T& operator[](const int i);
  74.     INLINE const T& operator[](const int i) const;
  75.  
  76.     int count(void) const{ return cnt; }
  77.  
  78.     void add(const T& n);
  79.     void add(const int i, const T& n);
  80.     void erase(void){ cnt= 0; first= (allocated>>1);}
  81. };
  82.  
  83. // forward declarations
  84. class SPStringList;
  85. class Slice;
  86. template <class T> class SPList;
  87. template <class T> class SubList;
  88.  
  89. //************************************************************
  90. // Slice class to keep track of, and create, slices
  91. //************************************************************
  92.  
  93. #include <stdarg.h>
  94. class Slice
  95. {
  96. private:
  97.     SPList<Range> *rl;
  98.  
  99. public:
  100.     inline Slice();
  101.     Slice(const char *); // parse the string to get a slice
  102.     Slice(int n, ...); // list of indices to add to slice
  103.     inline Slice(const Slice& slc);
  104.     inline Slice(const Range& r);
  105.     inline ~Slice();
  106.      
  107.     inline int count(void) const;
  108.     inline const Range& operator[](int i) const;
  109.     void add(int i); // add one element to slice
  110.     friend ostream& operator<<(ostream&, const Slice&);
  111. };
  112.  
  113. //************************************************************
  114. // Allows assignment to slices of a list
  115. //************************************************************
  116.  
  117. template <class T>
  118. class SubList
  119. {
  120. private:
  121.     // This has to be a pointer because we don't know the size of Splice
  122.     // and there is a nasty cyclic interdependency between the next 3 classes
  123.     Slice *sl; // because we may want to use a temp in call T/O convenience with efficiency
  124.     SPList<T>& l;
  125.  
  126. public:
  127.     SubList(SPList<T>& lst, const Slice& slc);
  128.     SubList(SPList<T>& lst, int st, int len);
  129.     SubList(SPList<T>& lst, const Range& r);
  130.     ~SubList();
  131.  
  132.     SubList<T>& operator=(const SPList<T>& lst);
  133.     friend SPList<T>;
  134. };
  135.  
  136. //************************************************************
  137. // SPList
  138. //************************************************************
  139.  
  140. template <class T>
  141. class SPList: private SPListBase<T>
  142. {
  143. public:
  144.  
  145.     SPList(int sz= 10): SPListBase<T>(sz){}
  146.     SPList(const SubList<T>& sbl);
  147.     
  148.     // stuff I want public to see from SPListBase
  149.     T& operator[](const int i){return SPListBase<T>::operator[](i);}
  150.     const T& operator[](const int i) const{return SPListBase<T>::operator[](i);}
  151.     SPListBase<T>::count;   // some compilers don't like this
  152.  
  153.     // add perl-like synonyms
  154.     void reset(void){ erase(); }
  155.     int scalar(void) const { return count(); }
  156.  
  157.     operator void*() { return count()?this:0; } // so it can be used in tests
  158.     int isempty(void) const{ return !count(); } // for those that don't like the above (hi michael)
  159.  
  160.     T pop(void)
  161.     {
  162.     T tmp;
  163.     int n= count()-1;
  164.     if(n >= 0){
  165.         tmp= (*this)[n];
  166.         compact(n);
  167.     }
  168.     return tmp;
  169.     }
  170.  
  171.     void push(const T& a){ add(a);}
  172.     void push(const SPList<T>& l);
  173.  
  174.     T shift(void)
  175.     {
  176.     T tmp= (*this)[0];
  177.     compact(0);
  178.     return tmp;
  179.     }
  180.     
  181.     int unshift(const T& a)
  182.     {
  183.     add(0, a);
  184.     return count();
  185.     }
  186.     
  187.     int unshift(const SPList<T>& l);
  188.  
  189.     SPList<T> reverse(void);
  190.     SPList<T> sort();
  191.     
  192.     SPList<T> splice(int offset, int len, const SPList<T>& l);
  193.     SPList<T> splice(int offset, int len);
  194.     SPList<T> splice(int offset);
  195.  
  196.     SubList<T> operator()(int st, int len){return SubList<T>(*this, st, len);}
  197.     SubList<T> operator()(const Range& r){return SubList<T>(*this, r);}
  198.     SubList<T> operator()(const Slice& slc){return SubList<T>(*this, slc);}
  199.     SubList<T> operator()(const char *s){return SubList<T>(*this, Slice(s));}
  200. };
  201.  
  202. //****************************************************************
  203. // just a mechanism for self deleteing strings which can be hacked
  204. //****************************************************************
  205.  
  206. class TempString
  207. {
  208. private:
  209.     char *str;
  210. public:
  211.     TempString(const char *s)    
  212.     {
  213.         str= new char[strlen(s) + 1];
  214.         strcpy(str, s);
  215.     }
  216.     
  217.     TempString(const char *s, int len)    
  218.     {
  219.         str= new char[len + 1];
  220.         if(len) strncpy(str, s, len);
  221.         str[len]= '\0';
  222.     }
  223.  
  224.     ~TempString(){ delete [] str; }
  225.  
  226.     operator char*() const { return str; }
  227. };
  228.  
  229. //************************************************************
  230. // This class takes care of the mechanism behind variable
  231. // length strings
  232. //************************************************************
  233.  
  234. class VarString
  235. {
  236. private:
  237.     enum{ALLOCINC=32};
  238.     char *a;
  239.     int len;
  240.     int allocated;
  241.     int allocinc;
  242.     INLINE void grow(int n= 0);
  243.  
  244. public:
  245. #ifdef    USLCOMPILER
  246.     // USL 3.0 bug with enums losing the value
  247.     INLINE VarString(int n= 32);
  248. #else
  249.     INLINE VarString(int n= ALLOCINC);
  250. #endif
  251.  
  252.     INLINE VarString(const VarString& n);
  253.     INLINE VarString(const char *);
  254.     INLINE VarString(const char* s, int n);
  255.     INLINE VarString(char);
  256.  
  257.     ~VarString(){
  258. #       ifdef    DEBUG
  259.     fprintf(stderr, "~VarString() a= %p, allocinc= %d\n", a, allocinc);
  260. #       endif
  261.     delete [] a;
  262.     }
  263.  
  264.     VarString& operator=(const VarString& n);
  265.     VarString& operator=(const char *);
  266.  
  267.     INLINE const char operator[](const int i) const;
  268.     INLINE char& operator[](const int i);
  269.  
  270.     operator const char *() const{ return a; }
  271.  
  272.     int length(void) const{ return len; }
  273.  
  274.     void add(char);
  275.     void add(const char *);
  276.     void add(int, const char *);
  277.     void remove(int, int= 1);
  278.  
  279.     void erase(void){ len= 0; }
  280. };
  281.  
  282. class SPStringList;
  283.  
  284. //************************************************************
  285. // Implements the perl specific string functionality 
  286. //************************************************************
  287.  
  288. class SPString
  289. {
  290. private:
  291.     VarString pstr;  // variable length string mechanism
  292.     
  293. public:
  294.     class substring;
  295.     
  296.     SPString():pstr(){}
  297.     SPString(const SPString& n) : pstr(n.pstr){}     
  298.     SPString(const char *s) : pstr(s){}
  299.     SPString(const char c) : pstr(c){}
  300.     SPString(const substring& sb) : pstr(sb.pt, sb.len){}
  301.     
  302.     SPString& operator=(const char *s){pstr= s; return *this;}        
  303.     SPString& operator=(const SPString& n); 
  304.     SPString& operator=(const substring& sb);
  305.  
  306.     operator const char*() const{return pstr;}
  307.     const char operator[](int n) const{ return pstr[n]; }
  308.  
  309.     int length(void) const{ return pstr.length(); }
  310.     
  311.     char chop(void);
  312.     
  313.     int index(const SPString& s, int offset= 0);    
  314.     int rindex(const SPString& s, int offset= -1);
  315.     substring substr(int offset, int len= -1);
  316.     substring substr(const Range& r){ return substr(r.start(), r.length());}
  317.         
  318.     int m(const char *, const char *opts=""); // the regexp match m/.../ equiv
  319.     int m(Regexp&);
  320.     int m(const char *, SPStringList&, const char *opts="");
  321.     int m(Regexp&, SPStringList&);
  322.    
  323.     int tr(const char *, const char *, const char *opts="");
  324.     int s(const char *, const char *, const char *opts="");
  325.  
  326.     SPStringList split(const char *pat= "[ \t\n]+", int limit= -1);
  327.     
  328.     int operator<(const SPString& s) const { return (strcmp(pstr, s) < 0); }
  329.     int operator>(const SPString& s) const { return (strcmp(pstr, s) > 0); }
  330.     int operator<=(const SPString& s) const { return (strcmp(pstr, s) <= 0); }
  331.     int operator>=(const SPString& s) const { return (strcmp(pstr, s) >= 0); }
  332.     int operator==(const SPString& s) const { return (strcmp(pstr, s) == 0); }
  333.     int operator!=(const SPString& s) const { return (strcmp(pstr, s) != 0); }
  334.  
  335.     int operator<(const char *s) const { return (strcmp(pstr, s) < 0); }
  336.     int operator>(const char *s) const { return (strcmp(pstr, s) > 0); }
  337.     int operator<=(const char *s) const { return (strcmp(pstr, s) <= 0); }
  338.     int operator>=(const char *s) const { return (strcmp(pstr, s) >= 0); }
  339.     int operator==(const char *s) const { return (strcmp(pstr, s) == 0); }
  340.     int operator!=(const char *s) const { return (strcmp(pstr, s) != 0); }
  341.  
  342.     friend int operator<(const char *s, const SPString& sp)  { return (strcmp(s, sp.pstr) < 0); }
  343.     friend int operator>(const char *s, const SPString& sp)  { return (strcmp(s, sp.pstr) > 0); }
  344.     friend int operator<=(const char *s, const SPString& sp)  { return (strcmp(s, sp.pstr) <= 0); }
  345.     friend int operator>=(const char *s, const SPString& sp)  { return (strcmp(s, sp.pstr) >= 0); }
  346.     friend int operator==(const char *s, const SPString& sp)  { return (strcmp(s, sp.pstr) == 0); }
  347.     friend int operator!=(const char *s, const SPString& sp)  { return (strcmp(s, sp.pstr) != 0); }
  348.  
  349.     SPString operator+(const SPString& s) const;
  350.     SPString operator+(const char *s) const;
  351.     SPString operator+(char c) const;
  352.     friend SPString operator+(const char *s1, const SPString& s2);
  353.  
  354.     SPString& operator+=(const SPString& s){pstr.add(s); return *this;}
  355.     SPString& operator+=(const char *s){pstr.add(s); return *this;}
  356.     SPString& operator+=(char c){pstr.add(c); return *this;}
  357.     friend substring;
  358.  
  359. private:
  360.     void insert(int pos, int len, const char *pt, int nlen);
  361.  
  362.     // This idea lifted from NIH class library -
  363.     // to handle substring LHS assignment
  364.     // Note if subclasses can't be used then take external and make
  365.     // the constructors private, and specify friend SPString
  366.     class substring
  367.     {
  368.     public:
  369.         int pos, len;
  370.     SPString& str;
  371.     char *pt;
  372.     public:
  373.         substring(SPString& os, int p, int l) : str(os)
  374.     {
  375.         if(p > os.length()) p= os.length();
  376.         if((p+l) > os.length()) l= os.length() - p;
  377.         pos= p; len= l;
  378.         if(p == os.length()) pt= 0; // append to end of string
  379.         else pt= &os.pstr[p];
  380.     }
  381.  
  382.         void operator=(const SPString& s)
  383.         {
  384.             if(&str == &s){ // potentially overlapping
  385.         VarString tmp(s);
  386.         str.insert(pos, len, tmp, strlen(tmp));
  387.         }else str.insert(pos, len, s, s.length());
  388.         }
  389.         
  390.         void operator=(const substring& s)
  391.         {
  392.         if(&str == &s.str){ // potentially overlapping
  393.         VarString tmp(s.pt, s.len);
  394.         str.insert(pos, len, tmp, strlen(tmp));
  395.         }else str.insert(pos, len, s.pt, s.len);
  396.         }
  397.  
  398.         void operator=(const char *s)
  399.         {
  400.             str.insert(pos, len, s, strlen(s));
  401.         }
  402.     };
  403. };
  404.  
  405. //************************************************************
  406. // SPStringList
  407. //************************************************************
  408.  
  409. class SPStringList: public SPList<SPString>
  410. {
  411. public:
  412.     SPStringList(int sz= 6):SPList<SPString>(sz){}
  413.     // copy lists, need to duplicate all internal strings
  414.     SPStringList(const SPStringList& n);
  415.  
  416.     SPStringList& operator=(const SPList<SPString>& n);
  417.  
  418.     int split(const char *str, const char *pat= "[ \t\n]+", int limit= -1);
  419.     SPString join(const char *pat= " ");
  420.     int m(const char *rege, const char *targ, const char *opts=""); // makes list of sub exp matches
  421.     friend SPStringList m(const char *pat, const char *str, const char *opts="")
  422.     {
  423.     SPStringList l;
  424.     l.m(pat, str, opts);
  425.         l.shift(); // remove the first element which would be $&
  426.         return l;
  427.     }
  428.     SPStringList grep(const char *rege, const char *opts=""); // trys rege against elements in list
  429. };
  430.  
  431. //************************************************************
  432. // Streams operators
  433. //************************************************************
  434.  
  435. template <class T>
  436. istream& operator>>(istream& ifs, SPList<T>& arr)
  437. {
  438. T a;
  439.     // Should I reset arr first?
  440.     arr.reset(); // I think so, to be consistent
  441.     
  442.     while(ifs >> a){
  443.     arr.push(a);
  444. //    cout << "<" << a << ">" << endl;
  445.     };
  446.     return ifs;    
  447. }
  448.  
  449. template <class T>
  450. ostream& operator<<(ostream& os,  const SPList<T>& arr)
  451. {
  452.  
  453.     for(int i=0;i<arr.count();i++){
  454. #ifdef    TEST
  455.     os << "[" << i << "]" << arr[i] << " ";
  456.     }
  457.     os << endl; 
  458. #else
  459.     os << arr[i] << endl;
  460.     }
  461. #endif
  462.     return os;   
  463. }
  464.  
  465. istream& operator>>(istream& ifs, SPString& s);
  466. istream& operator>>(istream& ifs, SPStringList& sl);
  467. ostream& operator<<(ostream& os,  const SPString& arr);
  468. ostream& operator<<(ostream& os,  const SPStringList& arr);
  469.  
  470. //************************************************************
  471. // Implementation of template functions for splistbase
  472. //************************************************************
  473.  
  474. template <class T>
  475. INLINE T& SPListBase<T>::operator[](const int i)
  476. {
  477.     assert((i >= 0) && (first >= 0) && ((first+cnt) <= allocated));
  478.     int indx= first+i;
  479.         
  480.     if(indx >= allocated){  // need to grow it
  481.     grow((indx-allocated)+allocinc, i+1); // index as yet unused element
  482.     indx= first+i;              // first will have changed in grow()
  483.     }
  484.     assert(indx >= 0 && indx < allocated);
  485.  
  486.     if(i >= cnt) cnt= i+1;  // it grew
  487.     return a[indx];
  488. }
  489.  
  490. template <class T>
  491. INLINE const T& SPListBase<T>::operator[](const int i) const
  492. {
  493.      assert((i >= 0) && (i < cnt));
  494.      return a[first+i];
  495. }
  496.  
  497. template <class T>
  498. SPListBase<T>::SPListBase(const SPListBase<T>& n)
  499. {
  500.     allocated= n.allocated;
  501.     allocinc= n.allocinc;
  502.     cnt= n.cnt;
  503.     first= n.first;
  504.     a= new T[allocated];
  505.     for(int i=0;i<cnt;i++) a[first+i]= n.a[first+i];
  506. #ifdef    DEBUG
  507.     fprintf(stderr, "SPListBase(SPListBase&) a= %p, source= %p\n", a, n.a);
  508. #endif
  509.  
  510. }
  511.  
  512. template <class T>
  513. SPListBase<T>& SPListBase<T>::operator=(const SPListBase<T>& n){
  514. //  cout << "SPListBase<T>::operator=()" << endl;
  515.     if(this == &n) return *this;
  516. #ifdef    DEBUG
  517.     fprintf(stderr, "~operator=(SPListBase&) a= %p\n", a);
  518. #endif
  519.     delete [] a; // get rid of old one
  520.     allocated= n.allocated;
  521.     allocinc= n.allocinc;
  522.     cnt= n.cnt;
  523.     first= n.first;
  524.     a= new T[allocated];
  525.     for(int i=0;i<cnt;i++) a[first+i]= n.a[first+i];
  526. #ifdef    DEBUG
  527.     fprintf(stderr, "operator=(SPListBase&) a= %p, source= %p\n", a, n.a);
  528. #endif
  529.     return *this;
  530. }
  531.  
  532. template <class T>
  533. void SPListBase<T>::grow(int amnt, int newcnt){
  534.     if(amnt <= 0) amnt= allocinc; // default value
  535.     if(newcnt < 0) newcnt= cnt;   // default
  536.     allocated += amnt;
  537.     T *tmp= new T[allocated];
  538.     int newfirst= (allocated>>1) - (newcnt>>1);
  539.     for(int i=0;i<cnt;i++) tmp[newfirst+i]= a[first+i];
  540. #ifdef    DEBUG
  541.     fprintf(stderr, "SPListBase::grow() a= %p, old= %p, allocinc= %d\n", tmp, a, allocinc);
  542.     fprintf(stderr, "~SPListBase::grow() a= %p\n", a);
  543. #endif
  544.     delete [] a;
  545.     a= tmp;
  546.     first= newfirst;
  547. }
  548.  
  549. template <class T>
  550. void SPListBase<T>::add(const T& n){
  551.     if(cnt+first >= allocated) grow();
  552.     a[first+cnt]= n;
  553.     cnt++;
  554. }
  555.  
  556. template <class T>
  557. void SPListBase<T>::add(const int ip, const T& n){
  558.     assert(ip >= 0);
  559.     if(first == 0 || (first+cnt) >= allocated) grow();
  560.     assert((first > 0) && ((first+cnt) < allocated));
  561.     if(ip == 0){ // just stick it on the bottom
  562.         first--;
  563.         a[first]= n;
  564.     }else{
  565.         for(int i=cnt;i>ip;i--) // shuffle up
  566.         a[first+i]= a[(first+i)-1];
  567.         a[first+ip]= n;
  568.     }
  569.     cnt++;
  570. }
  571.  
  572. template <class T>
  573. void SPListBase<T>::compact(const int n){ // shuffle down starting at n
  574. int i;
  575.     assert((n >= 0) && (n < cnt));
  576.     if(n == 0) first++;
  577.     else for(i=n;i<cnt-1;i++){
  578.         a[first+i]= a[(first+i)+1];
  579.     }
  580.     cnt--;
  581. }
  582.  
  583. //************************************************************
  584. // implementation of template functions for SPList
  585. //************************************************************
  586.  
  587. template <class T>
  588. void SPList<T>::push(const SPList<T>& l)
  589. {
  590.     for(int i=0;i<l.count();i++)
  591.     add(l[i]);
  592. }
  593.  
  594. template <class T>
  595. int SPList<T>::unshift(const SPList<T>& l)
  596. {
  597.     for(int i=l.count()-1;i>=0;i--)
  598.     unshift(l[i]);
  599.     return count();
  600. }
  601.  
  602. template <class T>
  603. SPList<T> SPList<T>::reverse(void)
  604. {
  605.     SPList<T> tmp;
  606.     for(int i=count()-1;i>=0;i--)
  607.     tmp.add((*this)[i]);
  608.     
  609.     return tmp;    
  610. }
  611.  
  612. template <class T>
  613. SPList<T> SPList<T>::sort(void)
  614. {
  615. SPList<T> tmp(*this);
  616. int n= tmp.scalar();
  617.  
  618.     for(int i=0;i<n-1;i++)
  619.     for(int j=n-1;i<j;j--)
  620.         if(tmp[j] < tmp[j-1]){
  621.         T temp = tmp[j];
  622.         tmp[j] = tmp[j-1];
  623.         tmp[j-1]= temp;
  624.         }
  625.     
  626.     return tmp;    
  627. }
  628.  
  629. template <class T>
  630. SPList<T> SPList<T>::splice(int offset, int len, const SPList<T>& l)
  631. {
  632. SPList<T> r= splice(offset, len);
  633.  
  634.     if(offset > count()) offset= count();
  635.     for(int i=0;i<l.count();i++){
  636.     add(offset+i, l[i]);    // insert into list
  637.     }
  638.     return r;
  639. }
  640.  
  641. template <class T>
  642. SPList<T>  SPList<T>::splice(int offset, int len)
  643. {
  644. SPList<T> r;
  645.  
  646.     if(offset >= count()) return r;
  647.     for(int i=offset;i<offset+len;i++){
  648.         r.add((*this)[i]);
  649.     }
  650.  
  651.     for(i=offset;i<offset+len;i++)
  652.     compact(offset);
  653.     return r;
  654. }
  655.  
  656. template <class T>
  657. SPList<T>  SPList<T>::splice(int offset)
  658. {
  659. SPList<T> r;
  660.  
  661.     if(offset >= count()) return r;
  662.     for(int i=offset;i<count();i++){
  663.     r.add((*this)[i]);
  664.     }
  665.  
  666.     int n= count(); // count() will change so remember what it is
  667.     for(i=offset;i<n;i++)
  668.     compact(offset);
  669.     return r;
  670. }
  671.  
  672. //************************************************************
  673. // VarString Implementation
  674. //************************************************************
  675.  
  676. INLINE VarString::VarString(int n)
  677. {
  678.     a= new char[n];
  679.     *a= '\0';
  680.     len= 0;
  681.     allocated= n;
  682.     allocinc= n;
  683. #   ifdef    DEBUG
  684.     fprintf(stderr, "VarString(int %d) a= %p\n", allocinc, a);
  685. #   endif
  686. }
  687.  
  688. INLINE VarString::VarString(const char* s)
  689. {
  690.     int n= strlen(s) + 1;
  691.     a= new char[n];
  692.     strcpy(a, s);
  693.     len= n-1;
  694.     allocated= n;
  695.     allocinc= ALLOCINC;
  696. #   ifdef    DEBUG
  697.     fprintf(stderr, "VarString(const char *(%d)) a= %p\n", allocinc, a);
  698. #   endif
  699. }
  700.  
  701. INLINE VarString::VarString(const char* s, int n)
  702. {
  703.     a= new char[n+1];
  704.     if(n) strncpy(a, s, n);
  705.     a[n]= '\0';
  706.     len= n;
  707.     allocated= n+1;
  708.     allocinc= ALLOCINC;
  709. #   ifdef    DEBUG
  710.     fprintf(stderr, "VarString(const char *, int(%d)) a= %p\n", allocinc, a);
  711. #   endif
  712. }
  713.  
  714. INLINE VarString::VarString(char c)
  715. {
  716.     int n= 2;
  717.     a= new char[n];
  718.     a[0]= c; a[1]= '\0';
  719.     len= 1;
  720.     allocated= n;
  721.     allocinc= ALLOCINC;
  722. #   ifdef    DEBUG
  723.     fprintf(stderr, "VarString(char (%d)) a= %p\n", allocinc, a);
  724. #   endif
  725. }
  726.  
  727.  
  728. INLINE ostream& operator<<(ostream& os,  const VarString& arr)
  729. {
  730. #ifdef TEST
  731.     os << "(" << arr.length() << ")" << (const char *)arr;
  732. #else
  733.     os << (const char *)arr;
  734. #endif
  735.     
  736.     return os;    
  737. }
  738.  
  739. INLINE const char VarString::operator[](const int i) const
  740. {
  741.      assert((i >= 0) && (i < len) && (a[len] == '\0'));
  742.      return a[i];
  743. }
  744.  
  745. INLINE char& VarString::operator[](const int i)
  746. {
  747.      assert((i >= 0) && (i < len) && (a[len] == '\0'));
  748.      return a[i];
  749. }
  750.  
  751. INLINE VarString::VarString(const VarString& n)
  752. {
  753.     allocated= n.allocated;
  754.     allocinc= n.allocinc;
  755.     len= n.len;
  756.     a= new char[allocated];
  757.     strcpy(a, n.a);
  758. #ifdef    DEBUG
  759.     fprintf(stderr, "VarString(VarString&) a= %p, source= %p\n", a, n.a);
  760. #endif
  761.  
  762. }
  763.  
  764. //************************************************************
  765. // Sublist and Slice stuff
  766. //************************************************************
  767.  
  768. template <class T>
  769. SubList<T>::SubList(SPList<T>& lst, const Slice& slc) : l(lst)
  770. {
  771.     sl= new Slice(slc);
  772. }
  773.  
  774. template <class T>
  775. SubList<T>::SubList(SPList<T>& lst, int st, int len) : l(lst)
  776. {
  777.     sl= new Slice(Range(st, st+len-1));
  778. }
  779.  
  780. template <class T>
  781. SubList<T>::SubList(SPList<T>& lst, const Range& r) : l(lst)
  782. {
  783.     sl= new Slice(r);
  784. }
  785.  
  786. template <class T>
  787. SubList<T>::~SubList()
  788. {
  789.     delete sl;
  790. }
  791.  
  792. template <class T>
  793. SubList<T>& SubList<T>::operator=(const SPList<T>& lst)
  794. {
  795. int n= 0;
  796.     for(int i=0;i<sl->count();i++){
  797.     for(int j=(*sl)[i].start();j<=(*sl)[i].end();j++){
  798.             if(n < lst.count()) l[j]= lst[n++];
  799.         }
  800.     }        
  801.     return *this;
  802. }
  803.  
  804. template <class T>
  805. SPList<T>::SPList(const SubList<T>& sbl)
  806. {
  807.     for(int i=0;i<sbl.sl->count();i++){
  808.     for(int j=(*sbl.sl)[i].start();j<=(*sbl.sl)[i].end();j++)
  809.         (*this).push(sbl.l[j]);
  810.     }
  811. }
  812.  
  813. //************************************************************
  814. // Slice inline stuff
  815. //************************************************************
  816.  
  817. inline Slice::Slice(const Range& r)
  818. {
  819.     rl= new SPList<Range>;
  820.     rl->push(r);
  821. }
  822.  
  823. inline Slice::Slice()
  824. {
  825.     rl= new SPList<Range>;
  826. }
  827.  
  828. inline Slice::Slice(const Slice& slc)
  829. {
  830.     rl= new SPList<Range>(*slc.rl);    
  831. }
  832.  
  833.  
  834. inline Slice::~Slice()
  835. {
  836.     delete rl;
  837. }
  838.      
  839. inline int Slice::count(void) const
  840. {
  841.     return rl->count();
  842. }
  843.  
  844. inline const Range& Slice::operator[](int i) const
  845. {
  846.     return (*rl)[i];
  847. }
  848.  
  849.  
  850. // For Old-timers compatibility
  851. typedef SPStringList PerlStringList;
  852. typedef SPString PerlString;
  853. #define PerlList SPList
  854. #endif
  855.  
  856.