NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
tools.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2014 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19
20#include "tools.hpp"
21#include "../../kernel.hpp"
22#include "../io/file.hpp"
23#include <cstdlib>
24#include <omp.h>
25
26
34{
35 private:
36 std::vector<std::mt19937> m_randGenArray;
37
38 public:
46 {
47 double t = time(0);
48
49 for (int i = 0; i < omp_get_max_threads(); i++)
50 {
51 m_randGenArray.push_back(std::mt19937(t+i));
52 }
53 }
54
62 std::mt19937& getGenerator()
63 {
64 int threadId = omp_get_thread_num();
65
66 if (threadId >= (int)m_randGenArray.size())
67 throw std::out_of_range("Requested a random number generator for thread " + std::to_string(threadId)
68 + ", which is larger than the number of available generators (i.e. "
69 + std::to_string(m_randGenArray.size()) + ")");
70
71 return m_randGenArray[threadId];
72 }
73
74};
75
76
80
81
91std::mt19937& getRandGenInstance()
92{
94}
95
96using namespace std;
97
113int findParameter(const string& sCmd, const string& sParam, const char cFollowing)
114{
115 // --> Wenn kein '-' im string zu finden ist, ist da auch kein Parameter: FALSE zurueckgeben <--
116 if (sCmd.find('-') == string::npos)
117 return 0;
118 else
119 {
120 // There's a minus sign.
121 // Transform everything to lower case to avoid case sensitivity
122 string __sCmd = toLowerCase(sCmd + " ");
123 int nQuotes = 0;
124 size_t nParamStart = string::npos;
125 bool isOptionValue = false;
126
127 // Go through the complete string
128 for (size_t i = 0; i < __sCmd.length(); i++)
129 {
130 // Count the quotation marks, so that we're not inside of a string
131 if (__sCmd[i] == '"'
132 && (!i || (i && __sCmd[i - 1] != '\\')))
133 nQuotes++;
134
135 // If all quotation marks are pairs and we found a minus sign, then we're probably at the start of a parameter
136 if (!(nQuotes % 2) && __sCmd[i] == '-' && nParamStart == string::npos)
137 {
138 nParamStart = i;
139 }
140
141 // Detect option values and force NumeRe to ignore
142 // them in this context
143 if (nParamStart != string::npos
144 && !(nQuotes % 2)
145 && !isOptionValue
146 && __sCmd[i] == '=')
147 {
148 isOptionValue = true;
149
150 // jump over the following white spaces
151 while (i+1 < __sCmd.length() && __sCmd[i+1] == ' ')
152 i++;
153 }
154 else if (nParamStart != string::npos
155 && !(nQuotes % 2)
156 && isOptionValue
157 && __sCmd[i] == ' ')
158 isOptionValue = false;
159
160 // If we found a paramter start and the substring with the length of the searched parameter
161 // is matching to the searched parameter, then we go into this block
162 if (nParamStart != string::npos
163 && !(nQuotes % 2)
164 && !isOptionValue
165 && __sCmd.substr(i, sParam.length()) == toLowerCase(sParam))
166 {
167 /* --> Pruefe die Zeichen davor und danach (unter Beachtung eines moeglicherweise
168 * speziell gewaehlten Zeichens) <--
169 * --> Ein Parameter darf auf jeden Fall kein Teil eines anderen, laengeren Wortes
170 * sein <--
171 */
172 if (cFollowing == ' ')
173 {
174 // Examine the characters before and after the found parameter match
175 if ((__sCmd[i - 1] == ' '
176 || __sCmd[i - 1] == '-')
177 && (__sCmd[i + sParam.length()] == ' '
178 || __sCmd[i + sParam.length()] == '-'
179 || __sCmd[i + sParam.length()] == '='
180 || __sCmd[i + sParam.length()] == '"')
181 )
182 {
183 // Avoid the identification of an option value as parameter
184 if (__sCmd[i - 1] == ' ' && __sCmd[__sCmd.find_last_not_of(' ', i - 1)] == '=')
185 i += sParam.length() - 1; // Add the parameter length to the loop index and continue
186 else
187 return i + 1; // i+1 zurueckgeben, wenn Treffer
188 }
189 else
190 i += sParam.length() - 1; // Positionsindex um die Laenge des Parameters weitersetzen
191 }
192 else
193 {
194 // --> Wenn ein spezielles Zeichen gewaehlt wurde, wird dies hier gesucht <--
195 if ((__sCmd[i - 1] == ' ' || __sCmd[i - 1] == '-')
196 && (__sCmd[i + sParam.length()] == cFollowing))
197 {
198 // The following char matches explicit to the searched character
199 // Avoid the identification of an option value as parameter
200 if (__sCmd[i - 1] == ' ' && __sCmd[__sCmd.find_last_not_of(' ', i - 1)] == '=')
201 i += sParam.length() - 1;
202 else
203 return i + 1;
204 }
205 else if ((__sCmd[i - 1] == ' ' || __sCmd[i - 1] == '-')
206 && (__sCmd[i + sParam.length()] == ' '))
207 {
208 // The following character is a white space. We'll handle that further down
209 // First ensure that we did't find an option value
210 if (__sCmd[i - 1] == ' ' && __sCmd[__sCmd.find_last_not_of(' ', i - 1)] == '=')
211 i += sParam.length() - 1;
212 else
213 {
214 /* --> Fehlertoleranz: Leerzeichen zwischen dem Parameter und cFollowing werden ignoriert
215 * (wenn cFollowing sowieso ein Leerzeichen sein sollte, wurde das ohnehin vorhin schon abgefangen) <--
216 */
217 int nSkip = 0;
218 while (i + sParam.length() + nSkip < __sCmd.length() && __sCmd[i + sParam.length() + nSkip] == ' ')
219 nSkip++;
220 if (__sCmd[i + sParam.length() + nSkip] == cFollowing)
221 return i + 1 + nSkip; // Wir addieren nSkip, da der Rueckgabewert vorzugsweise zum Navigieren zum Ende des Parameters verwendet wird
222 else
223 i += sParam.length() - 1;
224 }
225 }
226 else
227 i += sParam.length() - 1;
228 }
229 }
230 }
231 }
232
233 // --> Wenn nichts gefunden wurde, gib' FALSE zurueck <--
234 return 0;
235}
236
237
250bool getStringArgument(const string& sCmd, string& sArgument)
251{
252 size_t nPos = 0;
253
254 // --> Wenn kein '"' oder kein '#' zu finden ist, gibt es auch kein String-Argument: FALSE zurueckgeben <--
255 if (!containsStrings(sCmd))
256 return false;
257
258 if (sCmd.front() != '=')
259 {
260 // If the first character is not an equal sign, then try to find the first string operation part
261 // This block only handles a small set of all available string functions
262 nPos = sCmd.find('"');
263
264 if (sCmd.find('#') != string::npos && (sCmd.find('#') < nPos || nPos == string::npos))
265 nPos = sCmd.find('#');
266
267 if (sCmd.find("to_string(") != string::npos && (sCmd.find("to_string(") < nPos || nPos == string::npos))
268 nPos = sCmd.find("to_string(");
269
270 if (sCmd.find("string(") != string::npos && (sCmd.find("string(") < nPos || nPos == string::npos))
271 nPos = sCmd.find("string(");
272
273 if (sCmd.find("substr(") != string::npos && (sCmd.find("substr(") < nPos || nPos == string::npos))
274 nPos = sCmd.find("substr(");
275
276 if (sCmd.find("strlen(") != string::npos && (sCmd.find("strlen(") < nPos || nPos == string::npos))
277 nPos = sCmd.find("strlen(");
278
279 if (sCmd.find("strfnd(") != string::npos && (sCmd.find("strfnd(") < nPos || nPos == string::npos))
280 nPos = sCmd.find("strfnd(");
281
282 if (sCmd.find("ascii(") != string::npos && (sCmd.find("ascii(") < nPos || nPos == string::npos))
283 nPos = sCmd.find("ascii(");
284
285 if (sCmd.find("to_char(") != string::npos && (sCmd.find("to_char(") < nPos || nPos == string::npos))
286 nPos = sCmd.find("to_char(");
287
288 if (sCmd.find("char(") != string::npos && (sCmd.find("char(") < nPos || nPos == string::npos))
289 nPos = sCmd.find("char(");
290 }
291
292 // Try to find the end of the string block
293 // and cut out the identified argument
294 sArgument = extractStringToken(sCmd, nPos);
295 return true;
296}
297
298
310string extractStringToken(const string& sCmd, size_t nPos)
311{
312 // Increment the first position, if the command string begins with an equal sign
313 if (sCmd.front() == '=')
314 nPos++;
315
316 size_t nPos_2 = 0;
317 size_t nQuotes = isInQuotes(sCmd, nPos, true);
318
319 for (size_t i = nPos; i < sCmd.length(); i++)
320 {
321 if (sCmd[i] == '"' && (!i || sCmd[i-1] != '\\'))
322 {
323 nQuotes++;
324 continue;
325 }
326
327 if (nQuotes % 2)
328 continue;
329
330 // Jump over each parenthesis block
331 if (sCmd[i] == '(' || sCmd[i] == '[' || sCmd[i] == '{')
332 {
333 i += getMatchingParenthesis(sCmd.substr(i));
334 continue;
335 }
336
337 // Handle the variable to string parser
338 if (sCmd[i] == '#')
339 {
340 for (size_t j = i; j < sCmd.length(); j++)
341 {
342 if (sCmd[j] == ' ')
343 {
344 i = j;
345 break;
346 }
347 // jump over parentheses
348 if (sCmd[j] == '(')
349 j += getMatchingParenthesis(sCmd.substr(j));
350
351 if (j == sCmd.length() - 1)
352 {
353 i = j;
354 break;
355 }
356 }
357 }
358
359 // If there's a whitespace
360 if (sCmd[i] == ' ')
361 {
362 // Try to find a trailing plus sign
363 if (sCmd.find_first_not_of(' ', i) != string::npos && sCmd[sCmd.find_first_not_of(' ', i)] != '+')
364 {
365 // None was found - break the loop
366 nPos_2 = i - 1;
367 break;
368 }
369 else
370 {
371 // A plus sign was found
372 // Jump over the following whitespaces around the plus sign
373 i = sCmd.find_first_not_of(" +", i)-1;
374 continue;
375 }
376 }
377
378 // If it's the last character or the current character is a
379 // punctuation character
380 if (i >= sCmd.length() - 1 || (ispunct(sCmd[i]) && sCmd[i] != '.' && sCmd[i] != '_' && sCmd[i] != '+' && sCmd[i] != '#'))
381 {
382 if (i == string::npos)
383 nPos_2 = sCmd.length();
384 else
385 nPos_2 = i;
386 break;
387 }
388 }
389
390 // Cut out the identified argument
391 if (!nPos_2)
392 return sCmd.substr(nPos);
393
394 return sCmd.substr(nPos, nPos_2 - nPos + 1);
395}
396
397
414unsigned int getMatchingParenthesis(const StringView& sLine)
415{
416 size_t pos = sLine.find_first_of("([{");
417
418 if (pos == string::npos)
419 return pos;
420
421 // Get the opening parenthesis
422 char cParenthesis = sLine[pos];
423 char cClosingParenthesis = 0;
424
425 // Depending on the opening parenthesis, determine the closing one
426 switch (cParenthesis)
427 {
428 case '(':
429 cClosingParenthesis = ')';
430 break;
431 case '{':
432 cClosingParenthesis = '}';
433 break;
434 case '[':
435 cClosingParenthesis = ']';
436 break;
437 default:
438 // Default case will handle that the user didn't pass a string, which begins with a parenthesis
439 cParenthesis = '(';
440 cClosingParenthesis = ')';
441 }
442
443 int nOpenParenthesis = 0;
444 size_t nQuotes = 0;
445
446 // Go through the string and count the opening and closing parentheses
447 // Consider also whether the the current position is part of a larger string
448 for (size_t i = 0; i < sLine.length(); i++)
449 {
450 // Count unmasked quotation marks
451 if (sLine[i] == '"' && (!i || sLine[i-1] != '\\'))
452 nQuotes++;
453
454 if (nQuotes % 2)
455 continue;
456
457 // Increment the counter at opening paretheses
458 if (sLine[i] == cParenthesis)
459 nOpenParenthesis++;
460
461 // Decrement the counter at closing parentheses
462 if (sLine[i] == cClosingParenthesis)
463 nOpenParenthesis--;
464
465 // All parentheses are closed -> Return the position of this parenthesis
466 if (!nOpenParenthesis && i > pos)
467 return i;
468 }
469
470 // --> Falls die Klammer nicht schliesst, gebe -1 zurueck (analog zu string::find()) <--
471 return string::npos;
472}
473
474
484bool isMultiValue(const string& sExpr, bool bIgnoreClosingParenthesis)
485{
486 // --> Kein Komma? Auf jeden Fall kein Mehrfachausdruck! <--
487 if (sExpr.find(',') == string::npos)
488 return false;
489 else
490 {
491 size_t nQuotationMarks = 0;
492
493 // Go through the string
494 for (unsigned int i = 0; i < sExpr.length(); i++)
495 {
496 // Jump over parentheses
497 if ((sExpr[i] == '(' || sExpr[i] == '{' || sExpr[i] == '[') && !(nQuotationMarks % 2))
498 i += getMatchingParenthesis(sExpr.substr(i));
499
500 // Count quotation marks
501 if (sExpr[i] == '"')
502 nQuotationMarks++;
503
504 if (sExpr[i] == ',' && !(nQuotationMarks % 2))
505 return true;
506 }
507
508 // If the string contains a comma and the "ignore the closing parenthesis" flag is set, enter a recursion
509 // This will cut out the argument of the first opening parenthesis
510 // If no opening parenthesis is available, then leave this block
511 if (sExpr.find_first_of("([{") != string::npos && bIgnoreClosingParenthesis)
512 return isMultiValue(sExpr.substr(sExpr.find_first_of("([{")+1), true);
513 }
514
515 // Nothing found - fallback
516 return false;
517}
518
519
527static std::map<std::string, std::string> getTeXCodePage()
528{
529 std::map<std::string, std::string> mCodePage;
530
531 mCodePage["_pi"] = "\\pi ";
532 mCodePage["_hbar"] = "\\hbar ";
533 mCodePage["_k_boltz"] = "k_B";
534 mCodePage["_2pi"] = "2\\cdot \\pi ";
535 mCodePage["_elek_feldkonst"] = "\\varepsilon ";
536 mCodePage["_elem_ladung"] = "e";
537 mCodePage["_m_elektron"] = "m_{e}";
538 mCodePage["_m_neutron"] = "m_{n}";
539 mCodePage["_m_proton"] = "m_{p}";
540 mCodePage["_m_sonne"] = "m_{Sonne}";
541 mCodePage["_m_erde"] = "m_{Erde}";
542 mCodePage["_m_muon"] = "m_{\\mu}";
543 mCodePage["_m_tau"] = "m_{\\tau}";
544 mCodePage["_magn_feldkonst"] = "\\mu ";
545 mCodePage["_n_avogadro"] = "N_A";
546 mCodePage["_r_erde"] = "r_{Erde}";
547 mCodePage["_r_sonne"] = "r_{Sonne}";
548 mCodePage["_c"] = "c_{Licht}";
549 mCodePage["_e"] = "e";
550 mCodePage["_g"] = "g";
551 mCodePage["_h"] = "h";
552 mCodePage["_R"] = "R";
553 mCodePage["_alpha_fs"] = "\\alpha_{FS}";
554 mCodePage["_mu_bohr"] = "\\mu_{B}";
555 mCodePage["_mu_kern"] = "\\mu_{K}";
556 mCodePage["_m_amu"] = "m_u";
557 mCodePage["_r_bohr"] = "a_0";
558 mCodePage["_G"] = "G";
559 mCodePage["_theta_weinberg"] = "\\theta_{W}";
560 mCodePage["_mu_e"] = "\\mu_{e}";
561 mCodePage["_mu_p"] = "\\mu_{p}";
562 mCodePage["_mu_n"] = "\\mu_{n}";
563 mCodePage["_gamma_e"] = "\\gamma_{e}";
564 mCodePage["_gamma_p"] = "\\gamma_{p}";
565 mCodePage["_gamma_n"] = "\\gamma_{n}";
566 mCodePage["_stefan_boltzmann"] = "\\sigma ";
567 mCodePage["_rydberg"] = "R_{\\infty}";
568 mCodePage["_hartree"] = "E_{h}";
569 mCodePage["_wien"] = "b_{Energie}";
570 mCodePage["_lande_e"] = "g_{e}";
571 mCodePage["_feigenbaum_alpha"] = "\\alpha ";
572 mCodePage["_feigenbaum_delta"] = "\\delta ";
573 mCodePage["inf"] = "\\infty";
574 mCodePage["alpha"] = "\\alpha ";
575 mCodePage["Alpha"] = "\\Alpha ";
576 mCodePage["beta"] = "\\beta ";
577 mCodePage["Beta"] = "\\Beta ";
578 mCodePage["gamma"] = "\\gamma ";
579 mCodePage["Gamma"] = "\\Gamma ";
580 mCodePage["delta"] = "\\delta ";
581 mCodePage["Delta"] = "\\Delta ";
582 mCodePage["epsilon"] = "\\varepsilon ";
583 mCodePage["Epsilon"] = "\\Epsilon ";
584 mCodePage["zeta"] = "\\zeta ";
585 mCodePage["Zeta"] = "\\Zeta ";
586 mCodePage["eta"] = "\\eta ";
587 mCodePage["Eta"] = "\\Eta ";
588 mCodePage["\theta"] = "\\theta ";
589 mCodePage["theta"] = "\\vartheta ";
590 mCodePage["Theta"] = "\\Theta ";
591 mCodePage["iota"] = "\\iota ";
592 mCodePage["Iota"] = "\\Iota ";
593 mCodePage["kappa"] = "\\kappa ";
594 mCodePage["Kappa"] = "\\Kappa ";
595 mCodePage["lambda"] = "\\lambda ";
596 mCodePage["Lambda"] = "\\Lambda ";
597 mCodePage["mu"] = "\\mu";
598 mCodePage["Mu"] = "\\Mu ";
599 mCodePage["\nu"] = "\\nu ";
600 mCodePage["nu"] = "\\nu ";
601 mCodePage["Nu"] = "\\Nu ";
602 mCodePage["xi"] = "\\xi ";
603 mCodePage["Xi"] = "\\Xi ";
604 mCodePage["omikron"] = "o ";
605 mCodePage["Omikron"] = "O ";
606 mCodePage["pi"] = "\\pi ";
607 mCodePage["Pi"] = "\\Pi ";
608 mCodePage["rho"] = "\\rho ";
609 mCodePage["Rho"] = "\\Rho ";
610 mCodePage["sigma"] = "\\sigma ";
611 mCodePage["Sigma"] = "\\Sigma ";
612 mCodePage["\tau"] = "\\tau ";
613 mCodePage["tau"] = "\\tau ";
614 mCodePage["Tau"] = "\\Tau ";
615 mCodePage["ypsilon"] = "\\upsilon ";
616 mCodePage["Ypsilon"] = "\\Upsilon ";
617 mCodePage["phi"] = "\\varphi ";
618 mCodePage["Phi"] = "\\Phi";
619 mCodePage["chi"] = "\\chi ";
620 mCodePage["Chi"] = "\\Chi ";
621 mCodePage["psi"] = "\\psi ";
622 mCodePage["Psi"] = "\\Psi ";
623 mCodePage["omega"] = "\\omega ";
624 mCodePage["Omega"] = "\\Omega ";
625 mCodePage["heaviside"] = "\\Theta";
626 mCodePage["Li2"] = "Li_2";
627 mCodePage["Cl2"] = "Cl_2";
628
629 return mCodePage;
630}
631
632
633static std::map<std::string, std::string> getTeXCodePageSpecial()
634{
635 std::map<std::string, std::string> mCodePage;
636
637 mCodePage["*"] = "\\cdot ";
638 mCodePage["+"] = " + ";
639 mCodePage["-"] = " -- ";
640 mCodePage[","] = ", ";
641 mCodePage["x"] = "{\\i x}";
642 mCodePage["y"] = "{\\i y}";
643 mCodePage["z"] = "{\\i z}";
644 mCodePage["t"] = "{\\i t}";
645
646 return mCodePage;
647}
648
649
661static void handleTeXIndicesAndExponents(std::string& sReturn, const std::map<std::string,std::string>& mCodePage)
662{
663 static std::string sDelimiter = "+-*/, #()&|!_'";
664
665 // Handle the exponents
666 for (size_t i = 0; i < sReturn.length() - 1; i++)
667 {
668 // Insert braces
669 if (sReturn[i] == '^' && sReturn[i + 1] != '{' && sReturn[i + 1] != '(')
670 {
671 i++;
672 sReturn = sReturn.substr(0, i) + "{" + sReturn.substr(i);
673
674 if (sReturn[i + 1] == '-' || sReturn[i + 1] == '+')
675 i++;
676
677 i++;
678
679 // Find the end of the current brace
680 for (size_t j = i + 1; j < sReturn.length(); j++)
681 {
682 if (sDelimiter.find(sReturn[j]) != std::string::npos)
683 {
684 sReturn = sReturn.substr(0, j) + "}" + sReturn.substr(j);
685 break;
686 }
687 else if (j + 1 == sReturn.length())
688 sReturn += "}";
689 }
690 }
691 }
692
693 // Append the exponent operator
694 sDelimiter[sDelimiter.length() - 1] = '^';
695
696 // Handle the indices
697 for (size_t i = 0; i < sReturn.length() - 1; i++)
698 {
699 // Ignore constants
700 if (sReturn[i] == '_' && sReturn[i + 1] != '{')
701 {
702 for (const auto& iter : mCodePage)
703 {
704 if (iter.first.front() != '_')
705 break;
706
707 if (sReturn.substr(i, iter.first.length()) == iter.first
708 && sDelimiter.find(sReturn[i + iter.first.length()]) != std::string::npos)
709 {
710 i++;
711 break;
712 }
713 }
714 }
715
716 // Insert braces
717 if (sReturn[i] == '_' && sReturn[i + 1] != '{')
718 {
719 i++;
720 sReturn = sReturn.substr(0, i) + "{" + sReturn.substr(i);
721 i++;
722
723 // Find the end of the current brace
724 for (unsigned int j = i + 1; j < sReturn.length(); j++)
725 {
726 if (sDelimiter.find(sReturn[j]) != std::string::npos)
727 {
728 sReturn = sReturn.substr(0, j) + "}" + sReturn.substr(j);
729 break;
730 }
731 else if (j + 1 == sReturn.length())
732 {
733 sReturn += "}";
734 }
735 }
736 }
737 }
738}
739
740
753std::string replaceToTeX(const std::string& sString, bool replaceForTeXFile)
754{
755 std::string sReturn = " " + sString + " "; // Rueckgabe-String
756 size_t nPos = 0; // Positions-Index-Variable
757
758 static std::map<std::string, std::string> mCodePage = getTeXCodePage();
759 static std::map<std::string, std::string> mSpecialSymbols = getTeXCodePageSpecial();
760
761 // --> Ersetze zunaechst die gamma-Funktion <--
762 while ((nPos = sReturn.find("gamma(", nPos)) != std::string::npos)
763 {
764 if (nPos && !isDelimiter(sReturn[nPos-1]))
765 {
766 nPos++;
767 continue;
768 }
769
770 sReturn.replace(nPos, nPos+6, "\\Gamma(");
771 nPos += 7;
772 }
773
774 // --> Laufe durch alle bekannten Symbole <--
775 for (const auto& iter : mCodePage)
776 {
777 // --> Positions-Indices zuruecksetzen <--
778 nPos = 0;
779
780 // --> So lange in dem String ab der Position nPos das Token auftritt <--
781 while ((nPos = sReturn.find(iter.first, nPos)) != string::npos)
782 {
783 // --> Falls vor dem Token schon ein '\' ist, wurde das hier schon mal ersetzt <--
784 if (sReturn[nPos - 1] == '\\')
785 {
786 // --> Positionsindex um die Laenge des Tokens weitersetzen <--
787 nPos += iter.first.length();
788 continue;
789 }
790
791 if (sReturn[nPos + iter.first.length()] == '_')
792 {
793 // Wird das Token von '_' abgeschlossen? Pruefen wir, ob es von vorne auch begrenzt ist <--
794 if (!isDelimiter(sReturn[nPos-1]))
795 {
796 // --> Nein? Den Positionsindex um die Laenge des Tokens weitersetzen <--
797 nPos += iter.first.length();
798 continue;
799 }
800 }
801 else if (!checkDelimiter(sReturn.substr(nPos - 1, iter.first.length() + 2)))
802 {
803 // --> Pruefen wir auch getrennt den Fall, ob das Token ueberhaupt begrenzt ist ('_' zaehlt nicht zu den Delimitern) <--
804 nPos += iter.first.length();
805 continue;
806 }
807
808 sReturn.replace(nPos, iter.first.length(), iter.second);
809 nPos += iter.second.length();
810 }
811 }
812
813 for (const auto& iter : mSpecialSymbols)
814 {
815 // --> Positions-Indices zuruecksetzen <--
816 nPos = 0;
817
818 // --> So lange in dem String ab der Position nPos das Token auftritt <--
819 while ((nPos = sReturn.find(iter.first, nPos)) != string::npos)
820 {
821 // --> Falls vor dem Token schon ein '\' ist, wurde das hier schon mal ersetzt <--
822 if (sReturn[nPos - 1] == '\\')
823 {
824 // --> Positionsindex um die Laenge des Tokens weitersetzen <--
825 nPos += iter.first.length();
826 continue;
827 }
828
829 if (iter.first == "*"
830 || (!replaceForTeXFile && !isalpha(iter.first.front())))
831 {
832 // remove obsolete whitespaces around the operators
833 // first in front of the operator
834 if (sReturn[nPos - 1] == ' ')
835 {
836 size_t nPos_2 = sReturn.find_last_not_of(' ', nPos-1)+1;
837 sReturn.erase(nPos_2, nPos - nPos_2);
838 nPos = nPos_2;
839 }
840
841 // after the operator
842 if (sReturn[nPos + 1] == ' ')
843 sReturn.erase(nPos, sReturn.find_first_not_of(' ', nPos+1) - nPos);
844
845 // Identify exponents and ignore them
846 if (iter.first == "+" || iter.first == "-")
847 {
848 if (sReturn[nPos-1] == 'e' || sReturn[nPos-1] == 'E')
849 {
850 if (isdigit(sReturn[nPos-2]) && isdigit(sReturn[nPos+1]) )
851 {
852 nPos++;
853 continue;
854 }
855 }
856
857 // Don't insert whitespaces directly after opening parentheses and commas
858 if (!nPos
859 || sReturn[nPos-1] == '('
860 || sReturn[nPos-1] == '['
861 || sReturn[nPos-1] == '{'
862 || sReturn[nPos-1] == ',')
863 {
864 if (iter.first == "-")
865 {
866 sReturn.insert(nPos, 1, '-');
867 nPos++;
868 }
869
870 nPos++;
871 continue;
872 }
873 }
874 }
875 else if (sReturn[nPos + iter.first.length()] == '_')
876 {
877 // Wird das Token von '_' abgeschlossen? Pruefen wir, ob es von vorne auch begrenzt ist <--
878 if (!isDelimiter(sReturn[nPos-1]))
879 {
880 // --> Nein? Den Positionsindex um die Laenge des Tokens weitersetzen <--
881 nPos += iter.first.length();
882 continue;
883 }
884 }
885 else if (!checkDelimiter(sReturn.substr(nPos - 1, iter.first.length() + 2)))
886 {
887 // --> Pruefen wir auch getrennt den Fall, ob das Token ueberhaupt begrenzt ist ('_' zaehlt nicht zu den Delimitern) <--
888 nPos += iter.first.length();
889 continue;
890 }
891
892 sReturn.replace(nPos, iter.first.length(), iter.second);
893 nPos += iter.second.length();
894 }
895 }
896
897 // --> Ersetze nun lange Indices "_INDEX" durch "_{INDEX}" <--
898 handleTeXIndicesAndExponents(sReturn, mCodePage);
899
900 nPos = 0;
901
902 // replace "sqrt()"
903 while ((nPos = sReturn.find("sqrt(", nPos)) != string::npos)
904 {
905 size_t len = getMatchingParenthesis(StringView(sReturn, nPos+4));
906 sReturn.replace(nPos, len + 6, "@{\\sqrt{" + sReturn.substr(nPos+5, len) + "}}");
907 }
908
909 nPos = 0;
910
911 // replace "norm()"
912 while ((nPos = sReturn.find("norm(", nPos)) != string::npos)
913 {
914 size_t len = getMatchingParenthesis(StringView(sReturn, nPos+4));
915 sReturn.replace(nPos, len + 6, "|" + sReturn.substr(nPos+5, len) + "|");
916 }
917
918 nPos = 0;
919
920 // replace "abs()"
921 while ((nPos = sReturn.find("abs(", nPos)) != string::npos)
922 {
923 size_t len = getMatchingParenthesis(StringView(sReturn, nPos+3));
924 sReturn.replace(nPos, len + 5, "|" + sReturn.substr(nPos+4, len) + "|");
925 }
926
927 nPos = 0;
928
929 // Long exponents
930 while ((nPos = sReturn.find("^(", nPos)) != string::npos)
931 {
932 size_t len = getMatchingParenthesis(StringView(sReturn, nPos+1));
933 sReturn.replace(nPos+1, len + 2, "{" + sReturn.substr(nPos+2, len) + "}");
934 }
935
936 // --> Entferne die Leerzeichen am Anfang und Ende und gib sReturn zurueck <--
937 StripSpaces(sReturn);
938 return sReturn;
939}
940
941
951{
952 Match _mMatch;
953 _mMatch.sString = "";
954 _mMatch.nPos = string::npos;
955 size_t nStart = 0;
956
957 // Jump over breakpoints
958 if (sCmd.subview(0,2) == "|>")
959 nStart = 2;
960
961 // Go through the complete command line
962 for (unsigned int i = nStart; i < sCmd.length(); i++)
963 {
964 // Break the loop, if one recognizes typical initializers of the parameter list
965 if ((sCmd.subview(i, 2) == "--" || sCmd.subview(i, 5) == "-set ") && !isInQuotes(sCmd, i))
966 break;
967
968 // Jump over some special characters, if one didn't find any command yet
969 if ((sCmd[i] == ' ' || sCmd[i] == '\t' || sCmd[i] == '-' || sCmd[i] == '=') && _mMatch.nPos == string::npos)
970 continue;
971 else if ((sCmd[i] == ' ' || sCmd[i] == '-' || sCmd[i] == ';' || sCmd[i] == ':') && _mMatch.nPos != string::npos)
972 {
973 // If we found a command start, then we examine these characters further
974 if (sCmd[i] != '-' && sCmd.find_first_not_of(' ', i) != string::npos && sCmd[sCmd.find_first_not_of(' ', i)] == '=')
975 {
976 // This is probably no commmand, because there's a equal sign following it
977 // Reset the match position and continue
978 _mMatch.nPos = string::npos;
979 continue;
980 }
981
982 // Store the command string
983 _mMatch.sString = sCmd.subview(_mMatch.nPos, i - _mMatch.nPos).to_string();
984
985 // Ensure that this is not inside of quotation marks
986 if (isInQuotes(sCmd, (i - _mMatch.nPos) / 2))
987 {
988 _mMatch.sString = "";
989 _mMatch.nPos = string::npos;
990 }
991
992 // Return the found match
993 return _mMatch;
994 }
995 else if ((sCmd[i] == '(') && _mMatch.nPos != string::npos)
996 {
997 // We found an opening parenthesis although we already found a match position
998 // Store the command string
999 _mMatch.sString = sCmd.subview(_mMatch.nPos, i - _mMatch.nPos).to_string();
1000
1001 // Ensure that this is not inside of quotation marks
1002 // Also ensure that the found command string is one of the
1003 // control flow commands (the only ones, which require parentheses)
1004 if (isInQuotes(sCmd, (i - _mMatch.nPos) / 2)
1005 || (_mMatch.sString != "if"
1006 && _mMatch.sString != "elseif"
1007 && _mMatch.sString != "switch"
1008 && _mMatch.sString != "for"
1009 && _mMatch.sString != "while"))
1010 {
1011 _mMatch.sString = "";
1012 _mMatch.nPos = string::npos;
1013 }
1014
1015 // Return the found match
1016 return _mMatch;
1017 }
1018
1019 // No other case invoked. The current character
1020 // is a candidate for a command string match
1021 if (_mMatch.nPos == string::npos)
1022 _mMatch.nPos = i;
1023 }
1024
1025 // Special case: We walked through the complete command line and didn't find
1026 // the end of the command. Simply use the rest of the command line as the command
1027 if (_mMatch.nPos != string::npos)
1028 _mMatch.sString = sCmd.subview(_mMatch.nPos).to_string();
1029 else
1030 _mMatch.sString = sCmd.to_string();
1031
1032 // Return the found match
1033 return _mMatch;
1034}
1035
1036
1049static bool findShortestMatchForCommand(Match& _mMatch, size_t position, char character, StringView sCmd, const std::string& sCommand)
1050{
1051 // Store the command string and the match position
1052 _mMatch.sString = sCmd.subview(position, sCmd.find(character, position + sCommand.length()) - position).to_string();
1053 _mMatch.nPos = position;
1054
1055 // If there's a whitespace in the match string, erase it end everything after it
1056 if (_mMatch.sString.find(' ') != string::npos)
1057 _mMatch.sString.erase(_mMatch.sString.find(' '));
1058
1059 // Ensure that the found command is a single word
1060 if (!isInQuotes(sCmd, position)
1061 && isDelimiter(sCmd[position+_mMatch.sString.length()])
1062 && (!position || isDelimiter(sCmd[position-1])))
1063 {
1064 // If the command line is longer than the match position and the length of both strings
1065 if (sCmd.length() >= sCommand.length() + _mMatch.nPos + _mMatch.sString.length())
1066 {
1067 // Try to find the command further back by calling findCommand recursively
1068 Match _mTemp = findCommand(sCmd.subview(_mMatch.nPos + _mMatch.sString.length()), sCommand);
1069
1070 // If a match was found and it's length is shorter than the current one
1071 // then use the new match
1072 if (_mTemp.sString.length()
1073 && _mTemp.sString.length() < _mMatch.sString.length())
1074 {
1075 _mMatch.nPos += _mTemp.nPos + _mMatch.sString.length();
1076 _mMatch.sString = _mTemp.sString;
1077 }
1078 }
1079
1080 // Return true
1081 return true;
1082 }
1083 else
1084 {
1085 // It is not a single word
1086 // reset the match and return false
1087 _mMatch.sString = "";
1088 _mMatch.nPos = string::npos;
1089 return false;
1090 }
1091}
1092
1093
1103static Match findCommandWithReturnValue(StringView sCmd, const string& sCommand)
1104{
1105 Match _mMatch;
1106 _mMatch.sString = "";
1107 _mMatch.nPos = string::npos;
1108 size_t nStart = 0;
1109
1110 // Jump over breakpoints
1111 if (sCmd.subview(0,2) == "|>")
1112 nStart = 2;
1113
1114 // Go through the complete command line
1115 for (unsigned int i = nStart; i < sCmd.length(); i++)
1116 {
1117 // Break the loop, if we find typical parameter string initializers
1118 if ((sCmd.subview(i, 2) == "--" || sCmd.subview(i, 5) == "-set ") && !isInQuotes(sCmd, i))
1119 break;
1120
1121 // Jump over some special characters
1122 if (sCmd[i] == ' ' || sCmd[i] == '\t' || sCmd[i] == '(')
1123 continue;
1124
1125 // Jump, if this is not our searched command
1126 if (sCmd.subview(i, sCommand.length()) != sCommand)
1127 continue;
1128
1129 // This is our command and it is not at the beginning of the line
1130 if (sCmd.subview(i, sCommand.length()) == sCommand && i)
1131 {
1132 // Is the command filling the rest of the command line?
1133 if (i + sCommand.length() == sCmd.length() - 1)
1134 {
1135 // Store the command string with the previous character
1136 _mMatch.sString = sCmd.subview(i - 1).to_string() + " ";
1137
1138 // Store the position
1139 _mMatch.nPos = i;
1140
1141 // Ensure that the command is not part of a larger word
1142 if (checkDelimiter(_mMatch.sString) && !isInQuotes(sCmd, i))
1143 {
1144 // It is not
1145 // Remove the additional characters
1146 _mMatch.sString = _mMatch.sString.substr(1, _mMatch.sString.length() - 2);
1147 }
1148 else
1149 {
1150 // It is
1151 // Reset the match
1152 _mMatch.sString = "";
1153 _mMatch.nPos = string::npos;
1154 }
1155
1156 // return the found match
1157 return _mMatch;
1158 }
1159
1160 // Continue, if the command ends with a parenthesis and there's another match
1161 // Otherwise reset the match
1162 if (sCmd[i + sCommand.length()] == '(' && sCmd.find(sCommand, i + 1) != string::npos)
1163 continue;
1164 else if (sCmd[i + sCommand.length()] == '(' && sCmd.find(sCommand, i + 1) == string::npos)
1165 {
1166 // Reset the match
1167 _mMatch.sString = "";
1168 _mMatch.nPos = string::npos;
1169
1170 // Return the resetted match
1171 return _mMatch;
1172 }
1173
1174 // There's a minus sign after the command
1175 if (sCmd.find('-', i + sCommand.length()) != string::npos)
1176 {
1177 // If the match is not a single word, continue
1178 if (!findShortestMatchForCommand(_mMatch, i, '-', sCmd, sCommand))
1179 continue;
1180 return _mMatch;
1181 }
1182
1183 // There's a whitespace after the command
1184 if (sCmd.find(' ', i + sCommand.length()) != string::npos)
1185 {
1186 // If the match is not a single word, continue
1187 if (!findShortestMatchForCommand(_mMatch, i, ' ', sCmd, sCommand))
1188 continue;
1189 return _mMatch;
1190 }
1191 }
1192
1193 // This is our command and it is at the beginning of the line
1194 if (sCmd.subview(i, sCommand.length()) == sCommand && !i)
1195 {
1196 // If the command lenght and the command line length are nearly the same
1197 if (sCommand.length() == sCmd.length() - 1)
1198 {
1199 // Store string and match position
1200 // Add surrounding characters
1201 _mMatch.sString = " " + sCommand.substr(0, sCommand.length() + 1);
1202 _mMatch.nPos = 0;
1203
1204 // Ensure that the found string is not part of a larger word
1205 if (checkDelimiter(_mMatch.sString) && !isInQuotes(sCmd, i))
1206 {
1207 // It is not
1208 // remove the additional characters
1209 _mMatch.sString = _mMatch.sString.substr(1, _mMatch.sString.length() - 2);
1210 }
1211 else
1212 {
1213 // It is
1214 // Reset the match and continue
1215 _mMatch.sString = "";
1216 _mMatch.nPos = string::npos;
1217 continue;
1218 }
1219
1220 // Return the found match
1221 return _mMatch;
1222 }
1223
1224 // Continue, if the command ends with a parenthesis and there's another match
1225 // Otherwise reset the match
1226 if (sCmd[i + sCommand.length()] == '(' && sCmd.find(sCommand, i + 1) != string::npos)
1227 continue;
1228 else if (sCmd[i + sCommand.length()] == '(' && sCmd.find(sCommand, i + 1) == string::npos)
1229 {
1230 _mMatch.sString = "";
1231 _mMatch.nPos = string::npos;
1232 return _mMatch;
1233 }
1234
1235 // There's a minus sign after the command
1236 if (sCmd.find('-', i + sCommand.length()) != string::npos)
1237 {
1238 // If the match is not a single word, continue
1239 if (!findShortestMatchForCommand(_mMatch, i, '-', sCmd, sCommand))
1240 continue;
1241 return _mMatch;
1242 }
1243
1244 // There's a whitespace after the command
1245 if (sCmd.find(' ', i + sCommand.length()) != string::npos)
1246 {
1247 // If the match is not a single word, continue
1248 if (!findShortestMatchForCommand(_mMatch, i, ' ', sCmd, sCommand))
1249 continue;
1250 return _mMatch;
1251 }
1252 }
1253 }
1254
1255 // Return the found match
1256 return _mMatch;
1257}
1258
1259
1275Match findCommand(StringView sCmd, const std::string& sCommand)
1276{
1277 Match _mMatch;
1278 _mMatch.sString = "";
1279 _mMatch.nPos = string::npos;
1280
1281 // There are two possible use cases:
1282 // If one defines a command, for which this function shall look for,
1283 // then it will also find commands after other special characters
1284 if (!sCommand.length())
1285 {
1286 // find a causal command
1287 return findCasualCommand(sCmd);
1288 }
1289 else if (sCommand.length() && (sCmd == sCommand || sCmd == sCommand + " "))
1290 {
1291 // the command line is identical to the searched command
1292 _mMatch.sString = sCmd.to_string();
1293 StripSpaces(_mMatch.sString);
1294 _mMatch.nPos = 0;
1295
1296 // Return the found match
1297 return _mMatch;
1298 }
1299 else if (sCommand.length()
1300 && sCmd.find(sCommand) != string::npos
1301 && sCmd.find(' ', sCmd.find(sCommand)) != string::npos
1302 && findCommand(sCmd).sString != "help"
1303 && findCommand(sCmd).sString != "edit"
1304 && findCommand(sCmd).sString != "new")
1305 {
1306 // find a command with a return value
1307 return findCommandWithReturnValue(sCmd, sCommand);
1308 }
1309
1310 // Nothing was found
1311 return _mMatch;
1312}
1313
1314
1325string extractCommandString(const string& sCmd, const Match& _mMatch)
1326{
1327 string sCommandString = "";
1328
1329 // if not match was found, return an empty string
1330 if (_mMatch.nPos == string::npos)
1331 return "";
1332
1333 // A match is available
1334 if (_mMatch.nPos)
1335 {
1336 // go through the string inversely. Start at the match position
1337 for (int i = _mMatch.nPos; i >= 0; i--)
1338 {
1339 // An opening parenthesis was found, which is not part of a string
1340 if (sCmd[i] == '(' && !isInQuotes(sCmd, i))
1341 {
1342 // Find the matching parenthesis
1343 if (getMatchingParenthesis(sCmd.substr(i)) != string::npos)
1344 {
1345 // Use the contents of the parenthesis
1346 // However, only extract the command and not the characters in front of it
1347 sCommandString = sCmd.substr(_mMatch.nPos, getMatchingParenthesis(sCmd.substr(i)) - (_mMatch.nPos - i + 1));
1348 break;
1349 }
1350 else
1352 }
1353 }
1354 }
1355
1356 // If the command string length is zero, use the complete command string
1357 // from the position to the end
1358 if (!sCommandString.length())
1359 sCommandString = sCmd.substr(_mMatch.nPos);
1360
1361 // Return the extracted string
1362 return sCommandString;
1363}
1364
1365
1375void openExternally(const string& sFile)
1376{
1377 std::string _sFile;
1378
1379 int nErrorCode = 0;
1380
1381 // Add quotation marks if there are none and convert the string to a character pointer
1382 if (_sFile[0] != '"')
1383 _sFile = "\"" + sFile + "\"";
1384 else
1385 _sFile = sFile;
1386
1387 replaceAll(_sFile, "/", "\\");
1388
1389 // Invoke the Windows shell
1390 nErrorCode = (int)ShellExecute(nullptr, "open", sFile.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
1391
1392 // Examine the return value
1393 if (nErrorCode <= 32)
1394 {
1395 if (nErrorCode == SE_ERR_NOASSOC)
1397 else
1399 }
1400}
1401
1402
1412void moveFile(const string& sFile, const string& sNewFileName)
1413{
1414 // Copy first
1415 copyFile(sFile, sNewFileName);
1416
1417 // remove old file
1418 remove(sFile.c_str());
1419}
1420
1421
1431void copyFile(const string& sFile, const string& sTarget)
1432{
1433 // Open two file streams to copy the contents
1434 ifstream File(sFile.c_str(), ios_base::binary);
1435 ofstream NewFile(sTarget.c_str(), ios_base::binary);
1436
1437 if (!File.good())
1439
1440 if (!NewFile.good())
1442
1443 // Copy the file
1444 NewFile << File.rdbuf();
1445}
1446
1447
1448// --> Generiert eine TeX-Hauptdatei fuer eine gegebene TikZ-Plot-Datei <--
1449void writeTeXMain(const string& sTeXFile)
1450{
1451 string sTemp = sTeXFile;
1452
1453 // Extract the path
1454 if (sTemp.find('\\') != string::npos || sTemp.find('/') != string::npos)
1455 {
1456 if (sTemp.find('\\') != string::npos)
1457 sTemp = sTemp.substr(sTemp.rfind('\\') + 1);
1458 if (sTemp.find('/') != string::npos)
1459 sTemp = sTemp.substr(sTemp.rfind('/') + 1);
1460 }
1461
1462 // --> Fuege vor ".tex" den String "main" ein <--
1463 ofstream TexMain((sTeXFile.substr(0, sTeXFile.find(".tex")) + "main.tex").c_str());
1464 if (!TexMain.good())
1465 throw SyntaxError(SyntaxError::CANNOT_OPEN_TARGET, "", SyntaxError::invalid_position, sTeXFile.substr(0, sTeXFile.find(".tex")) + "main.tex");
1466
1467 // Write the files contents
1468 TexMain << "\\documentclass{scrartcl} % KOMA-SCRIPT-KLASSE (Kann durch \"article\" ersetzt werden)" << endl << endl;
1469 TexMain << "% Ein paar hilfreiche Packages:" << endl;
1470 TexMain << "\\usepackage[utf8]{inputenc} % Sonderzeichen in der Eingabe" << endl;
1471 TexMain << "\\usepackage[T1]{fontenc} % Sonderzeichen in der Ausgabe" << endl;
1472 TexMain << "\\usepackage[ngerman]{babel} % Deutsch als Dokumentsprache" << endl;
1473 TexMain << "\\usepackage{mathpazo} % Palatino als Schriftart (passend zum Plot)" << endl;
1474 TexMain << "\\usepackage{tikz} % TikZ fuer die eigentliche Graphik" << endl;
1475 TexMain << "% Eigentliches Dokument" << endl;
1476 TexMain << "\\begin{document}" << endl;
1477 TexMain << "\t% Hier bietet sich ein beschreibender Text an" << endl;
1478 TexMain << "\t\\input{";
1479 TexMain << sTemp;
1480 TexMain << "} % Einbinden des Plots" << endl;
1481 TexMain << "\t% Mit derselben Syntax wie der vorherigen Zeile koennen auch weitere Plots in diese TeX-Ausgabe eingebunden werden" << endl;
1482 TexMain << "\\end{document}" << endl;
1483 TexMain << "% EOF" << endl;
1484 TexMain.close();
1485
1486 /* --> Die Datei "mglmain.tex" wird bei einem TeX-Export automatisch erstellt (und entspricht in etwa dieser Datei),
1487 * allerdings wird diese Datei jedes Mal bei einem TeX-Export ueberschrieben. Daher schreiben wir unsere eigene
1488 * und loeschen diese automatische Datei <--
1489 */
1490 remove("mglmain.tex");
1491 return;
1492}
1493
1494
1504static size_t isStringContinuation(const std::string& sCmd, size_t pos)
1505{
1506 if (sCmd.substr(pos, 2) == " ")
1507 return std::string::npos;
1508
1509 size_t nextChar = sCmd.find_first_not_of(' ', pos+1);
1510
1511 if (nextChar == std::string::npos || sCmd[nextChar] != '+')
1512 return std::string::npos;
1513
1514 nextChar++;
1515
1516 if (sCmd.length() > nextChar && sCmd[nextChar] != ' ')
1517 return nextChar;
1518
1519 nextChar++;
1520
1521 if (sCmd.length() > nextChar && sCmd[nextChar] != ' ')
1522 return nextChar;
1523
1524 return std::string::npos;
1525}
1526
1527
1538static void parseArg(std::string& sArg, int flags)
1539{
1541
1542 // Function call
1543 if (!instance->getDefinitions().call(sArg))
1545
1546 // Read data
1547 if (instance->getMemoryManager().containsTablesOrClusters(sArg)
1548 && !instance->getStringParser().isStringExpression(sArg))
1549 getDataElements(sArg, instance->getParser(), instance->getMemoryManager(), instance->getSettings());
1550
1551 // String evaluation
1552 if (instance->getStringParser().isStringExpression(sArg))
1553 {
1554 std::string dummy;
1555
1556 NumeRe::StringParser::StringParserRetVal _ret = instance->getStringParser().evalAndFormat(sArg, dummy, true);
1557
1559 return;
1560 }
1561
1562 if (flags & ARGEXTRACT_ASSTRING)
1563 return;
1564
1565 // Numerical evaluation
1566 instance->getParser().SetExpr(sArg);
1567
1568 int results;
1569 int nPrec = instance->getSettings().getPrecision();
1570 mu::value_type* v = instance->getParser().Eval(results);
1571
1572 sArg.clear();
1573
1574 for (int i = 0; i < results; i++)
1575 {
1576 if (sArg.length())
1577 sArg += ",";
1578
1579 if (flags & ARGEXTRACT_ASINT)
1580 sArg += toString(intCast(v[i]));
1581 else
1582 sArg += toString(v[i], nPrec);
1583 }
1584}
1585
1586
1598string getArgAtPos(const string& sCmd, unsigned int nPos, int extraction)
1599{
1600 string sArgument = "";
1601
1602 // If the position is greater than the string length
1603 // return an empty string
1604 if (nPos >= sCmd.length())
1605 return "";
1606
1607 // Jump over whitespaces
1608 while (nPos < sCmd.length() && sCmd[nPos] == ' ')
1609 nPos++;
1610
1611 // Ensure that the position is smaller than the length of the string
1612 if (nPos >= sCmd.length())
1613 return "";
1614
1615 size_t nQuotes = 0;
1616
1617 for (size_t i = nPos; i < sCmd.length(); i++)
1618 {
1619 if (sCmd[i] == '"' && (!i || sCmd[i - 1] != '\\'))
1620 nQuotes++;
1621
1622 if (nQuotes % 2)
1623 continue;
1624
1625 if (sCmd[i] == '(' || sCmd[i] == '[' || sCmd[i] == '{')
1626 i += getMatchingParenthesis(sCmd.substr(i));
1627
1628 if (sCmd[i] == ' ')
1629 {
1630 size_t cont = isStringContinuation(sCmd, i);
1631
1632 if (cont < sCmd.length() && NumeReKernel::getInstance()->getStringParser().isStringExpression(sCmd.substr(nPos, i-nPos)))
1633 i = cont-1;
1634 else
1635 {
1636 sArgument = sCmd.substr(nPos, i-nPos);
1637 break;
1638 }
1639 }
1640 else if (i+1 == sCmd.length())
1641 sArgument = sCmd.substr(nPos);
1642 }
1643
1644 // Parse the argument, if necessary
1645 if (extraction & ARGEXTRACT_PARSED)
1646 parseArg(sArgument, extraction);
1647
1648 // Strip the argument, if necessary
1649 if (extraction & ARGEXTRACT_STRIPPED)
1650 {
1651 StripSpaces(sArgument);
1652
1653 if (sArgument.front() == '"' && sArgument.back() == '"')
1654 sArgument = sArgument.substr(1, sArgument.length()-2);
1655 }
1656
1657 // return the found option value
1658 return sArgument;
1659}
1660
1661
1672bool isInQuotes(StringView sExpr, unsigned int nPos, bool bIgnoreVarParser /* = false*/)
1673{
1674 int nQuotes = 0;
1675
1676 // --> Zaehlt schlicht und einfach die Anfuehrungszeichen <--
1677 for (size_t i = 0; i < nPos; i++)
1678 {
1679 // Parse the special string_cast function
1680 if (sExpr.subview(i, 12) == "string_cast(" && i + 12 <= nPos)
1681 {
1682 // Argument of "string_cast"?
1683 if (getMatchingParenthesis(sExpr.subview(i + 11)) + i + 11 > nPos)
1684 return true;
1685 else
1686 i += getMatchingParenthesis(sExpr.subview(i + 11)) + 11;
1687 }
1688
1689 // Count the quotation marks
1690 if (sExpr[i] == '"' && (!i || sExpr[i-1] != '\\'))
1691 nQuotes++;
1692 }
1693
1694 // Simplest case: The number of quotation marks is odd
1695 // Therefore the position is inside of quotation marks
1696 if (nQuotes % 2) // nQuotes % 2 == 1, wenn eine ungerade Zahl an Anfuehrungszeichen aufgetreten ist => die Position befindet sich als hinter einem geoeffneten Anfuehrungszeichen.
1697 return true;
1698
1699 // Shall the variable to string parser be examined, too?
1700 if (!bIgnoreVarParser)
1701 {
1702 // No variable to string parser was found
1703 if (sExpr.rfind('#', nPos) == string::npos)
1704 return false;
1705
1706 // Ensure that the variable to string parser is not part of quotation marks itself
1707 // Do this by calling the function on its position recursively
1708 if (isInQuotes(sExpr, sExpr.rfind('#', nPos), true))
1709 return false;
1710
1711 // If it is not part of quotation marks, examine the contents of the
1712 // variable to string parser (i.e. everything between "#" and the current position)
1713 for (unsigned int i = sExpr.rfind('#', nPos); i < nPos; i++)
1714 {
1715 // Parenthesis is found
1716 // Jump over it
1717 if (sExpr[i] == '(')
1718 {
1719 // Has no closing parenthesis -> the closing one must be after the current position
1720 if (getMatchingParenthesis(sExpr.subview(i, nPos - i)) == string::npos)
1721 return true;
1722
1723 // Advance the index variabel
1724 i += getMatchingParenthesis(sExpr.subview(i, nPos - i));
1725
1726 // Probably we're now at the current position. Then
1727 // this is the closing parenthesis of the variable to string parser
1728 if (i == nPos)
1729 return true;
1730 continue;
1731 }
1732
1733 // Whitespaces, commas, string concatenators (plus sign) and closing parentheses
1734 // are indicators for the end of the variable to string arguments. This means
1735 // that the current position is not part of any string
1736 if (sExpr[i] == ' ' || sExpr[i] == '+' || sExpr[i] == ',' || sExpr[i] == ')')
1737 return false;
1738 }
1739
1740 // Exclude special characters, which are the terminators of the variable to string parser by themselves
1741 if (nPos < sExpr.length() - 1 && (sExpr[nPos] == ',' || sExpr[nPos] == '+' || sExpr[nPos] == ' ' || sExpr[nPos] == ')'))
1742 return false;
1743 else if (nPos == sExpr.length() - 1 && sExpr[nPos] == ')')
1744 return false;
1745 else
1746 return true;
1747
1748 }
1749
1750 // return false
1751 return false;
1752}
1753
1754
1766bool isToStringArg(const string& sExpr, unsigned int nPos)
1767{
1768 // Ensure that at least one of the three functions is available in the string
1769 if (sExpr.find("valtostr(") == string::npos && sExpr.find("to_string(") == string::npos && sExpr.find("string_cast(") == string::npos)
1770 return false;
1771
1772 // Go inversely through the string
1773 for (int i = nPos; i >= 8; i--)
1774 {
1775 // An opening parenthesis was found with its counterpart after the current position
1776 if (sExpr[i] == '(' && getMatchingParenthesis(sExpr.substr(i)) + i > nPos)
1777 {
1778 // Is there one of the three functions left from the current position?
1779 if (i > 10 && sExpr.substr(i - 11, 12) == "string_cast(")
1780 return true;
1781 else if (i > 8 && sExpr.substr(i - 9, 10) == "to_string(")
1782 return true;
1783 else if (sExpr.substr(i - 8, 9) == "valtostr(")
1784 return true;
1785 else if (isDelimiter(sExpr[i - 1]))
1786 continue; // There's a delimiter left of the parenthesis, continue
1787 else
1788 return false;
1789 }
1790 }
1791
1792 // No part of any of the functions' arguments
1793 return false;
1794}
1795
1796
1805long long int intCast(double number)
1806{
1807 // if quite close, use rint
1808 if (fabs(number - rint(number)) < 1e-7)
1809 return rint(number);
1810 // otherwise truncate
1811 return static_cast<int>(number);
1812}
1813
1814
1824long long int intCast(const std::complex<double>& number)
1825{
1826 return intCast(number.real());
1827}
1828
1829
1838bool isInt(const std::complex<double>& number)
1839{
1840 return number.imag() == 0.0 && fabs(number.real() - rint(number.real())) < 1e-12;
1841}
1842
1843
1852bool isDelimiter(char c)
1853{
1854 // Characters converted to a single logical expression (should be faster in principle)
1855 return c >= 32 && c <= 125 && c != 36 && c != 39 && c != 46 && (c < 48 || c > 57) && (c < 64 || c > 90) && (c < 95 || c > 122);
1856 // Only construct the string once
1857 //static string sDelimiter = "+-*/ ^&|!%<>,=\\#?:;()[]{}\"";
1858
1859 // Try to find the current character
1860 /*if (sDelimiter.find(cChar) != string::npos)
1861 return true;
1862 return false;*/
1863}
1864
1865
1875bool addLegends(string& sExpr)
1876{
1877 // Validate the number of parentheses
1878 if (!validateParenthesisNumber(sExpr))
1880
1882
1883 std::string sTemp;
1884
1885 for (size_t i = 0; i < args.size(); i++)
1886 {
1887 /* --> Nun koennte es sein, dass bereits eine Legende angegeben worden ist. Dabei gibt es drei
1888 * Moeglichkeiten: entweder durch umschliessende Anfuehrungszeichen, durch eine vorangestellte
1889 * Raute '#' oder auch beides. Wir muessen hier diese drei Faelle einzeln behandeln <--
1890 * --> Ebenfalls ist es natuerlich moeglich, dass gar keine Legende angegeben worden ist. Das behandeln
1891 * wir im ELSE-Fall <--
1892 */
1893 if (args[i].find('"') != std::string::npos)
1894 {
1895 /* --> Hier ist auf jeden Fall '"' vorhanden. Es ist aber nicht gesagt, dass '#' nicht auch
1896 * zu finden ist <--
1897 * --> Speichern wir zunaechst die Position des '"' in nPos <--
1898 */
1899 size_t nPos = args[i].find('"') + 1;
1900
1901 // --> Pruefe nun, ob in diesem Stringbereich ein zweites '"' zu finden ist <--
1902 if (args[i].find('"', nPos) != std::string::npos)
1903 {
1904 // --> Ja? Gibt's denn dann eine Raute? <--
1905 if (args[i].find('#', nPos) != std::string::npos)
1906 {
1907 // --> Ja? Dann muessen wir (zur Vereinfachung an anderer Stelle) noch zwei Anfuehrungszeichen ergaenzen <--
1908 sTemp += args[i] + "+\"\"";
1909 }
1910 else
1911 sTemp += args[i];
1912 }
1913 else
1914 return false; // Nein? Dann ist irgendwas ganz Falsch: FALSE zurueckgeben!
1915 }
1916 else if (args[i].find('#') != string::npos)
1917 {
1918 /* --> Hier gibt's nur '#' und keine '"' (werden im ersten Fall schon gefangen). Speichern wir
1919 * die Position der Raute in nPos <--
1920 */
1921 size_t nPos = args[i].find('#');
1922
1923 /* --> Setze sExpr dann aus dem Teil vor nPos und, wenn noch mindestens Komma ab nPos gefunden werden kann,
1924 * dem Teil ab nPos vor dem Komma, dem String '+""' und dem Teil ab dem Komma zusammen, oder, wenn kein
1925 * Komma gefunden werden kann, dem Teil nach nPos und dem String '+""' zusammen <--
1926 * --> An dieser Stelle bietet sich der Ternary (A ? x : y) tatsaechlich einmal an, da er die ganze Sache,
1927 * die sonst eine temporaere Variable benoetigt haette, in einem Befehl erledigen kann <--
1928 */
1929 for (size_t j = nPos; j < args[i].length(); j++)
1930 {
1931 if (args[i][j] == '(')
1932 j += getMatchingParenthesis(args[i].substr(j));
1933
1934 if (args[i][j] == ' ')
1935 {
1936 sTemp += args[i].insert(j, "+\"\"");
1937 break;
1938 }
1939 else if (j+1 == args[i].length())
1940 {
1941 sTemp += args[i] + "+\"\"";
1942 break;
1943 }
1944 }
1945 }
1946 else
1947 {
1948 /* --> Hier gibt's weder '"' noch '#'; d.h., wir muessen die Legende selbst ergaenzen <--
1949 * --> Schneiden wir zunaechst den gesamten Ausdurck zwischen den zwei Kommata heraus <--
1950 */
1951 std::string sLabel = args[i];
1952
1953 // --> Entfernen wir ueberzaehlige Leerzeichen <--
1954 StripSpaces(sLabel);
1955
1956 /* --> Setzen wir den gesamten Ausdruck wieder zusammen, wobei wir den Ausdruck in
1957 * Anfuehrungszeichen als Legende einschieben <--
1958 */
1959 sTemp += args[i] + " \"" + sLabel + "\"";
1960 }
1961
1962 if (i+1 < args.size())
1963 sTemp += ", ";
1964 }
1965
1966 sExpr = sTemp;
1967
1968 return true;
1969}
1970
1971
1982bool checkDelimiter(const string& sString, bool stringdelim)
1983{
1984 // --> Gib die Auswertung dieses logischen Ausdrucks zurueck <--
1985 return isDelimiter(sString.front()) && (isDelimiter(sString.back()) || (sString.back() == '.' && stringdelim));
1986}
1987
1988
2002std::vector<std::string> splitIntoLines(std::string sOutput, size_t lineWidth, bool bAllowDashBreaks, int nFirstIndent, int nIndent)
2003{
2004 // Set the return vector of strings
2005 std::vector<std::string> outputInLines;
2006
2007 // Variable to store the position of the last line break
2008 unsigned int nLastLineBreak = 0;
2009
2010 // Convert the output to the system code page
2011 sOutput = toSystemCodePage(sOutput);
2012
2013 // Check if the output already contains the line starting chars
2014 if ((sOutput.substr(0, 4) == "| " || sOutput.substr(0, 4) == "|-> ") && nFirstIndent == 4)
2015 nFirstIndent = 0;
2016
2017 // Check if string is already shorter than the line length and does not have any new line commands
2018 if (sOutput.length() < lineWidth - nFirstIndent && sOutput.find('$') == string::npos && sOutput.find("\\n") == string::npos && sOutput.find('\n') == string::npos)
2019 {
2020 outputInLines.push_back(sOutput);
2021 return outputInLines;
2022 }
2023
2024 // Go through the whole string
2025 for (unsigned int i = 1; i < sOutput.length(); i++)
2026 {
2027 // Check for the '$' sign. If found update the last line break
2028 if (sOutput[i] == '$' && sOutput[i - 1] != '\\')
2029 nLastLineBreak = i;
2030
2031 if (sOutput[i] == 'n' && sOutput[i - 1] == '\\')
2032 {
2033 if ((i == 1 || sOutput[i - 2] != '\\')
2034 && !(sOutput.substr(i, 2) == "nu" && checkDelimiter(sOutput.substr(i - 1, 4)))
2035 && !(sOutput.substr(i, 3) == "neq" && checkDelimiter(sOutput.substr(i - 1, 5))))
2036 nLastLineBreak = i;
2037 else if (i != 1 && sOutput[i - 2] != '\\')
2038 sOutput.insert(i, "\\");
2039 }
2040 // Check for explicit line break
2041 if (sOutput[i] == '\n')
2042 {
2043 nLastLineBreak = i;
2044 }
2045
2046 // Check if max line length is reached. In that case, split the string at a fitting position
2047 if ((i == lineWidth - nFirstIndent && !nLastLineBreak) || (nLastLineBreak && i - nLastLineBreak == lineWidth - nIndent))
2048 {
2049 // Go backwards from the current position and look for 1 space or 1 minus sign (if allowed) or the "$"
2050 for (unsigned int j = i; j > nLastLineBreak; j--)
2051 {
2052 if (sOutput[j] == ' ')
2053 {
2054 if (sOutput[j - 1] == '\\')
2055 {
2056 sOutput.insert(j + 1, "$");
2057 nLastLineBreak = j + 1;
2058 }
2059 else
2060 {
2061 sOutput[j] = '$'; // Replace " " with a "$"
2062 nLastLineBreak = j;
2063 }
2064 break;
2065 }
2066 else if (sOutput[j] == '-' && bAllowDashBreaks && j != i)
2067 {
2068 // Check if a line break is applicable for the "-" used
2069 if (j &&
2070 (sOutput[j - 1] == ' '
2071 || sOutput[j - 1] == '('
2072 || sOutput[j + 1] == ')'
2073 || sOutput[j - 1] == '['
2074 || (sOutput[j + 1] >= '0' && sOutput[j + 1] <= '9')
2075 || sOutput[j + 1] == ','
2076 || (sOutput[j + 1] == '"' && sOutput[j - 1] == '"')
2077 ))
2078 continue;
2079 sOutput.insert(j + 1, 1, '\n'); // Insert a linebreak
2080 nLastLineBreak = j + 1;
2081 break;
2082 }
2083 else if (sOutput[j] == ',' && bAllowDashBreaks && sOutput[j + 1] != ' ' && j != i)
2084 {
2085 sOutput[j] = '%';
2086 nLastLineBreak = j + 1;
2087 break;
2088 }
2089 else if (sOutput[j] == '$' && sOutput[j - 1] != '\\') // Definitely a line break is required here
2090 {
2091 nLastLineBreak = j;
2092 break;
2093 }
2094 if (j - 1 == nLastLineBreak)
2095 {
2096 string sDelim = "+-*/";
2097 for (unsigned int n = i; n > nLastLineBreak; n--)
2098 {
2099 if (sDelim.find(sOutput[n]) != string::npos)
2100 {
2101 sOutput = sOutput.substr(0, n) + '$' + sOutput.substr(n);
2102 nLastLineBreak = n;
2103 break;
2104 }
2105 if (n - 1 == nLastLineBreak)
2106 {
2107 sOutput = sOutput.substr(0, i - 1) + '$' + sOutput.substr(i - 1);
2108 nLastLineBreak = i;
2109 }
2110 }
2111 }
2112 }
2113 }
2114 }
2115
2116 // Go through the whole string again
2117 size_t lastBreak = 0; // lastBreak is the position of the first relevant char for the new line
2118 for (unsigned int i = 0; i < sOutput.length(); i++)
2119 {
2120 if (sOutput[i] == '$' && sOutput[i - 1] != '\\')
2121 {
2122 // Split the string at the '$' sign
2123 outputInLines.push_back(sOutput.substr(lastBreak, i - lastBreak));
2124 lastBreak = i + 1;
2125 continue;
2126 }
2127 else if (sOutput[i] == '\n')
2128 {
2129 outputInLines.push_back(sOutput.substr(lastBreak, i - lastBreak));
2130 lastBreak = i + 1;
2131 continue;
2132 }
2133 else if (sOutput[i] == 'n' && sOutput[i - 1] == '\\' && sOutput[i - 2] != '\\')
2134 sOutput = sOutput.substr(0, i - 1) + "\n" + sOutput.substr(i + 1);
2135 else if (sOutput[i] == 'n' && sOutput[i - 1] == '\\' && sOutput[i - 2] == '\\')
2136 sOutput.erase(i - 1, 1);
2137 else if (sOutput[i] == '$' && sOutput[i - 1] == '\\')
2138 sOutput.erase(i - 1, 1);
2139 else if (sOutput[i] == '%' && bAllowDashBreaks)
2140 {
2141 // Replace '%' with ',' and the indent if allowed
2142 sOutput = sOutput.substr(0, i) + ",\n" + sOutput.substr(i + 1);
2143 }
2144 }
2145
2146 // Add the rest of the string
2147 outputInLines.push_back(sOutput.substr(lastBreak));
2148
2149 return outputInLines;
2150}
2151
2152
2164std::string outputString(std::vector<std::string> stringInLines, int nFirstIndent, int nIndent)
2165{
2166 std::string sOutput = "";
2167
2168 // Check if vector is empty and return empty string if so
2169 if (!stringInLines.size())
2170 return sOutput;
2171
2172 // Check if the output already contains the line starting chars
2173 if ((sOutput.substr(0, 4) == "| " || sOutput.substr(0, 4) == "|-> ") && nFirstIndent == 4)
2174 nFirstIndent = 0;
2175
2176 // Add the first line with the corresponding indent
2177 sOutput.append(stringInLines[0]);
2178
2179 // Prepare the prefix for all strings except the first one
2180 std::string sIndent = "\n|";
2181 for (int i = 1; i < nIndent; i++)
2182 sIndent += " ";
2183
2184 // Add the prefixes and join the strings
2185 for (size_t i = 1; i < stringInLines.size(); i++)
2186 sOutput.append(sIndent + stringInLines[i]);
2187
2188 return sOutput;
2189}
2190
2191
2205std::string LineBreak(std::string sOutput, const Settings& _option, bool bAllowDashBreaks, int nFirstIndent, int nIndent)
2206{
2207 return outputString(splitIntoLines(sOutput, _option.getWindow(), bAllowDashBreaks, nFirstIndent, nIndent), nFirstIndent, nIndent);
2208}
2209
2210
2222double Linearize(double x_0, double y_0, double x_1, double y_1)
2223{
2224 double b = y_0;
2225 double m = (y_1 - y_0) / (x_1 - x_0);
2226 // y = m*x + b ==> x = 1/m*(y-b) ==> x = -b/m fuer y = 0.0
2227 return x_0 - b / m;
2228}
2229
2230
2243{
2244 if (!sArgList.length())
2245 return StringView();
2246
2247 size_t nPos = 0;
2248 size_t nMatching = 0;
2249 size_t nQuotes = 0;
2250
2251 // Go through the complete string
2252 for (size_t i = 0; i < sArgList.length(); i++)
2253 {
2254 if (sArgList[i] == '"' && (!i || sArgList[i-1] != '\\'))
2255 nQuotes++;
2256
2257 if (nQuotes % 2)
2258 continue;
2259
2260 // Jump over parentheses
2261 if ((sArgList[i] == '(' || sArgList[i] == '[' || sArgList[i] == '{' ) && (nMatching = getMatchingParenthesis(sArgList.subview(i))) != string::npos)
2262 i += nMatching;
2263
2264 // A comma was found -> break the loop
2265 if (sArgList[i] == cSep)
2266 {
2267 nPos = i;
2268 break;
2269 }
2270 }
2271
2272 // If no comma was found, simply use the complete string
2273 if (!nPos && sArgList[0] != cSep)
2274 nPos = sArgList.length();
2275
2276 // If the comma was at the first position, then return nothing
2277 if (!nPos)
2278 {
2279 if (sArgList[0] == cSep)
2280 sArgList.trim_front(1);
2281 return StringView();
2282 }
2283
2284 // Get the first argument
2285 StringView sArg = sArgList.subview(0, nPos);
2286 sArg.strip();
2287
2288 sArgList.trim_front(nPos+1);
2289
2290 // return the first argument
2291 return sArg;
2292}
2293
2294string getNextArgument(string& sArgList, bool bCut)
2295{
2296 StringView argList(sArgList);
2297 string sArg = getNextCommandLineToken(argList, ',').to_string();
2298
2299 if (bCut)
2300 sArgList = argList.to_string();
2301
2302 return sArg;
2303}
2304
2305string getNextIndex(string& sArgList, bool bCut)
2306{
2307 StringView argList(sArgList);
2308 string sArg = getNextCommandLineToken(argList, ':').to_string();
2309
2310 if (bCut)
2311 sArgList = argList.to_string();
2312
2313 return sArg;
2314}
2315
2316string getNextSemiColonSeparatedToken(string& sArgList, bool bCut)
2317{
2318 StringView argList(sArgList);
2319 string sArg = getNextCommandLineToken(argList, ';').to_string();
2320
2321 if (bCut)
2322 sArgList = argList.to_string();
2323
2324 return sArg;
2325}
2326
2328{
2329 return getNextCommandLineToken(sView, ',');
2330}
2331
2333{
2334 return getNextCommandLineToken(sView, ':');
2335}
2336
2337
2347{
2349
2350 while (sArgList.length())
2351 vArgs.push_back(getNextViewedArgument(sArgList));
2352
2353 return vArgs;
2354}
2355
2356
2366{
2368
2369 while (sArgList.length())
2370 vArgs.push_back(getNextArgument(sArgList, true));
2371
2372 return vArgs;
2373}
2374
2375
2385{
2386 EndlessVector<string> vIndices;
2387
2388 while (sArgList.length())
2389 vIndices.push_back(getNextIndex(sArgList, true));
2390
2391 return vIndices;
2392}
2393
2394
2404{
2405 EndlessVector<string> vIndices;
2406
2407 while (sArgList.length())
2408 vIndices.push_back(getNextSemiColonSeparatedToken(sArgList, true));
2409
2410 return vIndices;
2411}
2412
2413
2425void make_progressBar(int nStep, int nFirstStep, int nFinalStep, const string& sType)
2426{
2427 NumeReKernel::progressBar(nStep, nFirstStep, nFinalStep, sType);
2428 return;
2429}
2430
2431
2442static bool containsStringClusters(const string& sLine)
2443{
2444 const map<string,NumeRe::Cluster>& mClusterMap = NumeReKernel::getInstance()->getMemoryManager().getClusterMap();
2445
2446 for (auto iter = mClusterMap.begin(); iter != mClusterMap.end(); ++iter)
2447 {
2448 if (iter->second.isString())
2449 {
2450 size_t pos = sLine.find(iter->first + "{");
2451
2452 if (pos != string::npos && (!pos || isDelimiter(sLine[pos-1])))
2453 return true;
2454 }
2455 }
2456
2457 return false;
2458}
2459
2460
2470bool containsStrings(const string& sLine)
2471{
2472 if (!sLine.length())
2473 return false;
2474
2475 // It's only necessary to check the following functions.
2476 // All other string functions need strings as input
2477 if (sLine.find_first_of("\"#") != string::npos
2478 || sLine.find("string(") != string::npos
2479 || sLine.find("string_cast(") != string::npos
2480 || sLine.find("char(") != string::npos
2481 || sLine.find("getlasterror(") != string::npos
2482 || sLine.find("getversioninfo(") != string::npos
2483 || sLine.find("valtostr(") != string::npos
2484 || sLine.find("weekday(") != string::npos
2485 || sLine.find("to_tex(") != std::string::npos)
2486 return true;
2487
2488 return containsStringClusters(sLine);
2489}
2490
2491
2500bool fileExists(const string& sFilename)
2501{
2502 if (sFilename.length())
2503 {
2504 string _sFile = sFilename;
2505 _sFile = fromSystemCodePage(_sFile);
2506
2507 // Open the ifstream (ifstream doesn't create a file)
2508 ifstream ifFile(_sFile.c_str());
2509 return ifFile.good(); // If the stream is good(), the file exists
2510 }
2511 else
2512 return false;
2513}
2514
2515
2527void eraseToken(string& sExpr, const string& sToken, bool bTokenHasValue)
2528{
2529 unsigned int nLength = sToken.length();
2530
2531 // If the option token has a value, then the erase process is a bit more complex
2532 if (bTokenHasValue)
2533 {
2534 // Is the token actually available?
2535 if (!findParameter(sExpr, sToken, '='))
2536 return;
2537
2538 // Search for the option value
2539 for (unsigned int i = findParameter(sExpr, sToken, '=') + nLength - 1; i < sExpr.length(); i++)
2540 {
2541 // Assignment operator found
2542 if (sExpr[i] == '=')
2543 {
2544 // Find the end of the option value
2545 for (unsigned int j = sExpr.find_first_not_of("= ", i); j < sExpr.length(); j++)
2546 {
2547 // jump over parentheses
2548 if (!isInQuotes(sExpr, j) && (sExpr[j] == '(' || sExpr[j] == '[' || sExpr[j] == '{'))
2549 j += getMatchingParenthesis(sExpr.substr(j));
2550
2551 // White space found -> end of option value
2552 // erase token and its value together
2553 if (sExpr[j] == ' ')
2554 {
2555 sExpr.erase(findParameter(sExpr, sToken, '=') - 1, j - findParameter(sExpr, sToken, '=') + 1);
2556 return;
2557 }
2558 }
2559 }
2560 }
2561 }
2562 else
2563 {
2564 // Is the token actually available?
2565 if (!findParameter(sExpr, sToken))
2566 return;
2567
2568 // Simply erase the token
2569 sExpr.erase(findParameter(sExpr, sToken) - 1, nLength);
2570 }
2571}
2572
2573
2584vector<string> resolveChooseTokens(const string& sDirectory, const Settings& _option)
2585{
2586 vector<string> vResolved;
2587 vResolved.push_back(sDirectory);
2588 string sToken;
2589 unsigned int nSize = 0, nth_choose = 0;
2590 bool bResolvingPath = false;
2591
2592 // Is there at least one pipe in the directory?
2593 if (sDirectory.find('|') != string::npos)
2594 {
2595 // As long as the directory contains pipes
2596 while (vResolved[0].find('|') != string::npos)
2597 {
2598 // no opening angle for the token?
2599 if (!vResolved[0].rfind('<'))
2600 break;
2601
2602 // Get the token and remove the remaining part
2603 sToken = vResolved[0].substr(vResolved[0].rfind('<') + 1);
2604 sToken.erase(sToken.find('>'));
2605
2606 // Store the current size of the directory tree
2607 nSize = vResolved.size();
2608 nth_choose = 0;
2609
2610 // As long as a pipe is found in the token or the token has a length
2611 while (sToken.find('|') != string::npos || sToken.length())
2612 {
2613 // so lange ein "|" in dem Token gefunden wird, muss der Baum dupliziert werden
2614 if (sToken.find('|') != string::npos)
2615 {
2616 // duplicate the "root" tree
2617 for (unsigned int i = 0; i < nSize; i++)
2618 vResolved.push_back(vResolved[i + nth_choose * nSize]);
2619 }
2620
2621 // Replace the tokens with the first of the current tokens
2622 for (unsigned int i = nth_choose * nSize; i < (nth_choose + 1)*nSize; i++)
2623 {
2624 if (!bResolvingPath && vResolved[i].rfind('/') != string::npos && vResolved[i].rfind('/') > vResolved[i].rfind('>'))
2625 bResolvingPath = true;
2626 vResolved[i].replace(vResolved[i].rfind('<'), vResolved[i].rfind('>') + 1 - vResolved[i].rfind('<'), sToken.substr(0, sToken.find('|')));
2627 }
2628
2629 // If we want to resolve a path, then we have to do that with a recursion
2630 if (bResolvingPath
2631 && ((vResolved[nth_choose * nSize].find('*') != string::npos && vResolved[nth_choose * nSize].find('*') < vResolved[nth_choose * nSize].rfind('/'))
2632 || (vResolved[nth_choose * nSize].find('?') != string::npos && vResolved[nth_choose * nSize].find('?') < vResolved[nth_choose * nSize].rfind('/'))))
2633 {
2634 // Platzhalter in Pfaden werden mit einer Rekursion geloest.
2635 // Resolve the current tree
2636 vector<string> vFolderList = getFolderList(vResolved[nth_choose * nSize].substr(0, vResolved[nth_choose * nSize].rfind('/')), _option, 1);
2637
2638 // Remove obsolete paths (i.e. paths pointing to itself or to one directory further up
2639 for (unsigned int j = 0; j < vFolderList.size(); j++)
2640 {
2641 if ((vFolderList[j].length() >= 3 && vFolderList[j].substr(vFolderList[j].length() - 3) == "/..")
2642 || (vFolderList[j].length() >= 2 && vFolderList[j].substr(vFolderList[j].length() - 2) == "/."))
2643 {
2644 vFolderList.erase(vFolderList.begin() + j);
2645
2646 // If we erase the current position, we have to decrement the position
2647 j--;
2648 }
2649 }
2650
2651 // If we didn't get a result, remove the current token from the token list and continue
2652 if (!vFolderList.size())
2653 {
2654 bResolvingPath = false;
2655 nth_choose++;
2656 if (sToken.find('|') != string::npos)
2657 sToken.erase(0, sToken.find('|') + 1);
2658 else
2659 {
2660 sToken.clear();
2661 break;
2662 }
2663 continue;
2664 }
2665
2666 // Copy the obtained tree to the resolved tree
2667 for (unsigned int j = 0; j < vFolderList.size(); j++)
2668 {
2669 // Does the tree need to be duplicated?
2670 if (vFolderList.size() > 1 && j < vFolderList.size() - 1)
2671 {
2672 // ggf. Baum duplizieren
2673 if (vResolved.size() > (nth_choose + 1)*nSize)
2674 {
2675 for (unsigned int k = 0; k < nSize; k++)
2676 {
2677 vResolved.push_back(vResolved[k + (nth_choose + 1)*nSize]);
2678 vResolved[k + (nth_choose + 1)*nSize] = vResolved[k + nth_choose * nSize];
2679 }
2680 }
2681 else
2682 {
2683 for (unsigned int k = 0; k < nSize; k++)
2684 {
2685 vResolved.push_back(vResolved[(nth_choose)*nSize]);
2686 }
2687 }
2688 }
2689
2690 // simply replace the path part of the resolved tree
2691 for (unsigned int k = nth_choose * nSize; k < (nth_choose + 1)*nSize; k++)
2692 {
2693 vResolved[k].replace(0, vResolved[k].rfind('/'), vFolderList[j]);
2694 }
2695
2696 // Increment the choose token counter
2697 if (vFolderList.size() > 1 && j < vFolderList.size() - 1)
2698 nth_choose++;
2699 }
2700 }
2701
2702 // Erase the current token from the token list and continue
2703 bResolvingPath = false;
2704 nth_choose++;
2705 if (sToken.find('|') != string::npos)
2706 sToken.erase(0, sToken.find('|') + 1);
2707 else
2708 {
2709 sToken.clear();
2710 break;
2711 }
2712 }
2713 }
2714 }
2715
2716 // This is not using path tokens but place holders/wildcards in the path part
2717 if (vResolved[0].find('/') != string::npos
2718 && ((vResolved[0].find('*') != string::npos && vResolved[0].find('*') < vResolved[0].rfind('/'))
2719 || (vResolved[0].find('?') != string::npos && vResolved[0].find('?') < vResolved[0].rfind('/'))))
2720 {
2721 // Platzhalter in Pfaden werden mit einer Rekursion geloest.
2722 vector<string> vFolderList = getFolderList(vResolved[0].substr(0, vResolved[0].rfind('/')), _option, 1);
2723
2724 // store the current tree size
2725 nSize = vResolved.size();
2726
2727 // Remove obsolete paths (i.e. paths pointing to itself or to one directory further up
2728 for (unsigned int j = 0; j < vFolderList.size(); j++)
2729 {
2730 if ((vFolderList[j].length() >= 3 && vFolderList[j].substr(vFolderList[j].length() - 3) == "/..")
2731 || (vFolderList[j].length() >= 2 && vFolderList[j].substr(vFolderList[j].length() - 2) == "/."))
2732 {
2733 vFolderList.erase(vFolderList.begin() + j);
2734
2735 // If we erase the current position, we have to decrement the position
2736 j--;
2737 }
2738 }
2739
2740 // Return, if no result was found
2741 if (!vFolderList.size())
2742 return vResolved;
2743
2744 // Copy the resolved tree, if it is necessary
2745 for (unsigned int i = 0; i < vFolderList.size() - 1; i++)
2746 {
2747 // Don't use paths, which weren't resolved
2748 if (vFolderList[i].find('*') != string::npos || vFolderList[i].find('?') != string::npos || !vFolderList[i].size())
2749 continue;
2750
2751 // ggf. Baum duplizieren
2752 for (unsigned int k = 0; k < nSize; k++)
2753 {
2754 vResolved.push_back(vResolved[k]);
2755 }
2756
2757 }
2758
2759 // Replace the paths with wildcards with the results obtained by recursion
2760 for (unsigned int j = 0; j < vFolderList.size(); j++)
2761 {
2762 // Don't use paths, which weren't resolved
2763 if (vFolderList[j].find('*') != string::npos || vFolderList[j].find('?') != string::npos || !vFolderList[j].size())
2764 continue;
2765
2766 // replace the paths in the resolved tree
2767 for (unsigned int k = j * nSize; k < (j + 1)*nSize; k++)
2768 {
2769 vResolved[k].replace(0, vResolved[k].rfind('/'), vFolderList[j]);
2770 }
2771 }
2772 }
2773
2774 // return the resolved tree
2775 return vResolved;
2776}
2777
2778
2789static HANDLE initializeFileHandle(string& sDir, WIN32_FIND_DATA* FindFileData, const Settings& _option)
2790{
2791 HANDLE hFind = INVALID_HANDLE_VALUE;
2792 string sPath;
2793
2794 // Initialize the Windows structures
2795 if (sDir[0] == '.')
2796 {
2797 // Only a dot -> root path
2798 hFind = FindFirstFile((_option.getExePath() + "\\" + sDir).c_str(), FindFileData);
2799 sDir = replacePathSeparator(_option.getExePath() + "/" + sDir);
2800 sDir.erase(sDir.rfind('/') + 1);
2801 }
2802 else if (sDir[0] == '<')
2803 {
2804 // Get the default paths
2805 if (sDir.substr(0, 10) == "<loadpath>")
2806 sPath = _option.getLoadPath() + sDir.substr(sDir.find('>') + 1);
2807 else if (sDir.substr(0, 10) == "<savepath>")
2808 sPath = _option.getSavePath() + sDir.substr(sDir.find('>') + 1);
2809 else if (sDir.substr(0, 12) == "<scriptpath>")
2810 sPath = _option.getScriptPath() + sDir.substr(sDir.find('>') + 1);
2811 else if (sDir.substr(0, 10) == "<plotpath>")
2812 sPath = _option.getPlotPath() + sDir.substr(sDir.find('>') + 1);
2813 else if (sDir.substr(0, 10) == "<procpath>")
2814 sPath = _option.getProcPath() + sDir.substr(sDir.find('>') + 1);
2815 else if (sDir.substr(0, 2) == "<>")
2816 sPath = _option.getExePath() + sDir.substr(sDir.find('>') + 1);
2817 else if (sDir.substr(0, 6) == "<this>")
2818 sPath = _option.getExePath() + sDir.substr(sDir.find('>') + 1);
2819 else if (sDir.substr(0, 4) == "<wp>")
2820 sPath = _option.getWorkPath() + sDir.substr(sDir.find('>') + 1);
2821
2822 // If the path has a length then initialize the file handle
2823 if (sPath.length())
2824 {
2825 hFind = FindFirstFile(sPath.c_str(), FindFileData);
2826 sDir = replacePathSeparator(sPath);
2827 sDir.erase(sDir.rfind('/') + 1);
2828 }
2829 }
2830 else
2831 {
2832 // an arbitrary path
2833 hFind = FindFirstFile(sDir.c_str(), FindFileData);
2834 if (sDir.find('/') != string::npos)
2835 sDir.erase(sDir.rfind('/') + 1);
2836 }
2837
2838 // return the initialized file handle
2839 return hFind;
2840}
2841
2842
2853vector<string> getFileList(const string& sDirectory, const Settings& _option, int nFlags)
2854{
2855 vector<string> vFileList;
2856 vector<string> vDirList;
2857
2858 // Replace the Windows-Style Path separators to Unix-Style
2859 string sDir = replacePathSeparator(sDirectory);
2860
2861 // Get the resolved tree
2862 vDirList = resolveChooseTokens(sDir, _option);
2863
2864 // Walk through the resolved tree
2865 for (unsigned int i = 0; i < vDirList.size(); i++)
2866 {
2867 sDir = vDirList[i];
2868
2869 // Append a wildcard, if one is missing
2870 if (sDir.rfind('.') == string::npos && sDir.find('*') == string::npos && sDir.find('?') == string::npos)
2871 {
2872 if (sDir[sDir.find_last_not_of(' ')] != '/')
2873 sDir += '/';
2874 sDir += "*";
2875 }
2876 else if ((sDir.find('.') == string::npos
2877 || (sDir.find('.') != string::npos && sDir.find('/', sDir.rfind('.')) != string::npos))
2878 && sDir.back() != '*')
2879 sDir += "*";
2880
2881 // Declare the Windows structures;
2882 WIN32_FIND_DATA FindFileData;
2883 HANDLE hFind = initializeFileHandle(sDir, &FindFileData, _option);
2884
2885 // Ensure that the structures were initialized correctly
2886 if (hFind == INVALID_HANDLE_VALUE)
2887 continue;
2888
2889 // As long as the FindNextFile function returns non-zero
2890 // read the contents of FindFileData
2891 do
2892 {
2893 // Ignore directories
2894 if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2895 continue;
2896
2897 // Push back filenames
2898 if (nFlags & 1)
2899 vFileList.push_back(sDir + FindFileData.cFileName);
2900 else
2901 vFileList.push_back(FindFileData.cFileName);
2902 }
2903 while (FindNextFile(hFind, &FindFileData) != 0);
2904
2905 // Close the handle
2906 FindClose(hFind);
2907 }
2908
2909 // Return the obtained file list
2910 return vFileList;
2911}
2912
2913
2925vector<string> getFolderList(const string& sDirectory, const Settings& _option, int nFlags)
2926{
2927 vector<string> vFileList;
2928 vector<string> vDirList;
2929
2930 // Replace the Windows-Style Path separators to Unix-Style
2931 string sDir = replacePathSeparator(sDirectory);
2932
2933 // Get the resolved tree
2934 vDirList = resolveChooseTokens(sDir, _option);
2935
2936 // Walk through the resolved tree
2937 for (unsigned int i = 0; i < vDirList.size(); i++)
2938 {
2939 sDir = vDirList[i];
2940
2941 // Append a wildcard, if one is missing
2942 if (sDir.rfind('.') == string::npos && sDir.find('*') == string::npos && sDir.find('?') == string::npos)
2943 {
2944 if (sDir[sDir.find_last_not_of(' ')] != '/')
2945 sDir += '/';
2946 sDir += "*";
2947 }
2948 else if ((sDir.find('.') == string::npos
2949 || (sDir.find('.') != string::npos && sDir.find('/', sDir.rfind('.')) != string::npos))
2950 && sDir.back() != '*')
2951 sDir += "*";
2952
2953 // Declare the Windows structures;
2954 WIN32_FIND_DATA FindFileData;
2955 HANDLE hFind = initializeFileHandle(sDir, &FindFileData, _option);
2956
2957 // Ensure that the structures were initialized correctly
2958 if (hFind == INVALID_HANDLE_VALUE)
2959 continue;
2960
2961 // As long as the FindNextFile function returns non-zero
2962 // read the contents of FindFileData
2963 do
2964 {
2965 // USe directories
2966 if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2967 {
2968 // Push back the directories
2969 if (nFlags & 1)
2970 vFileList.push_back(sDir + FindFileData.cFileName);
2971 else
2972 vFileList.push_back(FindFileData.cFileName);
2973 }
2974 else // ignore files
2975 continue;
2976
2977 }
2978 while (FindNextFile(hFind, &FindFileData) != 0);
2979
2980 // Close the handle
2981 FindClose(hFind);
2982 }
2983
2984 // Return the obtained file list
2985 return vFileList;
2986}
2987
2988
2998void reduceLogFilesize(const string& sFileName)
2999{
3000 fstream fFile;
3001 size_t nLines = 0;
3002 string sTemp;
3003 const size_t MAXLINES = 100000;
3004 const size_t MINLINES = 20000;
3005
3006 // Open the logfile and check, whether the file stream is OK
3007 fFile.open(sFileName.c_str(), ios_base::binary | ios_base::in);
3008 if (fFile.fail())
3009 return;
3010
3011 // Count the lines in the log file
3012 while (!fFile.eof())
3013 {
3014 getline(fFile, sTemp);
3015 nLines++;
3016 }
3017
3018 // Clear the file state and return to the first position
3019 fFile.clear();
3020 fFile.seekg(0);
3021
3022 // If the number of lines is larger than the predefined lines
3023 if (nLines >= MAXLINES)
3024 {
3025 fstream fTemp;
3026
3027 // Open a temporary file in binary mode and check, whether the file is good
3028 fTemp.open("$~tempfile.txt", ios_base::binary | ios_base::out);
3029 if (fTemp.fail())
3030 return;
3031
3032 // Copy the last 20.000 lines of the log file to the temporary file
3033 for (unsigned int i = 0; i < nLines; i++)
3034 {
3035 getline(fFile, sTemp);
3036 if (nLines - i > MINLINES)
3037 continue;
3038 fTemp << sTemp << endl;
3039 }
3040
3041 // Close the file streams
3042 fFile.close();
3043 fTemp.close();
3044
3045 // Re-open the file streams with exchanged read/write flags
3046 // and a truncate flag on the log file
3047 fTemp.open("$~tempfile.txt", ios_base::binary | ios_base::in);
3048 fFile.open(sFileName.c_str(), ios_base::trunc | ios_base::binary | ios_base::out);
3049 fTemp.seekg(0);
3050
3051 // Copy the entire content of the temporary file
3052 // (i.e. the last 20.000 lines of the original log file)
3053 fFile << fTemp.rdbuf();
3054
3055 // Close the file streams and remove the temporary file
3056 fFile.close();
3057 fTemp.close();
3058 remove("$~tempfile.txt");
3059 }
3060}
3061
3062
3073static void OprtRplc_setup(map<string, string>& mOprtRplc)
3074{
3075 mOprtRplc["("] = "[";
3076 mOprtRplc[")"] = "]";
3077 mOprtRplc[":"] = "~c~";
3078 mOprtRplc[","] = "_";
3079 mOprtRplc["."] = "_";
3080 mOprtRplc["+"] = "~p~";
3081 mOprtRplc["-"] = "~m~";
3082 mOprtRplc["*"] = "~ml~";
3083 mOprtRplc["/"] = "~d~";
3084 mOprtRplc["^"] = "~e~";
3085 mOprtRplc["{"] = "~ob~";
3086 mOprtRplc["}"] = "~cb~";
3087 mOprtRplc["&"] = "~a~";
3088 mOprtRplc["|"] = "~o~";
3089 mOprtRplc["%"] = "~md~";
3090 mOprtRplc["!"] = "~n~";
3091 mOprtRplc["="] = "~eq~";
3092 mOprtRplc[">"] = "~g~";
3093 mOprtRplc["<"] = "~l~";
3094 mOprtRplc["?"] = "~q~";
3095}
3096
3097
3108string replaceToVectorname(const string& sExpression)
3109{
3110 string sVectorName = sExpression;
3111 static map<string, string> mOprtRplc;
3112
3113 // If the map wasn't initialized do that now
3114 if (!mOprtRplc.size())
3115 OprtRplc_setup(mOprtRplc);
3116
3117 // Remove whitespaces
3118 while (sVectorName.find(' ') != string::npos)
3119 sVectorName.erase(sVectorName.find(' '), 1);
3120
3121 // Replace mathematical operators
3122 for (auto iter = mOprtRplc.begin(); iter != mOprtRplc.end(); ++iter)
3123 {
3124 while (sVectorName.find(iter->first) != string::npos)
3125 sVectorName.replace(sVectorName.find(iter->first), (iter->first).length(), iter->second);
3126 }
3127
3128 if (sVectorName.find('[') == string::npos)
3129 sVectorName += "[]";
3130
3131 // return the new vector name
3132 return "_~" + sVectorName;
3133}
3134
3135
3146static bool handleRecursiveOperators(string& sExpr, size_t& nPos, size_t& nArgSepPos)
3147{
3148 size_t nLength = 2;
3149 if (sExpr.substr(nPos, 3) == "**=")
3150 nLength = 3;
3151 // Do we find another comma?
3152 if (sExpr.find(',', nPos) != string::npos)
3153 {
3154 int nQuotes = 0;
3155
3156 // Go through the remaining expression and try to find the end
3157 // of the current expression part
3158 for (unsigned int j = nPos; j < sExpr.length(); j++)
3159 {
3160 // Jump over parentheses
3161 if (!(nQuotes % 2)
3162 && (sExpr[j] == '(' || sExpr[j] == '[' || sExpr[j] == '{'))
3163 j += getMatchingParenthesis(sExpr.substr(j));
3164
3165 // Count the not escaped parentheses
3166 if (sExpr[j] == '"')
3167 {
3168 if (j && sExpr[j - 1] == '\\')
3169 continue;
3170 nQuotes++;
3171 }
3172
3173 // continue, if we're inside of quotation marks
3174 if (nQuotes % 2)
3175 continue;
3176
3177 // Do we find a comma or did we reach the end of the whole expression?
3178 if (sExpr[j] == ',' || j + 1 == sExpr.length())
3179 {
3180 // Do we have a comma now?
3181 if (j + 1 != sExpr.length())
3182 {
3183 // The comma case
3184 if (!nArgSepPos)
3185 {
3186 sExpr = sExpr.substr(0, nPos)
3187 + " = "
3188 + sExpr.substr(0, nPos)
3189 + sExpr.substr(nPos, nLength-1)
3190 + "("
3191 + sExpr.substr(nPos + nLength, j - nPos - nLength)
3192 + ") "
3193 + sExpr.substr(j);
3194 }
3195 else
3196 {
3197 sExpr = sExpr.substr(0, nPos)
3198 + " = "
3199 + sExpr.substr(nArgSepPos + 1, nPos - nArgSepPos - 1)
3200 + sExpr.substr(nPos, nLength-1)
3201 + "("
3202 + sExpr.substr(nPos + nLength, j - nPos - nLength)
3203 + ") "
3204 + sExpr.substr(j);
3205 }
3206 }
3207 else
3208 {
3209 // The end-of-expression case
3210 if (!nArgSepPos)
3211 {
3212 sExpr = sExpr.substr(0, nPos)
3213 + " = "
3214 + sExpr.substr(0, nPos)
3215 + sExpr.substr(nPos, nLength-1)
3216 + "("
3217 + sExpr.substr(nPos + nLength)
3218 + ") ";
3219 }
3220 else
3221 {
3222 sExpr = sExpr.substr(0, nPos)
3223 + " = "
3224 + sExpr.substr(nArgSepPos + 1, nPos - nArgSepPos - 1)
3225 + sExpr.substr(nPos, nLength-1)
3226 + "("
3227 + sExpr.substr(nPos + nLength)
3228 + ") ";
3229 }
3230
3231 // return false means: this is the end of the expression
3232 return false;
3233 }
3234
3235 // Go through the expression and try to find the next argument separator
3236 for (unsigned int k = nPos; k < sExpr.length(); k++)
3237 {
3238 // Jump over parentheses
3239 if (!(nQuotes % 2)
3240 && (sExpr[k] == '(' || sExpr[k] == '[' || sExpr[k] == '{'))
3241 k += getMatchingParenthesis(sExpr.substr(k));
3242
3243 // Count the quotation marks, which are not escaped
3244 if (sExpr[k] == '"')
3245 {
3246 if (k && sExpr[k - 1] == '\\')
3247 continue;
3248 nQuotes++;
3249 }
3250
3251 // Contine, if we're inside of quotation marks
3252 if (nQuotes % 2)
3253 continue;
3254
3255 // Do we find a comma?
3256 // Update all index variables and break
3257 // the current loop
3258 if (sExpr[k] == ',')
3259 {
3260 nArgSepPos = k;
3261 nPos = k;
3262 break;
3263 }
3264 }
3265
3266 // break this loop
3267 break;
3268 }
3269 }
3270 }
3271 else
3272 {
3273 // Simple case: no further comma
3274 if (!nArgSepPos)
3275 {
3276 sExpr = sExpr.substr(0, nPos)
3277 + " = "
3278 + sExpr.substr(0, nPos)
3279 + sExpr.substr(nPos, nLength-1)
3280 + "("
3281 + sExpr.substr(nPos + nLength)
3282 + ")";
3283 }
3284 else
3285 {
3286 sExpr = sExpr.substr(0, nPos)
3287 + " = "
3288 + sExpr.substr(nArgSepPos + 1, nPos - nArgSepPos - 1)
3289 + sExpr.substr(nPos, nLength-1)
3290 + "("
3291 + sExpr.substr(nPos + nLength)
3292 + ")";
3293 }
3294
3295 // return false means: was last expression
3296 return false;
3297 }
3298
3299 // return true means: continue the detection of recursive expressions
3300 return true;
3301}
3302
3303
3314static void handleIncAndDecOperators(string& sExpr, size_t nPos, size_t nArgSepPos)
3315{
3316 if (!nArgSepPos)
3317 {
3318 sExpr = sExpr.substr(0, nPos)
3319 + " = "
3320 + sExpr.substr(0, nPos)
3321 + sExpr[nPos]
3322 + "1"
3323 + sExpr.substr(nPos + 2);
3324 }
3325 else
3326 {
3327 sExpr = sExpr.substr(0, nPos)
3328 + " = "
3329 + sExpr.substr(nArgSepPos + 1, nPos - nArgSepPos - 1)
3330 + sExpr[nPos]
3331 + "1"
3332 + sExpr.substr(nPos + 2);
3333 }
3334}
3335
3336
3346void evalRecursiveExpressions(string& sExpr)
3347{
3348 // Ignore flow control blocks
3349 if (sExpr.substr(0, 3) == "if "
3350 || sExpr.substr(0, 3) == "if("
3351 || sExpr.substr(0, 7) == "elseif "
3352 || sExpr.substr(0, 7) == "elseif("
3353 || sExpr.substr(0, 5) == "else "
3354 || sExpr.substr(0, 7) == "switch "
3355 || sExpr.substr(0, 7) == "switch("
3356 || sExpr.substr(0, 5) == "case "
3357 || sExpr.substr(0, 8) == "default:"
3358 || sExpr.substr(0, 4) == "for "
3359 || sExpr.substr(0, 4) == "for("
3360 || sExpr.substr(0, 6) == "while "
3361 || sExpr.substr(0, 6) == "while(")
3362 return;
3363
3364 unsigned int nArgSepPos = 0;
3365 int nQuotes = 0;
3366 bool bAnswerSuppressor = false;
3367
3368 // Find the trailing semicolon
3369 if (sExpr.find_last_not_of(" \t") != string::npos && sExpr[sExpr.find_last_not_of(" \t")] == ';')
3370 {
3371 sExpr.erase(sExpr.find_last_not_of(" \t"));
3372 bAnswerSuppressor = true;
3373 }
3374
3375 // Go through the complete expression
3376 for (unsigned int i = 0; i < sExpr.length(); i++)
3377 {
3378 // Jump over parentheses
3379 if (!(nQuotes % 2)
3380 && (sExpr[i] == '(' || sExpr[i] == '{' || sExpr[i] == '['))
3381 {
3382 size_t parens = getMatchingParenthesis(sExpr.substr(i));
3383 if (parens != string::npos)
3384 i += parens;
3385 }
3386
3387 // Count the quatation marks, which are not escaped
3388 if (sExpr[i] == '"')
3389 {
3390 if (i && sExpr[i - 1] == '\\')
3391 continue;
3392 nQuotes++;
3393 }
3394
3395 // Continue, if we're inside of quotation marks
3396 if (nQuotes % 2) // nQuotes % 2 == 1, wenn eine ungerade Zahl an Anfuehrungszeichen aufgetreten ist => die Position befindet sich als hinter einem geoeffneten Anfuehrungszeichen.
3397 continue;
3398
3399 // If there's a comma, store its position as
3400 // argument/expression separator and continue
3401 if (sExpr[i] == ',')
3402 {
3403 nArgSepPos = i;
3404 continue;
3405 }
3406
3407 // Do we find a recursive expression?
3408 if (sExpr.substr(i, 2) == "+="
3409 || sExpr.substr(i, 2) == "-="
3410 || sExpr.substr(i, 3) == "**="
3411 || sExpr.substr(i, 2) == "*="
3412 || sExpr.substr(i, 2) == "/="
3413 || sExpr.substr(i, 2) == "^=")
3414 {
3415 // if the handler returns false, we may break the loop
3416 if (!handleRecursiveOperators(sExpr, i, nArgSepPos))
3417 break;
3418 }
3419
3420 // Do we find a increment or decrement operator?
3421 if (sExpr.substr(i, 2) == "++" || sExpr.substr(i, 2) == "--")
3422 {
3423 // Handle this type of operators
3424 handleIncAndDecOperators(sExpr, i, nArgSepPos);
3425 }
3426 }
3427
3428 // Add the trailing semicolon
3429 if (bAnswerSuppressor)
3430 sExpr += ";";
3431
3432 return;
3433}
3434
3435
3436
3446string getFileInfo(const string& sFileName)
3447{
3448 NumeRe::NumeReDataFile file(sFileName);
3449 string sFileInfo;
3450
3451 try
3452 {
3453 file.readFileInformation();
3454 }
3455 catch (...)
3456 {
3457 return "";
3458 }
3459
3461
3462 sFileInfo = toString(info.timeStamp, 0)
3463 + " (NDAT v" + toString(info.fileVersion, 5) + ") | "
3464 + toString(info.nRows) + " x " + toString(info.nCols) + " | \"" + info.sTableName + "()\"";
3465
3466 if (info.sComment.length() > 204)
3467 sFileInfo += "\n" + info.sComment.substr(0, 200) + "...";
3468 else if (info.sComment.length())
3469 sFileInfo += "\n" + info.sComment;
3470
3471 // Return the read file meta information
3472 return sFileInfo;
3473}
3474
3475
3476string decodeNameSpace(string sCommandLine, const string& sThisNameSpace)
3477{
3478 string sNameSpace = "";
3479
3480 if (sCommandLine.find("namespace") != string::npos)
3481 {
3482 sCommandLine.erase(0, sCommandLine.find("namespace") + 9);
3483
3484 while (sCommandLine.back() == '\r' || sCommandLine.back() == '\n')
3485 sCommandLine.pop_back();
3486
3487 StripSpaces(sCommandLine);
3488
3489 if (sCommandLine.substr(0, 5) == "this~" || sCommandLine == "this")
3490 sCommandLine.replace(0, 4, sThisNameSpace);
3491
3492 while (sCommandLine.back() == '~')
3493 sCommandLine.pop_back();
3494
3495 if (sCommandLine != "main")
3496 sNameSpace = sCommandLine;
3497 }
3498
3499 return sNameSpace;
3500}
3501
3502
3512bool validateParenthesisNumber(const string& sCmd)
3513{
3514 int nParCount = 0;
3515 int nVectCount = 0;
3516 int nBracketCount = 0;
3517 int nQuotes = 0;
3518
3519 // Go through the whole string
3520 for (size_t i = 0; i < sCmd.length(); i++)
3521 {
3522 // This function counts the quotation marks by itself
3523 // because it's much faster
3524 if (sCmd[i] == '"' && (!i || sCmd[i - 1] != '\\'))
3525 nQuotes++;
3526
3527 // If we're not in quotation marks
3528 if (!(nQuotes % 2))
3529 {
3530 // Count the opening and closing parentheses
3531 if (sCmd[i] == '(')
3532 nParCount++;
3533 else if (sCmd[i] == ')')
3534 nParCount--;
3535 else if (sCmd[i] == '{')
3536 nVectCount++;
3537 else if (sCmd[i] == '}')
3538 nVectCount--;
3539 else if (sCmd[i] == '[')
3540 nBracketCount++;
3541 else if (sCmd[i] == ']')
3542 nBracketCount--;
3543 }
3544 }
3545
3546 // If one of the counters is nonzero, something is wrong
3547 return !((bool)nParCount || (bool)nVectCount || (bool)nBracketCount);
3548}
3549
3550
3560void addArgumentQuotes(string& sToAdd, const string& sParam)
3561{
3562 // Check, whether the parameter exists
3563 if (findParameter(sToAdd, sParam, '='))
3564 {
3565 // Store the position of the equal sign of the parameter token
3566 addArgumentQuotes(sToAdd, findParameter(sToAdd, sParam, '=') + sParam.length());
3567 }
3568}
3569
3570
3580void addArgumentQuotes(string& sToAdd, size_t pos)
3581{
3582 // Jump over following whitespaces
3583 while (sToAdd[pos] == ' ')
3584 pos++;
3585
3586 // Only if the value doesn't contain strings
3587 if (!containsStrings(sToAdd.substr(pos, sToAdd.find(' ', pos) - pos)))
3588 {
3589 // Add surrounding quotation marks
3590 sToAdd = sToAdd.substr(0, pos)
3591 + "\"" + getArgAtPos(sToAdd, pos) + "\""
3592 + sToAdd.substr(sToAdd.find(' ', sToAdd.find(getArgAtPos(sToAdd, pos)) + getArgAtPos(sToAdd, pos).length()));
3593 }
3594}
3595
3596
3607double intPower(double dNumber, int nExponent)
3608{
3609 long double dResult = 1.0L;
3610
3611 // An exponent of zero returns always 1
3612 if (!nExponent)
3613 return 1.0;
3614
3615 // Calculuate the exponentation
3616 for (int i = abs(nExponent); i > 0; i--)
3617 {
3618 dResult *= (long double)dNumber;
3619 }
3620
3621 // Apply the sign of the exponent
3622 if (nExponent > 0)
3623 return dResult;
3624 else
3625 return 1.0 / dResult;
3626}
3627
3628
3640std::complex<double> intPower(const std::complex<double>& dNumber, int nExponent)
3641{
3642 if (dNumber.imag() == 0.0)
3643 return intPower(dNumber.real(), nExponent);
3644
3645 std::complex<double> dResult = 1.0;
3646
3647 // An exponent of zero returns always 1
3648 if (!nExponent)
3649 return 1.0;
3650
3651 // Calculuate the exponentation
3652 for (int i = abs(nExponent); i > 0; i--)
3653 {
3654 dResult *= dNumber;
3655 }
3656
3657 // Apply the sign of the exponent
3658 if (nExponent > 0)
3659 return dResult;
3660 else
3661 return 1.0 / dResult;
3662}
3663
3664
3675bool isToCmd(const string& sCmd, unsigned int nPos)
3676{
3677 // Exclude border cases
3678 if (nPos < 6 || nPos >= sCmd.length())
3679 return false;
3680 if (sCmd.find("to_cmd(") == string::npos || sCmd.find("to_cmd(") > nPos)
3681 return false;
3682
3683 // Go through the whole string and try to find the functions arguments
3684 for (int i = nPos - 6; i >= 0; i--)
3685 {
3686 if (sCmd.substr(i, 7) == "to_cmd(" && !isInQuotes(sCmd, i))
3687 {
3688 // function found -> try to find the matching parenthesis
3689 // If it is left of the desired position, then return true
3690 if (getMatchingParenthesis(sCmd.substr(i + 6)) > nPos - i - 6 && getMatchingParenthesis(sCmd.substr(i + 6)) != string::npos)
3691 return true;
3692 }
3693 }
3694
3695 // End was reached -> return false
3696 return false;
3697}
3698
3699
3708unsigned int countEscapeSymbols(const string& sLine)
3709{
3710 unsigned int nCount = 0;
3711
3712 // Go through the line
3713 for (unsigned int i = 0; i < sLine.length(); i++)
3714 {
3715 // If we find a escaped dollar sign, increment the counter
3716 if (sLine.substr(i, 2) == "\\$")
3717 nCount++;
3718 }
3719
3720 // return the number of escaped dollar signs
3721 return nCount;
3722}
3723
3724
3734static int compareDouble(const void* p1, const void* p2)
3735{
3736 if (isnan(*(double*)p1) && isnan(*(double*)p2))
3737 return 0;
3738
3739 if (isnan(*(double*)p1))
3740 return 1;
3741
3742 if (isnan(*(double*)p2))
3743 return -1;
3744
3745 return *(double*)p1 == *(double*)p2
3746 ? 0
3747 : -(*(double*)p1 < *(double*)p2) + (*(double*)p1 > *(double*)p2); // Returns -1 for smaller and +1 for larger
3748}
3749
3750
3762size_t qSortDouble(double* dArray, size_t nlength)
3763{
3764 // Sort the passed array using the compareDouble helper function
3765 qsort((void*)dArray, nlength, sizeof(double), compareDouble);
3766
3767 // Exclude the NaNs in the array
3768 for (int i = nlength - 1; i >= 0; i--)
3769 {
3770 if (!isnan(dArray[i]) && !isinf(dArray[i]))
3771 return i + 1;
3772 }
3773 return 0;
3774}
3775
3776
3791static void replaceSearchMethods(string& sLine, size_t nPos, size_t nFinalPos, const string& sReplacement, const string& sMethod, string& sArgument)
3792{
3793 // Prepare the argument (use empty one or construct one
3794 // from argument and variable value)
3795 if (sArgument == "()")
3796 sArgument = "(" + sReplacement + ", " + sReplacement + ")";
3797 else if (sArgument.find(',') == string::npos)
3798 sArgument.insert(sArgument.length()-1, ", " + sReplacement + "");
3799 else
3800 {
3801 string sTemp = "(";
3802 sArgument.erase(0,1);
3803 sTemp += getNextArgument(sArgument, true);
3804 sTemp += ", " + sReplacement;
3805
3806 if (sArgument[sArgument.find_first_not_of(' ')] == ')')
3807 sArgument = sTemp + ")";
3808 else
3809 sArgument = sTemp + ", " + sArgument;
3810 }
3811
3812 // Replace the method with its standard function signature
3813 if (sMethod == "fnd")
3814 sLine.replace(nPos, nFinalPos-nPos, "strfnd" + sArgument);
3815 else if (sMethod == "rfnd")
3816 sLine.replace(nPos, nFinalPos-nPos, "strrfnd" + sArgument);
3817 else if (sMethod == "mtch")
3818 sLine.replace(nPos, nFinalPos-nPos, "strmatch" + sArgument);
3819 else if (sMethod == "rmtch")
3820 sLine.replace(nPos, nFinalPos-nPos, "strrmatch" + sArgument);
3821 else if (sMethod == "nmtch")
3822 sLine.replace(nPos, nFinalPos-nPos, "str_not_match" + sArgument);
3823 else if (sMethod == "nrmtch")
3824 sLine.replace(nPos, nFinalPos-nPos, "str_not_rmatch" + sArgument);
3825}
3826
3827
3843static void replaceAccessMethods(string& sLine, size_t nPos, size_t nFinalPos, const string& sReplacement, const string& sMethod, string& sArgument)
3844{
3845 // Prepare the argument (use empty one or construct one
3846 // from argument and variable value)
3847 if (sArgument == "()")
3848 sArgument = "(" + sReplacement + ", 1)";
3849 else
3850 sArgument.insert(1, sReplacement + ", ");
3851
3852 // Replace the method with its standard function signature
3853 if (sMethod == "at")
3854 sLine.replace(nPos, nFinalPos-nPos, "char" + sArgument);
3855 else if (sMethod == "sub")
3856 sLine.replace(nPos, nFinalPos-nPos, "substr" + sArgument);
3857 else if (sMethod == "splt")
3858 sLine.replace(nPos, nFinalPos-nPos, "split" + sArgument);
3859}
3860
3861
3875void replaceStringMethod(string& sLine, size_t nPos, size_t nLength, const string& sReplacement)
3876{
3877 // Does the string variable name end with a dot?
3878 if (sLine[nPos+nLength] != '.')
3879 {
3880 sLine.replace(nPos, nLength, sReplacement);
3881 return;
3882 }
3883
3884 static const string sDELIMITER = "+-*/ ={}^&|!,\\%#?:\";";
3885 string sMethod = "";
3886 string sArgument = "";
3887 size_t nFinalPos = 0;
3888
3889 // Find the end of the appended method. This is either
3890 // the closing parenthesis or a delimiter character. Split
3891 // the found method into its name and its argument
3892 for (size_t i = nPos+nLength+1; i < sLine.length(); i++)
3893 {
3894 if (sLine[i] == '(')
3895 {
3896 // Method ends with closing parenthesis
3897 sMethod = sLine.substr(nPos+nLength+1, i-(nPos+nLength+1));
3898 sArgument = sLine.substr(i, getMatchingParenthesis(sLine.substr(i))+1);
3899 nFinalPos = i += getMatchingParenthesis(sLine.substr(i))+1;
3900 break;
3901 }
3902 else if (sDELIMITER.find(sLine[i]) != string::npos)
3903 {
3904 // Method ends with a delimiter
3905 sMethod = sLine.substr(nPos+nLength+1, i-(nPos+nLength+1));
3906 nFinalPos = i;
3907 break;
3908 }
3909 }
3910
3911 // If the argument list is empty, use an empty
3912 // parenthesis instead
3913 if (!sArgument.length())
3914 sArgument = "()";
3915
3916 // This if-else constrct replaces the found
3917 // method occurences with their standard string function
3918 if (sMethod == "len")
3919 {
3920 // String length methods
3921 sLine.replace(nPos, nFinalPos-nPos, "strlen(" + sReplacement + ")");
3922 }
3923 else if (sMethod == "at"
3924 || sMethod == "sub"
3925 || sMethod == "splt")
3926 {
3927 // Access methods and splitter
3928 replaceAccessMethods(sLine, nPos, nFinalPos, sReplacement, sMethod, sArgument);
3929 }
3930 else if (sMethod == "fnd"
3931 || sMethod == "rfnd"
3932 || sMethod == "mtch"
3933 || sMethod == "rmtch"
3934 || sMethod == "nmtch"
3935 || sMethod == "nrmtch")
3936 {
3937 // All search-oriented methods
3938 replaceSearchMethods(sLine, nPos, nFinalPos, sReplacement, sMethod, sArgument);
3939 }
3940}
3941
3942
3953std::string shortenFileName(const std::string& sFullFileName)
3954{
3955 size_t nPos = std::string::npos;
3956
3957 std::string sFileName = replacePathSeparator(sFullFileName);
3958
3959 while (sFileName.rfind('/', nPos) != string::npos)
3960 {
3961 nPos = sFileName.rfind('/', nPos);
3962
3963 if (nPos != 0 && nPos-1 != ':')
3964 {
3965 size_t nPos_2 = sFileName.rfind('/', nPos-1);
3966
3967 if (nPos_2 != string::npos)
3968 {
3969 sFileName = sFileName.substr(0,nPos_2+1) + ".." + sFileName.substr(nPos);
3970 nPos = nPos_2;
3971 }
3972 else
3973 break;
3974 }
3975 else
3976 break;
3977 }
3978
3979 return sFileName;
3980}
3981
3982
3991std::string incrementVersion(std::string _sVer)
3992{
3993 // Increment the version by one (corresponds to
3994 // the build count)
3995 return intToVersion(versionToInt(_sVer)+1);
3996}
3997
std::string toLowerCase(const std::string &)
Converts uppercase to lowercase letters.
This class extends the std::vector for endlessness.
Definition: structures.hpp:838
bool call(std::string &sExpr, int nRecursion=0)
This function searches for known custom definitions in the passed expression and replaces them with t...
Definition: define.cpp:801
bool containsTablesOrClusters(const std::string &sCmdLine)
This member function evaluates, whether the passed command line contains tables or clusters.
const std::map< std::string, Cluster > & getClusterMap() const
Definition: cluster.hpp:475
This class resembles the binary NumeRe data file format. The data is red and written in binary mode u...
Definition: file.hpp:1471
void readFileInformation()
Reads only the header of the referenced file.
Definition: file.hpp:1523
virtual FileHeaderInfo getFileHeaderInformation() override
Returns the file header information structure.
Definition: file.hpp:1540
virtual bool isStringExpression(const std::string &sExpression) override
Returns true, if the passed expression is an expression containing strings, string variables or strin...
StringParserRetVal evalAndFormat(std::string &sLine, std::string &sCache, bool bSilent=false, bool bCheckAssertions=false)
This public member function evaluates the passed string expression and formats the results for the co...
This class provides the interface to the core of NumeRe. It provides all functionalities,...
Definition: kernel.hpp:97
static NumeReKernel * getInstance()
This static member function returns a a pointer to the singleton instance of the kernel.
Definition: kernel.hpp:221
NumeRe::StringParser & getStringParser()
Definition: kernel.hpp:286
mu::Parser & getParser()
Definition: kernel.hpp:281
MemoryManager & getMemoryManager()
Definition: kernel.hpp:263
static void progressBar(int nStep, int nFirstStep, int nFinalStep, const std::string &sType)
This function displays a progress bar constructed from characters in the terminal.
Definition: kernel.cpp:2950
FunctionDefinitionManager & getDefinitions()
Definition: kernel.hpp:291
Settings & getSettings()
Definition: kernel.hpp:296
This class manages the setting values of the internal (kernel) settings of this application.
Definition: settings.hpp:663
std::string getLoadPath() const
Returns the current loading path.
Definition: settings.hpp:1038
std::string getWorkPath() const
Returns the current working path (connected to the <wp> token).
Definition: settings.hpp:1020
std::string getSavePath() const
Returns the current saving path.
Definition: settings.hpp:1029
size_t getPrecision() const
Returns the precision for displaying floating numbers in the terminal. This value determines the numb...
Definition: settings.hpp:1000
std::string getProcPath() const
Returns the current procedure root import path.
Definition: settings.hpp:1068
std::string getPlotPath() const
Returns the current plotting path (plot storing location).
Definition: settings.hpp:1048
std::string getExePath() const
Returns the current application root folder path.
Definition: settings.hpp:1010
size_t getWindow(int nWindow=0) const
Returns the current window size of the terminal.
Definition: settings.hpp:1101
std::string getScriptPath() const
Returns the current script import folder path.
Definition: settings.hpp:1058
size_t rfind(const std::string &findstr, size_t pos=std::string::npos) const
Wrapper member function for std::string::rfind()
void strip()
This member function shrinks the viewed section to remove all leading or trailing whitespace characte...
void trim_front(size_t len)
This member function can be used to remove characters from the front of the viewed section.
size_t find_first_of(const std::string &findstr, size_t pos=0) const
Wrapper member function for std::string::find_first_of()
std::string to_string() const
This member function returns a copy of the viewed section of the string (via std::string::substr)....
size_t find(const std::string &findstr, size_t pos=0) const
Wrapper member function for std::string::find()
size_t length() const
This member function simply returns the length of the viewed section.
size_t find_first_not_of(const std::string &findstr, size_t pos=0) const
Wrapper member function for std::string::find_first_not_of()
This class is the immutable (const) version of a string view. It can be constructed from a MutableStr...
StringView subview(size_t pos=0, size_t len=std::string::npos) const
This member function creates a new StringView class instance using the selected position and length a...
Common exception class for all exceptions thrown in NumeRe.
Definition: error.hpp:32
@ EXTERNAL_PROGRAM_NOT_FOUND
Definition: error.hpp:99
@ CANNOT_READ_FILE
Definition: error.hpp:75
@ CANNOT_OPEN_TARGET
Definition: error.hpp:73
@ FUNCTION_ERROR
Definition: error.hpp:110
@ UNMATCHED_PARENTHESIS
Definition: error.hpp:224
@ CANNOT_OPEN_SOURCE
Definition: error.hpp:72
static size_t invalid_position
Definition: error.hpp:235
This class represents a thread safe random number generator (it is a container for multiple generator...
Definition: tools.cpp:34
std::mt19937 & getGenerator()
Returns an instance of a random number generator for the current thread.
Definition: tools.cpp:62
std::vector< std::mt19937 > m_randGenArray
Definition: tools.cpp:36
ThreadsafeRandGen()
Create an instance of this thread safe random number generator by filling the internal array with the...
Definition: tools.cpp:45
void SetExpr(StringView a_sExpr)
Set the expression. Triggers first time calculation thus the creation of the bytecode and scanning of...
value_type Eval()
Single-value wrapper around the vectorized overload of this member function.
string getDataElements(string &sLine, Parser &_parser, MemoryManager &_data, const Settings &_option, int options)
Searches the passed string for calls to any table or cluster and replaces them with internal vectors ...
Definition: dataaccess.cpp:276
std::string fromSystemCodePage(std::string)
Transforms the system code page to the internal one.
std::string toSystemCodePage(std::string)
Converts an internal to an external string. Does nothing currently.
std::string replacePathSeparator(const std::string &)
This function replaces the Windows style path sparators to UNIX style.
CONSTCD11 std::enable_if<!std::chrono::treat_as_floating_point< T >::value, T >::type trunc(T t) NOEXCEPT
Definition: date.h:1113
CONSTCD11 std::chrono::duration< Rep, Period > abs(std::chrono::duration< Rep, Period > d)
Definition: date.h:1317
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:251
bool isnan(const value_type &v)
Definition: muParserDef.h:379
bool isinf(const value_type &v)
Definition: muParserDef.h:374
value_type rint(value_type v)
void StripSpaces(std::string &)
Removes leading and trailing white spaces and tabulator characters.
size_t versionToInt(std::string sVersion)
Converts a version string into a multi-digit integer.
std::string intToVersion(size_t nVersionDigits)
Converts a multi-digit integer into a verison string.
void replaceAll(std::string &sToModify, const char *sToRep, const char *sNewValue, size_t nStart, size_t nEnd)
This function replaces all occurences of the string sToRep in the string sToModify with the new value...
Structure for the findCommand function.
unsigned int nPos
std::string sString
This structure wraps all necessary meta information of a single file.
Definition: file.hpp:41
long long int nCols
Definition: file.hpp:47
__time64_t timeStamp
Definition: file.hpp:52
std::string sTableName
Definition: file.hpp:44
std::string sComment
Definition: file.hpp:45
long long int nRows
Definition: file.hpp:46
std::string toString(int)
Converts an integer to a string without the Settings bloat.
static Match findCasualCommand(StringView sCmd)
This is a static helper function for the findCommand function.
Definition: tools.cpp:950
void replaceStringMethod(string &sLine, size_t nPos, size_t nLength, const string &sReplacement)
This function searches the indicated string variable occurence for possible string methods and replac...
Definition: tools.cpp:3875
void addArgumentQuotes(string &sToAdd, const string &sParam)
This function adds quotation marks around the value of the specified parameter.
Definition: tools.cpp:3560
static void handleIncAndDecOperators(string &sExpr, size_t nPos, size_t nArgSepPos)
This function is a static helper function for evalRecursiveExpressions.
Definition: tools.cpp:3314
void openExternally(const string &sFile)
Opens a file with the program, which is associated by default within the Windows shell.
Definition: tools.cpp:1375
bool fileExists(const string &sFilename)
This function checks, whether the file with the passed file name exists.
Definition: tools.cpp:2500
std::string shortenFileName(const std::string &sFullFileName)
This function will return a shortened version of the data file name, where each "/Path/" string part ...
Definition: tools.cpp:3953
std::vector< std::string > splitIntoLines(std::string sOutput, size_t lineWidth, bool bAllowDashBreaks, int nFirstIndent, int nIndent)
This function splits a string into multiple lines if the line is longer than the desired line width.
Definition: tools.cpp:2002
static bool findShortestMatchForCommand(Match &_mMatch, size_t position, char character, StringView sCmd, const std::string &sCommand)
This is a static helper function for the findCommandWithReturnValue function.
Definition: tools.cpp:1049
Match findCommand(StringView sCmd, const std::string &sCommand)
This function is very important for the command handler.
Definition: tools.cpp:1275
string getNextArgument(string &sArgList, bool bCut)
Definition: tools.cpp:2294
bool containsStrings(const string &sLine)
This function checks, whether the passed expression contains strings or valtostring parser.
Definition: tools.cpp:2470
static Match findCommandWithReturnValue(StringView sCmd, const string &sCommand)
This is a static helper function for the findCommand function.
Definition: tools.cpp:1103
bool addLegends(string &sExpr)
This function adds the missing legend strings to the expressions in the passed string.
Definition: tools.cpp:1875
bool getStringArgument(const string &sCmd, string &sArgument)
This function searches for the first string value in the passed expression and writes that into sArgu...
Definition: tools.cpp:250
vector< string > getFileList(const string &sDirectory, const Settings &_option, int nFlags)
This function returns a list of files (including their paths, if nFlags & 1).
Definition: tools.cpp:2853
string getFileInfo(const string &sFileName)
This function opens a NumeRe-Datafile file, reads its header and converts it to a human-readable stri...
Definition: tools.cpp:3446
string decodeNameSpace(string sCommandLine, const string &sThisNameSpace)
Definition: tools.cpp:3476
StringView getNextViewedIndex(StringView &sView)
Definition: tools.cpp:2332
string getArgAtPos(const string &sCmd, unsigned int nPos, int extraction)
Extracts a options value at the selected position and applies automatic parsing, if necessary.
Definition: tools.cpp:1598
static size_t isStringContinuation(const std::string &sCmd, size_t pos)
This static function detects, whether the current string expression is continued.
Definition: tools.cpp:1504
std::string replaceToTeX(const std::string &sString, bool replaceForTeXFile)
Replace the special tokens with their TeX counterparts, so that they can be handled by a LaTeX interp...
Definition: tools.cpp:753
EndlessVector< string > getAllSemiColonSeparatedTokens(string sArgList)
Splits up the complete index list and returns them as an EndlessVector.
Definition: tools.cpp:2403
vector< string > getFolderList(const string &sDirectory, const Settings &_option, int nFlags)
This function returns a list of directories (including their paths, if nFlags & 1).
Definition: tools.cpp:2925
static bool containsStringClusters(const string &sLine)
This function is a static helper function for containsStrings to search through the list of known clu...
Definition: tools.cpp:2442
double intPower(double dNumber, int nExponent)
This function calculates the power of a value with the specialization that the exponent is an integer...
Definition: tools.cpp:3607
string extractStringToken(const string &sCmd, size_t nPos)
This function extracts a string token at the selected position. If the position is start of an option...
Definition: tools.cpp:310
void moveFile(const string &sFile, const string &sNewFileName)
Move a file from one to another location. Can be used for renaming as well.
Definition: tools.cpp:1412
void writeTeXMain(const string &sTeXFile)
Definition: tools.cpp:1449
static void replaceSearchMethods(string &sLine, size_t nPos, size_t nFinalPos, const string &sReplacement, const string &sMethod, string &sArgument)
This static function replaces all search-oriented methods in the current string variable access.
Definition: tools.cpp:3791
static void OprtRplc_setup(map< string, string > &mOprtRplc)
This function is a variable initializer for the function replaceToVector name. It will only be called...
Definition: tools.cpp:3073
string extractCommandString(const string &sCmd, const Match &_mMatch)
Extracts the whole command string from a command line (which might contain more than one).
Definition: tools.cpp:1325
double Linearize(double x_0, double y_0, double x_1, double y_1)
Determines the root of the line connecting the two passed points.
Definition: tools.cpp:2222
vector< string > resolveChooseTokens(const string &sDirectory, const Settings &_option)
This function resolves the possibility to select multiple paths at once by inserting something like t...
Definition: tools.cpp:2584
void evalRecursiveExpressions(string &sExpr)
This function converts the recursive assignments like VAR += VAL into VAR = VAR + (VAL)
Definition: tools.cpp:3346
string getNextIndex(string &sArgList, bool bCut)
Definition: tools.cpp:2305
static StringView getNextCommandLineToken(StringView &sArgList, char cSep)
This function gets the first argument in the passed argument list if the boolean bCut is true then th...
Definition: tools.cpp:2242
string replaceToVectorname(const string &sExpression)
This function replaces a data access expression (i.e. the contents of the object argument parentheses...
Definition: tools.cpp:3108
bool isInQuotes(StringView sExpr, unsigned int nPos, bool bIgnoreVarParser)
Checks, whether the position in the passed expression is part of a string literal.
Definition: tools.cpp:1672
StringView getNextViewedArgument(StringView &sView)
Definition: tools.cpp:2327
static bool handleRecursiveOperators(string &sExpr, size_t &nPos, size_t &nArgSepPos)
This function is a static helper function for evalRecursiveExpressions.
Definition: tools.cpp:3146
unsigned int countEscapeSymbols(const string &sLine)
This function counts the number of escaped dollar signs.
Definition: tools.cpp:3708
static ThreadsafeRandGen randGenerator
Definition: tools.cpp:79
static void replaceAccessMethods(string &sLine, size_t nPos, size_t nFinalPos, const string &sReplacement, const string &sMethod, string &sArgument)
This static function replaces all access-oriented methods and the string splitter in the current stri...
Definition: tools.cpp:3843
static std::map< std::string, std::string > getTeXCodePageSpecial()
Definition: tools.cpp:633
void reduceLogFilesize(const string &sFileName)
This function is used to reduce the log file size from >= 100.000 to 20.000 lines to reduce the neede...
Definition: tools.cpp:2998
bool isInt(const std::complex< double > &number)
Determines, whether the content of a complex value is actually a regular integer.
Definition: tools.cpp:1838
static void handleTeXIndicesAndExponents(std::string &sReturn, const std::map< std::string, std::string > &mCodePage)
This function is a static helper function for the function replaceToTeX further down.
Definition: tools.cpp:661
bool isToStringArg(const string &sExpr, unsigned int nPos)
This function determines, whether the current position is part of an argument of the three value to s...
Definition: tools.cpp:1766
void copyFile(const string &sFile, const string &sTarget)
Copy the file's contents to another file.
Definition: tools.cpp:1431
std::string LineBreak(std::string sOutput, const Settings &_option, bool bAllowDashBreaks, int nFirstIndent, int nIndent)
This function takes a string, splits it into multiple lines if it is too long and returns the result.
Definition: tools.cpp:2205
string getNextSemiColonSeparatedToken(string &sArgList, bool bCut)
Definition: tools.cpp:2316
std::string outputString(std::vector< std::string > stringInLines, int nFirstIndent, int nIndent)
This function outputs a string by adding the required prefixes and joining the various strings togeth...
Definition: tools.cpp:2164
bool isMultiValue(const string &sExpr, bool bIgnoreClosingParenthesis)
Determines, if a string contains multiple comma-separated expressions.
Definition: tools.cpp:484
static void parseArg(std::string &sArg, int flags)
This static function is a helper for getArgAtPos to parse the expressions in the string.
Definition: tools.cpp:1538
std::mt19937 & getRandGenInstance()
Returns a reference to the central random number generator instance, which is globally accessible by ...
Definition: tools.cpp:91
static std::map< std::string, std::string > getTeXCodePage()
Static helper returning the TeX code page.
Definition: tools.cpp:527
unsigned int getMatchingParenthesis(const StringView &sLine)
Returns the position of the closing parenthesis.
Definition: tools.cpp:414
bool checkDelimiter(const string &sString, bool stringdelim)
Checks, whether the first and the last character in the passed string is a delimiter character.
Definition: tools.cpp:1982
size_t qSortDouble(double *dArray, size_t nlength)
This is a wrapper for the standard qsort algorithm. It returns the number of valid elements and sorts...
Definition: tools.cpp:3762
std::string incrementVersion(std::string _sVer)
Increments a MAJOR.MINOR.BUILD version string by one build count.
Definition: tools.cpp:3991
EndlessVector< string > getAllIndices(string sArgList)
Splits up the complete index list and returns them as an EndlessVector.
Definition: tools.cpp:2384
bool validateParenthesisNumber(const string &sCmd)
This function is used to validate the number of parentheses, i.e. whether there's a closing parenthes...
Definition: tools.cpp:3512
static int compareDouble(const void *p1, const void *p2)
This is a static helper function for the standard qsort algorithm.
Definition: tools.cpp:3734
long long int intCast(double number)
Casts doubles to integers and avoids rounding errors.
Definition: tools.cpp:1805
EndlessVector< StringView > getAllArguments(StringView sArgList)
Splits up the complete argument list and returns them as an EndlessVector.
Definition: tools.cpp:2346
bool isDelimiter(char c)
This function determines, if the passed character is a delimiter character.
Definition: tools.cpp:1852
void eraseToken(string &sExpr, const string &sToken, bool bTokenHasValue)
This function erases option tokens including their possible value from a parameter string.
Definition: tools.cpp:2527
bool isToCmd(const string &sCmd, unsigned int nPos)
This function evaluates, whether the desired position is part of the argument of a to_cmd() function.
Definition: tools.cpp:3675
int findParameter(const string &sCmd, const string &sParam, const char cFollowing)
This function searches the passed parameter in the passed command string. If something is found,...
Definition: tools.cpp:113
static HANDLE initializeFileHandle(string &sDir, WIN32_FIND_DATA *FindFileData, const Settings &_option)
This function is a static helper function for getFileList and getFolderList.
Definition: tools.cpp:2789
void make_progressBar(int nStep, int nFirstStep, int nFinalStep, const string &sType)
Wrapper for the static member function of the kernel.
Definition: tools.cpp:2425
@ ARGEXTRACT_ASINT
Definition: tools.hpp:58
@ ARGEXTRACT_STRIPPED
Definition: tools.hpp:56
@ ARGEXTRACT_PARSED
Definition: tools.hpp:57
@ ARGEXTRACT_ASSTRING
Definition: tools.hpp:59