Why I Don't Use Else When Programming

This may sound crazy but I really don’t use the else keyword in my programming anymore. When I do end up using else it usually leads to worse code than if I purposely avoided it. In this video I explain exactly why that is.

⏱️ Timestamps:

  • 00:00 - Introduction
  • 01:00 - Guard Clauses
  • 04:03 - Single Return Is Bad
  • 05:43 - Extract Functions

#developer #programming

What is GEEK

Buddha Community

Why I Don't Use Else When Programming

It’s an idea to think about, in many cases may leave the most readable code.

Cyril  Parisian

Cyril Parisian

1661092140

Udlib: Header-only Series Of C++20 Usermode Utilities

Overview and roadmap

FeatureAvailability
xorstr
stack strings
rot string
signature scans
segment wrappers
module wrappers
shellcode wrappers
constexpr emittion✅ (clang only)
constexpr fnv-1a hashing
lazy importer🟦 (untested)
disassembler engine
memory scanning utility

ud.hpp

#pragma once
#include <optional>
#include <string>
#include <vector>
#include <array>
#include <algorithm>
#include <string_view>
#include <fstream>
#include <unordered_map>

#include <Windows.h>
#include <winternl.h>

#if defined(_MSC_VER)
#define UD_FORCEINLINE __forceinline
#pragma warning( push )
#pragma warning( disable : 4244 4083 )
#else
#define UD_FORCEINLINE __attribute__( ( always_inline ) )
#endif

#define ud_encode_c( str ) ud::rot::decode( ud::rot::rot_t<str>{ } ).data
#define ud_encode( str ) std::string_view( ud::rot::decode( ud::rot::rot_t<str>{ } ) )

#define ud_xorstr_c( str ) ud::xorstr::decrypt( ud::xorstr::xorstr_t< str, __COUNTER__ + 1 ^ 0x90 >{ } ).data
#define ud_xorstr( str ) std::string_view{ ud::xorstr::decrypt( ud::xorstr::xorstr_t< str, __COUNTER__ + 1 ^ 0x90 >{ } ) }

#define ud_stack_str( str ) ud::details::comp_string_t{ str }.data

#define ud_import( mod, func )	reinterpret_cast< decltype( &func ) >( ud::lazy_import::find_module_export< TEXT( mod ), #func >( ) )
#define ud_first_import( func ) reinterpret_cast< decltype( &func ) >( ud::lazy_import::find_first_export< #func >( ) )

// preprocessed settings due to MSVC (not clang or gcc) throwing errors even in `if constexpr` bodies
#define UD_USE_SEH false

namespace ud
{
    namespace details
    {
        struct LDR_DATA_TABLE_ENTRY32
        {
            LIST_ENTRY in_load_order_links;

            std::uint8_t pad[ 16 ];
            std::uintptr_t dll_base;
            std::uintptr_t entry_point;
            std::size_t size_of_image;

            UNICODE_STRING full_name;
            UNICODE_STRING base_name;
        };

        struct LDR_DATA_TABLE_ENTRY64
        {
            LIST_ENTRY in_load_order_links;
            LIST_ENTRY dummy_0;
            LIST_ENTRY dummy_1;

            std::uintptr_t dll_base;
            std::uintptr_t entry_point;
            union {
                unsigned long size_of_image;
                const char* _dummy;
            };

            UNICODE_STRING full_name;
            UNICODE_STRING base_name;
        };

#if defined( _M_X64 )
        using LDR_DATA_TABLE_ENTRY = LDR_DATA_TABLE_ENTRY64;
#else
        using LDR_DATA_TABLE_ENTRY = LDR_DATA_TABLE_ENTRY32;
#endif

        template < std::size_t sz >
        struct comp_string_t
        {
            std::size_t size = sz;
            char data[ sz ]{ };

            comp_string_t( ) = default;
            consteval explicit comp_string_t( const char( &str )[ sz ] )
            {
                std::copy_n( str, sz, data );
            }

            constexpr explicit operator std::string_view( ) const
            {
                return { data, size };
            }
        };

        template < std::size_t sz >
        struct wcomp_string_t
        {
            std::size_t size = sz;
            wchar_t data[ sz ]{ };

            wcomp_string_t( ) = default;
            consteval explicit wcomp_string_t( const wchar_t( &str )[ sz ] )
            {
                std::copy_n( str, sz, data );
            }

            constexpr explicit operator std::wstring_view( ) const
            {
                return { data, size };
            }
        };

        inline constexpr std::uint64_t multiplier = 0x5bd1e995;
        inline consteval std::uint64_t get_seed( )
        {
            constexpr auto time_str = __TIME__;
            constexpr auto time_len = sizeof( __TIME__ ) - 1;

            constexpr auto time_int = [ ] ( const char* const str, const std::size_t len )
            {
                auto res = 0ull;
                for ( auto i = 0u; i < len; ++i )
                    if ( str[ i ] >= '0' && str[ i ] <= '9' )
                        res = res * 10 + str[ i ] - '0';

                return res;
            }( time_str, time_len );

            return time_int;
        }

        template < auto v >
        struct constant_t
        {
            enum : decltype( v )
            {
                value = v
            };
        };

        template < auto v >
        inline constexpr auto constant_v = constant_t< v >::value;

#undef max
#undef min

        template < std::uint32_t seq >
        consteval std::uint64_t recursive_random( )
        {
            constexpr auto seed = get_seed( );
            constexpr auto mask = std::numeric_limits< std::uint64_t >::max( );

            constexpr auto x = ( ( seq * multiplier ) + seed ) & mask;
            constexpr auto x_prime = ( x >> 0x10 ) | ( x << 0x10 );

            return constant_v< x_prime >;
        }
    }

    namespace rot
    {
        template < details::comp_string_t str >
        struct rot_t
        {
            char rotted[ str.size ];

            [[nodiscard]] consteval const char* encoded( ) const
            {
                return rotted;
            }

            consteval rot_t( )
            {
                for ( auto i = 0u; i < str.size; ++i )
                {
                    const auto c = str.data[ i ];
                    const auto set = c >= 'A' && c <= 'Z' ? 'A' : c >= 'a' && c <= 'z' ? 'a' : c;

                    if ( set == 'a' || set == 'A' )
                        rotted[ i ] = ( c - set - 13 + 26 ) % 26 + set;

                    else
                        rotted[ i ] = c;
                }
            }
        };

        template < details::comp_string_t str >
        UD_FORCEINLINE details::comp_string_t< str.size > decode( rot_t< str > encoded )
        {
            details::comp_string_t< str.size > result{ };

            for ( auto i = 0u; i < str.size; ++i )
            {
                const auto c = encoded.rotted[ i ];
                const auto set = c >= 'A' && c <= 'Z' ? 'A' : c >= 'a' && c <= 'z' ? 'a' : c;

                if ( set == 'a' || set == 'A' )
                    result.data[ i ] = ( c - set - 13 + 26 ) % 26 + set;

                else
                    result.data[ i ] = c;
            }

            return result;
        }
    }

    namespace fnv
    {
        inline constexpr std::uint32_t fnv_1a( const char* const str, const std::size_t size )
        {
            constexpr auto prime = 16777619u;

            std::uint32_t hash = 2166136261;

            for ( auto i = 0u; i < size; ++i )
            {
                hash ^= str[ i ];
                hash *= prime;
            }

            return hash;
        }

        inline constexpr std::uint32_t fnv_1a( const wchar_t* const str, const std::size_t size )
        {
            constexpr auto prime = 16777619u;

            std::uint32_t hash = 2166136261;

            for ( auto i = 0u; i < size; ++i )
            {
                hash ^= static_cast< char >( str[ i ] );
                hash *= prime;
            }

            return hash;
        }

        inline constexpr std::uint32_t fnv_1a( const std::wstring_view str )
        {
            return fnv_1a( str.data( ), str.size( ) );
        }

        inline constexpr std::uint32_t fnv_1a( const std::string_view str )
        {
            return fnv_1a( str.data( ), str.size( ) );
        }

        template < details::comp_string_t str >
        consteval std::uint32_t fnv_1a( )
        {
            return fnv_1a( str.data, str.size );
        }

        template < details::wcomp_string_t str >
        consteval std::uint32_t fnv_1a( )
        {
            return fnv_1a( str.data, str.size );
        }
    }

    namespace xorstr
    {
        template < details::comp_string_t str, std::uint32_t key_multiplier >
        struct xorstr_t
        {
            char xored[ str.size ];

            [[nodiscard]] consteval std::uint64_t xor_key( ) const
            {
                return details::recursive_random< key_multiplier >( );
            }

