1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // Chain.cc
4 // ---------
5 // String class implementation
6 //
7 // Design and Implementation by Bjoern Lemke
8 //
9 // (C)opyright 2000-2016 Bjoern Lemke
10 //
11 // IMPLEMENTATION MODULE
12 //
13 // Class: Chain
14 //
15 // Description: All operations on strings
16 //
17 // Status: CLEAN
18 //
19 ///////////////////////////////////////////////////////////////////////////////
20 
21 // SYSTEM INCLUDES
22 #include <stdlib.h>
23 #include <ctype.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include <wctype.h>
28 
29 // BASE INCLUDES
30 #include "Exception.h"
31 #include "Chain.h"
32 
33 // DEFINES
34 #define TMPBUFSIZE 100
35 #define INBUFSIZE 100
36 
Chain()37 Chain::Chain()
38 {
39      _buf = 0;
40      _len = 0;
41 }
42 
Chain(const char * s)43 Chain::Chain(const char *s)
44 {
45      _buf = 0;
46      _len = 0;
47 
48      if ( s == 0 )
49      {
50 	  return;
51      }
52 
53      size_t sl = strlen(s) + 1;
54 
55      if ( sl < STATICBUFSIZE )
56      {
57 	 _buf = _staticBuf;
58      }
59      else
60      {
61 	 _buf = (char*)malloc(sl);
62 	 if ( _buf == 0 )
63 	 {
64 	     throw Exception(EXLOC, "Malloc system error");
65 	 }
66      }
67      strcpy(_buf, s);
68      _len=sl;
69 }
70 
Chain(const char * s,int len)71 Chain::Chain(const char *s, int len)
72 {
73      _buf = 0;
74      _len = 0;
75 
76      if ( s == 0 )
77      {
78 	  return;
79      }
80 
81      if ( len+1 < STATICBUFSIZE )
82      {
83 	 _buf = _staticBuf;
84      }
85      else
86      {
87 	 _buf = (char*)malloc(len+1);
88 
89 	 if ( _buf == 0 )
90 	 {
91 	     throw Exception(EXLOC, "Malloc system error");
92 	 }
93      }
94 
95      memcpy(_buf, s, len);
96      _buf[len]=0;
97      _len=len+1;
98 }
99 
Chain(const Chain & str)100 Chain::Chain(const Chain& str)
101 {
102      _len = 0;
103      _buf = 0;
104 
105      *this = str;
106 }
107 
Chain(const char c)108 Chain::Chain(const char c)
109 {
110      _buf = 0;
111      _len = 0;
112 
113      if ( c > 0 )
114      {
115 	 _buf = _staticBuf;
116 	 _buf[0]=c;
117 	 _buf[1]=0;
118 	 _len=2;
119      }
120 }
121 
Chain(long l)122 Chain::Chain(long l)
123 {
124     char tmpBuf[TMPBUFSIZE];
125 
126     _len = snprintf(tmpBuf, TMPBUFSIZE, "%ld", l);
127     if ( _len > TMPBUFSIZE )
128     {
129 	throw Exception(EXLOC, "Temp buf size exceeded");
130     }
131 
132     _len++;
133 
134     if (_len > STATICBUFSIZE )
135     {
136 	throw Exception(EXLOC, "Static buf size exceeded");
137     }
138 
139     _buf = _staticBuf;
140 
141     strcpy(_buf, tmpBuf);
142 }
143 
Chain(long long ll)144 Chain::Chain(long long ll)
145 {
146     char tmpBuf[TMPBUFSIZE];
147 
148     _len = snprintf(tmpBuf, TMPBUFSIZE, "%lld", ll);
149     if ( _len > TMPBUFSIZE )
150     {
151 	throw Exception(EXLOC, "Temp buf size exceeded");
152     }
153 
154     _len++;
155 
156     if (_len > STATICBUFSIZE )
157     {
158 	throw Exception(EXLOC, "Static buf size exceeded");
159     }
160 
161     _buf = _staticBuf;
162 
163     strcpy(_buf, tmpBuf);
164 }
165 
Chain(unsigned long l)166 Chain::Chain(unsigned long l)
167 {
168     char tmpBuf[TMPBUFSIZE];
169 
170     _len = snprintf(tmpBuf, TMPBUFSIZE, "%lu", l);
171     if ( _len > TMPBUFSIZE )
172     {
173 	throw Exception(EXLOC, "Temp buf size exceeded");
174     }
175 
176     _len++;
177 
178     if (_len > STATICBUFSIZE )
179     {
180 	throw Exception(EXLOC, "Static buf size exceeded");
181     }
182 
183     _buf = _staticBuf;
184 
185     strcpy(_buf, tmpBuf);
186 }
187 
Chain(unsigned long long ull)188 Chain::Chain(unsigned long long ull)
189 {
190     char tmpBuf[TMPBUFSIZE];
191 
192     _len = snprintf(tmpBuf, TMPBUFSIZE, "%llu", ull);
193     if ( _len > TMPBUFSIZE )
194     {
195 	throw Exception(EXLOC, "Temp buf size exceeded");
196     }
197 
198     _len++;
199 
200     if (_len > STATICBUFSIZE )
201     {
202 	throw Exception(EXLOC, "Static buf size exceeded");
203     }
204 
205     _buf = _staticBuf;
206 
207     strcpy(_buf, tmpBuf);
208 }
209 
Chain(unsigned ui)210 Chain::Chain(unsigned ui)
211 {
212     char tmpBuf[TMPBUFSIZE];
213 
214     _len = snprintf(tmpBuf, TMPBUFSIZE, "%u", ui);
215     if ( _len > TMPBUFSIZE )
216     {
217 	throw Exception(EXLOC, "Temp buf size exceeded");
218     }
219 
220     _len++;
221 
222     if (_len > STATICBUFSIZE )
223     {
224 	throw Exception(EXLOC, "Static buf size exceeded");
225     }
226 
227     _buf = _staticBuf;
228 
229     strcpy(_buf, tmpBuf);
230 }
231 
Chain(int i)232 Chain::Chain(int i)
233 {
234     char tmpBuf[TMPBUFSIZE];
235 
236     _len = snprintf(tmpBuf, TMPBUFSIZE, "%d", i);
237     if ( _len > TMPBUFSIZE )
238     {
239 	throw Exception(EXLOC, "Temp buf size exceeded");
240     }
241 
242     _len++;
243 
244     if (_len > STATICBUFSIZE )
245     {
246 	throw Exception(EXLOC, "Static buf size exceeded");
247     }
248 
249     _buf = _staticBuf;
250 
251     strcpy(_buf, tmpBuf);
252 }
253 
Chain(float f)254 Chain::Chain(float f)
255 {
256     char tmpBuf[TMPBUFSIZE];
257 
258     int l = snprintf(tmpBuf, TMPBUFSIZE, "%f", f);
259     if ( l > TMPBUFSIZE )
260     {
261 	throw Exception(EXLOC, "Temp buf size exceeded");
262     }
263 
264     if ( l < 0 )
265     {
266 	throw Exception(EXLOC, "Invalid format for float value");
267     }
268 
269     _len = l+1;
270 
271     if (_len > STATICBUFSIZE )
272     {
273 	throw Exception(EXLOC, "Static buf size exceeded");
274     }
275 
276     _buf = _staticBuf;
277 
278     strcpy(_buf, tmpBuf);
279 }
280 
Chain(double d,const char * format)281 Chain::Chain(double d, const char* format)
282 {
283     char tmpBuf[TMPBUFSIZE];
284 
285     int l = snprintf(tmpBuf, TMPBUFSIZE, format, d);
286     if ( l > TMPBUFSIZE )
287     {
288 	throw Exception(EXLOC, "Temp buf size exceeded");
289     }
290 
291     if ( l < 0 )
292     {
293 	throw Exception(EXLOC, "Invalid format for double value");
294     }
295     _len = l+1;
296 
297     if (_len > STATICBUFSIZE )
298     {
299 	throw Exception(EXLOC, "Static buf size exceeded");
300     }
301 
302     _buf = _staticBuf;
303 
304     strcpy(_buf, tmpBuf);
305 }
306 
~Chain()307 Chain::~Chain()
308 {
309     if (_buf != 0 && _buf != _staticBuf)
310     {
311 	free(_buf);
312     }
313     _buf = 0;
314     _len = 0;
315 }
316 
setData(char * s)317 void Chain::setData(char* s)
318 {
319     _buf = s;
320     _len=strlen(s)+1;
321 }
322 
length() const323 unsigned long Chain::length() const
324 {
325      return _len;
326 }
327 
visibleLength() const328 unsigned long Chain::visibleLength() const
329 {
330     unsigned long vlen=0;
331     unsigned long i=0;
332 
333     wchar_t t;
334     int result;
335     while ( ( result = mbtowc(&t, _buf+i, MB_CUR_MAX)) > 0  && i < _len-1 )
336     {
337 	i+=result;
338 	vlen++;
339     }
340     vlen++;
341     return vlen;
342 }
343 
toUpper() const344 Chain Chain::toUpper() const
345 {
346      Chain s = *this;
347 
348      /*
349      unsigned long i=0;
350      while ( i<_len )
351      {
352 	  s._buf[i] = toupper(s._buf[i]);
353 	  i++;
354      }
355      */
356 
357 
358      wchar_t* wText = new wchar_t[_len];
359      ::mbstowcs(wText, _buf, _len);
360 
361      unsigned long i=0;
362      wchar_t c;
363      while (wText[i])
364      {
365 	 c = wText[i];
366 	 wText[i] = towupper(c);
367 	 i++;
368      }
369 
370      ::wcstombs(s._buf, wText, _len);
371      free(wText);
372 
373      return s;
374 }
375 
toLower() const376 Chain Chain::toLower() const
377 {
378      Chain s = *this;
379 
380      /*
381      unsigned long i=0;
382      while ( i <_len )
383      {
384 	  s._buf[i] = tolower(s._buf[i]);
385 	  i++;
386      }
387      */
388 
389      wchar_t* wText = new wchar_t[_len];
390      ::mbstowcs(wText, _buf, _len);
391 
392      unsigned long i=0;
393      wchar_t c;
394      while (wText[i])
395      {
396 	 c = wText[i];
397 	 wText[i] = towlower(c);
398 	 i++;
399      }
400 
401      ::wcstombs(s._buf, wText, _len);
402      free(wText);
403 
404 
405      return s;
406 }
407 
asUnsigned(bool doStrict) const408 int Chain::asUnsigned(bool doStrict) const
409 {
410     if ( _buf == 0 )
411 	return 0;
412 
413     long l = strtol(_buf, NULL, 0);
414 
415     if ( doStrict )
416     {
417 	if ( l == 0 && errno == EINVAL )
418 	{
419 	    Chain msg = Chain("Integer conversion error : ") + Chain(strerror(errno));
420 	    throw Exception(EXLOC, msg);
421 	}
422     }
423 
424     if ( l > INT_MAX || l < 0 )
425     {
426 	Chain msg = Chain("Integer conversion error : Out of range");
427 	throw Exception(EXLOC, msg);
428     }
429 
430     unsigned ui = (unsigned)l;
431     return ui;
432 }
433 
asInteger(bool doStrict) const434 int Chain::asInteger(bool doStrict) const
435 {
436     if ( _buf == 0 )
437 	return 0;
438 
439     long l = strtol(_buf, NULL, 0);
440 
441     if ( doStrict )
442     {
443 	if ( l == 0 && errno == EINVAL )
444 	{
445 	    Chain msg = Chain("Integer conversion error : ") + Chain(strerror(errno));
446 	    throw Exception(EXLOC, msg);
447 	}
448     }
449 
450     if ( l > INT_MAX || l < INT_MIN )
451     {
452 	Chain msg = Chain("Integer conversion error : Out of range");
453 	throw Exception(EXLOC, msg);
454     }
455 
456     int i = (int)l;
457     return i;
458 }
459 
asLong(bool doStrict) const460 long Chain::asLong(bool doStrict) const
461 {
462     if ( _buf == 0 )
463 	return 0;
464 
465     if ( doStrict )
466     {
467 	long l = strtol(_buf, NULL, 0);
468 	if ( l == 0 && errno == EINVAL )
469 	{
470 	    Chain msg = Chain("Long conversion error : ") + Chain(strerror(errno));
471 	    throw Exception(EXLOC, msg);
472 	}
473 	return l;
474     }
475     else
476     {
477 	return strtol(_buf, NULL, 0);
478     }
479 }
480 
asUnsignedLong(bool doStrict) const481 unsigned long Chain::asUnsignedLong(bool doStrict) const
482 {
483     if ( _buf == 0 )
484 	return 0;
485 
486     if ( doStrict )
487     {
488 	unsigned long ul = strtoul(_buf, NULL, 0);
489 	if ( ul == 0 && errno == EINVAL )
490 	{
491 	    Chain msg = Chain("Unsigned long conversion error : ") + Chain(strerror(errno));
492 	    throw Exception(EXLOC, msg);
493 	}
494 	return ul;
495     }
496     else
497     {
498 	return strtoul(_buf, NULL, 0);
499     }
500 }
501 
asLongLong(bool doStrict) const502 long long Chain::asLongLong(bool doStrict ) const
503 {
504     if ( _buf == 0 )
505 	return 0;
506 
507     if ( doStrict )
508     {
509 	long long ll = strtoll(_buf, NULL, 0);
510 	if ( ll == 0 && errno == EINVAL)
511 	{
512 	    Chain msg = Chain("Long long conversion error : ") + Chain(strerror(errno));
513 	    throw Exception(EXLOC, msg);
514 	}
515 	return ll;
516     }
517     else
518     {
519 	return strtoll(_buf, NULL, 0);
520     }
521 }
522 
asUnsignedLongLong(bool doStrict) const523 unsigned long long Chain::asUnsignedLongLong(bool doStrict) const
524 {
525     if ( _buf == 0 )
526 	return 0;
527 
528     if ( doStrict )
529     {
530 	unsigned long long ull = strtoull(_buf, NULL, 0);
531 	if ( ull == 0 && errno == EINVAL)
532 	{
533 	    Chain msg = Chain("Unsigned long long conversion error : ") + Chain(strerror(errno));
534 	    throw Exception(EXLOC, msg);
535 	}
536 	return ull;
537     }
538     else
539     {
540 	return strtoull(_buf, NULL, 0);
541     }
542 }
543 
asFloat() const544 float Chain::asFloat() const
545 {
546     if ( _buf == 0 )
547 	return 0.0;
548 
549     float f;
550     if ( sscanf((char*)(_buf), "%f", &f) == 0 )
551 	throw Exception(EXLOC, "Cannot convert to float");
552     return f;
553 }
554 
asDouble() const555 double Chain::asDouble() const
556 {
557     if ( _buf == 0 )
558 	return (double)0.0;
559 
560     double d;
561     if ( sscanf((char*)(_buf), "%lf", &d) == 0 )
562     	throw Exception(EXLOC, "Cannot convert to double");
563     return d;
564 }
565 
asShort() const566 short Chain::asShort() const
567 {
568     if ( _buf == 0 )
569 	return 0;
570 
571     short s;
572     if ( sscanf((char*)(_buf), "%hd", &s) == 0 )
573 	throw Exception(EXLOC, "Cannot convert to short");
574     return s;
575 }
576 
asChar() const577 char Chain::asChar() const
578 {
579     if ( _buf == 0 )
580 	return 0;
581 
582     char c;
583     if ( sscanf((char*)(_buf), "%c", &c) == 0 )
584     	throw Exception(EXLOC, "Cannot convert to char");
585     return c;
586 }
587 
asBool() const588 bool Chain::asBool() const
589 {
590     if ( _buf == 0 )
591 	return false;
592 
593     if ( Chain(_buf) == Chain("true") || Chain(_buf) == Chain("yes") || Chain(_buf) == Chain("Y") || atoi(_buf) > 0 )
594 	return true;
595     return false;
596 }
597 
isNum() const598 bool Chain::isNum() const
599 {
600     if ( _len > 1 )
601     {
602 	unsigned long i=0;
603 	while ( i < _len-1 )
604 	{
605 	    if ( ! isdigit(_buf[i]) )
606 		return false;
607 	    i++;
608 	}
609 	return true;
610     }
611     return false;
612 }
613 
isDec() const614 bool Chain::isDec() const
615 {
616      unsigned long i=0;
617      bool dotRead = false;
618      while ( i < _len-1 )
619      {
620 	 if ( ! isdigit(_buf[i]) )
621 	 {
622 	     if ( _buf[i] == '.' && dotRead == false )
623 		 dotRead = true;
624 	     else
625 		 return false;
626 	 }
627 	 i++;
628      }
629      return true;
630 }
631 
cutTrailing(const Chain & str) const632 Chain Chain::cutTrailing(const Chain& str) const
633 {
634     if ( _len > 1 )
635     {
636 	int i, l,u;
637 
638 	l=0;
639 	u=_len-1;
640 	i=0;
641 	while (i < str._len && l < _len)
642 	{
643 	    if (_buf[l] == str._buf[i])
644 	    {
645 		l++;
646 		i=0;
647 	    }
648 	    else
649 	    {
650 		i++;
651 	    }
652 	}
653 
654 	i=0;
655 	while (i < str._len && u > 0)
656 	{
657 	    if (_buf[u] == str._buf[i])
658 	    {
659 		u--;
660 		i=0;
661 	    }
662 	    else
663 	    {
664 		i++;
665 	    }
666 	}
667 	if (l <= u)
668 	    return subChain(l+1, u+1);
669 	else
670 	    return Chain();
671     }
672     return *this;
673 }
674 
truncLeft(const Chain & str) const675 Chain Chain::truncLeft(const Chain& str) const
676 {
677     if ( _len > 1 )
678     {
679 	int i, l;
680 
681 	l=0;
682 	i=0;
683 	while (i < str._len && l < _len)
684 	{
685 	    if (_buf[l] == str._buf[i])
686 	    {
687 		l++;
688 		i=0;
689 	    }
690 	    else
691 	    {
692 		i++;
693 	    }
694 	}
695 	if ( l < _len )
696 	    return subChain(l+1, _len);
697 	else
698 	    return Chain("");
699     }
700     return *this;
701 }
702 
truncRight(const Chain & str) const703 Chain Chain::truncRight(const Chain& str) const
704 {
705     if ( _len > 1 )
706     {
707 	int i, u;
708 
709 	u=_len-1;
710 	i=0;
711 	while (i < str._len && u >= 0)
712 	{
713 	    if (_buf[u] == str._buf[i])
714 	    {
715 		u--;
716 		i=0;
717 	    }
718 	    else
719 	    {
720 		i++;
721 	    }
722 	}
723 
724 	if ( u >= 0 )
725 	    return subChain(1, u+1);
726 	else
727 	    return Chain("");
728     }
729     return *this;
730 }
731 
posStr(const Chain & s1,int & result,int start,int occur) const732 bool Chain::posStr(const Chain& s1, int& result, int start, int occur) const
733 {
734     int ocount=1;
735     if ( start >=0 )
736     {
737 	for (int i=start; i<_len; i++)
738 	{
739 	    if ( matchAtPos(s1, i) )
740 	    {
741 		if ( ocount == occur )
742 		{
743 		    result = i + 1;
744 		    return true;
745 		}
746 		else
747 		    ocount++;
748 	    }
749 	}
750     }
751     else
752     {
753 	for (int i=_len-1; i>0; i--)
754 	{
755 	    if ( matchAtPos(s1, i) )
756 	    {
757 		if ( ocount == occur )
758 		{
759 		    result = i + 1;
760 		    return true;
761 		}
762 		else
763 		    ocount++;
764 	    }
765 	}
766     }
767     return false;
768 }
769 
matchAtPos(const Chain & s1,int pos) const770 bool Chain::matchAtPos(const Chain& s1, int pos) const
771 {
772     if ( _buf[pos] == s1[0] )
773     {
774 	int j=0;
775 	bool match = true;
776 	while (match && j < s1.length()-1 && pos+j < _len)
777 	{
778 	    if ( _buf[pos+j] != s1[j] )
779 	    {
780 		match = false;
781 	    }
782 	    else
783 	    {
784 		j++;
785 	    }
786 	}
787 	if (match && j == s1.length()-1)
788 	{
789 	    return true;
790 	}
791     }
792 
793     return false;
794 }
795 
replace(const Chain & s1,const Chain & s2,Chain & result) const796 bool Chain::replace(const Chain& s1, const Chain& s2, Chain& result) const
797 {
798     for (int i=0; i<_len; i++)
799     {
800 	if ( _buf[i] == s1[0] )
801 	{
802 	    int j=0;
803 	    bool match = true;
804 	    while (match && j < s1.length()-1 && i+j < _len)
805 	    {
806 		if ( _buf[i+j] != s1[j] )
807 		{
808 		    match = false;
809 		}
810 		else
811 		{
812 
813 		    j++;
814 		}
815 	    }
816 	    if (match && j == s1.length()-1)
817 	    {
818 
819 		Chain a, c;
820 		if (i > 0)
821 		{
822 		    a = subChain(1,i);
823 		}
824 		if (i+j < _len)
825 		{
826 		    c = subChain(i+1+j, _len);
827 		}
828 
829 		result = a + s2 + c;
830 
831 		return true;
832 	    }
833 	}
834     }
835     return false;
836 }
837 
replaceAll(const Chain & s1,const Chain & s2,Chain & result) const838 int Chain::replaceAll(const Chain& s1, const Chain& s2, Chain& result) const
839 {
840     Chain target;
841     int count=0;
842     int l=0;
843     Chain c;
844     int i=0;
845     while( i<_len )
846     {
847         if ( _buf[i] == s1[0] )
848         {
849             int j=0;
850             bool match = true;
851             while (match && j < s1.length()-1 && i+j < _len)
852             {
853                 if ( _buf[i+j] != s1[j] )
854                 {
855                     match = false;
856                 }
857                 else
858                 {
859                     j++;
860                 }
861             }
862             if (match && j == s1.length()-1)
863             {
864                 Chain a;
865                 if (i > l)
866                 {
867                     a = subChain(l+1,i);
868                 }
869                 if (i+j < _len)
870                 {
871                     c = subChain(i+j+1, _len);
872                 }
873                 target += a + s2;
874                 count++;
875                 l=i+j;
876                 i=l;
877             }
878 	    else
879 	    {
880 		i++;
881 	    }
882         }
883         else
884         {
885 	    i++;
886         }
887     }
888     target += c;
889 
890     if ( count > 0 )
891         result = target;
892     else
893         result = *this;
894     return count;
895 }
896 
setChar(int i,char c)897 void Chain::setChar(int i, char c)
898 {
899     _buf[i] = c;
900 }
901 
getHashPos(int hashSize) const902 int Chain::getHashPos(int hashSize) const
903 {
904     int val=0;
905     for ( int i=0; i<_len; i++)
906     {
907 	val += (int)_buf[i] ;
908     }
909     return ( val * ( hashSize / 100 + 1))  % hashSize;
910 }
911 
subChain(int l,int u) const912 Chain Chain::subChain(int l, int u) const
913 {
914 
915     if (l >= 0 && u <= _len && l <= u)
916     {
917 	char *tmpBuf = (char*)malloc(u-l+2);
918 
919 	if ( _buf == 0 )
920 	{
921 	    throw Exception(EXLOC, "Malloc system error");
922 	}
923 	else
924 	{
925 	    memcpy(tmpBuf,(char*)(this->_buf+l-1), u-l+1);
926 	    tmpBuf[u-l+1]='\0';
927 	    Chain tmpChain(tmpBuf);
928 	    free(tmpBuf);
929 	    return tmpChain;
930 	}
931     }
932     else
933     {
934 	throw Exception(EXLOC, "String position exceeded");
935     }
936 }
937 
operator [](int i) const938 char Chain::operator [] (int i) const
939 {
940     if (i < _len)
941     {
942 	return _buf[i];
943     }
944     else
945     {
946 	throw Exception(EXLOC, "String position exceeded");
947     }
948 }
949 
operator char*() const950 Chain::operator char* () const
951 {
952     return _buf;
953 }
954 
operator =(const Chain & str)955 Chain& Chain::operator=(const Chain& str)
956 {
957 
958     if (str._len == 0)
959     {
960 	if (_len > 0)
961 	{
962 	    if ( _buf != 0 && _buf != _staticBuf )
963 		free(_buf);
964 	    _buf = 0;
965 	    _len = 0;
966 	}
967     }
968     else if ( str._len <= _len)
969     {
970 	strcpy (_buf, str._buf);
971 	_len = str._len;
972     }
973     else
974     {
975 
976 	if (_len > 0)
977 	{
978 	    if ( _buf != 0 && _buf != _staticBuf )
979 		free(_buf);
980 	    _buf = 0;
981 	    _len = 0;
982 	}
983 
984 	if ( str._len + 1 < STATICBUFSIZE )
985 	{
986 	    _buf = _staticBuf;
987 	}
988 	else
989 	{
990 
991 	    _buf = (char*)malloc(str._len + 1);
992 
993 	    if ( _buf == 0 )
994 	    {
995 		throw Exception(EXLOC, "Malloc system error");
996 	    }
997 	}
998 
999 	strcpy(_buf, str._buf);
1000 	_len=str._len;
1001     }
1002     return (*this);
1003 }
1004 
operator +=(const Chain & str)1005 Chain& Chain::operator += (const Chain& str)
1006 {
1007 
1008     if ( str._len == 0 )
1009     {
1010 	// nothing to do
1011     }
1012     else if ( _len == 0 )
1013     {
1014 	*this = str; // just copy
1015     }
1016     else
1017     {
1018 
1019 	if ( _len + str._len - 1 < STATICBUFSIZE )
1020 	{
1021 	    strcpy((char*)(_buf + _len - 1), str._buf);
1022 	    _len = _len + str._len -1;
1023 	}
1024 	else
1025 	{
1026 	    char *tmpBuf = (char*)malloc(_len + str._len -1);
1027 	    if ( tmpBuf == 0 )
1028 	    {
1029 		throw Exception(EXLOC, "Malloc system error");
1030 	    }
1031 
1032 	    strcpy(tmpBuf, _buf);
1033 
1034 	    if ( _buf != _staticBuf )
1035 		free(_buf);
1036 
1037 	    _buf = tmpBuf;
1038 	    strcpy((char*)(_buf + _len - 1), str._buf);
1039 	    _len = _len + str._len -1;
1040 
1041 	}
1042     }
1043 
1044     return (*this);
1045 }
1046 
operator ==(const Chain & str) const1047 bool Chain::operator==(const Chain& str) const
1048 {
1049 
1050     if (str._buf && _buf)
1051     {
1052 	if (!strcmp(str._buf, _buf))
1053 	{
1054 	    return(true);
1055 	}
1056 	return (false);
1057     }
1058     return ( str._buf == _buf );
1059 }
1060 
operator !=(const Chain & str) const1061 bool Chain::operator!=(const Chain& str) const
1062 {
1063     if (str._buf && _buf)
1064     {
1065 	if (strcmp(str._buf, _buf))
1066 	{
1067 
1068 	    return(true);
1069 	}
1070 	return (false);
1071     }
1072     return ( str._buf != _buf );
1073 }
1074 
operator <(const Chain & str) const1075 bool Chain::operator < (const Chain& str) const
1076 {
1077     if (str._buf && _buf)
1078     {
1079 	if (strcmp(str._buf, _buf) > 0)
1080 	{
1081 	    return(true);
1082 	}
1083 	return (false);
1084     }
1085     return ( str._buf != _buf );
1086 }
1087 
operator >(const Chain & str) const1088 bool Chain::operator > (const Chain& str) const
1089 {
1090     if (str._buf && _buf)
1091     {
1092 	if (strcmp(str._buf, _buf) < 0 )
1093 	{
1094 
1095 	    return(true);
1096 	}
1097 	return (false);
1098     }
1099     return ( str._buf != _buf );
1100 }
1101 
operator <=(const Chain & str) const1102 bool Chain::operator <= (const Chain& str) const
1103 {
1104     if (str._buf && _buf)
1105     {
1106 	if (strcmp(str._buf, _buf) >= 0)
1107 	{
1108 	    return(true);
1109 	}
1110 	return (false);
1111     }
1112     return ( str._buf != _buf );
1113 }
1114 
operator >=(const Chain & str) const1115 bool Chain::operator >= (const Chain& str) const
1116 {
1117     if (str._buf && _buf)
1118     {
1119 	if (strcmp(str._buf, _buf) <= 0 )
1120 	{
1121 	    return(true);
1122 	}
1123 	return (false);
1124     }
1125     return ( str._buf != _buf );
1126 }
1127 
operator +(const Chain & str1,const Chain & str2)1128 Chain operator+( const Chain& str1, const Chain& str2)
1129 {
1130     Chain str3;
1131     str3 = str1;
1132     str3 += str2;
1133     return (str3);
1134 }
1135 
operator <<(ostream & s,const Chain & str)1136 ostream& operator << (ostream& s, const  Chain& str)
1137 {
1138     if ( str._buf != 0)
1139 	s << str._buf;
1140     return s;
1141 }
1142 
operator >>(istream & s,Chain & str)1143 istream& operator >> (istream& s,  Chain& str)
1144 {
1145     char buf[INBUFSIZE];
1146     cin.getline(buf, INBUFSIZE);
1147     str = Chain(buf);
1148     return s;
1149 }
1150