<commit_before>//
// Created by everettjf on 2017/7/23.
//

#include "LoadCommandsViewNode.h"

MOEX_NAMESPACE_BEGIN

void LoadCommandViewNode::Init(LoadCommandPtr d){
    d_ = d;

}

std::string LoadCommandViewNode::GetDisplayName(){
    std::string charact = d_->GetShortCharacteristicDescription();
    if(charact.length() > 0){
        return boost::str(boost::format("%1%(%2%)")%d_->GetLoadCommandTypeString()%charact);
    }else{
        return d_->GetLoadCommandTypeString();
    }
}

// --------------------------------------------------------------
void LoadCommandsViewNode::Init(MachHeaderPtr mh){
    mh_ = mh;

    for(auto & cmd : mh_->loadcmds_ref()){
        LoadCommandViewNodePtr o = std::make_shared<LoadCommandViewNode>();
        o->Init(cmd);
        cmds_.push_back(o);
    }
}

void LoadCommandsViewNode::ForEachChild(std::function<void(ViewNode*)> callback){
    for(auto & cmd : cmds_){
        callback(cmd.get());
    }
}
void LoadCommandsViewNode::InitViewDatas(){

    // Binary
    {
        BinaryViewDataPtr b = std::make_shared<BinaryViewData>();
        b->offset = (char*)mh_->header_start() + mh_->DATA_SIZE();
        b->size = mh_->data_ptr()->sizeofcmds;
        AddViewData(b);
    }
}

MOEX_NAMESPACE_END<commit_msg>cmd count<commit_after>//
// Created by everettjf on 2017/7/23.
//

#include "LoadCommandsViewNode.h"

MOEX_NAMESPACE_BEGIN

void LoadCommandViewNode::Init(LoadCommandPtr d){
    d_ = d;

}

std::string LoadCommandViewNode::GetDisplayName(){
    std::string charact = d_->GetShortCharacteristicDescription();
    if(charact.length() > 0){
        return boost::str(boost::format("%1%(%2%)")%d_->GetLoadCommandTypeString()%charact);
    }else{
        return d_->GetLoadCommandTypeString();
    }
}

// --------------------------------------------------------------
void LoadCommandsViewNode::Init(MachHeaderPtr mh){
    mh_ = mh;

    for(auto & cmd : mh_->loadcmds_ref()){
        LoadCommandViewNodePtr o = std::make_shared<LoadCommandViewNode>();
        o->Init(cmd);
        cmds_.push_back(o);
    }
}

void LoadCommandsViewNode::ForEachChild(std::function<void(ViewNode*)> callback){
    for(auto & cmd : cmds_){
        callback(cmd.get());
    }
}
void LoadCommandsViewNode::InitViewDatas(){

    using namespace moex::util;

    // Table
    {
        TableViewDataPtr  t = std::make_shared<TableViewData>();
        t->AddRow("","","Number of commands",AsString(cmds_.size()));
        AddViewData(t);
    }
    // Binary
    {
        BinaryViewDataPtr b = std::make_shared<BinaryViewData>();
        b->offset = (char*)mh_->header_start() + mh_->DATA_SIZE();
        b->size = mh_->data_ptr()->sizeofcmds;
        AddViewData(b);
    }
}

MOEX_NAMESPACE_END<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libfreehand project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <sstream>
#include <string>
#include <string.h>
#include <libfreehand/libfreehand.h>
#include "FHParser.h"
#include "libfreehand_utils.h"

namespace
{

using namespace libfreehand;

bool findAGD(librevenge::RVNGInputStream *input)
{
  unsigned agd = readU32(input);
  input->seek(-4, librevenge::RVNG_SEEK_CUR);
  if (((agd >> 24) & 0xff) == 'A' && ((agd >> 16) & 0xff) == 'G' && ((agd >> 8) & 0xff) == 'D')
  {
    FH_DEBUG_MSG(("Found AGD at offset 0x%lx (FreeHand version %i)\n", input->tell(), (agd & 0xff) - 0x30 + 5));
    return true;
  }
  else if (((agd >> 24) & 0xff) == 'F' && ((agd >> 16) & 0xff) == 'H' && ((agd >> 8) & 0xff) == '3')
  {
    FH_DEBUG_MSG(("Found FH3 at offset 0x%lx (FreeHand version %c.%c)\n", input->tell(), (agd >> 8) & 0xff, agd & 0xff));
    return true;
  }
  else
  {
    // parse the document for AGD block
    while (!input->isEnd())
    {
      if (0x1c != readU8(input))
        return false;
      unsigned short opcode = readU16(input);
      unsigned char flag = readU8(input);
      unsigned length = readU8(input);
      if (0x80 == flag)
      {
        if (4 != length)
          return false;
        length = readU32(input);
        if (0x080a == opcode)
        {
          agd = readU32(input);
          input->seek(-4, librevenge::RVNG_SEEK_CUR);
          if (((agd >> 24) & 0xff) == 'A' && ((agd >> 16) & 0xff) == 'G' && ((agd >> 8) & 0xff) == 'D')
          {
            FH_DEBUG_MSG(("Found AGD at offset 0x%lx (FreeHand version %i)\n", input->tell(), (agd & 0xff) - 0x30 + 5));
            return true;
          }
        }
      }
      input->seek(length, librevenge::RVNG_SEEK_CUR);
    }
  }
  return false;
}

} // anonymous namespace

/**
Analyzes the content of an input stream to see if it can be parsed
\param input The input stream
\return A value that indicates whether the content from the input
stream is a FreeHand Document that libfreehand is able to parse
*/
FHAPI bool libfreehand::FreeHandDocument::isSupported(librevenge::RVNGInputStream *input)
{
  if (!input)
    return false;

  try
  {
    input->seek(0, librevenge::RVNG_SEEK_SET);
    if (findAGD(input))
    {
      input->seek(0, librevenge::RVNG_SEEK_SET);
      return true;
    }
  }
  catch (...)
  {
  }
  return false;

}

/**
Parses the input stream content. It will make callbacks to the functions provided by a
librevenge::RVNGDrawingInterface class implementation when needed. This is often commonly called the
'main parsing routine'.
\param input The input stream
\param painter A librevenge::RVNGDrawingerInterface implementation
\return A value that indicates whether the parsing was successful
*/
FHAPI bool libfreehand::FreeHandDocument::parse(librevenge::RVNGInputStream *input, librevenge::RVNGDrawingInterface *painter)
{
  if (!input)
    return false;

  try
  {
    input->seek(0, librevenge::RVNG_SEEK_SET);
    if (findAGD(input))
    {
      FHParser parser;
      if (!parser.parse(input, painter))
        return false;
    }
    else
      return false;
    return true;
  }
  catch (...)
  {
  }
  return false;
}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<commit_msg>move everything into namespace<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libfreehand project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <sstream>
#include <string>
#include <string.h>
#include <libfreehand/libfreehand.h>
#include "FHParser.h"
#include "libfreehand_utils.h"