            consteval xorstr_t( )
            {
                for ( auto i = 0u; i < str.size; ++i )
                    xored[ i ] = str.data[ i ] ^ xor_key( );
            }
        };

        template < details::comp_string_t str, std::uint32_t key_multiplier >
        UD_FORCEINLINE details::comp_string_t< str.size > decrypt( xorstr_t< str, key_multiplier > enc )
        {
            details::comp_string_t< str.size > result{ };

            for ( auto i = 0u; i < str.size; ++i )
            {
                const auto c = enc.xored[ i ];

                result.data[ i ] = c ^ enc.xor_key( );
            }

            return result;
        }
    }

    namespace lazy_import
    {
        UD_FORCEINLINE std::uintptr_t get_module_handle( const std::uint64_t hash )
        {
#if defined( _M_X64 )
            const auto peb = reinterpret_cast< const PEB* >( __readgsqword( 0x60 ) );
#else
            const auto peb = reinterpret_cast< const PEB* >( __readfsdword( 0x30 ) );
#endif

            const auto modules = reinterpret_cast< const LIST_ENTRY* >( peb->Ldr->InMemoryOrderModuleList.Flink );

            for ( auto i = modules->Flink; i != modules; i = i->Flink )
            {
                const auto entry = reinterpret_cast< const details::LDR_DATA_TABLE_ENTRY* >( i );

                const auto name = entry->base_name.Buffer;
                const auto len = entry->base_name.Length;

                if ( fnv::fnv_1a( static_cast< const wchar_t* >( name ), len ) == hash )
                    return entry->dll_base;
            }

            return 0;
        }

        UD_FORCEINLINE void* find_primitive_export( const std::uint64_t dll_hash, const std::uint64_t function_hash )
        {
            const auto module = get_module_handle( dll_hash );

            if ( !module )
                return nullptr;

            const auto dos = reinterpret_cast< const IMAGE_DOS_HEADER* >( module );
            const auto nt = reinterpret_cast< const IMAGE_NT_HEADERS* >( module + dos->e_lfanew );

            const auto exports = reinterpret_cast< const IMAGE_EXPORT_DIRECTORY* >( module + nt->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress );

            const auto names = reinterpret_cast< const std::uint32_t* >( module + exports->AddressOfNames );
            const auto ordinals = reinterpret_cast< const std::uint16_t* >( module + exports->AddressOfNameOrdinals );
            const auto functions = reinterpret_cast< const std::uint32_t* >( module + exports->AddressOfFunctions );

            for ( auto i = 0u; i < exports->NumberOfNames; ++i )
            {
                const auto name = reinterpret_cast< const char* >( module + names[ i ] );
                std::size_t len = 0;

                for ( ; name[ len ]; ++len );

                if ( fnv::fnv_1a( name, len ) == function_hash )
                    return reinterpret_cast< void* >( module + functions[ ordinals[ i ] ] );
            }

            return nullptr;
        }

        template < details::wcomp_string_t dll_name, details::comp_string_t function_name >
        UD_FORCEINLINE void* find_module_export( )
        {
            return find_primitive_export( fnv::fnv_1a< dll_name >( ), fnv::fnv_1a< function_name >( ) );
        }

        template < details::comp_string_t function_name >
        UD_FORCEINLINE void* find_first_export( )
        {
            constexpr auto function_hash = fnv::fnv_1a< function_name >( );

#if defined( _M_X64 )
            const auto peb = reinterpret_cast< const PEB* >( __readgsqword( 0x60 ) );
#else
            const auto peb = reinterpret_cast< const PEB* >( __readfsdword( 0x30 ) );
#endif

            const auto modules = reinterpret_cast< const LIST_ENTRY* >( peb->Ldr->InMemoryOrderModuleList.Flink );


            for ( auto i = modules->Flink; i != modules; i = i->Flink )
            {
                const auto entry = reinterpret_cast< const details::LDR_DATA_TABLE_ENTRY* >( i );

                const auto name = entry->base_name.Buffer;
                std::size_t len = 0;

                if ( !name )
                    continue;

                for ( ; name[ len ]; ++len );

                if ( const auto exp = find_primitive_export( fnv::fnv_1a( name, len ), function_hash ) )
                    return exp;
            }

            return nullptr;
        }
    }

    template < typename ty = std::uintptr_t >
    std::optional< ty > find_pattern_primitive( const std::uintptr_t start, const std::uintptr_t end, const std::string_view pattern )
    {
        std::vector< std::pair< bool, std::uint8_t > > bytes;

        for ( auto it = pattern.begin( ); it != pattern.end( ); ++it )
        {
            if ( *it == ' ' )
                continue;

            else if ( *it == '?' )
            {
                if ( it + 1 < pattern.end( ) && *( it + 1 ) == '?' )
                {
                    bytes.push_back( { true, 0x00 } );
                    ++it;
                }

                else
                    bytes.push_back( { false, 0x00 } );
            }

            else
            {
                if ( it + 1 == pattern.end( ) )
                    break;

                const auto get_byte = [ ] ( const std::string& x ) -> std::uint8_t
                {
                    return static_cast< std::uint8_t >( std::stoul( x, nullptr, 16 ) );
                };

                bytes.emplace_back( false, get_byte( std::string( it - 1, ( ++it ) + 1 ) ) );
            }
        }

        for ( auto i = reinterpret_cast< const std::uint8_t* >( start ); i < reinterpret_cast< const std::uint8_t* >( end ); )
        {
            auto found = true;
            for ( const auto& [ is_wildcard, byte ] : bytes )
            {
                ++i;

                if ( is_wildcard )
                    continue;

                if ( *i != byte )
                {
                    found = false;
                    break;
                }
            }

            if ( found )
                return ty( i - bytes.size( ) + 1 );
        }

        return std::nullopt;
    }

    struct segment_t
    {
        std::string_view name = "";
        std::uintptr_t start{ }, end{ };
        std::size_t size{ };

        template < typename ty = std::uintptr_t >
        std::optional< ty > find_pattern( const std::string_view pattern ) const
        {
            return find_pattern_primitive< ty >( start, end, pattern );
        }

        explicit segment_t( const std::string_view segment_name )
        {
            init( GetModuleHandle( nullptr ), segment_name );
        }

        segment_t( const void* const module, const std::string_view segment_name )
        {
            init( module, segment_name );
        }

        segment_t( const void* const handle, const IMAGE_SECTION_HEADER* section )
        {
            init( handle, section );
        }

    private:
        void init( const void* const handle, const IMAGE_SECTION_HEADER* section )
        {
            name = std::string_view( reinterpret_cast< const char* >( section->Name ), 8 );
            start = reinterpret_cast< std::uintptr_t >( handle ) + section->VirtualAddress;
            end = start + section->Misc.VirtualSize;
            size = section->Misc.VirtualSize;
        }

        void init( const void* const handle, const std::string_view segment_name )
        {
            const auto dos = reinterpret_cast< const IMAGE_DOS_HEADER* >( handle );
            const auto nt = reinterpret_cast< const IMAGE_NT_HEADERS* >( reinterpret_cast< const std::uint8_t* >( handle ) + dos->e_lfanew );

            const auto section = reinterpret_cast< const IMAGE_SECTION_HEADER* >( reinterpret_cast< const std::uint8_t* >( &nt->OptionalHeader ) + nt->FileHeader.SizeOfOptionalHeader );

            for ( auto i = 0u; i < nt->FileHeader.NumberOfSections; ++i )
            {
                if ( std::string_view( reinterpret_cast< const char* >( section[ i ].Name ), 8 ).find( segment_name ) != std::string_view::npos )
                {
                    start = reinterpret_cast< std::uintptr_t >( handle ) + section[ i ].VirtualAddress;
                    end = start + section[ i ].Misc.VirtualSize;
                    size = section[ i ].Misc.VirtualSize;
                    name = segment_name;
                    return;
                }
            }
        }
    };

#pragma code_seg( push, ".text" )
    template < auto... bytes>
    struct shellcode_t
    {
        static constexpr std::size_t size = sizeof...( bytes );
        __declspec( allocate( ".text" ) ) static constexpr std::uint8_t data[ ]{ bytes... };
    };
#pragma code_seg( pop )

    template < typename ty, auto... bytes >
    constexpr ty make_shellcode( )
    {
        return reinterpret_cast< const ty >( &shellcode_t< bytes... >::data );
    }

    template < std::uint8_t... bytes >
    UD_FORCEINLINE constexpr void emit( )
    {
#if defined( __clang__ ) || defined( __GNUC__ )
        constexpr std::uint8_t data[ ]{ bytes... };

        for ( auto i = 0u; i < sizeof...( bytes ); ++i )
            __asm volatile( ".byte %c0\t\n" :: "i" ( data[ i ] ) );
#endif
    }

