1/*
2Open Asset Import Library (assimp)
3----------------------------------------------------------------------
4
5Copyright (c) 2006-2019, assimp team
6
7
8All rights reserved.
9
10Redistribution and use of this software in source and binary forms,
11with or without modification, are permitted provided that the
12following conditions are met:
13
14* Redistributions of source code must retain the above
15 copyright notice, this list of conditions and the
16 following disclaimer.
17
18* Redistributions in binary form must reproduce the above
19 copyright notice, this list of conditions and the
20 following disclaimer in the documentation and/or other
21 materials provided with the distribution.
22
23* Neither the name of the assimp team, nor the names of its
24 contributors may be used to endorse or promote products
25 derived from this software without specific prior
26 written permission of the assimp team.
27
28THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
40----------------------------------------------------------------------
41*/
42
43/** @file FBXUtil.cpp
44 * @brief Implementation of internal FBX utility functions
45 */
46
47#include "FBXUtil.h"
48#include "FBXTokenizer.h"
49
50#include <assimp/TinyFormatter.h>
51#include <string>
52#include <cstring>
53
54#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
55
56namespace Assimp {
57namespace FBX {
58namespace Util {
59
60// ------------------------------------------------------------------------------------------------
61const char* TokenTypeString(TokenType t)
62{
63 switch(t) {
64 case TokenType_OPEN_BRACKET:
65 return "TOK_OPEN_BRACKET";
66
67 case TokenType_CLOSE_BRACKET:
68 return "TOK_CLOSE_BRACKET";
69
70 case TokenType_DATA:
71 return "TOK_DATA";
72
73 case TokenType_COMMA:
74 return "TOK_COMMA";
75
76 case TokenType_KEY:
77 return "TOK_KEY";
78
79 case TokenType_BINARY_DATA:
80 return "TOK_BINARY_DATA";
81 }
82
83 ai_assert(false);
84 return "";
85}
86
87
88// ------------------------------------------------------------------------------------------------
89std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset)
90{
91 return static_cast<std::string>( (Formatter::format() << prefix << " (offset 0x" << std::hex << offset << ") " << text) );
92}
93
94// ------------------------------------------------------------------------------------------------
95std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column)
96{
97 return static_cast<std::string>( (Formatter::format() << prefix << " (line " << line << " << col " << column << ") " << text) );
98}
99
100// ------------------------------------------------------------------------------------------------
101std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok)
102{
103 if(tok->IsBinary()) {
104 return static_cast<std::string>( (Formatter::format() << prefix <<
105 " (" << TokenTypeString(t: tok->Type()) <<
106 ", offset 0x" << std::hex << tok->Offset() << ") " <<
107 text) );
108 }
109
110 return static_cast<std::string>( (Formatter::format() << prefix <<
111 " (" << TokenTypeString(t: tok->Type()) <<
112 ", line " << tok->Line() <<
113 ", col " << tok->Column() << ") " <<
114 text) );
115}
116
117// Generated by this formula: T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;
118static const uint8_t base64DecodeTable[128] = {
119 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
120 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
121 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
122 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
123 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
124 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
125 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
126 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255
127};
128
129uint8_t DecodeBase64(char ch)
130{
131 const auto idx = static_cast<uint8_t>(ch);
132 if (idx > 127)
133 return 255;
134 return base64DecodeTable[idx];
135}
136
137size_t ComputeDecodedSizeBase64(const char* in, size_t inLength)
138{
139 if (inLength < 2)
140 {
141 return 0;
142 }
143 const size_t equals = size_t(in[inLength - 1] == '=') + size_t(in[inLength - 2] == '=');
144 const size_t full_length = (inLength * 3) >> 2; // div by 4
145 if (full_length < equals)
146 {
147 return 0;
148 }
149 return full_length - equals;
150}
151
152size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOutLength)
153{
154 if (maxOutLength == 0 || inLength < 2) {
155 return 0;
156 }
157 const size_t realLength = inLength - size_t(in[inLength - 1] == '=') - size_t(in[inLength - 2] == '=');
158 size_t dst_offset = 0;
159 int val = 0, valb = -8;
160 for (size_t src_offset = 0; src_offset < realLength; ++src_offset)
161 {
162 const uint8_t table_value = Util::DecodeBase64(ch: in[src_offset]);
163 if (table_value == 255)
164 {
165 return 0;
166 }
167 val = (val << 6) + table_value;
168 valb += 6;
169 if (valb >= 0)
170 {
171 out[dst_offset++] = static_cast<uint8_t>((val >> valb) & 0xFF);
172 valb -= 8;
173 val &= 0xFFF;
174 }
175 }
176 return dst_offset;
177}
178
179static const char to_base64_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
180char EncodeBase64(char byte)
181{
182 return to_base64_string[(size_t)byte];
183}
184
185/** Encodes a block of 4 bytes to base64 encoding
186*
187* @param bytes Bytes to encode.
188* @param out_string String to write encoded values to.
189* @param string_pos Position in out_string.*/
190void EncodeByteBlock(const char* bytes, std::string& out_string, size_t string_pos)
191{
192 char b0 = (bytes[0] & 0xFC) >> 2;
193 char b1 = (bytes[0] & 0x03) << 4 | ((bytes[1] & 0xF0) >> 4);
194 char b2 = (bytes[1] & 0x0F) << 2 | ((bytes[2] & 0xC0) >> 6);
195 char b3 = (bytes[2] & 0x3F);
196
197 out_string[string_pos + 0] = EncodeBase64(byte: b0);
198 out_string[string_pos + 1] = EncodeBase64(byte: b1);
199 out_string[string_pos + 2] = EncodeBase64(byte: b2);
200 out_string[string_pos + 3] = EncodeBase64(byte: b3);
201}
202
203std::string EncodeBase64(const char* data, size_t length)
204{
205 // calculate extra bytes needed to get a multiple of 3
206 size_t extraBytes = 3 - length % 3;
207
208 // number of base64 bytes
209 size_t encodedBytes = 4 * (length + extraBytes) / 3;
210
211 std::string encoded_string(encodedBytes, '=');
212
213 // read blocks of 3 bytes
214 for (size_t ib3 = 0; ib3 < length / 3; ib3++)
215 {
216 const size_t iByte = ib3 * 3;
217 const size_t iEncodedByte = ib3 * 4;
218 const char* currData = &data[iByte];
219
220 EncodeByteBlock(bytes: currData, out_string&: encoded_string, string_pos: iEncodedByte);
221 }
222
223 // if size of data is not a multiple of 3, also encode the final bytes (and add zeros where needed)
224 if (extraBytes > 0)
225 {
226 char finalBytes[4] = { 0,0,0,0 };
227 memcpy(dest: &finalBytes[0], src: &data[length - length % 3], n: length % 3);
228
229 const size_t iEncodedByte = encodedBytes - 4;
230 EncodeByteBlock(bytes: &finalBytes[0], out_string&: encoded_string, string_pos: iEncodedByte);
231
232 // add '=' at the end
233 for (size_t i = 0; i < 4 * extraBytes / 3; i++)
234 encoded_string[encodedBytes - i - 1] = '=';
235 }
236 return encoded_string;
237}
238
239} // !Util
240} // !FBX
241} // !Assimp
242
243#endif
244

source code of qt3d/src/3rdparty/assimp/src/code/FBX/FBXUtil.cpp