1 /*
2 This file forked from https://github.com/srajotte/libplyxx
3 
4 Copyright (c) 2016 Simon Rajotte
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 
24 Updated (c) 2021 Runette Software Ltd to make multiplatform, to complete the typemaps and add to voxel types.
25 
26 Permission is hereby granted, free of charge, to any person obtaining a copy
27 of this software and associated documentation files (the "Software"), to deal
28 in the Software without restriction, including without limitation the rights
29 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
30 copies of the Software, and to permit persons to whom the Software is
31 furnished to do so, subject to the following conditions:
32 
33 The above copyright notice and this permission notice shall be included in all
34 copies or substantial portions of the Software.
35 
36 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
39 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
40 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
41 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
42 SOFTWARE.
43 
44 */
45 
46 #pragma once
47 
48 #include <vector>
49 #include <array>
50 #include <map>
51 #include <unordered_map>
52 #include <type_traits>
53 #include <cassert>
54 #include <memory>
55 #include <functional>
56 
57 #include "textio.h"
58 
59 namespace libply
60 {
61   enum class Type
62   {
63     INT8,
64     UINT8,
65     INT16,
66     UINT16,
67     INT32,
68     UINT32,
69     FLOAT32,
70     FLOAT64,
71     COORDINATE
72   };
73 
74   class IProperty
75   {
76     public:
77       virtual ~IProperty() = default;
78 
79       virtual IProperty &operator=( unsigned int value ) = 0;
80       virtual IProperty &operator=( int value ) = 0;
81       virtual IProperty &operator=( float value ) = 0;
82       virtual IProperty &operator=( double value ) = 0;
83 
84       virtual operator unsigned int() = 0;
85       virtual operator int() = 0;
86       virtual operator float() = 0;
87       virtual operator double() = 0;
88 
89       virtual bool isList() = 0;
90 
91   };
92 
93   template<typename InternalType>
94   class ScalarProperty: public IProperty
95   {
96     public :
97 
98       virtual ~ScalarProperty() = default;
99 
100       virtual ScalarProperty &operator=( unsigned int value ) override
101       {
102         m_value = static_cast<InternalType>( value );
103         return *this;
104       };
105       virtual ScalarProperty &operator=( int value ) override
106       {
107         m_value = static_cast<InternalType>( value );
108         return *this;
109       };
110       virtual ScalarProperty &operator=( float value ) override
111       {
112         m_value = static_cast<InternalType>( value );
113         return *this;
114       };
115       virtual ScalarProperty &operator=( double value ) override
116       {
117         m_value = static_cast<InternalType>( value );
118         return *this;
119       };
120 
121       virtual operator unsigned int() override
122       {
123         return static_cast<unsigned int>( m_value );
124       };
125       virtual operator int() override
126       {
127         return static_cast<int>( m_value );
128       };
129       virtual operator float() override
130       {
131         return static_cast<float>( m_value );
132       };
133       virtual operator double() override
134       {
135         return static_cast<double>( m_value );
136       };
137 
isList()138       virtual bool isList() override { return false; }
139 
140     public:
value()141       InternalType value() const { return m_value; };
142 
143     private :
144       InternalType m_value;
145   };
146 
147   class ListProperty : public IProperty
148   {
149     public:
150 
151       IProperty &operator=( unsigned int ) override { return *this; };
152       IProperty &operator=( int ) override  { return *this; };
153       IProperty &operator=( float ) override  { return *this; };
154       IProperty &operator=( double ) override  { return *this; };
155 
156       operator unsigned int() override { return 0; };
157       operator int() override { return 0; };
158       operator float() override { return 0; };
159       operator double() override { return 0; };
160 
isList()161       bool isList() override { return true; }
162 
163       void define( Type type, size_t size );
size()164       size_t size() const { return list.size(); }
165 
166       IProperty &value( size_t index );
167 
168     private:
169       std::vector<std::unique_ptr<IProperty>> list;
170       std::unique_ptr<IProperty> getScalarProperty( Type type );
171   };
172 
173   struct ElementDefinition;
174 
175   class ElementBuffer
176   {
177     public:
178       ElementBuffer() = default;
179       ElementBuffer( const ElementDefinition &definition );
180 
181     public:
size()182       size_t size() const { return properties.size(); };
183       IProperty &operator[]( size_t index );
184 
185     private:
186       void appendScalarProperty( Type type );
187       void appendListProperty( Type type );
188       std::unique_ptr<IProperty> getScalarProperty( Type type );
189 
190     private:
191       std::vector<std::unique_ptr<IProperty>> properties;
192   };
193 
194   struct Property
195   {
PropertyProperty196     Property( const std::string &name, Type type, bool isList )
197       : name( name ), type( type ), isList( isList ) {};
198 
199     std::string name;
200     Type type;
201     bool isList;
202     size_t listCount;
203   };
204 
205   typedef std::size_t ElementSize;
206 
207   struct Element
208   {
ElementElement209     Element( const std::string &name, ElementSize size, const std::vector<Property> &properties )
210       : name( name ), size( size ), properties( properties ) {};
211 
212     std::string name;
213     ElementSize size;
214     std::vector<Property> properties;
215   };
216 
217   typedef std::function< void( ElementBuffer & ) > ElementReadCallback;
218 
219   class FileParser;
220 
221   typedef std::vector<Element> ElementsDefinition;
222   typedef std::unordered_map<std::string, std::string> Metadata;
223 
224   class File
225   {
226     public:
227       File( const std::string &filename );
228       ~File();
229 
230       ElementsDefinition definitions() const;
231       Metadata metadata() const;
232       void setElementReadCallback( std::string elementName, ElementReadCallback &readCallback );
233       void read();
234 
235     public:
236       enum class Format
237       {
238         ASCII,
239         BINARY_LITTLE_ENDIAN,
240         BINARY_BIG_ENDIAN
241       };
242 
243     private:
244       std::string m_filename;
245       std::unique_ptr<FileParser> m_parser;
246   };
247 
248 
249   typedef std::function< void( ElementBuffer &, size_t index ) > ElementWriteCallback;
250 
251   class FileOut
252   {
253     public:
254       FileOut( const std::string &filename, File::Format format );
255 
256       void setElementsDefinition( const ElementsDefinition &definitions );
257       void setElementWriteCallback( const std::string &elementName, ElementWriteCallback &writeCallback );
258       void write();
259       Metadata metadata;
260 
261     private:
262       void createFile();
263       void writeHeader();
264       void writeData();
265 
266     private:
267       std::string m_filename;
268       File::Format m_format;
269       ElementsDefinition m_definitions;
270       std::map<std::string, ElementWriteCallback> m_writeCallbacks;
271   };
272 }
273