LCOV - code coverage report
Current view: top level - ezlibs - ezBuildInc.hpp (source / functions) Coverage Total Hit
Test: Coverage (llvm-cov → lcov → genhtml) Lines: 86.2 % 196 169
Test Date: 2025-09-16 22:55:37 Functions: 80.0 % 25 20
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 76.1 % 46 35

             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
        

Generated by: LCOV version 2.0-1