mirror of
				https://github.com/RetroDECK/Duckstation.git
				synced 2025-04-10 19:15:14 +00:00 
			
		
		
		
	
		
			
	
	
		
			125 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			125 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								#ifndef _C4_BASE64_HPP_
							 | 
						||
| 
								 | 
							
								#define _C4_BASE64_HPP_
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** @file base64.hpp encoding/decoding for base64.
							 | 
						||
| 
								 | 
							
								 * @see https://en.wikipedia.org/wiki/Base64
							 | 
						||
| 
								 | 
							
								 * @see https://www.base64encode.org/
							 | 
						||
| 
								 | 
							
								 * */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "c4/charconv.hpp"
							 | 
						||
| 
								 | 
							
								#include "c4/blob.hpp"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace c4 {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** check that the given buffer is a valid base64 encoding
							 | 
						||
| 
								 | 
							
								 * @see https://en.wikipedia.org/wiki/Base64 */
							 | 
						||
| 
								 | 
							
								C4CORE_EXPORT bool base64_valid(csubstr encoded);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** base64-encode binary data.
							 | 
						||
| 
								 | 
							
								 * @param encoded [out] output buffer for encoded data
							 | 
						||
| 
								 | 
							
								 * @param data [in] the input buffer with the binary data
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return the number of bytes needed to return the output (ie the
							 | 
						||
| 
								 | 
							
								 * required size for @p encoded). No writes occur beyond the end of
							 | 
						||
| 
								 | 
							
								 * the output buffer, so it is safe to do a speculative call where the
							 | 
						||
| 
								 | 
							
								 * encoded buffer is empty, or maybe too small. The caller should
							 | 
						||
| 
								 | 
							
								 * ensure that the returned size is smaller than the size of the
							 | 
						||
| 
								 | 
							
								 * encoded buffer.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @note the result depends on endianness. If transfer between
							 | 
						||
| 
								 | 
							
								 * little/big endian systems is desired, the caller should normalize
							 | 
						||
| 
								 | 
							
								 * @p data before encoding.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @see https://en.wikipedia.org/wiki/Base64 */
							 | 
						||
| 
								 | 
							
								C4CORE_EXPORT size_t base64_encode(substr encoded, cblob data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** decode the base64 encoding in the given buffer
							 | 
						||
| 
								 | 
							
								 * @param encoded [in] the encoded base64
							 | 
						||
| 
								 | 
							
								 * @param data [out] the output buffer
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @return the number of bytes needed to return the output (ie the
							 | 
						||
| 
								 | 
							
								 * required size for @p data). No writes occur beyond the end of the
							 | 
						||
| 
								 | 
							
								 * output buffer, so it is safe to do a speculative call where the
							 | 
						||
| 
								 | 
							
								 * data buffer is empty, or maybe too small. The caller should ensure
							 | 
						||
| 
								 | 
							
								 * that the returned size is smaller than the size of the data buffer.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @note the result depends on endianness. If transfer between
							 | 
						||
| 
								 | 
							
								 * little/big endian systems is desired, the caller should normalize
							 | 
						||
| 
								 | 
							
								 * @p data after decoding.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @see https://en.wikipedia.org/wiki/Base64 */
							 | 
						||
| 
								 | 
							
								C4CORE_EXPORT size_t base64_decode(csubstr encoded, blob data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace fmt {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<typename CharOrConstChar>
							 | 
						||
| 
								 | 
							
								struct base64_wrapper_
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    blob_<CharOrConstChar> data;
							 | 
						||
| 
								 | 
							
								    base64_wrapper_() : data() {}
							 | 
						||
| 
								 | 
							
								    base64_wrapper_(blob_<CharOrConstChar> blob) : data(blob) {}
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								/** a tag type to mark a payload as base64-encoded */
							 | 
						||
| 
								 | 
							
								using const_base64_wrapper = base64_wrapper_<cbyte>;
							 | 
						||
| 
								 | 
							
								/** a tag type to mark a payload to be encoded as base64 */
							 | 
						||
| 
								 | 
							
								using base64_wrapper = base64_wrapper_<byte>;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** mark a variable to be written in base64 format */
							 | 
						||
| 
								 | 
							
								template<class ...Args>
							 | 
						||
| 
								 | 
							
								C4_ALWAYS_INLINE const_base64_wrapper cbase64(Args const& C4_RESTRICT ...args)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return const_base64_wrapper(cblob(args...));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								/** mark a csubstr to be written in base64 format */
							 | 
						||
| 
								 | 
							
								C4_ALWAYS_INLINE const_base64_wrapper cbase64(csubstr s)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return const_base64_wrapper(cblob(s.str, s.len));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								/** mark a variable to be written in base64 format */
							 | 
						||
| 
								 | 
							
								template<class ...Args>
							 | 
						||
| 
								 | 
							
								C4_ALWAYS_INLINE const_base64_wrapper base64(Args const& C4_RESTRICT ...args)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return const_base64_wrapper(cblob(args...));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								/** mark a csubstr to be written in base64 format */
							 | 
						||
| 
								 | 
							
								C4_ALWAYS_INLINE const_base64_wrapper base64(csubstr s)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return const_base64_wrapper(cblob(s.str, s.len));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** mark a variable to be read in base64 format */
							 | 
						||
| 
								 | 
							
								template<class ...Args>
							 | 
						||
| 
								 | 
							
								C4_ALWAYS_INLINE base64_wrapper base64(Args &... args)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return base64_wrapper(blob(args...));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								/** mark a variable to be read in base64 format */
							 | 
						||
| 
								 | 
							
								C4_ALWAYS_INLINE base64_wrapper base64(substr s)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return base64_wrapper(blob(s.str, s.len));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // namespace fmt
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** write a variable in base64 format */
							 | 
						||
| 
								 | 
							
								inline size_t to_chars(substr buf, fmt::const_base64_wrapper b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return base64_encode(buf, b.data);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** read a variable in base64 format */
							 | 
						||
| 
								 | 
							
								inline size_t from_chars(csubstr buf, fmt::base64_wrapper *b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return base64_decode(buf, b->data);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // namespace c4
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* _C4_BASE64_HPP_ */
							 |