namespace libfreehand
{

namespace
{

bool findAGD(librevenge::RVNGInputStream *input)
{
  unsigned agd = readU32(input);
  input->seek(-4, librevenge::RVNG_SEEK_CUR);
  if (((agd >> 24) & 0xff) == 'A' && ((agd >> 16) & 0xff) == 'G' && ((agd >> 8) & 0xff) == 'D')
  {
    FH_DEBUG_MSG(("Found AGD at offset 0x%lx (FreeHand version %i)\n", input->tell(), (agd & 0xff) - 0x30 + 5));
    return true;
  }
  else if (((agd >> 24) & 0xff) == 'F' && ((agd >> 16) & 0xff) == 'H' && ((agd >> 8) & 0xff) == '3')
  {
    FH_DEBUG_MSG(("Found FH3 at offset 0x%lx (FreeHand version %c.%c)\n", input->tell(), (agd >> 8) & 0xff, agd & 0xff));
    return true;
  }
  else
  {
    // parse the document for AGD block
    while (!input->isEnd())
    {
      if (0x1c != readU8(input))
        return false;
      unsigned short opcode = readU16(input);
      unsigned char flag = readU8(input);
      unsigned length = readU8(input);
      if (0x80 == flag)
      {
        if (4 != length)
          return false;
        length = readU32(input);
        if (0x080a == opcode)
        {
          agd = readU32(input);
          input->seek(-4, librevenge::RVNG_SEEK_CUR);
          if (((agd >> 24) & 0xff) == 'A' && ((agd >> 16) & 0xff) == 'G' && ((agd >> 8) & 0xff) == 'D')
          {
            FH_DEBUG_MSG(("Found AGD at offset 0x%lx (FreeHand version %i)\n", input->tell(), (agd & 0xff) - 0x30 + 5));
            return true;
          }
        }
      }
      input->seek(length, librevenge::RVNG_SEEK_CUR);
    }
  }
  return false;
}

} // anonymous namespace

/**
Analyzes the content of an input stream to see if it can be parsed
\param input The input stream
\return A value that indicates whether the content from the input
stream is a FreeHand Document that libfreehand is able to parse
*/
FHAPI bool FreeHandDocument::isSupported(librevenge::RVNGInputStream *input)
{
  if (!input)
    return false;

  try
  {
    input->seek(0, librevenge::RVNG_SEEK_SET);
    if (findAGD(input))
    {
      input->seek(0, librevenge::RVNG_SEEK_SET);
      return true;
    }
  }
  catch (...)
  {
  }
  return false;

}

/**
Parses the input stream content. It will make callbacks to the functions provided by a
librevenge::RVNGDrawingInterface class implementation when needed. This is often commonly called the
'main parsing routine'.
\param input The input stream
\param painter A librevenge::RVNGDrawingerInterface implementation
\return A value that indicates whether the parsing was successful
*/
FHAPI bool FreeHandDocument::parse(librevenge::RVNGInputStream *input, librevenge::RVNGDrawingInterface *painter)
{
  if (!input)
    return false;

  try
  {
    input->seek(0, librevenge::RVNG_SEEK_SET);
    if (findAGD(input))
    {
      FHParser parser;
      if (!parser.parse(input, painter))
        return false;
    }
    else
      return false;
    return true;
  }
  catch (...)
  {
  }
  return false;
}

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <boost/scoped_array.hpp>
#include <boost/scoped_ptr.hpp>
#include <cppunit/TestFixture.h>
#include <cppunit/plugin/TestPlugIn.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cstdlib>
#include <string>
#include <stdio.h>

#include <osl/file.hxx>
#include <rtl/bootstrap.hxx>

#include <config_options.h>
    // see use of ENABLE_RUNTIME_OPTIMIZATIONS in LibreOfficeKintInit.h
#define LOK_USE_UNSTABLE_API
#include <LibreOfficeKit/LibreOfficeKitInit.h>
#include <LibreOfficeKit/LibreOfficeKit.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>

using namespace ::boost;
using namespace ::lok;
using namespace ::std;

OUString getFileURLFromSystemPath(OUString const & path)
{
    OUString url;
    osl::FileBase::RC e = osl::FileBase::getFileURLFromSystemPath(path, url);
    CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
    if (!url.endsWith("/"))
        url += "/";
    return url;
}

// We specifically don't use the usual BootStrapFixture, as LOK does
// all it's own setup and bootstrapping, and should be useable in a
// raw C++ program.
class TiledRenderingTest : public ::CppUnit::TestFixture
{
public:
    const string m_sSrcRoot;
    const string m_sInstDir;
    const string m_sLOPath;

    TiledRenderingTest()
        : m_sSrcRoot( getenv( "SRC_ROOT" ) )
        , m_sInstDir( getenv( "INSTDIR" ) )
        , m_sLOPath( m_sInstDir + "/program" )
    {
    }

    // Currently it isn't possible to do multiple startup/shutdown
    // cycle of LOK in a single process -- hence we run all our tests
    // as one test, which simply carries out the individual test
    // components on the one Office instance that we retrieve.
    void runAllTests();

    void testDocumentLoadFail( Office* pOffice );
    void testDocumentTypes( Office* pOffice );
#if 0
    void testImpressSlideNames( Office* pOffice );
    void testOverlay( Office* pOffice );
#endif

    CPPUNIT_TEST_SUITE(TiledRenderingTest);
    CPPUNIT_TEST(runAllTests);
    CPPUNIT_TEST_SUITE_END();
};

void TiledRenderingTest::runAllTests()
{
    // set UserInstallation to user profile dir in test/user-template
    const char* pWorkdirRoot = getenv("WORKDIR_FOR_BUILD");
    OUString aWorkdirRootPath = OUString::createFromAscii(pWorkdirRoot);
    OUString aWorkdirRootURL = getFileURLFromSystemPath(aWorkdirRootPath);
    OUString sUserInstallURL = aWorkdirRootURL + "/unittest";
    rtl::Bootstrap::set(OUString("UserInstallation"), sUserInstallURL);

    scoped_ptr< Office > pOffice( lok_cpp_init(
                                      m_sLOPath.c_str() ) );
    CPPUNIT_ASSERT( pOffice.get() );

    testDocumentLoadFail( pOffice.get() );
    testDocumentTypes( pOffice.get() );
#if 0
    testImpressSlideNames( pOffice.get() );
    testOverlay( pOffice.get() );
#endif
}

void TiledRenderingTest::testDocumentLoadFail( Office* pOffice )
{
    const string sDocPath = m_sSrcRoot + "/libreofficekit/qa/data/IDONOTEXIST.odt";
    scoped_ptr< Document> pDocument( pOffice->documentLoad( sDocPath.c_str() ) );
    CPPUNIT_ASSERT( !pDocument.get() );
    // TODO: we probably want to have some way of returning what
    // the cause of failure was. getError() will return
    // something along the lines of:
    // "Unsupported URL <file:///SRC_ROOT/libreofficekit/qa/data/IDONOTEXIST.odt>: "type detection failed""
}

// Our dumped .png files end up in
// workdir/CppunitTest/libreofficekit_tiledrendering.test.core

int getDocumentType( Office* pOffice, const string& rPath )
{
    scoped_ptr< Document> pDocument( pOffice->documentLoad( rPath.c_str() ) );
    CPPUNIT_ASSERT( pDocument.get() );
    return pDocument->getDocumentType();
}

void TiledRenderingTest::testDocumentTypes( Office* pOffice )
{
    const string sTextDocPath = m_sSrcRoot + "/libreofficekit/qa/data/blank_text.odt";
    const string sTextLockFile = m_sSrcRoot +"/libreofficekit/qa/data/.~lock.blank_text.odt#";

    // FIXME: same comment as below wrt lockfile removal.
    remove( sTextLockFile.c_str() );

    CPPUNIT_ASSERT( getDocumentType( pOffice, sTextDocPath ) == LOK_DOCTYPE_TEXT );

    const string sPresentationDocPath = m_sSrcRoot + "/libreofficekit/qa/data/blank_presentation.odp";
    const string sPresentationLockFile = m_sSrcRoot +"/libreofficekit/qa/data/.~lock.blank_presentation.odp#";

    // FIXME: same comment as below wrt lockfile removal.
    remove( sPresentationLockFile.c_str() );

    CPPUNIT_ASSERT( getDocumentType( pOffice, sPresentationDocPath ) == LOK_DOCTYPE_PRESENTATION );

    // TODO: do this for all supported document types
}

#if 0
void TiledRenderingTest::testImpressSlideNames( Office* pOffice )
{
    const string sDocPath = m_sSrcRoot + "/libreofficekit/qa/data/impress_slidenames.odp";
    const string sLockFile = m_sSrcRoot +"/libreofficekit/qa/data/.~lock.impress_slidenames.odp#";

    // FIXME: this is a temporary hack: LOK will fail when trying to open a
    // locked file, and since we're reusing the file for a different unit
    // test it's entirely possible that an unwanted lock file will remain.
    // Hence forcefully remove it here.
    remove( sLockFile.c_str() );

    scoped_ptr< Document> pDocument( pOffice->documentLoad( sDocPath.c_str() ) );

    CPPUNIT_ASSERT( pDocument->getParts() == 3 );
    CPPUNIT_ASSERT( strcmp( pDocument->getPartName( 0 ), "TestText1" ) == 0 );
    CPPUNIT_ASSERT( strcmp( pDocument->getPartName( 1 ), "TestText2" ) == 0 );
    // The third slide hasn't had a name given to it (i.e. using the rename
    // context menu in Impress), thus it should (as far as I can determine)
    // have a localised version of "Slide 3".
}

static void dumpRGBABitmap( const OUString& rPath, const unsigned char* pBuffer,
                            const int nWidth, const int nHeight )
{
    Bitmap aBitmap( Size( nWidth, nHeight ), 32 );
    Bitmap::ScopedWriteAccess pWriteAccess( aBitmap );
    memcpy( pWriteAccess->GetBuffer(), pBuffer, 4*nWidth*nHeight );

    BitmapEx aBitmapEx( aBitmap );
    vcl::PNGWriter aWriter( aBitmapEx );
    SvFileStream sOutput( rPath, StreamMode::WRITE );
    aWriter.Write( sOutput );
    sOutput.Close();
}

void TiledRenderingTest::testOverlay( Office* /*pOffice*/ )
{
    const string sDocPath = m_sSrcRoot + "/odk/examples/java/DocumentHandling/test/test1.odt";
    const string sLockFile = m_sSrcRoot + "/odk/examples/java/DocumentHandling/test/.~lock.test1.odt#";

    // FIXME: this is a temporary hack: LOK will fail when trying to open a
    // locked file, and since we're reusing the file for a different unit
    // test it's entirely possible that an unwanted lock file will remain.
    // Hence forcefully remove it here.
    remove( sLockFile.c_str() );
    scoped_ptr< Office > pOffice( lok_cpp_init(
                                      m_sLOPath.c_str() ) );
    assert( pOffice.get() );

    scoped_ptr< Document> pDocument( pOffice->documentLoad(
                                         sDocPath.c_str() ) );

    if ( !pDocument.get() )
    {
        fprintf( stderr, "documentLoad failed: %s\n", pOffice->getError() );
        CPPUNIT_FAIL( "Document could not be loaded -- tiled rendering not possible." );
    }

    // We render one large tile, then subdivide it into 4 and render those parts, and finally
    // iterate over each smaller tile and check whether their contents match the large
    // tile.
    const int nTotalWidthPix = 512;
    const int nTotalHeightPix = 512;
    int nRowStride;

    long nTotalWidthDoc;
    long nTotalHeightDoc;
    // pDocument->getDocumentSize( &nTotalWidthDoc, &nTotalHeightDoc );
    // TODO: make sure we select an actually interesting part of the document
    // for this comparison, i.e. ideally an image and lots of text, in order
    // to test as many edge cases as possible.
    // Alternatively we could rewrite this to actually grab the document size
    // and iterate over it (subdividing into an arbitrary number of tiles rather
    // than our less sophisticated test of just 4 sub-tiles).
    nTotalWidthDoc = 8000;
    nTotalHeightDoc = 9000;

    scoped_array< unsigned char > pLarge( new unsigned char[ 4*nTotalWidthPix*nTotalHeightPix ] );
    pDocument->paintTile( pLarge.get(),  nTotalWidthPix, nTotalHeightPix, &nRowStride,
                          0, 0,
                          nTotalWidthDoc, nTotalHeightDoc );
    dumpRGBABitmap( "large.png", pLarge.get(), nTotalWidthPix, nTotalHeightPix );

    scoped_array< unsigned char > pSmall[4];
    for ( int i = 0; i < 4; i++ )
    {
        pSmall[i].reset( new unsigned char[ 4*(nTotalWidthPix/2)*(nTotalHeightPix/2) ] );
        pDocument->paintTile( pSmall[i].get(),  nTotalWidthPix / 2, nTotalHeightPix / 2, &nRowStride,
                              // Tile 0/2: left. Tile 1/3: right. Tile 0/1: top. Tile 2/3: bottom
                              ((i%2 == 0) ?  0 : nTotalWidthDoc / 2), ((i < 2 ) ? 0 : nTotalHeightDoc / 2),
                              nTotalWidthDoc / 2, nTotalHeightDoc / 2);
        dumpRGBABitmap( "small_" + OUString::number(i) + ".png",
                        pSmall[i].get(), nTotalWidthPix/2, nTotalHeightPix/2 );
    }

    // Iterate over each pixel of the sub-tile, and compare that pixel for every
    // tile with the equivalent super-tile pixel.
    for ( int i = 0; i < 4*nTotalWidthPix / 2 * nTotalHeightPix / 2; i++ )
    {
        int xSmall = i % (4*nTotalWidthPix/2);
        int ySmall = i / (4*nTotalWidthPix/2);
        // Iterate over our array of tiles
        // However for now we only bother with the top-left
        // tile as the other ones don't match yet...
        for ( int x = 0; x < 2; x++ )
        {
            for ( int y = 0; y < 2; y++ )
            {
                int xLarge = (x * (4 * nTotalWidthPix / 2)) + xSmall;
                int yLarge = (y * (nTotalHeightPix / 2)) + ySmall;
                CPPUNIT_ASSERT( pSmall[2*y+x][i] == pLarge[yLarge*4*nTotalWidthPix + xLarge] );
            }
        }
    }
}
#endif

CPPUNIT_TEST_SUITE_REGISTRATION(TiledRenderingTest);

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>CppunitTest_libreofficekit_tiledrendering: add postUnoCommand() testcase<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <boost/scoped_array.hpp>
#include <boost/scoped_ptr.hpp>
#include <cppunit/TestFixture.h>
#include <cppunit/plugin/TestPlugIn.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cstdlib>
#include <string>
#include <stdio.h>

#include <osl/file.hxx>
#include <rtl/bootstrap.hxx>

#include <config_options.h>
    // see use of ENABLE_RUNTIME_OPTIMIZATIONS in LibreOfficeKintInit.h
#define LOK_USE_UNSTABLE_API
#include <LibreOfficeKit/LibreOfficeKitInit.h>
#include <LibreOfficeKit/LibreOfficeKit.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>

using namespace ::boost;
using namespace ::lok;
using namespace ::std;

OUString getFileURLFromSystemPath(OUString const & path)
{
    OUString url;
    osl::FileBase::RC e = osl::FileBase::getFileURLFromSystemPath(path, url);
    CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
    if (!url.endsWith("/"))
        url += "/";
    return url;
}

// We specifically don't use the usual BootStrapFixture, as LOK does
// all it's own setup and bootstrapping, and should be useable in a
// raw C++ program.
class TiledRenderingTest : public ::CppUnit::TestFixture
{
public:
    const string m_sSrcRoot;
    const string m_sInstDir;
    const string m_sLOPath;

