<commit_before>/* Copyright (c) 2013-2017 Jeffrey Pfau
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VideoDumper.h"

#include <QImage>

using namespace QGBA;

VideoDumper::VideoDumper(QObject* parent)
	: QAbstractVideoSurface(parent)
{
}

bool VideoDumper::present(const QVideoFrame& frame) {
	QVideoFrame mappedFrame(frame);
	if (!mappedFrame.map(QAbstractVideoBuffer::ReadOnly)) {
		return false;
	}
	QVideoFrame::PixelFormat vFormat = mappedFrame.pixelFormat();
	QImage::Format format = QVideoFrame::imageFormatFromPixelFormat(vFormat);
	bool swap = false;
	if (format == QImage::Format_Invalid) {
		vFormat = static_cast<QVideoFrame::PixelFormat>(vFormat - QVideoFrame::Format_BGRA32 + QVideoFrame::Format_ARGB32);
		format = QVideoFrame::imageFormatFromPixelFormat(vFormat);
		if (format == QImage::Format_ARGB32) {
			format = QImage::Format_RGBA8888;
		} else if (format == QImage::Format_ARGB32_Premultiplied) {
			format = QImage::Format_RGBA8888_Premultiplied;
		}
		swap = true;
	}
	uchar* bits = mappedFrame.bits();
	QImage image(bits, mappedFrame.width(), mappedFrame.height(), mappedFrame.bytesPerLine(), format);
	if (swap) {
		image = image.rgbSwapped();
	} else {
		image = image.copy(); // Create a deep copy of the bits
	}
	mappedFrame.unmap();
	emit imageAvailable(image);
	return true;
}

QList<QVideoFrame::PixelFormat> VideoDumper::supportedPixelFormats(QAbstractVideoBuffer::HandleType) const {
	QList<QVideoFrame::PixelFormat> list;
	list.append(QVideoFrame::Format_RGB32);
	list.append(QVideoFrame::Format_ARGB32);
	list.append(QVideoFrame::Format_RGB24);
	list.append(QVideoFrame::Format_ARGB32_Premultiplied);
	list.append(QVideoFrame::Format_RGB565);
	list.append(QVideoFrame::Format_RGB555);
	list.append(QVideoFrame::Format_BGR32);
	list.append(QVideoFrame::Format_BGRA32);
	list.append(QVideoFrame::Format_BGR24);
	list.append(QVideoFrame::Format_BGRA32_Premultiplied);
	list.append(QVideoFrame::Format_BGR565);
	list.append(QVideoFrame::Format_BGR555);
	return list;
}
<commit_msg>Qt: Work around Qt DirectShow bug (fixes #829)<commit_after>/* Copyright (c) 2013-2017 Jeffrey Pfau
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VideoDumper.h"

#include <QImage>

using namespace QGBA;

VideoDumper::VideoDumper(QObject* parent)
	: QAbstractVideoSurface(parent)
{
}

bool VideoDumper::present(const QVideoFrame& frame) {
	QVideoFrame mappedFrame(frame);
	if (!mappedFrame.map(QAbstractVideoBuffer::ReadOnly)) {
		return false;
	}
	QVideoFrame::PixelFormat vFormat = mappedFrame.pixelFormat();
	QImage::Format format = QVideoFrame::imageFormatFromPixelFormat(vFormat);
	bool swap = false;
	if (format == QImage::Format_Invalid) {
		vFormat = static_cast<QVideoFrame::PixelFormat>(vFormat - QVideoFrame::Format_BGRA32 + QVideoFrame::Format_ARGB32);
		format = QVideoFrame::imageFormatFromPixelFormat(vFormat);
		if (format == QImage::Format_ARGB32) {
			format = QImage::Format_RGBA8888;
		} else if (format == QImage::Format_ARGB32_Premultiplied) {
			format = QImage::Format_RGBA8888_Premultiplied;
		}
		swap = true;
	}
	uchar* bits = mappedFrame.bits();
	QImage image(bits, mappedFrame.width(), mappedFrame.height(), mappedFrame.bytesPerLine(), format);
	if (swap) {
		image = image.rgbSwapped();
	} else {
#ifdef Q_OS_WIN
		// Qt's DirectShow plug-in is pretty dang buggy
		image = image.mirrored(true);
#else
		image = image.copy(); // Create a deep copy of the bits
#endif
	}
	mappedFrame.unmap();
	emit imageAvailable(image);
	return true;
}

QList<QVideoFrame::PixelFormat> VideoDumper::supportedPixelFormats(QAbstractVideoBuffer::HandleType) const {
	QList<QVideoFrame::PixelFormat> list;
	list.append(QVideoFrame::Format_RGB32);
	list.append(QVideoFrame::Format_ARGB32);
	list.append(QVideoFrame::Format_RGB24);
	list.append(QVideoFrame::Format_ARGB32_Premultiplied);
	list.append(QVideoFrame::Format_RGB565);
	list.append(QVideoFrame::Format_RGB555);
	list.append(QVideoFrame::Format_BGR32);
	list.append(QVideoFrame::Format_BGRA32);
	list.append(QVideoFrame::Format_BGR24);
	list.append(QVideoFrame::Format_BGRA32_Premultiplied);
	list.append(QVideoFrame::Format_BGR565);
	list.append(QVideoFrame::Format_BGR555);
	return list;
}
<|endoftext|>


<commit_before>#include <sensors.h>
#include <iostream>

using namespace std;

sensors::sensors()
{
	cout << "Initiating sensors" << endl;
}

sensors::~sensors()
{
	cout << "Termination sensors" << endl;
}<commit_msg>sensor_ox() function was implemented<commit_after>#include <sensors.h>
#include <iostream>

using namespace std;

sensors::sensors()
{
	cout << "Initiating sensors" << endl;
}

sensors::~sensors()
{
	cout << "Termination sensors" << endl;
}

char sensor_ox()
{
	return 'a';
}
<|endoftext|>


<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include <xenia/kernel/xam/xam_info.h>

#include <xenia/kernel/shim_utils.h>
#include <xenia/kernel/xex2.h>
#include <xenia/kernel/xam/xam_private.h>
#include <xenia/kernel/xam/xam_state.h>

using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::xam;

namespace xe {
namespace kernel {
namespace xam {

SHIM_CALL XGetAVPack_shim(
    PPCContext* ppc_state, XamState* state) {
  // DWORD
  // Not sure what the values are for this, but 6 is VGA.
  // Other likely values are 3/4/8 for HDMI or something.
  // Games seem to use this as a PAL check - if the result is not 3/4/6/8
  // they explode with errors if not in PAL mode.
  SHIM_SET_RETURN(6);
}

SHIM_CALL XGetGameRegion_shim(
    PPCContext* ppc_state, XamState* state) {
  XELOGD("XGetGameRegion()");

  SHIM_SET_RETURN(XEX_REGION_ALL);
}

SHIM_CALL XGetLanguage_shim(
    PPCContext* ppc_state, XamState* state) {
  XELOGD("XGetLanguage()");

  uint32_t desired_language = X_LANGUAGE_ENGLISH;

  // Switch the language based on game region.
  // TODO(benvanik): pull from xex header.
  uint32_t game_region = XEX_REGION_NTSCU;
  if (game_region & XEX_REGION_NTSCU) {
    desired_language = X_LANGUAGE_ENGLISH;
  } else if (game_region & XEX_REGION_NTSCJ) {
    desired_language = X_LANGUAGE_JAPANESE;
  }
  // Add more overrides?

  SHIM_SET_RETURN(desired_language);
}

}  // namespace xam
}  // namespace kernel
}  // namespace xe

void xe::kernel::xam::RegisterInfoExports(
    ExportResolver* export_resolver, XamState* state) {
  SHIM_SET_MAPPING("xam.xex", XGetAVPack, state);
  SHIM_SET_MAPPING("xam.xex", XGetGameRegion, state);
  SHIM_SET_MAPPING("xam.xex", XGetLanguage, state);
}
<commit_msg>XamGetSystemVersion = 0 to stop dynamic kernel function loading (for now).<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include <xenia/kernel/xam/xam_info.h>

#include <xenia/kernel/shim_utils.h>
#include <xenia/kernel/xex2.h>
#include <xenia/kernel/xam/xam_private.h>
#include <xenia/kernel/xam/xam_state.h>

using namespace xe;
using namespace xe::kernel;
using namespace xe::kernel::xam;

namespace xe {
namespace kernel {
namespace xam {

SHIM_CALL XamGetSystemVersion_shim(
    PPCContext* ppc_state, XamState* state) {
  XELOGD("XamGetSystemVersion()");
  // eh, just picking one. If we go too low we may break new games, but
  // this value seems to be used for conditionally loading symbols and if
  // we pretend to be old we have less to worry with implementing.
  // 0x200A3200
  // 0x20096B00
  SHIM_SET_RETURN(0);
}

SHIM_CALL XGetAVPack_shim(
    PPCContext* ppc_state, XamState* state) {
  // DWORD
  // Not sure what the values are for this, but 6 is VGA.
  // Other likely values are 3/4/8 for HDMI or something.
  // Games seem to use this as a PAL check - if the result is not 3/4/6/8
  // they explode with errors if not in PAL mode.
  SHIM_SET_RETURN(6);
}

SHIM_CALL XGetGameRegion_shim(
    PPCContext* ppc_state, XamState* state) {
  XELOGD("XGetGameRegion()");

  SHIM_SET_RETURN(XEX_REGION_ALL);
}

SHIM_CALL XGetLanguage_shim(
    PPCContext* ppc_state, XamState* state) {
  XELOGD("XGetLanguage()");

  uint32_t desired_language = X_LANGUAGE_ENGLISH;

  // Switch the language based on game region.
  // TODO(benvanik): pull from xex header.
  uint32_t game_region = XEX_REGION_NTSCU;
  if (game_region & XEX_REGION_NTSCU) {
    desired_language = X_LANGUAGE_ENGLISH;
  } else if (game_region & XEX_REGION_NTSCJ) {
    desired_language = X_LANGUAGE_JAPANESE;
  }
  // Add more overrides?

  SHIM_SET_RETURN(desired_language);
}

}  // namespace xam
}  // namespace kernel
}  // namespace xe

void xe::kernel::xam::RegisterInfoExports(
    ExportResolver* export_resolver, XamState* state) {
  SHIM_SET_MAPPING("xam.xex", XamGetSystemVersion, state);
  SHIM_SET_MAPPING("xam.xex", XGetAVPack, state);
  SHIM_SET_MAPPING("xam.xex", XGetGameRegion, state);
  SHIM_SET_MAPPING("xam.xex", XGetLanguage, state);
}
<|endoftext|>


<commit_before>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
// File: StackBuilderSink.cpp
//

//
// Purpose: Native implementation for System.Runtime.Remoting.Messaging.StackBuilderSink
//

#include "common.h"

#ifdef FEATURE_REMOTING

#include "excep.h"
#include "message.h"
#include "stackbuildersink.h"
#include "dbginterface.h"
#include "remoting.h"
#include "profilepriv.h"
#include "class.h"

struct ArgInfo
{
    PBYTE             dataLocation;
    INT32             dataSize;
    TypeHandle        dataTypeHandle;
    BYTE              dataType;
    BYTE              byref;
};

//+----------------------------------------------------------------------------
//
//  Method:     CStackBuilderSink::PrivateProcessMessage, public
//
//  Synopsis:   Builds the stack and calls an object
//
//
//+----------------------------------------------------------------------------
FCIMPL5(Object*, CStackBuilderSink::PrivateProcessMessage,
                                        Object* pSBSinkUNSAFE,
                                        MethodDesc* pMD,
                                        PTRArray* pArgsUNSAFE,
                                        Object* pServerUNSAFE,
                                        PTRARRAYREF* ppVarOutParams)
{
    CONTRACTL
    {
        FCALL_CHECK;
        PRECONDITION(CheckPointer(pMD));
        PRECONDITION(!pMD->IsGenericMethodDefinition());
        PRECONDITION(pMD->IsRuntimeMethodHandle());
    }
    CONTRACTL_END;

    struct _gc
    {
        PTRARRAYREF pArgs;
        OBJECTREF pServer;
        OBJECTREF pSBSink;
        OBJECTREF ret;
    } gc;
    gc.pArgs = (PTRARRAYREF) pArgsUNSAFE;
    gc.pServer = (OBJECTREF) pServerUNSAFE;
    gc.pSBSink = (OBJECTREF) pSBSinkUNSAFE;
    gc.ret = NULL;

    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);

    // pMD->IsStatic() is SO_INTOLERANT.
    // Either pServer is non-null or the method is static (but not both)
    _ASSERTE( (pServerUNSAFE!=NULL) == !(pMD->IsStatic()) );

    LOG((LF_REMOTING, LL_INFO10, "CStackBuilderSink::PrivateProcessMessage\n"));

    MethodDesc *pResolvedMD = pMD;
    // Check if this is an interface invoke, if yes, then we have to find the
    // real method descriptor on the class of the server object.
    if(pMD->GetMethodTable()->IsInterface())
    {
        _ASSERTE(gc.pServer != NULL);

        // NOTE: This method can trigger GC
        // The last parameter (true) causes the method to take into account that
        // the object passed in is a TP and try to resolve the interface MD into
        // a server MD anyway (normally the call short circuits thunking objects
        // and just returns the interface MD unchanged).
        MethodTable *pRealMT = gc.pServer->GetTrueMethodTable();

#ifdef FEATURE_COMINTEROP
        if (pRealMT->IsComObjectType())
            pResolvedMD = pRealMT->GetMethodDescForComInterfaceMethod(pMD, true);
        else
#endif // FEATURE_COMINTEROP
        {
            if (pRealMT->ImplementsInterface(pMD->GetMethodTable()))
            {
                pResolvedMD = pRealMT->GetMethodDescForInterfaceMethod(TypeHandle(pMD->GetMethodTable()), pMD);

                // If the method is generic then we have more work to do --
                // we'll get back the generic method descriptor and we'll have
                // to load the version with the right instantiation (get the
                // instantiation from the interface method).
                if (pResolvedMD->HasMethodInstantiation())
                {
                    _ASSERTE(pResolvedMD->IsGenericMethodDefinition());
                    _ASSERTE(pMD->GetNumGenericMethodArgs() == pResolvedMD->GetNumGenericMethodArgs());

                    pResolvedMD = MethodDesc::FindOrCreateAssociatedMethodDesc(pResolvedMD,
                                                                               pRealMT,
                                                                               FALSE,
                                                                               pMD->GetMethodInstantiation(),
                                                                               FALSE);

                    _ASSERTE(!pResolvedMD->ContainsGenericVariables());
                }
            }
            else
                pResolvedMD = NULL;
        }

        if(!pResolvedMD)
        {
            MAKE_WIDEPTR_FROMUTF8(wName, pMD->GetName());
            COMPlusThrow(kMissingMethodException, IDS_EE_MISSING_METHOD, wName);
        }
    }

    // <TODO>This looks a little dodgy for generics: pResolvedMD has been interface-resolved but not
    // virtual-resolved.  So we seem to be taking the signature of a
    // half-resolved-virtual-call.  But the MetaSig
    // is only used for GC purposes, and thus is probably OK: although the
    // metadata for the signature of a call may be different
    // as we move to base classes, the instantiated version
    // of the signature will still be the same
    // at both the callsite and the target). </TODO>
    MetaSig mSig(pResolvedMD);

    // get the target depending on whether the method is virtual or non-virtual
    // like a constructor, private or final method
    PCODE pTarget = pResolvedMD->GetCallTarget(&(gc.pServer));

    VASigCookie *pCookie = NULL;
    _ASSERTE(NULL != pTarget);

        // this function does the work
    ::CallDescrWithObjectArray(
            gc.pServer,
            pResolvedMD,
            //pRM,
            pTarget,
            &mSig,
            pCookie,
            gc.pArgs,
            &gc.ret,
            ppVarOutParams);

    LOG((LF_REMOTING, LL_INFO10, "CStackBuilderSink::PrivateProcessMessage OUT\n"));

    HELPER_METHOD_FRAME_END();

    return OBJECTREFToObject(gc.ret);
}
FCIMPLEND

class ProfilerServerCallbackHolder
{
public:
    ProfilerServerCallbackHolder(Thread* pThread) : m_pThread(pThread)
    {
#ifdef PROFILING_SUPPORTED
        // If we're profiling, notify the profiler that we're about to invoke the remoting target
        {
            BEGIN_PIN_PROFILER(CORProfilerTrackRemoting());
            GCX_PREEMP();
            g_profControlBlock.pProfInterface->RemotingServerInvocationStarted();
            END_PIN_PROFILER();
        }
#endif // PROFILING_SUPPORTED
    }

    ~ProfilerServerCallbackHolder()
    {
#ifdef PROFILING_SUPPORTED
        // If profiling is active, tell profiler we've made the call, received the
        // return value, done any processing necessary, and now remoting is done.
        {
            BEGIN_PIN_PROFILER(CORProfilerTrackRemoting());
            GCX_PREEMP();
            g_profControlBlock.pProfInterface->RemotingServerInvocationReturned();
            END_PIN_PROFILER();
        }
#endif // PROFILING_SUPPORTED
    }

private:
    Thread* m_pThread;
};

//+----------------------------------------------------------------------------
//
//  Function:   CallDescrWithObjectArray, private
//
//  Synopsis:   Builds the stack from a object array and call the object
//
//
// Note this function triggers GC and assumes that pServer, pArguments, pVarRet, and ppVarOutParams are
// all already protected!!
//+----------------------------------------------------------------------------
void CallDescrWithObjectArray(OBJECTREF& pServer,
                  //ReflectMethod *pRM,
                  MethodDesc *pMeth,
                  PCODE pTarget,
                  MetaSig* sig,
                  VASigCookie *pCookie,
                  PTRARRAYREF& pArgArray,
                  OBJECTREF *pVarRet,
                  PTRARRAYREF *ppVarOutParams)
{
    CONTRACTL
    {
        THROWS;
        GC_TRIGGERS;
        MODE_COOPERATIVE;
        INJECT_FAULT(COMPlusThrowOM());
    }
    CONTRACTL_END;

    LOG((LF_REMOTING, LL_INFO10, "CallDescrWithObjectArray IN\n"));

#ifdef _PREFAST_
#pragma warning(push)
#pragma warning(disable:6263) // "Suppress PREFast warning about _alloca in a loop"
    // _alloca is called within a loop in a number of places within this method
    // (as an ultra fast means of acquiring temporary storage). This can be a
    // problem in some scenarios (swiftly drive us to stack overflow). But in
    // this case the allocations are tightly bounded (by the number of arguments
    // in the target method) and the allocations themselves are small (no worse
    // really than calling the method an extra time).
#endif

    ByRefInfo *pByRefs = NULL;
    FrameWithCookie<ProtectValueClassFrame> *pProtectValueClassFrame = NULL;
    FrameWithCookie<ProtectByRefsFrame> *pProtectionFrame = NULL;
    UINT  nStackBytes = 0;
    LPBYTE pAlloc = 0;
    LPBYTE pTransitionBlock = 0;
    UINT32 numByRef = 0;
    //DWORD attr = pRM->dwFlags;
#ifdef _DEBUG
    //MethodDesc *pMD = pRM->pMethod;
#endif
    ValueClassInfo *pValueClasses = NULL;

    // check the calling convention

    BYTE callingconvention = sig->GetCallingConvention();
    if (!isCallConv(callingconvention, IMAGE_CEE_CS_CALLCONV_DEFAULT))
    {
        _ASSERTE(!"This calling convention is not supported.");
        COMPlusThrow(kInvalidProgramException);
    }

    // Make sure we are properly loaded
    CONSISTENCY_CHECK(GetAppDomain()->CheckCanExecuteManagedCode(pMeth));

    // Note this is redundant with the above but we do it anyway for safety
    pMeth->EnsureActive();

#ifdef DEBUGGING_SUPPORTED
    // debugger goo What does this do? can someone put a comment here?
    if (CORDebuggerTraceCall())
    {
        g_pDebugInterface->TraceCall((const BYTE *)pTarget);
    }
#endif // DEBUGGING_SUPPORTED

    Thread * pThread = GetThread();

    {
        ProfilerServerCallbackHolder profilerHolder(pThread);

    ArgIterator argit(sig);

    // Create a fake FramedMethodFrame on the stack.
    nStackBytes = argit.SizeOfFrameArgumentArray();

    UINT32 cbAlloc = 0;
    if (!ClrSafeInt<UINT32>::addition(TransitionBlock::GetNegSpaceSize(), sizeof(TransitionBlock), cbAlloc))
        COMPlusThrow(kArgumentException);
    if (!ClrSafeInt<UINT32>::addition(cbAlloc, nStackBytes, cbAlloc))
        COMPlusThrow(kArgumentException);

    pAlloc = (LPBYTE)_alloca(cbAlloc);
    pTransitionBlock = pAlloc + TransitionBlock::GetNegSpaceSize();

    // cycle through the parameters and see if there are byrefs
    BOOL   fHasByRefs = FALSE;

    //if (attr & RM_ATTR_BYREF_FLAG_SET)
    //    fHasByRefs = attr & RM_ATTR_HAS_BYREF_ARG;
    //else
    {
        sig->Reset();
        CorElementType typ;
        while ((typ = sig->NextArg()) != ELEMENT_TYPE_END)
        {
            if (typ == ELEMENT_TYPE_BYREF)
            {
                fHasByRefs = TRUE;
                //attr |= RM_ATTR_HAS_BYREF_ARG;
                break;
            }
        }
        //attr |= RM_ATTR_BYREF_FLAG_SET;
        //pRM->dwFlags = attr;
        sig->Reset();
    }

    UINT32 nFixedArgs = sig->NumFixedArgs();
    // To avoid any security problems with integer overflow/underflow we're
    // going to validate the number of args here (we're about to _alloca an
    // array of ArgInfo structures and maybe a managed object array as well
    // based on this count).
    _ASSERTE(sizeof(Object*) <= sizeof(ArgInfo));
    UINT32 nMaxArgs = UINT32_MAX / sizeof(ArgInfo);
    if (nFixedArgs > nMaxArgs)
        COMPlusThrow(kArgumentException);

    // if there are byrefs allocate and array for the out parameters
    if (fHasByRefs)
    {
        *ppVarOutParams = PTRARRAYREF(AllocateObjectArray(sig->NumFixedArgs(), g_pObjectClass));

        // Null out the array
        memset(&(*ppVarOutParams)->m_Array, 0, sizeof(OBJECTREF) * sig->NumFixedArgs());
    }

    OBJECTREF *ppThis = NULL;

    if (sig->HasThis())
    {
        ppThis = (OBJECTREF*)(pTransitionBlock + argit.GetThisOffset());

        // *ppThis is not GC protected. It will be set to the right value
        // after all object allocations are made.
        *ppThis = NULL;
    }

    // if we have the Value Class return, we need to allocate that class and place a pointer to it on the stack.

    *pVarRet = NULL;
    TypeHandle retType = sig->GetRetTypeHandleThrowing();
    // Note that we want the unnormalized (signature) type because GetStackObject
    // boxes as the element type, which if we normalized it would loose information.
    CorElementType retElemType = sig->GetReturnType();

    // The MethodTable pointer of the return type, if that's a struct
    MethodTable* pStructRetTypeMT = NULL;

        // Allocate a boxed struct instance to hold the return value in any case.
    if (retElemType == ELEMENT_TYPE_VALUETYPE)
    {
        pStructRetTypeMT = retType.GetMethodTable();
        *pVarRet = pStructRetTypeMT->Allocate();
    }
    else  {
        _ASSERTE(!argit.HasRetBuffArg());
    }

#ifdef CALLDESCR_REGTYPEMAP
    UINT64  dwRegTypeMap    = 0;
    BYTE*   pMap            = (BYTE*)&dwRegTypeMap;
#endif // CALLDESCR_REGTYPEMAP

#ifdef CALLDESCR_FPARGREGS
    FloatArgumentRegisters *pFloatArgumentRegisters = NULL;
#endif // CALLDESCR_FPARGREGS

    // gather data about the parameters by iterating over the sig:
    UINT32 arg = 0;
    int    ofs = 0;

    // REVIEW: need to use actual arg count if VarArgs are supported
    ArgInfo* pArgInfoStart = (ArgInfo*) _alloca(nFixedArgs*sizeof(ArgInfo));

#ifdef _DEBUG
    // We expect to write useful data over every part of this so need
    // not do this in retail!
    memset((void *)pArgInfoStart, 0, sizeof(ArgInfo)*nFixedArgs);
#endif

    for (; TransitionBlock::InvalidOffset != (ofs = argit.GetNextOffset()); arg++)
    {
        CONSISTENCY_CHECK(arg < nFixedArgs);
        ArgInfo* pArgInfo = pArgInfoStart + arg;

#ifdef CALLDESCR_REGTYPEMAP
        FillInRegTypeMap(ofs, argit.GetArgType(), pMap);
#endif

#ifdef CALLDESCR_FPARGREGS
        // Under CALLDESCR_FPARGREGS we can have arguments in floating point registers. If we have at
        // least one such argument we point the call worker at the floating point area of the frame (we leave
        // it null otherwise since the worker can perform a useful optimization if it knows no floating point
        // registers need to be set up).
        if (TransitionBlock::HasFloatRegister(ofs, argit.GetArgLocDescForStructInRegs()) &&
            (pFloatArgumentRegisters == NULL))
        {
            pFloatArgumentRegisters = (FloatArgumentRegisters*)(pTransitionBlock +
                                                                TransitionBlock::GetOffsetOfFloatArgumentRegisters());
        }
#endif

        if (argit.GetArgType() == ELEMENT_TYPE_BYREF)
        {
            TypeHandle ty = TypeHandle();
            CorElementType brType = sig->GetByRefType(&ty);
            if (CorIsPrimitiveType(brType))
            {
                pArgInfo->dataSize = gElementTypeInfo[brType].m_cbSize;
            }
            else if (ty.IsValueType())
            {
                pArgInfo->dataSize = ty.GetMethodTable()->GetNumInstanceFieldBytes();
                numByRef ++;
            }
            else
            {
                pArgInfo->dataSize = sizeof(Object *);
                numByRef ++;
            }

            ByRefInfo *brInfo = (ByRefInfo *) _alloca(offsetof(ByRefInfo,data) + pArgInfo->dataSize);
            brInfo->argIndex = arg;
            brInfo->typ = brType;
            brInfo->typeHandle = ty;
            brInfo->pNext = pByRefs;
            pByRefs = brInfo;
            pArgInfo->dataLocation = (BYTE*)brInfo->data;
            *((void**)(pTransitionBlock + ofs)) = (void*)pArgInfo->dataLocation;
            pArgInfo->dataTypeHandle = ty;
            pArgInfo->dataType = static_cast<BYTE>(brType);
            pArgInfo->byref = TRUE;
        }
        else
        {
            pArgInfo->dataLocation = pTransitionBlock + ofs;
            pArgInfo->dataSize = argit.GetArgSize();
            pArgInfo->dataTypeHandle = sig->GetLastTypeHandleThrowing(); // this may cause GC!
            pArgInfo->dataType = (BYTE)argit.GetArgType();
            pArgInfo->byref = FALSE;
        }
    }

    if (ppThis)
    {
        // If this isn't a value class, verify the objectref
#ifdef _DEBUG
        //if (pMD->GetMethodTable()->IsValueType() == FALSE)
        //{
        //    VALIDATEOBJECTREF(pServer);
        //}
#endif //_DEBUG
        *ppThis = pServer;
    }

    PVOID pRetBufStackData = NULL;

    if (argit.HasRetBuffArg())
    {
        // If the return buffer *must* be a stack-allocated object, allocate it.
        PVOID pRetBufData = NULL;
        if (pStructRetTypeMT->IsStructRequiringStackAllocRetBuf())
        {
            SIZE_T sz = pStructRetTypeMT->GetNumInstanceFieldBytes();
            pRetBufData = pRetBufStackData = _alloca(sz);
            memset(pRetBufData, 0, sz);
            pValueClasses = new (_alloca(sizeof(ValueClassInfo))) ValueClassInfo(pRetBufStackData, pStructRetTypeMT, pValueClasses);
        }
        else
        {
            pRetBufData = (*pVarRet)->GetData();
        }
        *((LPVOID*) (pTransitionBlock + argit.GetRetBuffArgOffset())) = pRetBufData;
    }

    // There should be no GC when we fill up the stack with parameters, as we don't protect them
    // Assignment of "*ppThis" above triggers the point where we become unprotected.
    {
        GCX_FORBID();

        PBYTE             dataLocation;
        INT32             dataSize;
        TypeHandle        dataTypeHandle;
        BYTE              dataType;

        OBJECTREF* pArguments = pArgArray->m_Array;
        UINT32 i;
        for (i=0; i<nFixedArgs; i++)
        {
            ArgInfo* pArgInfo = pArgInfoStart + i;

            dataSize = pArgInfo->dataSize;
            dataLocation = pArgInfo->dataLocation;
            dataTypeHandle = pArgInfo->dataTypeHandle;
            dataType = pArgInfo->dataType;

                // Nullable<T> needs special treatment, even if it is 1, 2, 4, or 8 bytes
            if (dataType == ELEMENT_TYPE_VALUETYPE)
                goto DEFAULT_CASE;

            switch (dataSize)
            {
                case 1:
                    // This "if" statement is necessary to make the assignement big-endian aware
                    if (pArgInfo->byref)
                        *((INT8*)dataLocation) = *((INT8*)pArguments[i]->GetData());
                    else
                        *(StackElemType*)dataLocation = (StackElemType)*((INT8*)pArguments[i]->GetData());
                    break;
                case 2:
                    // This "if" statement is necessary to make the assignement big-endian aware
                    if (pArgInfo->byref)
                    *((INT16*)dataLocation) = *((INT16*)pArguments[i]->GetData());
                    else
                        *(StackElemType*)dataLocation = (StackElemType)*((INT16*)pArguments[i]->GetData());
                    break;
                case 4:
#ifndef _WIN64
                    if ((dataType == ELEMENT_TYPE_STRING)  ||
                        (dataType == ELEMENT_TYPE_OBJECT)  ||
                        (dataType == ELEMENT_TYPE_CLASS)   ||
                        (dataType == ELEMENT_TYPE_SZARRAY) ||
                        (dataType == ELEMENT_TYPE_ARRAY))
                    {
                        *(OBJECTREF *)dataLocation = pArguments[i];
                    }
                    else
                    {
                        *(StackElemType*)dataLocation = (StackElemType)*((INT32*)pArguments[i]->GetData());
                    }
#else // !_WIN64
                    // This "if" statement is necessary to make the assignement big-endian aware
                    if (pArgInfo->byref)
                        *(INT32*)dataLocation = *((INT32*)pArguments[i]->GetData());
                    else
                        *(StackElemType*)dataLocation = (StackElemType)*((INT32*)pArguments[i]->GetData());
#endif // !_WIN64
                    break;

                case 8:
#ifdef _WIN64
                    if ((dataType == ELEMENT_TYPE_STRING)  ||
                        (dataType == ELEMENT_TYPE_OBJECT)  ||
                        (dataType == ELEMENT_TYPE_CLASS)   ||
                        (dataType == ELEMENT_TYPE_SZARRAY) ||
                        (dataType == ELEMENT_TYPE_ARRAY))
                    {
                        *(OBJECTREF *)dataLocation = pArguments[i];
                    }
                    else
                    {
                        *((INT64*)dataLocation) = *((INT64*)pArguments[i]->GetData());
                    }
#else // _WIN64
                    *((INT64*)dataLocation) = *((INT64*)pArguments[i]->GetData());
#endif // _WIN64
                    break;

                default:
                {
                DEFAULT_CASE:
                    MethodTable * pMT = dataTypeHandle.GetMethodTable();

#ifdef ENREGISTERED_PARAMTYPE_MAXSIZE
                    // We do not need to allocate a buffer if the argument is already passed by reference.
                    if (!pArgInfo->byref && ArgIterator::IsArgPassedByRef(dataTypeHandle))
                    {
                        PVOID pvArg = _alloca(dataSize);
                        pMT->UnBoxIntoUnchecked(pvArg, pArguments[i]);
                        *(PVOID*)dataLocation = pvArg;

                        pValueClasses = new (_alloca(sizeof(ValueClassInfo))) ValueClassInfo(pvArg, pMT, pValueClasses);
                    }
                    else
#endif
                    {
                        pMT->UnBoxIntoUnchecked(dataLocation, pArguments[i]);
                    }
                }
            }
        }

#ifdef _DEBUG
        // Should not be using this any more
        memset((void *)pArgInfoStart, 0, sizeof(ArgInfo)*nFixedArgs);
#endif

        // if there were byrefs, push a protection frame
        if (pByRefs && numByRef > 0)
        {
            char *pBuffer = (char*)_alloca (sizeof (FrameWithCookie<ProtectByRefsFrame>));
            pProtectionFrame = new (pBuffer) FrameWithCookie<ProtectByRefsFrame>(pThread, pByRefs);
        }

        // If there were any value classes that must be protected by the
        // caller, push a ProtectValueClassFrame.
        if (pValueClasses)
        {
            char *pBuffer = (char*)_alloca (sizeof (FrameWithCookie<ProtectValueClassFrame>));
            pProtectValueClassFrame = new (pBuffer) FrameWithCookie<ProtectValueClassFrame>(pThread, pValueClasses);
        }

    } // GCX_FORBID

    UINT fpReturnSize = argit.GetFPReturnSize();

    CallDescrData callDescrData;

    callDescrData.pSrc = pTransitionBlock + sizeof(TransitionBlock);
    callDescrData.numStackSlots = nStackBytes / STACK_ELEM_SIZE;
#ifdef CALLDESCR_ARGREGS
    callDescrData.pArgumentRegisters = (ArgumentRegisters*)(pTransitionBlock + TransitionBlock::GetOffsetOfArgumentRegisters());
#endif
#ifdef CALLDESCR_FPARGREGS
    callDescrData.pFloatArgumentRegisters = pFloatArgumentRegisters;
#endif
#ifdef CALLDESCR_REGTYPEMAP
    callDescrData.dwRegTypeMap = dwRegTypeMap;
#endif
    callDescrData.fpReturnSize = fpReturnSize;
    callDescrData.pTarget = pTarget;

    CallDescrWorkerWithHandler(&callDescrData);

        // It is still illegal to do a GC here.  The return type might have/contain GC pointers.
    if (retElemType == ELEMENT_TYPE_VALUETYPE)
    {
        _ASSERTE(*pVarRet != NULL);            // we have already allocated a return object
        PVOID pVarRetData = (*pVarRet)->GetData();

        // If the return result was passed back in registers, then copy it into the return object
        if (!argit.HasRetBuffArg())
        {
            CopyValueClass(pVarRetData, &callDescrData.returnValue, (*pVarRet)->GetMethodTable(), (*pVarRet)->GetAppDomain());
        }
        else if (pRetBufStackData != NULL)
        {
            // Copy the stack-allocated ret buff to the heap-allocated one.
            CopyValueClass(pVarRetData, pRetBufStackData, (*pVarRet)->GetMethodTable(), (*pVarRet)->GetAppDomain());
        }

        // If the return is a Nullable<T>, box it using Nullable<T> conventions.
        // TODO: this double allocates on constructions which is wasteful
        if (!retType.IsNull())
            *pVarRet = Nullable::NormalizeBox(*pVarRet);
    }
    else
        CMessage::GetObjectFromStack(pVarRet, &callDescrData.returnValue, retElemType, retType);

        // You can now do GCs if you want to

    if (pProtectValueClassFrame)
        pProtectValueClassFrame->Pop(pThread);

    // extract the out args from the byrefs
    if (pByRefs)
    {
        do
        {
            // Always extract the data ptr every time we enter this loop because
            // calls to GetObjectFromStack below can cause a GC.
            // Even this is not enough, because that we are passing a pointer to GC heap
            // to GetObjectFromStack .  If GC happens, nobody is protecting the passed in pointer.

            OBJECTREF pTmp = NULL;
            void* dataLocation = pByRefs->data;
            CMessage::GetObjectFromStack(&pTmp, &dataLocation, pByRefs->typ, pByRefs->typeHandle, TRUE);
            (*ppVarOutParams)->SetAt(pByRefs->argIndex, pTmp);
            pByRefs = pByRefs->pNext;
        }
        while (pByRefs);

        if (pProtectionFrame)
            pProtectionFrame->Pop(pThread);
    }

    }  // ProfilerServerCallbackHolder

#ifdef _PREFAST_
#pragma warning(pop)
#endif

    LOG((LF_REMOTING, LL_INFO10, "CallDescrWithObjectArray OUT\n"));
}

#endif // FEATURE_REMOTING
<commit_msg>Remove dead stackbuildersink.cpp<commit_after><|endoftext|>


<commit_before>#include "fileinputstream.h"
#include "stringterminatedsubstream.h"
#include "xmlindexwriter.h"
#include <iostream>
using namespace Strigi;
using namespace std;

string
readHeader(InputStream* f) {
    StringTerminatedSubStream header(f, "\r\n\r\n");
    string h;
    const char* d;
    int32_t nread = header.read(d, 1000, 0);
    while (nread > 0) {
        h.append(d, nread);
        nread = header.read(d, 1000, 0);
    }
    return h;
}

/**
 * Start parsing a file. The stream must be positioned at the start of the file
 * header.
 **/
