Aeon Engine c550894
AeonGames Open Source Game Engine
Loading...
Searching...
No Matches
ProtoBufHelpers.hpp
1/*
2Copyright (C) 2016,2018,2019,2021,2023-2026 Rodrigo Jose Hernandez Cordoba
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16#ifndef AEONGAMES_PROTOBUFHELPERS_H
17#define AEONGAMES_PROTOBUFHELPERS_H
18#include <fstream>
19#include <sstream>
20#include <exception>
21#include <limits>
22#include <mutex>
23#ifdef _MSC_VER
24#pragma warning( push )
25#pragma warning( disable : PROTOBUF_WARNINGS )
26#endif
27#include <google/protobuf/text_format.h>
28#include <google/protobuf/io/zero_copy_stream.h>
29#ifdef _MSC_VER
30#pragma warning( pop )
31#endif
32#include "aeongames/Utilities.hpp"
34
35namespace AeonGames
36{
41 constexpr uint64_t operator ""_mgk ( const char* literal, const std::size_t ) noexcept
42 {
44 return
45 ( static_cast<uint64_t> ( literal[7] ) << 56 ) |
46 ( static_cast<uint64_t> ( literal[6] ) << 48 ) |
47 ( static_cast<uint64_t> ( literal[5] ) << 40 ) |
48 ( static_cast<uint64_t> ( literal[4] ) << 32 ) |
49 ( static_cast<uint64_t> ( literal[3] ) << 24 ) |
50 ( static_cast<uint64_t> ( literal[2] ) << 16 ) |
51 ( static_cast<uint64_t> ( literal[1] ) << 8 ) |
52 static_cast<uint64_t> ( literal[0] );
53 }
54
60 class BufferInputStream : public google::protobuf::io::ZeroCopyInputStream
61 {
62 public:
67 BufferInputStream ( const void * aData, size_t aSize ) :
68 mStart{ reinterpret_cast<const uint8_t*> ( aData ) },
69 mCursor{ mStart },
70 mEnd{mStart + aSize} {}
71
72 virtual ~BufferInputStream() {}
78 bool Next ( const void** data, int* size ) override
79 {
80 *data = mCursor;
81 *size = ( ( mEnd - mCursor ) > std::numeric_limits<int>::max() ) ? std::numeric_limits<int>::max() : static_cast<int> ( mEnd - mCursor );
82 mCursor += *size;
83 return ( ( mCursor != mEnd ) || *size );
84 }
85
88 void BackUp ( int count ) override
89 {
90 mCursor = ( ( mCursor - count ) > mStart ) ? mCursor - count : mStart;
91 }
92
96 bool Skip ( int count ) override
97 {
98 mCursor = ( ( mCursor + count ) < mEnd ) ? mCursor + count : mEnd;
99 return mCursor != mEnd;
100 }
101
104 google::protobuf::int64 ByteCount() const override
105 {
106 return mCursor - mStart;
107 }
108 private:
109 const uint8_t* mStart;
110 const uint8_t* mCursor;
111 const uint8_t* mEnd;
112 };
113
125 template<class T> void LoadProtoBufObject ( T& t, const void * aData, size_t aSize, uint64_t aMagick )
126 {
127 if ( !aData || aSize < 8 )
128 {
129 throw std::runtime_error ( "Not enough data or null pointer passed to LoadProtoBufObject." );
130 }
131 if ( strncmp ( reinterpret_cast<const char * > ( aData ), reinterpret_cast<const char * > ( &aMagick ), 7 ) != 0 )
132 {
133 std::ostringstream stream;
134 stream << "Provided buffer does not contain " << reinterpret_cast<const char*> ( &aMagick ) << " information.";
135 std::cout << LogLevel::Error << stream.str() << std::endl;
136 throw std::runtime_error ( stream.str().c_str() );
137 }
138 else if ( reinterpret_cast<const uint8_t * > ( aData ) [7] == '\0' )
139 {
140 BufferInputStream buffer_input_stream ( reinterpret_cast<const uint8_t*> ( aData ) + 8, aSize - 8 );
141 if ( !t.ParseFromZeroCopyStream ( &buffer_input_stream ) )
142 {
143 std::ostringstream stream;
144 stream << "Binary parse failed on " << reinterpret_cast<const char*> ( &aMagick ) << "buffer.";
145 std::cout << LogLevel::Error << stream.str() << std::endl;
146 throw std::runtime_error ( stream.str().c_str() );
147 }
148 }
149 else
150 {
151 BufferInputStream buffer_input_stream ( reinterpret_cast<const uint8_t*> ( aData ) + 8, aSize - 8 );
152 if ( !google::protobuf::TextFormat::Parse ( &buffer_input_stream, &t ) )
153 {
154 std::ostringstream stream;
155 stream << "Text parse failed on " << reinterpret_cast<const char*> ( &aMagick ) << " buffer.";
156 std::cout << LogLevel::Error << stream.str() << std::endl;
157 throw std::runtime_error ( stream.str().c_str() );
158 }
159 }
160 }
161
169 template<class T> T LoadProtoBufObject ( const void * aData, size_t aSize, uint64_t aMagick )
170 {
171 T t;
172 LoadProtoBufObject ( t, aData, aSize, aMagick );
173 return t;
174 }
175
186 template<class T> void LoadProtoBufObject ( T& t, const std::string& aFilename, uint64_t aMagick )
187 {
188 if ( !FileExists ( aFilename ) )
189 {
190 std::ostringstream stream;
191 stream << "File " << aFilename << " not found.";
192 throw std::runtime_error ( stream.str().c_str() );
193 }
194 std::ifstream file;
195 file.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
196 file.open ( aFilename, std::ifstream::in | std::ifstream::binary );
197 file.exceptions ( std::ifstream::badbit );
198 std::string text ( ( std::istreambuf_iterator<char> ( file ) ), std::istreambuf_iterator<char>() );
199 file.close();
200 LoadProtoBufObject ( t, text.data(), text.size(), aMagick );
201 }
202
209 template<class T> T LoadProtoBufObject ( const std::string& aFilename, uint64_t aMagick )
210 {
211 T t;
212 LoadProtoBufObject ( t, aFilename, aMagick );
213 return t;
214 }
215
228 template<class T, class U, uint64_t Magick>
229 void LoadFromProtoBufObject ( T& aTarget, const void* aBuffer, size_t aBufferSize )
230 {
231 static std::mutex m{};
232 static U buffer{};
233 std::lock_guard<std::mutex> hold ( m );
234 LoadProtoBufObject ( buffer, aBuffer, aBufferSize, Magick );
235 aTarget.LoadFromPBMsg ( buffer );
236 buffer.Clear();
237 }
238}
239#endif
Defines log severity levels and stream output for the AeonGames engine.
Zero-copy input stream that reads from a raw memory buffer.
google::protobuf::int64 ByteCount() const override
Returns the total number of bytes read from the buffer so far.
void BackUp(int count) override
Backs up the read cursor by count bytes.
virtual ~BufferInputStream()
Destructor.
bool Next(const void **data, int *size) override
Returns the next contiguous block of data from the buffer.
BufferInputStream(const void *aData, size_t aSize)
Constructs a BufferInputStream over a memory region.
bool Skip(int count) override
Skips forward count bytes in the buffer.
<- This is here just for the literals
Definition AABB.hpp:31
DLL bool FileExists(const std::string &aFilePath)
Check whether a file exists at the given path.
Definition Utilities.cpp:38
void LoadFromProtoBufObject(T &aTarget, const void *aBuffer, size_t aBufferSize)
Loads a Protocol Buffer message from a buffer and populates a target object.
@ Error
Error conditions.
Definition LogLevel.hpp:33
void LoadProtoBufObject(T &t, const void *aData, size_t aSize, uint64_t aMagick)
Loads a Protocol Buffer Object from a meory buffer into the provided reference.