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 }