<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------

#define INCL_DOSSEMAPHORES
#define INCL_DOSERRORS
#define INCL_DOSMISC
#define INCL_DOSFILEMGR

#include    <xercesc/util/XercesDefs.hpp>
#include    <xercesc/util/PlatformUtils.hpp>
#include    <xercesc/util/RuntimeException.hpp>
#include    <xercesc/util/Janitor.hpp>
#include    <xercesc/util/XMLString.hpp>
#include    <xercesc/util/XMLUniDefs.hpp>
#include    <xercesc/util/PanicHandler.hpp>

#include    <stdio.h>
#include    <stdlib.h>
#include    <io.h>
#if defined(XML_USE_ICU_TRANSCODER)
  #include  <xercesc/util/Transcoders/ICU/ICUTransService.hpp>
#elif defined(XML_USE_ICONV_TRANSCODER)
  #include  <xercesc/util/Transcoders/Iconv/IconvTransService.hpp>
#else
  #error A transcoding service must be chosen
#endif

#if defined(XML_USE_INMEMORY_MSGLOADER)
  #include  <xercesc/util/MsgLoaders/InMemory/InMemMsgLoader.hpp>
#else
  #error A message loading service must be chosen
#endif

#if defined(XML_IBMVAOS2)
#include    <builtin.h>
#endif
#include    <OS2.h>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  XMLPlatformUtils: Platform init and term methods
// ---------------------------------------------------------------------------
void XMLPlatformUtils::platformInit()
{
}

void XMLPlatformUtils::platformTerm()
{
    // We don't have any termination requirements at this time
}

// ---------------------------------------------------------------------------
//  XMLPlatformUtils: File Methods
// ---------------------------------------------------------------------------
unsigned int XMLPlatformUtils::curFilePos(FileHandle theFile)
{
    // Get the current position
    int curPos = ftell( (FILE*)theFile);
    if (curPos == -1)
        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos);

    return (unsigned int)curPos;
}

void XMLPlatformUtils::closeFile(FileHandle theFile)
{
    if (fclose((FILE*)theFile))
        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile);
}

unsigned int XMLPlatformUtils::fileSize(FileHandle theFile)
{
    return (unsigned int)filelength(fileno((FILE *)theFile));
}

FileHandle XMLPlatformUtils::openFile(const char* const fileName)
{
    FileHandle retVal = (FILE*)fopen( fileName , "rb" );

    if (retVal == NULL)
        return 0;
    return retVal;
}

FileHandle XMLPlatformUtils::openFile(const XMLCh* const fileName)
{
    const char* tmpFileName = XMLString::transcode(fileName);
    ArrayJanitor<char> janText((char*)tmpFileName);
    FileHandle retVal = (FILE*)fopen( tmpFileName , "rb" );

    if (retVal == NULL)
        return 0;
    return retVal;
}

FileHandle XMLPlatformUtils::openStdInHandle()
{
    return (FileHandle)fdopen(dup(0), "rb");
}

unsigned int XMLPlatformUtils::readFileBuffer ( FileHandle      theFile
                            , const unsigned int    toRead
                            ,       XMLByte* const  toFill )
{
    size_t noOfItemsRead = fread( (void*) toFill, 1, toRead, (FILE*)theFile);

    if(ferror((FILE*)theFile))
    {
        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile);
    }

    return (unsigned int)noOfItemsRead;
}

void XMLPlatformUtils::resetFile(FileHandle theFile)
{
    // Seek to the start of the file
    if (fseek((FILE*)theFile, 0, SEEK_SET) )
        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotResetFile);
}

// -----------------------------------------------------------------------
//  File system methods
// -----------------------------------------------------------------------
XMLCh* XMLPlatformUtils::getFullPath(const XMLCh* const srcPath)
{
    // Transcode the incoming string
    char* tmpSrcPath = XMLString::transcode(srcPath);
    ArrayJanitor<char> janSrcPath(tmpSrcPath);

    char tmpPath[CCHMAXPATH];
    _fullpath(tmpPath, tmpSrcPath, CCHMAXPATH);

    return XMLString::transcode(tmpPath);
}

bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck)
{
    // Check for pathological case of an empty path
    if (!toCheck[0])
        return false;

    //
    //  If it starts with a drive, then it cannot be relative. Note that
    //  we checked the drive not being empty above, so worst case it's one
    //  char long and the check of the 1st char will fail because it's really
    //  a null character.
    //
    if (toCheck[1] == chColon)
    {
        if (((toCheck[0] >= chLatin_A) && (toCheck[0] <= chLatin_Z))
        ||  ((toCheck[0] >= chLatin_a) && (toCheck[0] <= chLatin_z)))
        {
            return false;
        }
    }

    //
    //  If it starts with a double slash, then it cannot be relative since
    //  its a remote file.
    //
    if ((toCheck[0] == chBackSlash) && (toCheck[1] == chBackSlash))
        return false;

    // Else assume its a relative path
    return true;
}

XMLCh* XMLPlatformUtils::getCurrentDirectory()
{

    /***
     *  REVISIT:
     *
     *   To be implemented later
    ***/

    XMLCh curDir[]={ chPeriod, chForwardSlash, chNull};
    return getFullPath(curDir);
}

inline bool XMLPlatformUtils::isAnySlash(XMLCh c)
{
    return ( chBackSlash == c || chForwardSlash == c);
}

// -----------------------------------------------------------------------
//  Timing methods
// -----------------------------------------------------------------------
unsigned long XMLPlatformUtils::getCurrentMillis()
{
    APIRET  retr;
    ULONG   timerBuf = 0;

    retr =  DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, (PVOID) &timerBuf,
                             sizeof( ULONG ) );
//  if ( retr != NO_ERROR )
//     return (timerBuf);

    return (timerBuf);
}

// -----------------------------------------------------------------------
//  Mutex methods
// -----------------------------------------------------------------------
void XMLPlatformUtils::closeMutex(void* const mtxHandle)
{
#if ! defined(APP_NO_THREADS)
    if (mtxHandle == NULL)
      return;

    if (DosCloseMutexSem( (HMTX)mtxHandle))
    {
      ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotDestroy);
    }
#endif
}

void XMLPlatformUtils::lockMutex(void* const mtxHandle)
{
#if ! defined(APP_NO_THREADS)
    if (mtxHandle == NULL)
      return;

    if (DosRequestMutexSem( (HMTX)mtxHandle,(ULONG) SEM_INDEFINITE_WAIT) )
    {
      ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotLock);
    }
#endif
}

void* XMLPlatformUtils::makeMutex()
{
#if ! defined(APP_NO_THREADS)
    HMTX hRet; // Mutex Handle

    if (DosCreateMutexSem(NULL, &hRet, 0, FALSE))
        ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotCreate);
    return (void*)hRet;
#else
    return 0;
#endif
}

void XMLPlatformUtils::unlockMutex(void* const mtxHandle)
{
#if ! defined(APP_NO_THREADS)
    if (mtxHandle == NULL)
       return;

    if (DosReleaseMutexSem( (HMTX)mtxHandle))
    {
      ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotUnlock);
    }
#endif
}

// -----------------------------------------------------------------------
//  Miscellaneous synchronization methods
// -----------------------------------------------------------------------
void* XMLPlatformUtils::compareAndSwap ( void**      toFill
                                       , const void* const newValue
                                       , const void* const toCompare )
{
#if defined(XML_IBMVA4_OS2)
    return (void *)__smp_cmpxchg4((unsigned int *)toFill,
                                  (unsigned int)newValue,
                                  (unsigned int)toCompare);
#elif defined(__GNUG__)
    char ret;
    long int readval;
    long int * p    = (long **)toFill;

    __asm__ __volatile__ ("lock; cmpxchgl %3, %1\n\tsete %0"
                          : "=q" (ret), "=m" (*p), "=a" (readval)
                          : "r" (newValue), "m" (*p), "a" (toCompare)
                          : "memory");
    return (void *)(long)ret;
#else
    void * retVal = *toFill;
    if (*toFill == toCompare)
      *toFill = (void *)newValue;
    return
#endif
}

// -----------------------------------------------------------------------
//  Atomic Increment and Decrement
//
//  The function return value is positive if the result of the operation
//  was positive. Zero if the result of the operation was zero. Negative
//  if the result of the operation was negative. Except for the zero
//  case, the value returned may differ from the actual result of the
//  operation - only the sign and zero/nonzero state is guaranteed to be
//  correct.
// -----------------------------------------------------------------------
int XMLPlatformUtils::atomicIncrement(int& location)
{
#if defined(XML_IBMVA4_OS2)
    return __smp_inc4(&location);
#elif defined(__GNUG__)
    __asm__ __volatile__ ("lock; incl %0" : "=m" (location) : );
    return location;
#else
    return ++location;
#endif
}

int XMLPlatformUtils::atomicDecrement(int& location)
{
#if defined(XML_IBMVA4_OS2)
    return __smp_dec4(&location);
#elif defined(__GNUG__)
    __asm__ __volatile__ ("lock; decl %0" : "=m" (location) : );
    return location;
#else
    return --location;
#endif
}

// ---------------------------------------------------------------------------
//  XMLPlatformUtils: The panic method
// ---------------------------------------------------------------------------
void XMLPlatformUtils::panic(const PanicHandler::PanicReasons reason)
{
    fgUserPanicHandler? fgUserPanicHandler->panic(reason) : fgDefaultPanicHandler->panic(reason);
}

// -----------------------------------------------------------------------
//  Private static methods. These are provided by the per-platform
//  implementation files.
// -----------------------------------------------------------------------
XMLMsgLoader* XMLPlatformUtils::loadAMsgSet(const XMLCh* const msgDomain)
{
#if defined(XML_USE_INMEMORY_MSGLOADER)
    return new InMemMsgLoader(msgDomain);
#else
    return 0;
#endif
}

XMLNetAccessor* XMLPlatformUtils::makeNetAccessor()
{
  return 0;
}

XMLTransService* XMLPlatformUtils::makeTransService()
{
#if defined(XML_USE_ICU_TRANSCODER)
    return new ICUTransService;
#elif defined(XML_USE_ICONV_TRANSCODER)
    return new IconvTransService;
#else
    return 0;
#endif
}

#include <xercesc/util/LogicalPath.c>

XERCES_CPP_NAMESPACE_END

<commit_msg>Bug#19402: OS2PlatformUtils.cpp compareAndSwap() need to return retVal. Patch from ailian.ding@medtronic.com (Ailian Ding)<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------

#define INCL_DOSSEMAPHORES
#define INCL_DOSERRORS
#define INCL_DOSMISC
#define INCL_DOSFILEMGR

#include    <xercesc/util/XercesDefs.hpp>
#include    <xercesc/util/PlatformUtils.hpp>
#include    <xercesc/util/RuntimeException.hpp>
#include    <xercesc/util/Janitor.hpp>
#include    <xercesc/util/XMLString.hpp>
#include    <xercesc/util/XMLUniDefs.hpp>
#include    <xercesc/util/PanicHandler.hpp>

