FlightGear next
fgrcc.hxx
Go to the documentation of this file.
1// -*- coding: utf-8 -*-
2//
3// fgrcc.hxx --- Simple resource compiler for FlightGear
4// Copyright (C) 2017 Florent Rougon
5//
6// This program is free software; you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 2 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License along
17// with this program; if not, write to the Free Software Foundation, Inc.,
18// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20#ifndef _FGRCC_HXX_
21#define _FGRCC_HXX_
22
23#include <ios>
24#include <iosfwd>
25#include <vector>
26#include <array>
27#include <cstddef> // std::size_t
28
29#include <simgear/misc/sg_path.hxx>
30#include <simgear/xml/easyxml.hxx>
31#include <simgear/embedded_resources/EmbeddedResource.hxx>
32
33// Simple class to hold data gathered by the parser. Each instance corresponds
34// to a resource declaration (i.e., to a 'file' element in the XML resource
35// declaration file).
37{
39 const SGPath& virtualPath, const SGPath& realPath,
40 const std::string& language,
41 simgear::AbstractEmbeddedResource::CompressionType compressionType);
42
43 bool isCompressed() const;
44
46 SGPath realPath;
47 std::string language;
48 simgear::AbstractEmbeddedResource::CompressionType compressionType;
49};
50
51// Class for turning a byte stream into a stream of escape sequences suitable
52// for use inside a C++ string literal. This class could be changed so as to
53// be *derived* from std::istream, however this is not needed here.
55{
56public:
57 explicit CPPEncoder(std::istream& inputStream);
58
59 // Used to implement operator<<
60 virtual std::size_t write(std::ostream& oStream);
61
62private:
63 // errorNumber: should be the 'errno' value set by the failing call.
64 [[ noreturn ]] static void handleWriteError(int errorNumber);
65
66 std::istream& _inputStream;
67};
68
69std::ostream& operator<<(std::ostream&, CPPEncoder&);
70
71// Generate all the C++ code needed to initialize a set of resources with the
72// EmbeddedResourceManager.
74{
75public:
76 explicit ResourceCodeGenerator(
77 const std::vector<ResourceDeclaration>& resourceDeclarations,
78 std::ostream& outputStream,
79 const SGPath& outputCppFile,
80 const std::string& initFuncName,
81 const SGPath& outputHeaderFile,
82 const std::string& headerIdentifier,
83 std::size_t inBufSize = 262144,
84 std::size_t outBufSize = 242144);
85
86 void writeCode() const; // write the main C++ file
87 void writeHeaderFile() const; // write the associated header file
88
89private:
90 // Return a string representing the compression type of a resource
91 static std::string resourceClass(
92 simgear::AbstractEmbeddedResource::CompressionType compressionType);
93 // Encode an integral index in a way that can be safely used as part of a
94 // C++ variable name. This is needed because, for instance, 'resource10' is
95 // not a valid C++ variable name.
96 static std::string encodeResourceIndex(std::size_t index);
97 std::size_t writeEncodedResourceContents(const ResourceDeclaration& resDecl)
98 const;
99
100 const std::vector<ResourceDeclaration>& _resDecl;
101 std::ostream& _outputStream;
102 const SGPath _outputCppFile; // SGPath() if stdout, otherwise the path
103 const std::string _initFuncName; // in UTF-8 encoding
104 const SGPath _outputHeaderFile; // SGPath() if header not requested
105 const std::string _headerIdentifier; // in UTF-8 encoding
106
107 const std::size_t _compInBufSize;
108 const std::size_t _compOutBufSize;
109 std::unique_ptr<char[]> _compressionInBuf;
110 std::unique_ptr<char[]> _compressionOutBuf;
111};
112
113// Parser class for XML resource declaration files
114class ResourceBuilderXMLVisitor: public XMLVisitor
115{
116public:
117 explicit ResourceBuilderXMLVisitor(const SGPath& rootDir);
118
119 // Give access to the structured data obtained once parsing is finished
120 const std::vector<ResourceDeclaration>& getResourceDeclarations() const;
121
122protected:
123 void startElement(const char *name, const XMLAttributes &atts) override;
124 void endElement(const char *name) override;
125 void data(const char *s, int len) override;
126 void warning(const char *message, int line, int column) override;
127
128private:
129 void startQResourceElement(const XMLAttributes &atts);
130 void startFileElement(const XMLAttributes &atts);
131 void error(const char *message, int line, int column);
132
133 enum class XMLTagType {
134 START = 0,
135 END
136 };
137
138 static const std::array<std::string, 2> _tagTypeStr;
139
140 enum class ParserState {
141 START = 0,
142 INSIDE_FGRCC_ELT,
143 INSIDE_QRESOURCE_ELT,
144 INSIDE_FILE_ELT,
145 END
146 };
147
148 static const std::array<std::string, 5> _parserStateStr;
149
150 static bool readBoolean(const std::string& s);
151
152 static simgear::AbstractEmbeddedResource::CompressionType
153 determineCompressionType(const SGPath& resourceFilePath,
154 const std::string& compression);
155
156 [[ noreturn ]] void unexpectedTagError(
157 XMLTagType tagType, const std::string& found,
158 const std::string& expected = std::string());
159
160 ParserState _parserState = ParserState::START;
161 // Value obtained from the --root command line option
162 const SGPath _rootDir;
163
164 // 'prefix' attribute of the current 'qresource' element
165 std::string _currentPrefix;
166 // 'lang' attribute of the current 'qresource' element
167 std::string _currentLanguage;
168 // 'alias' attribute of the current 'file' element
169 std::string _currentAlias;
170 // This attribute is not part of the v1.0 QRC format, it's a FlightGear
171 // extension. It tells whether, and if so, how the current <file> should be
172 // compressed in the generated code.
173 std::string _currentCompressionTypeStr;
174 // String used to assemble resource file paths declared in 'file' elements
175 // (the contents of an element can be provided in several chunks by
176 // XMLVisitor::data())
177 std::string _resourceFile;
178
179 // Holds the resulting structured data once the parsing is finished
180 std::vector<ResourceDeclaration> _resourceDeclarations;
181};
182
183#endif // _FGRCC_HXX_
CPPEncoder(std::istream &inputStream)
Definition fgrcc.cxx:447
virtual std::size_t write(std::ostream &oStream)
Definition fgrcc.cxx:462
ResourceBuilderXMLVisitor(const SGPath &rootDir)
Definition fgrcc.cxx:148
void endElement(const char *name) override
Definition fgrcc.cxx:255
const std::vector< ResourceDeclaration > & getResourceDeclarations() const
Definition fgrcc.cxx:153
void warning(const char *message, int line, int column) override
Definition fgrcc.cxx:428
void data(const char *s, int len) override
Definition fgrcc.cxx:396
void startElement(const char *name, const XMLAttributes &atts) override
Definition fgrcc.cxx:216
void writeCode() const
Definition fgrcc.cxx:626
ResourceCodeGenerator(const std::vector< ResourceDeclaration > &resourceDeclarations, std::ostream &outputStream, const SGPath &outputCppFile, const std::string &initFuncName, const SGPath &outputHeaderFile, const std::string &headerIdentifier, std::size_t inBufSize=262144, std::size_t outBufSize=242144)
Definition fgrcc.cxx:524
void writeHeaderFile() const
Definition fgrcc.cxx:744
const char * name
std::ostream & operator<<(std::ostream &, CPPEncoder &)
Definition fgrcc.cxx:514
simgear::AbstractEmbeddedResource::CompressionType compressionType
Definition fgrcc.hxx:48
bool isCompressed() const
Definition fgrcc.cxx:110
std::string language
Definition fgrcc.hxx:47
ResourceDeclaration(const SGPath &virtualPath, const SGPath &realPath, const std::string &language, simgear::AbstractEmbeddedResource::CompressionType compressionType)
Definition fgrcc.cxx:100