<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: swdet2.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-27 12:41:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#define _SWLIB_CXX

#ifndef _SFX_OBJFAC_HXX //autogen
#include <sfx2/docfac.hxx>
#endif
#ifndef _SFX_DOCFILT_HACK_HXX //autogen
#include <sfx2/docfilt.hxx>
#endif
#ifndef _SFX_FCONTNR_HXX //autogen
#include <sfx2/fcontnr.hxx>
#endif
#ifndef _SFXDOCFILE_HXX //autogen
#include <sfx2/docfile.hxx>
#endif
#ifndef _SFXAPP_HXX //autogen
#include <sfx2/app.hxx>
#endif
#ifndef _SFXECODE_HXX
#include <svtools/sfxecode.hxx>
#endif
#ifndef _MSGBOX_HXX //autogen
#include <vcl/msgbox.hxx>
#endif
#ifndef _PARHTML_HXX //autogen
#include <svtools/parhtml.hxx>
#endif
#include <sot/clsids.hxx>

#ifndef _SHELLIO_HXX //autogen
#include <shellio.hxx>
#endif

#undef _DLL_

#include <swdetect.hxx>
#include "iodetect.cxx"

#include <app.hrc>
#include <web.hrc>
#include <globdoc.hrc>

#include <svtools/moduleoptions.hxx>

#include <unomid.h>

USHORT AutoDetec( const String& FileName, USHORT & rVersion );

bool IsDocShellRegistered()
{
    return SvtModuleOptions().IsWriter();
}

extern const char __FAR_DATA sHTML[];

//-------------------------------------------------------------------------

ULONG SwFilterDetect::DetectFilter( SfxMedium& rMedium, const SfxFilter** ppFilter )
{
    ULONG nRet = ERRCODE_NONE;
    if( *ppFilter )
    {
        // verify the given filter
        String aPrefFlt = (*ppFilter)->GetUserData();

        // detection for TextFilter needs an additional checking
        BOOL bTxtFilter = aPrefFlt.EqualsAscii( FILTER_TEXT, 0, 4 );
        BOOL bDetected = SwIoSystem::IsFileFilter( rMedium, aPrefFlt );
        if (!bTxtFilter && bDetected )
            return nRet;
        else if (bTxtFilter)
        {
            // #50498#: SWDOS uses "txt" extension - so a file detected as "Text" could
            // also be an SWDOS file
            if (SwIoSystem::IsFileFilter( rMedium, C2S("SW6"), ppFilter))
                return nRet;
        }
        else if ( !bDetected )
            // mba: don't guess filters, only verify it
            return ERRCODE_ABORT;
    }

    // mba: without preselection there is no PrefFlt
    String aPrefFlt;
    const SfxFilter* pTmp = SwIoSystem::GetFileFilter( rMedium.GetPhysicalName(), aPrefFlt, &rMedium );
    if( !pTmp )
        return ERRCODE_ABORT;
    /*
    else if( *ppFilter && (*ppFilter)->GetUserData().EqualsAscii( "W4W", 0, 3 )
                && pTmp->GetUserData().EqualsAscii( FILTER_TEXT, 0, 4 ) )
    {
        // Bug 95262 - if the user (or short  detect) select a
        //              Word 4 Word filter, but the autodect of mastersoft
        //              can't detect it, we normally return the ascii filter
        //              But the user may have a change to use the W4W filter,
        //              so the SFX must show now a dialog with the 2 filters
        nRet = ERRCODE_SFX_CONSULTUSER;
        *ppFilter = pTmp;
    } */

    // sollte der voreingestellte Filter ASCII sein und wir haben
    // ASCII erkannt, dann ist das ein gultiger Filter, ansonsten ist das
    // ein Fehler und wir wollen die Filterbox sehen
    /*
    else if( pTmp->GetUserData().EqualsAscii( FILTER_TEXT ) )
    {
        // Bug 28974: "Text" erkannt, aber "Text Dos" "Text ..." eingestellt
        //  -> keine FilterBox, sondern den eingestellten Filter benutzen
        if( *ppFilter && (*ppFilter)->GetUserData().EqualsAscii( FILTER_TEXT, 0, 4 ) )
            ;
        else
//          if( !*ppFilter || COMPARE_EQUAL != pTmp->GetUserData().Compare((*ppFilter)->GetUserData(), 4 ))
        {
//              nRet = ERRCODE_ABORT;
            *ppFilter = pTmp;
        }
    } */
    else
    {
        //Bug 41417: JP 09.07.97: HTML documents should be loaded by WebWriter
        SfxFilterContainer aFilterContainer( String::CreateFromAscii("swriter/web") );
        if( pTmp->GetUserData() != C2S(sHTML) ||
            String::CreateFromAscii( "com.sun.star.text.WebDocument" ) ==
            String( pTmp->GetServiceName() ) ||
            0 == ( (*ppFilter) = SwIoSystem::GetFilterOfFormat( C2S(sHTML),
                    &aFilterContainer ) ) )
            *ppFilter = pTmp;
    }

    return nRet;
}

<commit_msg>INTEGRATION: CWS os103 (1.10.468); FILE MERGED 2007/10/01 09:40:59 os 1.10.468.3: #i54127# unused variable 2007/10/01 07:05:07 os 1.10.468.2: RESYNC: (1.10-1.11); FILE MERGED 2007/09/12 11:08:17 os 1.10.468.1: #i54127# special (wrong) handling of SW6 file format removed<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: swdet2.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: rt $ $Date: 2007-11-06 16:27:55 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#define _SWLIB_CXX

#ifndef _SFX_OBJFAC_HXX //autogen
#include <sfx2/docfac.hxx>
#endif
#ifndef _SFX_DOCFILT_HACK_HXX //autogen
#include <sfx2/docfilt.hxx>
#endif
#ifndef _SFX_FCONTNR_HXX //autogen
#include <sfx2/fcontnr.hxx>
#endif
#ifndef _SFXDOCFILE_HXX //autogen
#include <sfx2/docfile.hxx>
#endif
#ifndef _SFXAPP_HXX //autogen
#include <sfx2/app.hxx>
#endif
#ifndef _SFXECODE_HXX
#include <svtools/sfxecode.hxx>
#endif
#ifndef _MSGBOX_HXX //autogen
#include <vcl/msgbox.hxx>
#endif
#ifndef _PARHTML_HXX //autogen
#include <svtools/parhtml.hxx>
#endif
#include <sot/clsids.hxx>

#ifndef _SHELLIO_HXX //autogen
#include <shellio.hxx>
#endif

#undef _DLL_

#include <swdetect.hxx>
#include "iodetect.cxx"

#include <app.hrc>
#include <web.hrc>
#include <globdoc.hrc>

#include <svtools/moduleoptions.hxx>

#include <unomid.h>

USHORT AutoDetec( const String& FileName, USHORT & rVersion );

bool IsDocShellRegistered()
{
    return SvtModuleOptions().IsWriter();
}

extern const char __FAR_DATA sHTML[];

//-------------------------------------------------------------------------