    template < std::size_t size, std::uint32_t seed = __COUNTER__ + 0x69, std::size_t count = 0 >
    UD_FORCEINLINE constexpr void emit_random( )
    {
        if constexpr ( count < size )
        {
            constexpr auto random = details::recursive_random< seed >( );
            emit< static_cast< std::uint8_t >( random ) >( );
            emit_random< size, static_cast< std::uint32_t >( random )* seed, count + 1 >( );
        }
    }

    inline bool is_valid_page( const void* const data, const std::uint32_t flags = PAGE_READWRITE )
    {
        MEMORY_BASIC_INFORMATION mbi{ };

        if ( !VirtualQuery( data, &mbi, sizeof( mbi ) ) )
            return false;

        return mbi.Protect & flags;
    }

    struct export_t
    {
        std::string_view name;
        std::uint16_t ordinal{ };
        std::uintptr_t address{ };
    };

    struct module_t
    {
        std::string name;
        std::uintptr_t start, end;

        segment_t operator[ ]( const std::string_view segment_name ) const
        {
            return { reinterpret_cast< const void* >( start ), segment_name };
        }

        std::vector< export_t > get_exports( ) const
        {
            const auto dos = reinterpret_cast< const IMAGE_DOS_HEADER* >( start );
            const auto nt = reinterpret_cast< const IMAGE_NT_HEADERS* >( start + dos->e_lfanew );

            const auto directory_header = nt->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
            if ( !directory_header.VirtualAddress )
                return { };

            const auto export_dir = reinterpret_cast< const IMAGE_EXPORT_DIRECTORY* >( start + directory_header.VirtualAddress );
            const auto name_table = reinterpret_cast< const std::uint32_t* >( start + export_dir->AddressOfNames );
            const auto ord_table = reinterpret_cast< const std::uint16_t* >( start + export_dir->AddressOfNameOrdinals );
            const auto addr_table = reinterpret_cast< const std::uint32_t* >( start + export_dir->AddressOfFunctions );

            std::vector< export_t > exports( export_dir->NumberOfNames );

            for ( auto i = 0u; i < export_dir->NumberOfNames; ++i )
            {
                const auto name_str = reinterpret_cast< const char* >( start + name_table[ i ] );
                const auto ord = ord_table[ i ];
                const auto addr = start + addr_table[ ord ];

                exports[ i ] = { name_str, ord, addr };
            }

            return exports;
        }

        [[nodiscard]] std::vector< segment_t > get_segments( ) const
        {
            const auto dos = reinterpret_cast< const IMAGE_DOS_HEADER* >( start );
            const auto nt = reinterpret_cast< const IMAGE_NT_HEADERS* >( start + dos->e_lfanew );

            const auto section = reinterpret_cast< const IMAGE_SECTION_HEADER* >( reinterpret_cast< const std::uint8_t* >( &nt->OptionalHeader ) + nt->FileHeader.SizeOfOptionalHeader );

            std::vector< segment_t > segments;
            segments.reserve( nt->FileHeader.NumberOfSections );

            for ( auto i = 0u; i < nt->FileHeader.NumberOfSections; ++i )
            {
                const segment_t seg( dos, &section[ i ] );
                segments.push_back( seg );
            }

            return segments;
        }

        [[nodiscard]] std::vector< export_t > get_imports( ) const
        {
            const auto dos = reinterpret_cast< const IMAGE_DOS_HEADER* >( start );
            const auto nt = reinterpret_cast< const IMAGE_NT_HEADERS* >( start + dos->e_lfanew );

            const auto directory_header = &nt->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];
            if ( !directory_header->VirtualAddress )
                return { };

            const auto import_dir = reinterpret_cast< const IMAGE_IMPORT_DESCRIPTOR* >( start + directory_header->VirtualAddress );
            std::vector< export_t > imports;

            for ( auto i = 0u;; ++i )
            {
                if ( !import_dir[ i ].OriginalFirstThunk )
                    break;

                const auto directory = &import_dir[ i ];

                const auto name_table = reinterpret_cast< const std::uint32_t* >( start + directory->OriginalFirstThunk );
                const auto addr_table = reinterpret_cast< const std::uint32_t* >( start + directory->FirstThunk );

                for ( auto j = 0u;; ++j )
                {
                    if ( !addr_table[ j ] )
                        break;

                    if ( !name_table[ j ] )
                        continue;

                    std::string_view name_str;

                    constexpr auto name_alignment = 2;

                    const auto addr = &addr_table[ j ];
                    const auto name_ptr = reinterpret_cast< const char* >( start + name_table[ j ] ) + name_alignment;

#if UD_USE_SEH
                    // using SEH here is not a very good solution
					// however, it's faster than querying that page protection to see if it's readable
					__try
					{
						name = name_ptr;
					}
					__except ( EXCEPTION_EXECUTE_HANDLER )
					{
						name = "";
					}
#else
                    // runtime overhead of ~3us compared to SEH on single calls
                    // on bulk calls it can go up to ~300-500us
                    name_str = is_valid_page( name_ptr, PAGE_READONLY ) ? name_ptr : "";
#endif

                    // emplace_back doesn't allow for implicit conversion, so we have to do it manually
                    imports.push_back( { name_str, static_cast< std::uint16_t >( j ), reinterpret_cast< std::uintptr_t >( addr ) } );
                }
            }

            return imports;
        }

        template < typename ty = std::uintptr_t >
        ty get_address( const std::string_view name ) const
        {
            for ( const auto& export_ : get_exports( ) )
            {
                if ( export_.name.find( name ) != std::string_view::npos )
                    return ty( export_.address );
            }

            return 0;
        }

        template < typename ty = std::uintptr_t >
        std::optional< ty > find_pattern( const std::string_view pattern ) const
        {
            return find_pattern_primitive< ty >( start, end, pattern );
        }

        [[nodiscard]] std::vector< std::string_view > get_strings( const std::size_t minimum_size = 0 ) const
        {
            std::vector< std::string_view > result;

            const auto rdata = ( *this )[ ".rdata" ];

            if ( !rdata.size )
                return { };

            const auto start = reinterpret_cast< const std::uint8_t* >( rdata.start );
            const auto end = reinterpret_cast< const std::uint8_t* >( rdata.end );

            for ( auto i = start; i < end; ++i )
            {
                if ( *i == 0 || *i > 127 )
                    continue;

                const auto str = reinterpret_cast< const char* >( i );
                const auto sz = std::strlen( str );

                if ( !sz || sz < minimum_size )
                    continue;

                result.emplace_back( str, sz );
                i += sz;
            }

            return result;
        }

        module_t( )
        {
            init( GetModuleHandle( nullptr ) );
        }

        explicit module_t( void* const handle )
        {
            init( handle );
        }

        explicit module_t( const std::string_view module_name )
        {
            init( GetModuleHandleA( module_name.data( ) ) );
        }

    private:
        void* module;

        void init( void* const handle )
        {
            module = handle;

            const auto dos = reinterpret_cast< const IMAGE_DOS_HEADER* >( handle );
            const auto nt = reinterpret_cast< const IMAGE_NT_HEADERS* >( reinterpret_cast< const std::uint8_t* >( handle ) + dos->e_lfanew );

            start = reinterpret_cast< std::uintptr_t >( handle );
            end = start + nt->OptionalHeader.SizeOfImage;

            char buffer[ MAX_PATH ];
            const auto sz = GetModuleFileNameA( static_cast< HMODULE >( handle ), buffer, MAX_PATH );

            name = sz ? std::string{ buffer, sz } : std::string{ };
        }
    };

    inline std::vector< module_t > get_modules( )
    {
        std::vector< module_t > result;

#if defined( _M_X64 )
        const auto peb = reinterpret_cast< const PEB* >( __readgsqword( 0x60 ) );
#else
        const auto peb = reinterpret_cast< const PEB* >( __readfsdword( 0x30 ) );
#endif

        const auto modules = reinterpret_cast< const LIST_ENTRY* >( peb->Ldr->InMemoryOrderModuleList.Flink );
        for ( auto i = modules->Flink; i != modules; i = i->Flink )
        {
            const auto entry = reinterpret_cast< const LDR_DATA_TABLE_ENTRY* >( i );

            if ( entry->Reserved2[ 0 ] || entry->DllBase )
                result.emplace_back( entry->Reserved2[ 0 ] ? entry->Reserved2[ 0 ] : entry->DllBase );
        }

        return result;
    }

    inline std::optional< module_t > get_module_at_address( const std::uintptr_t address )
    {
        for ( const auto& module : get_modules( ) )
        {
            if ( module.start <= address && address < module.end )
                return module;
        }

        return std::nullopt;
    }

    inline std::optional< export_t > get_export( const std::uintptr_t address )
    {
        for ( const auto& module : get_modules( ) )
        {
            if ( module.start <= address && address < module.end )
            {
                const auto exports = module.get_exports( );
                for ( const auto& export_ : exports )
                {
                    if ( export_.address == address )
                        return export_;
                }
            }
        }

        return std::nullopt;
    }

    template < typename rel_t, typename ty = std::uintptr_t >
    ty calculate_relative( const std::uintptr_t address, const std::uint8_t size, const std::uint8_t offset )
    {
        return ty( address + *reinterpret_cast< rel_t* >( address + offset ) + size );
    }
}

