GCC Code Coverage Report


Directory: ./
File: src/directory_replace_placeholder.cpp
Date: 2026-09-29 15:32:11
Exec Total Coverage
Lines: 33 49 67.3%
Functions: 3 4 75.0%
Branches: 41 79 51.9%

Line Branch Exec Source
1 /***************************************
2 Auteur : Pierre Aubert
3 Mail : pierre.aubert@lapp.in2p3.fr
4 Licence : LGPL-3.0-only
5 ****************************************/
6
7
8 #include <fstream>
9 #include <set>
10
11 #include "directory_replace_placeholder.h"
12
13 ///Extensions of binary/image assets that must never go through text placeholder substitution :
14 ///it is meaningless on such content (no XXXPlaceholderXXX token to substitute), unsafe (PPath::saveFileContent
15 ///writes through a NUL-terminated C string, so binary content gets truncated at the first embedded '\0'),
16 ///and prohibitively slow on large files (PString concatenation is not amortised, so replace() on a
17 ///multi-megabyte blob is effectively quadratic).
18 /** @param file : file to be checked
19 * @return true if the file extension is a known binary/image asset
20 */
21 8 bool directory_replace_isBinaryAsset(const PPath & file){
22 static const std::set<PString> setBinaryExtension{
23 //images
24 "png", "jpg", "jpeg", "gif", "bmp", "ico", "svg", "webp", "tiff", "tif",
25 //fonts
26 "woff", "woff2", "ttf", "otf", "eot",
27 //archives
28 "zip", "gz", "tar", "7z", "bz2", "xz",
29 //documents
30 "pdf",
31 //audio/video
32 "mp3", "mp4", "wav", "ogg", "avi", "mov",
33 //compiled/binary artefacts
34 "so", "dll", "dylib", "a", "o", "exe", "class", "pyc"
35
9/18
✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→19) taken 7 times.
✓ Branch 2 (4→5) taken 1 times.
✗ Branch 3 (4→19) not taken.
✓ Branch 4 (6→7) taken 36 times.
✓ Branch 6 (8→6) taken 36 times.
✓ Branch 7 (8→9) taken 1 times.
✓ Branch 8 (11→12) taken 1 times.
✓ Branch 10 (16→17) taken 36 times.
✓ Branch 11 (16→18) taken 1 times.
✗ Branch 12 (33→34) not taken.
✗ Branch 13 (33→35) not taken.
✗ Branch 14 (36→37) not taken.
✗ Branch 15 (36→40) not taken.
✗ Branch 16 (38→39) not taken.
✗ Branch 17 (38→40) not taken.
✗ Branch 18 (42→43) not taken.
✗ Branch 19 (42→44) not taken.
82 };
36
3/3
✓ Branch 0 (19→20) taken 8 times.
✓ Branch 2 (20→21) taken 8 times.
✓ Branch 4 (21→22) taken 8 times.
8 return setBinaryExtension.find(file.getExtension().toLower()) != setBinaryExtension.end();
37 }
38
39 ///Copy a file byte for byte, with no text processing of any kind (safe for binary content)
40 /** @param inputFile : source file
41 * @param outputFile : destination file
42 * @return true on success, false otherwise
43 */
44 ✗ bool directory_replace_copyBinaryFile(const PPath & inputFile, const PPath & outputFile){
45 ✗ std::ifstream in(inputFile.c_str(), std::ios::binary);
46 ✗ if(!in.is_open()){return false;}
47 ✗ std::ofstream out(outputFile.c_str(), std::ios::binary);
48 ✗ if(!out.is_open()){return false;}
49 ✗ out << in.rdbuf();
50 ✗ return static_cast<bool>(out);
51 ✗ }
52
53 ///Replace placeholder in a directory and its content by respect to the given map of value for all place holder (file only)
54 /** @param outputDir : output directory
55 * @param inputConfigDir : input configuration directory
56 * @param mapReplacePlaceholder : map of placeholders and values to be replaced with
57 * @return true on success, false otherwise
58 */
59 7 bool directory_replace_placeholderFile(const PPath & outputDir, const PPath & inputConfigDir, const PMapString & mapReplacePlaceholder){
60 7 bool b(true);
61
1/1
✓ Branch 0 (2→3) taken 7 times.
7 PVecPath vecFileInputDir = inputConfigDir.getAllFileInDir();
62
2/2
✓ Branch 0 (48→4) taken 8 times.
✓ Branch 1 (48→49) taken 7 times.
30 for(PVecPath::iterator it(vecFileInputDir.begin()); it != vecFileInputDir.end(); ++it){
63
2/2
✓ Branch 0 (6→7) taken 8 times.
✓ Branch 2 (7→8) taken 8 times.
16 PPath relativeFile = it->replace(mapReplacePlaceholder);
64
1/1
✓ Branch 0 (11→12) taken 8 times.
16 PPath fullFile = inputConfigDir / *it;
65
1/1
✓ Branch 0 (12→13) taken 8 times.
8 PPath outputFile = outputDir / relativeFile;
66
2/3
✓ Branch 0 (13→14) taken 8 times.
✗ Branch 2 (14→15) not taken.
✓ Branch 3 (14→17) taken 8 times.
8 if(directory_replace_isBinaryAsset(fullFile)){
67 //Binary/image assets are copied verbatim, the file name/path may still use placeholders, but the content must not be touched
68 ✗ b &= directory_replace_copyBinaryFile(fullFile, outputFile);
69 ✗ continue;
70 }
71
1/1
✓ Branch 0 (17→18) taken 8 times.
8 PString fileContent = fullFile.loadFileContent();
72 //TODO : this could be optimised with the dico_replace_var algorithm, but this is enough for now
73
1/1
✓ Branch 0 (18→19) taken 8 times.
8 PString replacedContent = fileContent.replace(mapReplacePlaceholder);
74
1/1
✓ Branch 0 (19→20) taken 8 times.
8 b &= outputFile.saveFileContent(replacedContent);
75
3/6
✓ Branch 0 (24→25) taken 8 times.
✗ Branch 1 (24→26) not taken.
✓ Branch 2 (29→30) taken 8 times.
✗ Branch 3 (29→31) not taken.
✓ Branch 4 (34→35) taken 8 times.
✗ Branch 5 (34→37) not taken.
24 }
76 7 return b;
77 7 }
78
79 ///Replace placeholder in a directory and its content by respect to the given map of value for all place holder
80 /** @param outputDir : output directory
81 * @param inputConfigDir : input configuration directory
82 * @param mapReplacePlaceholder : map of placeholders and values to be replaced with
83 * @return true on success, false otherwise
84 */
85 4 bool directory_replace_placeholder(const PPath & outputDir, const PPath & inputConfigDir, const PMapString & mapReplacePlaceholder){
86
2/3
✓ Branch 0 (2→3) taken 4 times.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→9) taken 4 times.
4 if(!outputDir.createDirectory()){
87 ✗ std::cerr << "directory_replace_placeholder : cannot create dir '"<<outputDir<<"'" << std::endl;
88 ✗ return false;
89 }
90 //Let's get content of inputConfigDir
91
1/1
✓ Branch 0 (9→10) taken 4 times.
4 PVecPath vecDirInputDir = inputConfigDir.getAllDirectoryInDir();
92 4 bool b(true);
93
2/2
✓ Branch 0 (36→11) taken 3 times.
✓ Branch 1 (36→37) taken 4 times.
14 for(PVecPath::iterator itDir(vecDirInputDir.begin()); itDir != vecDirInputDir.end(); ++itDir){
94
2/2
✓ Branch 0 (13→14) taken 3 times.
✓ Branch 2 (14→15) taken 3 times.
6 PPath relativeDir = itDir->replace(mapReplacePlaceholder);
95
1/1
✓ Branch 0 (18→19) taken 3 times.
6 PPath fullInputDir = inputConfigDir / *itDir;
96
1/1
✓ Branch 0 (19→20) taken 3 times.
3 PPath fullOutputDir = outputDir / relativeDir;
97
1/1
✓ Branch 0 (20→21) taken 3 times.
3 b &= fullOutputDir.createDirectory();
98
99
1/1
✓ Branch 0 (21→22) taken 3 times.
3 b &= directory_replace_placeholderFile(fullOutputDir, fullInputDir, mapReplacePlaceholder);
100
1/1
✓ Branch 0 (22→23) taken 3 times.
3 b &= directory_replace_placeholder(fullOutputDir, fullInputDir, mapReplacePlaceholder);
101 3 }
102
1/1
✓ Branch 0 (37→38) taken 4 times.
4 b &= directory_replace_placeholderFile(outputDir, inputConfigDir, mapReplacePlaceholder);
103
1/2
✗ Branch 0 (38→39) not taken.
✓ Branch 1 (38→50) taken 4 times.
4 if(!b){
104 ✗ std::cerr << "directory_replace_placeholder : cannot create output directories architecture" << std::endl;
105 ✗ std::cerr << "\tinputConfigDir = '"<<inputConfigDir<<"'" << std::endl;
106 ✗ std::cerr << "\toutputDir = '"<<outputDir<<"'" << std::endl;
107 ✗ return false;
108 }
109 4 return b;
110 4 }
111