1 // Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <regex>
9 #if defined(__CYGWIN__)
10 #include <sys/cygwin.h>
11 #endif
12 #include "StringUtils.h"
13 #include "GmshMessage.h"
14 #include "OS.h"
15 
SwapBytes(char * array,int size,int n)16 void SwapBytes(char *array, int size, int n)
17 {
18   char *x = new char[size];
19   for(int i = 0; i < n; i++) {
20     char *a = &array[i * size];
21     memcpy(x, a, size);
22     for(int c = 0; c < size; c++) a[size - 1 - c] = x[c];
23   }
24   delete[] x;
25 }
26 
ExtractDoubleQuotedString(const char * str,int len)27 std::string ExtractDoubleQuotedString(const char *str, int len)
28 {
29   char *c = strstr((char *)str, "\"");
30   if(!c) return "";
31   std::string ret;
32   for(int i = 1; i < len; i++) {
33     if(c[i] == '"' || c[i] == EOF || c[i] == '\n' || c[i] == '\r') break;
34     ret.push_back(c[i]);
35   }
36   return ret;
37 }
38 
SanitizeTeXString(const char * in,int equation)39 std::string SanitizeTeXString(const char *in, int equation)
40 {
41   // if there is a '$' or a '\' in the string, assume the author knows
42   // what he's doing:
43   if(strstr(in, "$") || strstr(in, "\\")) return std::string(in);
44 
45   std::string out;
46 
47   if(equation) out.push_back('$');
48 
49   // otherwise, escape the following special characters:
50   char bad[8] = {'%', '^', '#', '%', '&', '_', '{', '}'};
51   while(*in) {
52     for(std::size_t i = 0; i < sizeof(bad); i++) {
53       if(*in == bad[i]) {
54         out.push_back('\\');
55         break;
56       }
57     }
58     out.push_back(*in++);
59   }
60 
61   if(equation) out.push_back('$');
62   return out;
63 }
64 
FixWindowsPath(const std::string & in)65 std::string FixWindowsPath(const std::string &in)
66 {
67 #if defined(__CYGWIN__)
68   char tmp[1024];
69   cygwin_conv_to_win32_path(in.c_str(), tmp);
70   return std::string(tmp);
71 #else
72   return in;
73 #endif
74 }
75 
FixRelativePath(const std::string & reference,const std::string & in)76 std::string FixRelativePath(const std::string &reference, const std::string &in)
77 {
78   if(in.empty()) return "";
79 
80   if(in[0] == '/' || in[0] == '\\' ||
81      (in.size() > 3 && in[1] == ':' && (in[2] == '/' || in[2] == '\\'))) {
82     // do nothing: 'in' is an absolute path
83     return in;
84   }
85   else {
86     // append 'in' to the path of the reference file
87     std::vector<std::string> split = SplitFileName(reference);
88     return split[0] + in;
89   }
90 }
91 
SplitFileName(const std::string & fileName)92 std::vector<std::string> SplitFileName(const std::string &fileName)
93 {
94   // JFR DO NOT CHANGE TO std::vector<std::string> s(3), it segfaults while
95   // destructor si called
96   std::vector<std::string> s;
97   s.resize(3);
98   if(fileName.size()) {
99     // returns [path, baseName, extension]
100     int idot = (int)fileName.find_last_of('.');
101     int islash = (int)fileName.find_last_of("/\\");
102     if(idot == (int)std::string::npos) idot = -1;
103     if(islash == (int)std::string::npos) islash = -1;
104     if(idot > 0) s[2] = fileName.substr(idot);
105     if(islash > 0) s[0] = fileName.substr(0, islash + 1);
106     s[1] =
107       fileName.substr(s[0].size(), fileName.size() - s[0].size() - s[2].size());
108   }
109   return s;
110 }
111 
GetFileNameWithoutPath(const std::string & fileName)112 std::string GetFileNameWithoutPath(const std::string &fileName)
113 {
114   std::vector<std::string> s = SplitFileName(fileName);
115   return s[1] + s[2];
116 }
117 
ConvertFileToString(const std::string & fileName)118 std::string ConvertFileToString(const std::string &fileName)
119 {
120   FILE *fp = Fopen(fileName.c_str(), "r");
121   if(!fp) return "";
122   std::string out;
123   char str[256];
124   while(!feof(fp) && fgets(str, sizeof(str), fp)) out += str;
125   fclose(fp);
126   return out;
127 }
128 
ReplaceSubStringInPlace(const std::string & olds,const std::string & news,std::string & str)129 void ReplaceSubStringInPlace(const std::string &olds, const std::string &news,
130                              std::string &str)
131 {
132   while(1) {
133     int pos = (int)str.find(olds.c_str());
134     if(pos == (int)std::string::npos) break;
135     str.replace(pos, olds.size(), news.c_str());
136   }
137 }
138 
ReplaceSubString(const std::string & olds,const std::string & news,const std::string & str)139 std::string ReplaceSubString(const std::string &olds, const std::string &news,
140                              const std::string &str)
141 {
142   std::string copy(str);
143   ReplaceSubStringInPlace(olds, news, copy);
144   return copy;
145 }
146 
ConvertToHTML(std::string & str)147 void ConvertToHTML(std::string &str)
148 {
149   ReplaceSubStringInPlace("<", "&lt;", str);
150   ReplaceSubStringInPlace(">", "&gt;", str);
151   ReplaceSubStringInPlace("\n\n", "<p>", str);
152   ReplaceSubStringInPlace("\n", "<br>", str);
153 }
154 
SplitOptionName(const std::string & fullName,std::string & category,std::string & name,int & index)155 bool SplitOptionName(const std::string &fullName, std::string &category,
156                      std::string &name, int &index)
157 {
158   std::string::size_type d = fullName.find_first_of('.');
159   if(d == std::string::npos) {
160     name = fullName;
161     return false;
162   }
163   category = fullName.substr(0, d);
164   std::string::size_type b1 = fullName.find_first_of('[');
165   std::string::size_type b2 = fullName.find_last_of(']');
166   if(b1 != std::string::npos && b2 != std::string::npos) {
167     std::string id = fullName.substr(b1 + 1, b2 - b1 - 1);
168     index = atoi(id.c_str());
169     category = fullName.substr(0, b1);
170     name = fullName.substr(d + 1, b1 - d);
171   }
172   else {
173     index = 0;
174     name = fullName.substr(d + 1);
175   }
176   Msg::Debug("Decoded option name '%s' . '%s' (index %d)", category.c_str(),
177              name.c_str(), index);
178   return true;
179 }
180 
RemoveWhiteSpace(const std::string & s)181 std::string RemoveWhiteSpace(const std::string &s)
182 {
183   std::regex r("\\s+");
184   return std::regex_replace(s, r, "");
185 }
186 
getNextTokenInString(const std::string & msg,std::string::size_type & first,char separator)187 static std::string getNextTokenInString(const std::string &msg,
188                                         std::string::size_type &first,
189                                         char separator)
190 {
191   if(first == std::string::npos) return "";
192   std::string::size_type last = msg.find_first_of(separator, first);
193   std::string next("");
194   if(last == std::string::npos) {
195     next = msg.substr(first);
196     first = last;
197   }
198   else if(first == last) {
199     next = "";
200     first = last + 1;
201   }
202   else {
203     next = msg.substr(first, last - first);
204     first = last + 1;
205   }
206   return next;
207 }
208 
SplitString(const std::string & msg,char separator,bool removeWhiteSpace)209 std::vector<std::string> SplitString(const std::string &msg, char separator,
210                                      bool removeWhiteSpace)
211 {
212   std::vector<std::string> out;
213   std::string::size_type first = 0;
214   while(first != std::string::npos) {
215     if(removeWhiteSpace)
216       out.push_back(
217         RemoveWhiteSpace(getNextTokenInString(msg, first, separator)));
218     else
219       out.push_back(getNextTokenInString(msg, first, separator));
220   }
221   return out;
222 }
223 
IsOnelabName(const std::string & name,std::string & cleanName)224 bool IsOnelabName(const std::string &name, std::string &cleanName)
225 {
226   std::string::size_type n = name.find('/');
227   if(name.empty() || n == std::string::npos) return false;
228 
229   if(name.size() > 1 && name[0] == '/')
230     cleanName = name.substr(1);
231   else
232     cleanName = name;
233 
234   return true;
235 }
236