template < std::size_t size >
UD_FORCEINLINE std::ostream& operator<<( std::ostream& os, const ud::details::comp_string_t< size >& str )
{
    return os << std::string_view{ str.data, str.size };
}

#if defined( _MSC_VER )
#pragma warning( pop )
#endif

Author: AmJayden
Source code: https://github.com/AmJayden/udlib

#cpluplus 

Hermann  Frami

Hermann Frami

1651383480

A Simple Wrapper Around Amplify AppSync Simulator

This serverless plugin is a wrapper for amplify-appsync-simulator made for testing AppSync APIs built with serverless-appsync-plugin.

Install

npm install serverless-appsync-simulator
# or
yarn add serverless-appsync-simulator

Usage

This plugin relies on your serverless yml file and on the serverless-offline plugin.

plugins:
  - serverless-dynamodb-local # only if you need dynamodb resolvers and you don't have an external dynamodb
  - serverless-appsync-simulator
  - serverless-offline

Note: Order is important serverless-appsync-simulator must go before serverless-offline

To start the simulator, run the following command:

sls offline start

You should see in the logs something like:

...
Serverless: AppSync endpoint: http://localhost:20002/graphql
Serverless: GraphiQl: http://localhost:20002
...

Configuration

Put options under custom.appsync-simulator in your serverless.yml file

| option | default | description | | ------------------------ | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | | apiKey | 0123456789 | When using API_KEY as authentication type, the key to authenticate to the endpoint. | | port | 20002 | AppSync operations port; if using multiple APIs, the value of this option will be used as a starting point, and each other API will have a port of lastPort + 10 (e.g. 20002, 20012, 20022, etc.) | | wsPort | 20003 | AppSync subscriptions port; if using multiple APIs, the value of this option will be used as a starting point, and each other API will have a port of lastPort + 10 (e.g. 20003, 20013, 20023, etc.) | | location | . (base directory) | Location of the lambda functions handlers. | | refMap | {} | A mapping of resource resolutions for the Ref function | | getAttMap | {} | A mapping of resource resolutions for the GetAtt function | | importValueMap | {} | A mapping of resource resolutions for the ImportValue function | | functions | {} | A mapping of external functions for providing invoke url for external fucntions | | dynamoDb.endpoint | http://localhost:8000 | Dynamodb endpoint. Specify it if you're not using serverless-dynamodb-local. Otherwise, port is taken from dynamodb-local conf | | dynamoDb.region | localhost | Dynamodb region. Specify it if you're connecting to a remote Dynamodb intance. | | dynamoDb.accessKeyId | DEFAULT_ACCESS_KEY | AWS Access Key ID to access DynamoDB | | dynamoDb.secretAccessKey | DEFAULT_SECRET | AWS Secret Key to access DynamoDB | | dynamoDb.sessionToken | DEFAULT_ACCESS_TOKEEN | AWS Session Token to access DynamoDB, only if you have temporary security credentials configured on AWS | | dynamoDb.* | | You can add every configuration accepted by DynamoDB SDK | | rds.dbName | | Name of the database | | rds.dbHost | | Database host | | rds.dbDialect | | Database dialect. Possible values (mysql | postgres) | | rds.dbUsername | | Database username | | rds.dbPassword | | Database password | | rds.dbPort | | Database port | | watch | - *.graphql
- *.vtl | Array of glob patterns to watch for hot-reloading. |

Example:

custom:
  appsync-simulator:
    location: '.webpack/service' # use webpack build directory
    dynamoDb:
      endpoint: 'http://my-custom-dynamo:8000'

Hot-reloading

By default, the simulator will hot-relad when changes to *.graphql or *.vtl files are detected. Changes to *.yml files are not supported (yet? - this is a Serverless Framework limitation). You will need to restart the simulator each time you change yml files.

Hot-reloading relies on watchman. Make sure it is installed on your system.

You can change the files being watched with the watch option, which is then passed to watchman as the match expression.

e.g.

custom:
  appsync-simulator:
    watch:
      - ["match", "handlers/**/*.vtl", "wholename"] # => array is interpreted as the literal match expression
      - "*.graphql"                                 # => string like this is equivalent to `["match", "*.graphql"]`

Or you can opt-out by leaving an empty array or set the option to false

Note: Functions should not require hot-reloading, unless you are using a transpiler or a bundler (such as webpack, babel or typescript), un which case you should delegate hot-reloading to that instead.

Resource CloudFormation functions resolution

This plugin supports some resources resolution from the Ref, Fn::GetAtt and Fn::ImportValue functions in your yaml file. It also supports some other Cfn functions such as Fn::Join, Fb::Sub, etc.

Note: Under the hood, this features relies on the cfn-resolver-lib package. For more info on supported cfn functions, refer to the documentation

Basic usage

You can reference resources in your functions' environment variables (that will be accessible from your lambda functions) or datasource definitions. The plugin will automatically resolve them for you.

provider:
  environment:
    BUCKET_NAME:
      Ref: MyBucket # resolves to `my-bucket-name`

resources:
  Resources:
    MyDbTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: myTable
      ...
    MyBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: my-bucket-name
    ...

# in your appsync config
dataSources:
  - type: AMAZON_DYNAMODB
    name: dynamosource
    config:
      tableName:
        Ref: MyDbTable # resolves to `myTable`

Override (or mock) values

Sometimes, some references cannot be resolved, as they come from an Output from Cloudformation; or you might want to use mocked values in your local environment.

In those cases, you can define (or override) those values using the refMap, getAttMap and importValueMap options.

  • refMap takes a mapping of resource name to value pairs
  • getAttMap takes a mapping of resource name to attribute/values pairs
  • importValueMap takes a mapping of import name to values pairs

Example:

custom:
  appsync-simulator:
    refMap:
      # Override `MyDbTable` resolution from the previous example.
      MyDbTable: 'mock-myTable'
    getAttMap:
      # define ElasticSearchInstance DomainName
      ElasticSearchInstance:
        DomainEndpoint: 'localhost:9200'
    importValueMap:
      other-service-api-url: 'https://other.api.url.com/graphql'

# in your appsync config
dataSources:
  - type: AMAZON_ELASTICSEARCH
    name: elasticsource
    config:
      # endpoint resolves as 'http://localhost:9200'
      endpoint:
        Fn::Join:
          - ''
          - - https://
            - Fn::GetAtt:
                - ElasticSearchInstance
                - DomainEndpoint

Key-value mock notation

In some special cases you will need to use key-value mock nottation. Good example can be case when you need to include serverless stage value (${self:provider.stage}) in the import name.

This notation can be used with all mocks - refMap, getAttMap and importValueMap

provider:
  environment:
    FINISH_ACTIVITY_FUNCTION_ARN:
      Fn::ImportValue: other-service-api-${self:provider.stage}-url

custom:
  serverless-appsync-simulator:
    importValueMap:
      - key: other-service-api-${self:provider.stage}-url
        value: 'https://other.api.url.com/graphql'

Limitations

This plugin only tries to resolve the following parts of the yml tree:

  • provider.environment
  • functions[*].environment
  • custom.appSync

If you have the need of resolving others, feel free to open an issue and explain your use case.

For now, the supported resources to be automatically resovled by Ref: are:

  • DynamoDb tables
  • S3 Buckets

Feel free to open a PR or an issue to extend them as well.

External functions

When a function is not defined withing the current serverless file you can still call it by providing an invoke url which should point to a REST method. Make sure you specify "get" or "post" for the method. Default is "get", but you probably want "post".

custom:
  appsync-simulator:
    functions:
      addUser:
        url: http://localhost:3016/2015-03-31/functions/addUser/invocations
        method: post
      addPost:
        url: https://jsonplaceholder.typicode.com/posts
        method: post

Supported Resolver types

This plugin supports resolvers implemented by amplify-appsync-simulator, as well as custom resolvers.