    TiledRenderingTest()
        : m_sSrcRoot( getenv( "SRC_ROOT" ) )
        , m_sInstDir( getenv( "INSTDIR" ) )
        , m_sLOPath( m_sInstDir + "/program" )
    {
    }

    // Currently it isn't possible to do multiple startup/shutdown
    // cycle of LOK in a single process -- hence we run all our tests
    // as one test, which simply carries out the individual test
    // components on the one Office instance that we retrieve.
    void runAllTests();

    void testDocumentLoadFail( Office* pOffice );
    void testDocumentTypes( Office* pOffice );
#if 0
    void testImpressSlideNames( Office* pOffice );
    void testOverlay( Office* pOffice );
#endif

    CPPUNIT_TEST_SUITE(TiledRenderingTest);
    CPPUNIT_TEST(runAllTests);
    CPPUNIT_TEST_SUITE_END();
};

void TiledRenderingTest::runAllTests()
{
    // set UserInstallation to user profile dir in test/user-template
    const char* pWorkdirRoot = getenv("WORKDIR_FOR_BUILD");
    OUString aWorkdirRootPath = OUString::createFromAscii(pWorkdirRoot);
    OUString aWorkdirRootURL = getFileURLFromSystemPath(aWorkdirRootPath);
    OUString sUserInstallURL = aWorkdirRootURL + "/unittest";
    rtl::Bootstrap::set(OUString("UserInstallation"), sUserInstallURL);

    scoped_ptr< Office > pOffice( lok_cpp_init(
                                      m_sLOPath.c_str() ) );
    CPPUNIT_ASSERT( pOffice.get() );

    testDocumentLoadFail( pOffice.get() );
    testDocumentTypes( pOffice.get() );
#if 0
    testImpressSlideNames( pOffice.get() );
    testOverlay( pOffice.get() );
#endif
}

void TiledRenderingTest::testDocumentLoadFail( Office* pOffice )
{
    const string sDocPath = m_sSrcRoot + "/libreofficekit/qa/data/IDONOTEXIST.odt";
    scoped_ptr< Document> pDocument( pOffice->documentLoad( sDocPath.c_str() ) );
    CPPUNIT_ASSERT( !pDocument.get() );
    // TODO: we probably want to have some way of returning what
    // the cause of failure was. getError() will return
    // something along the lines of:
    // "Unsupported URL <file:///SRC_ROOT/libreofficekit/qa/data/IDONOTEXIST.odt>: "type detection failed""
}

// Our dumped .png files end up in
// workdir/CppunitTest/libreofficekit_tiledrendering.test.core

int getDocumentType( Office* pOffice, const string& rPath )
{
    scoped_ptr< Document> pDocument( pOffice->documentLoad( rPath.c_str() ) );
    CPPUNIT_ASSERT( pDocument.get() );
    return pDocument->getDocumentType();
}

void TiledRenderingTest::testDocumentTypes( Office* pOffice )
{
    const string sTextDocPath = m_sSrcRoot + "/libreofficekit/qa/data/blank_text.odt";
    const string sTextLockFile = m_sSrcRoot +"/libreofficekit/qa/data/.~lock.blank_text.odt#";

    // FIXME: same comment as below wrt lockfile removal.
    remove( sTextLockFile.c_str() );

    std::unique_ptr<Document> pDocument(pOffice->documentLoad( sTextDocPath.c_str()));
    CPPUNIT_ASSERT(pDocument.get());
    CPPUNIT_ASSERT_EQUAL(LOK_DOCTYPE_TEXT, static_cast<LibreOfficeKitDocumentType>(pDocument->getDocumentType()));
    // This crashed.
    pDocument->postUnoCommand(".uno:Bold");

    const string sPresentationDocPath = m_sSrcRoot + "/libreofficekit/qa/data/blank_presentation.odp";
    const string sPresentationLockFile = m_sSrcRoot +"/libreofficekit/qa/data/.~lock.blank_presentation.odp#";

    // FIXME: same comment as below wrt lockfile removal.
    remove( sPresentationLockFile.c_str() );

    CPPUNIT_ASSERT( getDocumentType( pOffice, sPresentationDocPath ) == LOK_DOCTYPE_PRESENTATION );

    // TODO: do this for all supported document types
}

#if 0
void TiledRenderingTest::testImpressSlideNames( Office* pOffice )
{
    const string sDocPath = m_sSrcRoot + "/libreofficekit/qa/data/impress_slidenames.odp";
    const string sLockFile = m_sSrcRoot +"/libreofficekit/qa/data/.~lock.impress_slidenames.odp#";

    // FIXME: this is a temporary hack: LOK will fail when trying to open a
    // locked file, and since we're reusing the file for a different unit
    // test it's entirely possible that an unwanted lock file will remain.
    // Hence forcefully remove it here.
    remove( sLockFile.c_str() );

    scoped_ptr< Document> pDocument( pOffice->documentLoad( sDocPath.c_str() ) );

    CPPUNIT_ASSERT( pDocument->getParts() == 3 );
    CPPUNIT_ASSERT( strcmp( pDocument->getPartName( 0 ), "TestText1" ) == 0 );
    CPPUNIT_ASSERT( strcmp( pDocument->getPartName( 1 ), "TestText2" ) == 0 );
    // The third slide hasn't had a name given to it (i.e. using the rename
    // context menu in Impress), thus it should (as far as I can determine)
    // have a localised version of "Slide 3".
}

static void dumpRGBABitmap( const OUString& rPath, const unsigned char* pBuffer,
                            const int nWidth, const int nHeight )
{
    Bitmap aBitmap( Size( nWidth, nHeight ), 32 );
    Bitmap::ScopedWriteAccess pWriteAccess( aBitmap );
    memcpy( pWriteAccess->GetBuffer(), pBuffer, 4*nWidth*nHeight );

    BitmapEx aBitmapEx( aBitmap );
    vcl::PNGWriter aWriter( aBitmapEx );
    SvFileStream sOutput( rPath, StreamMode::WRITE );
    aWriter.Write( sOutput );
    sOutput.Close();
}

void TiledRenderingTest::testOverlay( Office* /*pOffice*/ )
{
    const string sDocPath = m_sSrcRoot + "/odk/examples/java/DocumentHandling/test/test1.odt";
    const string sLockFile = m_sSrcRoot + "/odk/examples/java/DocumentHandling/test/.~lock.test1.odt#";

    // FIXME: this is a temporary hack: LOK will fail when trying to open a
    // locked file, and since we're reusing the file for a different unit
    // test it's entirely possible that an unwanted lock file will remain.
    // Hence forcefully remove it here.
    remove( sLockFile.c_str() );
    scoped_ptr< Office > pOffice( lok_cpp_init(
                                      m_sLOPath.c_str() ) );
    assert( pOffice.get() );

    scoped_ptr< Document> pDocument( pOffice->documentLoad(
                                         sDocPath.c_str() ) );

    if ( !pDocument.get() )
    {
        fprintf( stderr, "documentLoad failed: %s\n", pOffice->getError() );
        CPPUNIT_FAIL( "Document could not be loaded -- tiled rendering not possible." );
    }

    // We render one large tile, then subdivide it into 4 and render those parts, and finally
    // iterate over each smaller tile and check whether their contents match the large
    // tile.
    const int nTotalWidthPix = 512;
    const int nTotalHeightPix = 512;
    int nRowStride;

    long nTotalWidthDoc;
    long nTotalHeightDoc;
    // pDocument->getDocumentSize( &nTotalWidthDoc, &nTotalHeightDoc );
    // TODO: make sure we select an actually interesting part of the document
    // for this comparison, i.e. ideally an image and lots of text, in order
    // to test as many edge cases as possible.
    // Alternatively we could rewrite this to actually grab the document size
    // and iterate over it (subdividing into an arbitrary number of tiles rather
    // than our less sophisticated test of just 4 sub-tiles).
    nTotalWidthDoc = 8000;
    nTotalHeightDoc = 9000;

    scoped_array< unsigned char > pLarge( new unsigned char[ 4*nTotalWidthPix*nTotalHeightPix ] );
    pDocument->paintTile( pLarge.get(),  nTotalWidthPix, nTotalHeightPix, &nRowStride,
                          0, 0,
                          nTotalWidthDoc, nTotalHeightDoc );
    dumpRGBABitmap( "large.png", pLarge.get(), nTotalWidthPix, nTotalHeightPix );

    scoped_array< unsigned char > pSmall[4];
    for ( int i = 0; i < 4; i++ )
    {
        pSmall[i].reset( new unsigned char[ 4*(nTotalWidthPix/2)*(nTotalHeightPix/2) ] );
        pDocument->paintTile( pSmall[i].get(),  nTotalWidthPix / 2, nTotalHeightPix / 2, &nRowStride,
                              // Tile 0/2: left. Tile 1/3: right. Tile 0/1: top. Tile 2/3: bottom
                              ((i%2 == 0) ?  0 : nTotalWidthDoc / 2), ((i < 2 ) ? 0 : nTotalHeightDoc / 2),
                              nTotalWidthDoc / 2, nTotalHeightDoc / 2);
        dumpRGBABitmap( "small_" + OUString::number(i) + ".png",
                        pSmall[i].get(), nTotalWidthPix/2, nTotalHeightPix/2 );
    }

    // Iterate over each pixel of the sub-tile, and compare that pixel for every
    // tile with the equivalent super-tile pixel.
    for ( int i = 0; i < 4*nTotalWidthPix / 2 * nTotalHeightPix / 2; i++ )
    {
        int xSmall = i % (4*nTotalWidthPix/2);
        int ySmall = i / (4*nTotalWidthPix/2);
        // Iterate over our array of tiles
        // However for now we only bother with the top-left
        // tile as the other ones don't match yet...
        for ( int x = 0; x < 2; x++ )
        {
            for ( int y = 0; y < 2; y++ )
            {
                int xLarge = (x * (4 * nTotalWidthPix / 2)) + xSmall;
                int yLarge = (y * (nTotalHeightPix / 2)) + ySmall;
                CPPUNIT_ASSERT( pSmall[2*y+x][i] == pLarge[yLarge*4*nTotalWidthPix + xLarge] );
            }
        }
    }
}
#endif

CPPUNIT_TEST_SUITE_REGISTRATION(TiledRenderingTest);

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2013-2015 University of Hull                                                     */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  scene/loader/mtl.hpp                                                            */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

#if !defined(UKACHULLDCS_SCENE_LOADER_MTL_HPP)

#define UKACHULLDCS_SCENE_LOADER_MTL_HPP

// includes, system

#include <boost/intrusive_ptr.hpp> // boost::intrusive_ptr<>
#include <iosfwd>                  // std::istream, std::ostream (fwd decl)
#include <string>                  // std::string
#include <vector>                  // std::vector<>

// includes, project

#include <scene/object/material.hpp>

namespace scene {