bool
parseFile(StreamAnalyzer& sa, XmlIndexManager& manager,
        FileInputStream& f, const string& delim) {
    string header = readHeader(&f);
    string filename;
    const char* start = header.c_str();
    start = strstr(start, "filename=");
    if (start) {
        start += 9;
        const char* end = 0;
        char c = *start;
        if (c == '\'' || c == '"') {
            start += 1;
            end = strchr(start, c);
        }
        if (end) {
            filename.assign(start, end-start);
        } else {
            filename.assign(start);
        }
    }

    // analyzer the stream
    StringTerminatedSubStream stream(&f, delim);
    if (filename.size()) {
        AnalysisResult result(filename, time(0), *manager.indexWriter(), sa);
        sa.analyze(result, &stream);
    }
    // read the rest of the stream
    const char* d;
    int32_t nread = stream.read(d, 1000, 0);
    while (nread > 0) {
        nread = stream.read(d, 1000, 0);
    }

    // check if this is the last file
    nread = f.read(d, 2, 2);
    return nread == 2 && *d == '\r' && d[1] == '\n';
}

int
main() {
    const TagMapping mapping(0);
    cout << "Content-Type:text/xml;charset=UTF-8\r\n\r\n"
        "<?xml version='1.0' encoding='UTF-8'?>\n<"
        << mapping.map("metadata") << ">\n";

    // read from stdin
    FileInputStream f(stdin, "");

    // read the first line
    const char* d;
    const int32_t maxlength = 1024;
    int32_t nread = f.read(d, maxlength, maxlength);
    f.reset(0);
    if (nread < 1) {
        cout << " <error>input too small</error>\n</"
            << mapping.map("metadata") << ">\n" << flush;
        return 0;
    }

    // get out the delimiter
    const char* end = d + nread;
    const char* p = d;
    while (p < end-1 && *p != '\r') p++;
    if (*p != '\r' || p[1] != '\n') {
        cout << " <error>no delimiter line</error></"
            << mapping.map("metadata") << ">\n" << flush;
        return 0;
    }
    string delim(d, p-d);

    // skip the delimiter + '\r\n'
    f.reset(delim.length() + 2);

    // parse all files
    XmlIndexManager manager(cout, mapping);
    AnalyzerConfiguration ac;
    StreamAnalyzer sa(ac);
    sa.setIndexWriter(*manager.indexWriter());
    while (parseFile(sa, manager, f, delim));
    cout << "</" << mapping.map("metadata") << ">\n" << flush;

    return 0;
}
<commit_msg>more precise delimiter. the preceding \r\n were missing<commit_after>#include "fileinputstream.h"
#include "stringterminatedsubstream.h"
#include "xmlindexwriter.h"
#include <iostream>
using namespace Strigi;
using namespace std;

