<commit_before>#include "types.h"
#include "pen.h"
#include "threads.h"
#include "console.h"
#include "hash.h"
#include "renderer.h"
#include "timer.h"
#include "input.h"

#include <emscripten.h>
#include <GLES3/gl32.h>
#include <SDL/SDL.h>

#include <semaphore.h>
#include <sys/types.h>
#include <unistd.h>

#include <stdio.h>
#include <map>

#include <emscripten.h>
EM_JS(int, get_canvas_width, (), {
  return canvas.clientWidth;
});

EM_JS(int, get_canvas_height, (), {
  return canvas.clientHeight;
});

using namespace pen;

void pen_make_gl_context_current()
{
}

void pen_gl_swap_buffers()
{
    SDL_GL_SwapBuffers();
}

namespace
{
    struct os_context
    {
        SDL_Surface* 		surface;
        pen_creation_params	pcp;
    };
    os_context s_ctx;

    std::map<u32, virtual_key> k_key_map = {{SDLK_0, PK_0},
                                            {SDLK_1, PK_1},
                                            {SDLK_2, PK_2},
                                            {SDLK_3, PK_3},
                                            {SDLK_4, PK_4},
                                            {SDLK_5, PK_5},
                                            {SDLK_6, PK_6},
                                            {SDLK_7, PK_7},
                                            {SDLK_8, PK_8},
                                            {SDLK_9, PK_9},
                                            {SDLK_a, PK_A},
                                            {SDLK_b, PK_B},
                                            {SDLK_c, PK_C},
                                            {SDLK_d, PK_D},
                                            {SDLK_e, PK_E},
                                            {SDLK_f, PK_F},
                                            {SDLK_g, PK_G},
                                            {SDLK_h, PK_H},
                                            {SDLK_i, PK_I},
                                            {SDLK_j, PK_J},
                                            {SDLK_k, PK_K},
                                            {SDLK_l, PK_L},
                                            {SDLK_m, PK_M},
                                            {SDLK_n, PK_N},
                                            {SDLK_o, PK_O},
                                            {SDLK_p, PK_P},
                                            {SDLK_q, PK_Q},
                                            {SDLK_r, PK_R},
                                            {SDLK_s, PK_S},
                                            {SDLK_t, PK_T},
                                            {SDLK_u, PK_U},
                                            {SDLK_v, PK_V},
                                            {SDLK_w, PK_W},
                                            {SDLK_x, PK_X},
                                            {SDLK_y, PK_Y},
                                            {SDLK_z, PK_Z},
                                            {SDLK_KP_0, PK_NUMPAD0},
                                            {SDLK_KP_1, PK_NUMPAD1},
                                            {SDLK_KP_2, PK_NUMPAD2},
                                            {SDLK_KP_3, PK_NUMPAD3},
                                            {SDLK_KP_4, PK_NUMPAD4},
                                            {SDLK_KP_5, PK_NUMPAD5},
                                            {SDLK_KP_6, PK_NUMPAD6},
                                            {SDLK_KP_7, PK_NUMPAD7},
                                            {SDLK_KP_8, PK_NUMPAD8},
                                            {SDLK_KP_9, PK_NUMPAD9},
                                            {SDLK_KP_MULTIPLY, PK_MULTIPLY},
                                            {SDLK_KP_PLUS, PK_ADD},
                                            {SDLK_KP_MINUS, PK_SUBTRACT},
                                            {SDLK_KP_DECIMAL, PK_DECIMAL},
                                            {SDLK_KP_DIVIDE, PK_DIVIDE},
                                            {SDLK_F1, PK_F1},
                                            {SDLK_F2, PK_F2},
                                            {SDLK_F3, PK_F3},
                                            {SDLK_F4, PK_F4},
                                            {SDLK_F5, PK_F5},
                                            {SDLK_F6, PK_F6},
                                            {SDLK_F7, PK_F7},
                                            {SDLK_F8, PK_F8},
                                            {SDLK_F9, PK_F9},
                                            {SDLK_F10, PK_F10},
                                            {SDLK_F11, PK_F11},
                                            {SDLK_F12, PK_F12},
                                            {SDLK_CANCEL, PK_CANCEL},
                                            {SDLK_BACKSPACE, PK_BACK},
                                            {SDLK_TAB, PK_TAB},
                                            {SDLK_CLEAR, PK_CLEAR},
                                            {SDLK_RETURN, PK_RETURN},
                                            {SDLK_LSHIFT, PK_SHIFT},
                                            {SDLK_RSHIFT, PK_SHIFT},
                                            {SDLK_LCTRL, PK_CONTROL},
                                            {SDLK_RCTRL, PK_CONTROL},
                                            {SDLK_LALT, PK_MENU},
                                            {SDLK_CAPSLOCK, PK_CAPITAL},
                                            {SDLK_ESCAPE, PK_ESCAPE},
                                            {SDLK_SPACE, PK_SPACE},
                                            {SDLK_PAGEDOWN, PK_PRIOR},
                                            {SDLK_PAGEUP, PK_NEXT},
                                            {SDLK_END, PK_END},
                                            {SDLK_HOME, PK_HOME},
                                            {SDLK_LEFT, PK_LEFT},
                                            {SDLK_UP, PK_UP},
                                            {SDLK_RIGHT, PK_RIGHT},
                                            {SDLK_DOWN, PK_DOWN},
                                            {SDLK_INSERT, PK_INSERT},
                                            {SDLK_DELETE, PK_DELETE},
                                            {SDLK_LGUI, PK_COMMAND},
                                            {SDLK_LEFTBRACKET, PK_OPEN_BRACKET},
                                            {SDLK_RIGHTBRACKET, PK_CLOSE_BRACKET},
                                            {SDLK_COLON, PK_SEMICOLON},
                                            {SDLK_QUOTE, PK_APOSTRAPHE},
                                            {SDLK_BACKSLASH, PK_BACK_SLASH},
                                            {SDLK_SLASH, PK_FORWARD_SLASH},
                                            {SDLK_COMMA, PK_COMMA},
                                            {SDLK_PERIOD, PK_PERIOD},
                                            {SDLK_MINUS, PK_MINUS},
                                            {SDLK_EQUALS, PK_EQUAL},
                                            {0x00, PK_TILDE},
                                            {SDLK_BACKQUOTE, PK_GRAVE}};

    void handle_key_event(bool down, u32 key)
    {
        if (k_key_map.find(key) != k_key_map.end())
        {
            u32 pk = k_key_map[key];
            if (down)
            {
                pen::input_set_key_down(pk);
            }
            else
            {
                pen::input_set_key_up(pk);
            }
        }
    }

    void handle_mouse()
    {
        s32 x, y;
        u32 b = SDL_GetMouseState(&x, &y);
        input_set_mouse_pos((f32)x, (f32)y);
        if(b == SDL_BUTTON_LEFT)
        {
            input_set_mouse_down(PEN_MOUSE_L);
        }
        else
        {
            input_set_mouse_up(PEN_MOUSE_L);
        }

        if(b == SDL_BUTTON_RIGHT)
        {
            input_set_mouse_down(PEN_MOUSE_R);
        }
        else
        {
            input_set_mouse_up(PEN_MOUSE_R);
        }

        if(b == SDL_BUTTON_MIDDLE)
        {
            input_set_mouse_down(PEN_MOUSE_M);
        }
        else
        {
            input_set_mouse_up(PEN_MOUSE_M);
        }
    }

    void handle_window_resize()
    {
        if(s_ctx.pcp.window_width != get_canvas_width() || s_ctx.pcp.window_height != get_canvas_height())
        {
            s_ctx.pcp.window_width = get_canvas_width();
            s_ctx.pcp.window_height = get_canvas_height();

            if(s_ctx.surface)
                SDL_FreeSurface(s_ctx.surface);

            s_ctx.surface = SDL_SetVideoMode(s_ctx.pcp.window_width, s_ctx.pcp.window_height, 32, SDL_OPENGL | SDL_RESIZABLE);
        }
    }

    void run()
    {
        SDL_PumpEvents();

        SDL_Event event;
        while( SDL_PollEvent( &event ) )
        {
            switch( event.type ){
            case SDL_KEYDOWN:
                handle_key_event(true, (u32)event.key.keysym.sym);
                break;
            case SDL_KEYUP:
                handle_key_event(false, (u32)event.key.keysym.sym);
                break;
            case SDL_MOUSEWHEEL:
                input_set_mouse_wheel(event.wheel.y);
                break;
            default:
                break;
            }
        }

        handle_mouse();
        handle_window_resize();

        pen::renderer_dispatch();
    }

    void create_sdl_surface()
    {
        SDL_Init(SDL_INIT_VIDEO);

        if(s_ctx.pcp.window_sample_count > 1)
        {
            SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
            SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, s_ctx.pcp.window_sample_count);
        }

        handle_window_resize();
    }

    void init()
    {
        create_sdl_surface();
        SDL_EnableUNICODE(1);
        timer_system_intialise();
        pen::renderer_init(nullptr, false, 1024);

        // creates user thread
        jobs_create_job(s_ctx.pcp.user_thread_function, 1024 * 1024, s_ctx.pcp.user_data, pen::e_thread_start_flags::detached);
    }
}

//
// os public api
//

namespace pen
{
    bool os_update()
    {
        return true;
    }

    void os_terminate(u32 return_code)
    {

    }

    const c8* os_path_for_resource(const c8* filename)
    {
        return filename;
    }

    const c8* window_get_title()
    {
        return s_ctx.pcp.window_title;
    }

    void window_get_size(s32& width, s32& height)
    {
        width = s_ctx.pcp.window_width;
        height = s_ctx.pcp.window_height;
    }

    f32 window_get_aspect()
    {
        return (f32)s_ctx.pcp.window_width / (f32)s_ctx.pcp.window_height;
    }

    hash_id window_get_id()
    {
        static hash_id window_id = PEN_HASH(s_ctx.pcp.window_title);
        return window_id;
    }

    void window_get_frame(window_frame& f)
    {
        f = {0, 0, s_ctx.pcp.window_width, s_ctx.pcp.window_height};
    }

    void window_set_frame(const window_frame& f)
    {

    }

    void* window_get_primary_display_handle()
    {
        return (void*)s_ctx.surface;
    }

    bool input_undo_pressed()
    {
        return false;
    }

    bool input_redo_pressed()
    {
        return false;
    }

    const user_info& os_get_user_info()
    {
        static user_info u;
        return u;
    }
}

//
// entry
//

int main()
{
  	s_ctx.pcp = pen_entry(0, nullptr);
    init();
    emscripten_set_main_loop(run, 0, 1);
    return 0;
}
<commit_msg>- signle threaded web wip<commit_after>#include "types.h"
#include "pen.h"
#include "threads.h"
#include "console.h"
#include "hash.h"
#include "renderer.h"
#include "timer.h"
#include "input.h"

#include <emscripten.h>
#include <emscripten/html5.h>
#include <GLES3/gl32.h>
#include <SDL/SDL.h>

#include <semaphore.h>
#include <sys/types.h>
#include <unistd.h>

#include <stdio.h>
#include <map>

EM_JS(int, get_canvas_width, (), {
  return canvas.clientWidth;
});

EM_JS(int, get_canvas_height, (), {
  return canvas.clientHeight;
});

using namespace pen;

void pen_make_gl_context_current()
{
}

void pen_gl_swap_buffers()
{
    SDL_GL_SwapBuffers();
}

namespace
{
    struct os_context
    {
        SDL_Surface* 		surface;
        pen_creation_params	pcp;
    };
    os_context s_ctx;