  namespace file {

    namespace mtl {

      // types, exported (class, enum, struct, union, typedef)

      using list_type = std::vector<boost::intrusive_ptr<object::material>>;

      // variables, exported (extern)

      // functions, inlined (inline)

      // functions, exported (extern)

      list_type load(std::istream&);
      list_type load(std::string const&);
      bool      save(std::ostream&,      list_type const&);
      bool      save(std::string const&, list_type const&);

    } // namespace mtl {

  } // namespace file {

} // namespace scene {

#endif // #if !defined(UKACHULLDCS_SCENE_LOADER_MTL_HPP)
<commit_msg>update: include guards<commit_after>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2013-2015 University of Hull                                                     */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  scene/loader/mtl.hpp                                                            */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

#if !defined(UKACHULLDCS_08961_SCENE_LOADER_MTL_HPP)

#define UKACHULLDCS_08961_SCENE_LOADER_MTL_HPP

// includes, system

#include <boost/intrusive_ptr.hpp> // boost::intrusive_ptr<>
#include <iosfwd>                  // std::istream, std::ostream (fwd decl)
#include <string>                  // std::string
#include <vector>                  // std::vector<>

// includes, project

#include <scene/object/material.hpp>

namespace scene {

  namespace file {

    namespace mtl {

      // types, exported (class, enum, struct, union, typedef)

      using list_type = std::vector<boost::intrusive_ptr<object::material>>;

      // variables, exported (extern)

      // functions, inlined (inline)

      // functions, exported (extern)

      list_type load(std::istream&);
      list_type load(std::string const&);
      bool      save(std::ostream&,      list_type const&);
      bool      save(std::string const&, list_type const&);

    } // namespace mtl {

  } // namespace file {

} // namespace scene {

#endif // #if !defined(UKACHULLDCS_08961_SCENE_LOADER_MTL_HPP)
<|endoftext|>


<commit_before>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <votca/csg/csgapplication.h>
#include <votca/csg/trajectorywriter.h>
#include <votca/csg/trajectoryreader.h>
#include <votca/csg/topologyreader.h>
#include <votca/csg/topologymap.h>
#include <votca/csg/cgengine.h>
#include <votca/csg/version.h>
#include <boost/algorithm/string/trim.hpp>

namespace votca {
    namespace csg {

        CsgApplication::CsgApplication(void) {
        }

        CsgApplication::~CsgApplication(void) {
        }