ULONG SwFilterDetect::DetectFilter( SfxMedium& rMedium, const SfxFilter** ppFilter )
{
    ULONG nRet = ERRCODE_NONE;
    if( *ppFilter )
    {
        // verify the given filter
        String aPrefFlt = (*ppFilter)->GetUserData();

        // detection for TextFilter needs an additional checking
        BOOL bDetected = SwIoSystem::IsFileFilter( rMedium, aPrefFlt );
        return bDetected ? nRet : ERRCODE_ABORT;
    }

    // mba: without preselection there is no PrefFlt
    String aPrefFlt;
    const SfxFilter* pTmp = SwIoSystem::GetFileFilter( rMedium.GetPhysicalName(), aPrefFlt, &rMedium );
    if( !pTmp )
        return ERRCODE_ABORT;
    /*
    else if( *ppFilter && (*ppFilter)->GetUserData().EqualsAscii( "W4W", 0, 3 )
                && pTmp->GetUserData().EqualsAscii( FILTER_TEXT, 0, 4 ) )
    {
        // Bug 95262 - if the user (or short  detect) select a
        //              Word 4 Word filter, but the autodect of mastersoft
        //              can't detect it, we normally return the ascii filter
        //              But the user may have a change to use the W4W filter,
        //              so the SFX must show now a dialog with the 2 filters
        nRet = ERRCODE_SFX_CONSULTUSER;
        *ppFilter = pTmp;
    } */

    // sollte der voreingestellte Filter ASCII sein und wir haben
    // ASCII erkannt, dann ist das ein gultiger Filter, ansonsten ist das
    // ein Fehler und wir wollen die Filterbox sehen
    /*
    else if( pTmp->GetUserData().EqualsAscii( FILTER_TEXT ) )
    {
        // Bug 28974: "Text" erkannt, aber "Text Dos" "Text ..." eingestellt
        //  -> keine FilterBox, sondern den eingestellten Filter benutzen
        if( *ppFilter && (*ppFilter)->GetUserData().EqualsAscii( FILTER_TEXT, 0, 4 ) )
            ;
        else
//          if( !*ppFilter || COMPARE_EQUAL != pTmp->GetUserData().Compare((*ppFilter)->GetUserData(), 4 ))
        {
//              nRet = ERRCODE_ABORT;
            *ppFilter = pTmp;
        }
    } */
    else
    {
        //Bug 41417: JP 09.07.97: HTML documents should be loaded by WebWriter
        SfxFilterContainer aFilterContainer( String::CreateFromAscii("swriter/web") );
        if( pTmp->GetUserData() != C2S(sHTML) ||
            String::CreateFromAscii( "com.sun.star.text.WebDocument" ) ==
            String( pTmp->GetServiceName() ) ||
            0 == ( (*ppFilter) = SwIoSystem::GetFilterOfFormat( C2S(sHTML),
                    &aFilterContainer ) ) )
            *ppFilter = pTmp;
    }

    return nRet;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: wolesh.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 23:38:10 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#include "itemdef.hxx"

#ifndef _SFXAPP_HXX //autogen
#include <sfx2/app.hxx>
#endif
#ifndef _SFXOBJFACE_HXX //autogen
#include <sfx2/objface.hxx>
#endif
#ifndef _SVX_SRCHITEM_HXX //autogen
#include <svx/srchitem.hxx>
#endif

#include "wrtsh.hxx"
#include "view.hxx"
#include "helpid.h"
#include "globals.hrc"
#include "web.hrc"
#include "popup.hrc"
#include "shells.hrc"
#include "wolesh.hxx"
#include "cmdid.h"

#define SwWebOleShell
#include "swslots.hxx"

SFX_IMPL_INTERFACE(SwWebOleShell, SwOleShell, SW_RES(STR_SHELLNAME_OBJECT))
{
    SFX_POPUPMENU_REGISTRATION(SW_RES(MN_OLE_POPUPMENU));
    SFX_OBJECTBAR_REGISTRATION(SFX_OBJECTBAR_OBJECT, SW_RES(RID_WEBOLE_TOOLBOX));
}

SwWebOleShell::SwWebOleShell(SwView &rView) :
    SwOleShell(rView)

{
    SetName(String::CreateFromAscii("Object"));
    SetHelpId(SW_OLESHELL);
}

__EXPORT SwWebOleShell::~SwWebOleShell()
{
}

<commit_msg>INTEGRATION: CWS swwarnings (1.6.222); FILE MERGED 2007/03/26 12:09:38 tl 1.6.222.1: #i69287# warning-free code<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: wolesh.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-27 12:51:33 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#include "itemdef.hxx"

#ifndef _SFXAPP_HXX //autogen
#include <sfx2/app.hxx>
#endif
#ifndef _SFXOBJFACE_HXX //autogen
#include <sfx2/objface.hxx>
#endif
#ifndef _SVX_SRCHITEM_HXX //autogen
#include <svx/srchitem.hxx>
#endif

#include "wrtsh.hxx"
#include "view.hxx"
#include "helpid.h"
#include "globals.hrc"
#include "web.hrc"
#include "popup.hrc"
#include "shells.hrc"
#include "wolesh.hxx"
#include "cmdid.h"

#define SwWebOleShell
#include "swslots.hxx"

SFX_IMPL_INTERFACE(SwWebOleShell, SwOleShell, SW_RES(STR_SHELLNAME_OBJECT))
{
    SFX_POPUPMENU_REGISTRATION(SW_RES(MN_OLE_POPUPMENU));
    SFX_OBJECTBAR_REGISTRATION(SFX_OBJECTBAR_OBJECT, SW_RES(RID_WEBOLE_TOOLBOX));
}

SwWebOleShell::SwWebOleShell(SwView &_rView) :
    SwOleShell(_rView)

{
    SetName(String::CreateFromAscii("Object"));
    SetHelpId(SW_OLESHELL);
}

__EXPORT SwWebOleShell::~SwWebOleShell()
{
}

<|endoftext|>


<commit_before>// Copyright Hugh Perkins 2016

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cocl_memory.h"

#include "hostside_opencl_funcs.h"

#include <iostream>
#include <memory>
#include <vector>
#include <map>
#include <set>

// #include "EasyCL.h"

#include "CL/cl.h"

using namespace std;
using namespace cocl;
using namespace easycl;

extern "C" {
    size_t cudaMalloc(cocl::PMemory *pmem, size_t N);
    size_t cuMemAlloc_v2(cocl::PMemory *pmem, size_t bytes);
    size_t cuMemFree_v2(cocl::PMemory mem);
    size_t cudaFree(cocl::PMemory pmem);

    size_t cuMemHostAlloc(cocl::PMemory *pmem, unsigned int bytes, int CU_MEMHOSTALLOC_PORTABLE);
    size_t cuMemFreeHost(cocl::PMemory mem);

    size_t cudaMemsetAsync(void *devPtr, int value, size_t count, void *stream = 0);
    size_t cudaMemcpy(void *dst, const void *, size_t, size_t cudaMemcpyKind);
    size_t cudaMemcpyAsync (void *dst, const void *src, size_t count, size_t kind, void *stream = 0);
    size_t cuMemGetInfo_v2(size_t *free, size_t *total);
    size_t cuMemsetD8_v2(void *location, unsigned char value, uint32_t count);
    size_t cuMemsetD32_v2(void *location, unsigned int value, uint32_t count);
    size_t cuMemcpyHtoD_v2(void *gpu_dst, void *host_src, size_t size);
    size_t cuMemcpyDtoH_v2(void *host_dst, void *gpu_src, size_t size);
    size_t cuMemcpyHtoD(void *gpu_dst, void *host_src, size_t size);
    size_t cuMemcpyDtoH(void *host_dst, void *gpu_src, size_t size);
    size_t cuMemcpyHtoDAsync_v2(void *gpu_dst, void *host_src, size_t size);
    size_t cuMemcpyDtoHAsync_v2(void *host_dst, void *gpu_src, size_t size);

    size_t cuDeviceTotalMem_v2(uint64_t *value, void *device);
}

namespace cocl {
    map<void *, Memory *> memoryByHostPointer;
    // map<cl_mem, Memory *> memoryByClmem;

    // int nextIdx = 0;
    // map<int, cl_mem> clmemByIdx;  // seems like we could just merge these two maps :-P
    // map<void *, int> idxByAddr;
    // map<cl_mem, int> sizeByClmem;  // for mapped buffers mostly, ofr now

    // set<cl_mem> clmemNeedsMap;

    Memory::Memory(cl_mem clmem, size_t bytes, MemoryType type) :
            clmem(clmem), bytes(bytes), type(type) {
    }

    Memory *Memory::newPinned(size_t bytes) {
        cout << "Memory allocating new pinned memory object" << endl;
        cl_int err;
        cl_mem clmem = clCreateBuffer(*ctx, CL_MEM_ALLOC_HOST_PTR, bytes,
                                               NULL, &err);
        cl->checkError(err);
        Memory *memory = new Memory(clmem, bytes, MemoryType::Pinned);
        memory->hostPointer = memory->map();

        // memoryByClmem[memory->clmem] = memory;
        memoryByHostPointer[memory->hostPointer] = memory;
        return memory;
    }

    Memory *Memory::newDeviceAlloc(size_t bytes) {
        cout << "Memory allocating new device memory object" << endl;
        cl_int err;
        cl_mem clmem = clCreateBuffer(*ctx, CL_MEM_READ_WRITE, bytes,
                                               NULL, &err);
        cl->checkError(err);
        Memory *memory = new Memory(clmem, bytes, MemoryType::Device);
        memory->hostPointer = memory;

        // memoryByClmem[memory->clmem] = memory;
        memoryByHostPointer[memory->hostPointer] = memory;

        return memory;
    }

    Memory::~Memory() {
        cout << "~Memory releasing mem object" << endl;
        cl_int err = clReleaseMemObject(clmem);
        cl->checkError(err);
    }

    void *Memory::map() {
        cout << "Memory calling map" << endl;
        cl_int err;
        hostPointer = clEnqueueMapBuffer(*queue,
            clmem,
            CL_FALSE,
            CL_MAP_READ | CL_MAP_WRITE,
            0,
            bytes,
            0,
            0,
            0,
            &err
        );
        cl->checkError(err);
        cout << "Memory after map hostpoiner=" << hostPointer << endl;
        return hostPointer;
    }

    void Memory::unmap() {
        cl_int err = clEnqueueUnmapMemObject (
            *queue,
            clmem,
            hostPointer,
            0,
            0,
            0
        );
        cl->checkError(err);
    }
}

size_t cuMemHostAlloc(PMemory *ppMemory, unsigned int bytes, int CU_MEMHOSTALLOC_PORTABLE) {
    cout << "cuMemHostAlloc redirected bytes=" << bytes << endl;
    hostside_opencl_funcs_assure_initialized();
    cout << "cuMemHostAlloc using cl, size " << bytes << endl;
    Memory *memory = Memory::newPinned(bytes);
    // cl_mem float_data_gpu = clCreateBuffer(*ctx, CL_MEM_ALLOC_HOST_PTR, bytes,
    //                                        NULL, &err);
    // Memory *memory = new Memory(float_data_gpu, bytes);
    // cl->checkError(err);
    // int idx = nextIdx;
    // nextIdx++;
    // clmemByIdx[idx] = float_data_gpu;
    // clmems.push_back(float_data_gpu);
    // int idx = clmems.size() - 1;
    // *p_mem = (float *)&clmems[idx];

    // *p_mem = clEnqueueMapBuffer (*queue,
    //     float_data_gpu,
    //     CL_FALSE,
    //     CL_MAP_READ | CL_MAP_WRITE,
    //     0,
    //     bytes,
    //     0,
    //     0,
    //     0,
    //     &err
    // );
    // cl->checkError(err);
    // cout << "cuMemHostAlloc after map: " << *p_mem << endl;

    // memoryByHostpointer[memory->hostPointer] = memory;
    *ppMemory = memory;

    // idxByAddr[*p_mem] = idx;
    // cout << "ptr " << *p_mem << " idx=" << idx << endl;
    // clmemNeedsMap.insert(memory->clmem);
    // sizeByClmem[float_data_gpu] = bytes;

    // CL_MEM_ALLOC_HOST_PTR ?
    return 0;
}

size_t cuMemFreeHost(void *mem) {
    cout << "cuMemFreeHost redirected" << endl;
    return 0;
}

size_t cuMemGetInfo_v2(size_t *free, size_t *total) {
    cout << "cuMemGetInfo_v2 redirected" << endl;
    *free = 1024 * 1024;
    *total = 1024 * 1024;
    return 0;
}

size_t cudaMemcpyAsync (void *dst, const void *src, size_t count, size_t cudaMemcpyKind, void *stream) {
    cout << "cudaMemcpyAsync count=" << count << " cudaMemcpyKind=" << cudaMemcpyKind << " stream=" << stream << endl;

    assert(stream == 0);

    cout << "cudamempcy using opencl cudaMemcpyKind " << cudaMemcpyKind << " count=" << count << endl;
    // if(cudaMemcpyKind == 2) {
    //     // device => host
    //     int srcidx = idxByAddr[(void *)src];
    //     cl_mem srcclmem = clmemByIdx[srcidx];
    //     err = clEnqueueReadBuffer(*queue, srcclmem, CL_TRUE, 0,
    //                                      count, dst, 0, NULL, NULL);
    //     cl->checkError(err);
    //     // cl->finish();
    // } else if(cudaMemcpyKind == 1) {
    //     // host => device
    //     int dstidx = idxByAddr[(void *)dst];
    //     cl_mem dstclmem = clmemByIdx[dstidx];
    //     err = clEnqueueWriteBuffer(*queue, dstclmem, CL_TRUE, 0,
    //                                       count, src, 0, NULL, NULL);
    //     cl->checkError(err);
    // } else {
    //     cout << "cudaMemcpyKind using opencl " << cudaMemcpyKind << endl;
    //     throw runtime_error("unhandled cudaMemcpyKind");
    // }

    return 0;
}

size_t cudaMemsetAsync(void *devPtr, int value, size_t count, void *stream) {
    cout << "cudaMemsetAsync stub value=" << value << " count=" << count << " stream=" << stream << endl;
    assert(stream == 0);

    return 0;
}

size_t cuMemsetD8_v2(void *location, unsigned char value, uint32_t count) {
    cout << "cuMemsetD8_v2 redirected value " << value << " count=" << count << endl;
    // cl_int err = clEnqueueFillBuffer(*queue, *voidStarToClmem(location), &value, sizeof(unsigned char), 0, count * sizeof(unsigned char), 0, 0, 0);
    // cl->checkError(err);
    return 0;
}

size_t cuMemsetD32_v2(void *location, unsigned int value, uint32_t count) {
    cout << "cuMemsetD32_v2 redirected value " << value << " count=" << count << endl;
    // cl_int err = clEnqueueFillBuffer(*queue, *voidStarToClmem(location), &value, sizeof(int), 0, count * sizeof(int), 0, 0, 0);
    // cl->checkError(err);
    return 0;
}

size_t cuDeviceTotalMem_v2(uint64_t *value, void *device) {
    cout << "cuDeviceTotalMem_v2 redirected" << endl;
    *value = 1024 * 1024;
    return 0;
}

size_t cudaMemcpy(void *dst, const void *src, size_t bytes, size_t cudaMemcpyKind) {
    cout << "cudamempcy using opencl cudaMemcpyKind " << cudaMemcpyKind << " count=" << bytes << endl;
    // if(cudaMemcpyKind == 2) {
    //     // device => host
    //     int srcidx = idxByAddr[(void *)src];
    //     cl_mem srcclmem = clmemByIdx[srcidx];
    //     err = clEnqueueReadBuffer(*queue, srcclmem, CL_TRUE, 0,
    //                                      bytes, dst, 0, NULL, NULL);
    //     cl->checkError(err);
    //     // cl->finish();
    // } else if(cudaMemcpyKind == 1) {
    //     // host => device
    //     int dstidx = idxByAddr[(void *)dst];
    //     cl_mem dstclmem = clmemByIdx[dstidx];
    //     err = clEnqueueWriteBuffer(*queue, dstclmem, CL_TRUE, 0,
    //                                       bytes, src, 0, NULL, NULL);
    //     cl->checkError(err);
    // } else {
    //     cout << "cudaMemcpyKind using opencl " << cudaMemcpyKind << endl;
    //     throw runtime_error("unhandled cudaMemcpyKind");
    // }
    return 0;
}

size_t cudaMalloc(PMemory *ppMemory, size_t N) {
    hostside_opencl_funcs_assure_initialized();
    cout << "cudaMalloc using cl, size " << N << endl;
    Memory *memory = Memory::newDeviceAlloc(N);
    // memoryByHostpointer[memory->hostPointer] = memory;
    *ppMemory = memory;

    // cl_mem float_data_gpu = clCreateBuffer(*ctx, CL_MEM_READ_WRITE, N,
    //                                        NULL, &err);
    // cl->checkError(err);
    // int idx = nextIdx;
    // nextIdx++;
    // clmemByIdx[idx] = float_data_gpu;
    // // int idx = clmems.size() - 1;
    // *p_mem = (float *)&clmemByIdx[idx];
    // idxByAddr[*p_mem] = idx;
    // cout << "ptr " << *p_mem << endl;

    return 0;
}

size_t cuMemcpyHtoDAsync_v2(void *dst, void *src, size_t bytes) {
    // // host => device
    // int dstidx = idxByAddr[(void *)dst];
    // cl_mem dstclmem = clmemByIdx[dstidx];
    // err = clEnqueueWriteBuffer(*queue, dstclmem, CL_FALSE, 0,
    //                                   bytes, src, 0, NULL, NULL);
    // cl->checkError(err);
    return 0;
}

size_t  cuMemcpyDtoHAsync_v2(void *dst, void *src, size_t bytes) {
    // int srcidx = idxByAddr[(void *)src];
    // cl_mem srcclmem = clmemByIdx[srcidx];
    // err = clEnqueueReadBuffer(*queue, srcclmem, CL_FALSE, 0,
    //                                  bytes, dst, 0, NULL, NULL);
    // cl->checkError(err);
    return 0;
}

// => synchronous <=
size_t cuMemcpyHtoD_v2(void *gpu_dst, void *host_src, size_t size) {
    // cudaMemcpy(gpu_dst, host_src, size, 1);
    // cl->finish();
    return 0;
}

// => synchronous <=
size_t cuMemcpyHtoD(void *gpu_dst, void *host_src, size_t size) {
    return cuMemcpyHtoD_v2(gpu_dst, host_src, size);
}

// => synchronous <=
size_t  cuMemcpyDtoH_v2(void *host_dst, void *gpu_src, size_t size) {
    cudaMemcpy(host_dst, gpu_src, size, 2);
    cl->finish();
    return 0;
}

// => synchronous <=
size_t  cuMemcpyDtoH(void *host_dst, void *gpu_src, size_t size) {
    return cuMemcpyDtoH(host_dst, gpu_src, size);
}

size_t cudaFree(PMemory pMemory) {
    // for(int i = 0 ; i < clmems.size(); i++) {
    //     cout << "cuda free i " << i << " " << &clmems[i] << endl;
    //     // err = clReleaseMemObject(clmems[i]);
    //     // cl->checkError(err);
    // }
    // err = clReleaseMemObject(*(cl_mem *)(*p_mem));
    // cl->checkError(err);

    // int idx = idxByAddr[mem];

    cout << "cudafree using opencl hostpointer=" << pMemory << endl;
    delete pMemory;

    // err = clReleaseMemObject(clmemByIdx[idx]);
    // err = clReleaseMemObject(*(cl_mem *)mem);
    // cl->checkError(err);
    return 0;
}

size_t cuMemAlloc_v2(cocl::PMemory *mem, size_t bytes) {
    return cudaMalloc(mem, bytes);
}

size_t cuMemFree_v2(cocl::PMemory mem) {
    return cudaFree(mem);
}

// size_t cuMemsetD32_v2(void *location, int value, uint32 count) {
//     err = clEnqueueFillBuffer(*queue, location, &value, sizeof(int), 0, count * sizeof(int), 0, 0, 0);
// }

<commit_msg>remove dead code<commit_after>// Copyright Hugh Perkins 2016

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cocl_memory.h"

#include "hostside_opencl_funcs.h"

#include <iostream>
#include <memory>
#include <vector>
#include <map>
#include <set>

// #include "EasyCL.h"

#include "CL/cl.h"

using namespace std;
using namespace cocl;
using namespace easycl;

extern "C" {
    size_t cudaMalloc(cocl::PMemory *pmem, size_t N);
    size_t cuMemAlloc_v2(cocl::PMemory *pmem, size_t bytes);
    size_t cuMemFree_v2(cocl::PMemory mem);
    size_t cudaFree(cocl::PMemory pmem);

    size_t cuMemHostAlloc(cocl::PMemory *pmem, unsigned int bytes, int CU_MEMHOSTALLOC_PORTABLE);
    size_t cuMemFreeHost(cocl::PMemory mem);

    size_t cudaMemsetAsync(void *devPtr, int value, size_t count, void *stream = 0);
    size_t cudaMemcpy(void *dst, const void *, size_t, size_t cudaMemcpyKind);
    size_t cudaMemcpyAsync (void *dst, const void *src, size_t count, size_t kind, void *stream = 0);
    size_t cuMemGetInfo_v2(size_t *free, size_t *total);
    size_t cuMemsetD8_v2(void *location, unsigned char value, uint32_t count);
    size_t cuMemsetD32_v2(void *location, unsigned int value, uint32_t count);
    size_t cuMemcpyHtoD_v2(void *gpu_dst, void *host_src, size_t size);
    size_t cuMemcpyDtoH_v2(void *host_dst, void *gpu_src, size_t size);
    size_t cuMemcpyHtoD(void *gpu_dst, void *host_src, size_t size);
    size_t cuMemcpyDtoH(void *host_dst, void *gpu_src, size_t size);
    size_t cuMemcpyHtoDAsync_v2(void *gpu_dst, void *host_src, size_t size);
    size_t cuMemcpyDtoHAsync_v2(void *host_dst, void *gpu_src, size_t size);

    size_t cuDeviceTotalMem_v2(uint64_t *value, void *device);
}

namespace cocl {
    map<void *, Memory *> memoryByHostPointer;

    Memory::Memory(cl_mem clmem, size_t bytes, MemoryType type) :
            clmem(clmem), bytes(bytes), type(type) {
    }

    Memory *Memory::newPinned(size_t bytes) {
        cout << "Memory allocating new pinned memory object" << endl;
        cl_int err;
        cl_mem clmem = clCreateBuffer(*ctx, CL_MEM_ALLOC_HOST_PTR, bytes,
                                               NULL, &err);
        cl->checkError(err);
        Memory *memory = new Memory(clmem, bytes, MemoryType::Pinned);
        memory->hostPointer = memory->map();

        memoryByHostPointer[memory->hostPointer] = memory;
        return memory;
    }

    Memory *Memory::newDeviceAlloc(size_t bytes) {
        cout << "Memory allocating new device memory object" << endl;
        cl_int err;
        cl_mem clmem = clCreateBuffer(*ctx, CL_MEM_READ_WRITE, bytes,
                                               NULL, &err);
        cl->checkError(err);
        Memory *memory = new Memory(clmem, bytes, MemoryType::Device);
        memory->hostPointer = memory;

        memoryByHostPointer[memory->hostPointer] = memory;

        return memory;
    }

    Memory::~Memory() {
        cout << "~Memory releasing mem object" << endl;
        cl_int err = clReleaseMemObject(clmem);
        cl->checkError(err);
    }

    void *Memory::map() {
        cout << "Memory calling map" << endl;
        cl_int err;
        hostPointer = clEnqueueMapBuffer(*queue,
            clmem,
            CL_FALSE,
            CL_MAP_READ | CL_MAP_WRITE,
            0,
            bytes,
            0,
            0,
            0,
            &err
        );
        cl->checkError(err);
        cout << "Memory after map hostpoiner=" << hostPointer << endl;
        return hostPointer;
    }

    void Memory::unmap() {
        cl_int err = clEnqueueUnmapMemObject (
            *queue,
            clmem,
            hostPointer,
            0,
            0,
            0
        );
        cl->checkError(err);
    }
}

size_t cuMemHostAlloc(PMemory *ppMemory, unsigned int bytes, int CU_MEMHOSTALLOC_PORTABLE) {
    cout << "cuMemHostAlloc redirected bytes=" << bytes << endl;
    hostside_opencl_funcs_assure_initialized();
    cout << "cuMemHostAlloc using cl, size " << bytes << endl;
    Memory *memory = Memory::newPinned(bytes);

    *ppMemory = memory;

    return 0;
}

size_t cuMemFreeHost(void *mem) {
    cout << "cuMemFreeHost redirected" << endl;
    return 0;
}

size_t cuMemGetInfo_v2(size_t *free, size_t *total) {
    cout << "cuMemGetInfo_v2 redirected" << endl;
    *free = 1024 * 1024;
    *total = 1024 * 1024;
    return 0;
}

size_t cudaMemcpyAsync (void *dst, const void *src, size_t count, size_t cudaMemcpyKind, void *stream) {
    cout << "cudaMemcpyAsync count=" << count << " cudaMemcpyKind=" << cudaMemcpyKind << " stream=" << stream << endl;

    assert(stream == 0);

    cout << "cudamempcy using opencl cudaMemcpyKind " << cudaMemcpyKind << " count=" << count << endl;
    // if(cudaMemcpyKind == 2) {
    //     // device => host
    //     int srcidx = idxByAddr[(void *)src];
    //     cl_mem srcclmem = clmemByIdx[srcidx];
    //     err = clEnqueueReadBuffer(*queue, srcclmem, CL_TRUE, 0,
    //                                      count, dst, 0, NULL, NULL);
    //     cl->checkError(err);
    //     // cl->finish();
    // } else if(cudaMemcpyKind == 1) {
    //     // host => device
    //     int dstidx = idxByAddr[(void *)dst];
    //     cl_mem dstclmem = clmemByIdx[dstidx];
    //     err = clEnqueueWriteBuffer(*queue, dstclmem, CL_TRUE, 0,
    //                                       count, src, 0, NULL, NULL);
    //     cl->checkError(err);
    // } else {
    //     cout << "cudaMemcpyKind using opencl " << cudaMemcpyKind << endl;
    //     throw runtime_error("unhandled cudaMemcpyKind");
    // }

    return 0;
}

size_t cudaMemsetAsync(void *devPtr, int value, size_t count, void *stream) {
    cout << "cudaMemsetAsync stub value=" << value << " count=" << count << " stream=" << stream << endl;
    assert(stream == 0);

    return 0;
}

size_t cuMemsetD8_v2(void *location, unsigned char value, uint32_t count) {
    cout << "cuMemsetD8_v2 redirected value " << value << " count=" << count << endl;
    // cl_int err = clEnqueueFillBuffer(*queue, *voidStarToClmem(location), &value, sizeof(unsigned char), 0, count * sizeof(unsigned char), 0, 0, 0);
    // cl->checkError(err);
    return 0;
}

size_t cuMemsetD32_v2(void *location, unsigned int value, uint32_t count) {
    cout << "cuMemsetD32_v2 redirected value " << value << " count=" << count << endl;
    // cl_int err = clEnqueueFillBuffer(*queue, *voidStarToClmem(location), &value, sizeof(int), 0, count * sizeof(int), 0, 0, 0);
    // cl->checkError(err);
    return 0;
}

size_t cuDeviceTotalMem_v2(uint64_t *value, void *device) {
    cout << "cuDeviceTotalMem_v2 redirected" << endl;
    *value = 1024 * 1024;
    return 0;
}

size_t cudaMemcpy(void *dst, const void *src, size_t bytes, size_t cudaMemcpyKind) {
    cout << "cudamempcy using opencl cudaMemcpyKind " << cudaMemcpyKind << " count=" << bytes << endl;
    // if(cudaMemcpyKind == 2) {
    //     // device => host
    //     int srcidx = idxByAddr[(void *)src];
    //     cl_mem srcclmem = clmemByIdx[srcidx];
    //     err = clEnqueueReadBuffer(*queue, srcclmem, CL_TRUE, 0,
    //                                      bytes, dst, 0, NULL, NULL);
    //     cl->checkError(err);
    //     // cl->finish();
    // } else if(cudaMemcpyKind == 1) {
    //     // host => device
    //     int dstidx = idxByAddr[(void *)dst];
    //     cl_mem dstclmem = clmemByIdx[dstidx];
    //     err = clEnqueueWriteBuffer(*queue, dstclmem, CL_TRUE, 0,
    //                                       bytes, src, 0, NULL, NULL);
    //     cl->checkError(err);
    // } else {
    //     cout << "cudaMemcpyKind using opencl " << cudaMemcpyKind << endl;
    //     throw runtime_error("unhandled cudaMemcpyKind");
    // }
    return 0;
}

size_t cudaMalloc(PMemory *ppMemory, size_t N) {
    hostside_opencl_funcs_assure_initialized();
    cout << "cudaMalloc using cl, size " << N << endl;
    Memory *memory = Memory::newDeviceAlloc(N);

    *ppMemory = memory;
    return 0;
}

size_t cuMemcpyHtoDAsync_v2(void *dst, void *src, size_t bytes) {
    // // host => device
    // int dstidx = idxByAddr[(void *)dst];
    // cl_mem dstclmem = clmemByIdx[dstidx];
    // err = clEnqueueWriteBuffer(*queue, dstclmem, CL_FALSE, 0,
    //                                   bytes, src, 0, NULL, NULL);
    // cl->checkError(err);
    return 0;
}

size_t  cuMemcpyDtoHAsync_v2(void *dst, void *src, size_t bytes) {
    // int srcidx = idxByAddr[(void *)src];
    // cl_mem srcclmem = clmemByIdx[srcidx];
    // err = clEnqueueReadBuffer(*queue, srcclmem, CL_FALSE, 0,
    //                                  bytes, dst, 0, NULL, NULL);
    // cl->checkError(err);
    return 0;
}

// => synchronous <=
size_t cuMemcpyHtoD_v2(void *gpu_dst, void *host_src, size_t size) {
    // cudaMemcpy(gpu_dst, host_src, size, 1);
    // cl->finish();
    return 0;
}

// => synchronous <=
size_t cuMemcpyHtoD(void *gpu_dst, void *host_src, size_t size) {
    return cuMemcpyHtoD_v2(gpu_dst, host_src, size);
}

// => synchronous <=
size_t  cuMemcpyDtoH_v2(void *host_dst, void *gpu_src, size_t size) {
    cudaMemcpy(host_dst, gpu_src, size, 2);
    cl->finish();
    return 0;
}

// => synchronous <=
size_t  cuMemcpyDtoH(void *host_dst, void *gpu_src, size_t size) {
    return cuMemcpyDtoH(host_dst, gpu_src, size);
}

size_t cudaFree(PMemory pMemory) {
    cout << "cudafree using opencl hostpointer=" << pMemory << endl;
    delete pMemory;
    return 0;
}

size_t cuMemAlloc_v2(cocl::PMemory *mem, size_t bytes) {
    return cudaMalloc(mem, bytes);
}

size_t cuMemFree_v2(cocl::PMemory mem) {
    return cudaFree(mem);
}

// size_t cuMemsetD32_v2(void *location, int value, uint32 count) {
//     err = clEnqueueFillBuffer(*queue, location, &value, sizeof(int), 0, count * sizeof(int), 0, 0, 0);
// }

<|endoftext|>


<commit_before>#include <evpp/tcp_server.h>
#include <evpp/buffer.h>
#include <evpp/tcp_conn.h>

#ifdef _WIN32
#include "../../winmain-inl.h"
#endif

typedef std::map<uint64_t, evpp::TCPConnPtr> ConnectionsMap;
typedef std::shared_ptr<ConnectionsMap> ConnectionsMapPtr;

std::atomic<int> g_connected = {0}; // The all connected connection count
std::atomic<int> g_current_round_connected = {0};
std::atomic<int> g_current_round_disconnected = {0};

std::atomic<int64_t> g_recved_message = {0};
std::atomic<int64_t> g_current_round_recved_message = {0};

std::atomic<int64_t> g_current_round_recved_bytes = {0};

void Print() {
    LOG_ERROR << "Running ...\n"
        << "\t                Total connected " << g_connected << "\n"
        << "\t        Current round connected " << g_current_round_connected.exchange(0) << "\n"
        << "\t     Current round disconnected " << g_current_round_disconnected.exchange(0) << "\n"
        << "\t        Total received messages " << g_recved_message << "\n"
        << "\tCurrent round received messages " << g_current_round_recved_message.exchange(0) << "\n"
        << "\t                     Throughput " << g_current_round_recved_bytes.exchange(0) / 1024.0 / 1024.0 << "MB\n";
}

void OnMessage(const evpp::TCPConnPtr& conn,
               evpp::Buffer* msg) {
    const size_t kHeadLen = 4;
    while (msg->size() >= kHeadLen) {
        int32_t len = msg->PeekInt32();
        if (msg->size() < len + kHeadLen) {
            break;
        }

        conn->Send(msg->data(), len + kHeadLen);
        g_current_round_recved_bytes += len + kHeadLen;
        g_recved_message++;
        g_current_round_recved_message++;
        msg->Skip(kHeadLen);
        std::string m = msg->NextString(len);
        bool check = true;
        for (auto i : m) {
            if (i != 'a') {
                check = false;
                break;
            }
        }
        if (!check) {
            LOG_ERROR << "Received an ERROR message.";
        }
    }
}

void OnConnection(const evpp::TCPConnPtr& conn) {
    if (conn->IsConnected()) {
        LOG_INFO << "Accept a new connection " << conn->AddrToString();
        g_connected++;
        g_current_round_connected++;
    } else {
        LOG_INFO << "Disconnected from " << conn->remote_addr();
        g_connected--;
        g_current_round_disconnected--;
    }
}

int main(int argc, char* argv[]) {
    std::string port = "9099";
    if (argc == 2) {
        port = argv[1];
    }
    std::string addr = std::string("0.0.0.0:") + port;
    evpp::EventLoop loop;
    loop.RunEvery(evpp::Duration(1.0), &Print);
    evpp::TCPServer server(&loop, addr, "c10m", 23);
    server.SetMessageCallback(&OnMessage);
    server.SetConnectionCallback(&OnConnection);
    server.Init();
    server.Start();
    loop.Run();
    return 0;
}
<commit_msg>Update c10m<commit_after>#include <evpp/tcp_server.h>
#include <evpp/buffer.h>
#include <evpp/tcp_conn.h>

#ifdef _WIN32
#include "../../winmain-inl.h"
#endif

typedef std::map<uint64_t, evpp::TCPConnPtr> ConnectionsMap;
typedef std::shared_ptr<ConnectionsMap> ConnectionsMapPtr;

std::atomic<int> g_connected = {0}; // The all connected connection count
std::atomic<int> g_current_round_connected = {0};
std::atomic<int> g_current_round_disconnected = {0};

std::atomic<int64_t> g_recved_message = {0};
std::atomic<int64_t> g_current_round_recved_message = {0};

std::atomic<int64_t> g_current_round_recved_bytes = {0};

void Print() {
    LOG_ERROR << "Running ...\n"
        << "\t                Total connected " << g_connected << "\n"
        << "\t        Current round connected " << g_current_round_connected.exchange(0) << "\n"
        << "\t     Current round disconnected " << g_current_round_disconnected.exchange(0) << "\n"
        << "\t        Total received messages " << g_recved_message << "\n"
        << "\tCurrent round received messages " << g_current_round_recved_message.exchange(0) << "\n"
        << "\t                     Throughput " << g_current_round_recved_bytes.exchange(0) / 1024.0 / 1024.0 << "MB/s\n";
}

void OnMessage(const evpp::TCPConnPtr& conn,
               evpp::Buffer* msg) {
    const size_t kHeadLen = 4;
    while (msg->size() >= kHeadLen) {
        int32_t len = msg->PeekInt32();
        if (msg->size() < len + kHeadLen) {
            break;
        }

        conn->Send(msg->data(), len + kHeadLen);
        g_current_round_recved_bytes += len + kHeadLen;
        g_recved_message++;
        g_current_round_recved_message++;
        msg->Skip(kHeadLen);
        std::string m = msg->NextString(len);
        bool check = true;
        for (auto i : m) {
            if (i != 'a') {
                check = false;
                break;
            }
        }
        if (!check) {
            LOG_ERROR << "Received an ERROR message.";
        }
    }
}

void OnConnection(const evpp::TCPConnPtr& conn) {
    if (conn->IsConnected()) {
        LOG_INFO << "Accept a new connection " << conn->AddrToString();
        g_connected++;
        g_current_round_connected++;
    } else {
        LOG_INFO << "Disconnected from " << conn->remote_addr();
        g_connected--;
        g_current_round_disconnected++;
    }
}

int main(int argc, char* argv[]) {
    std::string port = "9099";
    if (argc == 2) {
        port = argv[1];
    }
    std::string addr = std::string("0.0.0.0:") + port;
    evpp::EventLoop loop;
    loop.RunEvery(evpp::Duration(1.0), &Print);
    evpp::TCPServer server(&loop, addr, "c10m", 23);
    server.SetMessageCallback(&OnMessage);
    server.SetConnectionCallback(&OnConnection);
    server.Init();
    server.Start();
    loop.Run();
    return 0;
}
<|endoftext|>


<commit_before>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * MockUsbWidget.cpp
 * The mock usb widget used for testing
 * Copyright (C) 2010 Simon Newton
 */

#include <string.h>
#include <cppunit/extensions/HelperMacros.h>
#include <queue>

#include "ola/Callback.h"
#include "ola/Logging.h"
#include "plugins/usbpro/MockUsbWidget.h"

bool MockUsbWidget::SendMessage(uint8_t label,
                                const uint8_t *data,
                                unsigned int length) const {
  CPPUNIT_ASSERT(m_expected_calls.size());
  expected_call call = m_expected_calls.front();
  m_expected_calls.pop();
  CPPUNIT_ASSERT_EQUAL(call.expected_command.label, label);
  CPPUNIT_ASSERT_EQUAL(call.expected_command.length, length);
  CPPUNIT_ASSERT(!memcmp(call.expected_command.data, data, length));

  if (call.send_response)
    m_callback->Run(call.return_command.label,
                    call.return_command.data,
                    call.return_command.length);
  return true;
}

/**
 * A Call that doesn't trigger a response
 */
void MockUsbWidget::AddExpectedCall(uint8_t expected_label,
                                    const uint8_t *expected_data,
                                    unsigned int expected_length) {
  expected_call call;
  call.send_response = false;
  call.expected_command.label = expected_label;
  call.expected_command.data = expected_data;
  call.expected_command.length = expected_length;
  m_expected_calls.push(call);
}

/**
 * A Call that triggers a response
 */
void MockUsbWidget::AddExpectedCall(uint8_t expected_label,
                                    const uint8_t *expected_data,
                                    unsigned int expected_length,
                                    uint8_t return_label,
                                    const uint8_t *return_data,
                                    unsigned int return_length) {
  expected_call call;
  call.send_response = true;
  call.expected_command.label = expected_label;
  call.expected_command.data = expected_data;
  call.expected_command.length = expected_length;
  call.return_command.label = return_label;
  call.return_command.data = return_data;
  call.return_command.length = return_length;
  m_expected_calls.push(call);
}

/**
 * Send an unsolicated message
 */
void MockUsbWidget::SendUnsolicited(uint8_t label,
                                    const uint8_t *data,
                                    unsigned int length) {
    m_callback->Run(label, data, length);
}
<commit_msg> * fix another warning<commit_after>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * MockUsbWidget.cpp
 * The mock usb widget used for testing
 * Copyright (C) 2010 Simon Newton
 */

#include <string.h>
#include <cppunit/extensions/HelperMacros.h>
#include <queue>

#include "ola/Callback.h"
#include "ola/Logging.h"
#include "plugins/usbpro/MockUsbWidget.h"

bool MockUsbWidget::SendMessage(uint8_t label,
                                const uint8_t *data,
                                unsigned int length) const {
  CPPUNIT_ASSERT(m_expected_calls.size());
  expected_call call = m_expected_calls.front();
  m_expected_calls.pop();
  CPPUNIT_ASSERT_EQUAL(call.expected_command.label, label);
  CPPUNIT_ASSERT_EQUAL(call.expected_command.length, length);
  CPPUNIT_ASSERT(!memcmp(call.expected_command.data, data, length));

  if (call.send_response)
    m_callback->Run(call.return_command.label,
                    call.return_command.data,
                    call.return_command.length);
  return true;
}

/**
 * A Call that doesn't trigger a response
 */
void MockUsbWidget::AddExpectedCall(uint8_t expected_label,
                                    const uint8_t *expected_data,
                                    unsigned int expected_length) {
  expected_call call = {
    true,
    {expected_label, expected_length, expected_data},
    {0, 0, NULL}
  };
  m_expected_calls.push(call);
}

/**
 * A Call that triggers a response
 */
void MockUsbWidget::AddExpectedCall(uint8_t expected_label,
                                    const uint8_t *expected_data,
                                    unsigned int expected_length,
                                    uint8_t return_label,
                                    const uint8_t *return_data,
                                    unsigned int return_length) {
  expected_call call = {
    true,
    {expected_label, expected_length, expected_data},
    {return_label, return_length, return_data}
  };
  m_expected_calls.push(call);
}

/**
 * Send an unsolicated message
 */
void MockUsbWidget::SendUnsolicited(uint8_t label,
                                    const uint8_t *data,
                                    unsigned int length) {
    m_callback->Run(label, data, length);
}
<|endoftext|>


<commit_before>/**
 * This is an example of using EntityX.
 *
 * It is an SFML2 application that spawns 100 random circles on a 2D plane
 * moving in random directions. If two circles collide they will explode and
 * emit particles.
 *
 * This illustrates a bunch of EC/EntityX concepts:
 *
 * - Separation of data via components.
 * - Separation of logic via systems.
 * - Use of events (colliding bodies trigger a CollisionEvent).
 *
 * Compile with:
 *
 *    c++ -I.. -O3 -std=c++11 -Wall -lsfml-system -lsfml-window -lsfml-graphics -lentityx example.cc -o example
 */
#include <cmath>
#include <unordered_set>
#include <sstream>
#include <cstdlib>
#include <memory>
#include <string>
#include <vector>
#include <iostream>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <entityx/entityx.h>

using std::cerr;
using std::cout;
using std::endl;

namespace ex = entityx;

namespace std {
template <>
struct hash<ex::Entity> {
  std::size_t operator()(const ex::Entity& k) const { return k.id().id(); }
};
}

float r(int a, float b = 0) {
  return static_cast<float>(std::rand() % (a * 1000) + b * 1000) / 1000.0;
}

struct Body {
  Body(const sf::Vector2f &position, const sf::Vector2f &direction, float rotationd = 0.0)
    : position(position), direction(direction), rotationd(rotationd) {}

  sf::Vector2f position;
  sf::Vector2f direction;
  float rotation = 0.0, rotationd;
};

struct Renderable {
  explicit Renderable(std::unique_ptr<sf::Shape> shape) : shape(std::move(shape)) {}

  std::unique_ptr<sf::Shape> shape;
};

struct Particle {
  explicit Particle(sf::Color colour, float radius, float duration)
      : colour(colour), radius(radius), alpha(colour.a), d(colour.a / duration) {}

  sf::Color colour;
  float radius, alpha, d;
};

struct Collideable {
  explicit Collideable(float radius) : radius(radius) {}

  float radius;
};

// Emitted when two entities collide.
struct CollisionEvent {
  CollisionEvent(ex::Entity left, ex::Entity right) : left(left), right(right) {}

  ex::Entity left, right;
};

class SpawnSystem : public ex::System<SpawnSystem> {
public:
  explicit SpawnSystem(sf::RenderTarget &target, int count) : size(target.getSize()), count(count) {}

  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    int c = 0;
    ex::ComponentHandle<Collideable> collideable;
    for (ex::Entity entity : es.entities_with_components(collideable)) c++;

    for (int i = 0; i < count - c; i++) {
      ex::Entity entity = es.create();

      // Mark as collideable (explosion particles will not be collideable).
      collideable = entity.assign<Collideable>(r(10, 5));

      // "Physical" attributes.
      entity.assign<Body>(
        sf::Vector2f(r(size.x), r(size.y)),
        sf::Vector2f(r(100, -50), r(100, -50)));

      // Shape to apply to entity.
      std::unique_ptr<sf::Shape> shape(new sf::CircleShape(collideable->radius));
      shape->setFillColor(sf::Color(r(128, 127), r(128, 127), r(128, 127)));
      shape->setOrigin(collideable->radius, collideable->radius);
      entity.assign<Renderable>(std::move(shape));
    }
  }

private:
  sf::Vector2u size;
  int count;
};