#include    <stdio.h>
#include    <stdlib.h>
#include    <io.h>
#if defined(XML_USE_ICU_TRANSCODER)
  #include  <xercesc/util/Transcoders/ICU/ICUTransService.hpp>
#elif defined(XML_USE_ICONV_TRANSCODER)
  #include  <xercesc/util/Transcoders/Iconv/IconvTransService.hpp>
#else
  #error A transcoding service must be chosen
#endif

#if defined(XML_USE_INMEMORY_MSGLOADER)
  #include  <xercesc/util/MsgLoaders/InMemory/InMemMsgLoader.hpp>
#else
  #error A message loading service must be chosen
#endif

#if defined(XML_IBMVAOS2)
#include    <builtin.h>
#endif
#include    <OS2.h>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  XMLPlatformUtils: Platform init and term methods
// ---------------------------------------------------------------------------
void XMLPlatformUtils::platformInit()
{
}

void XMLPlatformUtils::platformTerm()
{
    // We don't have any termination requirements at this time
}

// ---------------------------------------------------------------------------
//  XMLPlatformUtils: File Methods
// ---------------------------------------------------------------------------
unsigned int XMLPlatformUtils::curFilePos(FileHandle theFile)
{
    // Get the current position
    int curPos = ftell( (FILE*)theFile);
    if (curPos == -1)
        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos);

    return (unsigned int)curPos;
}

void XMLPlatformUtils::closeFile(FileHandle theFile)
{
    if (fclose((FILE*)theFile))
        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile);
}

unsigned int XMLPlatformUtils::fileSize(FileHandle theFile)
{
    return (unsigned int)filelength(fileno((FILE *)theFile));
}

FileHandle XMLPlatformUtils::openFile(const char* const fileName)
{
    FileHandle retVal = (FILE*)fopen( fileName , "rb" );

    if (retVal == NULL)
        return 0;
    return retVal;
}

FileHandle XMLPlatformUtils::openFile(const XMLCh* const fileName)
{
    const char* tmpFileName = XMLString::transcode(fileName);
    ArrayJanitor<char> janText((char*)tmpFileName);
    FileHandle retVal = (FILE*)fopen( tmpFileName , "rb" );

    if (retVal == NULL)
        return 0;
    return retVal;
}

FileHandle XMLPlatformUtils::openStdInHandle()
{
    return (FileHandle)fdopen(dup(0), "rb");
}

unsigned int XMLPlatformUtils::readFileBuffer ( FileHandle      theFile
                            , const unsigned int    toRead
                            ,       XMLByte* const  toFill )
{
    size_t noOfItemsRead = fread( (void*) toFill, 1, toRead, (FILE*)theFile);

    if(ferror((FILE*)theFile))
    {
        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile);
    }

    return (unsigned int)noOfItemsRead;
}

void XMLPlatformUtils::resetFile(FileHandle theFile)
{
    // Seek to the start of the file
    if (fseek((FILE*)theFile, 0, SEEK_SET) )
        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotResetFile);
}

// -----------------------------------------------------------------------
//  File system methods
// -----------------------------------------------------------------------
XMLCh* XMLPlatformUtils::getFullPath(const XMLCh* const srcPath)
{
    // Transcode the incoming string
    char* tmpSrcPath = XMLString::transcode(srcPath);
    ArrayJanitor<char> janSrcPath(tmpSrcPath);

    char tmpPath[CCHMAXPATH];
    _fullpath(tmpPath, tmpSrcPath, CCHMAXPATH);

    return XMLString::transcode(tmpPath);
}

bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck)
{
    // Check for pathological case of an empty path
    if (!toCheck[0])
        return false;

    //
    //  If it starts with a drive, then it cannot be relative. Note that
    //  we checked the drive not being empty above, so worst case it's one
    //  char long and the check of the 1st char will fail because it's really
    //  a null character.
    //
    if (toCheck[1] == chColon)
    {
        if (((toCheck[0] >= chLatin_A) && (toCheck[0] <= chLatin_Z))
        ||  ((toCheck[0] >= chLatin_a) && (toCheck[0] <= chLatin_z)))
        {
            return false;
        }
    }

    //
    //  If it starts with a double slash, then it cannot be relative since
    //  its a remote file.
    //
    if ((toCheck[0] == chBackSlash) && (toCheck[1] == chBackSlash))
        return false;

    // Else assume its a relative path
    return true;
}

XMLCh* XMLPlatformUtils::getCurrentDirectory()
{

    /***
     *  REVISIT:
     *
     *   To be implemented later
    ***/

    XMLCh curDir[]={ chPeriod, chForwardSlash, chNull};
    return getFullPath(curDir);
}

inline bool XMLPlatformUtils::isAnySlash(XMLCh c)
{
    return ( chBackSlash == c || chForwardSlash == c);
}

// -----------------------------------------------------------------------
//  Timing methods
// -----------------------------------------------------------------------
unsigned long XMLPlatformUtils::getCurrentMillis()
{
    APIRET  retr;
    ULONG   timerBuf = 0;

    retr =  DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, (PVOID) &timerBuf,
                             sizeof( ULONG ) );
//  if ( retr != NO_ERROR )
//     return (timerBuf);

    return (timerBuf);
}

// -----------------------------------------------------------------------
//  Mutex methods
// -----------------------------------------------------------------------
void XMLPlatformUtils::closeMutex(void* const mtxHandle)
{
#if ! defined(APP_NO_THREADS)
    if (mtxHandle == NULL)
      return;

    if (DosCloseMutexSem( (HMTX)mtxHandle))
    {
      ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotDestroy);
    }
#endif
}

void XMLPlatformUtils::lockMutex(void* const mtxHandle)
{
#if ! defined(APP_NO_THREADS)
    if (mtxHandle == NULL)
      return;

    if (DosRequestMutexSem( (HMTX)mtxHandle,(ULONG) SEM_INDEFINITE_WAIT) )
    {
      ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotLock);
    }
#endif
}

void* XMLPlatformUtils::makeMutex()
{
#if ! defined(APP_NO_THREADS)
    HMTX hRet; // Mutex Handle

    if (DosCreateMutexSem(NULL, &hRet, 0, FALSE))
        ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotCreate);
    return (void*)hRet;
#else
    return 0;
#endif
}

void XMLPlatformUtils::unlockMutex(void* const mtxHandle)
{
#if ! defined(APP_NO_THREADS)
    if (mtxHandle == NULL)
       return;

    if (DosReleaseMutexSem( (HMTX)mtxHandle))
    {
      ThrowXML(XMLPlatformUtilsException, XMLExcepts::Mutex_CouldNotUnlock);
    }
#endif
}

// -----------------------------------------------------------------------
//  Miscellaneous synchronization methods
// -----------------------------------------------------------------------
void* XMLPlatformUtils::compareAndSwap ( void**      toFill
                                       , const void* const newValue
                                       , const void* const toCompare )
{
#if defined(XML_IBMVA4_OS2)
    return (void *)__smp_cmpxchg4((unsigned int *)toFill,
                                  (unsigned int)newValue,
                                  (unsigned int)toCompare);
#elif defined(__GNUG__)
    char ret;
    long int readval;
    long int * p    = (long **)toFill;

    __asm__ __volatile__ ("lock; cmpxchgl %3, %1\n\tsete %0"
                          : "=q" (ret), "=m" (*p), "=a" (readval)
                          : "r" (newValue), "m" (*p), "a" (toCompare)
                          : "memory");
    return (void *)(long)ret;
#else
    void * retVal = *toFill;
    if (*toFill == toCompare)
      *toFill = (void *)newValue;

    return retVal;
#endif
}

// -----------------------------------------------------------------------
//  Atomic Increment and Decrement
//
//  The function return value is positive if the result of the operation
//  was positive. Zero if the result of the operation was zero. Negative
//  if the result of the operation was negative. Except for the zero
//  case, the value returned may differ from the actual result of the
//  operation - only the sign and zero/nonzero state is guaranteed to be
//  correct.
// -----------------------------------------------------------------------
int XMLPlatformUtils::atomicIncrement(int& location)
{
#if defined(XML_IBMVA4_OS2)
    return __smp_inc4(&location);
#elif defined(__GNUG__)
    __asm__ __volatile__ ("lock; incl %0" : "=m" (location) : );
    return location;
#else
    return ++location;
#endif
}

int XMLPlatformUtils::atomicDecrement(int& location)
{
#if defined(XML_IBMVA4_OS2)
    return __smp_dec4(&location);
#elif defined(__GNUG__)
    __asm__ __volatile__ ("lock; decl %0" : "=m" (location) : );
    return location;
#else
    return --location;
#endif
}

// ---------------------------------------------------------------------------
//  XMLPlatformUtils: The panic method
// ---------------------------------------------------------------------------
void XMLPlatformUtils::panic(const PanicHandler::PanicReasons reason)
{
    fgUserPanicHandler? fgUserPanicHandler->panic(reason) : fgDefaultPanicHandler->panic(reason);
}

// -----------------------------------------------------------------------
//  Private static methods. These are provided by the per-platform
//  implementation files.
// -----------------------------------------------------------------------
XMLMsgLoader* XMLPlatformUtils::loadAMsgSet(const XMLCh* const msgDomain)
{
#if defined(XML_USE_INMEMORY_MSGLOADER)
    return new InMemMsgLoader(msgDomain);
#else
    return 0;
#endif
}

XMLNetAccessor* XMLPlatformUtils::makeNetAccessor()
{
  return 0;
}

XMLTransService* XMLPlatformUtils::makeTransService()
{
#if defined(XML_USE_ICU_TRANSCODER)
    return new ICUTransService;
#elif defined(XML_USE_ICONV_TRANSCODER)
    return new IconvTransService;
#else
    return 0;
#endif
}

#include <xercesc/util/LogicalPath.c>

XERCES_CPP_NAMESPACE_END

<|endoftext|>


<commit_before>#include "stdafx.h"

#include "helper.h"
#include "Package.h"

using Platform::String;

using namespace doo::metrodriver;

enum Action {
  Run,
  Install,
  Update,
  Uninstall
};

Action getAction(const wchar_t* name) {
  if (name == nullptr || StrCmpIW(name, L"run") == 0) {
    return Action::Run;
  } else if (StrCmpIW(name, L"install") == 0) {
    return Action::Install;
  } else if (StrCmpIW(name, L"update") == 0) {
    return Action::Update;
  } else if (StrCmpIW(name, L"uninstall") == 0) {
    return Action::Uninstall;
  }
  throw ref new Platform::FailureException("Invalid action");
}

static bool endsWith(const std::wstring& str1, const std::wstring& str2) {
  size_t foundPos = str1.rfind(str2);
  return (foundPos == (str1.length()-str2.length()));
}