        void CsgApplication::Initialize(void) {
            // register all io plugins
            TrajectoryWriter::RegisterPlugins();
            TrajectoryReader::RegisterPlugins();
            TopologyReader::RegisterPlugins();

            AddProgramOptions()
                    ("top", boost::program_options::value<string > (), "  atomistic topology file");
            if (DoMapping()) {
                if (DoMappingDefault()) {
                    AddProgramOptions("Mapping options")
                            ("cg", boost::program_options::value<string > (), "  coarse graining mapping definitions (xml-file)")
                            ("map-ignore", boost::program_options::value<string >(), "  list of molecules to ignore separated by ;")
                            ("no-map", "  disable mapping and act on original trajectory");
                } else {
                    AddProgramOptions("Mapping options")
                            ("cg", boost::program_options::value<string > (), "  [OPTIONAL] coarse graining mapping definitions\n"
                            "  (xml-file). If no file is given, program acts on original trajectory");
                }
            }

            if (DoTrajectory())
                AddProgramOptions("Trajectory options")
                ("trj", boost::program_options::value<string > (), "  atomistic trajectory file")
                ("begin", boost::program_options::value<double>()->default_value(0.0), "  skip frames before this time")
                ("first-frame", boost::program_options::value<int>()->default_value(0), "  start with this frame")
                ("nframes", boost::program_options::value<int>(), "  process the given number of frames")
                ;

            if (DoThreaded())
                /*
                 * TODO default value of 1 for nt is not smart
                 */
                AddProgramOptions("Threading options")
                ("nt", boost::program_options::value<int>()->default_value(1), "  number of threads")
                ;

        }

        bool CsgApplication::EvaluateOptions(void) {
            _do_mapping = false;
            CheckRequired("top", "no topology file specified");

            // check for mapping options
            if (DoMapping()) {
                // default mapping is on
                if (DoMappingDefault()) {
                    // if the user does not explicitly ask to turn it off, cg is needed
                    if (OptionsMap().count("no-map") == 0) {
                        CheckRequired("cg", "no coarse graining definition specified");
                        _do_mapping = true;
                    }
                }// default mapping is off, if user gives cg, then do mapping
                else if (OptionsMap().count("cg")) {
                    _do_mapping = true;
                }
            }

            /* check threading options */
            if (DoThreaded()) {
                _nthreads = _op_vm["nt"].as<int > ();
                /* TODO
                 * does the number of threads make sense?
                 * which criteria should be used? smaller than system's cores?
                 */
            }

            return true;
        }

        void CsgApplication::ShowHelpText(std::ostream &out) {
            string name = ProgramName();
            if (VersionString() != "")
                name = name + ", version " + VersionString();

            HelpTextHeader(name);
            HelpText(out);
            out << "\n\n" << OptionsDesc() << endl;
        }

        void CsgApplication::Worker::Run(void) {
            while (_app->ProcessData(this)) {
                if (_app->SynchronizeThreads()) {
                    int id = getId();
                    _app->_threadsMutexesOut[id]->Lock();
                    _app->MergeWorker(this);
                    _app->_threadsMutexesOut[(id + 1) % _app->_nthreads]->Unlock();
                }
            }
        }

        bool CsgApplication::ProcessData(Worker * worker) {

            int id;
            id = worker->getId();

            if (SynchronizeThreads()) {
                //wait til its your turn
                _threadsMutexesIn[id]->Lock();
            }
            _traj_readerMutex.Lock();
            if (_nframes == 0) {
                _traj_readerMutex.Unlock();

                if (SynchronizeThreads()) {
                    //done processing? don't forget to unlock next worker anyway
                    _threadsMutexesIn[(id + 1) % _nthreads]->Unlock();
                }

                return false;
            }
            _nframes--;
            if (!_is_first_frame || worker->getId() != 0) {
                //get frame
                bool tmpRes = _traj_reader->NextFrame(worker->_top);
                if (!tmpRes) {
                    _traj_readerMutex.Unlock();
                    if (SynchronizeThreads())
                        _threadsMutexesIn[(id + 1) % _nthreads]->Unlock();
                    return false;
                }
            }
            if (worker->getId() == 0)
                _is_first_frame = false;

            _traj_readerMutex.Unlock();
            if (SynchronizeThreads()) {
                //unlock next frame for input
                _threadsMutexesIn[(id + 1) % _nthreads]->Unlock();
            }
            //evaluate
            if (_do_mapping) {
                worker->_map->Apply();
                worker->EvalConfiguration(&worker->_top_cg, &worker->_top);
            } else
                worker->EvalConfiguration(&worker->_top);

            return true;
        }

        void CsgApplication::Run(void) {
            TopologyReader *reader;
            // create reader for atomistic topology
            reader = TopReaderFactory().Create(_op_vm["top"].as<string > ());
            if (reader == NULL)
                throw runtime_error(string("input format not supported: ") + _op_vm["top"].as<string > ());

            class DummyWorker : public Worker {
            public:

                void EvalConfiguration(Topology *top, Topology *top_ref) {
                    _app->EvalConfiguration(top, top_ref);
                }
            };

            // create the master worker
            Worker *master = NULL;
            if (DoThreaded())
                master = ForkWorker();
            else
                master = new DummyWorker();

            master->setApplication(this);
            master->setId(0);
            _myWorkers.push_back(master);

            CGEngine cg;

            //////////////////////////////////////////////////
            // read in the topology for master
            //////////////////////////////////////////////////
            reader->ReadTopology(_op_vm["top"].as<string > (), master->_top);
            cout << "I have " << master->_top.BeadCount() << " beads in " << master->_top.MoleculeCount() << " molecules" << endl;
            master->_top.CheckMoleculeNaming();

            if (_do_mapping) {
                // read in the coarse graining definitions (xml files)
                cg.LoadMoleculeType(_op_vm["cg"].as<string > ());
                // create the mapping + cg topology

                if(_op_vm.count("map-ignore") != 0) {
                    Tokenizer tok(_op_vm["map-ignore"].as<string>(), ";");
                    Tokenizer::iterator iter;
                    for(iter=tok.begin(); iter!=tok.end(); ++iter) {
                        string str=*iter;
                        boost::trim(str);
                        if(str.length() > 0)
                            cg.AddIgnore(str);
                    }
                }

                master->_map = cg.CreateCGTopology(master->_top, master->_top_cg);

                cout << "I have " << master->_top_cg.BeadCount() << " beads in " << master->_top_cg.MoleculeCount() << " molecules for the coarsegraining" << endl;
                master->_map->Apply();
                if (!EvaluateTopology(&master->_top_cg, &master->_top))
                    return;
            } else
                if (!EvaluateTopology(&master->_top))
                return;

            //////////////////////////////////////////////////
            // Here trajectory parsing starts
            //////////////////////////////////////////////////
            if (DoTrajectory() && _op_vm.count("trj")) {
                double begin;
                int first_frame;
                bool has_begin = false;

                if (_op_vm.count("begin")) {
                    has_begin = true;
                    begin = _op_vm["begin"].as<double>();
                }

                _nframes = -1;
                if (_op_vm.count("nframes")) {
                    _nframes = _op_vm["nframes"].as<int>();
                }

                first_frame = _op_vm["first-frame"].as<int>();

                // create reader for trajectory
                _traj_reader = TrjReaderFactory().Create(_op_vm["trj"].as<string > ());
                if (_traj_reader == NULL)
                    throw runtime_error(string("input format not supported: ") + _op_vm["trj"].as<string > ());
                // open the trajectory
                _traj_reader->Open(_op_vm["trj"].as<string > ());

                //////////////////////////////////////////////////
                // Create all the workers
                /////////////////verbose/////////////////////////////////
                for (int thread = 1; thread < _nthreads && DoThreaded(); thread++) {
                    Worker *myWorker = ForkWorker();
                    myWorker->setApplication(this);
                    myWorker->setId(thread);
                    _myWorkers.push_back(myWorker);

                    // this will be changed to CopyTopologyData
                    // read in the topology
                    reader->ReadTopology(_op_vm["top"].as<string > (), myWorker->_top);
                    myWorker->_top.CheckMoleculeNaming();

                    if (_do_mapping) {
                        // create the mapping + cg topology
                        myWorker->_map = cg.CreateCGTopology(myWorker->_top, myWorker->_top_cg);
                    }
                }

                //////////////////////////////////////////////////
                // Proceed to first frame of interest
                //////////////////////////////////////////////////

                _traj_reader->FirstFrame(master->_top);
                if(master->_top.getBoxType()==BoundaryCondition::typeOpen) {
                    cout << "NOTE: You are using OpenBox boundary conditions. Check if this is intended.\n" << endl;
                }
                //seek first frame, let thread0 do that
                bool bok;
                for (bok = true; bok == true; bok = _traj_reader->NextFrame(master->_top)) {
                    if (((master->_top.getTime() < begin) && has_begin) || first_frame > 1) {
                        first_frame--;
                        continue;
                    }
                    break;
                }
                if (!bok) { // trajectory was too short and we did not proceed to first frame
                    _traj_reader->Close();
                    delete _traj_reader;

                    throw std::runtime_error("trajectory was too short, did not process a single frame");
                }

                // notify all observers that coarse graining has begun
                if (_do_mapping) {
                    master->_map->Apply();
                    BeginEvaluate(&master->_top_cg, &master->_top);
                } else
                    BeginEvaluate(&master->_top);

                _is_first_frame = true;
                /////////////////////////////////////////////////////////////////////////
                //start threads
                if (DoThreaded()) {
                    for (size_t thread = 0; thread < _myWorkers.size(); thread++) {

                        if (SynchronizeThreads()) {
                            Mutex *myMutexIn = new Mutex;
                            _threadsMutexesIn.push_back(myMutexIn);
                            // lock each worker for input
                            myMutexIn->Lock();

                            Mutex *myMutexOut = new Mutex;
                            _threadsMutexesOut.push_back(myMutexOut);
                            // lock each worker for output
                            myMutexOut->Lock();
                        }
                    }
                    for (size_t thread = 0; thread < _myWorkers.size(); thread++)
                        _myWorkers[thread]->Start();

                    if (SynchronizeThreads()) {
                        //unlock first thread and start ordered input/output
                        _threadsMutexesIn[0]->Unlock();
                        _threadsMutexesOut[0]->Unlock();
                    }
                    // mutex needed for merging if SynchronizeThreads()==False
                    Mutex mergeMutex;
                    for (size_t thread = 0; thread < _myWorkers.size(); thread++) {
                        _myWorkers[thread]->WaitDone();
                        if (!SynchronizeThreads()) {
                            mergeMutex.Lock();
                            MergeWorker(_myWorkers[thread]);
                            mergeMutex.Unlock();
                        }
                        delete _myWorkers[thread];
                    }
                    for (size_t thread = 0; thread < _threadsMutexesIn.size(); ++thread) {
                        delete _threadsMutexesIn[thread];
                        delete _threadsMutexesOut[thread];
                    }

                } else {
                    master->Run();
                    delete master;
                }

                EndEvaluate();

                _myWorkers.clear();
                _threadsMutexesIn.clear();
                _threadsMutexesOut.clear();
                _traj_reader->Close();

                delete _traj_reader;
            }

            delete reader;

        }