    std::map<u32, virtual_key> k_key_map = {{SDLK_0, PK_0},
                                            {SDLK_1, PK_1},
                                            {SDLK_2, PK_2},
                                            {SDLK_3, PK_3},
                                            {SDLK_4, PK_4},
                                            {SDLK_5, PK_5},
                                            {SDLK_6, PK_6},
                                            {SDLK_7, PK_7},
                                            {SDLK_8, PK_8},
                                            {SDLK_9, PK_9},
                                            {SDLK_a, PK_A},
                                            {SDLK_b, PK_B},
                                            {SDLK_c, PK_C},
                                            {SDLK_d, PK_D},
                                            {SDLK_e, PK_E},
                                            {SDLK_f, PK_F},
                                            {SDLK_g, PK_G},
                                            {SDLK_h, PK_H},
                                            {SDLK_i, PK_I},
                                            {SDLK_j, PK_J},
                                            {SDLK_k, PK_K},
                                            {SDLK_l, PK_L},
                                            {SDLK_m, PK_M},
                                            {SDLK_n, PK_N},
                                            {SDLK_o, PK_O},
                                            {SDLK_p, PK_P},
                                            {SDLK_q, PK_Q},
                                            {SDLK_r, PK_R},
                                            {SDLK_s, PK_S},
                                            {SDLK_t, PK_T},
                                            {SDLK_u, PK_U},
                                            {SDLK_v, PK_V},
                                            {SDLK_w, PK_W},
                                            {SDLK_x, PK_X},
                                            {SDLK_y, PK_Y},
                                            {SDLK_z, PK_Z},
                                            {SDLK_KP_0, PK_NUMPAD0},
                                            {SDLK_KP_1, PK_NUMPAD1},
                                            {SDLK_KP_2, PK_NUMPAD2},
                                            {SDLK_KP_3, PK_NUMPAD3},
                                            {SDLK_KP_4, PK_NUMPAD4},
                                            {SDLK_KP_5, PK_NUMPAD5},
                                            {SDLK_KP_6, PK_NUMPAD6},
                                            {SDLK_KP_7, PK_NUMPAD7},
                                            {SDLK_KP_8, PK_NUMPAD8},
                                            {SDLK_KP_9, PK_NUMPAD9},
                                            {SDLK_KP_MULTIPLY, PK_MULTIPLY},
                                            {SDLK_KP_PLUS, PK_ADD},
                                            {SDLK_KP_MINUS, PK_SUBTRACT},
                                            {SDLK_KP_DECIMAL, PK_DECIMAL},
                                            {SDLK_KP_DIVIDE, PK_DIVIDE},
                                            {SDLK_F1, PK_F1},
                                            {SDLK_F2, PK_F2},
                                            {SDLK_F3, PK_F3},
                                            {SDLK_F4, PK_F4},
                                            {SDLK_F5, PK_F5},
                                            {SDLK_F6, PK_F6},
                                            {SDLK_F7, PK_F7},
                                            {SDLK_F8, PK_F8},
                                            {SDLK_F9, PK_F9},
                                            {SDLK_F10, PK_F10},
                                            {SDLK_F11, PK_F11},
                                            {SDLK_F12, PK_F12},
                                            {SDLK_CANCEL, PK_CANCEL},
                                            {SDLK_BACKSPACE, PK_BACK},
                                            {SDLK_TAB, PK_TAB},
                                            {SDLK_CLEAR, PK_CLEAR},
                                            {SDLK_RETURN, PK_RETURN},
                                            {SDLK_LSHIFT, PK_SHIFT},
                                            {SDLK_RSHIFT, PK_SHIFT},
                                            {SDLK_LCTRL, PK_CONTROL},
                                            {SDLK_RCTRL, PK_CONTROL},
                                            {SDLK_LALT, PK_MENU},
                                            {SDLK_CAPSLOCK, PK_CAPITAL},
                                            {SDLK_ESCAPE, PK_ESCAPE},
                                            {SDLK_SPACE, PK_SPACE},
                                            {SDLK_PAGEDOWN, PK_PRIOR},
                                            {SDLK_PAGEUP, PK_NEXT},
                                            {SDLK_END, PK_END},
                                            {SDLK_HOME, PK_HOME},
                                            {SDLK_LEFT, PK_LEFT},
                                            {SDLK_UP, PK_UP},
                                            {SDLK_RIGHT, PK_RIGHT},
                                            {SDLK_DOWN, PK_DOWN},
                                            {SDLK_INSERT, PK_INSERT},
                                            {SDLK_DELETE, PK_DELETE},
                                            {SDLK_LGUI, PK_COMMAND},
                                            {SDLK_LEFTBRACKET, PK_OPEN_BRACKET},
                                            {SDLK_RIGHTBRACKET, PK_CLOSE_BRACKET},
                                            {SDLK_COLON, PK_SEMICOLON},
                                            {SDLK_QUOTE, PK_APOSTRAPHE},
                                            {SDLK_BACKSLASH, PK_BACK_SLASH},
                                            {SDLK_SLASH, PK_FORWARD_SLASH},
                                            {SDLK_COMMA, PK_COMMA},
                                            {SDLK_PERIOD, PK_PERIOD},
                                            {SDLK_MINUS, PK_MINUS},
                                            {SDLK_EQUALS, PK_EQUAL},
                                            {0x00, PK_TILDE},
                                            {SDLK_BACKQUOTE, PK_GRAVE}};

    void handle_key_event(bool down, u32 key)
    {
        if (k_key_map.find(key) != k_key_map.end())
        {
            u32 pk = k_key_map[key];
            if (down)
            {
                pen::input_set_key_down(pk);
            }
            else
            {
                pen::input_set_key_up(pk);
            }
        }
    }

    void handle_mouse()
    {
        s32 x, y;
        u32 b = SDL_GetMouseState(&x, &y);
        input_set_mouse_pos((f32)x, (f32)y);
        if(b == SDL_BUTTON_LEFT)
        {
            input_set_mouse_down(PEN_MOUSE_L);
        }
        else
        {
            input_set_mouse_up(PEN_MOUSE_L);
        }

        if(b == SDL_BUTTON_RIGHT)
        {
            input_set_mouse_down(PEN_MOUSE_R);
        }
        else
        {
            input_set_mouse_up(PEN_MOUSE_R);
        }

        if(b == SDL_BUTTON_MIDDLE)
        {
            input_set_mouse_down(PEN_MOUSE_M);
        }
        else
        {
            input_set_mouse_up(PEN_MOUSE_M);
        }
    }

    void handle_window_resize()
    {
        if(s_ctx.pcp.window_width != get_canvas_width() || s_ctx.pcp.window_height != get_canvas_height())
        {
            s_ctx.pcp.window_width = get_canvas_width();
            s_ctx.pcp.window_height = get_canvas_height();

            if(s_ctx.surface)
                SDL_FreeSurface(s_ctx.surface);

            s_ctx.surface = SDL_SetVideoMode(s_ctx.pcp.window_width, s_ctx.pcp.window_height, 32, SDL_OPENGL | SDL_RESIZABLE);
        }
    }

    EM_BOOL run(double time, void* user_data)
    {
        SDL_PumpEvents();

        SDL_Event event;
        while( SDL_PollEvent( &event ) )
        {
            switch( event.type ){
            case SDL_KEYDOWN:
                handle_key_event(true, (u32)event.key.keysym.sym);
                break;
            case SDL_KEYUP:
                handle_key_event(false, (u32)event.key.keysym.sym);
                break;
            case SDL_MOUSEWHEEL:
                input_set_mouse_wheel(event.wheel.y);
                break;
            default:
                break;
            }
        }

        handle_mouse();
        handle_window_resize();

        pen::jobs_run_single_threaded();
        pen::renderer_dispatch();

        return EM_TRUE;
    }

    void create_sdl_surface()
    {
        SDL_Init(SDL_INIT_VIDEO);

        if(s_ctx.pcp.window_sample_count > 1)
        {
            SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
            SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, s_ctx.pcp.window_sample_count);
        }

        handle_window_resize();
    }

    void init()
    {
        create_sdl_surface();
        SDL_EnableUNICODE(1);
        timer_system_intialise();
        pen::renderer_init(nullptr, false, 1024);

        // creates user thread
        jobs_create_job(s_ctx.pcp.user_thread_function, 1024 * 1024, s_ctx.pcp.user_data, pen::e_thread_start_flags::detached);
    }
}

//
// os public api
//

namespace pen
{
    bool os_update()
    {
        return true;
    }

    void os_terminate(u32 return_code)
    {

    }

    const c8* os_path_for_resource(const c8* filename)
    {
        return filename;
    }

    const c8* window_get_title()
    {
        return s_ctx.pcp.window_title;
    }

    void window_get_size(s32& width, s32& height)
    {
        width = s_ctx.pcp.window_width;
        height = s_ctx.pcp.window_height;
    }

    f32 window_get_aspect()
    {
        return (f32)s_ctx.pcp.window_width / (f32)s_ctx.pcp.window_height;
    }

    hash_id window_get_id()
    {
        static hash_id window_id = PEN_HASH(s_ctx.pcp.window_title);
        return window_id;
    }

    void window_get_frame(window_frame& f)
    {
        f = {0, 0, s_ctx.pcp.window_width, s_ctx.pcp.window_height};
    }

    void window_set_frame(const window_frame& f)
    {

    }

    void* window_get_primary_display_handle()
    {
        return (void*)s_ctx.surface;
    }

    bool input_undo_pressed()
    {
        return false;
    }

    bool input_redo_pressed()
    {
        return false;
    }

    const user_info& os_get_user_info()
    {
        static user_info u;
        return u;
    }
}

//
// entry
//

int main()
{
  	s_ctx.pcp = pen_entry(0, nullptr);
    init();
    emscripten_request_animation_frame_loop(run, 0);
    return 0;
}
<|endoftext|>


<commit_before>//
// Script to test the dN/dEta analysis using the dNdEtaAnalysis and
// dNdEtaCorrection classes. Note that there is a cut on the events,
// so the measurement will be biassed.
//
// implementation with TSelector
//

#include "../CreateESDChain.C"

testAnalysis2(Char_t* dataDir, Int_t nRuns=20, Bool_t aMC = kFALSE)
{
  gSystem->Load("libPWG0base");

  TChain* chain = CreateESDChain(dataDir, nRuns);

  // ########################################################
  // selection of esd tracks
  AliESDtrackCuts* esdTrackCuts = new AliESDtrackCuts();
  esdTrackCuts->DefineHistograms(1);

  esdTrackCuts->SetMinNClustersTPC(50);
  esdTrackCuts->SetMaxChi2PerClusterTPC(3.5);
  esdTrackCuts->SetMaxCovDiagonalElements(2,2,0.5,0.5,2);
  esdTrackCuts->SetRequireTPCRefit(kTRUE);

  esdTrackCuts->SetMinNsigmaToVertex(3);
  esdTrackCuts->SetAcceptKingDaughters(kFALSE);

  chain->GetUserInfo()->Add(esdTrackCuts);

  if (aMC == kFALSE)
  {
    dNdEtaCorrection* dNdEtaCorrection = new dNdEtaCorrection();
    dNdEtaCorrection->LoadHistograms("correction_map.root","dndeta_correction");
    dNdEtaCorrection->RemoveEdges(2,0,2);

    chain->GetUserInfo()->Add(dNdEtaCorrection);
  }

  TString selectorName = ((aMC == kFALSE) ? "AlidNdEtaAnalysisSelector" : "AlidNdEtaAnalysisMCSelector");

  AliLog::SetClassDebugLevel(selectorName, AliLog::kInfo);

  chain->Process(selectorName + ".cxx+");
}
<commit_msg>printing the execution time<commit_after>//
// Script to test the dN/dEta analysis using the dNdEtaAnalysis and
// dNdEtaCorrection classes. Note that there is a cut on the events,
// so the measurement will be biassed.
//
// implementation with TSelector
//

#include "../CreateESDChain.C"