/*
 validate command line arguments
 the first argument must be a file called AppxManifest.xml or a valid package file ending on ".appx"
 the second argument is the action to perform: install, update, uninstall or run
 the third is optional but if present must be an existing executable file
*/
bool validateArguments(Platform::Array<String^>^ args) {
  if (args->Length < 2) {
    _tprintf_s(L"Please specify the AppxManifest.xml for the application that should be run.\n");
    return false;
  }
  std::wstring sourceFileName(args[1]->Data());
  std::transform(sourceFileName.begin(), sourceFileName.end(), sourceFileName.begin(), ::tolower);
  if (!(endsWith(sourceFileName, L"appxmanifest.xml") || endsWith(sourceFileName, L".appx"))) {
    _tprintf_s(L"The first parameter needs to be a file called AppXManifest.xml or an .appx file\n");
    return false;
  }

  std::ifstream sourceFile(args[1]->Data(), std::ifstream::in);
  if (!sourceFile.is_open()) {
    _tprintf_s(L"Could not open %s\n", args[1]->Data());
    return false;
  }
  sourceFile.close();

  if (args->Length > 2) {
    try {
      auto action = getAction(args[2]->Data());
    } catch (...) {
      _tprintf_s(L"Invalid action. Available commands are: run, install, uninstall\n");
      return false;
    }
  }

  if (args->Length > 3) {
    std::ifstream callback(args[3]->Data(), std::ifstream::in);
    if (!callback.is_open()) {
      _tprintf_s(L"Callback not found: %s \n", args[3]->Data());
      return false;
    }
    callback.close();
  }

  return true;
}

// invoke the executable in callback with fullAppId as its argument
void InvokeCallback(Platform::String^ callback, Platform::String^ fullAppId) {
    EmptyStruct<PROCESS_INFORMATION> processInformation;
    EmptyStruct<STARTUPINFO> startupInfo;
    std::wstring commandLine(("\"" + callback + "\" " + fullAppId)->Data());
    if (CreateProcessW(NULL, &commandLine[0], NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation)) {
      WaitForSingleObjectEx(processInformation.hProcess, INFINITE, false );
      // Close process and thread handles.
      CloseHandle( processInformation.hProcess );
      CloseHandle( processInformation.hThread );
    } else {
      auto errorCode = GetLastError();
      LPVOID messageBuffer;
      FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        errorCode,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&messageBuffer,
        0, NULL );
      _tprintf_s(L"Couldn't execute callback: %s\n", messageBuffer);
      LocalFree(messageBuffer);
    }
}

void runPackage(Package& package) {
  package.install(Package::InstallationMode::Skip);
  package.enableDebugging(true);

  // start the application
  _tprintf_s(L"Launching app %s\n", package.getFullAppId()->Data());
  auto processId = package.startApplication();
  auto process = ATL::CHandle(OpenProcess(SYNCHRONIZE, false, (DWORD)processId));
  if (process == INVALID_HANDLE_VALUE) {
    throw ref new Platform::FailureException(L"Could not start app. Terminating.\n");
  }

  _tprintf_s(L"Waiting for application %s to finish...\n", package.getFullAppId()->Data());
  WaitForSingleObjectEx(process, INFINITE, false);
  _tprintf_s(L"Application complete\n");
}

/**
  Install and run the application identified by the manifest given as first parameter
  If a second parameter is given, it will be called after the application has exited
  The first parameter to the callback will be the name of the package
 **/
int __cdecl main(Platform::Array<String^>^ args) {
  if (!validateArguments(args)) {
    return -1;
  }

  Package package(args[1]);

  switch (getAction(args[2]->Data())) {
    case Install:
      package.install(Package::InstallationMode::Reinstall);
      package.enableDebugging(false);
      break;
    case Update:
      package.install(Package::InstallationMode::Update);
      package.enableDebugging(false);
      break;
    case Run:
      runPackage(package);
      // check if there was a callback supplied
      if (args->Length > 3) {
        _tprintf_s(L"Invoking callback: %s\n", args[3]->Data());
        InvokeCallback(args[3], package.getFullAppId());
      }
      break;
    case Uninstall:
      package.uninstall();
      break;
  }
  _tprintf_s(L"Done. Thank you for using MetroDriver.\n");
  return 0;
}<commit_msg>Improve error handling/reporting<commit_after>#include "stdafx.h"

#include "helper.h"
#include "Package.h"

using Platform::String;

using namespace doo::metrodriver;

enum Action {
  Run,
  Install,
  Update,
  Uninstall
};

Action getAction(const wchar_t* name) {
  if (name == nullptr || StrCmpIW(name, L"run") == 0) {
    return Action::Run;
  } else if (StrCmpIW(name, L"install") == 0) {
    return Action::Install;
  } else if (StrCmpIW(name, L"update") == 0) {
    return Action::Update;
  } else if (StrCmpIW(name, L"uninstall") == 0) {
    return Action::Uninstall;
  }
  throw ref new Platform::FailureException("Invalid action");
}

static bool endsWith(const std::wstring& str1, const std::wstring& str2) {
  size_t foundPos = str1.rfind(str2);
  return (foundPos == (str1.length()-str2.length()));
}

/*
 validate command line arguments
 the first argument must be a file called AppxManifest.xml or a valid package file ending on ".appx"
 the second argument is the action to perform: install, update, uninstall or run
 the third is optional but if present must be an existing executable file
*/
bool validateArguments(Platform::Array<String^>^ args) {
  if (args->Length < 2) {
    _tprintf_s(L"Please specify the AppxManifest.xml for the application that should be run.\n");
    return false;
  }
  std::wstring sourceFileName(args[1]->Data());
  std::transform(sourceFileName.begin(), sourceFileName.end(), sourceFileName.begin(), ::tolower);
  if (!(endsWith(sourceFileName, L"appxmanifest.xml") || endsWith(sourceFileName, L".appx"))) {
    _tprintf_s(L"The first parameter needs to be a file called AppXManifest.xml or an .appx file\n");
    return false;
  }

  std::ifstream sourceFile(args[1]->Data(), std::ifstream::in);
  if (!sourceFile.is_open()) {
    _tprintf_s(L"Could not open %s\n", args[1]->Data());
    return false;
  }
  sourceFile.close();

  if (args->Length > 2) {
    try {
      auto action = getAction(args[2]->Data());
    } catch (...) {
      _tprintf_s(L"Invalid action. Available commands are: run, install, uninstall\n");
      return false;
    }
  }

  if (args->Length > 3) {
    std::ifstream callback(args[3]->Data(), std::ifstream::in);
    if (!callback.is_open()) {
      _tprintf_s(L"Callback not found: %s \n", args[3]->Data());
      return false;
    }
    callback.close();
  }

  return true;
}

// invoke the executable in callback with fullAppId as its argument
void InvokeCallback(Platform::String^ callback, Platform::String^ fullAppId) {
    EmptyStruct<PROCESS_INFORMATION> processInformation;
    EmptyStruct<STARTUPINFO> startupInfo;
    std::wstring commandLine(("\"" + callback + "\" " + fullAppId)->Data());
    if (CreateProcessW(NULL, &commandLine[0], NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation)) {
      WaitForSingleObjectEx(processInformation.hProcess, INFINITE, false );
      // Close process and thread handles.
      CloseHandle( processInformation.hProcess );
      CloseHandle( processInformation.hThread );
    } else {
      auto errorCode = GetLastError();
      LPVOID messageBuffer;
      FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        errorCode,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&messageBuffer,
        0, NULL );
      _tprintf_s(L"Couldn't execute callback: %s\n", messageBuffer);
      LocalFree(messageBuffer);
    }
}

void runPackage(Package& package) {
  package.install(Package::InstallationMode::Skip);
  package.enableDebugging(true);

  // start the application
  _tprintf_s(L"Launching app %s\n", package.getFullAppId()->Data());
  auto processId = package.startApplication();
  auto process = ATL::CHandle(OpenProcess(SYNCHRONIZE, false, (DWORD)processId));
  if (process == INVALID_HANDLE_VALUE) {
    throw ref new Platform::FailureException(L"Could not start app. Terminating.\n");
  }

  _tprintf_s(L"Waiting for application %s to finish...\n", package.getFullAppId()->Data());
  WaitForSingleObjectEx(process, INFINITE, false);
  _tprintf_s(L"Application complete\n");
}

/**
  Install and run the application identified by the manifest given as first parameter
  If a second parameter is given, it will be called after the application has exited
  The first parameter to the callback will be the name of the package
 **/
int __cdecl main(Platform::Array<String^>^ args) {
  if (!validateArguments(args)) {
    return -1;
  }

  try {
    Package package(args[1]);

    switch (getAction(args[2]->Data())) {
    case Install:
      package.install(Package::InstallationMode::Reinstall);
      package.enableDebugging(false);
      break;
    case Update:
      package.install(Package::InstallationMode::Update);
      package.enableDebugging(false);
      break;
    case Run:
      runPackage(package);
      // check if there was a callback supplied
      if (args->Length > 3) {
        _tprintf_s(L"Invoking callback: %s\n", args[3]->Data());
        InvokeCallback(args[3], package.getFullAppId());
      }
      break;
    case Uninstall:
      package.uninstall();
      break;
    }
  } catch (Platform::Exception^ e) {
    _tprintf_s(L"An error occurred: %s\n", e->Message->Data());
  }

  _tprintf_s(L"Done. Thank you for using MetroDriver.\n");
  return 0;
}<|endoftext|>


<commit_before>/**
 * @copyright
 * ====================================================================
 *    Licensed to the Apache Software Foundation (ASF) under one
 *    or more contributor license agreements.  See the NOTICE file
 *    distributed with this work for additional information
 *    regarding copyright ownership.  The ASF licenses this file
 *    to you under the Apache License, Version 2.0 (the
 *    "License"); you may not use this file except in compliance
 *    with the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing,
 *    software distributed under the License is distributed on an
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *    KIND, either express or implied.  See the License for the
 *    specific language governing permissions and limitations
 *    under the License.
 * ====================================================================
 * @endcopyright
 */

#include "jniwrapper/jni_stack.hpp"

#include "AuthnCallback.hpp"