// Updates a body's position and rotation.
struct BodySystem : public ex::System<BodySystem> {
  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    ex::ComponentHandle<Body> body;
    for (ex::Entity entity : es.entities_with_components(body)) {
      body->position += body->direction * static_cast<float>(dt);
      body->rotation += body->rotationd * dt;
    }
  };
};

// Bounce bodies off the edge of the screen.
class BounceSystem : public ex::System<BounceSystem> {
public:
  explicit BounceSystem(sf::RenderTarget &target) : size(target.getSize()) {}

  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    ex::ComponentHandle<Body> body;
    for (ex::Entity entity : es.entities_with_components(body)) {
      if (body->position.x + body->direction.x < 0 ||
          body->position.x + body->direction.x >= size.x)
        body->direction.x = -body->direction.x;
      if (body->position.y + body->direction.y < 0 ||
          body->position.y + body->direction.y >= size.y)
        body->direction.y = -body->direction.y;
    }
  }

private:
  sf::Vector2u size;
};

// Determines if two Collideable bodies have collided. If they have it emits a
// CollisionEvent. This is used by ExplosionSystem to create explosion
// particles, but it could be used by a SoundSystem to play an explosion
// sound, etc..
//
// Uses a fairly rudimentary 2D partition system, but performs reasonably well.
class CollisionSystem : public ex::System<CollisionSystem> {
  static const int PARTITIONS = 200;

