1 //#**************************************************************
2 //#
3 //# filename:             mystring.cpp
4 //#
5 //# author:               Gerstmayr Johannes
6 //#
7 //# generated:            20.05.97
8 //# description:          Variable size string class
9 //# remarks:						  This class has been developed, because at that time there was
10 //#												no powerful string class available for UNIX-machines.
11 //#												However, CString of Microsoft VS.NET can do the same!
12 //#												Note that a string with n characters has 0..n-1 characters
13 //#												that there is a '0C' at position n+1 (length=n)
14 //#
15 //# Copyright (c) 2003-2013 Johannes Gerstmayr, Linz Center of Mechatronics GmbH, Austrian
16 //# Center of Competence in Mechatronics GmbH, Institute of Technical Mechanics at the
17 //# Johannes Kepler Universitaet Linz, Austria. All rights reserved.
18 //#
19 //# This file is part of HotInt.
20 //# HotInt is free software: you can redistribute it and/or modify it under the terms of
21 //# the HOTINT license. See folder 'licenses' for more details.
22 //#
23 //# bug reports are welcome!!!
24 //# WWW:		www.hotint.org
25 //# email:	bug_reports@hotint.org or support@hotint.org
26 //#**************************************************************
27 
28 //#include "stdafx.h" //for comment out
29 //#include "../WorkingModule/stdafx.h"
30 //#include <stdafx.h> //$!AD 2011-04-01 changed line such that tool:data_reader can compile... in case of error: add "../WorkingModule" to include path
31 
32 #include "ioincludes.h"
33 #include <string.h>
34 #include <math.h>
35 
36 #include "mystring.h"
37 
38 
39 extern void TIMBSWarningHandle(const char* warn, int use_instant_message_text);
40 
41 
DefaultStringErrHandler()42 void DefaultStringErrHandler()
43 {
44 	cerr << "ERROR: Invalid access to String-element!!!\n" << flush;
45 	//TIMBSWarningHandle(mystr("ERROR: Invalid access to String-element!!!\n"),1);
46 }
47 
48 void (*mystr::ErrHandler)() = DefaultStringErrHandler;
49 
mystr()50 mystr::mystr()
51 {
52 	length = 0;
53 	str = new char[1];
54 	str[0] = (char)0;
55 }
56 
mystr(const char * s)57 mystr::mystr(const char *s)
58 {
59 	length = strlen(s);
60 	str = new char[length + 1];
61 	strcpy(str, s);
62 }
63 
mystr(char s)64 mystr::mystr(char s)
65 {
66 	length = 1;
67 	str = new char[2];
68 	str[0] = s;
69 	str[1] = (char)0;
70 }
71 
mystr(const mystr & s)72 mystr::mystr(const mystr& s)
73 {
74 	length = s.length;
75 	str = new char[length + 1];
76 	strcpy(str, s.str);
77 }
78 
mystr(int i)79 mystr::mystr(int i)
80 {
81 	char buffer[32];
82 	sprintf_s(buffer, "%d", i);
83 	length = strlen(buffer);
84 	str = new char[length + 1];
85 	strcpy(str, buffer);
86 }
87 
mystr(long l)88 mystr::mystr(long l)
89 {
90 	char buffer[32];
91 	sprintf_s(buffer, "%ld", l);
92 	length = strlen(buffer);
93 	str = new char[length + 1];
94 	strcpy(str, buffer);
95 }
96 
mystr(double d)97 mystr::mystr(double d)
98 {
99 	char buffer[32];
100 	if (fabs(d) < 1E-100) {d = 0;}
101 	sprintf_s(buffer, "%g", d);
102 	length = strlen(buffer);
103 	str = new char[length + 1];
104 	strcpy(str, buffer);
105 }
106 
mystr(double d,int prec)107 mystr::mystr(double d, int prec) // with prec == significant digits
108 {
109 	char buffer[32];
110 	if (fabs(d) < 1E-100) {d = 0;}
111 	sprintf_s(buffer, "%.*g", prec+1,  d); //
112 	length = strlen(buffer);
113 	str = new char[length + 1];
114 	strcpy(str, buffer);
115 }
116 
mystr(int n,int)117 mystr::mystr(int n, int)
118 {
119 	length = n;
120 	str = new char[n + 1];
121 	str[n] = 0;
122 }
123 
Left(int r)124 mystr mystr::Left(int r)
125 {
126 	if(r > length)
127 	{
128 		mystr::ErrHandler();
129 		mystr s;
130 		return s;
131 	}
132 	else
133 	{
134 		mystr tmp(r, 0);
135 		strncpy(tmp.str, str, r);
136 		return tmp;
137 	}
138 }
139 
Right(int l)140 mystr mystr::Right(int l)
141 {
142 	if(l > length)
143 	{
144 		mystr::ErrHandler();
145 		mystr s;
146 		return s;
147 	}
148 	else
149 	{
150 		mystr tmp(l, 0);
151 		strncpy(tmp.str, str + length - l, l);
152 		return tmp;
153 	}
154 }
155 
156 //inclusive the char at pos1 and pos2 (if pos1=pos2 one char is taken)
SubString(int pos1,int pos2) const157 mystr mystr::SubString(int pos1, int pos2) const
158 {
159 	if (pos1<Length() && pos2 <Length() && pos1 <= pos2)
160 	{
161 		int l = pos2-pos1+1;
162 		mystr tmp(l, 0);
163 
164 		if (l!=0)
165 			strncpy(tmp.str, str + pos1, l);
166 
167 		return tmp;
168 	}
169 	else
170 	{
171 		mystr::ErrHandler();
172 		mystr s;
173 		return s;
174 	}
175 }
176 
CopySubStringNoSpaces(char * deststr,int pos1,int pos2,int limit)177 void mystr::CopySubStringNoSpaces(char* deststr, int pos1, int pos2, int limit)
178 {
179 	int j = 0;
180 	if (pos1<Length() && pos2 <Length() && pos1 <= pos2)
181 	{
182 		int l = pos2-pos1+1;
183 		for (int i=pos1; i <= pos2; i++)
184 		{
185 			if (j < limit-1 && !IsSpace(str[i]))
186 			{
187 				deststr[j++] = str[i];
188 			}
189 		}
190 		deststr[j] = (char)0;
191 	}
192 	else
193 	{
194 		mystr::ErrHandler();
195 	}
196 }
197 
198 //0-based pos!!! reads over leading spaces and moves pos to position after spaces, returns char at current position, pos=-1 for end of string
ReadLeadingSpaces(int & pos) const199 char mystr::ReadLeadingSpaces(int& pos) const
200 {
201 	int endit = 0;
202 	char ch=(char)0;
203 
204 	while(!endit) //read leading spaces, line feeds and carriage returns!
205 	{
206 		if (pos >= Length())
207 		{
208 			pos = -1;
209 			return (char)0;
210 		}
211 		ch = str[pos];
212 		if (!IsSpace(ch)) {endit = 1;}
213 		else {pos++;}
214 	}
215 	return ch;
216 }
217 
218 //0-based pos!!! reads over leading spaces and moves pos to position after spaces, returns char at current position, pos=-1 for end of string
219 //count lines in linecnt
ReadLeadingSpacesAndCountLines(int & pos,int & linecnt) const220 char mystr::ReadLeadingSpacesAndCountLines(int& pos, int& linecnt) const
221 {
222 	int endit = 0;
223 	char ch=(char)0;
224 
225 	while(!endit) //read leading spaces, line feeds and carriage returns!
226 	{
227 		if (pos >= Length())
228 		{
229 			pos = -1;
230 			return (char)0;
231 		}
232 		ch = str[pos];
233 		if (!IsSpace(ch)) {endit = 1;}
234 		else {pos++;}
235 		if (IsEOL(ch)) {linecnt++;}
236 	}
237 	return ch;
238 }
239 
240 //0-based pos!!! returns word and moves pos to position after delimiter or -1 for end of string
GetWord(int & pos,int incl_delimiter)241 mystr mystr::GetWord(int& pos, int incl_delimiter)
242 {
243 	mystr s;
244 	char sbuf[102];
245 	int endit = 0;
246 	char ch=(char)0;
247 
248 	//ch = ReadLeadingSpaces(pos); pos++
249 	while(!endit) //read leading spaces, line feeds and carriage returns!
250 	{
251 		if (pos >= Length())
252 		{
253 			pos = -1;
254 			return s;
255 		}
256 		ch = str[pos];
257 		if (!IsSpace(ch)) {endit = 1;}
258 		pos++;
259 	}
260 
261 	sbuf[0] = ch;
262 
263 	endit = 0;
264 	int bufpos = 1;
265 	while(!endit) //read word
266 	{
267 		if (pos >= Length()) {pos = -1; endit = 1;}
268 		else
269 		{
270 			ch = str[pos];
271 
272 			if (IsWordDelimiter(ch))
273 			{
274 				endit = 1;
275 				if (incl_delimiter)
276 				{
277 					sbuf[bufpos] = ch;
278 					bufpos++;
279 					pos++;
280 				}
281 			}
282 			else
283 			{
284 				if (bufpos >= 100) //100 !!!!!!!!!!!!
285 				{
286 					sbuf[bufpos] = (char)0;
287 					bufpos = 0;
288 					s += sbuf;
289 				}
290 				sbuf[bufpos] = ch;
291 				bufpos++;
292 				pos++;
293 			}
294 		}
295 	}
296 	sbuf[bufpos] = (char)0;
297 	s += sbuf;
298 	return s;
299 }
300 
301 //0-based pos!!! returns word and moves pos to position after delimiter or -1 for end of string
GetIdentifier(int & pos,int incl_delimiter)302 mystr mystr::GetIdentifier(int& pos, int incl_delimiter)
303 {
304 	mystr s;
305 	char sbuf[102];
306 	int endit = 0;
307 	char ch=(char)0;
308 
309 	//ch = ReadLeadingSpaces(pos); pos++
310 	while(!endit) //read leading spaces, line feeds and carriage returns!
311 	{
312 		if (pos >= Length())
313 		{
314 			pos = -1;
315 			return s;
316 		}
317 		ch = str[pos];
318 		if (!IsSpace(ch)) {endit = 1;}
319 		pos++;
320 	}
321 
322 	sbuf[0] = ch;
323 
324 	endit = 0;
325 	int bufpos = 1;
326 	while(!endit) //read word
327 	{
328 		if (pos >= Length()) {pos = -1; endit = 1;}
329 		else
330 		{
331 			ch = str[pos];
332 
333 			if (IsWordDelimiterIdentifier(ch))
334 			{
335 				endit = 1;
336 				if (incl_delimiter)
337 				{
338 					sbuf[bufpos] = ch;
339 					bufpos++;
340 					pos++;
341 				}
342 			}
343 			else
344 			{
345 				if (bufpos >= 100) //100 !!!!!!!!!!!!
346 				{
347 					sbuf[bufpos] = (char)0;
348 					bufpos = 0;
349 					s += sbuf;
350 				}
351 				sbuf[bufpos] = ch;
352 				bufpos++;
353 				pos++;
354 			}
355 		}
356 	}
357 	sbuf[bufpos] = (char)0;
358 	s += sbuf;
359 	return s;
360 }
361 
362 //reads string in brackets, counting opening and closing brackets, -1 if no success
363 //works for infinitely many levels (stack limit)
364 //startpos must point at opening bracket
365 //pos finally points at position after cb
366 //also works for quotation marks "text", but only one level ...
GetStringInBrackets(int & startpos,char ob,char cb) const367 mystr mystr::GetStringInBrackets(int& startpos, char ob, char cb) const
368 {
369 	int pos = startpos;
370 	int bracketcnt = 1;
371 
372 	if (str[pos] != ob)
373 	{
374 		startpos = -1;
375 		return mystr();
376 	}
377 	pos++;
378 
379 	while (pos < Length() && bracketcnt != 0)
380 	{
381 		if (str[pos] == cb) bracketcnt--;
382 		else if (str[pos] == ob) bracketcnt++;
383 		pos++;
384 	}
385 	if (bracketcnt != 0)
386 	{
387 		startpos = -1;
388 		return mystr();
389 	}
390 
391 	int pos1 = startpos;
392 	startpos = pos;
393 	return SubString(pos1+1,pos-2);
394 }
395 
PosGet(int & pos) const396 char mystr::PosGet(int& pos) const //returns char and increments position 'pos' (or sets -1 if end of string)
397 {
398 	char c = str[pos++];
399 	if (pos >= Length()) pos = -1;
400 	return c;
401 }
PosPeek(int & pos) const402 char mystr::PosPeek(int& pos) const //returns char at position 'pos'
403 {
404 	return str[pos];
405 }
GetUntil(int & pos,char until,mystr & s,int incl_delimiter) const406 int mystr::GetUntil(int& pos, char until, mystr& s, int incl_delimiter) const //returns string between 'pos' and char 'until', increments pos to after until, sets -1 if end of string
407 {
408 	int rv = 1;
409 	s = "";
410 	int endit = 0;
411 	char sbuf[1002];
412 	char ch=(char)0;
413 
414 	int bufpos = 0;
415 	while(!endit)
416 	{
417 		if (pos >= Length())
418 		{
419 			pos = -1;
420 			endit = 1;
421 			rv = 0;
422 		}
423 		else
424 		{
425 			ch = str[pos];
426 
427 			if (ch == until)
428 			{
429 				endit = 1;
430 				if (incl_delimiter)
431 				{
432 					sbuf[bufpos] = ch;
433 					bufpos++;
434 					pos++;
435 				}
436 			}
437 			else
438 			{
439 				if (bufpos >= 1000) //1000 !!!!!!!!!!!!
440 				{
441 					sbuf[bufpos] = (char)0;
442 					bufpos = 0;
443 					s += sbuf;
444 				}
445 				sbuf[bufpos] = ch;
446 				bufpos++;
447 				pos++;
448 			}
449 		}
450 	}
451 	sbuf[bufpos] = (char)0;
452 	s += sbuf;
453 	return rv;
454 }
455 
GetUntilEOL(int & pos,char until,mystr & s,int incl_delimiter) const456 int mystr::GetUntilEOL(int& pos, char until, mystr& s, int incl_delimiter) const //returns string between 'pos' and char 'until', increments pos to after until, sets -1 if end of string; if end of file return 0, if until found return 2, else return 1
457 {
458 	int rv = 1;
459 	s = "";
460 	int endit = 0;
461 	char sbuf[1002];
462 	char ch=(char)0;
463 
464 	int bufpos = 0;
465 	while(!endit)
466 	{
467 		if (pos >= Length())
468 		{
469 			pos = -1;
470 			endit = 1;
471 			rv = 0;
472 		}
473 		else
474 		{
475 			ch = str[pos];
476 
477 			if ((ch == until && until != (char)0) || IsEOL(ch))
478 			{
479 				endit = 1;
480 				if (incl_delimiter)
481 				{
482 					sbuf[bufpos] = ch;
483 					bufpos++;
484 					pos++;
485 				}
486 				if ((ch == until && until != (char)0)) rv = 2;
487 			}
488 			else
489 			{
490 				if (bufpos >= 1000) //1000 !!!!!!!!!!!!
491 				{
492 					sbuf[bufpos] = (char)0;
493 					bufpos = 0;
494 					s += sbuf;
495 				}
496 				sbuf[bufpos] = ch;
497 				bufpos++;
498 				pos++;
499 			}
500 		}
501 	}
502 	sbuf[bufpos] = (char)0;
503 	s += sbuf;
504 	return rv;
505 }
506 
GoUntil(int & pos,char until) const507 int mystr::GoUntil(int& pos, char until) const //moves 'pos' till char 'until', increments pos to after until, sets -1 if end of string
508 {
509 	while (1)
510 	{
511 		if (str[pos] == until)
512 		{
513 			pos++;
514 			if (pos>=Length()) pos = -1;
515 			return 1;
516 		}
517 		pos++;
518 		if (pos>=Length())
519 		{
520 			pos = -1;
521 			return 0;
522 		}
523 	}
524 	return 0;
525 }
526 
EraseSpaces()527 void mystr::EraseSpaces()
528 {
529 	int i = 0;
530 	int pos = 0;
531 	for (i = 0; i < length; i++)
532 	{
533 		str[pos] = str[i];
534 		//if (str[i] != ' ' && str[i] != (char)10 && str[i] != '\n') //old
535 		if (!IsSpace(str[i])) pos++;
536 	}
537 	str[pos] = 0;
538 	length = pos;
539 }
540 
EraseSpacesHeadTail()541 void mystr::EraseSpacesHeadTail()
542 {
543 // tail
544 	int pos = length-1;
545 	while (IsSpace(str[pos]))
546 		pos--;
547 	length = pos+1;
548 	str[length] = 0;
549 
550 //head
551 	pos = 0;
552 	while (IsSpace(str[pos]))
553 		pos++;
554 	for(int i=0; i <= length-pos; i++)
555 	  str[i] = str[i+pos];
556 	length = length - pos;
557 
558 }
559 
560 // returns position of first and last non-space letter (1-based)
IdentifySpacesHeadTail(int & first,int & last)561 void mystr::IdentifySpacesHeadTail(int& first, int& last)
562 {
563 // tail
564 	last = length;
565 	while (IsSpace(str[last-1]))
566 		last--;
567 //head
568 	first = 1;
569 	while (IsSpace(str[first-1]))
570 		first++;
571 }
572 
EraseChar(char c)573 void mystr::EraseChar(char c)
574 {
575 	int i = 0;
576 	int pos = 0;
577 	for (i = 0; i < length; i++)
578 	{
579 		str[pos] = str[i];
580 		if (str[i] != c)
581 			pos++;
582 	}
583 	str[pos] = 0;
584 	length = pos;
585 }
586 
EraseChar(int pos)587 void mystr::EraseChar(int pos) // 1 based !
588 {
589 	int i = 0;
590 	for (i = pos; i < length; i++)
591 	{
592 		str[i-1] = str[i];
593 	}
594 	str[length-1] = 0;
595 	length--;
596 }
Replace(const mystr & searchstr,const mystr & replacestr)597 int mystr::Replace(const mystr& searchstr, const mystr& replacestr) //find string searchstr, replace with string replacestr; this is done repeatedly; the return value counts the number of replacements
598 {
599 	int slen = searchstr.Length();
600 	int rlen = replacestr.Length();
601 	int pos = 0;
602 	int cnt = 0;
603 	while (pos < Length() && pos != -1)
604 	{
605 		pos = Find(pos, searchstr);
606 		if (pos != -1)
607 		{
608 			cnt++;
609 			for (int i=1; i<=slen; i++)
610 			{
611 				if (pos < Length()) EraseChar(pos+1);
612 			}
613 			InsertAt(pos, replacestr);
614 			pos += rlen;
615 			if (pos >= Length()) pos = -1;
616 		}
617 	}
618 	return cnt;
619 }
620 
InsertAt(int pos,const mystr & s)621 mystr& mystr::InsertAt(int pos, const mystr& s)
622 {
623 	if(pos > length)
624 	{
625 		mystr::ErrHandler();
626 		return *this;
627 	}
628 	int newLength = length + s.length;
629 	char *tmp = new char[newLength + 1];
630 	strncpy(tmp, str, pos);
631 	strcpy(tmp + pos, s.str);
632 	strcpy(tmp + pos + s.length, str + pos);
633 	delete[] str;
634 	length = newLength;
635 	str = tmp;
636 	return *this;
637 }
638 
WriteAt(int pos,const mystr & s)639 mystr &mystr::WriteAt(int pos, const mystr& s)
640 {
641 	if(pos > length)
642 	{
643 		mystr::ErrHandler();
644 		return *this;
645 	}
646 	int n = length - pos;
647 	if(s.length < n)
648 		n = s.length;
649 	strncpy(str + pos, s.str, n);
650 	return *this;
651 }
652 
SmartDouble2String(double x,int nDigits)653 void mystr::SmartDouble2String(double x, int nDigits)
654 {
655 	delete[] str;
656 
657 	char buffer[32];
658 	char buffer2[32];
659 
660 	if (fabs(x) < 1E-100) {x = 0;}
661 	sprintf_s(buffer, "%.14g", x);
662 	int slen1 = strlen(buffer);
663 	sprintf_s(buffer2, "%.16g", x);
664 	int slen2 = strlen(buffer2);
665 
666 	if(nDigits) //$ DR 2013-03-11: added in order to control the significant digits
667 	{
668 		mystr format = mystr("%.")+mystr(nDigits)+("g");
669 		sprintf_s(buffer,format,x);
670 		length = strlen(buffer);
671 		str = new char[length + 1];
672 		strcpy(str, buffer);
673 	}
674 	else	// original code
675 	{
676 		if (slen1 + 4 < slen2)
677 		{
678 			length = slen1;
679 			str = new char[length + 1];
680 			strcpy(str, buffer);
681 		}
682 		else
683 		{
684 			length = slen2;
685 			str = new char[length + 1];
686 			strcpy(str, buffer2);
687 		}
688 	}
689 }
690 
691 // $EK - 2013-01-17: added in order to resize (including memory reallocation) the string
ReSize(int len)692 void mystr::ReSize(int len)
693 {
694 	delete[] str;
695 	length = len;
696 	str = new char[len + 1];
697 	str[len] = (char)0;
698 }
699 
operator =(const mystr & s)700 mystr& mystr::operator = (const mystr& s)
701 {
702 	if (&s != this)
703 	{
704 		delete[] str;
705 		length = s.length;
706 		str = new char[length + 1];
707 		strcpy(str, s.str);
708 	}
709 	return *this;
710 }
711 
operator +(const mystr & s1,const mystr & s2)712 mystr operator + (const mystr& s1, const mystr& s2)
713 {
714 	mystr tmp(s1.length + s2.length, 0);
715 	if (s1.length != 0) strcpy(tmp.str, s1.str);
716 	if (s2.length != 0) strcpy(tmp.str + s1.length, s2.str);
717 	return tmp;
718 }
719 
operator +=(const mystr & s)720 void mystr::operator += (const mystr& s)
721 {
722 	char *tmp = new char[length + s.length + 1];
723 	if (length != 0) strcpy(tmp, str);
724 	if (s.length != 0) strcpy(tmp + length, s.str);
725 	length += s.length;
726 	delete[] str;
727 	str = tmp;
728 }
729 
operator [](int n)730 char& mystr::operator [] (int n)
731 {
732 	static char dummy;
733 	if(n < length)
734 		return str[n];
735 	else
736 	{
737 		mystr::ErrHandler();
738 		return dummy;
739 	}
740 }
741 
operator [](int n) const742 const char& mystr::operator [] (int n) const
743 {
744 	static char dummy;
745 	if(n < length)
746 		return str[n];
747 	else
748 	{
749 		mystr::ErrHandler();
750 		return dummy;
751 	}
752 }
753 
operator ()(int l,int r) const754 mystr mystr::operator () (int l, int r) const
755 {
756 	if((l > r) || (r > length))
757 	{
758 		mystr::ErrHandler();
759 		mystr s;
760 		return s;
761 	}
762 	else
763 	{
764 		int n = r - l + 1;
765 		mystr tmp(n, 0);
766 		strncpy(tmp.str, str + 1, n);
767 		return tmp;
768 	}
769 }
770 
operator >>(istream & is,mystr & s)771 istream& operator >> (istream& is, mystr& s)
772 {
773 	const int buflen = 1000;
774 	char buffer[buflen+1];
775 
776 	int end = 0;
777 	s = "";
778 	mystr str;
779 
780 	while (!end)
781 	{
782 		is.get(buffer, buflen);
783 		str = mystr(buffer);
784 		s += str;
785 		if (is.peek() == EOF) {end = 1;}
786 	}
787 
788 	return is;
789 }
790 // checks if String can contains a number
791 // removes spaces around first 'E' or 'e' found in string
792 // format of valid number:  [sign][digits][comma][digits][scientific: [ ] E|e [ ][sign]digits ]
793 // optional blanks before and after E in scientific notation
794 // return values:  =1: is a valid number; =0: not a valid number
795 
IsValidNumber()796 int mystr::IsValidNumber()
797 {
798 	this->EraseSpacesHeadTail();
799 // remove all spaces around 'E' and 'e'
800 	int pos = Find('E');
801 	if(pos==-1) pos = Find('e');
802 
803 	if(pos!=-1) // found an 'E' or an 'e'
804 	{
805 		while (str[pos-1] == ' ')
806 		{
807 			EraseChar(pos); // this function is 1 based
808 			pos--;
809 		}
810 		while (str[pos+1] == ' ')
811 		{
812 			EraseChar(pos+2);
813 		}
814 	}
815 
816 // positions at 0 for not found
817 	int pos_dot = 0;      // one dot allowed
818 	int pos_sign1 = 0;    // leading sign
819 	int pos_sign2 = 0;    // sign at floating point exponent
820 	int pos_digit = 0;
821 	int pos_digitexp = 0;
822 	int begin_number = 0;
823 	int begin_exponent = 0;
824 
825 	for(int i=1; i<=length; i++)
826 	{
827 		if(! begin_number) // begin of number
828 		{
829 			if (IsSign(str[i-1]))  { begin_number = i; pos_sign1 = i; }
830 			else if (IsNum(str[i-1]))  { begin_number = i; pos_digit = i; }
831 			else if (IsPoint(str[i-1])) { begin_number = i; pos_dot = i; }
832 			else return 0; // first non-space character is not a valid begin of a number
833 		}
834 		else if (!begin_exponent) // main part of number, before "E" or "e" of schientific notaion
835 		{
836 		 	if(IsNum(str[i-1])) { pos_digit = i; }
837 			else if(IsPoint(str[i-1])) // <-- point allowed only once
838 			{
839 				if (!pos_dot) pos_dot = i;
840 				else return 0; // decimal point for a 2nd time
841 			}
842 			else if (IsScientificE(str[i-1])) begin_exponent = i;
843 			else return 0; // any other character is not valid
844 		}
845 		else // if (begin_exponent)  // (optional) scientific notation
846 		{
847 			if (IsSign(str[i-1])) // <-- sign in exponent allowed only once
848 			{
849 				if (!pos_sign2 && !pos_digitexp) pos_sign2 = i;
850 				else return 0; // sign in exponent for a 2nd time
851 			}
852 			else if (IsNum(str[i-1])) pos_digitexp = i;
853 			else return 0;
854 		}
855 	}
856 	if (! begin_number) return 0; // could be empty string
857 	if (begin_exponent && !pos_digitexp) return 0; // could end with an "E" or "E-" ...
858 	return 1;
859 }
860 
861 
862 
863 
864 // check if the string holds a correct number (one-based)
865 // returns 1 if correct number was found & passes position-limits of number in integers first and last
866 // returns 0 otherwise
IsCorrectNumberBetween(mystr num,int & first,int & last)867 int IsCorrectNumberBetween(mystr num, int& first, int& last)
868 {
869 	num.IdentifySpacesHeadTail(first,last);
870 // positions at 0 for not found
871 	int pos_dot = 0;      // one dot allowed
872 	int pos_sign1 = 0;    // leading sign
873 	int pos_sign2 = 0;    // sign at floating point exponent
874 	int pos_digit = 0;
875 	int pos_digitexp = 0;
876 	int begin_number = 0;
877 	int begin_exponent = 0;
878 
879 
880 	for(int i=first; i<=last; i++)
881 	{
882 		if(! begin_number) // begin of number
883 		{
884 			if (IsSign(num[i-1]))  { begin_number = i; pos_sign1 = i; }
885 			else if (IsNum(num[i-1]))  { begin_number = i; pos_digit = i; }
886 			else if (IsPoint(num[i-1])) { begin_number = i; pos_dot = i; }
887 			else return 0; // first non-space character is not a valid begin of a number
888 		}
889 		else if (!begin_exponent) // main part of number, before "E" or "e" of schientific notaion
890 		{
891 		 	if(IsNum(num[i-1])) { pos_digit = i; }
892 			else if(IsPoint(num[i-1])) // <-- point allowed only once
893 			{
894 				if (!pos_dot) pos_dot = i;
895 				else return 0; // decimal point for a 2nd time
896 			}
897 			else if (IsScientificE(num[i-1])) begin_exponent = i;
898 			else return 0; // any other character is not valid
899 		}
900 		else // if (begin_exponent)  // (optional) scientific notation
901 		{
902 			if (IsSign(num[i-1])) // <-- sign in exponent allowed only once
903 			{
904 				if (!pos_sign2 && !pos_digitexp) pos_sign2 = i;
905 				else return 0; // sign in exponent for a 2nd time
906 			}
907 			else if (IsNum(num[i-1])) pos_digitexp = i;
908 			else return 0;
909 		}
910 	}
911 	if (! begin_number) return 0; // could be empty string
912 	if (begin_exponent && !pos_digitexp) return 0; // could end with an "E" or "E-" ...
913 	return 1;
914 }
915 
Trim_And_Get_Indices(int & comp1,int & comp2)916 int mystr::Trim_And_Get_Indices(int& comp1, int& comp2) // identifies and parses '[..,..]', shortens the string !! returns number of found components
917 {
918 	comp1=0; comp2=0;
919   mystr buff1(32,32);
920   mystr buff2(32,32);
921 
922 	int nr_of_components = Trim_And_Get_Indices(buff1,buff2);
923 	if (nr_of_components==1 || nr_of_components==2) comp1 = buff1.MakeInt();
924 	if (nr_of_components==2) comp2 = buff2.MakeInt();
925 
926 	return nr_of_components;
927 
928  // int pos_of_open_bracket = Find('[');
929 	//if (pos_of_open_bracket == -1) return 0;   // no bracket found
930 
931 	//int pos_of_close_bracket = Find(']');
932  // if (pos_of_close_bracket == -1) return -1; // error
933 
934 	//// identify first component
935 	//int pos=pos_of_open_bracket+1;
936  // mystr buffer = GetWord(pos);
937 	//comp1 = buffer.MakeInt();
938 	//int nr_of_components = 1;
939 
940 	//int pos_of_comma = Find(',');
941 	//if (pos_of_comma > pos_of_open_bracket && pos_of_comma < pos_of_close_bracket && pos_of_comma >= pos)
942 	//{
943 	//	// identify second component
944 	//	pos = pos_of_comma+1;
945 	//	buffer = GetWord(pos);
946 	//	comp2 = buffer.MakeInt();
947 	//	nr_of_components = 2;
948 	//}
949  //
950 	//// trim the string
951 	//SetLength(pos_of_open_bracket);
952 	//this->str[pos_of_open_bracket] = 0;
953 
954 	//return nr_of_components;
955 }
956 
957 //////// DOES NOT WORK WITH MORE THEN ONE BRACKET a[b[1,2]]
958 //////int mystr::Trim_And_Get_Indices(mystr& comp1, mystr& comp2) // identifies and parses '[..,..]', shortens the string !! returns number of found components
959 //////{
960 //////	comp1=0; comp2=0;
961 //////  int pos_of_open_bracket = Find('[');
962 //////	if (pos_of_open_bracket == -1) return 0;   // no bracket found
963 //////
964 //////
965 //////	int pos_of_close_bracket = Find(']');
966 //////  if (pos_of_close_bracket == -1) return -1; // error
967 //////
968 //////	// identify first component
969 //////	int pos=pos_of_open_bracket+1;
970 //////  comp1 = GetWord(pos);
971 //////	int nr_of_components = 1;
972 //////
973 //////	int pos_of_comma = Find(',');
974 //////	if (pos_of_comma > pos_of_open_bracket && pos_of_comma < pos_of_close_bracket && pos_of_comma >= pos)
975 //////	{
976 //////		// identify second component
977 //////		pos = pos_of_comma+1;
978 //////		comp2 = GetWord(pos);
979 //////		nr_of_components = 2;
980 //////	}
981 //////
982 //////	// trim the string
983 //////	SetLength(pos_of_open_bracket);
984 //////	this->str[pos_of_open_bracket] = 0;
985 //////
986 //////	return nr_of_components;
987 //////}
988 
Trim_And_Get_Indices(mystr & comp1,mystr & comp2)989 int mystr::Trim_And_Get_Indices(mystr& comp1, mystr& comp2)
990 {
991 	comp1=0; comp2=0;
992 
993   int nr_open_brac = 0;        // number of open brackets
994 	int pos_of_first_open_bracket = length;
995 	int comp1_start = 0;         // position of beginning of component 1 in full string
996 	int comp1_end = 0;           // position of end on component 1 in full string
997 	int comp2_start = 0;
998 	int comp2_end = 0;
999 
1000 	int pos=0;
1001 	int nr_comp=0;
1002 	while (pos<length)
1003 	{
1004 		if (str[pos]=='[') nr_open_brac++;
1005 		if (str[pos]==']') nr_open_brac--;
1006 
1007 		if (nr_open_brac==1 && str[pos]=='[') { comp1_start = pos+1; nr_comp = 1; pos_of_first_open_bracket = pos;}
1008 		if (nr_open_brac==1 && str[pos]==',') { comp1_end = pos-1, nr_comp = 2; comp2_start = pos+1; }
1009 		if (nr_open_brac==0 && str[pos]==']') { if(nr_comp==1) comp1_end = pos-1; if(nr_comp==2) comp2_end = pos-1; }
1010 
1011 		pos++;
1012 	}
1013 	if (nr_comp==1 || nr_comp==2) comp1 = this->SubString(comp1_start,comp1_end);
1014 	if (nr_comp==2) comp2 = this->SubString(comp2_start,comp2_end);
1015 
1016 // trim the string
1017 	SetLength(pos_of_first_open_bracket);
1018 	this->str[pos_of_first_open_bracket] = 0;
1019 
1020 	return nr_comp;
1021 }
1022 
CountLines()1023 int mystr::CountLines()
1024 {
1025 	//count lines:
1026 	mystr line;
1027 	int pos = 0;
1028 	int eof = 0;
1029 	int total_lines = 0;
1030 	while (!eof && pos != -1)
1031 	{
1032 		total_lines++;
1033 		if (GetUntilEOL(pos, (char)0, line, 1)) eof = 1;
1034 		//pos++;
1035 	}
1036 	return total_lines;
1037 }