        CsgApplication::Worker::~Worker() {
            if (_map)
                delete _map;

        }

        void CsgApplication::BeginEvaluate(Topology *top, Topology * top_ref) {
            list<CGObserver *>::iterator iter;
            for (iter = _observers.begin(); iter != _observers.end(); ++iter)
                (*iter)->BeginCG(top, top_ref);
        }

        void CsgApplication::EndEvaluate() {
            list<CGObserver *>::iterator iter;
            for (iter = _observers.begin(); iter != _observers.end(); ++iter)
                (*iter)->EndCG();
        }

        void CsgApplication::EvalConfiguration(Topology *top, Topology * top_ref) {
            list<CGObserver *>::iterator iter;
            for (iter = _observers.begin(); iter != _observers.end(); ++iter)
                (*iter)->EvalConfiguration(top, top_ref);
        }

        CsgApplication::Worker *CsgApplication::ForkWorker(void) {
            throw std::runtime_error("ForkWorker not implemented in application");
            return NULL;
        }

        void CsgApplication::MergeWorker(CsgApplication::Worker *worker) {
            throw std::runtime_error("MergeWorker not implemented in application");
        }

    }
}
<commit_msg>csgapps: also allow map-ignore in case of no default Mapping<commit_after>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <votca/csg/csgapplication.h>
#include <votca/csg/trajectorywriter.h>
#include <votca/csg/trajectoryreader.h>
#include <votca/csg/topologyreader.h>
#include <votca/csg/topologymap.h>
#include <votca/csg/cgengine.h>
#include <votca/csg/version.h>
#include <boost/algorithm/string/trim.hpp>

namespace votca {
    namespace csg {

        CsgApplication::CsgApplication(void) {
        }

        CsgApplication::~CsgApplication(void) {
        }

        void CsgApplication::Initialize(void) {
            // register all io plugins
            TrajectoryWriter::RegisterPlugins();
            TrajectoryReader::RegisterPlugins();
            TopologyReader::RegisterPlugins();

            AddProgramOptions()
                    ("top", boost::program_options::value<string > (), "  atomistic topology file");
            if (DoMapping()) {
                if (DoMappingDefault()) {
                    AddProgramOptions("Mapping options")
                            ("cg", boost::program_options::value<string > (), "  coarse graining mapping definitions (xml-file)")
                            ("map-ignore", boost::program_options::value<string >(), "  list of molecules to ignore separated by ;")
                            ("no-map", "  disable mapping and act on original trajectory");
                } else {
                    AddProgramOptions("Mapping options")
                            ("cg", boost::program_options::value<string > (), "  [OPTIONAL] coarse graining mapping definitions\n"
                            "  (xml-file). If no file is given, program acts on original trajectory")
                            ("map-ignore", boost::program_options::value<string >(), "  list of molecules to ignore if mapping is done separated by ;");
                }
            }

            if (DoTrajectory())
                AddProgramOptions("Trajectory options")
                ("trj", boost::program_options::value<string > (), "  atomistic trajectory file")
                ("begin", boost::program_options::value<double>()->default_value(0.0), "  skip frames before this time")
                ("first-frame", boost::program_options::value<int>()->default_value(0), "  start with this frame")
                ("nframes", boost::program_options::value<int>(), "  process the given number of frames")
                ;

            if (DoThreaded())
                /*
                 * TODO default value of 1 for nt is not smart
                 */
                AddProgramOptions("Threading options")
                ("nt", boost::program_options::value<int>()->default_value(1), "  number of threads")
                ;

        }

        bool CsgApplication::EvaluateOptions(void) {
            _do_mapping = false;
            CheckRequired("top", "no topology file specified");

            // check for mapping options
            if (DoMapping()) {
                // default mapping is on
                if (DoMappingDefault()) {
                    // if the user does not explicitly ask to turn it off, cg is needed
                    if (OptionsMap().count("no-map") == 0) {
                        CheckRequired("cg", "no coarse graining definition specified");
                        _do_mapping = true;
                    }
                }// default mapping is off, if user gives cg, then do mapping
                else if (OptionsMap().count("cg")) {
                    _do_mapping = true;
                }
            }

            /* check threading options */
            if (DoThreaded()) {
                _nthreads = _op_vm["nt"].as<int > ();
                /* TODO
                 * does the number of threads make sense?
                 * which criteria should be used? smaller than system's cores?
                 */
            }

            return true;
        }

        void CsgApplication::ShowHelpText(std::ostream &out) {
            string name = ProgramName();
            if (VersionString() != "")
                name = name + ", version " + VersionString();

            HelpTextHeader(name);
            HelpText(out);
            out << "\n\n" << OptionsDesc() << endl;
        }

        void CsgApplication::Worker::Run(void) {
            while (_app->ProcessData(this)) {
                if (_app->SynchronizeThreads()) {
                    int id = getId();
                    _app->_threadsMutexesOut[id]->Lock();
                    _app->MergeWorker(this);
                    _app->_threadsMutexesOut[(id + 1) % _app->_nthreads]->Unlock();
                }
            }
        }

        bool CsgApplication::ProcessData(Worker * worker) {

            int id;
            id = worker->getId();

            if (SynchronizeThreads()) {
                //wait til its your turn
                _threadsMutexesIn[id]->Lock();
            }
            _traj_readerMutex.Lock();
            if (_nframes == 0) {
                _traj_readerMutex.Unlock();

                if (SynchronizeThreads()) {
                    //done processing? don't forget to unlock next worker anyway
                    _threadsMutexesIn[(id + 1) % _nthreads]->Unlock();
                }

                return false;
            }
            _nframes--;
            if (!_is_first_frame || worker->getId() != 0) {
                //get frame
                bool tmpRes = _traj_reader->NextFrame(worker->_top);
                if (!tmpRes) {
                    _traj_readerMutex.Unlock();
                    if (SynchronizeThreads())
                        _threadsMutexesIn[(id + 1) % _nthreads]->Unlock();
                    return false;
                }
            }
            if (worker->getId() == 0)
                _is_first_frame = false;

            _traj_readerMutex.Unlock();
            if (SynchronizeThreads()) {
                //unlock next frame for input
                _threadsMutexesIn[(id + 1) % _nthreads]->Unlock();
            }
            //evaluate
            if (_do_mapping) {
                worker->_map->Apply();
                worker->EvalConfiguration(&worker->_top_cg, &worker->_top);
            } else
                worker->EvalConfiguration(&worker->_top);

            return true;
        }