  struct Candidate {
    sf::Vector2f position;
    float radius;
    ex::Entity entity;
  };

public:
  explicit CollisionSystem(sf::RenderTarget &target) : size(target.getSize()) {
    size.x = size.x / PARTITIONS + 1;
    size.y = size.y / PARTITIONS + 1;
  }

  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    reset();
    collect(es);
    collide(events);
  };

private:
  std::vector<std::vector<Candidate>> grid;
  sf::Vector2u size;

  void reset() {
    grid.clear();
    grid.resize(size.x * size.y);
  }

  void collect(ex::EntityManager &entities) {
    ex::ComponentHandle<Body> body;
    ex::ComponentHandle<Collideable> collideable;
    for (ex::Entity entity : entities.entities_with_components(body, collideable)) {
      unsigned int
          left = static_cast<int>(body->position.x - collideable->radius) / PARTITIONS,
          top = static_cast<int>(body->position.y - collideable->radius) / PARTITIONS,
          right = static_cast<int>(body->position.x + collideable->radius) / PARTITIONS,
          bottom = static_cast<int>(body->position.y + collideable->radius) / PARTITIONS;
        Candidate candidate {body->position, collideable->radius, entity};
        unsigned int slots[4] = {
          left + top * size.x,
          right + top * size.x,
          left  + bottom * size.x,
          right + bottom * size.x,
        };
        grid[slots[0]].push_back(candidate);
        if (slots[0] != slots[1]) grid[slots[1]].push_back(candidate);
        if (slots[1] != slots[2]) grid[slots[2]].push_back(candidate);
        if (slots[2] != slots[3]) grid[slots[3]].push_back(candidate);
    }
  }

  void collide(ex::EventManager &events) {
    for (const std::vector<Candidate> &candidates : grid) {
      for (const Candidate &left : candidates) {
        for (const Candidate &right : candidates) {
          if (left.entity == right.entity) continue;
          if (collided(left, right))
            events.emit<CollisionEvent>(left.entity, right.entity);
        }
      }
    }
  }

  float length(const sf::Vector2f &v) {
    return std::sqrt(v.x * v.x + v.y * v.y);
  }

  bool collided(const Candidate &left, const Candidate &right) {
    return length(left.position - right.position) < left.radius + right.radius;
  }
};

