Branch data Line data Source code
1 : : #pragma once
2 : :
3 : : /*
4 : : MIT License
5 : :
6 : : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
7 : :
8 : : Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : of this software and associated documentation files (the "Software"), to deal
10 : : in the Software without restriction, including without limitation the rights
11 : : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : copies of the Software, and to permit persons to whom the Software is
13 : : furnished to do so, subject to the following conditions:
14 : :
15 : : The above copyright notice and this permission notice shall be included in all
16 : : copies or substantial portions of the Software.
17 : :
18 : : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 : : SOFTWARE.
25 : : */
26 : :
27 : : // ezBuildInc is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
28 : :
29 : : #include <string>
30 : : #include <cstdint>
31 : : #include <fstream>
32 : : #include <sstream>
33 : : #include <iostream>
34 : :
35 : : // you msut include ezFigFont.hpp before this include
36 : : // if you want to enable the FigFont Label Generation
37 : :
38 : : namespace ez {
39 : :
40 : : /* File Format
41 : : #pragma once
42 : :
43 : : #define Project_Label "project"
44 : : #define Project_BuildNumber 3629
45 : : #define Project_MinorNumber 3
46 : : #define Project_MajorNumber 0
47 : : #define Project_BuildId "0.3.3629"
48 : : #define Project_FigFontLabel "..." // Optionnal
49 : : */
50 : :
51 : : class BuildInc {
52 : : private:
53 : : bool m_lastWriteStatus = false;
54 : : std::string m_buildFileHeader;
55 : : std::string m_project;
56 : : std::string m_label;
57 : : int32_t m_majorNumber = 0;
58 : : int32_t m_minorNumber = 0;
59 : : int32_t m_buildNumber = 0;
60 : : #ifdef EZ_FIG_FONT
61 : : class FigFontGenerator {
62 : : friend class BuildInc;
63 : : private:
64 : : ez::FigFont m_generator;
65 : : bool m_useLabel = true; // will use the label or not for the FigFont label
66 : : bool m_useBuildNumber = false; // will use the buildNumber or not for the FigFont label
67 : : public:
68 : 6 : bool isValid() { return m_generator.isValid(); }
69 : 2 : FigFontGenerator& useLabel(const bool vFlag) {
70 : 2 : m_useLabel = vFlag;
71 : 2 : return *this;
72 : 2 : }
73 : 2 : FigFontGenerator& useBuildNumber(const bool vFlag) {
74 : 2 : m_useBuildNumber = vFlag;
75 : 2 : return *this;
76 : 2 : }
77 : : } m_figFontGenerator;
78 : : #endif // EZ_FIG_FONT
79 : :
80 : : public:
81 : 1 : BuildInc(const std::string& vBuildFileHeader) {
82 : 1 : m_buildFileHeader = vBuildFileHeader;
83 : 1 : read();
84 : 1 : }
85 : 1 : BuildInc& read() {
86 : 1 : std::string content;
87 : 1 : std::ifstream docFile(m_buildFileHeader, std::ios::in);
88 [ + - ]: 1 : if (docFile.is_open()) {
89 : 1 : std::stringstream strStream;
90 : 1 : strStream << docFile.rdbuf();
91 : 1 : content = strStream.str();
92 : 1 : docFile.close();
93 : 1 : }
94 [ + - ]: 1 : if (!content.empty()) {
95 : 1 : size_t startLine = 0;
96 : 1 : size_t endLine = content.find('\n', startLine);
97 : 1 : std::string line;
98 : 1 : std::string project, key, value;
99 [ + + ]: 10 : while (endLine != std::string::npos) {
100 : 9 : line = content.substr(startLine, endLine - startLine);
101 [ + + ]: 9 : if (m_parseDefine(line, project, key, value)) {
102 : 6 : m_project = project; // overwrote each time but its the same for each
103 [ + + ]: 6 : if (key == "Label") {
104 : 1 : m_label = value;
105 [ + + ]: 5 : } else if (key == "MajorNumber") {
106 : 1 : m_majorNumber = m_toNumber(value);
107 [ + + ]: 4 : } else if (key == "MinorNumber") {
108 : 1 : m_minorNumber = m_toNumber(value);
109 [ + + ]: 3 : } else if (key == "BuildNumber") {
110 : 1 : m_buildNumber = m_toNumber(value);
111 : 1 : }
112 : 6 : }
113 : 9 : startLine = endLine+1;
114 : 9 : endLine = content.find('\n', startLine);
115 : 9 : }
116 : 1 : }
117 : 1 : return *this;
118 : 1 : }
119 : 8 : std::string getBuildIdInt() {
120 : 8 : std::stringstream ss;
121 : 8 : ss << std::setfill('0') << std::setw(2) << m_majorNumber << std::setfill('0') << std::setw(2) << m_minorNumber << m_buildNumber;
122 : 8 : return ss.str();
123 : 8 : }
124 : 8 : std::string getBuildIdStr() {
125 : 8 : std::stringstream ss;
126 : 8 : ss << m_majorNumber << "." << m_minorNumber << "." << m_buildNumber;
127 : 8 : return ss.str();
128 : 8 : }
129 : 4 : std::string getInfos() {
130 : 4 : std::stringstream project, build_id, file, infos;
131 : 4 : std::string project_str, build_id_str, file_str;
132 : 4 : build_id << "Build Id : " << getBuildIdStr() << " / " << getBuildIdInt();
133 : 4 : build_id_str = build_id.str();
134 : 4 : size_t row_len = build_id_str.size();
135 [ + - ]: 4 : if (m_lastWriteStatus) {
136 : 4 : file << "In file : " << m_buildFileHeader;
137 : 4 : } else {
138 : 0 : file << "failed to write to : " << m_buildFileHeader;
139 : 0 : }
140 : 4 : file_str = file.str();
141 [ - + ]: 4 : if (row_len < file_str.size()) {
142 : 0 : row_len = file_str.size();
143 : 0 : }
144 [ + - ]: 4 : if (!m_project.empty()) {
145 : 4 : project << "Project : " << m_project;
146 : 4 : project_str = project.str();
147 [ - + ]: 4 : if (row_len < project_str.size()) {
148 : 0 : row_len = project_str.size();
149 : 0 : }
150 : 4 : }
151 : 4 : auto spliter = std::string(row_len + 6, '-'); // +6 for '-- ' and ' --'
152 : 4 : infos << spliter << std::endl;
153 [ + - ]: 4 : if (!m_project.empty()) {
154 : 4 : infos << "-- " << project_str << std::string(row_len - project_str.size(), ' ') << " --" << std::endl;
155 : 4 : }
156 : 4 : infos << "-- " << build_id_str << std::string(row_len - build_id_str.size(), ' ') << " --" << std::endl;
157 : 4 : infos << "-- " << file_str << std::string(row_len - file_str.size(), ' ') << " --" << std::endl;
158 : 4 : infos << spliter << std::endl;
159 : 4 : return infos.str();
160 : 4 : }
161 : 4 : BuildInc& printInfos() {
162 : 4 : std::cout << getInfos();
163 : 4 : return *this;
164 : 4 : }
165 : 1 : const std::string& getProject() { return m_project; }
166 : 1 : const std::string& getLabel() { return m_label; }
167 : 1 : int32_t getMajor() { return m_majorNumber; }
168 : 1 : int32_t getMinor() { return m_minorNumber; }
169 : 1 : int32_t getBuildNumber() { return m_buildNumber; }
170 : 0 : BuildInc& setProject(const std::string& vProject) {
171 : 0 : m_project = vProject;
172 : 0 : return *this;
173 : 0 : }
174 : 0 : BuildInc& setLabel(const std::string& vLabel) {
175 : 0 : m_label = vLabel;
176 : 0 : return *this;
177 : 0 : }
178 : 0 : BuildInc& setMajor(const int32_t vMajorNumber) {
179 : 0 : m_majorNumber = vMajorNumber;
180 : 0 : return *this;
181 : 0 : }
182 : 0 : BuildInc& setMinor(const int32_t vMinorNumber) {
183 : 0 : m_minorNumber = vMinorNumber;
184 : 0 : return *this;
185 : 0 : }
186 : 0 : BuildInc& setBuildNumber(const int32_t vBuildNumber) {
187 : 0 : m_buildNumber = vBuildNumber;
188 : 0 : return *this;
189 : 0 : }
190 : 1 : BuildInc& incBuildNumber() {
191 : 1 : ++m_buildNumber;
192 : 1 : return *this;
193 : 1 : }
194 : : #ifdef EZ_FIG_FONT
195 : 2 : FigFontGenerator& setFigFontFile(const std::string& vFigFontFile) {
196 : 2 : m_figFontGenerator.m_generator.load(vFigFontFile);
197 : 2 : return m_figFontGenerator;
198 : 2 : }
199 : : #endif // EZ_FIG_FONT
200 : 4 : BuildInc& write() {
201 : 4 : m_lastWriteStatus = false;
202 : 4 : std::stringstream content;
203 : 4 : content << "#pragma once" << std::endl;
204 : 4 : content << std::endl;
205 : 4 : content << "#define " << m_project << "_Label \"" << m_label << "\"" << std::endl;
206 : 4 : content << "#define " << m_project << "_BuildNumber " << m_buildNumber << std::endl;
207 : 4 : content << "#define " << m_project << "_MinorNumber " << m_minorNumber << std::endl;
208 : 4 : content << "#define " << m_project << "_MajorNumber " << m_majorNumber << std::endl;
209 : 4 : content << "#define " << m_project << "_BuildId \"" << getBuildIdStr() << "\"" << std::endl;
210 : 4 : content << "#define " << m_project << "_BuildIdNum " << getBuildIdInt() << std::endl;
211 : 4 : #ifdef EZ_FIG_FONT
212 [ + - ]: 4 : if (m_figFontGenerator.isValid()) {
213 : 4 : std::stringstream version;
214 [ + + ]: 4 : if (m_figFontGenerator.m_useLabel) {
215 : 2 : version << m_label << " ";
216 : 2 : }
217 : 4 : version << "v" << m_majorNumber << "." << m_minorNumber;
218 [ + + ]: 4 : if (m_figFontGenerator.m_useBuildNumber) {
219 : 2 : version << "." << m_buildNumber;
220 : 2 : }
221 : 4 : content << "#define " << m_project << "_FigFontLabel u8R\"(" << m_figFontGenerator.m_generator.printString(version.str()) << ")\"" << std::endl;
222 : 4 : }
223 : 4 : #endif // EZ_FIG_FONT
224 : 4 : std::ofstream configFileWriter(m_buildFileHeader, std::ios::out);
225 [ + - ]: 4 : if (!configFileWriter.bad()) {
226 : 4 : configFileWriter << content.str();
227 : 4 : configFileWriter.close();
228 : 4 : m_lastWriteStatus = true;
229 : 4 : }
230 : 4 : return *this;
231 : 4 : }
232 : :
233 : : private:
234 : : // will parse a line '#define [PROJECT]_[KEY] [VALUE]'
235 : : // return true is succeed, false if the format is not recognized
236 : 9 : bool m_parseDefine(const std::string& vRowContent, std::string& vOutProject, std::string& vOutKey, std::string& vOutValue) {
237 [ + + ]: 9 : if (!vRowContent.empty()) {
238 : 7 : size_t def_pos = vRowContent.find("#define ");
239 [ + + ]: 7 : if (def_pos != std::string::npos) {
240 : 6 : def_pos += 8; // offset for '#define '
241 : 6 : size_t underScore_pos = vRowContent.find('_', def_pos);
242 [ + - ]: 6 : if (underScore_pos != std::string::npos) {
243 : 6 : vOutProject = vRowContent.substr(def_pos, underScore_pos - def_pos);
244 : 6 : ++underScore_pos; // offset for '_'
245 : 6 : size_t space_pos = vRowContent.find(' ', underScore_pos);
246 [ + - ]: 6 : if (space_pos != std::string::npos) {
247 : 6 : vOutKey = vRowContent.substr(underScore_pos, space_pos - underScore_pos);
248 : 6 : ++space_pos; // offset for ' '
249 : 6 : vOutValue = m_trim(vRowContent.substr(space_pos));
250 : 6 : return true;
251 : 6 : }
252 : 6 : }
253 : 6 : }
254 : 7 : }
255 : 3 : return false;
256 : 9 : }
257 : 3 : int32_t m_toNumber(const std::string& vNum) {
258 : 3 : int32_t ret = 0; // 0 is the default value
259 : 3 : try {
260 : 3 : ret = std::stoi(vNum);
261 : 3 : } catch (...) {
262 : 0 : }
263 : 3 : return ret;
264 : 3 : }
265 : : // will remove quotes
266 : 6 : std::string m_trim(const std::string& vValue) {
267 : 6 : std::string ret;
268 [ + + ]: 33 : for (auto& c : vValue) {
269 [ + + ]: 33 : if (c != '\"') {
270 : 29 : ret += c;
271 : 29 : }
272 : 33 : }
273 : 6 : return ret;
274 : 6 : }
275 : : };
276 : :
277 : : } // namespace ez
|