From Aws Amplify:

  • NONE
  • AWS_LAMBDA
  • AMAZON_DYNAMODB
  • PIPELINE

Implemented by this plugin

  • AMAZON_ELASTIC_SEARCH
  • HTTP
  • RELATIONAL_DATABASE

Relational Database

Sample VTL for a create mutation

#set( $cols = [] )
#set( $vals = [] )
#foreach( $entry in $ctx.args.input.keySet() )
  #set( $regex = "([a-z])([A-Z]+)")
  #set( $replacement = "$1_$2")
  #set( $toSnake = $entry.replaceAll($regex, $replacement).toLowerCase() )
  #set( $discard = $cols.add("$toSnake") )
  #if( $util.isBoolean($ctx.args.input[$entry]) )
      #if( $ctx.args.input[$entry] )
        #set( $discard = $vals.add("1") )
      #else
        #set( $discard = $vals.add("0") )
      #end
  #else
      #set( $discard = $vals.add("'$ctx.args.input[$entry]'") )
  #end
#end
#set( $valStr = $vals.toString().replace("[","(").replace("]",")") )
#set( $colStr = $cols.toString().replace("[","(").replace("]",")") )
#if ( $valStr.substring(0, 1) != '(' )
  #set( $valStr = "($valStr)" )
#end
#if ( $colStr.substring(0, 1) != '(' )
  #set( $colStr = "($colStr)" )
#end
{
  "version": "2018-05-29",
  "statements":   ["INSERT INTO <name-of-table> $colStr VALUES $valStr", "SELECT * FROM    <name-of-table> ORDER BY id DESC LIMIT 1"]
}

Sample VTL for an update mutation

#set( $update = "" )
#set( $equals = "=" )
#foreach( $entry in $ctx.args.input.keySet() )
  #set( $cur = $ctx.args.input[$entry] )
  #set( $regex = "([a-z])([A-Z]+)")
  #set( $replacement = "$1_$2")
  #set( $toSnake = $entry.replaceAll($regex, $replacement).toLowerCase() )
  #if( $util.isBoolean($cur) )
      #if( $cur )
        #set ( $cur = "1" )
      #else
        #set ( $cur = "0" )
      #end
  #end
  #if ( $util.isNullOrEmpty($update) )
      #set($update = "$toSnake$equals'$cur'" )
  #else
      #set($update = "$update,$toSnake$equals'$cur'" )
  #end
#end
{
  "version": "2018-05-29",
  "statements":   ["UPDATE <name-of-table> SET $update WHERE id=$ctx.args.input.id", "SELECT * FROM <name-of-table> WHERE id=$ctx.args.input.id"]
}

Sample resolver for delete mutation

{
  "version": "2018-05-29",
  "statements":   ["UPDATE <name-of-table> set deleted_at=NOW() WHERE id=$ctx.args.id", "SELECT * FROM <name-of-table> WHERE id=$ctx.args.id"]
}

Sample mutation response VTL with support for handling AWSDateTime

#set ( $index = -1)
#set ( $result = $util.parseJson($ctx.result) )
#set ( $meta = $result.sqlStatementResults[1].columnMetadata)
#foreach ($column in $meta)
    #set ($index = $index + 1)
    #if ( $column["typeName"] == "timestamptz" )
        #set ($time = $result["sqlStatementResults"][1]["records"][0][$index]["stringValue"] )
        #set ( $nowEpochMillis = $util.time.parseFormattedToEpochMilliSeconds("$time.substring(0,19)+0000", "yyyy-MM-dd HH:mm:ssZ") )
        #set ( $isoDateTime = $util.time.epochMilliSecondsToISO8601($nowEpochMillis) )
        $util.qr( $result["sqlStatementResults"][1]["records"][0][$index].put("stringValue", "$isoDateTime") )
    #end
#end
#set ( $res = $util.parseJson($util.rds.toJsonString($util.toJson($result)))[1][0] )
#set ( $response = {} )
#foreach($mapKey in $res.keySet())
    #set ( $s = $mapKey.split("_") )
    #set ( $camelCase="" )
    #set ( $isFirst=true )
    #foreach($entry in $s)
        #if ( $isFirst )
          #set ( $first = $entry.substring(0,1) )
        #else
          #set ( $first = $entry.substring(0,1).toUpperCase() )
        #end
        #set ( $isFirst=false )
        #set ( $stringLength = $entry.length() )
        #set ( $remaining = $entry.substring(1, $stringLength) )
        #set ( $camelCase = "$camelCase$first$remaining" )
    #end
    $util.qr( $response.put("$camelCase", $res[$mapKey]) )
#end
$utils.toJson($response)

Using Variable Map

Variable map support is limited and does not differentiate numbers and strings data types, please inject them directly if needed.

Will be escaped properly: null, true, and false values.

{
  "version": "2018-05-29",
  "statements":   [
    "UPDATE <name-of-table> set deleted_at=NOW() WHERE id=:ID",
    "SELECT * FROM <name-of-table> WHERE id=:ID and unix_timestamp > $ctx.args.newerThan"
  ],
  variableMap: {
    ":ID": $ctx.args.id,
##    ":TIMESTAMP": $ctx.args.newerThan -- This will be handled as a string!!!
  }
}

Requires

Author: Serverless-appsync
Source Code: https://github.com/serverless-appsync/serverless-appsync-simulator 
License: MIT License

#serverless #sync #graphql 

Why Use WordPress? What Can You Do With WordPress?

Can you use WordPress for anything other than blogging? To your surprise, yes. WordPress is more than just a blogging tool, and it has helped thousands of websites and web applications to thrive. The use of WordPress powers around 40% of online projects, and today in our blog, we would visit some amazing uses of WordPress other than blogging.
What Is The Use Of WordPress?

WordPress is the most popular website platform in the world. It is the first choice of businesses that want to set a feature-rich and dynamic Content Management System. So, if you ask what WordPress is used for, the answer is – everything. It is a super-flexible, feature-rich and secure platform that offers everything to build unique websites and applications. Let’s start knowing them:

1. Multiple Websites Under A Single Installation
WordPress Multisite allows you to develop multiple sites from a single WordPress installation. You can download WordPress and start building websites you want to launch under a single server. Literally speaking, you can handle hundreds of sites from one single dashboard, which now needs applause.
It is a highly efficient platform that allows you to easily run several websites under the same login credentials. One of the best things about WordPress is the themes it has to offer. You can simply download them and plugin for various sites and save space on sites without losing their speed.

2. WordPress Social Network
WordPress can be used for high-end projects such as Social Media Network. If you don’t have the money and patience to hire a coder and invest months in building a feature-rich social media site, go for WordPress. It is one of the most amazing uses of WordPress. Its stunning CMS is unbeatable. And you can build sites as good as Facebook or Reddit etc. It can just make the process a lot easier.
To set up a social media network, you would have to download a WordPress Plugin called BuddyPress. It would allow you to connect a community page with ease and would provide all the necessary features of a community or social media. It has direct messaging, activity stream, user groups, extended profiles, and so much more. You just have to download and configure it.
If BuddyPress doesn’t meet all your needs, don’t give up on your dreams. You can try out WP Symposium or PeepSo. There are also several themes you can use to build a social network.

3. Create A Forum For Your Brand’s Community
Communities are very important for your business. They help you stay in constant connection with your users and consumers. And allow you to turn them into a loyal customer base. Meanwhile, there are many good technologies that can be used for building a community page – the good old WordPress is still the best.
It is the best community development technology. If you want to build your online community, you need to consider all the amazing features you get with WordPress. Plugins such as BB Press is an open-source, template-driven PHP/ MySQL forum software. It is very simple and doesn’t hamper the experience of the website.
Other tools such as wpFoRo and Asgaros Forum are equally good for creating a community blog. They are lightweight tools that are easy to manage and integrate with your WordPress site easily. However, there is only one tiny problem; you need to have some technical knowledge to build a WordPress Community blog page.

4. Shortcodes
Since we gave you a problem in the previous section, we would also give you a perfect solution for it. You might not know to code, but you have shortcodes. Shortcodes help you execute functions without having to code. It is an easy way to build an amazing website, add new features, customize plugins easily. They are short lines of code, and rather than memorizing multiple lines; you can have zero technical knowledge and start building a feature-rich website or application.
There are also plugins like Shortcoder, Shortcodes Ultimate, and the Basics available on WordPress that can be used, and you would not even have to remember the shortcodes.