class ParticleSystem : public ex::System<ParticleSystem> {
public:
  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    ex::ComponentHandle<Particle> particle;
    for (ex::Entity entity : es.entities_with_components(particle)) {
      particle->alpha -= particle->d * dt;
      if (particle->alpha <= 0) {
        entity.destroy();
      } else {
        particle->colour.a = particle->alpha;
      }
    }
  }
};

class ParticleRenderSystem : public ex::System<ParticleRenderSystem> {
public:
  explicit ParticleRenderSystem(sf::RenderTarget &target) : target(target) {}

  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    sf::VertexArray vertices(sf::Quads);
    ex::ComponentHandle<Particle> particle;
    ex::ComponentHandle<Body> body;
    for (ex::Entity entity : es.entities_with_components(body, particle)) {
      float r = particle->radius;
      vertices.append(sf::Vertex(body->position + sf::Vector2f(-r, -r), particle->colour));
      vertices.append(sf::Vertex(body->position + sf::Vector2f(r, -r), particle->colour));
      vertices.append(sf::Vertex(body->position + sf::Vector2f(r, r), particle->colour));
      vertices.append(sf::Vertex(body->position + sf::Vector2f(-r, r), particle->colour));
    }
    target.draw(vertices);
  }
private:
  sf::RenderTarget ⌖
};

