GCC Code Coverage Report


Directory: ./
File: src/string_system.cpp
Date: 2024-09-19 16:05:14
Exec Total Coverage
Lines: 145 162 89.5%
Branches: 129 167 77.2%

Line Branch Exec Source
1
2 /***************************************
3 Auteur : Pierre Aubert
4 Mail : pierre.aubert@lapp.in2p3.fr
5 Licence : CeCILL-C
6 ****************************************/
7
8 #include <errno.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <dirent.h>
12 #include <regex.h>
13 #include <fcntl.h> //Definition of AT_* constants
14 #ifndef __APPLE__
15 #define GCC_VERSION (__GNUC__ * 10000 \
16 + __GNUC_MINOR__ * 100 \
17 + __GNUC_PATCHLEVEL__)
18 # if GCC_VERSION <= 60200
19 # include <asm-generic/errno-base.h>
20 # endif
21 #endif
22
23 #include <time.h>
24 #include <ctime>
25
26 #include <sys/types.h>
27 #include <unistd.h>
28
29 // #include <cerrno>
30 #include <iostream>
31
32
33 #include "string_filename.h"
34
35 #include "string_system.h"
36
37 /* From https://nicolasj.developpez.com/articles/regex/
38
39 [:digit:] 0-9
40 [:alpha:] A-Za-z
41 [:alnum:] 0-9A-Za-z
42 [:cntrl:] Les caractères de contrôles (code ASCII 0177 et inférieur à 040)
43 [:print:] Les caractères imprimables
44 [:graph:] Idem [:print:] sans l'espace
45 [:lower:] a-z
46 [:upper:] A-Z
47 [:punct:] Ni [:cntrl:] ni [:alnum:]
48 [:space:] \n\t\r\f
49 [:xdigit:] 0-9a-fA-F nombres hexadécimaux
50
51 Ces définitions concordent avec celles que l'on trouve dans le fichier d'en-tête ctype.h. Le point '.' permet de reconnaître n'importe quel caractère. Il est aussi possible de préciser le nombre de répétitions que l'on souhaite pour un élément :
52
53 Opérateurs Signification
54 ? L'élément est répété, au plus une fois
55 * L'élément est présent 0 ou plus de fois
56 + L'élément est présent au moins une fois
57 {n} L'élément est présent exactement n fois
58 {n,} L'élément est présent au moins n fois
59 {n,m} L'élément est présent entre n et m fois
60
61 Un élément est un groupe délimité par des crochets qui sont optionnels si le groupe ne comporte qu'un élément. Voici un exemple pour reconnaître si une chaîne contient trois 'a' consécutifs :
62
63 Sélectionnez
64
65 [a]{3}
66
67 L'opposé d'une expression est obtenu en la faisant précéder par le caractère '^'. Si l'on souhaite donner le choix entre deux expressions, il suffit de les séparer par le caractère '|'.
68 Ce même caractère peut être placé au début de l'expression régulière pour préciser que la chaîne à analyser doit commencer par l'élément suivant :
69
70 Sélectionnez
71
72 ^[A-Z]
73
74 Précise que la chaîne doit commencer par une lettre majuscule. Le caractère '$' a le même rôle, mais cette fois en fin de chaîne.
75 Pour finir, voici la liste des méta caractères ainsi que la manière de les échapper :
76
77 Méta caractères Echappés en
78 ? \?
79 + \+
80 . \.
81 * \*
82 { \{
83 | \|
84 ( \(
85 ) \)
86 */
87
88
89 ///Fonction qui dit si une chaine de caractère correspond à une expression régulière de regex
90 /** @param str : string dont on veut savoir si elle correspond à une expression régulière
91 * @param expression : expression régulière regex
92 * @return true si str correspond à une expression régulière, false sinon
93 */
94 41 bool isStringMatchRegex(const std::string & str, const std::string & expression){
95
6/6
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 37 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 37 times.
41 if(str.size() == 0lu || expression.size() == 0lu){return false;}
96 int err;
97 regex_t preg;
98 37 const char *str_request = str.c_str();
99 37 const char *str_regex = expression.c_str();
100
1/1
✓ Branch 1 taken 37 times.
37 err = regcomp(&preg, str_regex, 0); //REG_NOSUB | REG_EXTENDED
101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if(err != 0) return false;
102
1/1
✓ Branch 1 taken 37 times.
37 int match = regexec(&preg, str_request, 0, NULL, 0);
103
1/1
✓ Branch 1 taken 37 times.
37 regfree (&preg);
104
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 23 times.
37 if(match == 0){return true;}
105 23 else{return false;}//if (match == REG_NOMATCH){return false;}
106 // else{
107 // char *text;
108 // long unsigned int size;
109 // size = regerror (err, &preg, NULL, 0);
110 // text = new char[size];
111 // if (text){
112 // regerror (err, &preg, text, size);
113 // fprintf (stderr, "isStringMatchRegex : %s\n", text);
114 // delete [] text;
115 // }else{
116 // fprintf (stderr, "isStringMatchRegex : Memoire insuffisante\n");
117 // }
118 // return false;
119 // }
120 }
121
122 ///Function like a ls in shell
123 /** @param listFile : list of the files witch match with expr
124 * @param expr : expression like "name*.txt" or "*.dat" or "name_*_something_*.ext"
125 */
126 1 void getListFileInCurrentDir(std::list<std::string> & listFile, const std::string & expr){
127 1 char * curr_dir = getenv("PWD");
128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(NULL == curr_dir){
129 printf("getListFileInCurrentDir : Could not get the working directory\n");
130 return;
131 }
132 // Open the current directory
133 1 DIR * dp = opendir((const char*)curr_dir);
134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(NULL == dp){
135 printf("getListFileInCurrentDir : Could not open the working directory\n");
136 return;
137 }
138 1 dirent * dptr = readdir(dp);
139
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 1 times.
24 while(NULL != dptr){
140
6/6
✓ Branch 2 taken 23 times.
✓ Branch 5 taken 23 times.
✓ Branch 9 taken 7 times.
✓ Branch 10 taken 16 times.
✓ Branch 13 taken 7 times.
✓ Branch 16 taken 7 times.
23 if(isStringMatchRegex(std::string(dptr->d_name), expr)) listFile.push_back(std::string(dptr->d_name));
141 23 dptr = readdir(dp);
142 }
143 }
144
145 ///Get the list of files in a directory
146 /** @param[out] listFile : list of files in the current directory
147 * @param dirName : name of the directory to look in
148 * @param expr : regular expression like *.txt or *
149 */
150 1 bool getListFileInDir(std::list<std::string> & listFile, const std::string & dirName, const std::string & expr){
151 // Open the current directory
152 1 DIR * dp = opendir(dirName.c_str());
153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(NULL == dp){
154 // printf("getListFileInDir : Could not open the working directory\n");
155 return false;
156 }
157 1 dirent * dptr = readdir(dp);
158
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 while(NULL != dptr){
159
6/6
✓ Branch 2 taken 7 times.
✓ Branch 5 taken 7 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 5 times.
✓ Branch 13 taken 2 times.
✓ Branch 16 taken 2 times.
7 if(isStringMatchRegex(std::string(dptr->d_name), expr)) listFile.push_back(std::string(dptr->d_name));
160
4/4
✓ Branch 3 taken 7 times.
✓ Branch 6 taken 7 times.
✓ Branch 9 taken 7 times.
✓ Branch 12 taken 7 times.
7 std::cout << "getListFileInDir : '" << std::string(dptr->d_name) << "'"<< std::endl;
161 7 dptr = readdir(dp);
162 }
163 1 closedir(dp);
164 1 return true;
165 }
166
167 ///Get the list of files in a directory
168 /** @param[out] listFile : list of files in the current directory
169 * @param dirName : name of the directory to look in
170 */
171 1 bool getListAllFileInDir(std::list<std::string> & listFile, const std::string & dirName){
172 // Open the current directory
173 1 DIR * dp = opendir(dirName.c_str());
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(NULL == dp){
175 return false;
176 }
177 1 dirent * dptr = readdir(dp);
178
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 while(NULL != dptr){
179
1/1
✓ Branch 2 taken 7 times.
7 std::string fileName(dptr->d_name);
180
8/8
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1 times.
✓ Branch 6 taken 6 times.
✓ Branch 8 taken 5 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 5 times.
✓ Branch 11 taken 2 times.
7 if(fileName != ".." && fileName != "."){
181
1/1
✓ Branch 1 taken 5 times.
5 listFile.push_back(fileName);
182 }
183
1/1
✓ Branch 1 taken 7 times.
7 dptr = readdir(dp);
184 7 }
185 1 closedir(dp);
186 1 return true;
187 }
188 ///Makes the argument list of a program
189 /** @param[out] listArgument : list of the program arguments
190 * @param argc : number of arguments passed to the program
191 * @param argv : array of the passed arguments to the program
192 */
193 1 void makeListArgument(std::list<std::string> & listArgument, int argc, char** argv){
194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(argc <= 0) return;
195
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for(int i(0); i < argc; ++i){
196
2/2
✓ Branch 2 taken 1 times.
✓ Branch 5 taken 1 times.
1 listArgument.push_back(argv[i]);
197 }
198 }
199
200 ///Get the value of the given environment variable
201 /** @param varName : name of the environment variable to be used
202 * @return value of the variable, or empty string of the variable does not exist
203 */
204 3 std::string phoenix_getenv(const std::string & varName){
205 3 char * curr_var = getenv(varName.c_str());
206
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if(NULL == curr_var){
207
1/1
✓ Branch 2 taken 1 times.
1 return "";
208 }else{
209
1/1
✓ Branch 2 taken 2 times.
2 return std::string(curr_var);
210 }
211 }
212
213 ///Set a environment variable
214 /** @param name : name of the variable to be created
215 * @param value : value of the variable to be created
216 * @param overwrite : 1 to overwrite an existing variable, 0 to not to
217 * @return true on success, false otherwise
218 */
219 1 bool phoenix_setenv(const std::string & name, const std::string & value, int overwrite){
220 1 return setenv(name.c_str(), value.c_str(), overwrite) == 0;
221 }
222
223 ///Unset a environment variable
224 /** @param name : name of the variable to be unset
225 * @return true on success, false otherwise
226 */
227 1 bool phoenix_unsetenv(const std::string & name){
228 1 return unsetenv(name.c_str()) == 0;
229 }
230
231 ///Gets the $HOME directory
232 /** @return $HOME directory
233 */
234 1 std::string getHomeDir(){
235
2/2
✓ Branch 2 taken 1 times.
✓ Branch 5 taken 1 times.
1 return phoenix_getenv("HOME");
236 }
237
238 ///Creates a directory if it does not exist
239 /** @param directoryName : name of the directory we want to create
240 * @return true on success, false otherwise
241 */
242 2 bool createDirIfNotExist(const std::string & directoryName){
243
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if(directoryName == "") return false;
244
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if(isDirectoryExist(directoryName)){
245 1 return true;
246 }
247 1 int res = mkdir(directoryName.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
248
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 return res == 0 || res == EEXIST;
249 }
250
251 ///Get the last modification time of the given file
252 /** @param fileName : name of the file we want the last modification time
253 * @return last modification time of the given file
254 */
255 5 time_t getFileModificationTime(const std::string & fileName){
256 struct stat attr;
257
2/2
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
5 if(stat(fileName.c_str(), &attr) == 0){
258 #ifdef __APPLE__
259 return attr.st_mtimespec.tv_sec;
260 #else
261 3 return attr.st_mtim.tv_sec;
262 #endif
263 }else{
264 2 return -1l;
265 }
266 }
267
268 ///Get the list of most recent files in a directory
269 /** @param[out] vecFile : vector of found files (without directory name)
270 * @param dirName : name of the directory to be scanned
271 * @param mostRecentTime : threshold time to select only most recent files
272 * @return time of the most recent file found in the directory which is newer than the input mostRecentTime
273 */
274 2 time_t getFileInDirPerTime(std::vector<std::string> & vecFile, const std::string & dirName, time_t mostRecentTime){
275 2 DIR * dp = opendir(dirName.c_str());
276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(dp == NULL){return mostRecentTime;}
277 2 dirent * dptr = readdir(dp);
278
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 while(NULL != dptr){
279
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if(dptr->d_type == DT_REG){ //We search for directory only
280
1/1
✓ Branch 2 taken 2 times.
2 std::string pathName(dptr->d_name);
281
3/3
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 2 times.
2 time_t fileTime = getFileModificationTime(dirName + "/" + pathName);
282
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(fileTime > mostRecentTime){
283 1 mostRecentTime = fileTime;
284
1/1
✓ Branch 1 taken 1 times.
1 vecFile.push_back(pathName);
285 }
286 2 }
287 6 dptr = readdir(dp);
288 }
289 2 return mostRecentTime;
290 }
291
292
293 ///Get the program location
294 /** @return location of the current program
295 */
296 3 std::string getProgramLocation(){
297 char buffer[4096];
298 3 ssize_t nbChar = readlink("/proc/self/exe", buffer, 2048);
299 // readlink("/proc/self/exe", buf, bufsize) (Linux)
300 // readlink("/proc/curproc/file", buf, bufsize) (FreeBSD)
301 // readlink("/proc/self/path/a.out", buf, bufsize) (Solaris)
302
303
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(nbChar > 0l){
304
1/1
✓ Branch 2 taken 3 times.
3 std::string outputBuf("");
305
2/2
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 3 times.
261 for(ssize_t i(0l); i < nbChar; ++i){
306
1/1
✓ Branch 1 taken 258 times.
258 outputBuf += buffer[i];
307 }
308 3 return outputBuf;
309 3 }else{
310 return "";
311 }
312 }
313
314 ///Get the program directory
315 /** @return directory of the program
316 */
317 2 std::string getProgramDirectory(){
318
1/1
✓ Branch 1 taken 2 times.
2 std::string progLoc(getProgramLocation());
319
2/3
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 if(progLoc != ""){
320
1/1
✓ Branch 1 taken 2 times.
2 return getDirectory(progLoc);
321 }else{
322 #ifdef CMAKE_INSTALL_PREFIX
323 return CMAKE_INSTALL_PREFIX "/bin/";
324 #else
325 return "/usr/bin/";
326 #endif
327 }
328 2 }
329
330 ///Get the program prefix (installation directory without /bin)
331 /** @return prefix of the program (installation directory without /bin)
332 */
333 1 std::string getProgramPrefix(){
334
1/1
✓ Branch 2 taken 1 times.
2 return getDirectory(getProgramDirectory());
335 }
336
337 ///Execute the given command and returns the output of this command
338 /** @param command : command to be executed
339 * @return output of the given command, empty string if the command is empty or null character on fail
340 */
341 5 std::string phoenix_popen(const std::string & command){
342
3/3
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4 times.
✓ Branch 5 taken 1 times.
5 if(command == ""){return "";}
343
1/1
✓ Branch 2 taken 4 times.
4 FILE * fp = popen(command.c_str(), "r");
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(fp == NULL){
345 std::cerr << "phoenix_popen : cannot get result of command '"<<command<<"'" << std::endl;
346 return "";
347 }
348
1/1
✓ Branch 1 taken 4 times.
4 std::string resultCommand(getFileContent(fp));
349
1/1
✓ Branch 1 taken 4 times.
4 pclose(fp);
350 4 return resultCommand;
351 4 }
352
353 ///Execute the given command and returns the output of this command
354 /** @param[out] executionLog : output of the given command, empty string if the command is empty or null character on fail
355 * @param command : command to be executed
356 * @return exit status of the command
357 */
358 7 int phoenix_popen(std::string & executionLog, const std::string & command){
359 7 executionLog = "";
360
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6 times.
7 if(command == ""){return -1;}
361 6 FILE * fp = popen(command.c_str(), "r");
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if(fp == NULL){
363 std::cerr << "phoenix_popen : cannot get result of command '"<<command<<"'" << std::endl;
364 return -1;
365 }
366 6 executionLog = getFileContent(fp);
367 6 return pclose(fp);
368 }
369
370 ///Execute the given command and returns the output of this command
371 /** @param[out] executionLogFile : file which will get output of the given command, empty string if the command is empty or full log on fail
372 * @param command : command to be executed
373 * @param onlyLogOnFail : true to log only if the command fails
374 * @return true if the command was successful, false otherwise (in this case, log file will be created)
375 */
376 4 bool phoenix_popen(const std::string & executionLogFile, const std::string & command, bool onlyLogOnFail){
377
1/1
✓ Branch 2 taken 4 times.
4 std::string executionLog("");
378
1/1
✓ Branch 1 taken 4 times.
4 bool b(phoenix_popen(executionLog, command) == 0);
379
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if(!b){
380
6/6
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 10 taken 2 times.
✓ Branch 13 taken 2 times.
✓ Branch 16 taken 2 times.
2 std::cerr << "phoenix_popen : command '"<<command<<"' failed. To get more information see log '"<<executionLogFile<<"'" << std::endl;
381 }
382
6/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
4 if((onlyLogOnFail && !b) || !onlyLogOnFail){
383
2/3
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 if(!saveFileContent(executionLogFile, executionLog)){
384 std::cerr << "phoenix_popen : cannot create log file '"<<executionLogFile<<"'" << std::endl;
385 }
386 }
387 4 return b;
388 4 }
389
390 ///Change the mode of a file or directory
391 /** @param fileName : name of the file to be changed
392 * @param __mode : mode to be applied to the given file (Default value makes files executable S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)
393 * @return true on success, false otherwise
394 */
395 2 bool phoenix_chmod(const std::string & fileName, mode_t __mode){
396 2 bool b(chmod(fileName.c_str(), __mode) >= 0);
397
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(!b){
398 1 std::cerr << "phoenix_chmod : Cannot set mode of file '"<<fileName<<"'" << std::endl;
399 }
400 2 return b;
401 }
402
403 ///Get the name of the current node on which the program is running
404 /** @return name of the current node on which the program is running
405 */
406 1 std::string getCurrentNodeName(){
407
4/4
✓ Branch 2 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 12 taken 1 times.
2 return eraseCharsInStr(phoenix_popen("uname -n"), " \n\t");
408 }
409
410 ///Find all files which matches the path expression (example : /path/*.cpp)
411 /** @param[out] vecFile : vector of found files
412 * @param path : path which can matches several files
413 */
414 1 void phoenix_find(std::vector<std::string> & vecFile, const std::string & path){
415
2/2
✓ Branch 2 taken 1 times.
✓ Branch 5 taken 1 times.
1 vecFile = cutStringVector(phoenix_popen("ls " + path), '\n');
416 1 }
417
418 ///Find all files which matches the path expression (example : /path/*.cpp)
419 /** @param path : path which can matches several files
420 * @return vector of found files
421 */
422 1 std::vector<std::string> phoenix_find(const std::string & path){
423 1 std::vector<std::string> vecFile;
424
1/1
✓ Branch 1 taken 1 times.
1 phoenix_find(vecFile, path);
425 1 return vecFile;
426 }
427
428 ///Get current time
429 /** @return current time
430 */
431 time_t phoenix_getClock(){
432 return clock();
433 }
434
435 ///Get current time
436 /** @return current time
437 */
438 double phoenix_getClockSec(){
439 return ((double)phoenix_getClock())/((double)CLOCKS_PER_SEC);
440 }
441
442 ///Get the current time of the program
443 /** @return current time of the program
444 */
445 202 time_t phoenix_getTime(){
446 202 return std::time(0);
447 }
448
449 ///Get the current date
450 /** @return current date
451 */
452 24 std::string phoenix_getDate(){
453
1/1
✓ Branch 1 taken 24 times.
24 std::time_t currentTime = phoenix_getTime();
454 24 std::tm* now_tm = std::gmtime(&currentTime);
455 char buf[42];
456 24 std::strftime(buf, 42, "%Y/%m/%d : %X", now_tm);
457
1/1
✓ Branch 2 taken 24 times.
24 return buf;
458 }
459
460 ///Get the current date
461 /** @return current date
462 */
463 89 std::string phoenix_getDateCompact(){
464
1/1
✓ Branch 1 taken 89 times.
89 std::time_t currentTime = phoenix_getTime();
465 89 std::tm* now_tm = std::gmtime(&currentTime);
466 char buf[42];
467 89 std::strftime(buf, 42, "%Y/%m/%d-%X", now_tm);
468
1/1
✓ Branch 2 taken 89 times.
89 return buf;
469 }
470