        void CsgApplication::Run(void) {
            TopologyReader *reader;
            // create reader for atomistic topology
            reader = TopReaderFactory().Create(_op_vm["top"].as<string > ());
            if (reader == NULL)
                throw runtime_error(string("input format not supported: ") + _op_vm["top"].as<string > ());

            class DummyWorker : public Worker {
            public:

                void EvalConfiguration(Topology *top, Topology *top_ref) {
                    _app->EvalConfiguration(top, top_ref);
                }
            };

            // create the master worker
            Worker *master = NULL;
            if (DoThreaded())
                master = ForkWorker();
            else
                master = new DummyWorker();

            master->setApplication(this);
            master->setId(0);
            _myWorkers.push_back(master);

            CGEngine cg;

            //////////////////////////////////////////////////
            // read in the topology for master
            //////////////////////////////////////////////////
            reader->ReadTopology(_op_vm["top"].as<string > (), master->_top);
            cout << "I have " << master->_top.BeadCount() << " beads in " << master->_top.MoleculeCount() << " molecules" << endl;
            master->_top.CheckMoleculeNaming();

            if (_do_mapping) {
                // read in the coarse graining definitions (xml files)
                cg.LoadMoleculeType(_op_vm["cg"].as<string > ());
                // create the mapping + cg topology

                if(_op_vm.count("map-ignore") != 0) {
                    Tokenizer tok(_op_vm["map-ignore"].as<string>(), ";");
                    Tokenizer::iterator iter;
                    for(iter=tok.begin(); iter!=tok.end(); ++iter) {
                        string str=*iter;
                        boost::trim(str);
                        if(str.length() > 0)
                            cg.AddIgnore(str);
                    }
                }

                master->_map = cg.CreateCGTopology(master->_top, master->_top_cg);

                cout << "I have " << master->_top_cg.BeadCount() << " beads in " << master->_top_cg.MoleculeCount() << " molecules for the coarsegraining" << endl;
                master->_map->Apply();
                if (!EvaluateTopology(&master->_top_cg, &master->_top))
                    return;
            } else
                if (!EvaluateTopology(&master->_top))
                return;

            //////////////////////////////////////////////////
            // Here trajectory parsing starts
            //////////////////////////////////////////////////
            if (DoTrajectory() && _op_vm.count("trj")) {
                double begin;
                int first_frame;
                bool has_begin = false;

                if (_op_vm.count("begin")) {
                    has_begin = true;
                    begin = _op_vm["begin"].as<double>();
                }

                _nframes = -1;
                if (_op_vm.count("nframes")) {
                    _nframes = _op_vm["nframes"].as<int>();
                }

                first_frame = _op_vm["first-frame"].as<int>();

                // create reader for trajectory
                _traj_reader = TrjReaderFactory().Create(_op_vm["trj"].as<string > ());
                if (_traj_reader == NULL)
                    throw runtime_error(string("input format not supported: ") + _op_vm["trj"].as<string > ());
                // open the trajectory
                _traj_reader->Open(_op_vm["trj"].as<string > ());

                //////////////////////////////////////////////////
                // Create all the workers
                /////////////////verbose/////////////////////////////////
                for (int thread = 1; thread < _nthreads && DoThreaded(); thread++) {
                    Worker *myWorker = ForkWorker();
                    myWorker->setApplication(this);
                    myWorker->setId(thread);
                    _myWorkers.push_back(myWorker);

                    // this will be changed to CopyTopologyData
                    // read in the topology
                    reader->ReadTopology(_op_vm["top"].as<string > (), myWorker->_top);
                    myWorker->_top.CheckMoleculeNaming();

                    if (_do_mapping) {
                        // create the mapping + cg topology
                        myWorker->_map = cg.CreateCGTopology(myWorker->_top, myWorker->_top_cg);
                    }
                }

                //////////////////////////////////////////////////
                // Proceed to first frame of interest
                //////////////////////////////////////////////////

                _traj_reader->FirstFrame(master->_top);
                if(master->_top.getBoxType()==BoundaryCondition::typeOpen) {
                    cout << "NOTE: You are using OpenBox boundary conditions. Check if this is intended.\n" << endl;
                }
                //seek first frame, let thread0 do that
                bool bok;
                for (bok = true; bok == true; bok = _traj_reader->NextFrame(master->_top)) {
                    if (((master->_top.getTime() < begin) && has_begin) || first_frame > 1) {
                        first_frame--;
                        continue;
                    }
                    break;
                }
                if (!bok) { // trajectory was too short and we did not proceed to first frame
                    _traj_reader->Close();
                    delete _traj_reader;

                    throw std::runtime_error("trajectory was too short, did not process a single frame");
                }

                // notify all observers that coarse graining has begun
                if (_do_mapping) {
                    master->_map->Apply();
                    BeginEvaluate(&master->_top_cg, &master->_top);
                } else
                    BeginEvaluate(&master->_top);

                _is_first_frame = true;
                /////////////////////////////////////////////////////////////////////////
                //start threads
                if (DoThreaded()) {
                    for (size_t thread = 0; thread < _myWorkers.size(); thread++) {

                        if (SynchronizeThreads()) {
                            Mutex *myMutexIn = new Mutex;
                            _threadsMutexesIn.push_back(myMutexIn);
                            // lock each worker for input
                            myMutexIn->Lock();

                            Mutex *myMutexOut = new Mutex;
                            _threadsMutexesOut.push_back(myMutexOut);
                            // lock each worker for output
                            myMutexOut->Lock();
                        }
                    }
                    for (size_t thread = 0; thread < _myWorkers.size(); thread++)
                        _myWorkers[thread]->Start();

                    if (SynchronizeThreads()) {
                        //unlock first thread and start ordered input/output
                        _threadsMutexesIn[0]->Unlock();
                        _threadsMutexesOut[0]->Unlock();
                    }
                    // mutex needed for merging if SynchronizeThreads()==False
                    Mutex mergeMutex;
                    for (size_t thread = 0; thread < _myWorkers.size(); thread++) {
                        _myWorkers[thread]->WaitDone();
                        if (!SynchronizeThreads()) {
                            mergeMutex.Lock();
                            MergeWorker(_myWorkers[thread]);
                            mergeMutex.Unlock();
                        }
                        delete _myWorkers[thread];
                    }
                    for (size_t thread = 0; thread < _threadsMutexesIn.size(); ++thread) {
                        delete _threadsMutexesIn[thread];
                        delete _threadsMutexesOut[thread];
                    }

                } else {
                    master->Run();
                    delete master;
                }

                EndEvaluate();

                _myWorkers.clear();
                _threadsMutexesIn.clear();
                _threadsMutexesOut.clear();
                _traj_reader->Close();

                delete _traj_reader;
            }

            delete reader;

        }

        CsgApplication::Worker::~Worker() {
            if (_map)
                delete _map;

        }

        void CsgApplication::BeginEvaluate(Topology *top, Topology * top_ref) {
            list<CGObserver *>::iterator iter;
            for (iter = _observers.begin(); iter != _observers.end(); ++iter)
                (*iter)->BeginCG(top, top_ref);
        }

        void CsgApplication::EndEvaluate() {
            list<CGObserver *>::iterator iter;
            for (iter = _observers.begin(); iter != _observers.end(); ++iter)
                (*iter)->EndCG();
        }

        void CsgApplication::EvalConfiguration(Topology *top, Topology * top_ref) {
            list<CGObserver *>::iterator iter;
            for (iter = _observers.begin(); iter != _observers.end(); ++iter)
                (*iter)->EvalConfiguration(top, top_ref);
        }

        CsgApplication::Worker *CsgApplication::ForkWorker(void) {
            throw std::runtime_error("ForkWorker not implemented in application");
            return NULL;
        }