// For any two colliding bodies, destroys the bodies and emits a bunch of bodgy explosion particles.
class ExplosionSystem : public ex::System<ExplosionSystem>, public ex::Receiver<ExplosionSystem> {
public:
  void configure(ex::EventManager &events) override {
    events.subscribe<CollisionEvent>(*this);
  }

  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    for (ex::Entity entity : collided) {
      emit_particles(es, entity);
      entity.destroy();
    }
    collided.clear();
  }

  void emit_particles(ex::EntityManager &es, ex::Entity entity) {
    ex::ComponentHandle<Body> body = entity.component<Body>();
    ex::ComponentHandle<Renderable> renderable = entity.component<Renderable>();
    ex::ComponentHandle<Collideable> collideable = entity.component<Collideable>();
    sf::Color colour = renderable->shape->getFillColor();
    colour.a = 200;

    float area = (M_PI * collideable->radius * collideable->radius) / 3.0;
    for (int i = 0; i < area; i++) {
      ex::Entity particle = es.create();

      float rotationd = r(720, 180);
      if (std::rand() % 2 == 0) rotationd = -rotationd;

      float offset = r(collideable->radius, 1);
      float angle = r(360) * M_PI / 180.0;
      particle.assign<Body>(
        body->position + sf::Vector2f(offset * cos(angle), offset * sin(angle)),
        body->direction + sf::Vector2f(offset * 2 * cos(angle), offset * 2 * sin(angle)),
        rotationd);

      float radius = r(3, 1);
      particle.assign<Particle>(colour, radius, radius / 2);
    }
  }

  void receive(const CollisionEvent &collision) {
    // Events are immutable, so we can't destroy the entities here. We defer
    // the work until the update loop.
    collided.insert(collision.left);
    collided.insert(collision.right);
  }

private:
  std::unordered_set<ex::Entity> collided;
};

// Render all Renderable entities and draw some informational text.
class RenderSystem  :public ex::System<RenderSystem> {
public:
  explicit RenderSystem(sf::RenderTarget &target, sf::Font &font) : target(target) {
    text.setFont(font);
    text.setPosition(sf::Vector2f(2, 2));
    text.setCharacterSize(18);
    text.setColor(sf::Color::White);
  }

  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    ex::ComponentHandle<Body> body;
    ex::ComponentHandle<Renderable> renderable;
    for (ex::Entity entity : es.entities_with_components(body, renderable)) {
      renderable->shape->setPosition(body->position);
      renderable->shape->setRotation(body->rotation);
      target.draw(*renderable->shape.get());
    }
    last_update += dt;
    frame_count++;
    if (last_update >= 0.5) {
      std::ostringstream out;
      const double fps = frame_count / last_update;
      out << es.size() << " entities (" << static_cast<int>(fps) << " fps)";
      text.setString(out.str());
      last_update = 0.0;
      frame_count = 0.0;
    }
    target.draw(text);
  }

private:
  double last_update = 0.0;
  double frame_count = 0.0;
  sf::RenderTarget ⌖
  sf::Text text;
};

class Application : public ex::EntityX {
public:
  explicit Application(sf::RenderTarget &target, sf::Font &font) {
    systems.add<SpawnSystem>(target, 500);
    systems.add<BodySystem>();
    systems.add<BounceSystem>(target);
    systems.add<CollisionSystem>(target);
    systems.add<ExplosionSystem>();
    systems.add<ParticleSystem>();
    systems.add<RenderSystem>(target, font);
    systems.add<ParticleRenderSystem>(target);
    systems.configure();
  }

  void update(ex::TimeDelta dt) {
    systems.update<SpawnSystem>(dt);
    systems.update<BodySystem>(dt);
    systems.update<BounceSystem>(dt);
    systems.update<CollisionSystem>(dt);
    systems.update<ExplosionSystem>(dt);
    systems.update<ParticleSystem>(dt);
    systems.update<RenderSystem>(dt);
    systems.update<ParticleRenderSystem>(dt);
  }
};

int main() {
  std::srand(std::time(nullptr));

  sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "EntityX Example", sf::Style::Fullscreen);
  sf::Font font;
  if (!font.loadFromFile("LiberationSans-Regular.ttf")) {
    cerr << "error: failed to load LiberationSans-Regular.ttf" << endl;
    return 1;
  }

  Application app(window, font);

  sf::Clock clock;
  while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
      switch (event.type) {
        case sf::Event::Closed:
        case sf::Event::KeyPressed:
          window.close();
          break;

        default:
          break;
      }
    }

    window.clear();
    sf::Time elapsed = clock.restart();
    app.update(elapsed.asSeconds());
    window.display();
  }
}
<commit_msg>Update example.<commit_after>/**
 * This is an example of using EntityX.
 *
 * It is an SFML2 application that spawns 100 random circles on a 2D plane
 * moving in random directions. If two circles collide they will explode and
 * emit particles.
 *
 * This illustrates a bunch of EC/EntityX concepts:
 *
 * - Separation of data via components.
 * - Separation of logic via systems.
 * - Use of events (colliding bodies trigger a CollisionEvent).
 *
 * Compile with:
 *
 *    c++ -I.. -O3 -std=c++11 -Wall -lsfml-system -lsfml-window -lsfml-graphics -lentityx example.cc -o example
 */
#include <cmath>
#include <unordered_set>
#include <sstream>
#include <cstdlib>
#include <memory>
#include <string>
#include <vector>
#include <iostream>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <entityx/entityx.h>

using std::cerr;
using std::cout;
using std::endl;

namespace ex = entityx;

float r(int a, float b = 0) {
  return static_cast<float>(std::rand() % (a * 1000) + b * 1000) / 1000.0;
}

struct Body {
  Body(const sf::Vector2f &position, const sf::Vector2f &direction, float rotationd = 0.0)
    : position(position), direction(direction), rotationd(rotationd) {}

  sf::Vector2f position;
  sf::Vector2f direction;
  float rotation = 0.0, rotationd;
};

struct Renderable {
  explicit Renderable(std::unique_ptr<sf::Shape> shape) : shape(std::move(shape)) {}

  std::unique_ptr<sf::Shape> shape;
};

struct Particle {
  explicit Particle(sf::Color colour, float radius, float duration)
      : colour(colour), radius(radius), alpha(colour.a), d(colour.a / duration) {}

  sf::Color colour;
  float radius, alpha, d;
};

struct Collideable {
  explicit Collideable(float radius) : radius(radius) {}

  float radius;
};

// Emitted when two entities collide.
struct CollisionEvent {
  CollisionEvent(ex::Entity left, ex::Entity right) : left(left), right(right) {}

  ex::Entity left, right;
};

class SpawnSystem : public ex::System<SpawnSystem> {
public:
  explicit SpawnSystem(sf::RenderTarget &target, int count) : size(target.getSize()), count(count) {}

  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    int c = 0;
    ex::ComponentHandle<Collideable> collideable;
    for (ex::Entity entity : es.entities_with_components<Collideable>()) c++;

    for (int i = 0; i < count - c; i++) {
      ex::Entity entity = es.create();

      // Mark as collideable (explosion particles will not be collideable).
      collideable = entity.assign<Collideable>(r(10, 5));

      // "Physical" attributes.
      entity.assign<Body>(
        sf::Vector2f(r(size.x), r(size.y)),
        sf::Vector2f(r(100, -50), r(100, -50)));

      // Shape to apply to entity.
      std::unique_ptr<sf::Shape> shape(new sf::CircleShape(collideable->radius));
      shape->setFillColor(sf::Color(r(128, 127), r(128, 127), r(128, 127)));
      shape->setOrigin(collideable->radius, collideable->radius);
      entity.assign<Renderable>(std::move(shape));
    }
  }

private:
  sf::Vector2u size;
  int count;
};

// Updates a body's position and rotation.
struct BodySystem : public ex::System<BodySystem> {
  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    ex::ComponentHandle<Body> body;
    for (ex::Entity entity : es.entities_with_components(body)) {
      body->position += body->direction * static_cast<float>(dt);
      body->rotation += body->rotationd * dt;
    }
  };
};

// Bounce bodies off the edge of the screen.
class BounceSystem : public ex::System<BounceSystem> {
public:
  explicit BounceSystem(sf::RenderTarget &target) : size(target.getSize()) {}

  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    ex::ComponentHandle<Body> body;
    for (ex::Entity entity : es.entities_with_components(body)) {
      if (body->position.x + body->direction.x < 0 ||
          body->position.x + body->direction.x >= size.x)
        body->direction.x = -body->direction.x;
      if (body->position.y + body->direction.y < 0 ||
          body->position.y + body->direction.y >= size.y)
        body->direction.y = -body->direction.y;
    }
  }

private:
  sf::Vector2u size;
};

// Determines if two Collideable bodies have collided. If they have it emits a
// CollisionEvent. This is used by ExplosionSystem to create explosion
// particles, but it could be used by a SoundSystem to play an explosion
// sound, etc..
//
// Uses a fairly rudimentary 2D partition system, but performs reasonably well.
class CollisionSystem : public ex::System<CollisionSystem> {
  static const int PARTITIONS = 200;

  struct Candidate {
    sf::Vector2f position;
    float radius;
    ex::Entity entity;
  };

public:
  explicit CollisionSystem(sf::RenderTarget &target) : size(target.getSize()) {
    size.x = size.x / PARTITIONS + 1;
    size.y = size.y / PARTITIONS + 1;
  }

  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    reset();
    collect(es);
    collide(events);
  };

private:
  std::vector<std::vector<Candidate>> grid;
  sf::Vector2u size;

  void reset() {
    grid.clear();
    grid.resize(size.x * size.y);
  }

  void collect(ex::EntityManager &entities) {
    ex::ComponentHandle<Body> body;
    ex::ComponentHandle<Collideable> collideable;
    for (ex::Entity entity : entities.entities_with_components(body, collideable)) {
      unsigned int
          left = static_cast<int>(body->position.x - collideable->radius) / PARTITIONS,
          top = static_cast<int>(body->position.y - collideable->radius) / PARTITIONS,
          right = static_cast<int>(body->position.x + collideable->radius) / PARTITIONS,
          bottom = static_cast<int>(body->position.y + collideable->radius) / PARTITIONS;
        Candidate candidate {body->position, collideable->radius, entity};
        unsigned int slots[4] = {
          left + top * size.x,
          right + top * size.x,
          left  + bottom * size.x,
          right + bottom * size.x,
        };
        grid[slots[0]].push_back(candidate);
        if (slots[0] != slots[1]) grid[slots[1]].push_back(candidate);
        if (slots[1] != slots[2]) grid[slots[2]].push_back(candidate);
        if (slots[2] != slots[3]) grid[slots[3]].push_back(candidate);
    }
  }

  void collide(ex::EventManager &events) {
    for (const std::vector<Candidate> &candidates : grid) {
      for (const Candidate &left : candidates) {
        for (const Candidate &right : candidates) {
          if (left.entity == right.entity) continue;
          if (collided(left, right))
            events.emit<CollisionEvent>(left.entity, right.entity);
        }
      }
    }
  }

  float length(const sf::Vector2f &v) {
    return std::sqrt(v.x * v.x + v.y * v.y);
  }

  bool collided(const Candidate &left, const Candidate &right) {
    return length(left.position - right.position) < left.radius + right.radius;
  }
};

class ParticleSystem : public ex::System<ParticleSystem> {
public:
  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    ex::ComponentHandle<Particle> particle;
    for (ex::Entity entity : es.entities_with_components(particle)) {
      particle->alpha -= particle->d * dt;
      if (particle->alpha <= 0) {
        entity.destroy();
      } else {
        particle->colour.a = particle->alpha;
      }
    }
  }
};

