1 // -*- coding: utf-8 -*-
2 //
3 // EmbeddedResource.hxx --- Class for pointing to/accessing an embedded resource
4 // Copyright (C) 2017  Florent Rougon
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Library General Public
8 // License as published by the Free Software Foundation; either
9 // version 2 of the License, or (at your option) any later version.
10 //
11 // This library 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 GNU
14 // Library General Public License for more details.
15 //
16 // You should have received a copy of the GNU Library General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 // MA  02110-1301  USA.
20 
21 #ifndef FG_EMBEDDEDRESOURCE_HXX
22 #define FG_EMBEDDEDRESOURCE_HXX
23 
24 #include <iosfwd>
25 #include <string>
26 #include <ostream>
27 #include <memory>               // std::unique_ptr
28 #include <cstddef>              // std::size_t, std::ptrdiff_t
29 
30 #include <simgear/io/iostreams/zlibstream.hxx>
31 
32 
33 namespace simgear
34 {
35 
36 // Abstract base class for embedded resources
37 class AbstractEmbeddedResource
38 {
39 public:
40   enum class CompressionType {
41     NONE = 0,
42     ZLIB
43   };
44 
45   // Constructor.
46   //
47   // 'data' and 'size' indicate the resource contents. There is no requirement
48   // of null-termination, including for text data (given how
49   // EmbeddedResourceManager::getString() works, including a null terminator
50   // for text contents is actually counter-productive). The data may be of
51   // arbitrary type and size: binary, text, whatever. The constructed object
52   // (for derived classes since this one is abstract) does *not* hold a copy
53   // of the data, it just keeps a pointer to it and provides methods to access
54   // it. The data must therefore remain available as long as the object is in
55   // use---this class was designed for use with data stored in static
56   // variables.
57   explicit AbstractEmbeddedResource(const char *data, std::size_t size);
58   AbstractEmbeddedResource(const AbstractEmbeddedResource&) = default;
59   AbstractEmbeddedResource(AbstractEmbeddedResource&&) = default;
60   AbstractEmbeddedResource& operator=(const AbstractEmbeddedResource&) = default;
61   AbstractEmbeddedResource& operator=(AbstractEmbeddedResource&&) = default;
62   virtual ~AbstractEmbeddedResource() = default;
63 
64   // Return the pointer to beginning-of-resource contents---the same that was
65   // passed to the constructor.
66   const char *rawPtr() const;
67   // Return the resource size, as passed to the constructor. For a compressed
68   // resource, this is the compressed size; such resources provide an
69   // additional uncompressedSize() method.
70   std::size_t rawSize() const;
71 
72   // Return an std::string object containing a copy of the resource contents.
73   // For a compressed resource, this is the data obtained after decompression.
74   virtual std::string str() const;
75   // Return an std::streambuf instance providing read-only access to the
76   // resource contents (in uncompressed form for compressed resources). This
77   // allows memory-friendly access to large resources by enabling incremental
78   // processing with transparent decompression for compressed resources.
79   virtual std::unique_ptr<std::streambuf> streambuf() const = 0;
80   // Return an std::istream instance providing read-only access to the
81   // resource contents (in uncompressed form for compressed resources).
82   //
83   // The same remark as for streambuf() applies. std::istream is simply a
84   // higher-level interface than std::streambuf, otherwise both allow the same
85   // kind of processing.
86   virtual std::unique_ptr<std::istream> istream() const = 0;
87 
88   // Return the resource compression type.
89   virtual CompressionType compressionType() const = 0;
90   // Return a string description of the resource compression type. Examples:
91   // "none", "zlib".
92   virtual std::string compressionDescr() const = 0;
93 
94 private:
95   // Pointer to the start of resource contents
96   const char *_data;
97   // Size of resource contents, in bytes
98   std::size_t _size;
99 };
100 
101 // Class to describe an uncompressed resource. See AbstractEmbeddedResource.
102 class RawEmbeddedResource : public AbstractEmbeddedResource
103 {
104 public:
105   explicit RawEmbeddedResource(const char *data, std::size_t size);
106 
107   AbstractEmbeddedResource::CompressionType compressionType() const override;
108   std::string compressionDescr() const override;
109 
110   // The str() method is inherited from AbstractEmbeddedResource
111   std::unique_ptr<std::streambuf> streambuf() const override;
112   std::unique_ptr<std::istream> istream() const override;
113 };
114 
115 // Class to describe a zlib-compressed resource.
116 //
117 // Instances of this class point to resource contents stored in the stream
118 // format documented in RFC 1950.
119 class ZlibEmbeddedResource : public AbstractEmbeddedResource
120 {
121 public:
122   explicit ZlibEmbeddedResource(const char *data, std::size_t compressedSize,
123                                 std::size_t uncompressedSize);
124 
125   AbstractEmbeddedResource::CompressionType compressionType() const override;
126   std::string compressionDescr() const override;
127   // Return the resource uncompressed size, in bytes.
128   std::size_t uncompressedSize() const;
129 
130   std::string str() const override;
131   std::unique_ptr<std::streambuf> streambuf() const override;
132   std::unique_ptr<std::istream> istream() const override;
133 
134   // Getters and setters for parameters used in streambuf() and istream().
135   // Calling any of the setters affects the subsequent streambuf() and
136   // istream() calls.
137   char* getInputBufferStart();
138   void setInputBufferStart(char* inBuf);
139   std::size_t getInputBufferSize();
140   void setInputBufferSize(std::size_t size);
141   char* getOutputBufferStart();
142   void setOutputBufferStart(char* outBuf);
143   std::size_t getOutputBufferSize();
144   void setOutputBufferSize(std::size_t size);
145   std::size_t getPutbackSize();
146   void setPutbackSize(std::size_t size);
147 
148 private:
149   std::size_t _uncompressedSize;
150   char* _inBuf;
151   std::size_t _inBufSize;
152   char* _outBuf;
153   std::size_t _outBufSize;
154   std::size_t _putbackSize;
155 };
156 
157 // These functions are essentially intended for troubleshooting purposes.
158 std::ostream& operator<<(std::ostream&, const RawEmbeddedResource&);
159 std::ostream& operator<<(std::ostream&, const ZlibEmbeddedResource&);
160 
161 } // of namespace simgear
162 
163 #endif  // of FG_EMBEDDEDRESOURCE_HXX
164