string
readHeader(InputStream* f) {
    StringTerminatedSubStream header(f, "\r\n\r\n");
    string h;
    const char* d;
    int32_t nread = header.read(d, 1000, 0);
    while (nread > 0) {
        h.append(d, nread);
        nread = header.read(d, 1000, 0);
    }
    return h;
}

/**
 * Start parsing a file. The stream must be positioned at the start of the file
 * header.
 **/
bool
parseFile(StreamAnalyzer& sa, XmlIndexManager& manager,
        FileInputStream& f, const string& delim) {

    string header = readHeader(&f);
    string filename;
    const char* start = header.c_str();
    start = strstr(start, "filename=");
    if (start) {
        start += 9;
        const char* end = 0;
        char c = *start;
        if (c == '\'' || c == '"') {
            start += 1;
            end = strchr(start, c);
        }
        if (end) {
            filename.assign(start, end-start);
        } else {
            filename.assign(start);
        }
    }

    // analyzer the stream
    StringTerminatedSubStream stream(&f, delim);
    if (filename.size()) {
        AnalysisResult result(filename, time(0), *manager.indexWriter(), sa);
        sa.analyze(result, &stream);
    }
    // read the rest of the stream
    const char* d;
    int32_t nread = stream.read(d, 1000, 0);
    while (nread > 0) {
        nread = stream.read(d, 1000, 0);
    }

    // check if this is the last file
    nread = f.read(d, 2, 2);
    return nread == 2 && *d == '\r' && d[1] == '\n';
}