class ParticleRenderSystem : public ex::System<ParticleRenderSystem> {
public:
  explicit ParticleRenderSystem(sf::RenderTarget &target) : target(target) {}

  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    sf::VertexArray vertices(sf::Quads);
    ex::ComponentHandle<Particle> particle;
    ex::ComponentHandle<Body> body;
    for (ex::Entity entity : es.entities_with_components(body, particle)) {
      float r = particle->radius;
      vertices.append(sf::Vertex(body->position + sf::Vector2f(-r, -r), particle->colour));
      vertices.append(sf::Vertex(body->position + sf::Vector2f(r, -r), particle->colour));
      vertices.append(sf::Vertex(body->position + sf::Vector2f(r, r), particle->colour));
      vertices.append(sf::Vertex(body->position + sf::Vector2f(-r, r), particle->colour));
    }
    target.draw(vertices);
  }
private:
  sf::RenderTarget ⌖
};

// For any two colliding bodies, destroys the bodies and emits a bunch of bodgy explosion particles.
class ExplosionSystem : public ex::System<ExplosionSystem>, public ex::Receiver<ExplosionSystem> {
public:
  void configure(ex::EventManager &events) override {
    events.subscribe<CollisionEvent>(*this);
  }

  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    for (ex::Entity entity : collided) {
      emit_particles(es, entity);
      entity.destroy();
    }
    collided.clear();
  }

  void emit_particles(ex::EntityManager &es, ex::Entity entity) {
    ex::ComponentHandle<Body> body = entity.component<Body>();
    ex::ComponentHandle<Renderable> renderable = entity.component<Renderable>();
    ex::ComponentHandle<Collideable> collideable = entity.component<Collideable>();
    sf::Color colour = renderable->shape->getFillColor();
    colour.a = 200;

    float area = (M_PI * collideable->radius * collideable->radius) / 3.0;
    for (int i = 0; i < area; i++) {
      ex::Entity particle = es.create();

      float rotationd = r(720, 180);
      if (std::rand() % 2 == 0) rotationd = -rotationd;

      float offset = r(collideable->radius, 1);
      float angle = r(360) * M_PI / 180.0;
      particle.assign<Body>(
        body->position + sf::Vector2f(offset * cos(angle), offset * sin(angle)),
        body->direction + sf::Vector2f(offset * 2 * cos(angle), offset * 2 * sin(angle)),
        rotationd);

      float radius = r(3, 1);
      particle.assign<Particle>(colour, radius, radius / 2);
    }
  }

  void receive(const CollisionEvent &collision) {
    // Events are immutable, so we can't destroy the entities here. We defer
    // the work until the update loop.
    collided.insert(collision.left);
    collided.insert(collision.right);
  }

private:
  std::unordered_set<ex::Entity> collided;
};

// Render all Renderable entities and draw some informational text.
class RenderSystem  :public ex::System<RenderSystem> {
public:
  explicit RenderSystem(sf::RenderTarget &target, sf::Font &font) : target(target) {
    text.setFont(font);
    text.setPosition(sf::Vector2f(2, 2));
    text.setCharacterSize(18);
    text.setColor(sf::Color::White);
  }

  void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
    ex::ComponentHandle<Body> body;
    ex::ComponentHandle<Renderable> renderable;
    for (ex::Entity entity : es.entities_with_components(body, renderable)) {
      renderable->shape->setPosition(body->position);
      renderable->shape->setRotation(body->rotation);
      target.draw(*renderable->shape.get());
    }
    last_update += dt;
    frame_count++;
    if (last_update >= 0.5) {
      std::ostringstream out;
      const double fps = frame_count / last_update;
      out << es.size() << " entities (" << static_cast<int>(fps) << " fps)";
      text.setString(out.str());
      last_update = 0.0;
      frame_count = 0.0;
    }
    target.draw(text);
  }

private:
  double last_update = 0.0;
  double frame_count = 0.0;
  sf::RenderTarget ⌖
  sf::Text text;
};

class Application : public ex::EntityX {
public:
  explicit Application(sf::RenderTarget &target, sf::Font &font) {
    systems.add<SpawnSystem>(target, 500);
    systems.add<BodySystem>();
    systems.add<BounceSystem>(target);
    systems.add<CollisionSystem>(target);
    systems.add<ExplosionSystem>();
    systems.add<ParticleSystem>();
    systems.add<RenderSystem>(target, font);
    systems.add<ParticleRenderSystem>(target);
    systems.configure();
  }

  void update(ex::TimeDelta dt) {
    systems.update<SpawnSystem>(dt);
    systems.update<BodySystem>(dt);
    systems.update<BounceSystem>(dt);
    systems.update<CollisionSystem>(dt);
    systems.update<ExplosionSystem>(dt);
    systems.update<ParticleSystem>(dt);
    systems.update<RenderSystem>(dt);
    systems.update<ParticleRenderSystem>(dt);
  }
};

int main() {
  std::srand(std::time(nullptr));

  sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "EntityX Example", sf::Style::Fullscreen);
  sf::Font font;
  if (!font.loadFromFile("LiberationSans-Regular.ttf")) {
    cerr << "error: failed to load LiberationSans-Regular.ttf" << endl;
    return 1;
  }

  Application app(window, font);

  sf::Clock clock;
  while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
      switch (event.type) {
        case sf::Event::Closed:
        case sf::Event::KeyPressed:
          window.close();
          break;

        default:
          break;
      }
    }

    window.clear();
    sf::Time elapsed = clock.restart();
    app.update(elapsed.asSeconds());
    window.display();
  }
}
<|endoftext|>