5. Build Online Stores
If you still think about why to use WordPress, use it to build an online store. You can start selling your goods online and start selling. It is an affordable technology that helps you build a feature-rich eCommerce store with WordPress.
WooCommerce is an extension of WordPress and is one of the most used eCommerce solutions. WooCommerce holds a 28% share of the global market and is one of the best ways to set up an online store. It allows you to build user-friendly and professional online stores and has thousands of free and paid extensions. Moreover as an open-source platform, and you don’t have to pay for the license.
Apart from WooCommerce, there are Easy Digital Downloads, iThemes Exchange, Shopify eCommerce plugin, and so much more available.

6. Security Features
WordPress takes security very seriously. It offers tons of external solutions that help you in safeguarding your WordPress site. While there is no way to ensure 100% security, it provides regular updates with security patches and provides several plugins to help with backups, two-factor authorization, and more.
By choosing hosting providers like WP Engine, you can improve the security of the website. It helps in threat detection, manage patching and updates, and internal security audits for the customers, and so much more.

Read More

#use of wordpress #use wordpress for business website #use wordpress for website #what is use of wordpress #why use wordpress #why use wordpress to build a website

Avian: A lightweight Java Virtual Machine (JVM)

Quick Start

These are examples of building Avian on various operating systems for the x86_64 architecture. You may need to modify JAVA_HOME according to where the JDK is installed on your system. In all cases, be sure to use forward slashes in the path.

on Linux:

$ export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
$ make
$ build/linux-x86_64/avian -cp build/linux-x86_64/test Hello

on Mac OS X:

$ export JAVA_HOME=$(/usr/libexec/java_home)
$ make
$ build/macosx-x86_64/avian -cp build/macosx-x86_64/test Hello

on Windows (Cygwin):

$ git clone git@github.com:ReadyTalk/win64.git ../win64
$ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.7.0_45"
$ make
$ build/windows-x86_64/avian -cp build/windows-x86_64/test Hello

on FreeBSD:

$ export JAVA_HOME=/usr/local/openjdk7
$ gmake
$ build/freebsd-x86_64/avian -cp build/freebsd-x86_64/test Hello

Introduction

Avian is a lightweight virtual machine and class library designed to provide a useful subset of Java's features, suitable for building self-contained applications.

Supported Platforms

Avian can currently target the following platforms:

  • Linux (i386, x86_64, ARM, and ARM64)
  • Windows (i386 and x86_64)
  • Mac OS X (i386 and x86_64)
  • Apple iOS (i386, x86_64, ARM, and ARM64)
  • FreeBSD (i386, x86_64)

Building

Build requirements include:

  • GNU make 3.80 or later
  • GCC 4.6 or later or LLVM Clang 3.1 or later (see use-clang option below)
  • JDK 1.6 or later
  • MinGW 3.4 or later (only if compiling for Windows)
  • zlib 1.2.3 or later

Earlier versions of some of these packages may also work but have not been tested.

The build is directed by a single makefile and may be influenced via certain flags described below, all of which are optional.

$ make \
    platform={linux,windows,macosx,ios,freebsd} \
    arch={i386,x86_64,arm,arm64} \
    process={compile,interpret} \
    mode={debug,debug-fast,fast,small} \
    lzma=<lzma source directory> \
    bootimage={true,false} \
    tails={true,false} \
    continuations={true,false} \
    use-clang={true,false} \
    openjdk=<openjdk installation directory> \
    openjdk-src=<openjdk source directory> \
    android=<android source directory> \
    ios-version=<iOS minimum version>

platform - the target platform

  • default: output of $(uname -s | tr [:upper:] [:lower:]), normalized in some cases (e.g. CYGWIN_NT-5.1 -> windows)

arch - the target architecture

  • default: output of $(uname -m), normalized in some cases (e.g. i686 -> i386)

process - choice between pure interpreter or JIT compiler

  • default: compile

mode - which set of compilation flags to use to determine optimization level, debug symbols, and whether to enable assertions

  • default: fast

lzma - if set, support use of LZMA to compress embedded JARs and boot images. The value of this option should be a directory containing a recent LZMA SDK (available here). Currently, only version 9.20 of the SDK has been tested, but other versions might work.

  • default: not set

armv6 - if true, don't use any instructions newer than armv6. By default, we assume the target is armv7 or later, and thus requires explicit memory barrier instructions to ensure cache coherency

bootimage - if true, create a boot image containing the pre-parsed class library and ahead-of-time compiled methods. This option is only valid for process=compile builds. Note that you may need to specify both build-arch=x86_64 and arch=x86_64 on 64-bit systems where "uname -m" prints "i386".

  • default: false

tails - if true, optimize each tail call by replacing the caller's stack frame with the callee's. This convention ensures proper tail recursion, suitable for languages such as Scheme. This option is only valid for process=compile builds.

  • default: false

continuations - if true, support continuations via the avian.Continuations methods callWithCurrentContinuation and dynamicWind. See Continuations.java for details. This option is only valid for process=compile builds.

  • default: false

use-clang - if true, use LLVM's clang instead of GCC to build. Note that this does not currently affect cross compiles, only native builds.

  • default: false

openjdk - if set, use the OpenJDK class library instead of the default Avian class library. See "Building with the OpenJDK Class Library" below for details.

  • default: not set

openjdk-src - if this and the openjdk option above are both set, build an embeddable VM using the OpenJDK class library. The JNI components of the OpenJDK class library will be built from the sources found under the specified directory. See "Building with the OpenJDK Class Library" below for details.

  • default: not set

android - if set, use the Android class library instead of the default Avian class library. See "Building with the Android Class Library" below for details.

  • default: not set

ios-version - the minimum iOS SDK version which will be used when compiling for ios target. Do not use a value 11.0 or larger, if you want to support 32 bit version. This option is only valid for platform=ios .

  • default: 8.0

These flags determine the name of the directory used for the build. The name always starts with ${platform}-${arch}, and each non-default build option is appended to the name. For example, a debug build with bootimage enabled on Linux/x86_64 would be built in build/linux-x86_64-debug-bootimage. This allows you to build with several different sets of options independently and even simultaneously without doing a clean build each time.

Note that not all combinations of these flags are valid. For instance, non-jailbroken iOS devices do not allow JIT compilation, so only process=interpret or bootimage=true builds will run on such devices. See here for an example of an Xcode project for iOS which uses Avian.

If you are compiling for Windows, you may either cross-compile using MinGW or build natively on Windows under Cygwin.

Installing Cygwin:

1. Download and run setup.exe from cygwin's website, installing the base system and these packages: make, gcc-mingw-g++, mingw64-i686-gcc-g++, mingw64-x86_64-gcc-g++, and (optionally) git.

You may also find our win32 repository useful: (run this from the directory containing the avian directory)

$ git clone git@github.com:ReadyTalk/win32.git

This gives you the Windows JNI headers, zlib headers and library, and a few other useful libraries like OpenSSL, libjpeg, and libpng. There's also a win64 repository for 64-bit builds:

  $ git clone git@github.com:ReadyTalk/win64.git

Building with the Microsoft Visual C++ Compiler

You can also build using the MSVC compiler, which makes debugging with tools like WinDbg and Visual Studio much easier. Note that you will still need to have GCC installed - MSVC is only used to compile the C++ portions of the VM, while the assembly code and helper tools are built using GCC.

Note that the MSVC build isn't tested regularly, so is fairly likely to be broken.

Avian targets MSVC 11 and above (it uses c++ features not available in older versions).

To build with MSVC, install Cygwin as described above and set the following environment variables:

$ export PATH="/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/Common7/Tools:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v3.5:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/VC/VCPackages:/cygdrive/c/Program Files/Microsoft SDKs/Windows/v6.0A/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem"
$ export LIBPATH="C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 11.0\VC\LIB;"
$ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 11.0\VC"
$ export LIB="C:\Program Files\Microsoft Visual Studio 11.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;"
$ export INCLUDE="C:\Program Files\Microsoft Visual Studio 11.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;"

Adjust these definitions as necessary according to your MSVC installation.

Finally, build with the msvc flag set to the MSVC tool directory:

$ make msvc="/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/VC"

Building with the OpenJDK Class Library

By default, Avian uses its own lightweight class library. However, that library only contains a relatively small subset of the classes and methods included in the JRE. If your application requires features beyond that subset, you may want to tell Avian to use OpenJDK's class library instead. To do so, specify the directory where OpenJDK is installed, e.g.:

$ make openjdk=/usr/lib/jvm/java-7-openjdk

This will build Avian as a conventional JVM (e.g. libjvm.so) which loads its boot class library and native libraries (e.g. libjava.so) from /usr/lib/jvm/java-7-openjdk/jre at runtime. Note that you must use an absolute path here, or else the result will not work when run from other directories. In this configuration, OpenJDK needs to remain installed for Avian to work, and you can run applications like this:

$ build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \
    com.example.MyApplication

