text: /*
   * Original work Copyright 2009 - 2010 Kevin Ackley (kackley@gwi.net)
   * Modified work Copyright 2018 - 2020 Andy Maloney <asmaloney@gmail.com>
   *
   * Permission is hereby granted, free of charge, to any person or organization
   * obtaining a copy of the software and accompanying documentation covered by
   * this license (the "Software") to use, reproduce, display, distribute,
   * execute, and transmit the Software, and to prepare derivative works of the
   * Software, and to permit third-parties to whom the Software is furnished to
   * do so, all subject to the following:
   *
   * The copyright notices in the Software and this entire statement, including
   * the above license grant, this restriction and the following disclaimer,
   * must be included in all copies of the Software, in whole or in part, and
   * all derivative works of the Software, unless such copies or derivative
   * works are solely in the form of machine-executable object code generated by
   * a source language processor.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
   * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
   * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
   * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   * DEALINGS IN THE SOFTWARE.
   */
  
  #pragma once
  
  #include <iomanip>
  #include <iostream>
  #include <set>
  #include <sstream>
  #include <string>
  #include <vector>
  
  // Define the following symbol adds some functions to the API for implementation
  // purposes. These functions are not available to a normal API user.
  #define E57_INTERNAL_IMPLEMENTATION_ENABLE 1
  #include "E57Format.h"
  
  #ifdef _MSC_VER
  // Disable MSVC warning: warning C4224: nonstandard extension used : formal
  // parameter 'locale' was previously defined as a type
  #pragma warning( disable : 4224 )
  #endif
  
  namespace e57
  {
  //!!! inline these rather than macros?
  #define E57_EXCEPTION1( ecode )                                                                                        \
     ( E57Exception( ( ecode ), ustring(), __FILE__, __LINE__, static_cast<const char *>( __FUNCTION__ ) ) )
  #define E57_EXCEPTION2( ecode, context )                                                                               \
     ( E57Exception( ( ecode ), ( context ), __FILE__, __LINE__, static_cast<const char *>( __FUNCTION__ ) ) )
  
     /// Create whitespace of given length, for indenting printouts in dump()
     /// functions
     inline std::string space( size_t n )
     {
        return ( std::string( n, ' ' ) );
     }
  
     /// Convert number to decimal, hexadecimal, and binary strings  (Note hex
     /// strings don't have leading zeros).
     template <class T> std::string toString( T x )
     {
        std::ostringstream ss;
        ss << x;
        return ( ss.str() );
     }
  
     inline std::string hexString( uint64_t x )
     {
        std::ostringstream ss;
        ss << "0x" << std::hex << std::setw( 16 ) << std::setfill( '0' ) << x;
        return ( ss.str() );
     }
     inline std::string hexString( uint32_t x )
     {
        std::ostringstream ss;
        ss << "0x" << std::hex << std::setw( 8 ) << std::setfill( '0' ) << x;
        return ( ss.str() );
     }
     inline std::string hexString( uint16_t x )
     {
        std::ostringstream ss;
        ss << "0x" << std::hex << std::setw( 4 ) << std::setfill( '0' ) << x;
        return ( ss.str() );
     }
     inline std::string hexString( uint8_t x )
     {
        std::ostringstream ss;
        ss << "0x" << std::hex << std::setw( 2 ) << std::setfill( '0' ) << static_cast<unsigned>( x );
        return ( ss.str() );
     }
     inline std::string binaryString( uint64_t x )
     {
        std::ostringstream ss;
        for ( int i = 63; i >= 0; i-- )
        {
           ss << ( ( x & ( 1LL << i ) ) ? 1 : 0 );
           if ( i > 0 && i % 8 == 0 )
              ss << " ";
        }
        return ( ss.str() );
     }
     inline std::string binaryString( uint32_t x )
     {
        std::ostringstream ss;
        for ( int i = 31; i >= 0; i-- )
        {
           ss << ( ( x & ( 1LL << i ) ) ? 1 : 0 );
           if ( i > 0 && i % 8 == 0 )
              ss << " ";
        }
        return ( ss.str() );
     }
     inline std::string binaryString( uint16_t x )
     {
        std::ostringstream ss;
        for ( int i = 15; i >= 0; i-- )
        {
           ss << ( ( x & ( 1LL << i ) ) ? 1 : 0 );
           if ( i > 0 && i % 8 == 0 )
              ss << " ";
        }
        return ( ss.str() );
     }
     inline std::string binaryString( uint8_t x )
     {
        std::ostringstream ss;
        for ( int i = 7; i >= 0; i-- )
        {
           ss << ( ( x & ( 1LL << i ) ) ? 1 : 0 );
           if ( i > 0 && i % 8 == 0 )
              ss << " ";
        }
        return ( ss.str() );
     }
     inline std::string hexString( int64_t x )
     {
        return ( hexString( static_cast<uint64_t>( x ) ) );
     }
     inline std::string hexString( int32_t x )
     {
        return ( hexString( static_cast<uint32_t>( x ) ) );
     }
     inline std::string hexString( int16_t x )
     {
        return ( hexString( static_cast<uint16_t>( x ) ) );
     }
     inline std::string hexString( int8_t x )
     {
        return ( hexString( static_cast<uint8_t>( x ) ) );
     }
     inline std::string binaryString( int64_t x )
     {
        return ( binaryString( static_cast<uint64_t>( x ) ) );
     }
     inline std::string binaryString( int32_t x )
     {
        return ( binaryString( static_cast<uint32_t>( x ) ) );
     }
     inline std::string binaryString( int16_t x )
     {
        return ( binaryString( static_cast<uint16_t>( x ) ) );
     }
     inline std::string binaryString( int8_t x )
     {
        return ( binaryString( static_cast<uint8_t>( x ) ) );
     }
  
     using ImageFileImplSharedPtr = std::shared_ptr<class ImageFileImpl>;
     using ImageFileImplWeakPtr = std::weak_ptr<class ImageFileImpl>;
     using NodeImplSharedPtr = std::shared_ptr<class NodeImpl>;
     using NodeImplWeakPtr = std::weak_ptr<class NodeImpl>;
  
     using StringList = std::vector<std::string>;
     using StringSet = std::set<std::string>;
  
     //! generates a new random GUID
     std::string generateRandomGUID();
  }
  