int
main() {
    const TagMapping mapping(0);
    cout << "Content-Type:text/xml;charset=UTF-8\r\n\r\n"
        "<?xml version='1.0' encoding='UTF-8'?>\n<"
        << mapping.map("metadata") << ">\n";

    // read from stdin
    FileInputStream f(stdin, "");

    // read the first line
    const char* d;
    const int32_t maxlength = 1024;
    int32_t nread = f.read(d, maxlength, maxlength);
    f.reset(0);
    if (nread < 1) {
        cout << " <error>input too small</error>\n</"
            << mapping.map("metadata") << ">\n" << flush;
        return 0;
    }

    // get out the delimiter
    const char* end = d + nread;
    const char* p = d;
    while (p < end-1 && *p != '\r') p++;
    if (*p != '\r' || p[1] != '\n') {
        cout << " <error>no delimiter line</error></"
            << mapping.map("metadata") << ">\n" << flush;
        return 0;
    }
    string delim("\r\n");
    delim.append(d, p-d);

    // skip the delimiter + '\r\n'
    f.reset(delim.length() + 2);

    // parse all files
    XmlIndexManager manager(cout, mapping);
    AnalyzerConfiguration ac;
    StreamAnalyzer sa(ac);
    sa.setIndexWriter(*manager.indexWriter());
    while (parseFile(sa, manager, f, delim));
    cout << "</" << mapping.map("metadata") << ">\n" << flush;

    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <vector>
#include <random>

struct student
{
	unsigned id;
	std::wstring name;

	operator std::wstring()
	{
		auto strRep = std::wstring{L"id = "} + std::to_wstring(id) + L", name=" + name;
		return strRep;
	}
};

void printclass(std::vector<student>& c)
{
	for(auto&& s : c)
	{
		std::wcout << static_cast<std::wstring>(s) << std::endl;
	}
}

unsigned countsort(std::vector<student>& c)
{
	auto swaps = 0U;
	for(auto i = 0; i < c.size(); i++)
	{
		// keep swapping students until we are aligned
		while(c[i].id != i)
		{
			auto dest = c[i].id;
			std::swap(c[i], c[dest]);
			swaps++;
		}
	}
	return swaps;
}

void shuffle(std::vector<student>& c)
{
	static auto rando = std::minstd_rand{std::random_device{}()};
	for(auto i = 0U; i < 50; i++)
	{
		std::swap(c[i],c[rando() % 50]);
	}
}

int main(int argc, char *argv[])
{
	auto c = std::vector<student>{};
	for(auto i = 0U; i < 50; i++)
	{
		auto name = std::wstring{L"Student"} + std::to_wstring(i);
		c.push_back(student{i, name});
	}

	printclass(c);
	std::wcout << std::endl;
	shuffle(c);
	printclass(c);
	std::wcout << std::endl;

	std::wcout << L"swaps = " << countsort(c) << std::endl;
	printclass(c);

	return 0;
}<commit_msg>Small changes to countsort<commit_after>#include <iostream>
#include <string>
#include <vector>
#include <random>

struct student
{
	unsigned id;
	std::wstring name;

	operator std::wstring()
	{
		auto strRep = std::wstring{L"id = "} + std::to_wstring(id) + L", name=" + name;
		return strRep;
	}
};

void printclass(std::vector<student>& c)
{
	for(auto&& s : c)
	{
		std::wcout << static_cast<std::wstring>(s) << std::endl;
	}
}

unsigned countsort(std::vector<student>& c)
{
	auto swaps = 0U;
	for(auto i = 0; i < c.size(); i++)
	{
		// keep swapping students until we are aligned
		while(c[i].id != i)
		{
			auto dest = c[i].id;
			std::swap(c[i], c[dest]);
			++swaps;
		}
	}
	return swaps;
}

void shuffle(std::vector<student>& c)
{
	static auto rando = std::minstd_rand{std::random_device{}()};
	for(auto i = 0U; i < 50; ++i)
	{
		std::swap(c[i],c[rando() % 50]);
	}
}

int main(int argc, char *argv[])
{
	auto c = std::vector<student>{};
	for(auto i = 0U; i < 50; ++i)
	{
		auto name = std::wstring{L"Student"} + std::to_wstring(i);
		c.push_back(student{i, name});
	}

	printclass(c);
	std::wcout << std::endl;
	shuffle(c);
	printclass(c);
	std::wcout << std::endl;

	std::wcout << L"swaps = " << countsort(c) << std::endl;
	printclass(c);

	return 0;
}
<|endoftext|>


<commit_before>/* COPYRIGHT (c) 2014 Umut Acar, Arthur Chargueraud, and Michael
 * Rainey
 * All rights reserved.
 *
 * \file cmdline.cpp
 * \brief Command-line parsing routines
 *
 */

#include <string.h>
#include <utility>
#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
// NEW: remove useless includes

#include "cmdline.hpp"

namespace pasl {
namespace util {
namespace cmdline {

/***********************************************************************/
/* Command line arguments */

int global_argc = -1;
char** global_argv;
bool print_warning_on_use_of_default_value;

void set(int argc, char** argv)
{
  global_argc = argc;
  global_argv = argv;
  print_warning_on_use_of_default_value = parse_or_default_bool("warning", true, false);
}

std::string name_of_my_executable() {
  return std::string(global_argv[0]);
}

/*---------------------------------------------------------------------*/
/* Auxiliary failure functions */

static void failure()
{
   printf("sError illegal command line\n");
   exit(-1);
}

static void check_set()
{
  if (global_argc == -1) {
    printf("you must call cmdline::set(argc,argv) in your main.");
    exit(-1);
  }
}

static void check (std::string name, bool result)
{
  if (! result) {
     printf("missing command line argument %s\n", name.c_str());
     exit(-1);
  }
}

void die (const char *fmt, ...)
{
  va_list	ap;
  va_start (ap, fmt);
  vfprintf (stderr, fmt, ap);
  va_end(ap);
  exit(-1);
}

/*---------------------------------------------------------------------*/
/* Supported type of arguments */

typedef enum {
  INT,
  LONG,
  INT64,
  UINT64,
  FLOAT,
  DOUBLE,
  CHARS,
  STRING,
  BOOL,
  /* could add support for:
  INT32,
  INT64,
  UINT32,
  UINT64,
  */
} type_t;

/* Parsing of one value of a given type into a given address */

static void parse_value(type_t type, void* dest, char* arg_value)
{
  switch (type)
  {
    case INT: {
      int* vi = (int*) dest;
      *vi = atoi(arg_value);
      break; }
    case LONG: {
      long* vi = (long*) dest;
      sscanf(arg_value, "%ld", vi);
      break; }
    case INT64: {
      int64_t* vi = (int64_t*) dest;
      sscanf(arg_value, "%lld", vi);
      break; }
    case UINT64: {
      uint64_t* vi = (uint64_t*) dest;
      sscanf(arg_value, "%llu", vi);
      break; }
    case BOOL: {
      bool* vb = (bool*) dest;
      *vb = (atoi(arg_value) != 0);
      break; }
    case FLOAT: {
      float* vf = (float*) dest;
      *vf = (float)atof(arg_value);
      break; }
    case DOUBLE: {
      double* vf = (double*) dest;
      *vf = atof(arg_value);
      break; }
    case CHARS: {
      char* vs = (char*) dest;
      strcpy(vs, arg_value);
      break; }
    case STRING: {
      std::string* vs = (std::string*) dest;
      *vs = std::string(arg_value);
      break; }
    default: {
      printf("not yet supported");
      exit(-1); }
  }
}

static bool parse(type_t type, std::string name, void* dest)
{
  check_set();
  for (int a = 1; a < global_argc; a++)
  {
    if (*(global_argv[a]) != '-')
      failure();
    char* arg_name = global_argv[a] + 1;
    if (arg_name[0] == '-') {
      if (name.compare(arg_name+1) == 0) {
        *((bool*) dest) = 1;
        return true;
      }
    } else {
      a++;
      if (a >= global_argc)
        failure();
      char* arg_value = global_argv[a];
      //printf("%s %s\n", arg_name, arg_value);
      if (name.compare(arg_name) == 0) {
        parse_value(type, dest, arg_value);
        return true;
      }
    }
  }
  return false;
}

/*---------------------------------------------------------------------*/
/* Specific parsing functions */

bool parse_bool(std::string name) {
  bool r;
  check (name, parse(BOOL, name, &r));
  return r;
}

int parse_int(std::string name) {
  int r;
  check (name, parse(INT, name, &r));
  return r;
}

long parse_long(std::string name) {
  long r;
  check (name, parse(LONG, name, &r));
  return r;
}

int64_t parse_int64(std::string name) {
  int64_t r;
  check (name, parse(INT64, name, &r));
  return r;
}

uint64_t parse_uint64(std::string name) {
  uint64_t r;
  check (name, parse(UINT64, name, &r));
  return r;
}

float parse_float(std::string name) {
  float r;
  check (name, parse(FLOAT, name, &r));
  return r;
}

double parse_double(std::string name) {
  double r;
  check (name, parse(DOUBLE, name, &r));
  return r;
}

std::string parse_string(std::string name) {
  std::string r;
  check (name, parse(STRING, name, &r));
  return r;
}

/*---------------------------------------------------------------------*/
/* Specific parsing functions with default values */

template <class T>
void print_default(std::string name, T val, bool expected) {
  if (! expected || ! print_warning_on_use_of_default_value)
    return;
  std::cerr << "Warning: using default for " << name << " " << val << std::endl;
}

bool parse_or_default_bool(std::string name, bool d, bool expected) {
  bool r;
  if (parse(BOOL, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

int parse_or_default_int(std::string name, int d, bool expected) {
  int r;
  if (parse(INT, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

long parse_or_default_long(std::string name, long d, bool expected) {
  long r;
  if (parse(LONG, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

int64_t parse_or_default_int64(std::string name, int64_t d, bool expected) {
  int64_t r;
  if (parse(INT64, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

uint64_t parse_or_default_uint64(std::string name, uint64_t d, bool expected) {
  uint64_t r;
  if (parse(UINT64, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

float parse_or_default_float(std::string name, float f, bool expected) {
  float r;
  if (parse(FLOAT, name, &r)) {
    return r;
  } else {
    print_default(name, f, expected);
    return f;
  }
}

double parse_or_default_double(std::string name, double d, bool expected) {
  double r;
  if (parse(DOUBLE, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

std::string parse_or_default_string(std::string name, std::string d, bool expected) {
  std::string r;
  if (parse(STRING, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

/*---------------------------------------------------------------------*/
/* Could add support for parsing several arguments

class arg_t {
  string name;
  type_t type;
  void* dest;
  arg_t(string name, type_t type, void* dest)
    : name(name), type(type), dest(dest) {}
};

void parse_several(vector<arg_t*> args)
{
  for (vector<arg_t*>::iterator it = args.begin(); it != args.end(); it++) {
    arg_t* arg = *it;
    parse(arg->name, arg->type, arg->dest);
  }
}
*/

/*---------------------------------------------------------------------*/

static void add_dispatch_all_as_option(argmap_dispatch& c) {
  c.add("all", [&] { // runs all tests
    c.for_each_key([&] (std::string key, const thunk_type& t){
      if (key == "all")
        return;
      t();
    });
  });
}

void dispatch_by_argmap(argmap_dispatch& c, std::string arg, std::string dflt_key) {
  c.find_by_arg_or_default_key(arg, dflt_key)();
}

void dispatch_by_argmap(argmap_dispatch& c, std::string arg) {
  c.find_by_arg(arg)();
}

void dispatch_by_argmap_with_default_all(argmap_dispatch& c, std::string arg) {
  add_dispatch_all_as_option(c);
  dispatch_by_argmap(c, arg, "all");
}

/***********************************************************************/

} // end namespace
} // end namespace
} // end namespace

<commit_msg>Disable warnings for default command-line arguments.<commit_after>/* COPYRIGHT (c) 2014 Umut Acar, Arthur Chargueraud, and Michael
 * Rainey
 * All rights reserved.
 *
 * \file cmdline.cpp
 * \brief Command-line parsing routines
 *
 */

#include <string.h>
#include <utility>
#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
// NEW: remove useless includes

#include "cmdline.hpp"

namespace pasl {
namespace util {
namespace cmdline {

/***********************************************************************/
/* Command line arguments */

int global_argc = -1;
char** global_argv;
bool print_warning_on_use_of_default_value;

void set(int argc, char** argv)
{
  global_argc = argc;
  global_argv = argv;
  print_warning_on_use_of_default_value = parse_or_default_bool("warning", false, false);
}

std::string name_of_my_executable() {
  return std::string(global_argv[0]);
}

/*---------------------------------------------------------------------*/
/* Auxiliary failure functions */

static void failure()
{
   printf("sError illegal command line\n");
   exit(-1);
}

static void check_set()
{
  if (global_argc == -1) {
    printf("you must call cmdline::set(argc,argv) in your main.");
    exit(-1);
  }
}

static void check (std::string name, bool result)
{
  if (! result) {
     printf("missing command line argument %s\n", name.c_str());
     exit(-1);
  }
}

void die (const char *fmt, ...)
{
  va_list	ap;
  va_start (ap, fmt);
  vfprintf (stderr, fmt, ap);
  va_end(ap);
  exit(-1);
}

/*---------------------------------------------------------------------*/
/* Supported type of arguments */

typedef enum {
  INT,
  LONG,
  INT64,
  UINT64,
  FLOAT,
  DOUBLE,
  CHARS,
  STRING,
  BOOL,
  /* could add support for:
  INT32,
  INT64,
  UINT32,
  UINT64,
  */
} type_t;

/* Parsing of one value of a given type into a given address */

static void parse_value(type_t type, void* dest, char* arg_value)
{
  switch (type)
  {
    case INT: {
      int* vi = (int*) dest;
      *vi = atoi(arg_value);
      break; }
    case LONG: {
      long* vi = (long*) dest;
      sscanf(arg_value, "%ld", vi);
      break; }
    case INT64: {
      int64_t* vi = (int64_t*) dest;
      sscanf(arg_value, "%lld", vi);
      break; }
    case UINT64: {
      uint64_t* vi = (uint64_t*) dest;
      sscanf(arg_value, "%llu", vi);
      break; }
    case BOOL: {
      bool* vb = (bool*) dest;
      *vb = (atoi(arg_value) != 0);
      break; }
    case FLOAT: {
      float* vf = (float*) dest;
      *vf = (float)atof(arg_value);
      break; }
    case DOUBLE: {
      double* vf = (double*) dest;
      *vf = atof(arg_value);
      break; }
    case CHARS: {
      char* vs = (char*) dest;
      strcpy(vs, arg_value);
      break; }
    case STRING: {
      std::string* vs = (std::string*) dest;
      *vs = std::string(arg_value);
      break; }
    default: {
      printf("not yet supported");
      exit(-1); }
  }
}

static bool parse(type_t type, std::string name, void* dest)
{
  check_set();
  for (int a = 1; a < global_argc; a++)
  {
    if (*(global_argv[a]) != '-')
      failure();
    char* arg_name = global_argv[a] + 1;
    if (arg_name[0] == '-') {
      if (name.compare(arg_name+1) == 0) {
        *((bool*) dest) = 1;
        return true;
      }
    } else {
      a++;
      if (a >= global_argc)
        failure();
      char* arg_value = global_argv[a];
      //printf("%s %s\n", arg_name, arg_value);
      if (name.compare(arg_name) == 0) {
        parse_value(type, dest, arg_value);
        return true;
      }
    }
  }
  return false;
}

/*---------------------------------------------------------------------*/
/* Specific parsing functions */

bool parse_bool(std::string name) {
  bool r;
  check (name, parse(BOOL, name, &r));
  return r;
}

int parse_int(std::string name) {
  int r;
  check (name, parse(INT, name, &r));
  return r;
}

long parse_long(std::string name) {
  long r;
  check (name, parse(LONG, name, &r));
  return r;
}

int64_t parse_int64(std::string name) {
  int64_t r;
  check (name, parse(INT64, name, &r));
  return r;
}

uint64_t parse_uint64(std::string name) {
  uint64_t r;
  check (name, parse(UINT64, name, &r));
  return r;
}

float parse_float(std::string name) {
  float r;
  check (name, parse(FLOAT, name, &r));
  return r;
}

double parse_double(std::string name) {
  double r;
  check (name, parse(DOUBLE, name, &r));
  return r;
}

std::string parse_string(std::string name) {
  std::string r;
  check (name, parse(STRING, name, &r));
  return r;
}

/*---------------------------------------------------------------------*/
/* Specific parsing functions with default values */

template <class T>
void print_default(std::string name, T val, bool expected) {
  if (! expected || ! print_warning_on_use_of_default_value)
    return;
  std::cerr << "Warning: using default for " << name << " " << val << std::endl;
}

bool parse_or_default_bool(std::string name, bool d, bool expected) {
  bool r;
  if (parse(BOOL, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

int parse_or_default_int(std::string name, int d, bool expected) {
  int r;
  if (parse(INT, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

long parse_or_default_long(std::string name, long d, bool expected) {
  long r;
  if (parse(LONG, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

int64_t parse_or_default_int64(std::string name, int64_t d, bool expected) {
  int64_t r;
  if (parse(INT64, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

uint64_t parse_or_default_uint64(std::string name, uint64_t d, bool expected) {
  uint64_t r;
  if (parse(UINT64, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

float parse_or_default_float(std::string name, float f, bool expected) {
  float r;
  if (parse(FLOAT, name, &r)) {
    return r;
  } else {
    print_default(name, f, expected);
    return f;
  }
}

double parse_or_default_double(std::string name, double d, bool expected) {
  double r;
  if (parse(DOUBLE, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

std::string parse_or_default_string(std::string name, std::string d, bool expected) {
  std::string r;
  if (parse(STRING, name, &r)) {
    return r;
  } else {
    print_default(name, d, expected);
    return d;
  }
}

/*---------------------------------------------------------------------*/
/* Could add support for parsing several arguments

class arg_t {
  string name;
  type_t type;
  void* dest;
  arg_t(string name, type_t type, void* dest)
    : name(name), type(type), dest(dest) {}
};

void parse_several(vector<arg_t*> args)
{
  for (vector<arg_t*>::iterator it = args.begin(); it != args.end(); it++) {
    arg_t* arg = *it;
    parse(arg->name, arg->type, arg->dest);
  }
}
*/

/*---------------------------------------------------------------------*/

static void add_dispatch_all_as_option(argmap_dispatch& c) {
  c.add("all", [&] { // runs all tests
    c.for_each_key([&] (std::string key, const thunk_type& t){
      if (key == "all")
        return;
      t();
    });
  });
}

void dispatch_by_argmap(argmap_dispatch& c, std::string arg, std::string dflt_key) {
  c.find_by_arg_or_default_key(arg, dflt_key)();
}

void dispatch_by_argmap(argmap_dispatch& c, std::string arg) {
  c.find_by_arg(arg)();
}

void dispatch_by_argmap_with_default_all(argmap_dispatch& c, std::string arg) {
  add_dispatch_all_as_option(c);
  dispatch_by_argmap(c, arg, "all");
}

/***********************************************************************/

} // end namespace
} // end namespace
} // end namespace

<|endoftext|>


<commit_before>
#include "window_engine.h"

using namespace junior;
using namespace junior::_win32;

int window_engine::_window_count = 0;

window_engine::window_engine(window* owner, const wchar_t* title, const UINT32 background_color)
	: _owner(owner), _d2d_factory(nullptr), _dwrite_factory(nullptr), _screen_target(nullptr), _canvas_target(nullptr), _text_format(nullptr), _background_color(D2D1::ColorF(background_color))
{
	_create_device_independent_resources();
	_create_window(title);
}

window_engine::~window_engine()
{
	if (_handle) DestroyWindow(_handle);
}

void window_engine::_create_window(const wchar_t* title)
{
	WNDCLASSEXW wcex = { 0 };
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.hInstance = GetModuleHandleW(nullptr);
	wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW);
	wcex.lpszClassName = L"junior_window";

	wcex.lpfnWndProc = [](HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
		auto target = (window_engine*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
		return target ? target->_window_proc(msg, wp, lp) : DefWindowProcW(hwnd, msg, wp, lp);
	};

	RegisterClassExW(&wcex);

	_handle = CreateWindowExW(0, wcex.lpszClassName, title, WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, GetModuleHandleW(nullptr), nullptr);

	if (_handle)
	{
		_window_count++;
		SetWindowLongPtrW(_handle, GWLP_USERDATA, (LONG_PTR)this);
		_create_device_resources();
		ShowWindow(_handle, SW_SHOWDEFAULT);
		UpdateWindow(_handle);
	}
}

LRESULT window_engine::_window_proc(const UINT msg, const WPARAM wParam, const WPARAM lParam)
{
	switch (msg)
	{
	case WM_SIZE:
		if (_canvas_target)
		{
			auto buffer_size = _canvas_target->GetSize();
			if (buffer_size.width < LOWORD(lParam) || buffer_size.height < HIWORD(lParam))
				_resize_canvas(D2D1::SizeF(max(buffer_size.width, LOWORD(lParam)), max(buffer_size.height, HIWORD(lParam))));
		}
		if (_screen_target)
		{
			_screen_target->Resize(D2D1::SizeU(LOWORD(lParam), HIWORD(lParam)));
			InvalidateRect(_handle, nullptr, FALSE);
		}
		return 0;

	case WM_DISPLAYCHANGE:
		InvalidateRect(_handle, nullptr, FALSE);
		return 0;

	case WM_PAINT:
		_update_screen();
		return 0;

	case WM_DESTROY:
		PostMessageW(nullptr, WM_USER + 1, 0, (LPARAM)_owner);
		if (!--_window_count) PostQuitMessage(0);
		return 0;
	}
	return DefWindowProcW(_handle, msg, wParam, lParam);
}

std::wstring window_engine::get_title() const
{
	wchar_t buffer[1024];
	GetWindowTextW(_handle, buffer, 1024);
	return std::wstring(buffer);
}

void window_engine::set_owner(window* new_owner)
{
	_owner = new_owner;
}

window* window_engine::get_owner(const HWND hWnd)
{
	auto target = (window_engine*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
	return target ? target->_owner : nullptr;
}

HRESULT window_engine::_create_device_independent_resources()
{
	if (CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED) == S_FALSE)
		CoUninitialize();

	HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &_d2d_factory);

	if (SUCCEEDED(hr)) hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(_dwrite_factory), reinterpret_cast<IUnknown**>(&_dwrite_factory));

	if (SUCCEEDED(hr)) hr = _dwrite_factory->CreateTextFormat(L"Segoe UI", nullptr, DWRITE_FONT_WEIGHT_THIN, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 24.0f, L"", &_text_format);

	return hr;
}

HRESULT window_engine::_create_device_resources()
{
	if (_canvas_target) return S_FALSE;
	if (!_handle || !_d2d_factory) return E_NOT_VALID_STATE;

	RECT rc;
	GetClientRect(_handle, &rc);
	D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);

	HRESULT hr = _d2d_factory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties(_handle, size), &_screen_target);

	if (SUCCEEDED(hr)) hr = _screen_target->CreateCompatibleRenderTarget(&_canvas_target);
	if (SUCCEEDED(hr))
	{
		_canvas_target->BeginDraw();
		_canvas_target->Clear(_background_color);
		hr = _canvas_target->EndDraw();
	}

	return hr;
}

void window_engine::_discard_device_resources()
{
	_screen_target = nullptr;
	_canvas_target = nullptr;
}

HRESULT window_engine::_update_screen()
{
	HRESULT hr = _create_device_resources();
	if (FAILED(hr)) return E_NOT_VALID_STATE;

	RECT rc;
	GetUpdateRect(_handle, &rc, FALSE);

	CComPtr<ID2D1Bitmap> canvas;
	hr = _canvas_target->GetBitmap(&canvas);
	if (SUCCEEDED(hr))
	{
		auto rect = D2D1::RectF((float)rc.left, (float)rc.top, (float)rc.right, (float)rc.bottom);

		_screen_target->BeginDraw();
		_screen_target->DrawBitmap(canvas, rect, 1, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rect);
		hr = _screen_target->EndDraw();
	}

	if (SUCCEEDED(hr))
	{
		ValidateRect(_handle, &rc);
	}

	if (hr == D2DERR_RECREATE_TARGET)
	{
		_discard_device_resources();
		hr = S_OK;
	}

	return hr;
}

HRESULT window_engine::_resize_canvas(D2D1_SIZE_F new_size)
{
	if (!_screen_target || !_canvas_target) return E_NOT_VALID_STATE;

	CComPtr<ID2D1BitmapRenderTarget> new_target;
	HRESULT hr = _screen_target->CreateCompatibleRenderTarget(new_size, &new_target);
	if (SUCCEEDED(hr))
	{
		new_target->BeginDraw();
		new_target->Clear(_background_color);
		hr = new_target->EndDraw();
	}

	CComPtr<ID2D1Bitmap> current_canvas;
	CComPtr<ID2D1Bitmap> new_canvas;
	if (SUCCEEDED(hr)) hr = _canvas_target->GetBitmap(&current_canvas);
	if (SUCCEEDED(hr)) hr = new_target->GetBitmap(&new_canvas);
	if (SUCCEEDED(hr)) hr = new_canvas->CopyFromBitmap(nullptr, current_canvas, nullptr);

	if (SUCCEEDED(hr)) _canvas_target = new_target;

	return hr;
}

bool window_engine::begin_draw()
{
	HRESULT hr = _create_device_resources();
	if (SUCCEEDED(hr)) _canvas_target->BeginDraw();
	return SUCCEEDED(hr);
}

bool window_engine::end_draw()
{
	HRESULT hr = _canvas_target->EndDraw();

	if (hr == D2DERR_RECREATE_TARGET)
	{
		_discard_device_resources();
		hr = S_OK;
	}

	if (SUCCEEDED(hr))
	{
		InvalidateRect(_handle, nullptr, FALSE);
	}

	return SUCCEEDED(hr);
}

void window_engine::clear(const UINT32 rgb)
{
	// TODO: implement clear()
}

void window_engine::draw_line(const float x1, const float y1, const float x2, const float y2, const UINT32 rgb, const float width)
{
	if (_canvas_target)
	{
		CComPtr<ID2D1SolidColorBrush> brush = nullptr;
		_canvas_target->CreateSolidColorBrush(D2D1::ColorF(rgb), &brush);
		_canvas_target->DrawLine(D2D1::Point2F(x1, y1), D2D1::Point2F(x2, y2), brush, width);
	}
}

void window_engine::draw_ellipse(const float x, const float y, const float rx, const float ry, const UINT32 rgb, const float width)
{
	if (_canvas_target)
	{
		CComPtr<ID2D1SolidColorBrush> brush = nullptr;
		_canvas_target->CreateSolidColorBrush(D2D1::ColorF(rgb), &brush);
		_canvas_target->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(x, y), rx, ry), brush, width);
	}
}

void window_engine::fill_ellipse(const float x, const float y, const float rx, const float ry, const UINT32 rgb)
{
	if (_canvas_target)
	{
		CComPtr<ID2D1SolidColorBrush> brush = nullptr;
		_canvas_target->CreateSolidColorBrush(D2D1::ColorF(rgb), &brush);
		_canvas_target->FillEllipse(D2D1::Ellipse(D2D1::Point2F(x, y), rx, ry), brush);
	}
}

void window_engine::write(const wchar_t* text, const float x, const float y, const UINT32 rgb)
{
	if (_canvas_target && _text_format)
	{
		auto target_size = _canvas_target->GetSize();
		auto layout_rect = D2D1::RectF(x, y, target_size.width - 10, target_size.height);

		_text_format->SetReadingDirection(DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);

		CComPtr<ID2D1SolidColorBrush> brush = nullptr;
		_canvas_target->CreateSolidColorBrush(D2D1::ColorF(rgb), &brush);

		_canvas_target->DrawTextW(text, lstrlen(text), _text_format, layout_rect, brush);
	}
}

void window_engine::write(const wchar_t* text, const UINT32 rgb)
{
	static float margin = 10;

	if (_canvas_target && _text_format)
	{
		auto target_size = _canvas_target->GetSize();

		CComPtr<ID2D1SolidColorBrush> brush = nullptr;
		_canvas_target->CreateSolidColorBrush(D2D1::ColorF(rgb), &brush);

		bool is_arabic = text[0] && ((text[0] >= 0x0600 && text[0] <= 0x06ff) || (text[0] >= 0x08a0 && text[0] <= 0x08ff) || (text[0] >= 0xfb50 && text[0] <= 0xfdff) || (text[0] >= 0xfe70 && text[0] <= 0xfeff));
		_text_format->SetReadingDirection(is_arabic ? DWRITE_READING_DIRECTION_RIGHT_TO_LEFT : DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);

		CComPtr<IDWriteTextLayout> layout;
		HRESULT hr = _dwrite_factory->CreateTextLayout(text, lstrlen(text), _text_format, target_size.width - 2 * margin, target_size.height - _cursor_y - margin, &layout);

		if (SUCCEEDED(hr))
		{
			_canvas_target->DrawTextLayout(D2D1::Point2F(margin, _cursor_y), layout, brush);

			DWRITE_TEXT_METRICS metrics;
			layout->GetMetrics(&metrics);
			_cursor_y += metrics.height;
		}
	}
}
<commit_msg>Do not execute end_draw if render target is invalid<commit_after>
#include "window_engine.h"

using namespace junior;
using namespace junior::_win32;

int window_engine::_window_count = 0;

window_engine::window_engine(window* owner, const wchar_t* title, const UINT32 background_color)
	: _owner(owner), _d2d_factory(nullptr), _dwrite_factory(nullptr), _screen_target(nullptr), _canvas_target(nullptr), _text_format(nullptr), _background_color(D2D1::ColorF(background_color))
{
	_create_device_independent_resources();
	_create_window(title);
}

window_engine::~window_engine()
{
	if (_handle) DestroyWindow(_handle);
}

void window_engine::_create_window(const wchar_t* title)
{
	WNDCLASSEXW wcex = { 0 };
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.hInstance = GetModuleHandleW(nullptr);
	wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW);
	wcex.lpszClassName = L"junior_window";

	wcex.lpfnWndProc = [](HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
		auto target = (window_engine*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
		return target ? target->_window_proc(msg, wp, lp) : DefWindowProcW(hwnd, msg, wp, lp);
	};

	RegisterClassExW(&wcex);

	_handle = CreateWindowExW(0, wcex.lpszClassName, title, WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, GetModuleHandleW(nullptr), nullptr);

	if (_handle)
	{
		_window_count++;
		SetWindowLongPtrW(_handle, GWLP_USERDATA, (LONG_PTR)this);
		_create_device_resources();
		ShowWindow(_handle, SW_SHOWDEFAULT);
		UpdateWindow(_handle);
	}
}

LRESULT window_engine::_window_proc(const UINT msg, const WPARAM wParam, const WPARAM lParam)
{
	switch (msg)
	{
	case WM_SIZE:
		if (_canvas_target)
		{
			auto buffer_size = _canvas_target->GetSize();
			if (buffer_size.width < LOWORD(lParam) || buffer_size.height < HIWORD(lParam))
				_resize_canvas(D2D1::SizeF(max(buffer_size.width, LOWORD(lParam)), max(buffer_size.height, HIWORD(lParam))));
		}
		if (_screen_target)
		{
			_screen_target->Resize(D2D1::SizeU(LOWORD(lParam), HIWORD(lParam)));
			InvalidateRect(_handle, nullptr, FALSE);
		}
		return 0;

	case WM_DISPLAYCHANGE:
		InvalidateRect(_handle, nullptr, FALSE);
		return 0;

	case WM_PAINT:
		_update_screen();
		return 0;

	case WM_DESTROY:
		PostMessageW(nullptr, WM_USER + 1, 0, (LPARAM)_owner);
		if (!--_window_count) PostQuitMessage(0);
		return 0;
	}
	return DefWindowProcW(_handle, msg, wParam, lParam);
}

std::wstring window_engine::get_title() const
{
	wchar_t buffer[1024];
	GetWindowTextW(_handle, buffer, 1024);
	return std::wstring(buffer);
}

void window_engine::set_owner(window* new_owner)
{
	_owner = new_owner;
}

window* window_engine::get_owner(const HWND hWnd)
{
	auto target = (window_engine*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
	return target ? target->_owner : nullptr;
}

HRESULT window_engine::_create_device_independent_resources()
{
	if (CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED) == S_FALSE)
		CoUninitialize();

	HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &_d2d_factory);

	if (SUCCEEDED(hr)) hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(_dwrite_factory), reinterpret_cast<IUnknown**>(&_dwrite_factory));

	if (SUCCEEDED(hr)) hr = _dwrite_factory->CreateTextFormat(L"Segoe UI", nullptr, DWRITE_FONT_WEIGHT_THIN, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 24.0f, L"", &_text_format);

	return hr;
}

HRESULT window_engine::_create_device_resources()
{
	if (_canvas_target) return S_FALSE;
	if (!_handle || !_d2d_factory) return E_NOT_VALID_STATE;

	RECT rc;
	GetClientRect(_handle, &rc);
	D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);

	HRESULT hr = _d2d_factory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties(_handle, size), &_screen_target);

	if (SUCCEEDED(hr)) hr = _screen_target->CreateCompatibleRenderTarget(&_canvas_target);
	if (SUCCEEDED(hr))
	{
		_canvas_target->BeginDraw();
		_canvas_target->Clear(_background_color);
		hr = _canvas_target->EndDraw();
	}

	return hr;
}

void window_engine::_discard_device_resources()
{
	_screen_target = nullptr;
	_canvas_target = nullptr;
}

HRESULT window_engine::_update_screen()
{
	HRESULT hr = _create_device_resources();
	if (FAILED(hr)) return E_NOT_VALID_STATE;

	RECT rc;
	GetUpdateRect(_handle, &rc, FALSE);

	CComPtr<ID2D1Bitmap> canvas;
	hr = _canvas_target->GetBitmap(&canvas);
	if (SUCCEEDED(hr))
	{
		auto rect = D2D1::RectF((float)rc.left, (float)rc.top, (float)rc.right, (float)rc.bottom);

		_screen_target->BeginDraw();
		_screen_target->DrawBitmap(canvas, rect, 1, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rect);
		hr = _screen_target->EndDraw();
	}

	if (SUCCEEDED(hr))
	{
		ValidateRect(_handle, &rc);
	}

	if (hr == D2DERR_RECREATE_TARGET)
	{
		_discard_device_resources();
		hr = S_OK;
	}

	return hr;
}

HRESULT window_engine::_resize_canvas(D2D1_SIZE_F new_size)
{
	if (!_screen_target || !_canvas_target) return E_NOT_VALID_STATE;

	CComPtr<ID2D1BitmapRenderTarget> new_target;
	HRESULT hr = _screen_target->CreateCompatibleRenderTarget(new_size, &new_target);
	if (SUCCEEDED(hr))
	{
		new_target->BeginDraw();
		new_target->Clear(_background_color);
		hr = new_target->EndDraw();
	}

	CComPtr<ID2D1Bitmap> current_canvas;
	CComPtr<ID2D1Bitmap> new_canvas;
	if (SUCCEEDED(hr)) hr = _canvas_target->GetBitmap(&current_canvas);
	if (SUCCEEDED(hr)) hr = new_target->GetBitmap(&new_canvas);
	if (SUCCEEDED(hr)) hr = new_canvas->CopyFromBitmap(nullptr, current_canvas, nullptr);

	if (SUCCEEDED(hr)) _canvas_target = new_target;

	return hr;
}

bool window_engine::begin_draw()
{
	HRESULT hr = _create_device_resources();
	if (SUCCEEDED(hr)) _canvas_target->BeginDraw();
	return SUCCEEDED(hr);
}

bool window_engine::end_draw()
{
	if (!_canvas_target) return E_NOT_VALID_STATE;

	HRESULT hr = _canvas_target->EndDraw();

	if (hr == D2DERR_RECREATE_TARGET)
	{
		_discard_device_resources();
		hr = S_OK;
	}

	if (SUCCEEDED(hr))
	{
		InvalidateRect(_handle, nullptr, FALSE);
	}

	return SUCCEEDED(hr);
}

void window_engine::clear(const UINT32 rgb)
{
	// TODO: implement clear()
}

void window_engine::draw_line(const float x1, const float y1, const float x2, const float y2, const UINT32 rgb, const float width)
{
	if (_canvas_target)
	{
		CComPtr<ID2D1SolidColorBrush> brush = nullptr;
		_canvas_target->CreateSolidColorBrush(D2D1::ColorF(rgb), &brush);
		_canvas_target->DrawLine(D2D1::Point2F(x1, y1), D2D1::Point2F(x2, y2), brush, width);
	}
}

void window_engine::draw_ellipse(const float x, const float y, const float rx, const float ry, const UINT32 rgb, const float width)
{
	if (_canvas_target)
	{
		CComPtr<ID2D1SolidColorBrush> brush = nullptr;
		_canvas_target->CreateSolidColorBrush(D2D1::ColorF(rgb), &brush);
		_canvas_target->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(x, y), rx, ry), brush, width);
	}
}

void window_engine::fill_ellipse(const float x, const float y, const float rx, const float ry, const UINT32 rgb)
{
	if (_canvas_target)
	{
		CComPtr<ID2D1SolidColorBrush> brush = nullptr;
		_canvas_target->CreateSolidColorBrush(D2D1::ColorF(rgb), &brush);
		_canvas_target->FillEllipse(D2D1::Ellipse(D2D1::Point2F(x, y), rx, ry), brush);
	}
}

void window_engine::write(const wchar_t* text, const float x, const float y, const UINT32 rgb)
{
	if (_canvas_target && _text_format)
	{
		auto target_size = _canvas_target->GetSize();
		auto layout_rect = D2D1::RectF(x, y, target_size.width - 10, target_size.height);

		_text_format->SetReadingDirection(DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);

		CComPtr<ID2D1SolidColorBrush> brush = nullptr;
		_canvas_target->CreateSolidColorBrush(D2D1::ColorF(rgb), &brush);

		_canvas_target->DrawTextW(text, lstrlen(text), _text_format, layout_rect, brush);
	}
}

void window_engine::write(const wchar_t* text, const UINT32 rgb)
{
	static float margin = 10;

	if (_canvas_target && _text_format)
	{
		auto target_size = _canvas_target->GetSize();

		CComPtr<ID2D1SolidColorBrush> brush = nullptr;
		_canvas_target->CreateSolidColorBrush(D2D1::ColorF(rgb), &brush);

		bool is_arabic = text[0] && ((text[0] >= 0x0600 && text[0] <= 0x06ff) || (text[0] >= 0x08a0 && text[0] <= 0x08ff) || (text[0] >= 0xfb50 && text[0] <= 0xfdff) || (text[0] >= 0xfe70 && text[0] <= 0xfeff));
		_text_format->SetReadingDirection(is_arabic ? DWRITE_READING_DIRECTION_RIGHT_TO_LEFT : DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);

		CComPtr<IDWriteTextLayout> layout;
		HRESULT hr = _dwrite_factory->CreateTextLayout(text, lstrlen(text), _text_format, target_size.width - 2 * margin, target_size.height - _cursor_y - margin, &layout);

		if (SUCCEEDED(hr))
		{
			_canvas_target->DrawTextLayout(D2D1::Point2F(margin, _cursor_y), layout, brush);

			DWRITE_TEXT_METRICS metrics;
			layout->GetMetrics(&metrics);
			_cursor_y += metrics.height;
		}
	}
}
<|endoftext|>


<commit_before>#include "SkEndian.h"
#include "SkFontHost.h"
#include "SkStream.h"

struct SkSFNTHeader {
    uint32_t    fVersion;
    uint16_t    fNumTables;
    uint16_t    fSearchRange;
    uint16_t    fEntrySelector;
    uint16_t    fRangeShift;
};

struct SkTTCFHeader {
    uint32_t    fTag;
    uint32_t    fVersion;
    uint32_t    fNumOffsets;
    uint32_t    fOffset0;   // the first of N (fNumOffsets)
};

union SkSharedTTHeader {
    SkSFNTHeader    fSingle;
    SkTTCFHeader    fCollection;
};

struct SkSFNTDirEntry {
    uint32_t    fTag;
    uint32_t    fChecksum;
    uint32_t    fOffset;
    uint32_t    fLength;
};

/** Return the number of tables, or if this is a TTC (collection), return the
    number of tables in the first element of the collection. In either case,
    if offsetToDir is not-null, set it to the offset to the beginning of the
    table headers (SkSFNTDirEntry), relative to the start of the stream.

    On an error, return 0 for number of tables, and ignore offsetToDir
 */
static int count_tables(SkStream* stream, size_t* offsetToDir = NULL) {
    SkSharedTTHeader shared;
    if (stream->read(&shared, sizeof(shared)) != sizeof(shared)) {
        return 0;
    }

    // by default, SkSFNTHeader is at the start of the stream
    size_t offset = 0;

    // if we're really a collection, the first 4-bytes will be 'ttcf'
    uint32_t tag = SkEndian_SwapBE32(shared.fCollection.fTag);
    if (SkSetFourByteTag('t', 't', 'c', 'f') == tag) {
        if (shared.fCollection.fNumOffsets == 0) {
            return 0;
        }
        // this is the offset to the first local SkSFNTHeader
        offset = SkEndian_SwapBE32(shared.fCollection.fOffset0);
        stream->rewind();
        if (stream->skip(offset) != offset) {
            return 0;
        }
        if (stream->read(&shared, sizeof(shared)) != sizeof(shared)) {
            return 0;
        }
    }

    if (offsetToDir) {
        // add the size of the header, so we will point to the DirEntries
        *offsetToDir = offset + sizeof(SkSFNTDirEntry);
    }
    return SkEndian_SwapBE16(shared.fSingle.fNumTables);
}

///////////////////////////////////////////////////////////////////////////////

struct SfntHeader {
    SfntHeader() : fCount(0), fDir(NULL) {}
    ~SfntHeader() { sk_free(fDir); }

    /** If it returns true, then fCount and fDir are properly initialized.
        Note: fDir will point to the raw array of SkSFNTDirEntry values,
        meaning they will still be in the file's native endianness (BE).

        fDir will be automatically freed when this object is destroyed
     */
    bool init(SkStream* stream) {
        size_t offsetToDir;
        fCount = count_tables(stream, &offsetToDir);
        if (0 == fCount) {
            return false;
        }

        stream->rewind();
        if (stream->skip(offsetToDir) != offsetToDir) {
            return false;
        }

        size_t size = fCount * sizeof(SkSFNTDirEntry);
        fDir = reinterpret_cast<SkSFNTDirEntry*>(sk_malloc_throw(size));
        return stream->read(fDir, size) == size;
    }

    int             fCount;
    SkSFNTDirEntry* fDir;
};

///////////////////////////////////////////////////////////////////////////////

int SkFontHost::CountTables(SkFontID fontID) {
    SkStream* stream = SkFontHost::OpenStream(fontID);
    if (NULL == stream) {
        return 0;
    }

    SkAutoUnref au(stream);
    return count_tables(stream);
}

int SkFontHost::GetTableTags(SkFontID fontID, SkFontTableTag tags[]) {
    SkStream* stream = SkFontHost::OpenStream(fontID);
    if (NULL == stream) {
        return 0;
    }

    SkAutoUnref au(stream);
    SfntHeader  header;
    if (!header.init(stream)) {
        return 0;
    }

    for (int i = 0; i < header.fCount; i++) {
        tags[i] = SkEndian_SwapBE32(header.fDir[i].fTag);
    }
    return header.fCount;
}

size_t SkFontHost::GetTableSize(SkFontID fontID, SkFontTableTag tag) {
    SkStream* stream = SkFontHost::OpenStream(fontID);
    if (NULL == stream) {
        return 0;
    }

    SkAutoUnref au(stream);
    SfntHeader  header;
    if (!header.init(stream)) {
        return 0;
    }

    for (int i = 0; i < header.fCount; i++) {
        if (SkEndian_SwapBE32(header.fDir[i].fTag) == tag) {
            return SkEndian_SwapBE32(header.fDir[i].fLength);
        }
    }
    return 0;
}

size_t SkFontHost::GetTableData(SkFontID fontID, SkFontTableTag tag,
                                size_t offset, size_t length, void* data) {
    SkStream* stream = SkFontHost::OpenStream(fontID);
    if (NULL == stream) {
        return 0;
    }

    SkAutoUnref au(stream);
    SfntHeader  header;
    if (!header.init(stream)) {
        return 0;
    }

    for (int i = 0; i < header.fCount; i++) {
        if (SkEndian_SwapBE32(header.fDir[i].fTag) == tag) {
            size_t realOffset = SkEndian_SwapBE32(header.fDir[i].fOffset);
            size_t realLength = SkEndian_SwapBE32(header.fDir[i].fLength);
            // now sanity check the caller's offset/length
            if (offset >= realLength) {
                return 0;
            }
            // if the caller is trusting the length from the file, then a
            // hostile file might choose a value which would overflow offset +
            // length.
            if (offset + length < offset) {
                return 0;
            }
            if (offset + length > realLength) {
                length = realLength - offset;
            }
            // skip the stream to the part of the table we want to copy from
            stream->rewind();
            size_t bytesToSkip = realOffset + offset;
            if (stream->skip(bytesToSkip) != bytesToSkip) {
                return 0;
            }
            if (stream->read(data, length) != length) {
                return 0;
            }
            return length;
        }
    }
    return 0;
}

<commit_msg>trivial: fix ws<commit_after>#include "SkEndian.h"
#include "SkFontHost.h"
#include "SkStream.h"

struct SkSFNTHeader {
    uint32_t    fVersion;
    uint16_t    fNumTables;
    uint16_t    fSearchRange;
    uint16_t    fEntrySelector;
    uint16_t    fRangeShift;
};

struct SkTTCFHeader {
    uint32_t    fTag;
    uint32_t    fVersion;
    uint32_t    fNumOffsets;
    uint32_t    fOffset0;   // the first of N (fNumOffsets)
};

union SkSharedTTHeader {
    SkSFNTHeader    fSingle;
    SkTTCFHeader    fCollection;
};

struct SkSFNTDirEntry {
    uint32_t    fTag;
    uint32_t    fChecksum;
    uint32_t    fOffset;
    uint32_t    fLength;
};

/** Return the number of tables, or if this is a TTC (collection), return the
    number of tables in the first element of the collection. In either case,
    if offsetToDir is not-null, set it to the offset to the beginning of the
    table headers (SkSFNTDirEntry), relative to the start of the stream.

    On an error, return 0 for number of tables, and ignore offsetToDir
 */
static int count_tables(SkStream* stream, size_t* offsetToDir = NULL) {
    SkSharedTTHeader shared;
    if (stream->read(&shared, sizeof(shared)) != sizeof(shared)) {
        return 0;
    }

    // by default, SkSFNTHeader is at the start of the stream
    size_t offset = 0;

    // if we're really a collection, the first 4-bytes will be 'ttcf'
    uint32_t tag = SkEndian_SwapBE32(shared.fCollection.fTag);
    if (SkSetFourByteTag('t', 't', 'c', 'f') == tag) {
        if (shared.fCollection.fNumOffsets == 0) {
            return 0;
        }
        // this is the offset to the first local SkSFNTHeader
        offset = SkEndian_SwapBE32(shared.fCollection.fOffset0);
        stream->rewind();
        if (stream->skip(offset) != offset) {
            return 0;
        }
        if (stream->read(&shared, sizeof(shared)) != sizeof(shared)) {
            return 0;
        }
    }

    if (offsetToDir) {
        // add the size of the header, so we will point to the DirEntries
        *offsetToDir = offset + sizeof(SkSFNTDirEntry);
    }
    return SkEndian_SwapBE16(shared.fSingle.fNumTables);
}

///////////////////////////////////////////////////////////////////////////////

struct SfntHeader {
    SfntHeader() : fCount(0), fDir(NULL) {}
    ~SfntHeader() { sk_free(fDir); }

    /** If it returns true, then fCount and fDir are properly initialized.
        Note: fDir will point to the raw array of SkSFNTDirEntry values,
        meaning they will still be in the file's native endianness (BE).

        fDir will be automatically freed when this object is destroyed
     */
    bool init(SkStream* stream) {
        size_t offsetToDir;
        fCount = count_tables(stream, &offsetToDir);
        if (0 == fCount) {
            return false;
        }

        stream->rewind();
        if (stream->skip(offsetToDir) != offsetToDir) {
            return false;
        }

        size_t size = fCount * sizeof(SkSFNTDirEntry);
        fDir = reinterpret_cast<SkSFNTDirEntry*>(sk_malloc_throw(size));
        return stream->read(fDir, size) == size;
    }

    int             fCount;
    SkSFNTDirEntry* fDir;
};

///////////////////////////////////////////////////////////////////////////////

int SkFontHost::CountTables(SkFontID fontID) {
    SkStream* stream = SkFontHost::OpenStream(fontID);
    if (NULL == stream) {
        return 0;
    }

    SkAutoUnref au(stream);
    return count_tables(stream);
}

int SkFontHost::GetTableTags(SkFontID fontID, SkFontTableTag tags[]) {
    SkStream* stream = SkFontHost::OpenStream(fontID);
    if (NULL == stream) {
        return 0;
    }

    SkAutoUnref au(stream);
    SfntHeader  header;
    if (!header.init(stream)) {
        return 0;
    }

    for (int i = 0; i < header.fCount; i++) {
        tags[i] = SkEndian_SwapBE32(header.fDir[i].fTag);
    }
    return header.fCount;
}

size_t SkFontHost::GetTableSize(SkFontID fontID, SkFontTableTag tag) {
    SkStream* stream = SkFontHost::OpenStream(fontID);
    if (NULL == stream) {
        return 0;
    }

    SkAutoUnref au(stream);
    SfntHeader  header;
    if (!header.init(stream)) {
        return 0;
    }

    for (int i = 0; i < header.fCount; i++) {
        if (SkEndian_SwapBE32(header.fDir[i].fTag) == tag) {
            return SkEndian_SwapBE32(header.fDir[i].fLength);
        }
    }
    return 0;
}

size_t SkFontHost::GetTableData(SkFontID fontID, SkFontTableTag tag,
                                size_t offset, size_t length, void* data) {
    SkStream* stream = SkFontHost::OpenStream(fontID);
    if (NULL == stream) {
        return 0;
    }

    SkAutoUnref au(stream);
    SfntHeader  header;
    if (!header.init(stream)) {
        return 0;
    }

    for (int i = 0; i < header.fCount; i++) {
        if (SkEndian_SwapBE32(header.fDir[i].fTag) == tag) {
            size_t realOffset = SkEndian_SwapBE32(header.fDir[i].fOffset);
            size_t realLength = SkEndian_SwapBE32(header.fDir[i].fLength);
            // now sanity check the caller's offset/length
            if (offset >= realLength) {
                return 0;
            }
            // if the caller is trusting the length from the file, then a
            // hostile file might choose a value which would overflow offset +
            // length.
            if (offset + length < offset) {
                return 0;
            }
            if (offset + length > realLength) {
                length = realLength - offset;
            }
            // skip the stream to the part of the table we want to copy from
            stream->rewind();
            size_t bytesToSkip = realOffset + offset;
            if (stream->skip(bytesToSkip) != bytesToSkip) {
                return 0;
            }
            if (stream->read(data, length) != length) {
                return 0;
            }
            return length;
        }
    }
    return 0;
}

<|endoftext|>


<commit_before>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! @file

#ifndef DO_CORE_IMAGE_IMAGE_HPP
#define DO_CORE_IMAGE_IMAGE_HPP

#include <DO/Core/Image/ElementTraits.hpp>
#include <DO/Core/MultiArray.hpp>

namespace DO {

  // ======================================================================== //
  /*!
    \ingroup Core
    \defgroup Image Image
    @{
   */

  //! \brief Forward declaration of the image class.
  template <typename Color, int N = 2> class Image;

  //! \brief Forward declaration of the generic image converter class.
  template <typename T, typename U, int N>
  void convert_channel(const Image<T, N>& src, Image<U, N>& dst);

  //! \brief Convert color of image.
  template <typename T, typename U, int N>
  void convert_color(const Image<T, N>& src, Image<U, N>& dst);

  //! \brief The image class.
  template <typename Color, int N>
  class Image : public MultiArray<Color, N, ColMajor>
  {
    typedef MultiArray<Color, N, ColMajor> base_type;

  public: /* interface */
    //! N-dimensional integral vector type.
    typedef typename base_type::vector_type vector_type;

    //! Immutable matrix view for linear algebra.
    typedef Map<const Matrix<typename ElementTraits<Color>::value_type,
      Dynamic, Dynamic, RowMajor> > const_matrix_view_type;

    //! Mutable matrix view for linear algebra.
    typedef Map<Matrix<typename ElementTraits<Color>::value_type,
      Dynamic, Dynamic, RowMajor> > matrix_view_type;

    //! Default constructor.
    inline Image()
      : base_type()
    {
    }

    //! Constructor with specified sizes.
    inline explicit Image(const vector_type& sizes)
      : base_type(sizes)
    {
    }

    //! Constructor which wraps raw data.
    inline Image(Color *data, const vector_type& sizes,
                 bool acquire_ownership = false)
      : base_type(data, sizes, acquire_ownership)
    {
    }

    //! Constructor with specified sizes.
    inline Image(int width, int height)
      : base_type(width, height)
    {
    }

    //! Constructor with specified sizes.
    inline Image(int width, int height, int depth)
      : base_type(width, height, depth)
    {
    }

    //! Copy constructor.
    inline Image(const base_type& other)
      : base_type(other)
    {
    }

    //! Constant width getter.
    inline int width() const
    {
      return this->base_type::rows();
    }

    //! Constant height getter.
    inline int height() const
    {
      return this->base_type::cols();
    }

    //! Constant depth getter, which is only valid for 3D images.
    inline int depth() const
    {
      return this->base_type::depth();
    }

    //! Non-mutable matrix view for linear algebra with Eigen 3.
    inline const_matrix_view_type matrix() const
    {
      DO_STATIC_ASSERT(N == 2, MULTIARRAY_MUST_HAVE_TWO_DIMENSIONS);
      return const_matrix_view_type( reinterpret_cast<
        typename ElementTraits<T>::const_pointer>(data()),
        base_type::cols(), base_type::rows() );
    }

    //! Mutable matrix view for linear algebra with Eigen 3.
    inline matrix_view_type matrix()
    {
      DO_STATIC_ASSERT(N == 2, MULTIARRAY_MUST_HAVE_TWO_DIMENSIONS);
      return matrix_view_type( reinterpret_cast<
        typename ElementTraits<Color>::pointer>(data()),
        base_type::cols(), base_type::rows() );
    }

    //! Color conversion method.
    template <typename Color2>
    Image<Color2, N> convert_color() const
    {
      Image<Color2, N> dst(base_type::sizes());
      DO::convert_color(*this, dst);
      return dst;
    }

    //! Color conversion method.
    template <typename Color2>
    Image<Color2, N> convert_channel() const
    {
      Image<Color2, N> dst(base_type::sizes());
      DO::convert_channel(*this, dst);
      return dst;
    }

    //! Convenient helper for chaining filters.
    template <template<typename, int> class Filter>
    inline typename Filter<Color, N>::return_type compute() const
    {
      return Filter<Color, N>(*this)();
    }

    template <template<typename, int> class Filter>
    inline typename Filter<Color, N>::ReturnType
    compute(const typename Filter<Color, N>::ParamType& param) const
    {
      return Filter<Color, N>(*this)(param);
    }
  };

  //! @}

} /* namespace DO */

#endif /* DO_CORE_IMAGE_IMAGE_HPP */<commit_msg>Fix compilation errors.<commit_after>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! @file

#ifndef DO_CORE_IMAGE_IMAGE_HPP
#define DO_CORE_IMAGE_IMAGE_HPP

#include <DO/Core/Image/ElementTraits.hpp>
#include <DO/Core/MultiArray.hpp>

namespace DO {

  // ======================================================================== //
  /*!
    \ingroup Core
    \defgroup Image Image
    @{
   */

  //! \brief Forward declaration of the image class.
  template <typename Color, int N = 2> class Image;

  //! \brief Forward declaration of the generic image converter class.
  template <typename T, typename U, int N>
  void convert_channel(const Image<T, N>& src, Image<U, N>& dst);

  //! \brief Convert color of image.
  template <typename T, typename U, int N>
  void convert_color(const Image<T, N>& src, Image<U, N>& dst);

  //! \brief The image class.
  template <typename Color, int N>
  class Image : public MultiArray<Color, N, ColMajor>
  {
    typedef MultiArray<Color, N, ColMajor> base_type;

  public: /* interface */
    //! N-dimensional integral vector type.
    typedef typename base_type::vector_type vector_type;

    //! Immutable matrix view for linear algebra.
    typedef Map<const Matrix<typename ElementTraits<Color>::value_type,
      Dynamic, Dynamic, RowMajor> > const_matrix_view_type;

    //! Mutable matrix view for linear algebra.
    typedef Map<Matrix<typename ElementTraits<Color>::value_type,
      Dynamic, Dynamic, RowMajor> > matrix_view_type;

    //! Default constructor.
    inline Image()
      : base_type()
    {
    }

    //! Constructor with specified sizes.
    inline explicit Image(const vector_type& sizes)
      : base_type(sizes)
    {
    }

    //! Constructor which wraps raw data.
    inline Image(Color *data, const vector_type& sizes,
                 bool acquire_ownership = false)
      : base_type(data, sizes, acquire_ownership)
    {
    }

    //! Constructor with specified sizes.
    inline Image(int width, int height)
      : base_type(width, height)
    {
    }

    //! Constructor with specified sizes.
    inline Image(int width, int height, int depth)
      : base_type(width, height, depth)
    {
    }

    //! Copy constructor.
    inline Image(const base_type& other)
      : base_type(other)
    {
    }

    //! Constant width getter.
    inline int width() const
    {
      return this->base_type::rows();
    }

    //! Constant height getter.
    inline int height() const
    {
      return this->base_type::cols();
    }

    //! Constant depth getter, which is only valid for 3D images.
    inline int depth() const
    {
      return this->base_type::depth();
    }

    //! Non-mutable matrix view for linear algebra with Eigen 3.
    inline const_matrix_view_type matrix() const
    {
      DO_STATIC_ASSERT(N == 2, MULTIARRAY_MUST_HAVE_TWO_DIMENSIONS);
      return const_matrix_view_type( reinterpret_cast<
        typename ElementTraits<Color>::const_pointer>(base_type::data()),
        base_type::cols(), base_type::rows() );
    }

    //! Mutable matrix view for linear algebra with Eigen 3.
    inline matrix_view_type matrix()
    {
      DO_STATIC_ASSERT(N == 2, MULTIARRAY_MUST_HAVE_TWO_DIMENSIONS);
      return matrix_view_type( reinterpret_cast<
        typename ElementTraits<Color>::pointer>(base_type::data()),
        base_type::cols(), base_type::rows() );
    }

    //! Color conversion method.
    template <typename Color2>
    Image<Color2, N> convert_color() const
    {
      Image<Color2, N> dst(base_type::sizes());
      DO::convert_color(*this, dst);
      return dst;
    }

    //! Color conversion method.
    template <typename Color2>
    Image<Color2, N> convert_channel() const
    {
      Image<Color2, N> dst(base_type::sizes());
      DO::convert_channel(*this, dst);
      return dst;
    }

    //! Convenient helper for chaining filters.
    template <template<typename, int> class Filter>
    inline typename Filter<Color, N>::return_type compute() const
    {
      return Filter<Color, N>(*this)();
    }

    template <template<typename, int> class Filter>
    inline typename Filter<Color, N>::ReturnType
    compute(const typename Filter<Color, N>::ParamType& param) const
    {
      return Filter<Color, N>(*this)(param);
    }
  };

  //! @}

} /* namespace DO */

#endif /* DO_CORE_IMAGE_IMAGE_HPP */<|endoftext|>