namespace JavaHL {

// Class JavaHL::AuthnCallback
const char* const AuthnCallback::m_class_name =
  JAVA_PACKAGE"/callback/AuthnCallback";

AuthnCallback::ClassImpl::ClassImpl(::Java::Env env, jclass cls)
  : ::Java::Object::ClassImpl(env, cls),
    m_mid_username_prompt(
        env.GetMethodID(cls, "usernamePrompt",
                        "(Ljava/lang/String;Z)"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$UsernameResult;")),
    m_mid_user_password_prompt(
        env.GetMethodID(cls, "userPasswordPrompt",
                        "(Ljava/lang/String;Ljava/lang/String;Z)"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$UserPasswordResult;")),
    m_mid_ssl_server_trust_prompt(
        env.GetMethodID(cls, "sslServerTrustPrompt",
                        "(Ljava/lang/String;"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$SSLServerCertFailures;"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$SSLServerCertInfo;"
                        "Z)"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$SSLServerTrustResult;")),
    m_mid_ssl_client_cert_prompt(
        env.GetMethodID(cls, "sslClientCertPrompt",
                        "(Ljava/lang/String;Z)"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$SSLClientCertResult;")),
    m_mid_ssl_client_cert_passphrase_prompt(
        env.GetMethodID(cls, "sslClientCertPassphrasePrompt",
                        "(Ljava/lang/String;Z)"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$SSLClientCertPassphraseResult;")),
    m_mid_allow_store_plaintext_password(
        env.GetMethodID(cls, "allowStorePlaintextPassword",
                        "(Ljava/lang/String;)Z")),
    m_mid_allow_store_plaintext_passphrase(
        env.GetMethodID(cls, "allowStorePlaintextPassphrase",
                        "(Ljava/lang/String;)Z"))
{}

AuthnCallback::ClassImpl::~ClassImpl() {}

jobject AuthnCallback::username_prompt(const ::Java::String& realm,
                                       bool may_save)
{
  return m_env.CallObjectMethod(m_jthis, impl().m_mid_username_prompt,
                                realm.get(), jboolean(may_save));
}

jobject AuthnCallback::user_password_prompt(const ::Java::String& realm,
                                            const ::Java::String& username,
                                            bool may_save)
{
  return m_env.CallObjectMethod(m_jthis, impl().m_mid_user_password_prompt,
                                realm.get(), username.get(),
                                jboolean(may_save));
}

jobject AuthnCallback::ssl_server_trust_prompt(
    const ::Java::String& realm,
    const SSLServerCertFailures& failures,
    const SSLServerCertInfo& info,
    bool may_save)
{
  return m_env.CallObjectMethod(m_jthis, impl().m_mid_ssl_server_trust_prompt,
                                realm.get(), failures.get(), info.get(),
                                jboolean(may_save));
}

jobject AuthnCallback::ssl_client_cert_prompt(const ::Java::String&
                                              realm, bool may_save)
{
  return m_env.CallObjectMethod(m_jthis, impl().m_mid_ssl_client_cert_prompt,
                                realm.get(), jboolean(may_save));
}

jobject AuthnCallback::ssl_client_cert_passphrase_prompt(
    const ::Java::String& realm,
    bool may_save)
{
  return m_env.CallObjectMethod(m_jthis,
                                impl().m_mid_ssl_client_cert_passphrase_prompt,
                                realm.get(), jboolean(may_save));
}

bool AuthnCallback::allow_store_plaintext_password(const ::Java::String& realm)
{
  return m_env.CallBooleanMethod(m_jthis,
                                 impl().m_mid_allow_store_plaintext_password,
                                 realm.get());
}

bool AuthnCallback::allow_store_plaintext_passphrase(const ::Java::String& realm)
{
  return m_env.CallBooleanMethod(m_jthis,
                                 impl().m_mid_allow_store_plaintext_passphrase,
                                 realm.get());
}

// Class JavaHL::AuthnCallback::AuthnResult
const char* const AuthnCallback::AuthnResult::m_class_name =
  JAVA_PACKAGE"/callback/AuthnCallback$AuthnResult";

AuthnCallback::AuthnResult::ClassImpl::ClassImpl(::Java::Env env, jclass cls)
  : ::Java::Object::ClassImpl(env, cls),
    m_fid_save(env.GetFieldID(cls, "save", "Z")),
    m_fid_trust(env.GetFieldID(cls, "trust", "Z")),
    m_fid_identity(env.GetFieldID(cls, "identity", "Ljava/lang/String;")),
    m_fid_secret(env.GetFieldID(cls, "secret", "Ljava/lang/String;"))
{}

AuthnCallback::AuthnResult::ClassImpl::~ClassImpl() {}

// Class JavaHL::AuthnCallback::SSLServerCertFailures
const char* const AuthnCallback::SSLServerCertFailures::m_class_name =
  JAVA_PACKAGE"/callback/AuthnCallback$SSLServerCertFailures";

AuthnCallback::SSLServerCertFailures::ClassImpl::ClassImpl(
    ::Java::Env env, jclass cls)
  : ::Java::Object::ClassImpl(env, cls),
    m_mid_ctor(env.GetMethodID(cls, "<init>", "(I)V"))
{}

AuthnCallback::SSLServerCertFailures::ClassImpl::~ClassImpl() {}

AuthnCallback::SSLServerCertFailures::SSLServerCertFailures(
    ::Java::Env env, jint failures)
  : ::Java::Object(env,
                   ::Java::ClassCache::get_authn_ssl_server_cert_failures())
{
  set_this(env.NewObject(get_class(), impl().m_mid_ctor, failures));
}

// Class JavaHL::AuthnCallback::SSLServerCertInfo
const char* const AuthnCallback::SSLServerCertInfo::m_class_name =
  JAVA_PACKAGE"/callback/AuthnCallback$SSLServerCertInfo";

AuthnCallback::SSLServerCertInfo::ClassImpl::ClassImpl(
    ::Java::Env env, jclass cls)
  : ::Java::Object::ClassImpl(env, cls),
    m_mid_ctor(env.GetMethodID(cls, "<init>",
                               "(Ljava/lang/String;"
                               "Ljava/lang/String;"
                               "Ljava/lang/String;"
                               "Ljava/lang/String;"
                               "Ljava/lang/String;"
                               "Ljava/lang/String;)V"))
{}

AuthnCallback::SSLServerCertInfo::ClassImpl::~ClassImpl() {}

AuthnCallback::SSLServerCertInfo::SSLServerCertInfo(
    ::Java::Env env,
    const ::Java::String& hostname,
    const ::Java::String& fingerprint,
    const ::Java::String& validFrom,
    const ::Java::String& validUntil,
    const ::Java::String& issuer,
    const ::Java::String& der)
  : ::Java::Object(env,
                   ::Java::ClassCache::get_authn_ssl_server_cert_failures())
{
  set_this(env.NewObject(get_class(), impl().m_mid_ctor,
                         hostname.get(), fingerprint.get(),
                         validFrom.get(), validUntil.get(),
                         issuer.get(), der.get()));
}

// Class JavaHL::UserPasswordCallback
const char* const UserPasswordCallback::m_class_name =
  JAVA_PACKAGE"/callback/UserPasswordCallback";

UserPasswordCallback::ClassImpl::ClassImpl(::Java::Env env, jclass cls)
  : ::Java::Object::ClassImpl(env, cls),
    m_mid_ask_trust_ssl_server(
        env.GetMethodID(cls, "askTrustSSLServer",
                        "(Ljava/lang/String;Z)I")),
    m_mid_prompt_2arg(
        env.GetMethodID(cls, "prompt",
                        "(Ljava/lang/String;Ljava/lang/String;)Z")),
    m_mid_ask_yes_no(
        env.GetMethodID(cls, "askYesNo",
                        "(Ljava/lang/String;Ljava/lang/String;Z)Z")),
    m_mid_ask_question_3arg(
        env.GetMethodID(cls, "askQuestion",
                        "(Ljava/lang/String;Ljava/lang/String;Z)"
                        "Ljava/lang/String;")),
    m_mid_get_username(
        env.GetMethodID(cls, "getUsername",
                        "()Ljava/lang/String;")),
    m_mid_get_password(
        env.GetMethodID(cls, "getPassword",
                        "()Ljava/lang/String;")),
    m_mid_prompt(
        env.GetMethodID(cls, "prompt",
                        "(Ljava/lang/String;Ljava/lang/String;Z)Z")),
    m_mid_ask_question(
        env.GetMethodID(cls, "askQuestion",
                        "(Ljava/lang/String;Ljava/lang/String;ZZ)"
                        "Ljava/lang/String;")),
    m_mid_user_allowed_save(
        env.GetMethodID(cls, "userAllowedSave", "()Z"))
{}

UserPasswordCallback::ClassImpl::~ClassImpl() {}

jint UserPasswordCallback::ask_trust_ssl_server(const ::Java::String& info,
                                                bool allow_permanently)
{
  return m_env.CallIntMethod(m_jthis, impl().m_mid_ask_trust_ssl_server,
                             info.get(), jboolean(allow_permanently));
}

bool UserPasswordCallback::prompt(const ::Java::String& realm,
                                  const ::Java::String& username)
{
  return m_env.CallBooleanMethod(m_jthis, impl().m_mid_prompt_2arg,
                                 realm.get(), username.get());
}

bool UserPasswordCallback::ask_yes_no(const ::Java::String& realm,
                                      const ::Java::String& question,
                                      bool yes_is_default)
{
  return m_env.CallBooleanMethod(m_jthis, impl().m_mid_ask_yes_no,
                                 realm.get(), question.get(),
                                 jboolean(yes_is_default));
}

jstring UserPasswordCallback::ask_question(const ::Java::String& realm,
                                           const ::Java::String& question,
                                           bool show_answer)
{
  return jstring(m_env.CallObjectMethod(m_jthis,
                                        impl().m_mid_ask_question_3arg,
                                        realm.get(), question.get(),
                                        jboolean(show_answer)));
}

jstring UserPasswordCallback::get_username()
{
  return jstring(m_env.CallObjectMethod(m_jthis, impl().m_mid_get_username));
}

jstring UserPasswordCallback::get_password()
{
  return jstring(m_env.CallObjectMethod(m_jthis, impl().m_mid_get_password));
}

bool UserPasswordCallback::prompt(const ::Java::String& realm,
                                  const ::Java::String& username,
                                  bool may_save)
{
  return m_env.CallBooleanMethod(m_jthis, impl().m_mid_prompt,
                                 realm.get(), username.get(),
                                 jboolean(may_save));
}

jstring UserPasswordCallback::ask_question(const ::Java::String& realm,
                                           const ::Java::String& question,
                                           bool show_answer, bool may_save)
{
  return jstring(m_env.CallObjectMethod(m_jthis, impl().m_mid_ask_question,
                                        realm.get(), question.get(),
                                        jboolean(show_answer),
                                        jboolean(may_save)));
}

bool UserPasswordCallback::user_allowed_save()
{
  return m_env.CallBooleanMethod(m_jthis, impl().m_mid_user_allowed_save);
}

} // namespace JavaHL
<commit_msg>* subversion/bindings/javahl/native/AuthnCallback.cpp   (AuthnCallback::SSLServerCertInfo::SSLServerCertInfo):    Use the correct implementation class in the base constructor call.<commit_after>/**
 * @copyright
 * ====================================================================
 *    Licensed to the Apache Software Foundation (ASF) under one
 *    or more contributor license agreements.  See the NOTICE file
 *    distributed with this work for additional information
 *    regarding copyright ownership.  The ASF licenses this file
 *    to you under the Apache License, Version 2.0 (the
 *    "License"); you may not use this file except in compliance
 *    with the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing,
 *    software distributed under the License is distributed on an
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *    KIND, either express or implied.  See the License for the
 *    specific language governing permissions and limitations
 *    under the License.
 * ====================================================================
 * @endcopyright
 */

#include "jniwrapper/jni_stack.hpp"

#include "AuthnCallback.hpp"

namespace JavaHL {

// Class JavaHL::AuthnCallback
const char* const AuthnCallback::m_class_name =
  JAVA_PACKAGE"/callback/AuthnCallback";

AuthnCallback::ClassImpl::ClassImpl(::Java::Env env, jclass cls)
  : ::Java::Object::ClassImpl(env, cls),
    m_mid_username_prompt(
        env.GetMethodID(cls, "usernamePrompt",
                        "(Ljava/lang/String;Z)"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$UsernameResult;")),
    m_mid_user_password_prompt(
        env.GetMethodID(cls, "userPasswordPrompt",
                        "(Ljava/lang/String;Ljava/lang/String;Z)"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$UserPasswordResult;")),
    m_mid_ssl_server_trust_prompt(
        env.GetMethodID(cls, "sslServerTrustPrompt",
                        "(Ljava/lang/String;"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$SSLServerCertFailures;"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$SSLServerCertInfo;"
                        "Z)"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$SSLServerTrustResult;")),
    m_mid_ssl_client_cert_prompt(
        env.GetMethodID(cls, "sslClientCertPrompt",
                        "(Ljava/lang/String;Z)"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$SSLClientCertResult;")),
    m_mid_ssl_client_cert_passphrase_prompt(
        env.GetMethodID(cls, "sslClientCertPassphrasePrompt",
                        "(Ljava/lang/String;Z)"
                        "L"JAVA_PACKAGE"/callback/AuthnCallback"
                        "$SSLClientCertPassphraseResult;")),
    m_mid_allow_store_plaintext_password(
        env.GetMethodID(cls, "allowStorePlaintextPassword",
                        "(Ljava/lang/String;)Z")),
    m_mid_allow_store_plaintext_passphrase(
        env.GetMethodID(cls, "allowStorePlaintextPassphrase",
                        "(Ljava/lang/String;)Z"))
{}

AuthnCallback::ClassImpl::~ClassImpl() {}

jobject AuthnCallback::username_prompt(const ::Java::String& realm,
                                       bool may_save)
{
  return m_env.CallObjectMethod(m_jthis, impl().m_mid_username_prompt,
                                realm.get(), jboolean(may_save));
}

jobject AuthnCallback::user_password_prompt(const ::Java::String& realm,
                                            const ::Java::String& username,
                                            bool may_save)
{
  return m_env.CallObjectMethod(m_jthis, impl().m_mid_user_password_prompt,
                                realm.get(), username.get(),
                                jboolean(may_save));
}

jobject AuthnCallback::ssl_server_trust_prompt(
    const ::Java::String& realm,
    const SSLServerCertFailures& failures,
    const SSLServerCertInfo& info,
    bool may_save)
{
  return m_env.CallObjectMethod(m_jthis, impl().m_mid_ssl_server_trust_prompt,
                                realm.get(), failures.get(), info.get(),
                                jboolean(may_save));
}

jobject AuthnCallback::ssl_client_cert_prompt(const ::Java::String&
                                              realm, bool may_save)
{
  return m_env.CallObjectMethod(m_jthis, impl().m_mid_ssl_client_cert_prompt,
                                realm.get(), jboolean(may_save));
}

jobject AuthnCallback::ssl_client_cert_passphrase_prompt(
    const ::Java::String& realm,
    bool may_save)
{
  return m_env.CallObjectMethod(m_jthis,
                                impl().m_mid_ssl_client_cert_passphrase_prompt,
                                realm.get(), jboolean(may_save));
}

bool AuthnCallback::allow_store_plaintext_password(const ::Java::String& realm)
{
  return m_env.CallBooleanMethod(m_jthis,
                                 impl().m_mid_allow_store_plaintext_password,
                                 realm.get());
}

bool AuthnCallback::allow_store_plaintext_passphrase(const ::Java::String& realm)
{
  return m_env.CallBooleanMethod(m_jthis,
                                 impl().m_mid_allow_store_plaintext_passphrase,
                                 realm.get());
}

// Class JavaHL::AuthnCallback::AuthnResult
const char* const AuthnCallback::AuthnResult::m_class_name =
  JAVA_PACKAGE"/callback/AuthnCallback$AuthnResult";

AuthnCallback::AuthnResult::ClassImpl::ClassImpl(::Java::Env env, jclass cls)
  : ::Java::Object::ClassImpl(env, cls),
    m_fid_save(env.GetFieldID(cls, "save", "Z")),
    m_fid_trust(env.GetFieldID(cls, "trust", "Z")),
    m_fid_identity(env.GetFieldID(cls, "identity", "Ljava/lang/String;")),
    m_fid_secret(env.GetFieldID(cls, "secret", "Ljava/lang/String;"))
{}

AuthnCallback::AuthnResult::ClassImpl::~ClassImpl() {}

// Class JavaHL::AuthnCallback::SSLServerCertFailures
const char* const AuthnCallback::SSLServerCertFailures::m_class_name =
  JAVA_PACKAGE"/callback/AuthnCallback$SSLServerCertFailures";

AuthnCallback::SSLServerCertFailures::ClassImpl::ClassImpl(
    ::Java::Env env, jclass cls)
  : ::Java::Object::ClassImpl(env, cls),
    m_mid_ctor(env.GetMethodID(cls, "<init>", "(I)V"))
{}

AuthnCallback::SSLServerCertFailures::ClassImpl::~ClassImpl() {}

AuthnCallback::SSLServerCertFailures::SSLServerCertFailures(
    ::Java::Env env, jint failures)
  : ::Java::Object(env,
                   ::Java::ClassCache::get_authn_ssl_server_cert_failures())
{
  set_this(env.NewObject(get_class(), impl().m_mid_ctor, failures));
}

// Class JavaHL::AuthnCallback::SSLServerCertInfo
const char* const AuthnCallback::SSLServerCertInfo::m_class_name =
  JAVA_PACKAGE"/callback/AuthnCallback$SSLServerCertInfo";

AuthnCallback::SSLServerCertInfo::ClassImpl::ClassImpl(
    ::Java::Env env, jclass cls)
  : ::Java::Object::ClassImpl(env, cls),
    m_mid_ctor(env.GetMethodID(cls, "<init>",
                               "(Ljava/lang/String;"
                               "Ljava/lang/String;"
                               "Ljava/lang/String;"
                               "Ljava/lang/String;"
                               "Ljava/lang/String;"
                               "Ljava/lang/String;)V"))
{}

AuthnCallback::SSLServerCertInfo::ClassImpl::~ClassImpl() {}

AuthnCallback::SSLServerCertInfo::SSLServerCertInfo(
    ::Java::Env env,
    const ::Java::String& hostname,
    const ::Java::String& fingerprint,
    const ::Java::String& validFrom,
    const ::Java::String& validUntil,
    const ::Java::String& issuer,
    const ::Java::String& der)
  : ::Java::Object(env,
                   ::Java::ClassCache::get_authn_ssl_server_cert_info())
{
  set_this(env.NewObject(get_class(), impl().m_mid_ctor,
                         hostname.get(), fingerprint.get(),
                         validFrom.get(), validUntil.get(),
                         issuer.get(), der.get()));
}

// Class JavaHL::UserPasswordCallback
const char* const UserPasswordCallback::m_class_name =
  JAVA_PACKAGE"/callback/UserPasswordCallback";

UserPasswordCallback::ClassImpl::ClassImpl(::Java::Env env, jclass cls)
  : ::Java::Object::ClassImpl(env, cls),
    m_mid_ask_trust_ssl_server(
        env.GetMethodID(cls, "askTrustSSLServer",
                        "(Ljava/lang/String;Z)I")),
    m_mid_prompt_2arg(
        env.GetMethodID(cls, "prompt",
                        "(Ljava/lang/String;Ljava/lang/String;)Z")),
    m_mid_ask_yes_no(
        env.GetMethodID(cls, "askYesNo",
                        "(Ljava/lang/String;Ljava/lang/String;Z)Z")),
    m_mid_ask_question_3arg(
        env.GetMethodID(cls, "askQuestion",
                        "(Ljava/lang/String;Ljava/lang/String;Z)"
                        "Ljava/lang/String;")),
    m_mid_get_username(
        env.GetMethodID(cls, "getUsername",
                        "()Ljava/lang/String;")),
    m_mid_get_password(
        env.GetMethodID(cls, "getPassword",
                        "()Ljava/lang/String;")),
    m_mid_prompt(
        env.GetMethodID(cls, "prompt",
                        "(Ljava/lang/String;Ljava/lang/String;Z)Z")),
    m_mid_ask_question(
        env.GetMethodID(cls, "askQuestion",
                        "(Ljava/lang/String;Ljava/lang/String;ZZ)"
                        "Ljava/lang/String;")),
    m_mid_user_allowed_save(
        env.GetMethodID(cls, "userAllowedSave", "()Z"))
{}

UserPasswordCallback::ClassImpl::~ClassImpl() {}

jint UserPasswordCallback::ask_trust_ssl_server(const ::Java::String& info,
                                                bool allow_permanently)
{
  return m_env.CallIntMethod(m_jthis, impl().m_mid_ask_trust_ssl_server,
                             info.get(), jboolean(allow_permanently));
}

bool UserPasswordCallback::prompt(const ::Java::String& realm,
                                  const ::Java::String& username)
{
  return m_env.CallBooleanMethod(m_jthis, impl().m_mid_prompt_2arg,
                                 realm.get(), username.get());
}

bool UserPasswordCallback::ask_yes_no(const ::Java::String& realm,
                                      const ::Java::String& question,
                                      bool yes_is_default)
{
  return m_env.CallBooleanMethod(m_jthis, impl().m_mid_ask_yes_no,
                                 realm.get(), question.get(),
                                 jboolean(yes_is_default));
}

jstring UserPasswordCallback::ask_question(const ::Java::String& realm,
                                           const ::Java::String& question,
                                           bool show_answer)
{
  return jstring(m_env.CallObjectMethod(m_jthis,
                                        impl().m_mid_ask_question_3arg,
                                        realm.get(), question.get(),
                                        jboolean(show_answer)));
}

jstring UserPasswordCallback::get_username()
{
  return jstring(m_env.CallObjectMethod(m_jthis, impl().m_mid_get_username));
}

jstring UserPasswordCallback::get_password()
{
  return jstring(m_env.CallObjectMethod(m_jthis, impl().m_mid_get_password));
}

bool UserPasswordCallback::prompt(const ::Java::String& realm,
                                  const ::Java::String& username,
                                  bool may_save)
{
  return m_env.CallBooleanMethod(m_jthis, impl().m_mid_prompt,
                                 realm.get(), username.get(),
                                 jboolean(may_save));
}

jstring UserPasswordCallback::ask_question(const ::Java::String& realm,
                                           const ::Java::String& question,
                                           bool show_answer, bool may_save)
{
  return jstring(m_env.CallObjectMethod(m_jthis, impl().m_mid_ask_question,
                                        realm.get(), question.get(),
                                        jboolean(show_answer),
                                        jboolean(may_save)));
}

bool UserPasswordCallback::user_allowed_save()
{
  return m_env.CallBooleanMethod(m_jthis, impl().m_mid_user_allowed_save);
}

} // namespace JavaHL
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkTensorFractionalAnisotropyImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <itkImage.h>
#include <itkHessianRecursiveGaussianImageFilter.h>
#include <itkTensorFractionalAnisotropyImageFilter.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkDiffusionTensor3D.h>

int itkTensorFractionalAnisotropyImageFilterTest(int, char* [] )
{

  // Define the dimension of the images
  const unsigned int myDimension = 3;

  // Declare the types of the images
  typedef itk::Image<float, myDimension>           myImageType;

  // Declare the type of the index to access images
  typedef itk::Index<myDimension>             myIndexType;

  // Declare the type of the size
  typedef itk::Size<myDimension>              mySizeType;

  // Declare the type of the Region
  typedef itk::ImageRegion<myDimension>        myRegionType;

  // Create the image
  myImageType::Pointer inputImage  = myImageType::New();

  // Define their size, and start index
  mySizeType size;
  size[0] = 8;
  size[1] = 8;
  size[2] = 8;

  myIndexType start;
  start.Fill(0);

  myRegionType region;
  region.SetIndex( start );
  region.SetSize( size );

  // Initialize Image A
  inputImage->SetLargestPossibleRegion( region );
  inputImage->SetBufferedRegion( region );
  inputImage->SetRequestedRegion( region );
  inputImage->Allocate();

  // Declare Iterator type for the input image
  typedef itk::ImageRegionIteratorWithIndex<myImageType>  myIteratorType;

  // Create one iterator for the Input Image A (this is a light object)
  myIteratorType it( inputImage, inputImage->GetRequestedRegion() );

  // Initialize the content of Image A
  while( !it.IsAtEnd() )
    {
    it.Set( 0.0 );
    ++it;
    }

  size[0] = 4;
  size[1] = 4;
  size[2] = 4;

  start[0] = 2;
  start[1] = 2;
  start[2] = 2;

  // Create one iterator for an internal region
  region.SetSize( size );
  region.SetIndex( start );
  myIteratorType itb( inputImage, region );

  // Initialize the content the internal region
  while( !itb.IsAtEnd() )
    {
    itb.Set( 100.0 );
    ++itb;
    }

  // Declare the type for the tensor pixel and tensor image.
  typedef itk::DiffusionTensor3D< double > myTensorPixelType;
  typedef itk::Image< myTensorPixelType, myDimension > myDTIImageType;
  typedef myTensorPixelType::RealValueType myRealValueType;

  // Declare the type for the image generator
  typedef itk::HessianRecursiveGaussianImageFilter<
                                            myImageType,
                                            myDTIImageType >  myFilterType;

  typedef itk::Image< myRealValueType, myDimension > myFaImageType;

  // Create a  Filter
  myFilterType::Pointer filter = myFilterType::New();

  // Connect the input images
  filter->SetInput( inputImage );

  // Select the value of Sigma
  filter->SetSigma( 2.5 );

  typedef itk::TensorFractionalAnisotropyImageFilter<
                                                  myDTIImageType,
                                                  myFaImageType
                                                        > FAFilterType;

  FAFilterType::Pointer fractionalAnisotropyFilter = FAFilterType::New();

  fractionalAnisotropyFilter->SetInput( filter->GetOutput() );

  // Execute the filter
  fractionalAnisotropyFilter->Update();

  // Get the Smart Pointer to the Filter Output
  // It is important to do it AFTER the filter is Updated
  // Because the object connected to the output may be changed
  // by another during GenerateData() call
  myFaImageType::Pointer outputImage = fractionalAnisotropyFilter->GetOutput();

  // Declare Iterator type for the output image
  typedef itk::ImageRegionIteratorWithIndex<
                                 myFaImageType>  myOutputIteratorType;

  // Create an iterator for going through the output image
  myOutputIteratorType itg( outputImage,
                            outputImage->GetRequestedRegion() );

  //  Print the content of the result image
  std::cout << " Result " << std::endl;
  itg.GoToBegin();
  while( !itg.IsAtEnd() )
    {
    std::cout << itg.Get();
    ++itg;
    }

  // All objects should be automatically destroyed at this point
  return EXIT_SUCCESS;

}

<commit_msg>ENH: Added std::endl at the print out of final pixel results.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkTensorFractionalAnisotropyImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <itkImage.h>
#include <itkHessianRecursiveGaussianImageFilter.h>
#include <itkTensorFractionalAnisotropyImageFilter.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkDiffusionTensor3D.h>

int itkTensorFractionalAnisotropyImageFilterTest(int, char* [] )
{

  // Define the dimension of the images
  const unsigned int myDimension = 3;

  // Declare the types of the images
  typedef itk::Image<float, myDimension>           myImageType;

  // Declare the type of the index to access images
  typedef itk::Index<myDimension>             myIndexType;

  // Declare the type of the size
  typedef itk::Size<myDimension>              mySizeType;

  // Declare the type of the Region
  typedef itk::ImageRegion<myDimension>        myRegionType;

  // Create the image
  myImageType::Pointer inputImage  = myImageType::New();

  // Define their size, and start index
  mySizeType size;
  size[0] = 8;
  size[1] = 8;
  size[2] = 8;

  myIndexType start;
  start.Fill(0);

  myRegionType region;
  region.SetIndex( start );
  region.SetSize( size );

  // Initialize Image A
  inputImage->SetLargestPossibleRegion( region );
  inputImage->SetBufferedRegion( region );
  inputImage->SetRequestedRegion( region );
  inputImage->Allocate();

  // Declare Iterator type for the input image
  typedef itk::ImageRegionIteratorWithIndex<myImageType>  myIteratorType;

  // Create one iterator for the Input Image A (this is a light object)
  myIteratorType it( inputImage, inputImage->GetRequestedRegion() );

  // Initialize the content of Image A
  while( !it.IsAtEnd() )
    {
    it.Set( 0.0 );
    ++it;
    }

  size[0] = 4;
  size[1] = 4;
  size[2] = 4;

  start[0] = 2;
  start[1] = 2;
  start[2] = 2;

  // Create one iterator for an internal region
  region.SetSize( size );
  region.SetIndex( start );
  myIteratorType itb( inputImage, region );

  // Initialize the content the internal region
  while( !itb.IsAtEnd() )
    {
    itb.Set( 100.0 );
    ++itb;
    }

  // Declare the type for the tensor pixel and tensor image.
  typedef itk::DiffusionTensor3D< double > myTensorPixelType;
  typedef itk::Image< myTensorPixelType, myDimension > myDTIImageType;
  typedef myTensorPixelType::RealValueType myRealValueType;

  // Declare the type for the image generator
  typedef itk::HessianRecursiveGaussianImageFilter<
                                            myImageType,
                                            myDTIImageType >  myFilterType;

  typedef itk::Image< myRealValueType, myDimension > myFaImageType;

  // Create a  Filter
  myFilterType::Pointer filter = myFilterType::New();

  // Connect the input images
  filter->SetInput( inputImage );

  // Select the value of Sigma
  filter->SetSigma( 2.5 );

  typedef itk::TensorFractionalAnisotropyImageFilter<
                                                  myDTIImageType,
                                                  myFaImageType
                                                        > FAFilterType;

  FAFilterType::Pointer fractionalAnisotropyFilter = FAFilterType::New();

  fractionalAnisotropyFilter->SetInput( filter->GetOutput() );

  // Execute the filter
  fractionalAnisotropyFilter->Update();

  // Get the Smart Pointer to the Filter Output
  // It is important to do it AFTER the filter is Updated
  // Because the object connected to the output may be changed
  // by another during GenerateData() call
  myFaImageType::Pointer outputImage = fractionalAnisotropyFilter->GetOutput();

  // Declare Iterator type for the output image
  typedef itk::ImageRegionIteratorWithIndex<
                                 myFaImageType>  myOutputIteratorType;

  // Create an iterator for going through the output image
  myOutputIteratorType itg( outputImage,
                            outputImage->GetRequestedRegion() );

  //  Print the content of the result image
  std::cout << " Result " << std::endl;
  itg.GoToBegin();
  while( !itg.IsAtEnd() )
    {
    std::cout << itg.GetIndex() << " = " << itg.Get() << std::endl;
    ++itg;
    }

  // All objects should be automatically destroyed at this point
  return EXIT_SUCCESS;

}

<|endoftext|>


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

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

#ifndef _SDR_PROPERTIES_CUSTOMSHAPEPROPERTIES_HXX
#include <svx/sdr/properties/customshapeproperties.hxx>
#endif

#ifndef _SFXITEMSET_HXX
#include <svtools/itemset.hxx>
#endif
#ifndef _SFXSTYLE_HXX
#include <svtools/style.hxx>
#endif
#ifndef _SVDOASHP_HXX
#include <svx/svdoashp.hxx>
#endif
#ifndef _EEITEM_HXX
#include <svx/eeitem.hxx>
#endif
#ifndef _SDTAGITM_HXX
#include <svx/sdtagitm.hxx>
#endif
#ifndef _SFX_WHITER_HXX
#include <svtools/whiter.hxx>
#endif
#ifndef _SFXITEMSET_HXX
#include <svtools/itemset.hxx>
#endif
#ifndef _SFXSMPLHINT_HXX
#include <svtools/smplhint.hxx>
#endif

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

namespace sdr
{
    namespace properties
    {
        void CustomShapeProperties::UpdateTextFrameStatus()
        {
            SdrTextObj& rObj = (SdrTextObj&)GetSdrObject();
            SdrTextAutoGrowHeightItem& rAutoGrowHeightItem =
                (SdrTextAutoGrowHeightItem&)rObj.GetMergedItem( SDRATTR_TEXT_AUTOGROWHEIGHT );
            rObj.bTextFrame = rAutoGrowHeightItem.GetValue() != 0;

            if ( rObj.bTextFrame )
                rObj.NbcAdjustTextFrameWidthAndHeight();
        }

        SfxItemSet& CustomShapeProperties::CreateObjectSpecificItemSet(SfxItemPool& rPool)
        {
            return *(new SfxItemSet(rPool,

                // ranges from SdrAttrObj
                SDRATTR_START, SDRATTR_SHADOW_LAST,
                SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
                SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION,

                // Graphic Attributes
                SDRATTR_GRAF_FIRST, SDRATTR_GRAF_LAST,

                // 3d Properties
                SDRATTR_3D_FIRST, SDRATTR_3D_LAST,

                // CustomShape properties
                SDRATTR_CUSTOMSHAPE_FIRST, SDRATTR_CUSTOMSHAPE_LAST,

                // range from SdrTextObj
                EE_ITEMS_START, EE_ITEMS_END,

                // end
                0, 0));
        }
        sal_Bool CustomShapeProperties::AllowItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem ) const
        {
            sal_Bool bAllowItemChange = sal_True;
            if ( !pNewItem )
            {
                if ( ( nWhich >= SDRATTR_CUSTOMSHAPE_FIRST ) && ( nWhich <= SDRATTR_CUSTOMSHAPE_LAST ) )
                    bAllowItemChange = sal_False;
            }
            if ( bAllowItemChange )
                bAllowItemChange = TextProperties::AllowItemChange( nWhich, pNewItem );
            return bAllowItemChange;
        }
        void CustomShapeProperties::ClearObjectItem(const sal_uInt16 nWhich)
        {
            if ( !nWhich )
            {
                SfxWhichIter aIter( *mpItemSet );
                sal_uInt16 nWhich2 = aIter.FirstWhich();
                while( nWhich2 )
                {
                    TextProperties::ClearObjectItemDirect( nWhich2 );
                    nWhich2 = aIter.NextWhich();
                }
                SfxItemSet aSet((SfxItemPool&)(*GetSdrObject().GetObjectItemPool()));
                ItemSetChanged(aSet);
            }
            else
                TextProperties::ClearObjectItem( nWhich );
        }
        void CustomShapeProperties::ClearObjectItemDirect(const sal_uInt16 nWhich)
        {
            if ( !nWhich )
            {
                SfxWhichIter aIter( *mpItemSet );
                sal_uInt16 nWhich2 = aIter.FirstWhich();
                while( nWhich2 )
                {
                    TextProperties::ClearObjectItemDirect( nWhich2 );
                    nWhich2 = aIter.NextWhich();
                }
            }
            else
                TextProperties::ClearObjectItemDirect( nWhich );
        }
        void CustomShapeProperties::ItemSetChanged(const SfxItemSet& rSet)
        {
            SdrObjCustomShape& rObj = (SdrObjCustomShape&)GetSdrObject();

            if( SFX_ITEM_SET == rSet.GetItemState( SDRATTR_TEXT_AUTOGROWHEIGHT ) )
            {
                rObj.bTextFrame = ((SdrTextAutoGrowHeightItem&)rSet.Get( SDRATTR_TEXT_AUTOGROWHEIGHT )).GetValue() != 0;
            }

            // call parent
            TextProperties::ItemSetChanged(rSet);

            // local changes, removing cached objects
            rObj.InvalidateRenderGeometry();
        }
        void CustomShapeProperties::ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem)
        {
            SdrTextObj& rObj = (SdrTextObj&)GetSdrObject();
            //OutlinerParaObject* pParaObj = rObj.GetOutlinerParaObject();

            if( pNewItem && ( SDRATTR_TEXT_AUTOGROWHEIGHT == nWhich ) )
            {
                rObj.bTextFrame = ((SdrTextAutoGrowHeightItem*)pNewItem)->GetValue() != 0;
            }
            // call parent
            TextProperties::ItemChange( nWhich, pNewItem );
        }
        void CustomShapeProperties::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr)
        {
            TextProperties::SetStyleSheet( pNewStyleSheet, bDontRemoveHardAttr );
            UpdateTextFrameStatus();
        }
        void CustomShapeProperties::ForceDefaultAttributes()
        {
            UpdateTextFrameStatus();

/* SJ: Following is no good if creating customshapes, leading to objects that are white after loading via xml

            SdrTextObj& rObj = (SdrTextObj&)GetSdrObject();
            sal_Bool bTextFrame(rObj.IsTextFrame());

            // force ItemSet
            GetObjectItemSet();

            if(bTextFrame)
            {
                mpItemSet->Put(XLineStyleItem(XLINE_NONE));
                mpItemSet->Put(XFillColorItem(String(), Color(COL_WHITE)));
                mpItemSet->Put(XFillStyleItem(XFILL_NONE));
            }
            else
            {
                mpItemSet->Put(SvxAdjustItem(SVX_ADJUST_CENTER));
                mpItemSet->Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER));
                mpItemSet->Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER));
            }
*/
        }
        CustomShapeProperties::CustomShapeProperties(SdrObject& rObj)
        :   TextProperties(rObj)
        {
        }

        CustomShapeProperties::CustomShapeProperties(const CustomShapeProperties& rProps, SdrObject& rObj)
        :   TextProperties(rProps, rObj)
        {
        }

        CustomShapeProperties::~CustomShapeProperties()
        {
        }

        BaseProperties& CustomShapeProperties::Clone(SdrObject& rObj) const
        {
            return *(new CustomShapeProperties(*this, rObj));
        }
        void CustomShapeProperties::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
        {
            TextProperties::Notify( rBC, rHint );

            sal_Bool bRemoveRenderGeometry = sal_False;

            const SfxStyleSheetHint *pStyleHint = PTR_CAST( SfxStyleSheetHint, &rHint );
            const SfxSimpleHint *pSimpleHint = PTR_CAST( SfxSimpleHint, &rHint );
            if ( pStyleHint && pStyleHint->GetStyleSheet() == GetStyleSheet() )
            {
                switch( pStyleHint->GetHint() )
                {
                    case SFX_STYLESHEET_MODIFIED :
                    case SFX_STYLESHEET_CHANGED  :
                        bRemoveRenderGeometry = sal_True;
                    break;
                };
            }
            else if ( pSimpleHint && pSimpleHint->GetId() == SFX_HINT_DATACHANGED )
            {
                bRemoveRenderGeometry = sal_True;
            }
            if ( bRemoveRenderGeometry )
            {
                UpdateTextFrameStatus();

                // local changes, removing cached objects
                SdrObjCustomShape& rObj = (SdrObjCustomShape&)GetSdrObject();
                rObj.InvalidateRenderGeometry();
            }

        }
    } // end of namespace properties
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////
// eof
<commit_msg>INTEGRATION: CWS impress123 (1.13.32); FILE MERGED 2007/07/25 11:55:20 sj 1.13.32.1: #i79545# fixed refresh problem<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: customshapeproperties.cxx,v $
 *
 *  $Revision: 1.14 $
 *
 *  last change: $Author: hr $ $Date: 2007-08-02 18:27:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _SDR_PROPERTIES_CUSTOMSHAPEPROPERTIES_HXX
#include <svx/sdr/properties/customshapeproperties.hxx>
#endif

#ifndef _SFXITEMSET_HXX
#include <svtools/itemset.hxx>
#endif
#ifndef _SFXSTYLE_HXX
#include <svtools/style.hxx>
#endif
#ifndef _SVDOASHP_HXX
#include <svx/svdoashp.hxx>
#endif
#ifndef _EEITEM_HXX
#include <svx/eeitem.hxx>
#endif
#ifndef _SDTAGITM_HXX
#include <svx/sdtagitm.hxx>
#endif
#ifndef _SFX_WHITER_HXX
#include <svtools/whiter.hxx>
#endif
#ifndef _SFXITEMSET_HXX
#include <svtools/itemset.hxx>
#endif
#ifndef _SFXSMPLHINT_HXX
#include <svtools/smplhint.hxx>
#endif

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

namespace sdr
{
    namespace properties
    {
        void CustomShapeProperties::UpdateTextFrameStatus()
        {
            SdrTextObj& rObj = (SdrTextObj&)GetSdrObject();
            SdrTextAutoGrowHeightItem& rAutoGrowHeightItem =
                (SdrTextAutoGrowHeightItem&)rObj.GetMergedItem( SDRATTR_TEXT_AUTOGROWHEIGHT );
            rObj.bTextFrame = rAutoGrowHeightItem.GetValue() != 0;

            if ( rObj.bTextFrame )
                rObj.NbcAdjustTextFrameWidthAndHeight();
        }

        SfxItemSet& CustomShapeProperties::CreateObjectSpecificItemSet(SfxItemPool& rPool)
        {
            return *(new SfxItemSet(rPool,

                // ranges from SdrAttrObj
                SDRATTR_START, SDRATTR_SHADOW_LAST,
                SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
                SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION,

                // Graphic Attributes
                SDRATTR_GRAF_FIRST, SDRATTR_GRAF_LAST,

                // 3d Properties
                SDRATTR_3D_FIRST, SDRATTR_3D_LAST,

                // CustomShape properties
                SDRATTR_CUSTOMSHAPE_FIRST, SDRATTR_CUSTOMSHAPE_LAST,

                // range from SdrTextObj
                EE_ITEMS_START, EE_ITEMS_END,

                // end
                0, 0));
        }
        sal_Bool CustomShapeProperties::AllowItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem ) const
        {
            sal_Bool bAllowItemChange = sal_True;
            if ( !pNewItem )
            {
                if ( ( nWhich >= SDRATTR_CUSTOMSHAPE_FIRST ) && ( nWhich <= SDRATTR_CUSTOMSHAPE_LAST ) )
                    bAllowItemChange = sal_False;
            }
            if ( bAllowItemChange )
                bAllowItemChange = TextProperties::AllowItemChange( nWhich, pNewItem );
            return bAllowItemChange;
        }
        void CustomShapeProperties::ClearObjectItem(const sal_uInt16 nWhich)
        {
            if ( !nWhich )
            {
                SfxWhichIter aIter( *mpItemSet );
                sal_uInt16 nWhich2 = aIter.FirstWhich();
                while( nWhich2 )
                {
                    TextProperties::ClearObjectItemDirect( nWhich2 );
                    nWhich2 = aIter.NextWhich();
                }
                SfxItemSet aSet((SfxItemPool&)(*GetSdrObject().GetObjectItemPool()));
                ItemSetChanged(aSet);
            }
            else
                TextProperties::ClearObjectItem( nWhich );
        }
        void CustomShapeProperties::ClearObjectItemDirect(const sal_uInt16 nWhich)
        {
            if ( !nWhich )
            {
                SfxWhichIter aIter( *mpItemSet );
                sal_uInt16 nWhich2 = aIter.FirstWhich();
                while( nWhich2 )
                {
                    TextProperties::ClearObjectItemDirect( nWhich2 );
                    nWhich2 = aIter.NextWhich();
                }
            }
            else
                TextProperties::ClearObjectItemDirect( nWhich );
        }
        void CustomShapeProperties::ItemSetChanged(const SfxItemSet& rSet)
        {
            SdrObjCustomShape& rObj = (SdrObjCustomShape&)GetSdrObject();

            if( SFX_ITEM_SET == rSet.GetItemState( SDRATTR_TEXT_AUTOGROWHEIGHT ) )
            {
                rObj.bTextFrame = ((SdrTextAutoGrowHeightItem&)rSet.Get( SDRATTR_TEXT_AUTOGROWHEIGHT )).GetValue() != 0;
            }

            // call parent
            TextProperties::ItemSetChanged(rSet);

            // local changes, removing cached objects
            rObj.InvalidateRenderGeometry();
        }
        void CustomShapeProperties::ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem)
        {
            SdrObjCustomShape& rObj = (SdrObjCustomShape&)GetSdrObject();
            //OutlinerParaObject* pParaObj = rObj.GetOutlinerParaObject();

            if( pNewItem && ( SDRATTR_TEXT_AUTOGROWHEIGHT == nWhich ) )
            {
                rObj.bTextFrame = ((SdrTextAutoGrowHeightItem*)pNewItem)->GetValue() != 0;
            }
            // call parent
            TextProperties::ItemChange( nWhich, pNewItem );

            rObj.InvalidateRenderGeometry();
        }
        void CustomShapeProperties::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr)
        {
            TextProperties::SetStyleSheet( pNewStyleSheet, bDontRemoveHardAttr );
            UpdateTextFrameStatus();
        }
        void CustomShapeProperties::ForceDefaultAttributes()
        {
            UpdateTextFrameStatus();

/* SJ: Following is no good if creating customshapes, leading to objects that are white after loading via xml

            SdrTextObj& rObj = (SdrTextObj&)GetSdrObject();
            sal_Bool bTextFrame(rObj.IsTextFrame());

            // force ItemSet
            GetObjectItemSet();

            if(bTextFrame)
            {
                mpItemSet->Put(XLineStyleItem(XLINE_NONE));
                mpItemSet->Put(XFillColorItem(String(), Color(COL_WHITE)));
                mpItemSet->Put(XFillStyleItem(XFILL_NONE));
            }
            else
            {
                mpItemSet->Put(SvxAdjustItem(SVX_ADJUST_CENTER));
                mpItemSet->Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER));
                mpItemSet->Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER));
            }
*/
        }
        CustomShapeProperties::CustomShapeProperties(SdrObject& rObj)
        :   TextProperties(rObj)
        {
        }

        CustomShapeProperties::CustomShapeProperties(const CustomShapeProperties& rProps, SdrObject& rObj)
        :   TextProperties(rProps, rObj)
        {
        }

        CustomShapeProperties::~CustomShapeProperties()
        {
        }

        BaseProperties& CustomShapeProperties::Clone(SdrObject& rObj) const
        {
            return *(new CustomShapeProperties(*this, rObj));
        }
        void CustomShapeProperties::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
        {
            TextProperties::Notify( rBC, rHint );

            sal_Bool bRemoveRenderGeometry = sal_False;

            const SfxStyleSheetHint *pStyleHint = PTR_CAST( SfxStyleSheetHint, &rHint );
            const SfxSimpleHint *pSimpleHint = PTR_CAST( SfxSimpleHint, &rHint );
            if ( pStyleHint && pStyleHint->GetStyleSheet() == GetStyleSheet() )
            {
                switch( pStyleHint->GetHint() )
                {
                    case SFX_STYLESHEET_MODIFIED :
                    case SFX_STYLESHEET_CHANGED  :
                        bRemoveRenderGeometry = sal_True;
                    break;
                };
            }
            else if ( pSimpleHint && pSimpleHint->GetId() == SFX_HINT_DATACHANGED )
            {
                bRemoveRenderGeometry = sal_True;
            }
            if ( bRemoveRenderGeometry )
            {
                UpdateTextFrameStatus();

                // local changes, removing cached objects
                SdrObjCustomShape& rObj = (SdrObjCustomShape&)GetSdrObject();
                rObj.InvalidateRenderGeometry();
            }

        }
    } // end of namespace properties
} // end of namespace sdr

//////////////////////////////////////////////////////////////////////////////
// eof
<|endoftext|>


<commit_before>#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <vector>

#include "hash.hpp"

struct Block {
	hash256_t hash = {};
	hash256_t prevBlockHash = {};
	uint32_t bits;

	Block () {}
	Block (const hash256_t& hash, const hash256_t& prevBlockHash, const uint32_t bits) : hash(hash), prevBlockHash(prevBlockHash), bits(bits) {}
};

// find all blocks who are not parents to any other blocks (aka, a chain tip)
auto findChainTips(const std::map<hash256_t, Block>& blocks) {
	std::map<hash256_t, bool> parents;

	for (const auto& blockIter : blocks) {
		const auto block = blockIter.second;
		if (blocks.find(block.prevBlockHash) == blocks.end()) continue;

		parents[block.prevBlockHash] = true;
	}

	std::vector<Block> tips;
	for (const auto& blockIter : blocks) {
		const auto block = blockIter.second;
		if (parents.find(block.hash) != parents.end()) continue;

		tips.push_back(block);
	}

	return tips;
}

auto determineWork(std::map<hash256_t, size_t>& workCache, const std::map<hash256_t, Block>& blocks, const Block source) {
	auto visitor = source;
	size_t totalWork = source.bits;

	// naively walk the chain
	while (true) {
		const auto prevBlockIter = blocks.find(visitor.prevBlockHash);
		if (prevBlockIter == blocks.end()) break;

		const auto prevBlockWorkCacheIter = workCache.find(visitor.prevBlockHash);
		if (prevBlockWorkCacheIter != workCache.end()) {
			totalWork += prevBlockWorkCacheIter->second;
			break;
		}

		visitor = prevBlockIter->second;
		totalWork += visitor.bits;
	}

	workCache.emplace(source.hash, totalWork);

	return totalWork;
}

auto findBest(const std::map<hash256_t, Block>& blocks) {
	auto bestBlock = Block();
	size_t mostWork = 0;

	std::map<hash256_t, size_t> workCache;

	for (const auto& blockIter : blocks) {
		const auto block = blockIter.second;
		const auto work = determineWork(workCache, blocks, block);

		if (work > mostWork) {
			bestBlock = block;
			mostWork = work;
		}
	}

	auto visitor = bestBlock;
	std::vector<Block> blockchain;
	blockchain.push_back(visitor);

	// walk the chain
	while (true) {
		const auto prevBlockIter = blocks.find(visitor.prevBlockHash);
		if (prevBlockIter == blocks.end()) break;

		visitor = prevBlockIter->second;
		blockchain.push_back(visitor);
	}

	return blockchain;
}

int main () {
	std::map<hash256_t, Block> blocks;

	// read block headers from stdin until EOF
	{
		while (true) {
			uint8_t rbuf[80];
			const auto read = fread(rbuf, sizeof(rbuf), 1, stdin);

			// EOF?
			if (read == 0) break;

			hash256_t hash, prevBlockHash;
			uint32_t bits;

			hash256(&hash[0], rbuf, 80);
			memcpy(&prevBlockHash[0], rbuf + 4, 32);
			memcpy(&bits, rbuf + 72, 4);

			blocks[hash] = Block(hash, prevBlockHash, bits);
		}

		std::cerr << "Read " << blocks.size() << " headers" << std::endl;
	}

	// how many tips exist?
	{
		const auto chainTips = findChainTips(blocks);
		std::cerr << "Found " << chainTips.size() << " chain tips" << std::endl;
	}

	// what is the best?
	{
		const auto bestBlockChain = findBest(blocks);
		const auto genesis = bestBlockChain.back();
		const auto tip = bestBlockChain.front();

		// output
		std::cerr << "Best chain" << std::endl;
		std::cerr << "- Height: " << bestBlockChain.size() - 1 << std::endl;
		std::cerr << std::hex;
		std::cerr << "- Genesis: ";
		for (size_t i = 31; i < 32; --i) std::cerr << std::setw(2) << std::setfill('0') << (uint32_t) genesis.hash[i];
		std::cerr << std::endl << "- Tip: ";
		for (size_t i = 31; i < 32; --i) std::cerr << std::setw(2) << std::setfill('0') << (uint32_t) tip.hash[i];
		std::cerr << std::endl << std::dec;

		for (auto it = bestBlockChain.crbegin(); it != bestBlockChain.crend(); ++it) {
			fwrite(&it->hash[0], 32, 1, stdout);
		}
	}

	return 0;
}
<commit_msg>bestchain: use r-values and emplace<commit_after>#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <vector>

#include "hash.hpp"

struct Block {
	hash256_t hash = {};
	hash256_t prevBlockHash = {};
	uint32_t bits;

	Block () {}
	Block (const hash256_t& hash, const hash256_t& prevBlockHash, const uint32_t bits) : hash(hash), prevBlockHash(prevBlockHash), bits(bits) {}
};

// find all blocks who are not parents to any other blocks (aka, a chain tip)
auto findChainTips(const std::map<hash256_t, Block>& blocks) {
	std::map<hash256_t, bool> parents;

	for (const auto& blockIter : blocks) {
		const auto& block = blockIter.second;
		if (blocks.find(block.prevBlockHash) == blocks.end()) continue;

		parents[block.prevBlockHash] = true;
	}

	std::vector<Block> tips;
	for (const auto& blockIter : blocks) {
		const auto& block = blockIter.second;
		if (parents.find(block.hash) != parents.end()) continue;

		tips.emplace_back(block);
	}

	return tips;
}

auto determineWork(std::map<hash256_t, size_t>& workCache, const std::map<hash256_t, Block>& blocks, const Block source) {
	auto visitor = source;
	size_t totalWork = source.bits;

	// naively walk the chain
	while (true) {
		const auto prevBlockIter = blocks.find(visitor.prevBlockHash);
		if (prevBlockIter == blocks.end()) break;

		const auto prevBlockWorkCacheIter = workCache.find(visitor.prevBlockHash);
		if (prevBlockWorkCacheIter != workCache.end()) {
			totalWork += prevBlockWorkCacheIter->second;
			break;
		}

		visitor = prevBlockIter->second;
		totalWork += visitor.bits;
	}

	workCache.emplace(source.hash, totalWork);

	return totalWork;
}

auto findBest(const std::map<hash256_t, Block>& blocks) {
	auto bestBlock = Block();
	size_t mostWork = 0;

	std::map<hash256_t, size_t> workCache;

	for (const auto& blockIter : blocks) {
		const auto& block = blockIter.second;
		const auto work = determineWork(workCache, blocks, block);

		if (work > mostWork) {
			bestBlock = block;
			mostWork = work;
		}
	}

	auto visitor = bestBlock;
	std::vector<Block> blockchain;
	blockchain.push_back(visitor);

	// walk the chain
	while (true) {
		const auto prevBlockIter = blocks.find(visitor.prevBlockHash);
		if (prevBlockIter == blocks.end()) break;

		visitor = prevBlockIter->second;
		blockchain.push_back(visitor);
	}

	return blockchain;
}

int main () {
	std::map<hash256_t, Block> blocks;

	// read block headers from stdin until EOF
	{
		while (true) {
			uint8_t rbuf[80];
			const auto read = fread(rbuf, sizeof(rbuf), 1, stdin);

			// EOF?
			if (read == 0) break;

			hash256_t hash, prevBlockHash;
			uint32_t bits;

			hash256(&hash[0], rbuf, 80);
			memcpy(&prevBlockHash[0], rbuf + 4, 32);
			memcpy(&bits, rbuf + 72, 4);

			blocks[hash] = Block(hash, prevBlockHash, bits);
		}

		std::cerr << "Read " << blocks.size() << " headers" << std::endl;
	}

	// how many tips exist?
	{
		const auto chainTips = findChainTips(blocks);
		std::cerr << "Found " << chainTips.size() << " chain tips" << std::endl;
	}

	// what is the best?
	{
		const auto bestBlockChain = findBest(blocks);
		const auto genesis = bestBlockChain.back();
		const auto tip = bestBlockChain.front();

		// output
		std::cerr << "Best chain" << std::endl;
		std::cerr << "- Height: " << bestBlockChain.size() - 1 << std::endl;
		std::cerr << std::hex;
		std::cerr << "- Genesis: ";
		for (size_t i = 31; i < 32; --i) std::cerr << std::setw(2) << std::setfill('0') << (uint32_t) genesis.hash[i];
		std::cerr << std::endl << "- Tip: ";
		for (size_t i = 31; i < 32; --i) std::cerr << std::setw(2) << std::setfill('0') << (uint32_t) tip.hash[i];
		std::cerr << std::endl << std::dec;

		for (auto it = bestBlockChain.crbegin(); it != bestBlockChain.crend(); ++it) {
			fwrite(&it->hash[0], 32, 1, stdout);
		}
	}

	return 0;
}
<|endoftext|>