GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
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 |
36 |
bool isStringMatchRegex(const std::string & str, const std::string & expression){ |
|
95 |
✓✓✓✓ ✓✓ |
36 |
if(str.size() == 0lu || expression.size() == 0lu){return false;} |
96 |
int err; |
||
97 |
regex_t preg; |
||
98 |
32 |
const char *str_request = str.c_str(); |
|
99 |
32 |
const char *str_regex = expression.c_str(); |
|
100 |
✓ | 32 |
err = regcomp(&preg, str_regex, 0); //REG_NOSUB | REG_EXTENDED |
101 |
✗✓ | 32 |
if(err != 0) return false; |
102 |
✓ | 32 |
int match = regexec(&preg, str_request, 0, NULL, 0); |
103 |
✓ | 32 |
regfree (&preg); |
104 |
✓✓ | 32 |
if(match == 0){return true;} |
105 |
21 |
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 |
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 |
if(NULL == dp){ |
135 |
printf("getListFileInCurrentDir : Could not open the working directory\n"); |
||
136 |
return; |
||
137 |
} |
||
138 |
1 |
dirent * dptr = readdir(dp); |
|
139 |
✓✓ | 19 |
while(NULL != dptr){ |
140 |
✓✓✓✓ ✓✓ |
18 |
if(isStringMatchRegex(std::string(dptr->d_name), expr)) listFile.push_back(std::string(dptr->d_name)); |
141 |
18 |
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 |
if(NULL == dp){ |
154 |
// printf("getListFileInDir : Could not open the working directory\n"); |
||
155 |
return false; |
||
156 |
} |
||
157 |
1 |
dirent * dptr = readdir(dp); |
|
158 |
✓✓ | 8 |
while(NULL != dptr){ |
159 |
✓✓✓✓ ✓✓ |
7 |
if(isStringMatchRegex(std::string(dptr->d_name), expr)) listFile.push_back(std::string(dptr->d_name)); |
160 |
✓✓✓✓ |
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 |
if(NULL == dp){ |
175 |
return false; |
||
176 |
} |
||
177 |
1 |
dirent * dptr = readdir(dp); |
|
178 |
✓✓ | 8 |
while(NULL != dptr){ |
179 |
✓ | 7 |
std::string fileName(dptr->d_name); |
180 |
✓✓✓✓ ✓✓✓✓ |
7 |
if(fileName != ".." && fileName != "."){ |
181 |
✓ | 5 |
listFile.push_back(fileName); |
182 |
} |
||
183 |
✓ | 7 |
dptr = readdir(dp); |
184 |
} |
||
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 |
if(argc <= 0) return; |
195 |
✓✓ | 2 |
for(int i(0); i < argc; ++i){ |
196 |
✓✓ | 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 |
✓✓ | 3 |
if(NULL == curr_var){ |
207 |
✓ | 1 |
return ""; |
208 |
}else{ |
||
209 |
✓ | 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 |
✓✓ | 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 |
✗✓ | 2 |
if(directoryName == "") return false; |
244 |
✓✓ | 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 |
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 |
✓✓ | 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 |
✗✓ | 2 |
if(dp == NULL){return mostRecentTime;} |
277 |
2 |
dirent * dptr = readdir(dp); |
|
278 |
✓✓ | 8 |
while(NULL != dptr){ |
279 |
✓✓ | 6 |
if(dptr->d_type == DT_REG){ //We search for directory only |
280 |
✓ | 4 |
std::string pathName(dptr->d_name); |
281 |
✓✓✓ | 2 |
time_t fileTime = getFileModificationTime(dirName + "/" + pathName); |
282 |
✓✓ | 2 |
if(fileTime > mostRecentTime){ |
283 |
1 |
mostRecentTime = fileTime; |
|
284 |
✓ | 1 |
vecFile.push_back(pathName); |
285 |
} |
||
286 |
} |
||
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 |
✓✗ | 3 |
if(nbChar > 0l){ |
304 |
✓ | 6 |
std::string outputBuf(""); |
305 |
✓✓ | 327 |
for(ssize_t i(0l); i < nbChar; ++i){ |
306 |
✓ | 324 |
outputBuf += buffer[i]; |
307 |
} |
||
308 |
3 |
return outputBuf; |
|
309 |
}else{ |
||
310 |
return ""; |
||
311 |
} |
||
312 |
} |
||
313 |
|||
314 |
///Get the program directory |
||
315 |
/** @return directory of the program |
||
316 |
*/ |
||
317 |
2 |
std::string getProgramDirectory(){ |
|
318 |
✓ | 4 |
std::string progLoc(getProgramLocation()); |
319 |
✓✓✗ | 2 |
if(progLoc != ""){ |
320 |
✓ | 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 |
} |
||
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 |
✓ | 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 |
27 |
std::string phoenix_popen(const std::string & command){ |
|
342 |
✓✓✓ | 27 |
if(command == ""){return "";} |
343 |
✓ | 26 |
FILE * fp = popen(command.c_str(), "r"); |
344 |
✗✓ | 26 |
if(fp == NULL){ |
345 |
std::cerr << "phoenix_popen : cannot get result of command '"<<command<<"'" << std::endl; |
||
346 |
return ""; |
||
347 |
} |
||
348 |
✓ | 52 |
std::string resultCommand(getFileContent(fp)); |
349 |
✓ | 26 |
pclose(fp); |
350 |
26 |
return resultCommand; |
|
351 |
} |
||
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 |
✓✓ | 7 |
if(command == ""){return -1;} |
361 |
6 |
FILE * fp = popen(command.c_str(), "r"); |
|
362 |
✗✓ | 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 |
✓ | 4 |
std::string executionLog(""); |
378 |
✓ | 4 |
bool b(phoenix_popen(executionLog, command) == 0); |
379 |
✓✓ | 4 |
if(!b){ |
380 |
✓✓✓✓ ✓✓ |
2 |
std::cerr << "phoenix_popen : command '"<<command<<"' failed. To get more information see log '"<<executionLogFile<<"'" << std::endl; |
381 |
} |
||
382 |
✓✓✓✓ ✓✓ |
4 |
if((onlyLogOnFail && !b) || !onlyLogOnFail){ |
383 |
✓✗✓ | 3 |
if(!saveFileContent(executionLogFile, executionLog)){ |
384 |
std::cerr << "phoenix_popen : cannot create log file '"<<executionLogFile<<"'" << std::endl; |
||
385 |
} |
||
386 |
} |
||
387 |
8 |
return b; |
|
388 |
} |
||
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 |
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 |
✓✓✓✓ |
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 |
✓✓ | 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 |
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 |
✓ | 24 |
std::time_t currentTime = phoenix_getTime(); |
454 |
24 |
std::tm* now_tm = std::gmtime(¤tTime); |
|
455 |
char buf[42]; |
||
456 |
24 |
std::strftime(buf, 42, "%Y/%m/%d : %X", now_tm); |
|
457 |
✓ | 24 |
return buf; |
458 |
} |
||
459 |
|||
460 |
///Get the current date |
||
461 |
/** @return current date |
||
462 |
*/ |
||
463 |
89 |
std::string phoenix_getDateCompact(){ |
|
464 |
✓ | 89 |
std::time_t currentTime = phoenix_getTime(); |
465 |
89 |
std::tm* now_tm = std::gmtime(¤tTime); |
|
466 |
char buf[42]; |
||
467 |
89 |
std::strftime(buf, 42, "%Y/%m/%d-%X", now_tm); |
|
468 |
✓ | 89 |
return buf; |
469 |
} |
Generated by: GCOVR (Version 4.2) |