testAnalysis2(Char_t* dataDir, Int_t nRuns=20, Bool_t aMC = kFALSE)
{
  gSystem->Load("libPWG0base");

  TChain* chain = CreateESDChain(dataDir, nRuns);

  // ########################################################
  // selection of esd tracks
  AliESDtrackCuts* esdTrackCuts = new AliESDtrackCuts();
  esdTrackCuts->DefineHistograms(1);

  esdTrackCuts->SetMinNClustersTPC(50);
  esdTrackCuts->SetMaxChi2PerClusterTPC(3.5);
  esdTrackCuts->SetMaxCovDiagonalElements(2,2,0.5,0.5,2);
  esdTrackCuts->SetRequireTPCRefit(kTRUE);

  esdTrackCuts->SetMinNsigmaToVertex(3);
  esdTrackCuts->SetAcceptKingDaughters(kFALSE);

  chain->GetUserInfo()->Add(esdTrackCuts);

  if (aMC == kFALSE)
  {
    dNdEtaCorrection* dNdEtaCorrection = new dNdEtaCorrection();
    dNdEtaCorrection->LoadHistograms("correction_map.root","dndeta_correction");
    dNdEtaCorrection->RemoveEdges(2,0,2);

    chain->GetUserInfo()->Add(dNdEtaCorrection);
  }

  TString selectorName = ((aMC == kFALSE) ? "AlidNdEtaAnalysisSelector" : "AlidNdEtaAnalysisMCSelector");

  AliLog::SetClassDebugLevel(selectorName, AliLog::kInfo);

  TStopwatch timer;
  timer.Start();

  chain->Process(selectorName + ".cxx+");

  timer.Stop();
  timer.Print();
}
<|endoftext|>