        void CsgApplication::MergeWorker(CsgApplication::Worker *worker) {
            throw std::runtime_error("MergeWorker not implemented in application");
        }

    }
}
<|endoftext|>


<commit_before>
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qgeoaddress.h"
#include "qgeoaddress_p.h"

QTM_BEGIN_NAMESPACE

QGeoAddressPrivate::QGeoAddressPrivate()
{
}

QGeoAddressPrivate::QGeoAddressPrivate(const QGeoAddressPrivate &other)
    :QSharedData(other),
     sCountry(other.sCountry),
     sCountryCode(other.sCountryCode),
     sState(other.sState),
     sCounty(other.sCounty),
     sCity(other.sCity),
     sDistrict(other.sDistrict),
     sThoroughfareName(other.sThoroughfareName),
     sThoroughfareNumber(other.sThoroughfareNumber),
     sPostCode(other.sPostCode),
     sPostOfficeBox(other.sPostOfficeBox)
{
}

QGeoAddressPrivate::~QGeoAddressPrivate()
{
}

/*!
    \class QGeoAddress
    \brief The QGeoAddress class represents an address
    \ingroup location

    This class represents an address of a location.

    \sa QGeocodingReply
*/

/*!
    Default constructor.
*/
QGeoAddress::QGeoAddress()
{
}

/*!
    Constructs a copy of \a other.
*/
QGeoAddress::QGeoAddress(const QGeoAddress &other)
    :d(other.d)
{
}

/*!
    Destroys the address
*/
QGeoAddress::~QGeoAddress()
{
}

/*!
    Assigns the given \a address to this address and
    returns a reference to this address.
*/
QGeoAddress &QGeoAddress::operator=(const QGeoAddress &address)
{
    d = address.d;
    return *this;
}

/*!
    Returns true if this address is equal to \a other,
    otherwise returns false.
*/
bool QGeoAddress::operator==(const QGeoAddress &other) const
{
    return d->sCountry == other.country() &&
           d->sCountryCode == other.countryCode() &&
           d->sState == other.state() &&
           d->sCounty == other.county() &&
           d->sCity == other.city() &&
           d->sDistrict == other.district() &&
           d->sThoroughfareName == other.thoroughfareName() &&
           d->sThoroughfareNumber == other.thoroughfareNumber() &&
           d->sPostCode == other.postCode();
}

/*!
    \fn bool QGeoAddress::operator!=(const QGeoAddress &other) const

    Returns true if this address is not equal to \a other,
    otherwise returns false.
*/

/*!
    Returns the country name according to ISO 3166-1 alpha-3
*/
QString QGeoAddress::country() const
{
    return d->sCountry;
}

/*!
    Sets the \a country name according to ISO 3166-1 alpha-3
*/
void QGeoAddress::setCountry(const QString &country)
{
    d->sCountry = country;
}

/*!
    Returns the country code according to ISO 3166-1 alpha-3
*/
QString QGeoAddress::countryCode() const
{
    return d->sCountryCode;
}

/*!
    Sets the \a countryCode according to ISO 3166-1 alpha-3
*/
void QGeoAddress::setCountryCode(const QString &countryCode)
{
    d->sCountryCode = countryCode;
}

/*!
    Returns the state.
*/
QString QGeoAddress::state() const
{
    return d->sState;
}

/*!
    Sets the \a state.
*/
void QGeoAddress::setState(const QString &state)
{
    d->sState = state;
}

/*!
    Returns the county.
*/
QString QGeoAddress::county() const
{
    return d->sCounty;
}

/*!
    Sets the \a county.
*/
void QGeoAddress::setCounty(const QString &county)
{
    d->sCounty = county;
}

/*!
    Returns the city.
*/
QString QGeoAddress::city() const
{
    return d->sCity;
}

/*!
    Sets the \a city.
*/
void QGeoAddress::setCity(const QString &city)
{
    d->sCity = city;
}

/*!
    Returns the district.
*/
QString QGeoAddress::district() const
{
    return d->sDistrict;
}

/*!
    Sets the \a district.
*/
void QGeoAddress::setDistrict(const QString &district)
{
    d->sDistrict = district;
}

/*!
    Returns the thoroughfare name.
*/
QString QGeoAddress::thoroughfareName() const
{
    return d->sThoroughfareName;
}

/*!
    Sets the \a thoroughfareName.
*/
void QGeoAddress::setThoroughfareName(const QString &thoroughfareName)
{
    d->sThoroughfareName = thoroughfareName;
}

/*!
    Returns the thoroughfare number.
*/
QString QGeoAddress::thoroughfareNumber() const
{
    return d->sThoroughfareNumber;
}

/*!
    Sets the \a thoroughfareNumber.
*/
void QGeoAddress::setThoroughfareNumber(const QString &thoroughfareNumber)
{
    d->sThoroughfareNumber = thoroughfareNumber;
}

/*!
    Returns the post code.
*/
QString QGeoAddress::postCode() const
{
    return d->sPostCode;
}

/*!
    Sets the \a postCode.
*/
void QGeoAddress::setPostCode(const QString &postCode)
{
    d->sPostCode = postCode;
}

/*!
   Returns the post office box.
*/
QString QGeoAddress::postOfficeBox() const
{
    return d->sPostOfficeBox;
}

/*!
   Sets the \a postOfficeBox.
*/
void QGeoAddress::setPostOfficeBox(const QString &postOfficeBox)
{
    d->sPostOfficeBox = postOfficeBox;
}

/*!
    Returns whether this address is empty. An address is considered empty
    if \i all of its fields are empty.
*/
bool QGeoAddress::isEmpty() const
{
    return d->sCountry.isEmpty() &&
           d->sCountryCode.isEmpty() &&
           d->sState.isEmpty() &&
           d->sCounty.isEmpty() &&
           d->sCity.isEmpty() &&
           d->sDistrict.isEmpty() &&
           d->sThoroughfareName.isEmpty() &&
           d->sThoroughfareNumber.isEmpty() &&
           d->sPostCode.isEmpty();
}

QTM_END_NAMESPACE

<commit_msg>Added missing d construction to QGeoAddress<commit_after>
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qgeoaddress.h"
#include "qgeoaddress_p.h"

QTM_BEGIN_NAMESPACE

QGeoAddressPrivate::QGeoAddressPrivate()
{
}

QGeoAddressPrivate::QGeoAddressPrivate(const QGeoAddressPrivate &other)
    :QSharedData(other),
     sCountry(other.sCountry),
     sCountryCode(other.sCountryCode),
     sState(other.sState),
     sCounty(other.sCounty),
     sCity(other.sCity),
     sDistrict(other.sDistrict),
     sThoroughfareName(other.sThoroughfareName),
     sThoroughfareNumber(other.sThoroughfareNumber),
     sPostCode(other.sPostCode),
     sPostOfficeBox(other.sPostOfficeBox)
{
}

QGeoAddressPrivate::~QGeoAddressPrivate()
{
}

/*!
    \class QGeoAddress
    \brief The QGeoAddress class represents an address
    \ingroup location

    This class represents an address of a location.

    \sa QGeocodingReply
*/

/*!
    Default constructor.
*/
QGeoAddress::QGeoAddress()
    :d(new QGeoAddressPrivate)
{
}

/*!
    Constructs a copy of \a other.
*/
QGeoAddress::QGeoAddress(const QGeoAddress &other)
    :d(other.d)
{
}

/*!
    Destroys the address
*/
QGeoAddress::~QGeoAddress()
{
}

/*!
    Assigns the given \a address to this address and
    returns a reference to this address.
*/
QGeoAddress &QGeoAddress::operator=(const QGeoAddress &address)
{
    d = address.d;
    return *this;
}

/*!
    Returns true if this address is equal to \a other,
    otherwise returns false.
*/
bool QGeoAddress::operator==(const QGeoAddress &other) const
{
    return d->sCountry == other.country() &&
           d->sCountryCode == other.countryCode() &&
           d->sState == other.state() &&
           d->sCounty == other.county() &&
           d->sCity == other.city() &&
           d->sDistrict == other.district() &&
           d->sThoroughfareName == other.thoroughfareName() &&
           d->sThoroughfareNumber == other.thoroughfareNumber() &&
           d->sPostCode == other.postCode();
}

/*!
    \fn bool QGeoAddress::operator!=(const QGeoAddress &other) const

    Returns true if this address is not equal to \a other,
    otherwise returns false.
*/

/*!
    Returns the country name according to ISO 3166-1 alpha-3
*/
QString QGeoAddress::country() const
{
    return d->sCountry;
}

/*!
    Sets the \a country name according to ISO 3166-1 alpha-3
*/
void QGeoAddress::setCountry(const QString &country)
{
    d->sCountry = country;
}

/*!
    Returns the country code according to ISO 3166-1 alpha-3
*/
QString QGeoAddress::countryCode() const
{
    return d->sCountryCode;
}

/*!
    Sets the \a countryCode according to ISO 3166-1 alpha-3
*/
void QGeoAddress::setCountryCode(const QString &countryCode)
{
    d->sCountryCode = countryCode;
}

/*!
    Returns the state.
*/
QString QGeoAddress::state() const
{
    return d->sState;
}

/*!
    Sets the \a state.
*/
void QGeoAddress::setState(const QString &state)
{
    d->sState = state;
}

/*!
    Returns the county.
*/
QString QGeoAddress::county() const
{
    return d->sCounty;
}

/*!
    Sets the \a county.
*/
void QGeoAddress::setCounty(const QString &county)
{
    d->sCounty = county;
}

/*!
    Returns the city.
*/
QString QGeoAddress::city() const
{
    return d->sCity;
}

/*!
    Sets the \a city.
*/
void QGeoAddress::setCity(const QString &city)
{
    d->sCity = city;
}

/*!
    Returns the district.
*/
QString QGeoAddress::district() const
{
    return d->sDistrict;
}

/*!
    Sets the \a district.
*/
void QGeoAddress::setDistrict(const QString &district)
{
    d->sDistrict = district;
}

/*!
    Returns the thoroughfare name.
*/
QString QGeoAddress::thoroughfareName() const
{
    return d->sThoroughfareName;
}

/*!
    Sets the \a thoroughfareName.
*/
void QGeoAddress::setThoroughfareName(const QString &thoroughfareName)
{
    d->sThoroughfareName = thoroughfareName;
}

/*!
    Returns the thoroughfare number.
*/
QString QGeoAddress::thoroughfareNumber() const
{
    return d->sThoroughfareNumber;
}

/*!
    Sets the \a thoroughfareNumber.
*/
void QGeoAddress::setThoroughfareNumber(const QString &thoroughfareNumber)
{
    d->sThoroughfareNumber = thoroughfareNumber;
}

/*!
    Returns the post code.
*/
QString QGeoAddress::postCode() const
{
    return d->sPostCode;
}

/*!
    Sets the \a postCode.
*/
void QGeoAddress::setPostCode(const QString &postCode)
{
    d->sPostCode = postCode;
}

/*!
   Returns the post office box.
*/
QString QGeoAddress::postOfficeBox() const
{
    return d->sPostOfficeBox;
}

/*!
   Sets the \a postOfficeBox.
*/
void QGeoAddress::setPostOfficeBox(const QString &postOfficeBox)
{
    d->sPostOfficeBox = postOfficeBox;
}

/*!
    Returns whether this address is empty. An address is considered empty
    if \i all of its fields are empty.
*/
bool QGeoAddress::isEmpty() const
{
    return d->sCountry.isEmpty() &&
           d->sCountryCode.isEmpty() &&
           d->sState.isEmpty() &&
           d->sCounty.isEmpty() &&
           d->sCity.isEmpty() &&
           d->sDistrict.isEmpty() &&
           d->sThoroughfareName.isEmpty() &&
           d->sThoroughfareNumber.isEmpty() &&
           d->sPostCode.isEmpty();
}

QTM_END_NAMESPACE

<|endoftext|>