Alternatively, you can enable a stand-alone build using OpenJDK by specifying the location of the OpenJDK source code, e.g.:

$ make openjdk=$(pwd)/../jdk7/build/linux-amd64/j2sdk-image \
    openjdk-src=$(pwd)/../jdk7/jdk/src

You must ensure that the path specified for openjdk-src does not have any spaces in it; make gets confused when dependency paths include spaces, and we haven't found away around that except to avoid paths with spaces entirely.

The result of such a build is a self-contained binary which does not depend on external libraries, jars, or other files. In this case, the specified paths are used only at build time; anything needed at runtime is embedded in the binary. Thus, the process of running an application is simplified:

$ build/linux-x86_64-openjdk-src/avian -cp /path/to/my/application \
    com.example.MyApplication

Note that the resulting binary will be very large due to the size of OpenJDK's class library. This can be mitigated using UPX, preferably an LZMA-enabled version:

$ upx --lzma --best build/linux-x86_64-openjdk-src/avian

You can reduce the size futher for embedded builds by using ProGuard and the supplied openjdk.pro configuration file (see "Embedding with ProGuard and a Boot Image" below). Note that you'll still need to use vm.pro in that case -- openjdk.pro just adds additional constraints specific to the OpenJDK port. Also see app.mk in the avian-swt-examples project for an example of using Avian, OpenJDK, ProGuard, and UPX in concert.

Here are some examples of how to install OpenJDK and build Avian with it on various OSes:

Debian-based Linux:

Conventional build:

$ apt-get install openjdk-7-jdk
$ make openjdk=/usr/lib/jvm/java-7-openjdk test

Stand-alone build:

$ apt-get install openjdk-7-jdk
$ apt-get source openjdk-7-jdk
$ apt-get build-dep openjdk-7-jdk
$ (cd openjdk-7-7~b147-2.0 && dpkg-buildpackage)
$ make openjdk=/usr/lib/jvm/java-7-openjdk \
    openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \
    test

Mac OS X:

Prerequisite: Build OpenJDK 7 according to this site.

Conventional build:

$ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test

Stand-alone build:

$ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \
    openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test

Windows (Cygwin):

Prerequisite: Build OpenJDK 7 according to this site. Alternatively, use https://github.com/alexkasko/openjdk-unofficial-builds.

Conventional build:

$ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test

Stand-alone build:

$ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \
    openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test

Currently, only OpenJDK 7 is supported. Later versions might work, but have not yet been tested.

Building with the Android Class Library

As an alternative to both the Avian and OpenJDK class libaries, you can also build with the Android class library. Now it should work on Linux, OS X and Windows.

The simpliest way to build Avian with Android classpath is to use avian-pack project: https://github.com/bigfatbrowncat/avian-pack

Avian-pack consists of Avian itself with some Android components (such as libcore and icu4c).

Note that we use the upstream OpenSSL repository and apply the Android patches to it. This is because it is not clear how to build the Android fork of OpenSSL directly without checking out and building the entire platform. As of this writing, the patches apply cleanly against OpenSSL 1.0.1h, so that's the tag we check out, but this may change in the future when the Android fork rebases against a new OpenSSL version.

Installing

Installing Avian is as simple as copying the executable to the desired directory:

$ cp build/${platform}-${arch}/avian ~/bin/

Embedding

The following series of commands illustrates how to produce a stand-alone executable out of a Java application using Avian.

Note: if you are building on Cygwin, prepend "x86_64-w64-mingw32-" or "i686-w64-mingw32-" to the ar, g++, gcc, strip, and dlltool commands below (e.g. x86_64-w64-mingw32-gcc).

1. Build Avian, create a new directory, and populate it with the VM object files and bootstrap classpath jar.

$ make
$ mkdir hello
$ cd hello
$ ar x ../build/${platform}-${arch}/libavian.a
$ cp ../build/${platform}-${arch}/classpath.jar boot.jar

2. Build the Java code and add it to the jar.

$ cat >Hello.java <<EOF
public class Hello {
  public static void main(String[] args) {
    System.out.println("hello, world!");
  }
}
EOF
 $ javac -bootclasspath boot.jar Hello.java
 $ jar u0f boot.jar Hello.class

3. Make an object file out of the jar.

$ ../build/${platform}-${arch}/binaryToObject/binaryToObject boot.jar \
     boot-jar.o _binary_boot_jar_start _binary_boot_jar_end ${platform} ${arch}

If you've built Avian using the lzma option, you may optionally compress the jar before generating the object:

  ../build/$(platform}-${arch}-lzma/lzma/lzma encode boot.jar boot.jar.lzma
     && ../build/${platform}-${arch}-lzma/binaryToObject/binaryToObject \
       boot.jar.lzma boot-jar.o _binary_boot_jar_start _binary_boot_jar_end \
       ${platform} ${arch}

Note that you'll need to specify "-Xbootclasspath:[lzma.bootJar]" instead of "-Xbootclasspath:[bootJar]" in the next step if you've used LZMA to compress the jar.

4. Write a driver which starts the VM and runs the desired main method. Note the bootJar function, which will be called by the VM to get a handle to the embedded jar. We tell the VM about this jar by setting the boot classpath to "[bootJar]".

$ cat >embedded-jar-main.cpp <<EOF
#include "stdint.h"
#include "jni.h"
#include "stdlib.h"

#if (defined __MINGW32__) || (defined _MSC_VER)
#  define EXPORT __declspec(dllexport)
#else
#  define EXPORT __attribute__ ((visibility("default"))) \
  __attribute__ ((used))
#endif

#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
#  define SYMBOL(x) binary_boot_jar_##x
#else
#  define SYMBOL(x) _binary_boot_jar_##x
#endif

extern "C" {

  extern const uint8_t SYMBOL(start)[];
  extern const uint8_t SYMBOL(end)[];

  EXPORT const uint8_t*
  bootJar(size_t* size)
  {
    *size = SYMBOL(end) - SYMBOL(start);
    return SYMBOL(start);
  }

} // extern "C"

extern "C" void __cxa_pure_virtual(void) { abort(); }

int
main(int ac, const char** av)
{
  JavaVMInitArgs vmArgs;
  vmArgs.version = JNI_VERSION_1_2;
  vmArgs.nOptions = 1;
  vmArgs.ignoreUnrecognized = JNI_TRUE;

  JavaVMOption options[vmArgs.nOptions];
  vmArgs.options = options;

  options[0].optionString = const_cast<char*>("-Xbootclasspath:[bootJar]");

  JavaVM* vm;
  void* env;
  JNI_CreateJavaVM(&vm, &env, &vmArgs);
  JNIEnv* e = static_cast<JNIEnv*>(env);

  jclass c = e->FindClass("Hello");
  if (not e->ExceptionCheck()) {
    jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V");
    if (not e->ExceptionCheck()) {
      jclass stringClass = e->FindClass("java/lang/String");
      if (not e->ExceptionCheck()) {
        jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0);
        if (not e->ExceptionCheck()) {
          for (int i = 1; i < ac; ++i) {
            e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i]));
          }

          e->CallStaticVoidMethod(c, m, a);
        }
      }
    }
  }

  int exitCode = 0;
  if (e->ExceptionCheck()) {
    exitCode = -1;
    e->ExceptionDescribe();
  }

  vm->DestroyJavaVM();

  return exitCode;
}
EOF

on Linux:

 $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
     -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o

on Mac OS X:

 $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin \
     -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o

on Windows:

 $ g++ -fno-exceptions -fno-rtti -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/win32" \
     -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o

5. Link the objects produced above to produce the final executable, and optionally strip its symbols.

on Linux:

$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello
$ strip --strip-all hello

on Mac OS X:

$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation
$ strip -S -x hello

on Windows:

$ dlltool -z hello.def *.o
$ dlltool -d hello.def -e hello.exp
$ gcc hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \
    -lIphlpapi -mwindows -mconsole -o hello.exe
$ strip --strip-all hello.exe

Embedding with ProGuard and a Boot Image

The following illustrates how to embed an application as above, except this time we preprocess the code using ProGuard and build a boot image from it for quicker startup. The pros and cons of using ProGuard are as follow:

Pros: ProGuard will eliminate unused code, optimize the rest, and obfuscate it as well for maximum space savings

Cons: increased build time, especially for large applications, and extra effort needed to configure it for applications which rely heavily on reflection and/or calls to Java from native code

For boot image builds:

Pros: the boot image build pre-parses all the classes and compiles all the methods, obviating the need for JIT compilation at runtime. This also makes garbage collection faster, since the pre-parsed classes are never visited.