<commit_before>AliAnalysisTaskDiJets *AddTaskDiJets()
{
// Creates a dijet task, configures it and adds it to the analysis manager.

   // Get the pointer to the existing analysis manager via the static access method.
   //==============================================================================
   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
   if (!mgr) {
      ::Error("AddTaskJets", "No analysis manager to connect to.");
      return NULL;
   }

   // Check the analysis type using the event handlers connected to the analysis manager.
   //==============================================================================
   if (!mgr->GetInputEventHandler()) {
      ::Error("AddTaskDiJets", "This task requires an input event handler");
      return NULL;
   }

   // Create the task and configure it.
   //===========================================================================

   AliAnalysisTaskDiJets *dijetana = new AliAnalysisTaskDiJets("DiJetAnalysis");
   dijetana->SetDebugLevel(10);
   mgr->AddTask(dijetana);

   AliAnalysisDataContainer *cout_dijet = mgr->CreateContainer("DiJet", TList::Class(),AliAnalysisManager::kOutputContainer,
     Form("%s:PWG4_DiJet",AliAnalysisManager::GetCommonFileName()));

   // Create ONLY the output containers for the data produced by the task.
   // Get and connect other common input/output containers via the manager as below
   //==============================================================================
   mgr->ConnectInput  (dijetana, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput (dijetana, 0, mgr->GetCommonOutputContainer());
   mgr->ConnectOutput (dijetana, 1, cout_dijet);

   return dijetana;
}
<commit_msg>Debug option set to 0<commit_after>AliAnalysisTaskDiJets *AddTaskDiJets()
{
// Creates a dijet task, configures it and adds it to the analysis manager.

   // Get the pointer to the existing analysis manager via the static access method.
   //==============================================================================
   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
   if (!mgr) {
      ::Error("AddTaskJets", "No analysis manager to connect to.");
      return NULL;
   }

   // Check the analysis type using the event handlers connected to the analysis manager.
   //==============================================================================
   if (!mgr->GetInputEventHandler()) {
      ::Error("AddTaskDiJets", "This task requires an input event handler");
      return NULL;
   }

   // Create the task and configure it.
   //===========================================================================

   AliAnalysisTaskDiJets *dijetana = new AliAnalysisTaskDiJets("DiJetAnalysis");
   dijetana->SetDebugLevel(0);
   mgr->AddTask(dijetana);

   AliAnalysisDataContainer *cout_dijet = mgr->CreateContainer("DiJet", TList::Class(),AliAnalysisManager::kOutputContainer,
     Form("%s:PWG4_DiJet",AliAnalysisManager::GetCommonFileName()));

   // Create ONLY the output containers for the data produced by the task.
   // Get and connect other common input/output containers via the manager as below
   //==============================================================================
   mgr->ConnectInput  (dijetana, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput (dijetana, 0, mgr->GetCommonOutputContainer());
   mgr->ConnectOutput (dijetana, 1, cout_dijet);

   return dijetana;
}
<|endoftext|>


<commit_before>#include "game/lane_scorer.h"

#include "game/race_tracker.h"
#include "utils/stopwatch.h"

DECLARE_bool(log_overtaking);

namespace game {

LaneScorer::LaneScorer(const Race& race,
                       CarTracker& car_tracker,
                       RaceTracker& race_tracker,
                       std::vector<EnemyTracker>& enemies,
                       const string& color)
  : race_(race), car_tracker_(car_tracker), enemies_(enemies), color_(color),
    race_tracker_(race_tracker), kCarLength(race.cars()[0].length()) {
}

LaneScorer::~LaneScorer() {
  printf("Lane scorer longest computation time: %lf ms\n", longest_calculation_time_);
}

int LaneScorer::ScoreLane(int from, int to, int lane) {
  utils::StopWatch timer;
  using std::max; using std::min;
  auto& me = *std::find_if(enemies_.begin(), enemies_.end(), [this](const EnemyTracker& e){ return e.color() == this->color_; });

  Position end_position(to, 0);
  end_position.set_start_lane(lane);
  end_position.set_end_lane(lane);

  if (FLAGS_log_overtaking)
    printf ("(%d,%.2lf,<%d,%d>) CEL\n", end_position.piece(),
                                        end_position.piece_distance(),
                                        end_position.start_lane(),
                                        end_position.end_lane());

  int lane_score = 0;
  for (auto& enemy : enemies_) {
    if (enemy.color() == color_) continue;  // Me
    int score = ScoreEnemy(me, enemy, end_position);

    if (FLAGS_log_overtaking)
      printf("Score of %s is %d\n",enemy.color().c_str(), score);

    if (score < 0)  // If we should overtake someone
      lane_score = min(lane_score, score);

    if (score > 0 && lane_score >= 0)  // If there is s1 worth bumping
      lane_score = max(lane_score, score);
  }
  if (FLAGS_continuous_integration)
    printf("Lane %d scored in %lf ms\n", lane, timer.elapsed());

  longest_calculation_time_ = max(longest_calculation_time_, timer.elapsed());
  return lane_score;
}

int LaneScorer::ScoreEnemy(const EnemyTracker& me, const EnemyTracker& enemy, const Position& end_position) {
  if (FLAGS_log_overtaking)
    printf ("(%d,%.2lf,<%d,%d> =%.2lf) (%d,%.2lf,<%d,%d> =%.2lf) ",
        me.state().position().piece(),
        me.state().position().piece_distance(),
        me.state().position().start_lane(),
        me.state().position().end_lane(),
        car_tracker_.DistanceBetween(me.state().position(), end_position),
        enemy.state().position().piece(),
        enemy.state().position().piece_distance(),
        enemy.state().position().start_lane(),
        enemy.state().position().end_lane(),
        car_tracker_.DistanceBetween(enemy.state().position(), end_position));

  // if im closer to the end, then im ahead, so ignore the guy
  //
  // Clarification in case of switching into him:
  // Its If we are closer to target, in case of switching into him,
  // we will most probably land ahead of him.
  // If we would take such car seriously, we would never have safe switch
  // if there is s1 on another lane
  if (car_tracker_.DistanceBetween(me.state().position(), end_position) <
      car_tracker_.DistanceBetween(enemy.state().position(), end_position))
    return 0;

  if (enemy.has_finished()) {
    return 0;
  }
  else if (enemy.is_dead()) {
    return ScoreDeadEnemy(me, enemy, end_position);
  }
  else {
    return ScoreLivingEnemy(me, enemy, end_position);
  }
}

int LaneScorer::ScoreDeadEnemy(const EnemyTracker& me, const EnemyTracker& enemy, const Position& end_position) {
  auto safe_position = car_tracker_.PredictPosition(enemy.state().position(), 3 * kCarLength);

  // Wont reach safe_position before spawn
  if (!me.IsReady() || me.TimeToPosition(safe_position) > enemy.time_to_spawn()) {
    return (int) kDeadCrash;
  } else {
    return 0;
  }
}

int LaneScorer::ScoreLivingEnemy(const EnemyTracker& me, const EnemyTracker& enemy, const Position& end_position) {
  // If models are ready try to predict if we will actually hit
  if (enemy.IsReady() && me.IsReady()) {
    Position bump_position;
    bool will_bump = BumpPosition(me, enemy, end_position, &bump_position);

    if (will_bump) {
      return EnemyBumpScore(enemy, me.ExpectedVelocity(bump_position), enemy.ExpectedVelocity(bump_position));
    } else {
      return 0;
    }
  } else {
    return EnemyBumpScore(enemy, me.state().velocity(), enemy.state().velocity());
  }
}

int LaneScorer::EnemyBumpScore(const EnemyTracker& enemy, double my_speed, double his_speed) {
  if (his_speed < 0.95 * my_speed) {
    return (kDeadCrash) * (1 - his_speed / my_speed);
  } else {
    return 0;
  }
  // if (race_tracker_.IsCompetitive(enemy.color()))
  //   return 10;
}

bool LaneScorer::BumpPosition(const EnemyTracker& me, const EnemyTracker& enemy, const Position& end_position, Position* bump_position) {
  vector<Position> my_prediction, enemy_prediction;
  int my_time = me.TimeToPosition(end_position, &my_prediction);
  int enemy_time = enemy.TimeToPosition(car_tracker_.PredictPosition(end_position, kCarLength * 1.1), &enemy_prediction);

  if (my_time > enemy_time)
    return false;

  // TODO can make binsearch here, worth it?
  for (int i = 0; i < min(my_prediction.size(), enemy_prediction.size()); i++) {
    auto my_position = my_prediction[i];
    auto enemy_position = enemy_prediction[i];

    if (car_tracker_.DistanceBetween(my_position, enemy_position) < kCarLength) {
      *bump_position = enemy_position;
      return true;
    }
  }

  return false;  // We havent found bump (shouldnt happen)
}

}  // namespace game
<commit_msg>Compile error...<commit_after>#include "game/lane_scorer.h"

#include "game/race_tracker.h"
#include "utils/stopwatch.h"

DECLARE_bool(log_overtaking);
DECLARE_bool(continuous_integration);

namespace game {

LaneScorer::LaneScorer(const Race& race,
                       CarTracker& car_tracker,
                       RaceTracker& race_tracker,
                       std::vector<EnemyTracker>& enemies,
                       const string& color)
  : race_(race), car_tracker_(car_tracker), enemies_(enemies), color_(color),
    race_tracker_(race_tracker), kCarLength(race.cars()[0].length()) {
}

LaneScorer::~LaneScorer() {
  printf("Lane scorer longest computation time: %lf ms\n", longest_calculation_time_);
}

int LaneScorer::ScoreLane(int from, int to, int lane) {
  utils::StopWatch timer;
  using std::max; using std::min;
  auto& me = *std::find_if(enemies_.begin(), enemies_.end(), [this](const EnemyTracker& e){ return e.color() == this->color_; });

  Position end_position(to, 0);
  end_position.set_start_lane(lane);
  end_position.set_end_lane(lane);

  if (FLAGS_log_overtaking)
    printf ("(%d,%.2lf,<%d,%d>) CEL\n", end_position.piece(),
                                        end_position.piece_distance(),
                                        end_position.start_lane(),
                                        end_position.end_lane());

  int lane_score = 0;
  for (auto& enemy : enemies_) {
    if (enemy.color() == color_) continue;  // Me
    int score = ScoreEnemy(me, enemy, end_position);

    if (FLAGS_log_overtaking)
      printf("Score of %s is %d\n",enemy.color().c_str(), score);

    if (score < 0)  // If we should overtake someone
      lane_score = min(lane_score, score);

    if (score > 0 && lane_score >= 0)  // If there is s1 worth bumping
      lane_score = max(lane_score, score);
  }
  if (FLAGS_continuous_integration)
    printf("Lane %d scored in %lf ms\n", lane, timer.elapsed());

  longest_calculation_time_ = max(longest_calculation_time_, timer.elapsed());
  return lane_score;
}

int LaneScorer::ScoreEnemy(const EnemyTracker& me, const EnemyTracker& enemy, const Position& end_position) {
  if (FLAGS_log_overtaking)
    printf ("(%d,%.2lf,<%d,%d> =%.2lf) (%d,%.2lf,<%d,%d> =%.2lf) ",
        me.state().position().piece(),
        me.state().position().piece_distance(),
        me.state().position().start_lane(),
        me.state().position().end_lane(),
        car_tracker_.DistanceBetween(me.state().position(), end_position),
        enemy.state().position().piece(),
        enemy.state().position().piece_distance(),
        enemy.state().position().start_lane(),
        enemy.state().position().end_lane(),
        car_tracker_.DistanceBetween(enemy.state().position(), end_position));

  // if im closer to the end, then im ahead, so ignore the guy
  //
  // Clarification in case of switching into him:
  // Its If we are closer to target, in case of switching into him,
  // we will most probably land ahead of him.
  // If we would take such car seriously, we would never have safe switch
  // if there is s1 on another lane
  if (car_tracker_.DistanceBetween(me.state().position(), end_position) <
      car_tracker_.DistanceBetween(enemy.state().position(), end_position))
    return 0;

  if (enemy.has_finished()) {
    return 0;
  }
  else if (enemy.is_dead()) {
    return ScoreDeadEnemy(me, enemy, end_position);
  }
  else {
    return ScoreLivingEnemy(me, enemy, end_position);
  }
}

int LaneScorer::ScoreDeadEnemy(const EnemyTracker& me, const EnemyTracker& enemy, const Position& end_position) {
  auto safe_position = car_tracker_.PredictPosition(enemy.state().position(), 3 * kCarLength);

  // Wont reach safe_position before spawn
  if (!me.IsReady() || me.TimeToPosition(safe_position) > enemy.time_to_spawn()) {
    return (int) kDeadCrash;
  } else {
    return 0;
  }
}

int LaneScorer::ScoreLivingEnemy(const EnemyTracker& me, const EnemyTracker& enemy, const Position& end_position) {
  // If models are ready try to predict if we will actually hit
  if (enemy.IsReady() && me.IsReady()) {
    Position bump_position;
    bool will_bump = BumpPosition(me, enemy, end_position, &bump_position);

    if (will_bump) {
      return EnemyBumpScore(enemy, me.ExpectedVelocity(bump_position), enemy.ExpectedVelocity(bump_position));
    } else {
      return 0;
    }
  } else {
    return EnemyBumpScore(enemy, me.state().velocity(), enemy.state().velocity());
  }
}

int LaneScorer::EnemyBumpScore(const EnemyTracker& enemy, double my_speed, double his_speed) {
  if (his_speed < 0.95 * my_speed) {
    return (kDeadCrash) * (1 - his_speed / my_speed);
  } else {
    return 0;
  }
  // if (race_tracker_.IsCompetitive(enemy.color()))
  //   return 10;
}

bool LaneScorer::BumpPosition(const EnemyTracker& me, const EnemyTracker& enemy, const Position& end_position, Position* bump_position) {
  vector<Position> my_prediction, enemy_prediction;
  int my_time = me.TimeToPosition(end_position, &my_prediction);
  int enemy_time = enemy.TimeToPosition(car_tracker_.PredictPosition(end_position, kCarLength * 1.1), &enemy_prediction);

  if (my_time > enemy_time)
    return false;

  // TODO can make binsearch here, worth it?
  for (int i = 0; i < min(my_prediction.size(), enemy_prediction.size()); i++) {
    auto my_position = my_prediction[i];
    auto enemy_position = enemy_prediction[i];

    if (car_tracker_.DistanceBetween(my_position, enemy_position) < kCarLength) {
      *bump_position = enemy_position;
      return true;
    }
  }

  return false;  // We havent found bump (shouldnt happen)
}

}  // namespace game
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2010 Digital Bazaar, Inc. All rights reserved.
 */
#include "monarch/util/StringTools.h"

#include "monarch/rt/DynamicObjectIterator.h"
#include "monarch/rt/Exception.h"
#include "monarch/util/StringTokenizer.h"

#include <cerrno>
#include <cstring>
#include <cstdarg>
#include <cstdlib>
#include <cstdio>
#include <algorithm>

using namespace std;
using namespace monarch::rt;
using namespace monarch::util;

string& StringTools::trim(string& str, const char* trimChars)
{
   // erase front trim characters
   str.erase(0, str.find_first_not_of(trimChars));

   // find back trim characters
   string::size_type last = str.find_last_not_of(trimChars);
   if(last != string::npos)
   {
      // erase back trim characters
      str.erase(last + 1);
   }

   return str;
}

string& StringTools::replace(
   string& str, const char* find, const char* replace,
   string::size_type pos)
{
   string::size_type found = str.find(find, pos);
   if(found != string::npos)
   {
      str.replace(found, strlen(find), replace);
   }
   return str;
}

string& StringTools::replaceAll(
   string& str, const char* find, const char* replace)
{
   int findLen = strlen(find);
   int replaceLen = strlen(replace);
   string::size_type found = str.find(find);
   while(found != string::npos)
   {
      str.replace(found, findLen, replace);
      found = str.find(find, found + replaceLen);
   }
   return str;
}

string& StringTools::regexReplaceAll(
   string& str, const char* regex, const char* replace, bool matchCase)
{
   // compile regex pattern
   PatternRef p = Pattern::compile(regex, matchCase, true);
   if(!p.isNull())
   {
      regexReplaceAll(str, p, replace);
   }
   return str;
}

string& StringTools::regexReplaceAll(
   string& str, PatternRef& p, const char* replace)
{
   // replace all matches
   int start, end;
   int index = 0;
   int len = strlen(replace);
   while(p->match(str.c_str(), index, start, end))
   {
      str.replace(start, end - start, replace);
      index = start + len;
   }
   return str;
}

std::string& StringTools::regexRewrite(
   std::string& str, const char* regex,
   const char* replace, bool matchCase,
   bool* matched)
{
   // compile regex pattern
   PatternRef p = Pattern::compile(regex, matchCase, true);
   if(!p.isNull())
   {
      regexRewrite(str, p, replace, matched);
   }
   return str;
}

std::string& StringTools::regexRewrite(
   std::string& str, PatternRef& p, const char* replace, bool* matched)
{
   // get sub matches
   DynamicObject subs;
   if(p->getSubMatches(str.c_str(), subs))
   {
      if(matched != NULL)
      {
         *matched = true;
      }

      // do formatted replacement
      str.erase();
      const char* ptr = replace;
      const char* v;
      do
      {
         v = strpbrk(ptr, "$\\");
         if(v == NULL)
         {
            // append remainder
            str.append(ptr);
         }
         else if(*v == '\\')
         {
            // add everything up to this point
            str.append(ptr, v - ptr);

            ++v;
            switch(*v)
            {
               case '$':
               case '\\':
                  // add escaped '$' or '\'
                  str.push_back(*v);
                  break;
               case 'b':
                  str.push_back('\b');
                  break;
               case 'n':
                  str.push_back('\n');
                  break;
               case 't':
                  str.push_back('\t');
                  break;
               case 'r':
                  str.push_back('\r');
                  break;
               default:
                  // unknown escape sequence, just add it normally
                  str.push_back('\\');
                  str.push_back(*v);
                  break;
            }
            ++v;
         }
         else
         {
            // add everything up to this point
            str.append(ptr, v - ptr);

            // check for a number
            char* end;
            int idx = strtol(++v, &end, 10);
            if(idx < subs->length())
            {
               str.append(subs[idx]->getString());
            }
            v = end;
         }
         ptr = v;
      }
      while(ptr != NULL);
   }
   else if(matched != NULL)
   {
      *matched = false;
   }

   return str;
}

bool StringTools::vsnformat(
   string& str, size_t size, const char *format, va_list varargs)
{
   // Adapted from glibc sprintf docs.

   bool rval;

   int n;
   size_t psize;
   char *p;
   char *np;

   // Guess we need no more than 128 bytes to start.
   psize = 25;
   // limit size if needed
   if(size != 0)
   {
      psize = min(psize, size);
   }

   // allocate initial buffer
   p = (char*)malloc(psize);
   rval = (p != NULL);

   bool done = false;
   while(rval && !done)
   {
      // need to copy args since they are re-used each loop
      va_list varargs_copy;
      va_copy(varargs_copy, varargs);

      // Try to print in the allocated space.
      n = vsnprintf(p, psize, format, varargs_copy);

      // clean up the copy
      va_end(varargs_copy);

      // If that worked, return the string.
      if(n > -1 && (size_t)n < psize)
      {
         str.assign(p);
         free(p);
         done = true;
      }
      else
      {
         // make sure size isn't at the limit
         // this will enable an attempt with at least 1 more byte
         if(size != 0)
         {
            rval = (size > psize);
         }

         if(rval)
         {
            // Else try again with more space.
            if(n > -1)
            {
               // glibc 2.1
               // n is precisely what is needed
               psize = n + 1;
            }
            else
            {
               // glibc 2.0
               // guess new size, but limit increase in size for huge strings
               // FIXME: check psize < (max size_t / 2) to avoid overflow
               psize = min(psize * 2, psize + 16777216 /* 16MiB */);
               // limit size if needed
               if(size != 0)
               {
                  psize = min(psize, size);
               }
            }

            // try to realloc the buffer
            np = (char*)realloc(p, psize);
            rval = (np != NULL);
            if(rval)
            {
               p = np;
            }
         }
      }
   }

   if(!rval)
   {
      if(size == psize)
      {
         // failure due to limited size request
         ExceptionRef e = new Exception(
            "String formatting size overflow error.",
            "monarch.util.StringUtils.SizeOverflowError");
         e->getDetails()["format"] = format;
         e->getDetails()["maxSize"] = (int64_t)size;
         e->getDetails()["attemptedSize"] = (int64_t)psize;
         Exception::push(e);
      }
      else
      {
         // failure due to allocation error
         ExceptionRef e = new Exception(
            "String formating memory allocation error.",
            "monarch.util.StringUtils.MemoryAllocationError");
         e->getDetails()["format"] = format;
         e->getDetails()["errno"] = errno;
         e->getDetails()["maxSize"] = (int64_t)size;
         e->getDetails()["attemptedSize"] = (int64_t)psize;
         Exception::push(e);
      }
   }

   return rval;
}

bool StringTools::vsformat(string& str, const char *format, va_list varargs)
{
   return vsnformat(str, 0, format, varargs);
}

string StringTools::vformat(const char* format, va_list varargs)
{
   string rval;
   if(!vsformat(rval, format, varargs))
   {
      // no real error handling, just clear string
      rval.clear();
   }
   return rval;
}

bool StringTools::snformat(string& str, size_t size, const char *format, ...)
{
   bool rval;

   va_list ap;
   va_start(ap, format);
   rval = vsnformat(str, size, format, ap);
   va_end(ap);

   return rval;
}

bool StringTools::sformat(string& str, const char *format, ...)
{
   bool rval;

   va_list ap;
   va_start(ap, format);
   rval = vsformat(str, format, ap);
   va_end(ap);

   return rval;
}

string StringTools::format(const char* format, ...)
{
   string rval;

   va_list ap;
   va_start(ap, format);
   rval = vformat(format, ap);
   va_end(ap);

   return rval;
}

DynamicObject StringTools::split(const char* str, const char* delimiter)
{
   DynamicObject rval;
   rval->setType(Array);

   StringTokenizer st(str, delimiter, true);
   while(st.hasNextToken())
   {
      rval->append(st.nextToken());
   }

   return rval;
}

string StringTools::join(
   DynamicObject dyno, const char* glue, int start, int end)
{
   string rval;

   if(end == -1)
   {
      end = dyno->length();
   }

   int n = 0;
   DynamicObjectIterator i = dyno.getIterator();
   while(i->hasNext())
   {
      if(n >= start && n < end)
      {
         if(rval.length() > 0)
         {
            rval.append(glue);
         }
         rval.append(i->next()->getString());
      }
      else
      {
         i->next();
      }
      ++n;
   }

   return rval;
}

string StringTools::join(DynamicObject dyno, const char* glue)
{
   string rval;

   DynamicObjectIterator i = dyno.getIterator();
   while(i->hasNext())
   {
      if(rval.length() > 0)
      {
         rval.append(glue);
      }
      rval.append(i->next()->getString());
   }

   return rval;
}

string StringTools::toUpper(const char* str)
{
   string rval = str;
   std::transform(rval.begin(), rval.end(), rval.begin(), ::toupper);
   return rval;
}

string StringTools::toLower(const char* str)
{
   string rval = str;
   std::transform(rval.begin(), rval.end(), rval.begin(), ::tolower);
   return rval;
}

string StringTools::upperCaseWords(const char* words)
{
   string rval;

   StringTokenizer st;
   st.tokenize(words, ' ');
   while(st.hasNextToken())
   {
      const char* token = st.nextToken();
      if(token[0] != '\0')
      {
         rval.push_back(' ');
         rval.push_back(::toupper(token[0]));
         rval.append(token + 1);
      }
   }

   return rval;
}
<commit_msg>Start formatting with a 256 byte.<commit_after>/*
 * Copyright (c) 2007-2010 Digital Bazaar, Inc. All rights reserved.
 */
#include "monarch/util/StringTools.h"

#include "monarch/rt/DynamicObjectIterator.h"
#include "monarch/rt/Exception.h"
#include "monarch/util/StringTokenizer.h"

#include <cerrno>
#include <cstring>
#include <cstdarg>
#include <cstdlib>
#include <cstdio>
#include <algorithm>

using namespace std;
using namespace monarch::rt;
using namespace monarch::util;

string& StringTools::trim(string& str, const char* trimChars)
{
   // erase front trim characters
   str.erase(0, str.find_first_not_of(trimChars));

   // find back trim characters
   string::size_type last = str.find_last_not_of(trimChars);
   if(last != string::npos)
   {
      // erase back trim characters
      str.erase(last + 1);
   }

   return str;
}

string& StringTools::replace(
   string& str, const char* find, const char* replace,
   string::size_type pos)
{
   string::size_type found = str.find(find, pos);
   if(found != string::npos)
   {
      str.replace(found, strlen(find), replace);
   }
   return str;
}

string& StringTools::replaceAll(
   string& str, const char* find, const char* replace)
{
   int findLen = strlen(find);
   int replaceLen = strlen(replace);
   string::size_type found = str.find(find);
   while(found != string::npos)
   {
      str.replace(found, findLen, replace);
      found = str.find(find, found + replaceLen);
   }
   return str;
}

string& StringTools::regexReplaceAll(
   string& str, const char* regex, const char* replace, bool matchCase)
{
   // compile regex pattern
   PatternRef p = Pattern::compile(regex, matchCase, true);
   if(!p.isNull())
   {
      regexReplaceAll(str, p, replace);
   }
   return str;
}

string& StringTools::regexReplaceAll(
   string& str, PatternRef& p, const char* replace)
{
   // replace all matches
   int start, end;
   int index = 0;
   int len = strlen(replace);
   while(p->match(str.c_str(), index, start, end))
   {
      str.replace(start, end - start, replace);
      index = start + len;
   }
   return str;
}

std::string& StringTools::regexRewrite(
   std::string& str, const char* regex,
   const char* replace, bool matchCase,
   bool* matched)
{
   // compile regex pattern
   PatternRef p = Pattern::compile(regex, matchCase, true);
   if(!p.isNull())
   {
      regexRewrite(str, p, replace, matched);
   }
   return str;
}

std::string& StringTools::regexRewrite(
   std::string& str, PatternRef& p, const char* replace, bool* matched)
{
   // get sub matches
   DynamicObject subs;
   if(p->getSubMatches(str.c_str(), subs))
   {
      if(matched != NULL)
      {
         *matched = true;
      }

      // do formatted replacement
      str.erase();
      const char* ptr = replace;
      const char* v;
      do
      {
         v = strpbrk(ptr, "$\\");
         if(v == NULL)
         {
            // append remainder
            str.append(ptr);
         }
         else if(*v == '\\')
         {
            // add everything up to this point
            str.append(ptr, v - ptr);

            ++v;
            switch(*v)
            {
               case '$':
               case '\\':
                  // add escaped '$' or '\'
                  str.push_back(*v);
                  break;
               case 'b':
                  str.push_back('\b');
                  break;
               case 'n':
                  str.push_back('\n');
                  break;
               case 't':
                  str.push_back('\t');
                  break;
               case 'r':
                  str.push_back('\r');
                  break;
               default:
                  // unknown escape sequence, just add it normally
                  str.push_back('\\');
                  str.push_back(*v);
                  break;
            }
            ++v;
         }
         else
         {
            // add everything up to this point
            str.append(ptr, v - ptr);

            // check for a number
            char* end;
            int idx = strtol(++v, &end, 10);
            if(idx < subs->length())
            {
               str.append(subs[idx]->getString());
            }
            v = end;
         }
         ptr = v;
      }
      while(ptr != NULL);
   }
   else if(matched != NULL)
   {
      *matched = false;
   }

   return str;
}

bool StringTools::vsnformat(
   string& str, size_t size, const char *format, va_list varargs)
{
   // Adapted from glibc sprintf docs.

   bool rval;

   int n;
   size_t psize;
   char *p;
   char *np;

   // Guess the initial size of the buffer.
   psize = 256;
   // limit size if needed
   if(size != 0)
   {
      psize = min(psize, size);
   }

   // allocate initial buffer
   p = (char*)malloc(psize);
   rval = (p != NULL);

   bool done = false;
   while(rval && !done)
   {
      // need to copy args since they are re-used each loop
      va_list varargs_copy;
      va_copy(varargs_copy, varargs);

      // Try to print in the allocated space.
      n = vsnprintf(p, psize, format, varargs_copy);

      // clean up the copy
      va_end(varargs_copy);

      // If that worked, return the string.
      if(n > -1 && (size_t)n < psize)
      {
         str.assign(p);
         free(p);
         done = true;
      }
      else
      {
         // make sure size isn't at the limit
         // this will enable an attempt with at least 1 more byte
         if(size != 0)
         {
            rval = (size > psize);
         }

         if(rval)
         {
            // Else try again with more space.
            if(n > -1)
            {
               // glibc 2.1
               // n is precisely what is needed
               psize = n + 1;
            }
            else
            {
               // glibc 2.0
               // guess new size, but limit increase in size for huge strings
               // FIXME: check psize < (max size_t / 2) to avoid overflow
               psize = min(psize * 2, psize + 16777216 /* 16MiB */);
               // limit size if needed
               if(size != 0)
               {
                  psize = min(psize, size);
               }
            }

            // try to realloc the buffer
            np = (char*)realloc(p, psize);
            rval = (np != NULL);
            if(rval)
            {
               p = np;
            }
         }
      }
   }

   if(!rval)
   {
      if(size == psize)
      {
         // failure due to limited size request
         ExceptionRef e = new Exception(
            "String formatting size overflow error.",
            "monarch.util.StringUtils.SizeOverflowError");
         e->getDetails()["format"] = format;
         e->getDetails()["maxSize"] = (int64_t)size;
         e->getDetails()["attemptedSize"] = (int64_t)psize;
         Exception::push(e);
      }
      else
      {
         // failure due to allocation error
         ExceptionRef e = new Exception(
            "String formating memory allocation error.",
            "monarch.util.StringUtils.MemoryAllocationError");
         e->getDetails()["format"] = format;
         e->getDetails()["errno"] = errno;
         e->getDetails()["maxSize"] = (int64_t)size;
         e->getDetails()["attemptedSize"] = (int64_t)psize;
         Exception::push(e);
      }
   }

   return rval;
}

bool StringTools::vsformat(string& str, const char *format, va_list varargs)
{
   return vsnformat(str, 0, format, varargs);
}

string StringTools::vformat(const char* format, va_list varargs)
{
   string rval;
   if(!vsformat(rval, format, varargs))
   {
      // no real error handling, just clear string
      rval.clear();
   }
   return rval;
}

bool StringTools::snformat(string& str, size_t size, const char *format, ...)
{
   bool rval;

   va_list ap;
   va_start(ap, format);
   rval = vsnformat(str, size, format, ap);
   va_end(ap);

   return rval;
}

bool StringTools::sformat(string& str, const char *format, ...)
{
   bool rval;

   va_list ap;
   va_start(ap, format);
   rval = vsformat(str, format, ap);
   va_end(ap);

   return rval;
}

string StringTools::format(const char* format, ...)
{
   string rval;

   va_list ap;
   va_start(ap, format);
   rval = vformat(format, ap);
   va_end(ap);

   return rval;
}

DynamicObject StringTools::split(const char* str, const char* delimiter)
{
   DynamicObject rval;
   rval->setType(Array);

   StringTokenizer st(str, delimiter, true);
   while(st.hasNextToken())
   {
      rval->append(st.nextToken());
   }

   return rval;
}

string StringTools::join(
   DynamicObject dyno, const char* glue, int start, int end)
{
   string rval;

   if(end == -1)
   {
      end = dyno->length();
   }

   int n = 0;
   DynamicObjectIterator i = dyno.getIterator();
   while(i->hasNext())
   {
      if(n >= start && n < end)
      {
         if(rval.length() > 0)
         {
            rval.append(glue);
         }
         rval.append(i->next()->getString());
      }
      else
      {
         i->next();
      }
      ++n;
   }

   return rval;
}

string StringTools::join(DynamicObject dyno, const char* glue)
{
   string rval;

   DynamicObjectIterator i = dyno.getIterator();
   while(i->hasNext())
   {
      if(rval.length() > 0)
      {
         rval.append(glue);
      }
      rval.append(i->next()->getString());
   }

   return rval;
}

string StringTools::toUpper(const char* str)
{
   string rval = str;
   std::transform(rval.begin(), rval.end(), rval.begin(), ::toupper);
   return rval;
}

string StringTools::toLower(const char* str)
{
   string rval = str;
   std::transform(rval.begin(), rval.end(), rval.begin(), ::tolower);
   return rval;
}

string StringTools::upperCaseWords(const char* words)
{
   string rval;

   StringTokenizer st;
   st.tokenize(words, ' ');
   while(st.hasNextToken())
   {
      const char* token = st.nextToken();
      if(token[0] != '\0')
      {
         rval.push_back(' ');
         rval.push_back(::toupper(token[0]));
         rval.append(token + 1);
      }
   }

   return rval;
}
<|endoftext|>


<commit_before>/**
 *  Copyright (C) 2015 Topology LP
 *  Copyright (C) 2018 Jakob Petsovits
 *  All rights reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to
 *  deal in the Software without restriction, including without limitation the
 *  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 *  sell copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  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 AND NONINFRINGEMENT.  IN NO EVENT SHALL
 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 *  IN THE SOFTWARE.
 */

#ifndef CPPCODEC_DETAIL_DATA_ACCESS
#define CPPCODEC_DETAIL_DATA_ACCESS

#include <stdint.h> // for size_t
#include <string> // for static_assert() checking that string will be optimized
#include <type_traits> // for std::enable_if and such
#include <vector> // for static_assert() checking that vector will be optimized

#include "../detail/config.hpp" // for CPPCODEC_ALWAYS_INLINE

namespace cppcodec {
namespace data {

// This file contains a number of templated data accessors that can be
// implemented in the cppcodec::data namespace for types that don't fulfill
// the default type requirements:
// For result types: init(Result&, ResultState&, size_t capacity),
//     put(Result&, ResultState&, char), finish(Result&, State&)
// For const (read-only) types: char_data(const T&)
// For both const and result types: size(const T&)

template <typename T>
CPPCODEC_ALWAYS_INLINE size_t size(const T& t) { return t.size(); }

template <typename T, size_t N>
CPPCODEC_ALWAYS_INLINE constexpr size_t size(const T (&t)[N]) noexcept {
    return N * sizeof(t[0]);
}

class general_t {};
class specific_t : public general_t {};

class empty_result_state {
    template <typename Result>
    CPPCODEC_ALWAYS_INLINE void size(const Result& result) { return size(result); }
};

// SFINAE: Generic fallback in case no specific state function applies.
template <typename Result>
CPPCODEC_ALWAYS_INLINE empty_result_state create_state(Result&, general_t)
{
    return empty_result_state();
}

//
// Generic templates for containers: Use these init()/put()/finish()
// implementations if no specialization was found.
//

template <typename Result>
CPPCODEC_ALWAYS_INLINE void init(Result& result, empty_result_state&, size_t capacity)
{
    result.resize(0);
    result.reserve(capacity);
}

template <typename Result>
CPPCODEC_ALWAYS_INLINE void finish(Result&, empty_result_state&)
{
    // Default is to push_back(), which already increases the size.
}

// For the put() default implementation, we try calling push_back() with either uint8_t or char,
// whichever compiles. Scary-fancy template magic from http://stackoverflow.com/a/1386390.
namespace fallback {
    struct flag { char c[2]; }; // sizeof > 1
    flag put_uint8(...);

    int operator,(flag, flag);
    template <typename T> void operator,(flag, T&); // map everything else to void
    char operator,(int, flag); // sizeof 1
}

template <typename Result> inline void put_uint8(Result& result, uint8_t c) { result.push_back(c); }

template <bool> struct put_impl;
template <> struct put_impl<true> { // put_uint8() available
    template<typename Result>
    static CPPCODEC_ALWAYS_INLINE void put(Result& result, uint8_t c)
    {
        put_uint8(result, c);
    }
};
template <> struct put_impl<false> { // put_uint8() not available
    template<typename Result>
    static CPPCODEC_ALWAYS_INLINE void put(Result& result, uint8_t c)
    {
        result.push_back(static_cast<char>(c));
    }
};

template <typename Result>
CPPCODEC_ALWAYS_INLINE void put(Result& result, empty_result_state&, uint8_t c)
{
    using namespace fallback;
    put_impl<sizeof(fallback::flag(), put_uint8(result, c), fallback::flag()) != 1>::put(result, c);
}

//
// Specialization for container types with direct mutable data access,
// e.g. std::vector<uint8_t>.
//
// The expected way to specialize is to draft a new xyz_result_state type and
// return an instance of it from a create_state() template specialization.
// You can then create overloads for init(), put() and finish()
// for the new result state type.
//
// If desired, a non-templated overload for both specific types
// (result & state) can be added to tailor it to that particular result type.
//

template <typename T>
constexpr auto data_is_mutable(T* t) -> decltype(t->data()[size_t(0)] = 'x', bool())
{
    return true;
}
constexpr bool data_is_mutable(...) { return false; }

template <typename Result>
class direct_data_access_result_state
{
public:
    CPPCODEC_ALWAYS_INLINE void init(Result& result, size_t capacity)
    {
        // reserve() may not actually allocate the storage right away,
        // and it isn't guaranteed that it will be untouched upon the
        //.next resize(). In that light, resize from the start and
        // slightly reduce the size at the end if necessary.
        result.resize(capacity);
    }
    CPPCODEC_ALWAYS_INLINE void put(Result& result, char c)
    {
        result.data()[m_offset++] = c;
    }
    CPPCODEC_ALWAYS_INLINE void finish(Result& result)
    {
        result.resize(m_offset);
    }
    CPPCODEC_ALWAYS_INLINE size_t size(const Result&)
    {
        return m_offset;
    }
private:
    size_t m_offset = 0;
};

// SFINAE: Select a specific state based on the result type and possible result state type.
// Implement this if direct data access (`result.data()[0] = 'x') isn't already possible
// and you want to specialize it for your own result type.
// Note: The enable_if should ideally be part of the class declaration,
//       but Visual Studio C++ will not compile it that way.
//       Have it here in the factory function instead.
template <typename Result,
          typename = typename std::enable_if<
                  data_is_mutable((Result*)nullptr)>::type>
CPPCODEC_ALWAYS_INLINE direct_data_access_result_state<Result> create_state(Result&, specific_t)
{
    return direct_data_access_result_state<Result>();
}

static_assert(std::is_same<
        decltype(create_state(*(std::vector<uint8_t>*)nullptr, specific_t())),
        direct_data_access_result_state<std::vector<uint8_t>>>::value,
        "std::vector<uint8_t> must be handled by direct_data_access_result_state");

// Specialized init(), put() and finish() functions for direct_data_access_result_state.
template <typename Result>
CPPCODEC_ALWAYS_INLINE void init(Result& result, direct_data_access_result_state<Result>& state, size_t capacity)
{
    state.init(result, capacity);
}

template <typename Result>
CPPCODEC_ALWAYS_INLINE void put(Result& result, direct_data_access_result_state<Result>& state, char c)
{
    state.put(result, c);
}

template <typename Result>
CPPCODEC_ALWAYS_INLINE void finish(Result& result, direct_data_access_result_state<Result>& state)
{
    state.finish(result);
}

//
// Specialization for container types with direct mutable array access,
// e.g. std::string. This is generally faster because bound checks are
// minimal and operator[] is more likely noexcept. In addition,
// std::string::push_back() needs to write a null character on every
// expansion, which should be more efficient when done in bulk by resize().
//
// Compared to the above, tracking an extra offset variable is cheap.
//

template <typename T>
constexpr auto array_access_is_mutable(T* t) -> decltype((*t)[size_t(0)] = 'x', bool())
{
    return true;
}
constexpr bool array_access_is_mutable(...) { return false; }

template <typename Result>
class array_access_result_state
{
public:
    CPPCODEC_ALWAYS_INLINE void init(Result& result, size_t capacity)
    {
        // reserve() may not actually allocate the storage right away,
        // and it isn't guaranteed that it will be untouched upon the
        //.next resize(). In that light, resize from the start and
        // slightly reduce the size at the end if necessary.
        result.resize(capacity);
    }
    CPPCODEC_ALWAYS_INLINE void put(Result& result, char c)
    {
        result[m_offset++] = c;
    }
    CPPCODEC_ALWAYS_INLINE void finish(Result& result)
    {
        result.resize(m_offset);
    }
    CPPCODEC_ALWAYS_INLINE size_t size(const Result&)
    {
        return m_offset;
    }
private:
    size_t m_offset = 0;
};

// SFINAE: Select a specific state based on the result type and possible result state type.
// Note: The enable_if should ideally be part of the class declaration,
//       but Visual Studio C++ will not compile it that way.
//       Have it here in the factory function instead.
template <typename Result,
          typename = typename std::enable_if<
                  !data_is_mutable((Result*)nullptr) // no more than one template option
                  && array_access_is_mutable((Result*)nullptr)>::type>
CPPCODEC_ALWAYS_INLINE array_access_result_state<Result> create_state(Result&, specific_t)
{
    return array_access_result_state<Result>();
}

#if __cplusplus < 201703L
static_assert(std::is_same<
        decltype(create_state(*(std::string*)nullptr, specific_t())),
        array_access_result_state<std::string>>::value,
        "std::string (pre-C++17) must be handled by array_access_result_state");
#else
static_assert(std::is_same<
        decltype(create_state(*(std::string*)nullptr, specific_t())),
        direct_data_access_result_state<std::string>>::value,
        "std::string (C++17 and later) must be handled by direct_data_access_result_state");
#endif

// Specialized init(), put() and finish() functions for array_access_result_state.
template <typename Result>
CPPCODEC_ALWAYS_INLINE void init(Result& result, array_access_result_state<Result>& state, size_t capacity)
{
    state.init(result, capacity);
}

template <typename Result>
CPPCODEC_ALWAYS_INLINE void put(Result& result, array_access_result_state<Result>& state, char c)
{
    state.put(result, c);
}

template <typename Result>
CPPCODEC_ALWAYS_INLINE void finish(Result& result, array_access_result_state<Result>& state)
{
    state.finish(result);
}

// char_data() is only used to read, not for result buffers.
template <typename T> inline const char* char_data(const T& t)
{
    return reinterpret_cast<const char*>(t.data());
}
template <typename T, size_t N> inline const char* char_data(const T (&t)[N]) noexcept
{
    return reinterpret_cast<const char*>(&(t[0]));
}

template <typename T> inline const uint8_t* uchar_data(const T& t)
{
    return reinterpret_cast<const uint8_t*>(char_data(t));
}

} // namespace data
} // namespace cppcodec

#endif
<commit_msg>Compile on MSVC with /std:c++17 even without /Zc:__cplusplus<commit_after>/**
 *  Copyright (C) 2015 Topology LP
 *  Copyright (C) 2018 Jakob Petsovits
 *  All rights reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to
 *  deal in the Software without restriction, including without limitation the
 *  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 *  sell copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  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 AND NONINFRINGEMENT.  IN NO EVENT SHALL
 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 *  IN THE SOFTWARE.
 */

#ifndef CPPCODEC_DETAIL_DATA_ACCESS
#define CPPCODEC_DETAIL_DATA_ACCESS

#include <stdint.h> // for size_t
#include <string> // for static_assert() checking that string will be optimized
#include <type_traits> // for std::enable_if and such
#include <vector> // for static_assert() checking that vector will be optimized

#include "../detail/config.hpp" // for CPPCODEC_ALWAYS_INLINE

namespace cppcodec {
namespace data {

// This file contains a number of templated data accessors that can be
// implemented in the cppcodec::data namespace for types that don't fulfill
// the default type requirements:
// For result types: init(Result&, ResultState&, size_t capacity),
//     put(Result&, ResultState&, char), finish(Result&, State&)
// For const (read-only) types: char_data(const T&)
// For both const and result types: size(const T&)

template <typename T>
CPPCODEC_ALWAYS_INLINE size_t size(const T& t) { return t.size(); }

template <typename T, size_t N>
CPPCODEC_ALWAYS_INLINE constexpr size_t size(const T (&t)[N]) noexcept {
    return N * sizeof(t[0]);
}

class general_t {};
class specific_t : public general_t {};

class empty_result_state {
    template <typename Result>
    CPPCODEC_ALWAYS_INLINE void size(const Result& result) { return size(result); }
};

// SFINAE: Generic fallback in case no specific state function applies.
template <typename Result>
CPPCODEC_ALWAYS_INLINE empty_result_state create_state(Result&, general_t)
{
    return empty_result_state();
}

//
// Generic templates for containers: Use these init()/put()/finish()
// implementations if no specialization was found.
//

template <typename Result>
CPPCODEC_ALWAYS_INLINE void init(Result& result, empty_result_state&, size_t capacity)
{
    result.resize(0);
    result.reserve(capacity);
}

template <typename Result>
CPPCODEC_ALWAYS_INLINE void finish(Result&, empty_result_state&)
{
    // Default is to push_back(), which already increases the size.
}

// For the put() default implementation, we try calling push_back() with either uint8_t or char,
// whichever compiles. Scary-fancy template magic from http://stackoverflow.com/a/1386390.
namespace fallback {
    struct flag { char c[2]; }; // sizeof > 1
    flag put_uint8(...);

    int operator,(flag, flag);
    template <typename T> void operator,(flag, T&); // map everything else to void
    char operator,(int, flag); // sizeof 1
}

template <typename Result> inline void put_uint8(Result& result, uint8_t c) { result.push_back(c); }

template <bool> struct put_impl;
template <> struct put_impl<true> { // put_uint8() available
    template<typename Result>
    static CPPCODEC_ALWAYS_INLINE void put(Result& result, uint8_t c)
    {
        put_uint8(result, c);
    }
};
template <> struct put_impl<false> { // put_uint8() not available
    template<typename Result>
    static CPPCODEC_ALWAYS_INLINE void put(Result& result, uint8_t c)
    {
        result.push_back(static_cast<char>(c));
    }
};

template <typename Result>
CPPCODEC_ALWAYS_INLINE void put(Result& result, empty_result_state&, uint8_t c)
{
    using namespace fallback;
    put_impl<sizeof(fallback::flag(), put_uint8(result, c), fallback::flag()) != 1>::put(result, c);
}

//
// Specialization for container types with direct mutable data access,
// e.g. std::vector<uint8_t>.
//
// The expected way to specialize is to draft a new xyz_result_state type and
// return an instance of it from a create_state() template specialization.
// You can then create overloads for init(), put() and finish()
// for the new result state type.
//
// If desired, a non-templated overload for both specific types
// (result & state) can be added to tailor it to that particular result type.
//

template <typename T>
constexpr auto data_is_mutable(T* t) -> decltype(t->data()[size_t(0)] = 'x', bool())
{
    return true;
}
constexpr bool data_is_mutable(...) { return false; }

template <typename Result>
class direct_data_access_result_state
{
public:
    CPPCODEC_ALWAYS_INLINE void init(Result& result, size_t capacity)
    {
        // reserve() may not actually allocate the storage right away,
        // and it isn't guaranteed that it will be untouched upon the
        //.next resize(). In that light, resize from the start and
        // slightly reduce the size at the end if necessary.
        result.resize(capacity);
    }
    CPPCODEC_ALWAYS_INLINE void put(Result& result, char c)
    {
        result.data()[m_offset++] = c;
    }
    CPPCODEC_ALWAYS_INLINE void finish(Result& result)
    {
        result.resize(m_offset);
    }
    CPPCODEC_ALWAYS_INLINE size_t size(const Result&)
    {
        return m_offset;
    }
private:
    size_t m_offset = 0;
};

// SFINAE: Select a specific state based on the result type and possible result state type.
// Implement this if direct data access (`result.data()[0] = 'x') isn't already possible
// and you want to specialize it for your own result type.
// Note: The enable_if should ideally be part of the class declaration,
//       but Visual Studio C++ will not compile it that way.
//       Have it here in the factory function instead.
template <typename Result,
          typename = typename std::enable_if<
                  data_is_mutable((Result*)nullptr)>::type>
CPPCODEC_ALWAYS_INLINE direct_data_access_result_state<Result> create_state(Result&, specific_t)
{
    return direct_data_access_result_state<Result>();
}

static_assert(std::is_same<
        decltype(create_state(*(std::vector<uint8_t>*)nullptr, specific_t())),
        direct_data_access_result_state<std::vector<uint8_t>>>::value,
        "std::vector<uint8_t> must be handled by direct_data_access_result_state");

// Specialized init(), put() and finish() functions for direct_data_access_result_state.
template <typename Result>
CPPCODEC_ALWAYS_INLINE void init(Result& result, direct_data_access_result_state<Result>& state, size_t capacity)
{
    state.init(result, capacity);
}

template <typename Result>
CPPCODEC_ALWAYS_INLINE void put(Result& result, direct_data_access_result_state<Result>& state, char c)
{
    state.put(result, c);
}

template <typename Result>
CPPCODEC_ALWAYS_INLINE void finish(Result& result, direct_data_access_result_state<Result>& state)
{
    state.finish(result);
}

//
// Specialization for container types with direct mutable array access,
// e.g. std::string. This is generally faster because bound checks are
// minimal and operator[] is more likely noexcept. In addition,
// std::string::push_back() needs to write a null character on every
// expansion, which should be more efficient when done in bulk by resize().
//
// Compared to the above, tracking an extra offset variable is cheap.
//

template <typename T>
constexpr auto array_access_is_mutable(T* t) -> decltype((*t)[size_t(0)] = 'x', bool())
{
    return true;
}
constexpr bool array_access_is_mutable(...) { return false; }

template <typename Result>
class array_access_result_state
{
public:
    CPPCODEC_ALWAYS_INLINE void init(Result& result, size_t capacity)
    {
        // reserve() may not actually allocate the storage right away,
        // and it isn't guaranteed that it will be untouched upon the
        //.next resize(). In that light, resize from the start and
        // slightly reduce the size at the end if necessary.
        result.resize(capacity);
    }
    CPPCODEC_ALWAYS_INLINE void put(Result& result, char c)
    {
        result[m_offset++] = c;
    }
    CPPCODEC_ALWAYS_INLINE void finish(Result& result)
    {
        result.resize(m_offset);
    }
    CPPCODEC_ALWAYS_INLINE size_t size(const Result&)
    {
        return m_offset;
    }
private:
    size_t m_offset = 0;
};

// SFINAE: Select a specific state based on the result type and possible result state type.
// Note: The enable_if should ideally be part of the class declaration,
//       but Visual Studio C++ will not compile it that way.
//       Have it here in the factory function instead.
template <typename Result,
          typename = typename std::enable_if<
                  !data_is_mutable((Result*)nullptr) // no more than one template option
                  && array_access_is_mutable((Result*)nullptr)>::type>
CPPCODEC_ALWAYS_INLINE array_access_result_state<Result> create_state(Result&, specific_t)
{
    return array_access_result_state<Result>();
}

#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
static_assert(std::is_same<
    decltype(create_state(*(std::string*)nullptr, specific_t())),
    direct_data_access_result_state<std::string>>::value,
    "std::string (C++17 and later) must be handled by direct_data_access_result_state");
#elif __cplusplus < 201703 && !defined(_MSVC_LANG) // we can't trust MSVC to set this right
static_assert(std::is_same<
        decltype(create_state(*(std::string*)nullptr, specific_t())),
        array_access_result_state<std::string>>::value,
        "std::string (pre-C++17) must be handled by array_access_result_state");
#endif

// Specialized init(), put() and finish() functions for array_access_result_state.
template <typename Result>
CPPCODEC_ALWAYS_INLINE void init(Result& result, array_access_result_state<Result>& state, size_t capacity)
{
    state.init(result, capacity);
}

template <typename Result>
CPPCODEC_ALWAYS_INLINE void put(Result& result, array_access_result_state<Result>& state, char c)
{
    state.put(result, c);
}

template <typename Result>
CPPCODEC_ALWAYS_INLINE void finish(Result& result, array_access_result_state<Result>& state)
{
    state.finish(result);
}

// char_data() is only used to read, not for result buffers.
template <typename T> inline const char* char_data(const T& t)
{
    return reinterpret_cast<const char*>(t.data());
}
template <typename T, size_t N> inline const char* char_data(const T (&t)[N]) noexcept
{
    return reinterpret_cast<const char*>(&(t[0]));
}

template <typename T> inline const uint8_t* uchar_data(const T& t)
{
    return reinterpret_cast<const uint8_t*>(char_data(t));
}

} // namespace data
} // namespace cppcodec

#endif
<|endoftext|>


<commit_before>#include <set>
#include "Mesh.hh"

namespace Amanzi {
namespace AmanziGeometry {

Mesh2D::Mesh2D(std::vector<Point>&& coords_,
               std::vector<std::vector<int> >&& cell2node_,
               std::vector<std::vector<int> >&& cell_sets_) :
    coords(std::move(coords_)),
    cell2node(std::move(cell2node_)),
    cell_sets(std::move(cell_sets_)),
    datum(2)
{
  double area_eps = 1.e-6;

  for (auto& set : cell_sets) {
    ASSERT(set.size() == cell2node.size());
  }

  nnodes = coords.size();
  ncells = cell2node.size();

  for (auto& c : cell2node) {
    Point v1(2), v2(2);
    v1.set(coords[c[1]][0] - coords[c[0]][0], coords[c[1]][1] - coords[c[0]][1]);
    v2.set(coords[c[2]][0] - coords[c[0]][0], coords[c[2]][1] - coords[c[0]][1]);
    Point cross = v1^v2;
    if (cross[0] < 0) {
      std::reverse(c.begin(), c.end());
    }
    if (std::abs(cross[0]) < area_eps) {
      std::cout << "Zero area triangle:" << std::endl
                << " " << coords[c[0]] << std::endl
                << " " << coords[c[1]] << std::endl
                << " " << coords[c[2]] << std::endl;
      ASSERT(false);
    }
  }

  for (int c=0; c!=cell2node.size(); ++c) {
    std::vector<int> c2f(3);

    std::vector<int> f1 = {cell2node[c][0], cell2node[c][1]};
    c2f[0] = face_constructor(f1, 0, c);
    std::vector<int> f2 = {cell2node[c][1], cell2node[c][2]};
    c2f[1] = face_constructor(f2, 1, c);
    std::vector<int> f3 = {cell2node[c][2], cell2node[c][0]};
    c2f[2] = face_constructor(f3, 2, c);
    cell2face.emplace_back(c2f);
  }

  // set sizes
  nfaces = face2node.size();
  ASSERT(ncells == cell2face.size());

  // set boundaries
  std::vector<int> boundary_c, boundary_f;
  for (int lcv=0; lcv!=side_face_counts.size(); ++lcv) {
    if (side_face_counts[lcv] == 1) {
      boundary_c.push_back(face_cell_when_created[lcv]);
      boundary_f.push_back(face_in_cell_when_created[lcv]);
    }
  }
  boundary_faces = std::make_pair(std::move(boundary_c),
          std::move(boundary_f));

  // normalize the nodes
  int64_t x=0., y=0.;
  for (auto& p : coords) {
    x += p[0];
    y += p[1];
  }
  datum[0] = x / coords.size();
  datum[1] = y / coords.size();
  for (auto& p : coords) {
    p[0] -= datum[0];
    p[1] -= datum[1];
  }
}

int
Mesh2D::face_constructor(const std::vector<int>& nodes,
                         int index_in_cell,
                         int cell) {

  auto h = nodes[0] > nodes[1] ? hash(nodes[1], nodes[0]) :
      hash(nodes[0],nodes[1]);

  auto match = faces_sorted.find(h);
  if (match != faces_sorted.end()) {
    int f = match->second;
    side_face_counts[f]++;
    return f;
  }

  // not already created
  int f = face2node.size();
  faces_sorted[h] = f;
  face2node.emplace_back(nodes);
  face_in_cell_when_created.push_back(index_in_cell);
  face_cell_when_created.push_back(cell);
  side_face_counts.push_back(1);
  return f;
}

Mesh3D::Mesh3D(const Mesh2D& m_, int n_layers) :
    m(m_),
    current_layer(0),
    total_layers(n_layers),
    datum(m_.datum)
{

  // reserve/allocate space
  Point d(3);
  int n_nodes = m.nnodes*(n_layers+1);
  coords.resize(n_nodes, d);

  int n_cells = n_layers * m.ncells;
  cell2face.reserve(n_cells);

  int n_faces = n_layers * m.nfaces
      + (n_layers+1)*m.ncells;
  face2node.reserve(n_faces);

  // copy the top surface coords
  std::copy(m.coords.begin(), m.coords.end(), coords.begin());

  // create the top layer of faces
  face2node.insert(face2node.end(), m.cell2node.begin(),
                   m.cell2node.end());

  std::vector<int> top_c(m.ncells, -1);
  std::vector<int> top_f(m.ncells, 0);
  for (int i=0; i!=m.ncells; ++i)
    top_c[i] = i;
  face_sets.emplace_back(std::make_pair(std::move(top_c),
          std::move(top_f)));
  face_sets_id.push_back(1);

  // move the 2d cell sets to face sets on the surface
  std::set<int> set_ids;
  for (auto& part : m.cell_sets) {
    set_ids.insert(part.begin(), part.end());
  }
  for (int sid : set_ids) {
    std::vector<int> set_cells;
    for (auto& part : m.cell_sets) {
      for (int c=0; c!=part.size(); ++c) {
        if (part[c] == sid) {
          set_cells.push_back(c);
        }
      }
    }
    std::vector<int> set_faces(set_cells.size(), 0);
    face_sets.emplace_back(std::make_pair(std::move(set_cells),
            std::move(set_faces)));
    face_sets_id.push_back(sid);
  }
}

void
Mesh3D::extrude(const std::vector<double>& dz,
                const std::vector<int>& block_ids_) {
  ASSERT(dz.size() == coords.size());
  ASSERT(block_ids_.size() == coords.size());

  // shift the coordinates
  for (int n=0; n!=m.coords.size(); ++n) {
    coords[node_structure(n, current_layer+1)] =
        coords[node_structure(n, current_layer)];
    coords[node_structure(n,current_layer+1)][2] -= dz[n];
  }

  // add side faces
  int nc = cell2face.size();
  int nf = face2node.size();

  // add the side faces
  for (int f=0; f!=m.nfaces; ++f) {
    std::vector<int> nodes =
        { node_structure(m.face2node[f][1],current_layer),
          node_structure(m.face2node[f][0],current_layer),
          node_structure(m.face2node[f][0],current_layer+1),
          node_structure(m.face2node[f][1],current_layer+1)
        };
    face2node.emplace_back(std::move(nodes));
  }

  // add the bottom faces
  for (int c=0; c!=m.ncells; ++c) {
    std::vector<int> nodes =
        { node_structure(m.cell2node[c][0],current_layer+1),
          node_structure(m.cell2node[c][1],current_layer+1),
          node_structure(m.cell2node[c][2],current_layer+1)
        };
    if (current_layer+1 == total_layers) {
      nodes = { node_structure(m.cell2node[c][2],current_layer+1),
          node_structure(m.cell2node[c][1],current_layer+1),
          node_structure(m.cell2node[c][0],current_layer+1)
        };
    }
    face2node.emplace_back(std::move(nodes));
  }

  // add the cell
  for (int c=0; c!=m.ncells; ++c) {
    // cell2face
    std::vector<int> c2f =
        {
          nf - m.ncells + c,
          nf + m.nfaces + c,
          nf + m.cell2face[c][0],
          nf + m.cell2face[c][1],
          nf + m.cell2face[c][2]
        };
    cell2face.emplace_back(c2f);
  }

  // copy over the cell sets
  block_ids.insert(block_ids.end(), block_ids_.begin(), block_ids_.end());

  // increment
  current_layer++;

  std::cout << "POST-Extruding: currently " << cell2face.size() << " cells and " << face2node.size() << " faces." << std::endl;

}

void
Mesh3D::finish_sets() {
  // create the bottom set
  std::vector<int> bottom_c(m.ncells);
  int bottom_c_begin = cell2face.size() - m.ncells;
  for (int i=0; i!=m.ncells; ++i) bottom_c[i] = i + bottom_c_begin;

  std::vector<int> bottom_f(bottom_c.size(), 1);
  face_sets.emplace_back(std::make_pair(std::move(bottom_c),
          std::move(bottom_f)));
  face_sets_id.push_back(2);

  // side sets
  int n_boundary_faces = total_layers * m.boundary_faces.first.size();
  std::vector<int> sides_c, sides_f;
  sides_c.reserve(n_boundary_faces);
  sides_f.reserve(n_boundary_faces);
  auto prism_boundary_f(m.boundary_faces.second);
  for (auto& f: prism_boundary_f) f += 2;
  for (int layer=0; layer!=total_layers; ++layer) {
    int c_start = layer*m.ncells;
    for (auto c : m.boundary_faces.first)
      sides_c.push_back(c_start + c);

    sides_f.insert(sides_f.begin(),
                   prism_boundary_f.begin(),
                   prism_boundary_f.end());
  }

  face_sets.emplace_back(std::make_pair(std::move(sides_c),
          std::move(sides_f)));
  face_sets_id.push_back(3);
}

}
}
<commit_msg>bug fix get the Asserts right...<commit_after>#include <set>
#include "Mesh.hh"

namespace Amanzi {
namespace AmanziGeometry {

Mesh2D::Mesh2D(std::vector<Point>&& coords_,
               std::vector<std::vector<int> >&& cell2node_,
               std::vector<std::vector<int> >&& cell_sets_) :
    coords(std::move(coords_)),
    cell2node(std::move(cell2node_)),
    cell_sets(std::move(cell_sets_)),
    datum(2)
{
  double area_eps = 1.e-6;

  for (auto& set : cell_sets) {
    ASSERT(set.size() == cell2node.size());
  }

  nnodes = coords.size();
  ncells = cell2node.size();

  for (auto& c : cell2node) {
    Point v1(2), v2(2);
    v1.set(coords[c[1]][0] - coords[c[0]][0], coords[c[1]][1] - coords[c[0]][1]);
    v2.set(coords[c[2]][0] - coords[c[0]][0], coords[c[2]][1] - coords[c[0]][1]);
    Point cross = v1^v2;
    if (cross[0] < 0) {
      std::reverse(c.begin(), c.end());
    }
    if (std::abs(cross[0]) < area_eps) {
      std::cout << "Zero area triangle:" << std::endl
                << " " << coords[c[0]] << std::endl
                << " " << coords[c[1]] << std::endl
                << " " << coords[c[2]] << std::endl;
      ASSERT(false);
    }
  }

  for (int c=0; c!=cell2node.size(); ++c) {
    std::vector<int> c2f(3);

    std::vector<int> f1 = {cell2node[c][0], cell2node[c][1]};
    c2f[0] = face_constructor(f1, 0, c);
    std::vector<int> f2 = {cell2node[c][1], cell2node[c][2]};
    c2f[1] = face_constructor(f2, 1, c);
    std::vector<int> f3 = {cell2node[c][2], cell2node[c][0]};
    c2f[2] = face_constructor(f3, 2, c);
    cell2face.emplace_back(c2f);
  }

  // set sizes
  nfaces = face2node.size();
  ASSERT(ncells == cell2face.size());

  // set boundaries
  std::vector<int> boundary_c, boundary_f;
  for (int lcv=0; lcv!=side_face_counts.size(); ++lcv) {
    if (side_face_counts[lcv] == 1) {
      boundary_c.push_back(face_cell_when_created[lcv]);
      boundary_f.push_back(face_in_cell_when_created[lcv]);
    }
  }
  boundary_faces = std::make_pair(std::move(boundary_c),
          std::move(boundary_f));

  // normalize the nodes
  int64_t x=0., y=0.;
  for (auto& p : coords) {
    x += p[0];
    y += p[1];
  }
  datum[0] = x / coords.size();
  datum[1] = y / coords.size();
  for (auto& p : coords) {
    p[0] -= datum[0];
    p[1] -= datum[1];
  }
}

int
Mesh2D::face_constructor(const std::vector<int>& nodes,
                         int index_in_cell,
                         int cell) {

  auto h = nodes[0] > nodes[1] ? hash(nodes[1], nodes[0]) :
      hash(nodes[0],nodes[1]);

  auto match = faces_sorted.find(h);
  if (match != faces_sorted.end()) {
    int f = match->second;
    side_face_counts[f]++;
    return f;
  }

  // not already created
  int f = face2node.size();
  faces_sorted[h] = f;
  face2node.emplace_back(nodes);
  face_in_cell_when_created.push_back(index_in_cell);
  face_cell_when_created.push_back(cell);
  side_face_counts.push_back(1);
  return f;
}

Mesh3D::Mesh3D(const Mesh2D& m_, int n_layers) :
    m(m_),
    current_layer(0),
    total_layers(n_layers),
    datum(m_.datum)
{

  // reserve/allocate space
  Point d(3);
  int n_nodes = m.nnodes*(n_layers+1);
  coords.resize(n_nodes, d);

  int n_cells = n_layers * m.ncells;
  cell2face.reserve(n_cells);

  int n_faces = n_layers * m.nfaces
      + (n_layers+1)*m.ncells;
  face2node.reserve(n_faces);

  // copy the top surface coords
  std::copy(m.coords.begin(), m.coords.end(), coords.begin());

  // create the top layer of faces
  face2node.insert(face2node.end(), m.cell2node.begin(),
                   m.cell2node.end());

  std::vector<int> top_c(m.ncells, -1);
  std::vector<int> top_f(m.ncells, 0);
  for (int i=0; i!=m.ncells; ++i)
    top_c[i] = i;
  face_sets.emplace_back(std::make_pair(std::move(top_c),
          std::move(top_f)));
  face_sets_id.push_back(1);

  // move the 2d cell sets to face sets on the surface
  std::set<int> set_ids;
  for (auto& part : m.cell_sets) {
    set_ids.insert(part.begin(), part.end());
  }
  for (int sid : set_ids) {
    std::vector<int> set_cells;
    for (auto& part : m.cell_sets) {
      for (int c=0; c!=part.size(); ++c) {
        if (part[c] == sid) {
          set_cells.push_back(c);
        }
      }
    }
    std::vector<int> set_faces(set_cells.size(), 0);
    face_sets.emplace_back(std::make_pair(std::move(set_cells),
            std::move(set_faces)));
    face_sets_id.push_back(sid);
  }
}

void
Mesh3D::extrude(const std::vector<double>& dz,
                const std::vector<int>& block_ids_) {
  ASSERT(dz.size() == m.coords.size());
  ASSERT(block_ids_.size() == m.cell2node.size());

  // shift the coordinates
  for (int n=0; n!=m.coords.size(); ++n) {
    coords[node_structure(n, current_layer+1)] =
        coords[node_structure(n, current_layer)];
    coords[node_structure(n,current_layer+1)][2] -= dz[n];
  }

  // add side faces
  int nc = cell2face.size();
  int nf = face2node.size();

  // add the side faces
  for (int f=0; f!=m.nfaces; ++f) {
    std::vector<int> nodes =
        { node_structure(m.face2node[f][1],current_layer),
          node_structure(m.face2node[f][0],current_layer),
          node_structure(m.face2node[f][0],current_layer+1),
          node_structure(m.face2node[f][1],current_layer+1)
        };
    face2node.emplace_back(std::move(nodes));
  }

  // add the bottom faces
  for (int c=0; c!=m.ncells; ++c) {
    std::vector<int> nodes =
        { node_structure(m.cell2node[c][0],current_layer+1),
          node_structure(m.cell2node[c][1],current_layer+1),
          node_structure(m.cell2node[c][2],current_layer+1)
        };
    if (current_layer+1 == total_layers) {
      nodes = { node_structure(m.cell2node[c][2],current_layer+1),
          node_structure(m.cell2node[c][1],current_layer+1),
          node_structure(m.cell2node[c][0],current_layer+1)
        };
    }
    face2node.emplace_back(std::move(nodes));
  }

  // add the cell
  for (int c=0; c!=m.ncells; ++c) {
    // cell2face
    std::vector<int> c2f =
        {
          nf - m.ncells + c,
          nf + m.nfaces + c,
          nf + m.cell2face[c][0],
          nf + m.cell2face[c][1],
          nf + m.cell2face[c][2]
        };
    cell2face.emplace_back(c2f);
  }

  // copy over the cell sets
  block_ids.insert(block_ids.end(), block_ids_.begin(), block_ids_.end());

  // increment
  current_layer++;

  std::cout << "POST-Extruding: currently " << cell2face.size() << " cells and " << face2node.size() << " faces." << std::endl;

}

void
Mesh3D::finish_sets() {
  // create the bottom set
  std::vector<int> bottom_c(m.ncells);
  int bottom_c_begin = cell2face.size() - m.ncells;
  for (int i=0; i!=m.ncells; ++i) bottom_c[i] = i + bottom_c_begin;

  std::vector<int> bottom_f(bottom_c.size(), 1);
  face_sets.emplace_back(std::make_pair(std::move(bottom_c),
          std::move(bottom_f)));
  face_sets_id.push_back(2);

  // side sets
  int n_boundary_faces = total_layers * m.boundary_faces.first.size();
  std::vector<int> sides_c, sides_f;
  sides_c.reserve(n_boundary_faces);
  sides_f.reserve(n_boundary_faces);
  auto prism_boundary_f(m.boundary_faces.second);
  for (auto& f: prism_boundary_f) f += 2;
  for (int layer=0; layer!=total_layers; ++layer) {
    int c_start = layer*m.ncells;
    for (auto c : m.boundary_faces.first)
      sides_c.push_back(c_start + c);

    sides_f.insert(sides_f.begin(),
                   prism_boundary_f.begin(),
                   prism_boundary_f.end());
  }

  face_sets.emplace_back(std::make_pair(std::move(sides_c),
          std::move(sides_f)));
  face_sets_id.push_back(3);
}

}
}
<|endoftext|>


<commit_before><commit_msg>Avoid loplugin:redundantcast in non-debug build<commit_after><|endoftext|>