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("<", "<", str);
150 ReplaceSubStringInPlace(">", ">", 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