<commit_before>/** \file    augment_canones_references.cc
 *  \brief   A tool for adding numerical canon law references to MARC-21 datasets.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2019, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <string>
#include <unordered_map>
#include <cstdlib>
#include <strings.h>
#include "BibleUtil.h"
#include "Compiler.h"
#include "MARC.h"
#include "MiscUtil.h"
#include "RegexMatcher.h"
#include "StringUtil.h"
#include "UBTools.h"
#include "util.h"

namespace {

// To understand this code read https://github.com/ubtue/tuefind/wiki/Codices
std::string FieldToCanonLawCode(const std::string &ppn, const std::string &subfield_codex, const std::string &subfield_year,
                                const std::string &subfield_part)
{
    enum Codex { CIC1917, CIC1983, CCEO } codex;
    if (::strcasecmp(subfield_codex.c_str(), "Codex canonum ecclesiarum orientalium") == 0)
        codex = CCEO;
    else {
        if (unlikely(subfield_year.empty()))
            LOG_ERROR("missing year for Codex Iuris Canonici! (PPN: " + ppn + ")");
        if (subfield_year == "1917")
            codex = CIC1917;
        else if (subfield_year == "1983")
            codex = CIC1983;
        else
            LOG_ERROR("bad year for Codex Iuris Canonici \"" + subfield_year + "\"! (PPN: " + ppn + ")");
    }

    unsigned range_start, range_end;
    if (subfield_part.empty()) {
        range_start = 0;
        range_end = 99999999;
    } else if (not MiscUtil::ParseCanonLawRanges(subfield_part, &range_start, &range_end))
        LOG_ERROR("don't know how to parse codex parts \"" + subfield_part + "\"! (PPN: " + ppn + ")");

    switch (codex) {
    case CIC1917:
        return StringUtil::ToString(100000000 + range_start) + "_" + StringUtil::ToString(100000000 + range_end);
    case CIC1983:
        return StringUtil::ToString(200000000 + range_start) + "_" + StringUtil::ToString(200000000 + range_end);
    case CCEO:
        return StringUtil::ToString(300000000 + range_start) + "_" + StringUtil::ToString(300000000 + range_end);
    default:
        LOG_ERROR("unknown codex: " + std::to_string(codex));
    }
}

void LoadAuthorityData(MARC::Reader * const reader,
                       std::unordered_map<std::string, std::string> * const authority_ppns_to_canon_law_codes_map)
{
    unsigned total_count(0);
    while (auto record = reader->read()) {
        ++total_count;

        const auto _110_field(record.findTag("110"));
        if (_110_field == record.end() or ::strcasecmp(_110_field->getFirstSubfieldWithCode('a').c_str(), "Katholische Kirche") != 0)
            continue;

        const std::string t_subfield(_110_field->getFirstSubfieldWithCode('t'));
        if (::strcasecmp(t_subfield.c_str(),"Codex Iuris Canonici") != 0
            and ::strcasecmp(t_subfield.c_str(), "Codex canonum ecclesiarum orientalium") != 0)
            continue;

        (*authority_ppns_to_canon_law_codes_map)[record.getControlNumber()] = FieldToCanonLawCode(record.getControlNumber(),
                                                                                t_subfield,
                                                                                _110_field->getFirstSubfieldWithCode('f'),
                                                                                _110_field->getFirstSubfieldWithCode('p'));
    }

    LOG_INFO("found " + std::to_string(authority_ppns_to_canon_law_codes_map->size()) + " canon law records among "
             + std::to_string(total_count) + " authority records.");
}

void CollectAuthorityPPNs(const MARC::Record &record, const MARC::Tag &linking_field, std::vector<std::string> * const authority_ppns) {
    for (const auto &field : record.getTagRange(linking_field)) {
        const MARC::Subfields subfields(field.getSubfields());
        for (const auto &subfield : subfields) {
            if (subfield.code_ == '0' and StringUtil::StartsWith(subfield.value_, "(DE-576)"))
                authority_ppns->emplace_back(subfield.value_.substr(__builtin_strlen("(DE-576)")));
        }
    }
}

void ProcessRecords(MARC::Reader * const reader, MARC::Writer * const writer,
                    const std::unordered_map<std::string, std::string> &authority_ppns_to_canon_law_codes_map)
{
    static const std::vector<std::string> CANONES_GND_LINKING_TAGS{ "689", "655" };

    unsigned total_count(0), augmented_count(0);
    std::map<std::string, unsigned> reference_counts;

    while (auto record = reader->read()) {
        ++total_count;

        bool augmented_record(false);
        for (const auto &linking_tag : CANONES_GND_LINKING_TAGS) {
            std::vector<std::string> authority_ppns;
            CollectAuthorityPPNs(record, linking_tag, &authority_ppns);

            if (not authority_ppns.empty()) {
                for (const auto &authority_ppn : authority_ppns) {
                    const auto ppn_and_canon_law_code(authority_ppns_to_canon_law_codes_map.find(authority_ppn));
                    if (ppn_and_canon_law_code != authority_ppns_to_canon_law_codes_map.cend()) {
                        record.insertField("CAL", { { 'a', ppn_and_canon_law_code->second } });
                        augmented_record = true;
                        ++reference_counts[linking_tag];
                    }
                }
            }
        }

        if (not augmented_record) {
            // check if the codex data is embedded directly in the 689 field
            // apparently, 689$t is repeatable and the first instance (always?) appears to be 'Katholische Kirche'
            std::vector<std::string> ranges_to_insert;
            for (const auto &_689_field : record.getTagRange("689")) {
                if (_689_field.getFirstSubfieldWithCode('a') != "Katholische Kirche")
                    continue;

                std::string subfield_codex, subfield_year, subfield_part;
                for (const auto &subfield : _689_field.getSubfields()) {
                    if (subfield.code_ == 't' and subfield.value_ != "Katholische Kirche")
                        subfield_codex = subfield.value_;
                    else if (subfield.code_ == 'f')
                        subfield_year = subfield.value_;
                    else if (subfield.code_ == 'p')
                        subfield_part = subfield.value_;
                }

                if (not subfield_codex.empty() and not subfield_year.empty() and not subfield_part.empty()) {
                    ranges_to_insert.emplace_back(FieldToCanonLawCode(record.getControlNumber(), subfield_codex, subfield_year,
                                                                      subfield_part));
                    augmented_record = true;
                    ++reference_counts["689*"];
                }
            }

            for (const auto &range : ranges_to_insert)
                record.insertField("CAL", { { 'a', range } });
        }

        if (augmented_record)
            ++augmented_count;

        writer->write(record);
    }

    LOG_INFO("augmented " + std::to_string(augmented_count) + " of " + std::to_string(total_count) + " records.");
    LOG_INFO("found " + std::to_string(reference_counts["689"]) + " references in field 689");
    LOG_INFO("found " + std::to_string(reference_counts["689*"]) + " direct references in field 689");
    LOG_INFO("found " + std::to_string(reference_counts["655"]) + " references in field 655");
}

} // unnamed namespace

int Main(int argc, char **argv) {
    if (argc != 4)
        ::Usage("ixtheo_titles authority_records augmented_ixtheo_titles");

    const std::string title_input_filename(argv[1]);
    const std::string authority_filename(argv[2]);
    const std::string title_output_filename(argv[3]);
    if (unlikely(title_input_filename == title_output_filename))
        LOG_ERROR("Title input file name equals title output file name!");
    if (unlikely(title_input_filename == authority_filename))
        LOG_ERROR("Title input file name equals authority file name!");
    if (unlikely(title_output_filename == authority_filename))
        LOG_ERROR("Title output file name equals authority file name!");

    auto authority_reader(MARC::Reader::Factory(authority_filename));
    std::unordered_map<std::string, std::string> authority_ppns_to_canon_law_codes_map;
    LoadAuthorityData(authority_reader.get(), &authority_ppns_to_canon_law_codes_map);

    auto title_reader(MARC::Reader::Factory(title_input_filename));
    auto title_writer(MARC::Writer::Factory(title_output_filename));
    ProcessRecords(title_reader.get(), title_writer.get(), authority_ppns_to_canon_law_codes_map);

    return EXIT_SUCCESS;
}
<commit_msg>We now generate aliases for canon law references.<commit_after>/** \file    augment_canones_references.cc
 *  \brief   A tool for adding numerical canon law references to MARC-21 datasets.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2019, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <string>
#include <unordered_map>
#include <cstdlib>
#include <strings.h>
#include "BibleUtil.h"
#include "Compiler.h"
#include "FileUtil.h"
#include "MARC.h"
#include "MiscUtil.h"
#include "RegexMatcher.h"
#include "StringUtil.h"
#include "UBTools.h"
#include "util.h"

namespace {

enum Codex { CIC1917, CIC1983, CCEO };

Codex DetermineCodex(const std::string &subfield_codex, const std::string &subfield_year, const std::string &ppn) {
    if (::strcasecmp(subfield_codex.c_str(), "Codex canonum ecclesiarum orientalium") == 0)
        return CCEO;

    if (unlikely(subfield_year.empty()))
        LOG_ERROR("missing year for Codex Iuris Canonici! (PPN: " + ppn + ")");
    if (subfield_year == "1917")
        return CIC1917;
    else if (subfield_year == "1983")
        return CIC1983;

    LOG_ERROR("bad year for Codex Iuris Canonici \"" + subfield_year + "\"! (PPN: " + ppn + ")");
}

// To understand this code read https://github.com/ubtue/tuefind/wiki/Codices
std::string FieldToCanonLawCode(const std::string &ppn, const Codex codex, const std::string &subfield_part) {
    unsigned range_start, range_end;
    if (subfield_part.empty()) {
        range_start = 0;
        range_end = 99999999;
    } else if (not MiscUtil::ParseCanonLawRanges(subfield_part, &range_start, &range_end))
        LOG_ERROR("don't know how to parse codex parts \"" + subfield_part + "\"! (PPN: " + ppn + ")");

    switch (codex) {
    case CIC1917:
        return StringUtil::ToString(100000000 + range_start) + "_" + StringUtil::ToString(100000000 + range_end);
    case CIC1983:
        return StringUtil::ToString(200000000 + range_start) + "_" + StringUtil::ToString(200000000 + range_end);
    case CCEO:
        return StringUtil::ToString(300000000 + range_start) + "_" + StringUtil::ToString(300000000 + range_end);
    default:
        LOG_ERROR("unknown codex: " + std::to_string(codex));
    }
}

std::string CodexToPrefix(const Codex codex) {
    switch (codex) {
    case CIC1917:
        return "CIC17";
    case CIC1983:
        return "CIC83";
    case CCEO:
        return "CCEO";
    default:
        LOG_ERROR("unknown codex: " + std::to_string(codex));
    }
}

void LoadAuthorityData(MARC::Reader * const reader,
                       std::unordered_map<std::string, std::string> * const authority_ppns_to_canon_law_codes_map)
{
    const auto aliases_file(FileUtil::OpenOutputFileOrDie(UBTools::GetTuelibPath() + "canon_law_aliases.map"));

    unsigned total_count(0);
    while (auto record = reader->read()) {
        ++total_count;

        const auto _110_field(record.findTag("110"));
        if (_110_field == record.end() or ::strcasecmp(_110_field->getFirstSubfieldWithCode('a').c_str(), "Katholische Kirche") != 0)
            continue;

        const std::string t_subfield(_110_field->getFirstSubfieldWithCode('t'));
        if (::strcasecmp(t_subfield.c_str(),"Codex Iuris Canonici") != 0
            and ::strcasecmp(t_subfield.c_str(), "Codex canonum ecclesiarum orientalium") != 0)
            continue;

        const Codex codex(DetermineCodex(t_subfield, _110_field->getFirstSubfieldWithCode('f'), record.getControlNumber()));
        const auto canon_law_code(FieldToCanonLawCode(record.getControlNumber(), codex, _110_field->getFirstSubfieldWithCode('p')));
        (*authority_ppns_to_canon_law_codes_map)[record.getControlNumber()] = canon_law_code;

        for (const auto &_140_field : record.getTagRange("410")) {
            const auto p_subfield(_140_field.getFirstSubfieldWithCode('p'));
            if (not p_subfield.empty())
                (*aliases_file) << CodexToPrefix(codex) << ' ' << p_subfield << '=' << canon_law_code << '\n';
        }
    }

    LOG_INFO("found " + std::to_string(authority_ppns_to_canon_law_codes_map->size()) + " canon law records among "
             + std::to_string(total_count) + " authority records.");
}

void CollectAuthorityPPNs(const MARC::Record &record, const MARC::Tag &linking_field, std::vector<std::string> * const authority_ppns) {
    for (const auto &field : record.getTagRange(linking_field)) {
        const MARC::Subfields subfields(field.getSubfields());
        for (const auto &subfield : subfields) {
            if (subfield.code_ == '0' and StringUtil::StartsWith(subfield.value_, "(DE-576)"))
                authority_ppns->emplace_back(subfield.value_.substr(__builtin_strlen("(DE-576)")));
        }
    }
}

void ProcessRecords(MARC::Reader * const reader, MARC::Writer * const writer,
                    const std::unordered_map<std::string, std::string> &authority_ppns_to_canon_law_codes_map)
{
    static const std::vector<std::string> CANONES_GND_LINKING_TAGS{ "689", "655" };

    unsigned total_count(0), augmented_count(0);
    std::map<std::string, unsigned> reference_counts;

    while (auto record = reader->read()) {
        ++total_count;

        bool augmented_record(false);
        for (const auto &linking_tag : CANONES_GND_LINKING_TAGS) {
            std::vector<std::string> authority_ppns;
            CollectAuthorityPPNs(record, linking_tag, &authority_ppns);

            if (not authority_ppns.empty()) {
                for (const auto &authority_ppn : authority_ppns) {
                    const auto ppn_and_canon_law_code(authority_ppns_to_canon_law_codes_map.find(authority_ppn));
                    if (ppn_and_canon_law_code != authority_ppns_to_canon_law_codes_map.cend()) {
                        record.insertField("CAL", { { 'a', ppn_and_canon_law_code->second } });
                        augmented_record = true;
                        ++reference_counts[linking_tag];
                    }
                }
            }
        }

        if (not augmented_record) {
            // check if the codex data is embedded directly in the 689 field
            // apparently, 689$t is repeatable and the first instance (always?) appears to be 'Katholische Kirche'
            std::vector<std::string> ranges_to_insert;
            for (const auto &_689_field : record.getTagRange("689")) {
                if (_689_field.getFirstSubfieldWithCode('a') != "Katholische Kirche")
                    continue;

                std::string subfield_codex, subfield_year, subfield_part;
                for (const auto &subfield : _689_field.getSubfields()) {
                    if (subfield.code_ == 't' and subfield.value_ != "Katholische Kirche")
                        subfield_codex = subfield.value_;
                    else if (subfield.code_ == 'f')
                        subfield_year = subfield.value_;
                    else if (subfield.code_ == 'p')
                        subfield_part = subfield.value_;
                }

                if (not subfield_codex.empty() and not subfield_year.empty() and not subfield_part.empty()) {
                    const Codex codex(DetermineCodex(subfield_codex, subfield_year, record.getControlNumber()));
                    ranges_to_insert.emplace_back(FieldToCanonLawCode(record.getControlNumber(), codex, subfield_part));
                    augmented_record = true;
                    ++reference_counts["689*"];
                }
            }

            for (const auto &range : ranges_to_insert)
                record.insertField("CAL", { { 'a', range } });
        }

        if (augmented_record)
            ++augmented_count;

        writer->write(record);
    }

    LOG_INFO("augmented " + std::to_string(augmented_count) + " of " + std::to_string(total_count) + " records.");
    LOG_INFO("found " + std::to_string(reference_counts["689"]) + " references in field 689");
    LOG_INFO("found " + std::to_string(reference_counts["689*"]) + " direct references in field 689");
    LOG_INFO("found " + std::to_string(reference_counts["655"]) + " references in field 655");
}

} // unnamed namespace

int Main(int argc, char **argv) {
    if (argc != 4)
        ::Usage("ixtheo_titles authority_records augmented_ixtheo_titles");

    const std::string title_input_filename(argv[1]);
    const std::string authority_filename(argv[2]);
    const std::string title_output_filename(argv[3]);
    if (unlikely(title_input_filename == title_output_filename))
        LOG_ERROR("Title input file name equals title output file name!");
    if (unlikely(title_input_filename == authority_filename))
        LOG_ERROR("Title input file name equals authority file name!");
    if (unlikely(title_output_filename == authority_filename))
        LOG_ERROR("Title output file name equals authority file name!");

    auto authority_reader(MARC::Reader::Factory(authority_filename));
    std::unordered_map<std::string, std::string> authority_ppns_to_canon_law_codes_map;
    LoadAuthorityData(authority_reader.get(), &authority_ppns_to_canon_law_codes_map);

    auto title_reader(MARC::Reader::Factory(title_input_filename));
    auto title_writer(MARC::Writer::Factory(title_output_filename));
    ProcessRecords(title_reader.get(), title_writer.get(), authority_ppns_to_canon_law_codes_map);

    return EXIT_SUCCESS;
}
<|endoftext|>