Cons: the pre-parsed classes and AOT-compiled methods take up more space in the executable than the equivalent class files. In practice, this can make the executable 30-50% larger. Also, AOT compilation does not yet yield significantly faster or smaller code than JIT compilation. Finally, floating point code may be slower on 32-bit x86 since the compiler cannot assume SSE2 support will be available at runtime, and the x87 FPU is not supported except via out-of-line helper functions.

Note you can use ProGuard without using a boot image and vice-versa, as desired.

The following instructions assume we are building for Linux/x86_64. Please refer to the previous example for guidance on other platforms.

1. Build Avian, create a new directory, and populate it with the VM object files.

$ make bootimage=true
$ mkdir hello
$ cd hello
$ ar x ../build/linux-x86_64-bootimage/libavian.a

2. Create a stage1 directory and extract the contents of the class library jar into it.

$ mkdir stage1
$ (cd stage1 && jar xf ../../build/linux-x86_64-bootimage/classpath.jar)

3. Build the Java code and add it to stage1.

 $ cat >Hello.java <<EOF
public class Hello {
  public static void main(String[] args) {
    System.out.println("hello, world!");
  }
}
EOF
 $ javac -bootclasspath stage1 -d stage1 Hello.java

4. Create a ProGuard configuration file specifying Hello.main as the entry point.

 $ cat >hello.pro <<EOF
-keep class Hello {
   public static void main(java.lang.String[]);
 }
EOF

5. Run ProGuard with stage1 as input and stage2 as output.

 $ java -jar ../../proguard4.6/lib/proguard.jar \
     -dontusemixedcaseclassnames -injars stage1 -outjars stage2 \
     @../vm.pro @hello.pro

(note: The -dontusemixedcaseclassnames option is only needed when building on systems with case-insensitive filesystems such as Windows and OS X. Also, you'll need to add -ignorewarnings if you use the OpenJDK class library since the openjdk-src build does not include all the JARs from OpenJDK, and thus ProGuard will not be able to resolve all referenced classes. If you actually plan to use such classes at runtime, you'll need to add them to stage1 before running ProGuard. Finally, you'll need to add @../openjdk.pro to the above command when using the OpenJDK library.)

6. Build the boot and code images.

 $ ../build/linux-x86_64-bootimage/bootimage-generator \
    -cp stage2 \
    -bootimage bootimage-bin.o \
    -codeimage codeimage-bin.o \
    -hostvm ../build/linux-x86_64-interpret/libjvm.so

Note that you can override the default names for the start and end symbols in the boot/code image by also passing:

-bootimage-symbols my_bootimage_start:my_bootimage_end \
-codeimage-symbols my_codeimage_start:my_codeimage_end

7. Write a driver which starts the VM and runs the desired main method. Note the bootimageBin function, which will be called by the VM to get a handle to the embedded boot image. We tell the VM about this function via the "avian.bootimage" property.

Note also that this example includes no resources besides class files. If our application loaded resources such as images and properties files via the classloader, we would also need to embed the jar file containing them. See the previous example for instructions.

$ cat >bootimage-main.cpp <<EOF
#include "stdint.h"
#include "jni.h"

#if (defined __MINGW32__) || (defined _MSC_VER)
#  define EXPORT __declspec(dllexport)
#else
#  define EXPORT __attribute__ ((visibility("default")))
#endif

#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
#  define BOOTIMAGE_BIN(x) binary_bootimage_bin_##x
#  define CODEIMAGE_BIN(x) binary_codeimage_bin_##x
#else
#  define BOOTIMAGE_BIN(x) _binary_bootimage_bin_##x
#  define CODEIMAGE_BIN(x) _binary_codeimage_bin_##x
#endif

extern "C" {

  extern const uint8_t BOOTIMAGE_BIN(start)[];
  extern const uint8_t BOOTIMAGE_BIN(end)[];

  EXPORT const uint8_t*
  bootimageBin(size_t* size)
  {
    *size = BOOTIMAGE_BIN(end) - BOOTIMAGE_BIN(start);
    return BOOTIMAGE_BIN(start);
  }

  extern const uint8_t CODEIMAGE_BIN(start)[];
  extern const uint8_t CODEIMAGE_BIN(end)[];

  EXPORT const uint8_t*
  codeimageBin(size_t* size)
  {
    *size = CODEIMAGE_BIN(end) - CODEIMAGE_BIN(start);
    return CODEIMAGE_BIN(start);
  }

} // extern "C"

int
main(int ac, const char** av)
{
  JavaVMInitArgs vmArgs;
  vmArgs.version = JNI_VERSION_1_2;
  vmArgs.nOptions = 2;
  vmArgs.ignoreUnrecognized = JNI_TRUE;

  JavaVMOption options[vmArgs.nOptions];
  vmArgs.options = options;

  options[0].optionString
    = const_cast<char*>("-Davian.bootimage=bootimageBin");

  options[1].optionString
    = const_cast<char*>("-Davian.codeimage=codeimageBin");

  JavaVM* vm;
  void* env;
  JNI_CreateJavaVM(&vm, &env, &vmArgs);
  JNIEnv* e = static_cast<JNIEnv*>(env);

  jclass c = e->FindClass("Hello");
  if (not e->ExceptionCheck()) {
    jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V");
    if (not e->ExceptionCheck()) {
      jclass stringClass = e->FindClass("java/lang/String");
      if (not e->ExceptionCheck()) {
        jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0);
        if (not e->ExceptionCheck()) {
          for (int i = 1; i < ac; ++i) {
            e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i]));
          }

          e->CallStaticVoidMethod(c, m, a);
        }
      }
    }
  }

  int exitCode = 0;
  if (e->ExceptionCheck()) {
    exitCode = -1;
    e->ExceptionDescribe();
  }

  vm->DestroyJavaVM();

  return exitCode;
}
EOF

 $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
     -D_JNI_IMPLEMENTATION_ -c bootimage-main.cpp -o main.o

8. Link the objects produced above to produce the final executable, and optionally strip its symbols.

$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello
$ strip --strip-all hello

Trademarks

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

The Avian project is not affiliated with Oracle.

Download Details:
Author: ReadyTalk
Source Code: https://github.com/ReadyTalk/avian
License: View license

#java #JVM #jdk

Nat  Grady

Nat Grady

1660108440

Wordcloud2: R interface to Wordcloud for Data Visualization

wordcloud2

R interface to wordcloud for data visualization. Timdream's wordcloud2.js is used in this package.

Original description

Installation

devtools::install_github("lchiffon/wordcloud2")

knitr and shiny is support in wordcloud2 package.

Example

library(wordcloud2)
wordcloud2(demoFreq, size = 1,shape = 'star')

1

wordcloud2(demoFreq, size = 2, minRotation = -pi/2, maxRotation = -pi/2)

1

wordcloud2(demoFreq, size = 2, minRotation = -pi/6, maxRotation = -pi/6,
  rotateRatio = 1)

1

Chinese version

## Sys.setlocale("LC_CTYPE","eng")
wordcloud2(demoFreqC, size = 2, fontFamily = "微软雅黑",
           color = "random-light", backgroundColor = "grey")

1

Example of successfully deploying interactivate clickable wordcloud with special shape on R-shiny

Thanks JacobXPX's contribution to this feature:

Thanks AdamSpannbauer for pointing out the issues.

Additional features are added or modified:

hover information display are fixed, refering AdeelK93's previous work, thanks!

multiple wordclouds which seperatedly click are supported.

clickedWordInputId is changed to be automatically generated by: paste0(outputId, "_clicked_word")).

See sample below for more details:

library(shiny)
library(wordcloud2)
shinyApp(
  ui=shinyUI(fluidPage(
    #using default clicked word input id
    wordcloud2Output("my_wc", width = "50%", height = "400px"),
    #using custom clicked word input id
    wordcloud2Output("my_wc2", width = "50%", height = "400px"),
    
    verbatimTextOutput("print"),
    verbatimTextOutput("print2")
  )),
  server=shinyServer(function(input,output,session){
    
    figPath = system.file("examples/a.png",package = "wordcloud2")
    
    output$my_wc  = renderWordcloud2(wordcloud2(data = demoFreq, figPath = figPath, size = 0.4,color = "blue"))
    output$my_wc2 = renderWordcloud2(wordcloud2(demoFreq))
    
    #using default clicked word input id
    output$print  = renderPrint(input$my_wc_clicked_word)
    #using custom clicked word input id
    output$print2 = renderPrint(input$my_wc2_clicked_word)
  })
)

run the above code and click refresh, it will work.

1

contributors

Download Details:

Author: Lchiffon
Source Code: https://github.com/Lchiffon/wordcloud2 

#r #datavisualization