<commit_before>/* libvisio
 * Copyright (C) 2011 Fridrich Strba <fridrich.strba@bluewin.ch>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02111-1301 USA
 */

#include <libwpd-stream/libwpd-stream.h>
#include <libvisio_utils.h>
#include "VSDXParser.h"
#include "VSDInternalStream.h"
#include <locale.h>
#include <sstream>
#include <string>

libvisio::VSDXParser::VSDXParser(WPXInputStream *input)
  : m_input(input)
{}

libvisio::VSDXParser::~VSDXParser()
{}

/**************************************************
 * Visio 2000 parser implementation
 **************************************************/

libvisio::VSD6Parser::VSD6Parser(WPXInputStream *input)
  : VSDXParser(input)
{}

libvisio::VSD6Parser::~VSD6Parser()
{}

/** Parses VSD 2000 input stream content, making callbacks to functions provided
by WPGPaintInterface class implementation as needed.
\param iface A WPGPaintInterface implementation
\return A value indicating whether parsing was successful
*/
bool libvisio::VSD6Parser::parse(libwpg::WPGPaintInterface *iface)
{
  const unsigned int SHIFT = 4;
  if (!m_input)
  {
    return false;
  }
  // Seek to trailer stream pointer
  m_input->seek(0x24, WPX_SEEK_SET);

  m_input->seek(8, WPX_SEEK_CUR);
  unsigned int offset = readU32(m_input);
  unsigned int length = readU32(m_input);
  unsigned short format = readU16(m_input);
  bool compressed = ((format & 2) == 2);

  m_input->seek(offset, WPX_SEEK_SET);
  VSDInternalStream trailerStream(m_input, length, compressed);

  // Parse out pointers to other streams from trailer
  trailerStream.seek(SHIFT, WPX_SEEK_SET);
  offset = readU32(&trailerStream);
  trailerStream.seek(offset+SHIFT, WPX_SEEK_SET);
  unsigned int pointerCount = readU32(&trailerStream);
  trailerStream.seek(SHIFT, WPX_SEEK_CUR);

  unsigned int ptrType;
  unsigned int ptrOffset;
  unsigned int ptrLength;
  unsigned int ptrFormat;
  for (unsigned int i = 0; i < pointerCount; i++)
  {
    ptrType = readU32(&trailerStream);
    trailerStream.seek(4, WPX_SEEK_CUR); // Skip dword
    ptrOffset = readU32(&trailerStream);
    ptrLength = readU32(&trailerStream);
    ptrFormat = readU16(&trailerStream);
    VSD_DEBUG_MSG(("Found pointer of type %x and format %x\n", ptrType, ptrFormat));
  }

  return true;
}

/**************************************************
 * Visio 2003 parser implementation
 **************************************************/

libvisio::VSD11Parser::VSD11Parser(WPXInputStream *input)
  : VSDXParser(input)
{}

libvisio::VSD11Parser::~VSD11Parser()
{}

/** Parses VSD 2003 input stream content, making callbacks to functions provided
by WPGPaintInterface class implementation as needed.
\param iface A WPGPaintInterface implementation
\return A value indicating whether parsing was successful
*/
bool libvisio::VSD11Parser::parse(libwpg::WPGPaintInterface *iface)
{
  const unsigned int SHIFT = 4;
  if (!m_input)
  {
    return false;
  }
  // Seek to trailer stream pointer
  m_input->seek(0x24, WPX_SEEK_SET);

  m_input->seek(8, WPX_SEEK_CUR);
  unsigned int offset = readU32(m_input);
  unsigned int length = readU32(m_input);
  unsigned short format = readU16(m_input);
  bool compressed = ((format & 2) == 2);

  m_input->seek(offset, WPX_SEEK_SET);
  VSDInternalStream trailerStream(m_input, length, compressed);

  // Parse out pointers to other streams from trailer
  trailerStream.seek(SHIFT, WPX_SEEK_SET);
  offset = readU32(&trailerStream);
  trailerStream.seek(offset+SHIFT, WPX_SEEK_SET);
  unsigned int pointerCount = readU32(&trailerStream);
  trailerStream.seek(SHIFT, WPX_SEEK_CUR);

  unsigned int ptrType;
  unsigned int ptrOffset;
  unsigned int ptrLength;
  unsigned int ptrFormat;
  for (unsigned int i = 0; i < pointerCount; i++)
  {
    ptrType = readU32(&trailerStream);
    trailerStream.seek(4, WPX_SEEK_CUR); // Skip dword
    ptrOffset = readU32(&trailerStream);
    ptrLength = readU32(&trailerStream);
    ptrFormat = readU16(&trailerStream);
    VSD_DEBUG_MSG(("Found pointer of type %x and format %x\n", ptrType, ptrFormat));
  }

  return true;
}
<commit_msg>Started handling of stream types in v11 parser<commit_after>/* libvisio
 * Copyright (C) 2011 Fridrich Strba <fridrich.strba@bluewin.ch>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02111-1301 USA
 */

#include <libwpd-stream/libwpd-stream.h>
#include <libvisio_utils.h>
#include "VSDXParser.h"
#include "VSDInternalStream.h"
#include <locale.h>
#include <sstream>
#include <string>

libvisio::VSDXParser::VSDXParser(WPXInputStream *input)
  : m_input(input)
{}

libvisio::VSDXParser::~VSDXParser()
{}

/**************************************************
 * Visio 2000 parser implementation
 **************************************************/

libvisio::VSD6Parser::VSD6Parser(WPXInputStream *input)
  : VSDXParser(input)
{}

libvisio::VSD6Parser::~VSD6Parser()
{}

/** Parses VSD 2000 input stream content, making callbacks to functions provided
by WPGPaintInterface class implementation as needed.
\param iface A WPGPaintInterface implementation
\return A value indicating whether parsing was successful
*/
bool libvisio::VSD6Parser::parse(libwpg::WPGPaintInterface *iface)
{
  const unsigned int SHIFT = 4;
  if (!m_input)
  {
    return false;
  }
  // Seek to trailer stream pointer
  m_input->seek(0x24, WPX_SEEK_SET);

  m_input->seek(8, WPX_SEEK_CUR);
  unsigned int offset = readU32(m_input);
  unsigned int length = readU32(m_input);
  unsigned short format = readU16(m_input);
  bool compressed = ((format & 2) == 2);

  m_input->seek(offset, WPX_SEEK_SET);
  VSDInternalStream trailerStream(m_input, length, compressed);

  // Parse out pointers to other streams from trailer
  trailerStream.seek(SHIFT, WPX_SEEK_SET);
  offset = readU32(&trailerStream);
  trailerStream.seek(offset+SHIFT, WPX_SEEK_SET);
  unsigned int pointerCount = readU32(&trailerStream);
  trailerStream.seek(SHIFT, WPX_SEEK_CUR);

  unsigned int ptrType;
  unsigned int ptrOffset;
  unsigned int ptrLength;
  unsigned int ptrFormat;
  for (unsigned int i = 0; i < pointerCount; i++)
  {
    ptrType = readU32(&trailerStream);
    trailerStream.seek(4, WPX_SEEK_CUR); // Skip dword
    ptrOffset = readU32(&trailerStream);
    ptrLength = readU32(&trailerStream);
    ptrFormat = readU16(&trailerStream);
    VSD_DEBUG_MSG(("Found pointer of type %x and format %x\n", ptrType, ptrFormat));
  }

  return true;
}

/**************************************************
 * Visio 2003 parser implementation
 **************************************************/

libvisio::VSD11Parser::VSD11Parser(WPXInputStream *input)
  : VSDXParser(input)
{}

libvisio::VSD11Parser::~VSD11Parser()
{}

/** Parses VSD 2003 input stream content, making callbacks to functions provided
by WPGPaintInterface class implementation as needed.
\param iface A WPGPaintInterface implementation
\return A value indicating whether parsing was successful
*/
bool libvisio::VSD11Parser::parse(libwpg::WPGPaintInterface *iface)
{
  const unsigned int SHIFT = 4;
  if (!m_input)
  {
    return false;
  }
  // Seek to trailer stream pointer
  m_input->seek(0x24, WPX_SEEK_SET);

  m_input->seek(8, WPX_SEEK_CUR);
  unsigned int offset = readU32(m_input);
  unsigned int length = readU32(m_input);
  unsigned short format = readU16(m_input);
  bool compressed = ((format & 2) == 2);

  m_input->seek(offset, WPX_SEEK_SET);
  VSDInternalStream trailerStream(m_input, length, compressed);

  // Parse out pointers to other streams from trailer
  typedef void (VSD11Parser::*Method)(VSDInternalStream&);
  struct StreamHandler { unsigned int type; const char *name; Method handler;};
  static const struct StreamHandler handlers[] =
  {
    {0xa, "Name", 0},
    {0xb, "Name Idx", 0},
    {0x14, "Trailer, 0"},
    {0x15, "Page", 0},
    {0x16, "Colors"},
    {0x17, "??? seems to have no data", 0},
    {0x18, "FontFaces (ver.11)", 0},
    {0x1a, "Styles", 0},
    {0x1b, "??? saw 'Acrobat PDFWriter' string here", 0},
    {0x1c, "??? saw 'winspool.Acrobat PDFWriter.LPT1' string here", 0},
    {0x1d, "Stencils"},
    {0x1e, "Stencil Page (collection of Shapes, one collection per each stencil item)", 0},
    {0x20, "??? seems to have no data", 0},
    {0x21, "??? seems to have no data", 0},
    {0x23, "Icon (for stencil only?)", 0},
    {0x24, "??? seems to have no data", 0},
    {0x26, "??? some fractions, maybe PrintProps", 0},
    {0x27, "Pages", 0},
    {0x29, "Collection of Type 2a streams", 0},
    {0x2a, "???", 0},
    {0x31, "Document", 0},
    {0x32, "NameList", 0},
    {0x33, "Name", 0},
    {0x3d, "??? found in VSS, seems to have no data", 0},
    {0x3f, "List of name indexes collections", 0},
    {0x40, "Name Idx + ?? group (contains 0xb type streams)", 0},
    {0x44, "??? Collection of Type 0x45 streams", 0},
    {0x45, "??? match number of Pages or Stencil Pages in Pages/Stencils", 0},
    {0xc9, "some collection of 13 bytes structures related to 3f/40 streams", 0},
    {0xd7, "FontFace (ver.11)", 0},
    {0xd8, "FontFaces (ver.6)", 0}
  };

  trailerStream.seek(SHIFT, WPX_SEEK_SET);
  offset = readU32(&trailerStream);
  trailerStream.seek(offset+SHIFT, WPX_SEEK_SET);
  unsigned int pointerCount = readU32(&trailerStream);
  trailerStream.seek(SHIFT, WPX_SEEK_CUR);

  unsigned int ptrType;
  unsigned int ptrOffset;
  unsigned int ptrLength;
  unsigned int ptrFormat;
  for (unsigned int i = 0; i < pointerCount; i++)
  {
    ptrType = readU32(&trailerStream);
    trailerStream.seek(4, WPX_SEEK_CUR); // Skip dword
    ptrOffset = readU32(&trailerStream);
    ptrLength = readU32(&trailerStream);
    ptrFormat = readU16(&trailerStream);

    compressed = ((format & 2) == 2);
    m_input->seek(ptrOffset, WPX_SEEK_SET);
    VSDInternalStream stream(m_input, ptrLength, compressed);

    int index = -1;
    for (int i = 0; (index < 0) && handlers[i].name; i++)
    {
      if (handlers[i].type == ptrType)
        index = i;
    }

    if (index < 0)
    {
      VSD_DEBUG_MSG(("Unknown stream pointer type 0x%02x found in trailer at %li\n",
                     ptrType, trailerStream.tell() - 18));
    }
    else
    {
      Method streamHandler = handlers[index].handler;
      if (!streamHandler)
        VSD_DEBUG_MSG(("Stream '%s', type 0x%02x, format 0x%02x at %li ignored\n",
                       handlers[index].name, handlers[index].type, ptrFormat,
                       trailerStream.tell() - 18));
      else
      {
        VSD_DEBUG_MSG(("Stream '%s', type 0x%02x, format 0x%02x at %li handled\n",
                       handlers[index].name, handlers[index].type, ptrFormat,
                       trailerStream.tell() - 18));
        (this->*streamHandler)(stream);
      }
    }
  }

  return true;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009 Marc Boris Duerner, Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#if defined(HAVE_ACCEPT4) || defined(HAVE_SO_NOSIGPIPE) || defined(MSG_NOSIGNAL)
#include <sys/types.h>
#include <sys/socket.h>
#endif

#if !defined(MSG_MSG_NOSIGNAL)
#include <signal.h>
#endif

#include "tcpsocketimpl.h"
#include "tcpserverimpl.h"
#include "cxxtools/net/tcpserver.h"
#include "cxxtools/net/tcpsocket.h"
#include "cxxtools/systemerror.h"
#include "cxxtools/ioerror.h"
#include "cxxtools/log.h"
#include "config.h"
#include "error.h"
#include <cerrno>
#include <cstring>
#include <cassert>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sstream>

log_define("cxxtools.net.tcpsocket.impl")

namespace cxxtools
{

namespace net
{

namespace
{
    std::string connectFailedMessage(const AddrInfo& ai, int err)
    {
        std::ostringstream msg;
        msg << "failed to connect to host \"" << ai.host() << "\" port " << ai.port()
            << ": " << getErrnoString(err);
        return msg.str();
    }

}

void formatIp(const Sockaddr& sa, std::string& str)
{
#ifdef HAVE_INET_NTOP
#ifdef HAVE_IPV6
      char strbuf[INET6_ADDRSTRLEN + 1];
#else
      char strbuf[INET_ADDRSTRLEN + 1];
#endif

      const char* p = 0;

      switch(sa.sa_in.sin_family)
      {
            case AF_INET:
                  p = inet_ntop(AF_INET, &sa.sa_in.sin_addr, strbuf, sizeof(strbuf));
                  break;
#ifdef HAVE_IPV6
            case AF_INET6:
                  p = inet_ntop(AF_INET6, &sa.sa_in6.sin6_addr,
                        strbuf, sizeof(strbuf));
                  break;
#endif
      }

      str = (p == 0 ? "-" : strbuf);
#else
      static cxxtools::Mutex monitor;
      cxxtools::MutexLock lock(monitor);

      const char* p = inet_ntoa(sa.sa_in.sin_addr);
      if (p)
        str = p;
      else
        str.clear();
#endif
}

std::string getSockAddr(int fd)
{
    Sockaddr addr;

    socklen_t slen = sizeof(addr);
    if (::getsockname(fd, &addr.sa, &slen) < 0)
        throw SystemError("getsockname");

    std::string ret;
    formatIp(addr, ret);
    return ret;
}

TcpSocketImpl::TcpSocketImpl(TcpSocket& socket)
: IODeviceImpl(socket)
, _socket(socket)
, _isConnected(false)
{
}

TcpSocketImpl::~TcpSocketImpl()
{
    assert(_pfd == 0);
}

void TcpSocketImpl::close()
{
    log_debug("close socket " << _fd);
    IODeviceImpl::close();
    _isConnected = false;
}

std::string TcpSocketImpl::getSockAddr() const
{ return net::getSockAddr(fd()); }

std::string TcpSocketImpl::getPeerAddr() const
{
    Sockaddr addr;

    addr.storage = _peeraddr;

    std::string ret;
    formatIp(addr, ret);
    return ret;
}

void TcpSocketImpl::connect(const AddrInfo& addrInfo)
{
    log_debug("connect");
    this->beginConnect(addrInfo);
    this->endConnect();
}

int TcpSocketImpl::checkConnect()
{
    log_trace("checkConnect");

    int sockerr;
    socklen_t optlen = sizeof(sockerr);

    // check for socket error
    if( ::getsockopt(this->fd(), SOL_SOCKET, SO_ERROR, &sockerr, &optlen) != 0 )
    {
        // getsockopt failed
        int e = errno;
        close();
        throw SystemError(e, "getsockopt");
    }

    if (sockerr == 0)
    {
        log_debug("connected successfully to " << getPeerAddr());
        _isConnected = true;
    }

    return sockerr;
}

void TcpSocketImpl::checkPendingError()
{
    if (!_connectResult.empty())
    {
        std::string p = _connectResult;
        _connectResult.clear();
        throw IOError(p);
    }
}

std::string TcpSocketImpl::tryConnect()
{
    log_trace("tryConnect");

    assert(_fd == -1);

    if (_addrInfoPtr == _addrInfo.impl()->end())
    {
        log_debug("no more address informations");
        std::ostringstream msg;
        msg << "invalid address information; host \"" << _addrInfo.host() << "\" port " << _addrInfo.port();
        return msg.str();
    }

    while (true)
    {
        int fd;
        while (true)
        {
            log_debug("create socket");
            fd = ::socket(_addrInfoPtr->ai_family, SOCK_STREAM, 0);
            if (fd >= 0)
                break;

            if (++_addrInfoPtr == _addrInfo.impl()->end())
            {
                std::ostringstream msg;
                msg << "failed to create socket for host \"" << _addrInfo.host()
                    << "\" port " << _addrInfo.port()
                    << ": " << getErrnoString();
                return msg.str();
            }
        }

#ifdef HAVE_SO_NOSIGPIPE
        static const int on = 1;
        if (::setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)) < 0)
            throw cxxtools::SystemError("setsockopt(SO_NOSIGPIPE)");
#endif

        IODeviceImpl::open(fd, true, false);

        std::memmove(&_peeraddr, _addrInfoPtr->ai_addr, _addrInfoPtr->ai_addrlen);

        log_debug("created socket " << _fd << " max: " << FD_SETSIZE);

        if( ::connect(this->fd(), _addrInfoPtr->ai_addr, _addrInfoPtr->ai_addrlen) == 0 )
        {
            _isConnected = true;
            log_debug("connected successfully to " << getPeerAddr());
            break;
        }

        if (errno == EINPROGRESS)
        {
            log_debug("connect in progress");
            break;
        }

        close();
        if (++_addrInfoPtr == _addrInfo.impl()->end())
            return connectFailedMessage(_addrInfo, errno);
    }

    return std::string();
}

bool TcpSocketImpl::beginConnect(const AddrInfo& addrInfo)
{
    log_trace("begin connect");

    assert(!_isConnected);

    _addrInfo = addrInfo;
    _addrInfoPtr = _addrInfo.impl()->begin();
    _connectResult = tryConnect();
    checkPendingError();
    return _isConnected;
}

void TcpSocketImpl::endConnect()
{
    log_trace("ending connect");

    if(_pfd && ! _socket.wbuf())
    {
        _pfd->events &= ~POLLOUT;
    }

    checkPendingError();

    if( _isConnected )
        return;

    try
    {
        while (true)
        {
            pollfd pfd;
            pfd.fd = this->fd();
            pfd.revents = 0;
            pfd.events = POLLOUT;

            log_debug("wait " << timeout() << " ms");
            bool avail = this->wait(this->timeout(), pfd);

            if (avail)
            {
                // something has happened
                int sockerr = checkConnect();
                if (_isConnected)
                    return;

                if (++_addrInfoPtr == _addrInfo.impl()->end())
                {
                    // no more addrInfo - propagate error
                    throw IOError(connectFailedMessage(_addrInfo, sockerr));
                }
            }
            else if (++_addrInfoPtr == _addrInfo.impl()->end())
            {
                log_debug("timeout");
                throw IOTimeout();
            }

            close();

            _connectResult = tryConnect();
            if (_isConnected)
                return;
            checkPendingError();
        }
    }
    catch(...)
    {
        close();
        throw;
    }
}

void TcpSocketImpl::accept(const TcpServer& server, unsigned flags)
{
    socklen_t peeraddr_len = sizeof(_peeraddr);

    _fd = server.impl().accept(flags, reinterpret_cast <struct sockaddr*>(&_peeraddr), peeraddr_len);

    if( _fd < 0 )
        throw SystemError("accept");

#ifdef HAVE_ACCEPT4
    IODeviceImpl::open(_fd, false, false);
#else
    bool inherit = (flags & TcpSocket::INHERIT) != 0;
    IODeviceImpl::open(_fd, true, inherit);
#endif
    //TODO ECONNABORTED EINTR EPERM

    _isConnected = true;
    log_debug( "accepted from " << getPeerAddr());
}

void TcpSocketImpl::initWait(pollfd& pfd)
{
    IODeviceImpl::initWait(pfd);

    if( ! _isConnected )
    {
        log_debug("not connected, setting POLLOUT ");
        pfd.events = POLLOUT;
    }
}

bool TcpSocketImpl::checkPollEvent(pollfd& pfd)
{
    log_debug("checkPollEvent " << pfd.revents);

    if( _isConnected )
    {
        // check for error while neither reading nor writing
        //
        // if reading or writing, IODeviceImpl::checkPollEvent will emit
        // inputReady or outputReady signal and the user gets an exception in
        // endRead or endWrite.
        if ( !_device.reading() && !_device.writing()
            && (pfd.revents & POLLERR) )
        {
            _device.close();
            _socket.closed(_socket);
            return true;
        }

        return IODeviceImpl::checkPollEvent(pfd);
    }

    if ( pfd.revents & POLLERR )
    {
        AddrInfoImpl::const_iterator ptr = _addrInfoPtr;
        if (++ptr == _addrInfo.impl()->end())
        {
            // not really connected but error
            // end of addrinfo list means that no working addrinfo was found
            log_debug("no more addrinfos found");
            _socket.connected(_socket);
            return true;
        }
        else
        {
            _addrInfoPtr = ptr;

            close();
            _connectResult = tryConnect();

            if (_isConnected || !_connectResult.empty())
            {
                // immediate success or error
                log_debug("connected successfully");
                _socket.connected(_socket);
            }
            else
            {
                // by closing the previous file handle _pfd is set to 0.
                // creating a new socket in tryConnect may also change the value of fd.
                initializePoll(&pfd, 1);
            }

            return true;
        }
    }
    else if( pfd.revents & POLLOUT )
    {
        int sockerr = checkConnect();
        if (_isConnected)
        {
            _socket.connected(_socket);
            return true;
        }

        // something went wrong - look for next addrInfo
        log_debug("sockerr is " << sockerr << " try next");
        if (++_addrInfoPtr == _addrInfo.impl()->end())
        {
            // no more addrInfo - propagate error
            _connectResult = connectFailedMessage(_addrInfo, sockerr);
            _socket.connected(_socket);
            return true;
        }

        _connectResult = tryConnect();
        if (_isConnected)
        {
            _socket.connected(_socket);
            return true;
        }
    }

    return false;
}

size_t TcpSocketImpl::beginWrite(const char* buffer, size_t n)
{
    log_debug("::send(" << _fd << ", buffer, " << n << ')');

#if defined(HAVE_MSG_NOSIGNAL)

    ssize_t ret = ::send(_fd, (const void*)buffer, n, MSG_NOSIGNAL);

#elif defined(HAVE_SO_NOSIGPIPE)

    ssize_t ret = ::send(_fd, (const void*)buffer, n, 0);

#else

    // block SIGPIPE
    sigset_t sigpipeMask, oldSigmask;
    sigemptyset(&sigpipeMask);
    sigaddset(&sigpipeMask, SIGPIPE);
    pthread_sigmask(SIG_BLOCK, &sigpipeMask, &oldSigmask);

    // execute send
    ssize_t ret = ::send(_fd, (const void*)buffer, n, 0);

    // clear possible SIGPIPE
    sigset_t pending;
    sigemptyset(&pending);
    sigpending(&pending);
    if (sigismember(&pending, SIGPIPE))
    {
      static const struct timespec nowait = { 0, 0 };
      while (sigtimedwait(&sigpipeMask, 0, &nowait) == -1 && errno == EINTR)
        ;
    }

    // unblock SIGPIPE
    pthread_sigmask(SIG_SETMASK, &oldSigmask, 0);

#endif

    log_debug("send returned " << ret);
    if (ret > 0)
        return static_cast<size_t>(ret);

    if (ret == 0 || errno == ECONNRESET || errno == EPIPE)
        throw IOError("lost connection to peer");

    if(_pfd)
    {
        _pfd->events |= POLLOUT;
    }

    return 0;
}

} // namespace net

} // namespace cxxtools
<commit_msg>add missing include for os without inet_ntop like haiku<commit_after>/*
 * Copyright (C) 2009 Marc Boris Duerner, Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#if defined(HAVE_ACCEPT4) || defined(HAVE_SO_NOSIGPIPE) || defined(MSG_NOSIGNAL)
#include <sys/types.h>
#include <sys/socket.h>
#endif

#if !defined(MSG_MSG_NOSIGNAL)
#include <signal.h>
#endif

#include "tcpsocketimpl.h"
#include "tcpserverimpl.h"
#include "cxxtools/net/tcpserver.h"
#include "cxxtools/net/tcpsocket.h"
#include "cxxtools/systemerror.h"
#include "cxxtools/ioerror.h"
#include "cxxtools/log.h"
#include "config.h"
#include "error.h"
#include <cerrno>
#include <cstring>
#include <cassert>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sstream>
#ifndef HAVE_INET_NTOP
#include "cxxtools/mutex.h"
#endif

log_define("cxxtools.net.tcpsocket.impl")

namespace cxxtools
{

namespace net
{

namespace
{
    std::string connectFailedMessage(const AddrInfo& ai, int err)
    {
        std::ostringstream msg;
        msg << "failed to connect to host \"" << ai.host() << "\" port " << ai.port()
            << ": " << getErrnoString(err);
        return msg.str();
    }

}

void formatIp(const Sockaddr& sa, std::string& str)
{
#ifdef HAVE_INET_NTOP
#ifdef HAVE_IPV6
      char strbuf[INET6_ADDRSTRLEN + 1];
#else
      char strbuf[INET_ADDRSTRLEN + 1];
#endif

      const char* p = 0;

      switch(sa.sa_in.sin_family)
      {
            case AF_INET:
                  p = inet_ntop(AF_INET, &sa.sa_in.sin_addr, strbuf, sizeof(strbuf));
                  break;
#ifdef HAVE_IPV6
            case AF_INET6:
                  p = inet_ntop(AF_INET6, &sa.sa_in6.sin6_addr,
                        strbuf, sizeof(strbuf));
                  break;
#endif
      }

      str = (p == 0 ? "-" : strbuf);
#else
      static cxxtools::Mutex monitor;
      cxxtools::MutexLock lock(monitor);

      const char* p = inet_ntoa(sa.sa_in.sin_addr);
      if (p)
        str = p;
      else
        str.clear();
#endif
}

std::string getSockAddr(int fd)
{
    Sockaddr addr;

    socklen_t slen = sizeof(addr);
    if (::getsockname(fd, &addr.sa, &slen) < 0)
        throw SystemError("getsockname");

    std::string ret;
    formatIp(addr, ret);
    return ret;
}

TcpSocketImpl::TcpSocketImpl(TcpSocket& socket)
: IODeviceImpl(socket)
, _socket(socket)
, _isConnected(false)
{
}

TcpSocketImpl::~TcpSocketImpl()
{
    assert(_pfd == 0);
}

void TcpSocketImpl::close()
{
    log_debug("close socket " << _fd);
    IODeviceImpl::close();
    _isConnected = false;
}

std::string TcpSocketImpl::getSockAddr() const
{ return net::getSockAddr(fd()); }

std::string TcpSocketImpl::getPeerAddr() const
{
    Sockaddr addr;

    addr.storage = _peeraddr;

    std::string ret;
    formatIp(addr, ret);
    return ret;
}

void TcpSocketImpl::connect(const AddrInfo& addrInfo)
{
    log_debug("connect");
    this->beginConnect(addrInfo);
    this->endConnect();
}

int TcpSocketImpl::checkConnect()
{
    log_trace("checkConnect");

    int sockerr;
    socklen_t optlen = sizeof(sockerr);

    // check for socket error
    if( ::getsockopt(this->fd(), SOL_SOCKET, SO_ERROR, &sockerr, &optlen) != 0 )
    {
        // getsockopt failed
        int e = errno;
        close();
        throw SystemError(e, "getsockopt");
    }

    if (sockerr == 0)
    {
        log_debug("connected successfully to " << getPeerAddr());
        _isConnected = true;
    }

    return sockerr;
}

void TcpSocketImpl::checkPendingError()
{
    if (!_connectResult.empty())
    {
        std::string p = _connectResult;
        _connectResult.clear();
        throw IOError(p);
    }
}

std::string TcpSocketImpl::tryConnect()
{
    log_trace("tryConnect");

    assert(_fd == -1);

    if (_addrInfoPtr == _addrInfo.impl()->end())
    {
        log_debug("no more address informations");
        std::ostringstream msg;
        msg << "invalid address information; host \"" << _addrInfo.host() << "\" port " << _addrInfo.port();
        return msg.str();
    }

    while (true)
    {
        int fd;
        while (true)
        {
            log_debug("create socket");
            fd = ::socket(_addrInfoPtr->ai_family, SOCK_STREAM, 0);
            if (fd >= 0)
                break;

            if (++_addrInfoPtr == _addrInfo.impl()->end())
            {
                std::ostringstream msg;
                msg << "failed to create socket for host \"" << _addrInfo.host()
                    << "\" port " << _addrInfo.port()
                    << ": " << getErrnoString();
                return msg.str();
            }
        }

#ifdef HAVE_SO_NOSIGPIPE
        static const int on = 1;
        if (::setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)) < 0)
            throw cxxtools::SystemError("setsockopt(SO_NOSIGPIPE)");
#endif

        IODeviceImpl::open(fd, true, false);

        std::memmove(&_peeraddr, _addrInfoPtr->ai_addr, _addrInfoPtr->ai_addrlen);

        log_debug("created socket " << _fd << " max: " << FD_SETSIZE);

        if( ::connect(this->fd(), _addrInfoPtr->ai_addr, _addrInfoPtr->ai_addrlen) == 0 )
        {
            _isConnected = true;
            log_debug("connected successfully to " << getPeerAddr());
            break;
        }

        if (errno == EINPROGRESS)
        {
            log_debug("connect in progress");
            break;
        }

        close();
        if (++_addrInfoPtr == _addrInfo.impl()->end())
            return connectFailedMessage(_addrInfo, errno);
    }

    return std::string();
}

bool TcpSocketImpl::beginConnect(const AddrInfo& addrInfo)
{
    log_trace("begin connect");

    assert(!_isConnected);

    _addrInfo = addrInfo;
    _addrInfoPtr = _addrInfo.impl()->begin();
    _connectResult = tryConnect();
    checkPendingError();
    return _isConnected;
}

void TcpSocketImpl::endConnect()
{
    log_trace("ending connect");

    if(_pfd && ! _socket.wbuf())
    {
        _pfd->events &= ~POLLOUT;
    }

    checkPendingError();

    if( _isConnected )
        return;

    try
    {
        while (true)
        {
            pollfd pfd;
            pfd.fd = this->fd();
            pfd.revents = 0;
            pfd.events = POLLOUT;

            log_debug("wait " << timeout() << " ms");
            bool avail = this->wait(this->timeout(), pfd);

            if (avail)
            {
                // something has happened
                int sockerr = checkConnect();
                if (_isConnected)
                    return;

                if (++_addrInfoPtr == _addrInfo.impl()->end())
                {
                    // no more addrInfo - propagate error
                    throw IOError(connectFailedMessage(_addrInfo, sockerr));
                }
            }
            else if (++_addrInfoPtr == _addrInfo.impl()->end())
            {
                log_debug("timeout");
                throw IOTimeout();
            }

            close();

            _connectResult = tryConnect();
            if (_isConnected)
                return;
            checkPendingError();
        }
    }
    catch(...)
    {
        close();
        throw;
    }
}

void TcpSocketImpl::accept(const TcpServer& server, unsigned flags)
{
    socklen_t peeraddr_len = sizeof(_peeraddr);

    _fd = server.impl().accept(flags, reinterpret_cast <struct sockaddr*>(&_peeraddr), peeraddr_len);

    if( _fd < 0 )
        throw SystemError("accept");

#ifdef HAVE_ACCEPT4
    IODeviceImpl::open(_fd, false, false);
#else
    bool inherit = (flags & TcpSocket::INHERIT) != 0;
    IODeviceImpl::open(_fd, true, inherit);
#endif
    //TODO ECONNABORTED EINTR EPERM

    _isConnected = true;
    log_debug( "accepted from " << getPeerAddr());
}

void TcpSocketImpl::initWait(pollfd& pfd)
{
    IODeviceImpl::initWait(pfd);

    if( ! _isConnected )
    {
        log_debug("not connected, setting POLLOUT ");
        pfd.events = POLLOUT;
    }
}

bool TcpSocketImpl::checkPollEvent(pollfd& pfd)
{
    log_debug("checkPollEvent " << pfd.revents);

    if( _isConnected )
    {
        // check for error while neither reading nor writing
        //
        // if reading or writing, IODeviceImpl::checkPollEvent will emit
        // inputReady or outputReady signal and the user gets an exception in
        // endRead or endWrite.
        if ( !_device.reading() && !_device.writing()
            && (pfd.revents & POLLERR) )
        {
            _device.close();
            _socket.closed(_socket);
            return true;
        }

        return IODeviceImpl::checkPollEvent(pfd);
    }

    if ( pfd.revents & POLLERR )
    {
        AddrInfoImpl::const_iterator ptr = _addrInfoPtr;
        if (++ptr == _addrInfo.impl()->end())
        {
            // not really connected but error
            // end of addrinfo list means that no working addrinfo was found
            log_debug("no more addrinfos found");
            _socket.connected(_socket);
            return true;
        }
        else
        {
            _addrInfoPtr = ptr;

            close();
            _connectResult = tryConnect();

            if (_isConnected || !_connectResult.empty())
            {
                // immediate success or error
                log_debug("connected successfully");
                _socket.connected(_socket);
            }
            else
            {
                // by closing the previous file handle _pfd is set to 0.
                // creating a new socket in tryConnect may also change the value of fd.
                initializePoll(&pfd, 1);
            }

            return true;
        }
    }
    else if( pfd.revents & POLLOUT )
    {
        int sockerr = checkConnect();
        if (_isConnected)
        {
            _socket.connected(_socket);
            return true;
        }

        // something went wrong - look for next addrInfo
        log_debug("sockerr is " << sockerr << " try next");
        if (++_addrInfoPtr == _addrInfo.impl()->end())
        {
            // no more addrInfo - propagate error
            _connectResult = connectFailedMessage(_addrInfo, sockerr);
            _socket.connected(_socket);
            return true;
        }

        _connectResult = tryConnect();
        if (_isConnected)
        {
            _socket.connected(_socket);
            return true;
        }
    }

    return false;
}

size_t TcpSocketImpl::beginWrite(const char* buffer, size_t n)
{
    log_debug("::send(" << _fd << ", buffer, " << n << ')');

#if defined(HAVE_MSG_NOSIGNAL)

    ssize_t ret = ::send(_fd, (const void*)buffer, n, MSG_NOSIGNAL);

#elif defined(HAVE_SO_NOSIGPIPE)

    ssize_t ret = ::send(_fd, (const void*)buffer, n, 0);

#else

    // block SIGPIPE
    sigset_t sigpipeMask, oldSigmask;
    sigemptyset(&sigpipeMask);
    sigaddset(&sigpipeMask, SIGPIPE);
    pthread_sigmask(SIG_BLOCK, &sigpipeMask, &oldSigmask);

    // execute send
    ssize_t ret = ::send(_fd, (const void*)buffer, n, 0);

    // clear possible SIGPIPE
    sigset_t pending;
    sigemptyset(&pending);
    sigpending(&pending);
    if (sigismember(&pending, SIGPIPE))
    {
      static const struct timespec nowait = { 0, 0 };
      while (sigtimedwait(&sigpipeMask, 0, &nowait) == -1 && errno == EINTR)
        ;
    }

    // unblock SIGPIPE
    pthread_sigmask(SIG_SETMASK, &oldSigmask, 0);

#endif

    log_debug("send returned " << ret);
    if (ret > 0)
        return static_cast<size_t>(ret);

    if (ret == 0 || errno == ECONNRESET || errno == EPIPE)
        throw IOError("lost connection to peer");

    if(_pfd)
    {
        _pfd->events |= POLLOUT;
    }

    return 0;
}

} // namespace net

} // namespace cxxtools
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Name:      test-lexers.cpp
// Purpose:   Implementation for wxExtension cpp unit testing
// Author:    Anton van Wezenbeek
// Copyright: (c) 2015 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/extension/lexers.h>
#include <wx/extension/managedframe.h>
#include <wx/extension/stc.h>
#include "test.h"

void fixture::testLexers()
{
  wxExSTC* stc = new wxExSTC(m_Frame, "hello stc");

  CPPUNIT_ASSERT( wxExLexers::Get() != NULL);
  CPPUNIT_ASSERT( wxExLexers::Get()->GetCount() > 0);
  CPPUNIT_ASSERT( wxExLexers::Get()->GetDefaultStyle().ContainsDefaultStyle());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetDefaultStyle().IsOk());

  // Test lexer and global macros.
  for (const auto& macro : std::vector<
    std::pair<
      std::pair<std::string,std::string>,
      std::string>> {
    {{"number","asm"},"2"},
    {{"number","cpp"},"4"},
    {{"XXX","global"},"XXX"},
    {{"mark_lcorner","global"},"10"},
    {{"mark_circle","global"},"0"},
    {{"iv_none","global"},"0"}})
  {
    CPPUNIT_ASSERT( wxExLexers::Get()->ApplyMacro(
      macro.first.first, macro.first.second) == macro.second);
  }

  // At this moment we have no global properties.
  CPPUNIT_ASSERT( wxExLexers::Get()->GetProperties().empty());

  wxExLexers::Get()->ApplyMarkers(stc);
  wxExLexers::Get()->ApplyProperties(stc);

  CPPUNIT_ASSERT(!wxExLexers::Get()->BuildWildCards(  GetTestFile()).empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetCount() > 0);

  CPPUNIT_ASSERT( wxExLexers::Get()->FindByFileName(
    GetTestFile()).GetScintillaLexer() == "cpp");

  CPPUNIT_ASSERT( wxExLexers::Get()->FindByName(
    "xxx").GetScintillaLexer().empty());

  CPPUNIT_ASSERT( wxExLexers::Get()->FindByName(
    "cpp").GetScintillaLexer() == "cpp");

  for (const auto& findby : std::vector<std::pair<
    std::string,
    std::pair<std::string, std::string>>> {
    {"// this is a cpp comment text",{"cpp","cpp"}},
    {"#!/bin/sh",{"bash","sh"}},
    {"#!/bin/csh",{"bash","csh"}},
    {"#!/bin/tcsh",{"bash","tcsh"}},
    {"#!/bin/bash",{"bash","bash"}},
    {"#!/bin/bash\n",{"bash","bash"}},
    {"#!/usr/bin/csh",{"bash","bash"}},
    {"<html>",{"hypertext","hypertext"}},
    {"<?xml",{"hypertext","xml"}}})
  {
    CPPUNIT_ASSERT( wxExLexers::Get()->FindByText(
      findby.first).GetScintillaLexer() == findby.second.first);
    CPPUNIT_ASSERT( wxExLexers::Get()->FindByText(
      findby.first).GetDisplayLexer() == findby.second.second);
  }

  CPPUNIT_ASSERT( wxExLexers::Get()->GetFileName().IsOk());

  CPPUNIT_ASSERT(!wxExLexers::Get()->GetMacros("global").empty());
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetMacros("cpp").empty());
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetMacros("pascal").empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetMacros("XXX").empty());

  CPPUNIT_ASSERT(!wxExLexers::Get()->GetTheme().empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetThemeOk());
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetThemeMacros().empty());
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetThemes() > 1);

  CPPUNIT_ASSERT(!wxExLexers::Get()->SetTheme("xxx"));
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetTheme().empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetThemeOk());
  CPPUNIT_ASSERT( wxExLexers::Get()->SetTheme("torte"));
  CPPUNIT_ASSERT( wxExLexers::Get()->GetTheme() == "torte");
  CPPUNIT_ASSERT( wxExLexers::Get()->GetThemeOk());
  wxExLexers::Get()->SetThemeNone();
  CPPUNIT_ASSERT( wxExLexers::Get()->GetTheme().empty());
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetThemeOk());
  wxExLexers::Get()->RestoreTheme();
  CPPUNIT_ASSERT( wxExLexers::Get()->GetTheme() == "torte");
  CPPUNIT_ASSERT( wxExLexers::Get()->GetThemeOk());

  CPPUNIT_ASSERT(!wxExLexers::Get()->IndicatorIsLoaded(wxExIndicator(99, -1)));
  CPPUNIT_ASSERT( wxExLexers::Get()->IndicatorIsLoaded(wxExIndicator(0, -1)));
  CPPUNIT_ASSERT( wxExLexers::Get()->MarkerIsLoaded(wxExMarker(0, -1)));

  wxString lexer("cpp");
  wxExLexers::Get()->ShowDialog(m_Frame, lexer, wxEmptyString, false);
  wxExLexers::Get()->ShowThemeDialog(m_Frame, wxEmptyString, false);

  CPPUNIT_ASSERT(!wxExLexers::Get()->GetKeywords("cpp").empty());
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetKeywords("csh").empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetKeywords("xxx").empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetKeywords(wxEmptyString).empty());

  CPPUNIT_ASSERT( wxExLexers::Get()->LoadDocument());
}
<commit_msg>fixed test<commit_after>////////////////////////////////////////////////////////////////////////////////
// Name:      test-lexers.cpp
// Purpose:   Implementation for wxExtension cpp unit testing
// Author:    Anton van Wezenbeek
// Copyright: (c) 2015 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/extension/lexers.h>
#include <wx/extension/managedframe.h>
#include <wx/extension/stc.h>
#include "test.h"

void fixture::testLexers()
{
  wxExSTC* stc = new wxExSTC(m_Frame, "hello stc");

  CPPUNIT_ASSERT( wxExLexers::Get() != NULL);
  CPPUNIT_ASSERT( wxExLexers::Get()->GetCount() > 0);
  CPPUNIT_ASSERT( wxExLexers::Get()->GetDefaultStyle().ContainsDefaultStyle());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetDefaultStyle().IsOk());

  // Test lexer and global macros.
  for (const auto& macro : std::vector<
    std::pair<
      std::pair<std::string,std::string>,
      std::string>> {
    {{"number","asm"},"2"},
    {{"number","cpp"},"4"},
    {{"XXX","global"},"XXX"},
    {{"mark_lcorner","global"},"10"},
    {{"mark_circle","global"},"0"},
    {{"iv_none","global"},"0"}})
  {
    CPPUNIT_ASSERT( wxExLexers::Get()->ApplyMacro(
      macro.first.first, macro.first.second) == macro.second);
  }

  // At this moment we have no global properties.
  CPPUNIT_ASSERT( wxExLexers::Get()->GetProperties().empty());

  wxExLexers::Get()->ApplyMarkers(stc);
  wxExLexers::Get()->ApplyProperties(stc);

  CPPUNIT_ASSERT(!wxExLexers::Get()->BuildWildCards(  GetTestFile()).empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetCount() > 0);

  CPPUNIT_ASSERT( wxExLexers::Get()->FindByFileName(
    GetTestFile()).GetScintillaLexer() == "cpp");

  CPPUNIT_ASSERT( wxExLexers::Get()->FindByName(
    "xxx").GetScintillaLexer().empty());

  CPPUNIT_ASSERT( wxExLexers::Get()->FindByName(
    "cpp").GetScintillaLexer() == "cpp");

  for (const auto& findby : std::vector<std::pair<
    std::string,
    std::pair<std::string, std::string>>> {
    {"// this is a cpp comment text",{"cpp","cpp"}},
    {"#!/bin/sh",{"bash","sh"}},
    {"#!/bin/csh",{"bash","csh"}},
    {"#!/bin/tcsh",{"bash","tcsh"}},
    {"#!/bin/bash",{"bash","bash"}},
    {"#!/bin/bash\n",{"bash","bash"}},
    {"#!/usr/bin/csh",{"bash","bash"}},
    {"<html>",{"hypertext","hypertext"}},
    {"<?xml",{"hypertext","xml"}}})
  {
    CPPUNIT_ASSERT( wxExLexers::Get()->FindByText(
      findby.first).GetScintillaLexer() == findby.second.first);
    CPPUNIT_ASSERT( wxExLexers::Get()->FindByText(
      findby.first).GetDisplayLexer() == findby.second.second);
  }

  CPPUNIT_ASSERT( wxExLexers::Get()->GetFileName().IsOk());

  CPPUNIT_ASSERT(!wxExLexers::Get()->GetMacros("global").empty());
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetMacros("cpp").empty());
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetMacros("pascal").empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetMacros("XXX").empty());

  CPPUNIT_ASSERT(!wxExLexers::Get()->GetTheme().empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetThemeOk());
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetThemeMacros().empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetThemes() > 1);

  CPPUNIT_ASSERT(!wxExLexers::Get()->SetTheme("xxx"));
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetTheme().empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetThemeOk());
  CPPUNIT_ASSERT( wxExLexers::Get()->SetTheme("torte"));
  CPPUNIT_ASSERT( wxExLexers::Get()->GetTheme() == "torte");
  CPPUNIT_ASSERT( wxExLexers::Get()->GetThemeOk());
  wxExLexers::Get()->SetThemeNone();
  CPPUNIT_ASSERT( wxExLexers::Get()->GetTheme().empty());
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetThemeOk());
  wxExLexers::Get()->RestoreTheme();
  CPPUNIT_ASSERT( wxExLexers::Get()->GetTheme() == "torte");
  CPPUNIT_ASSERT( wxExLexers::Get()->GetThemeOk());

  CPPUNIT_ASSERT(!wxExLexers::Get()->IndicatorIsLoaded(wxExIndicator(99, -1)));
  CPPUNIT_ASSERT( wxExLexers::Get()->IndicatorIsLoaded(wxExIndicator(0, -1)));
  CPPUNIT_ASSERT( wxExLexers::Get()->MarkerIsLoaded(wxExMarker(0, -1)));

  wxString lexer("cpp");
  wxExLexers::Get()->ShowDialog(m_Frame, lexer, wxEmptyString, false);
  wxExLexers::Get()->ShowThemeDialog(m_Frame, wxEmptyString, false);

  CPPUNIT_ASSERT(!wxExLexers::Get()->GetKeywords("cpp").empty());
  CPPUNIT_ASSERT(!wxExLexers::Get()->GetKeywords("csh").empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetKeywords("xxx").empty());
  CPPUNIT_ASSERT( wxExLexers::Get()->GetKeywords(wxEmptyString).empty());

  CPPUNIT_ASSERT( wxExLexers::Get()->LoadDocument());
}
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkComputeContourSetNormalsFilter.h"

#include "mitkImagePixelReadAccessor.h"
#include "mitkIOUtil.h"

mitk::ComputeContourSetNormalsFilter::ComputeContourSetNormalsFilter()
  : m_SegmentationBinaryImage(NULL)
  , m_MaxSpacing(5)
  , m_NegativeNormalCounter(0)
  , m_PositiveNormalCounter(0)
  , m_UseProgressBar(false)
  , m_ProgressStepSize(1)
{
  mitk::Surface::Pointer output = mitk::Surface::New();
  this->SetNthOutput(0, output.GetPointer());
}

mitk::ComputeContourSetNormalsFilter::~ComputeContourSetNormalsFilter()
{
}

void mitk::ComputeContourSetNormalsFilter::GenerateData()
{
  unsigned int numberOfInputs = this->GetNumberOfIndexedInputs();
  this->CreateOutputsForAllInputs(numberOfInputs);

  //Iterating over each input
  for(unsigned int i = 0; i < numberOfInputs; i++)
  {
    //Getting the inputs polydata and polygons
    Surface* currentSurface = const_cast<Surface*>( this->GetInput(i) );
    vtkPolyData* polyData = currentSurface->GetVtkPolyData();

    vtkSmartPointer<vtkCellArray> existingPolys = polyData->GetPolys();

    vtkSmartPointer<vtkPoints> existingPoints = polyData->GetPoints();

    existingPolys->InitTraversal();

    vtkIdType* cell (NULL);
    vtkIdType cellSize (0);

    //The array that contains all the vertex normals of the current polygon
    vtkSmartPointer<vtkDoubleArray> normals = vtkSmartPointer<vtkDoubleArray>::New();
    normals->SetNumberOfComponents(3);
    normals->SetNumberOfTuples(polyData->GetNumberOfPoints());

    //If the current contour is an inner contour then the direction is -1
    //A contour lies inside another one if the pixel values in the direction of the normal is 1
    m_NegativeNormalCounter = 0;
    m_PositiveNormalCounter = 0;
    vtkIdType offSet (0);

    //Iterating over each polygon
    for( existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
    {
      if(cellSize < 3)continue;

      //First we calculate the current polygon's normal
      double polygonNormal[3] = {0.0};

      double p1[3];
      double p2[3];

      double v1[3];
      double v2[3];

      existingPoints->GetPoint(cell[0], p1);
      unsigned int index = cellSize*0.5;
      existingPoints->GetPoint(cell[index], p2);

      v1[0] = p2[0]-p1[0];
      v1[1] = p2[1]-p1[1];
      v1[2] = p2[2]-p1[2];

      for (vtkIdType k = 2; k < cellSize; k++)
      {
        index = cellSize*0.25;
        existingPoints->GetPoint(cell[index], p1);
        index = cellSize*0.75;
        existingPoints->GetPoint(cell[index], p2);

        v2[0] = p2[0]-p1[0];
        v2[1] = p2[1]-p1[1];
        v2[2] = p2[2]-p1[2];

        vtkMath::Cross(v1,v2,polygonNormal);
        if (vtkMath::Norm(polygonNormal) != 0)
          break;
      }

      vtkMath::Normalize(polygonNormal);

      //Now we start computing the normal for each vertex

      double vertexNormalTemp[3];
      existingPoints->GetPoint(cell[0], p1);
      existingPoints->GetPoint(cell[1], p2);

      v1[0] = p2[0]-p1[0];
      v1[1] = p2[1]-p1[1];
      v1[2] = p2[2]-p1[2];

      vtkMath::Cross(v1,polygonNormal,vertexNormalTemp);

      vtkMath::Normalize(vertexNormalTemp);

      double vertexNormal[3];

      for (vtkIdType j = 0; j < cellSize-2; j++)
      {
        existingPoints->GetPoint(cell[j+1], p1);
        existingPoints->GetPoint(cell[j+2], p2);

        v1[0] = p2[0]-p1[0];
        v1[1] = p2[1]-p1[1];
        v1[2] = p2[2]-p1[2];

        vtkMath::Cross(v1,polygonNormal,vertexNormal);

        vtkMath::Normalize(vertexNormal);

        double finalNormal[3];

        finalNormal[0] = (vertexNormal[0] + vertexNormalTemp[0])*0.5;
        finalNormal[1] = (vertexNormal[1] + vertexNormalTemp[1])*0.5;
        finalNormal[2] = (vertexNormal[2] + vertexNormalTemp[2])*0.5;

        //Here we determine the direction of the normal
        if (m_SegmentationBinaryImage)
        {
          Point3D worldCoord;
          worldCoord[0] = p1[0]+finalNormal[0]*m_MaxSpacing;
          worldCoord[1] = p1[1]+finalNormal[1]*m_MaxSpacing;
          worldCoord[2] = p1[2]+finalNormal[2]*m_MaxSpacing;

          std::cout << "World coords: " << worldCoord[0] << " , " << worldCoord[1] << " , " << worldCoord[2] << std::endl;
          std::cout << "...for point: " << p1[0] << " , " << p1[1] << " , " << p1[2] << std::endl;
          std::cout << "...and normal: " << finalNormal[0] << " , " << finalNormal[1] << " , " << finalNormal[2] << std::endl;
          std::cout << "MaxSpacing: " << m_MaxSpacing << std::endl;

          double val = 0.0;

          mitk::ImagePixelReadAccessor<unsigned char> readAccess(m_SegmentationBinaryImage);
          itk::Index<3> idx;
          m_SegmentationBinaryImage->GetGeometry()->WorldToIndex(worldCoord, idx);
          try
          {
            val = readAccess.GetPixelByIndexSafe(idx);
          }
          catch (mitk::Exception e)
          {
            // If value is outside the image's region ignore it
          }

          if (val == 0.0)
          {
              //MITK_INFO << "val equals zero.";
              ++m_PositiveNormalCounter;
          }
          else
          {
            //MITK_INFO << "val does not equal zero.";
              ++m_NegativeNormalCounter;
          }
        }

        vertexNormalTemp[0] = vertexNormal[0];
        vertexNormalTemp[1] = vertexNormal[1];
        vertexNormalTemp[2] = vertexNormal[2];

        vtkIdType id = cell[j+1];
        normals->SetTuple(id,finalNormal);
      }

      existingPoints->GetPoint(cell[0], p1);
      existingPoints->GetPoint(cell[1], p2);

      v1[0] = p2[0]-p1[0];
      v1[1] = p2[1]-p1[1];
      v1[2] = p2[2]-p1[2];

      vtkMath::Cross(v1,polygonNormal,vertexNormal);

      vtkMath::Normalize(vertexNormal);

      vertexNormal[0] = (vertexNormal[0] + vertexNormalTemp[0])*0.5;
      vertexNormal[1] = (vertexNormal[1] + vertexNormalTemp[1])*0.5;
      vertexNormal[2] = (vertexNormal[2] + vertexNormalTemp[2])*0.5;

      vtkIdType id = cell[0];
      normals->SetTuple(id,vertexNormal);
      id = cell[cellSize-1];
      normals->SetTuple(id,vertexNormal);

      std::cout << "Negative normal counter: " << m_NegativeNormalCounter << std::endl;
      std::cout << "Positive normal counter: " << m_PositiveNormalCounter << std::endl;

      if(m_NegativeNormalCounter > m_PositiveNormalCounter)
      {
          for(vtkIdType n = 0; n < cellSize; n++)
          {
              double normal[3];
              normals->GetTuple(offSet+n, normal);
              normal[0] = (-1)*normal[0];
              normal[1] = (-1)*normal[1];
              normal[2] = (-1)*normal[2];
              normals->SetTuple(offSet+n, normal);
          }
      }

      m_NegativeNormalCounter = 0;
      m_PositiveNormalCounter = 0;
      offSet += cellSize;

    }//end for all cells

    Surface::Pointer surface = this->GetOutput(i);
    surface->GetVtkPolyData()->GetCellData()->SetNormals(normals);
  }//end for all inputs

  //Setting progressbar
  if (this->m_UseProgressBar)
    mitk::ProgressBar::GetInstance()->Progress(this->m_ProgressStepSize);
}

mitk::Surface::Pointer mitk::ComputeContourSetNormalsFilter::GetNormalsAsSurface()
{
  //Just for debugging:
  vtkSmartPointer<vtkPolyData> newPolyData = vtkSmartPointer<vtkPolyData>::New();
  vtkSmartPointer<vtkCellArray> newLines = vtkSmartPointer<vtkCellArray>::New();
  vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New();
  unsigned int idCounter (0);
  //Debug end

  for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs(); i++)
  {
    Surface* currentSurface = const_cast<Surface*>( this->GetOutput(i) );
    vtkPolyData* polyData = currentSurface->GetVtkPolyData();

    vtkSmartPointer<vtkDoubleArray> currentCellNormals = vtkDoubleArray::SafeDownCast(polyData->GetCellData()->GetNormals());

    vtkSmartPointer<vtkCellArray> existingPolys = polyData->GetPolys();

    vtkSmartPointer<vtkPoints> existingPoints = polyData->GetPoints();

    existingPolys->InitTraversal();

    vtkIdType* cell (NULL);
    vtkIdType cellSize (0);

    for( existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
    {
      for ( vtkIdType j = 0; j < cellSize; j++ )
      {
        double currentNormal[3];
        currentCellNormals->GetTuple(cell[j], currentNormal);
        vtkSmartPointer<vtkLine> line = vtkSmartPointer<vtkLine>::New();
        line->GetPointIds()->SetNumberOfIds(2);
        double newPoint[3];
        double p0[3];
        existingPoints->GetPoint(cell[j], p0);
        newPoint[0] = p0[0] + currentNormal[0];
        newPoint[1] = p0[1] + currentNormal[1];
        newPoint[2] = p0[2] + currentNormal[2];

        line->GetPointIds()->SetId(0, idCounter);
        newPoints->InsertPoint(idCounter, p0);
        idCounter++;

        line->GetPointIds()->SetId(1, idCounter);
        newPoints->InsertPoint(idCounter, newPoint);
        idCounter++;

        newLines->InsertNextCell(line);
      }//end for all points
    }//end for all cells
  }//end for all outputs

  newPolyData->SetPoints(newPoints);
  newPolyData->SetLines(newLines);
  newPolyData->BuildCells();

  mitk::Surface::Pointer surface = mitk::Surface::New();
  surface->SetVtkPolyData(newPolyData);

  return surface;

}

void mitk::ComputeContourSetNormalsFilter::SetMaxSpacing(double maxSpacing)
{
    m_MaxSpacing = maxSpacing;
}

void mitk::ComputeContourSetNormalsFilter::GenerateOutputInformation()
{
  Superclass::GenerateOutputInformation();
}

void mitk::ComputeContourSetNormalsFilter::Reset()
{
  for (unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); i++)
  {
    this->PopBackInput();
  }
  this->SetNumberOfIndexedInputs(0);
  this->SetNumberOfIndexedOutputs(0);

  mitk::Surface::Pointer output = mitk::Surface::New();
  this->SetNthOutput(0, output.GetPointer());
}

void mitk::ComputeContourSetNormalsFilter::SetUseProgressBar(bool status)
{
  this->m_UseProgressBar = status;
}

void mitk::ComputeContourSetNormalsFilter::SetProgressStepSize(unsigned int stepSize)
{
  this->m_ProgressStepSize = stepSize;
}
<commit_msg>Cleanup.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkComputeContourSetNormalsFilter.h"

#include "mitkImagePixelReadAccessor.h"
#include "mitkIOUtil.h"

mitk::ComputeContourSetNormalsFilter::ComputeContourSetNormalsFilter()
  : m_SegmentationBinaryImage(NULL)
  , m_MaxSpacing(5)
  , m_NegativeNormalCounter(0)
  , m_PositiveNormalCounter(0)
  , m_UseProgressBar(false)
  , m_ProgressStepSize(1)
{
  mitk::Surface::Pointer output = mitk::Surface::New();
  this->SetNthOutput(0, output.GetPointer());
}

mitk::ComputeContourSetNormalsFilter::~ComputeContourSetNormalsFilter()
{
}

void mitk::ComputeContourSetNormalsFilter::GenerateData()
{
  unsigned int numberOfInputs = this->GetNumberOfIndexedInputs();
  this->CreateOutputsForAllInputs(numberOfInputs);

  //Iterating over each input
  for(unsigned int i = 0; i < numberOfInputs; i++)
  {
    //Getting the inputs polydata and polygons
    Surface* currentSurface = const_cast<Surface*>( this->GetInput(i) );
    vtkPolyData* polyData = currentSurface->GetVtkPolyData();

    vtkSmartPointer<vtkCellArray> existingPolys = polyData->GetPolys();

    vtkSmartPointer<vtkPoints> existingPoints = polyData->GetPoints();

    existingPolys->InitTraversal();

    vtkIdType* cell (NULL);
    vtkIdType cellSize (0);

    //The array that contains all the vertex normals of the current polygon
    vtkSmartPointer<vtkDoubleArray> normals = vtkSmartPointer<vtkDoubleArray>::New();
    normals->SetNumberOfComponents(3);
    normals->SetNumberOfTuples(polyData->GetNumberOfPoints());

    //If the current contour is an inner contour then the direction is -1
    //A contour lies inside another one if the pixel values in the direction of the normal is 1
    m_NegativeNormalCounter = 0;
    m_PositiveNormalCounter = 0;
    vtkIdType offSet (0);

    //Iterating over each polygon
    for( existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
    {
      if(cellSize < 3)continue;

      //First we calculate the current polygon's normal
      double polygonNormal[3] = {0.0};

      double p1[3];
      double p2[3];

      double v1[3];
      double v2[3];

      existingPoints->GetPoint(cell[0], p1);
      unsigned int index = cellSize*0.5;
      existingPoints->GetPoint(cell[index], p2);

      v1[0] = p2[0]-p1[0];
      v1[1] = p2[1]-p1[1];
      v1[2] = p2[2]-p1[2];

      for (vtkIdType k = 2; k < cellSize; k++)
      {
        index = cellSize*0.25;
        existingPoints->GetPoint(cell[index], p1);
        index = cellSize*0.75;
        existingPoints->GetPoint(cell[index], p2);

        v2[0] = p2[0]-p1[0];
        v2[1] = p2[1]-p1[1];
        v2[2] = p2[2]-p1[2];

        vtkMath::Cross(v1,v2,polygonNormal);
        if (vtkMath::Norm(polygonNormal) != 0)
          break;
      }

      vtkMath::Normalize(polygonNormal);

      //Now we start computing the normal for each vertex

      double vertexNormalTemp[3];
      existingPoints->GetPoint(cell[0], p1);
      existingPoints->GetPoint(cell[1], p2);

      v1[0] = p2[0]-p1[0];
      v1[1] = p2[1]-p1[1];
      v1[2] = p2[2]-p1[2];

      vtkMath::Cross(v1,polygonNormal,vertexNormalTemp);

      vtkMath::Normalize(vertexNormalTemp);

      double vertexNormal[3];

      for (vtkIdType j = 0; j < cellSize-2; j++)
      {
        existingPoints->GetPoint(cell[j+1], p1);
        existingPoints->GetPoint(cell[j+2], p2);

        v1[0] = p2[0]-p1[0];
        v1[1] = p2[1]-p1[1];
        v1[2] = p2[2]-p1[2];

        vtkMath::Cross(v1,polygonNormal,vertexNormal);

        vtkMath::Normalize(vertexNormal);

        double finalNormal[3];

        finalNormal[0] = (vertexNormal[0] + vertexNormalTemp[0])*0.5;
        finalNormal[1] = (vertexNormal[1] + vertexNormalTemp[1])*0.5;
        finalNormal[2] = (vertexNormal[2] + vertexNormalTemp[2])*0.5;

        //Here we determine the direction of the normal
        if (m_SegmentationBinaryImage)
        {
          Point3D worldCoord;
          worldCoord[0] = p1[0]+finalNormal[0]*m_MaxSpacing;
          worldCoord[1] = p1[1]+finalNormal[1]*m_MaxSpacing;
          worldCoord[2] = p1[2]+finalNormal[2]*m_MaxSpacing;

          double val = 0.0;

          mitk::ImagePixelReadAccessor<unsigned char> readAccess(m_SegmentationBinaryImage);
          itk::Index<3> idx;
          m_SegmentationBinaryImage->GetGeometry()->WorldToIndex(worldCoord, idx);
          try
          {
            val = readAccess.GetPixelByIndexSafe(idx);
          }
          catch (mitk::Exception e)
          {
            // If value is outside the image's region ignore it
          }

          if (val == 0.0)
          {
              //MITK_INFO << "val equals zero.";
              ++m_PositiveNormalCounter;
          }
          else
          {
            //MITK_INFO << "val does not equal zero.";
              ++m_NegativeNormalCounter;
          }
        }

        vertexNormalTemp[0] = vertexNormal[0];
        vertexNormalTemp[1] = vertexNormal[1];
        vertexNormalTemp[2] = vertexNormal[2];

        vtkIdType id = cell[j+1];
        normals->SetTuple(id,finalNormal);
      }

      existingPoints->GetPoint(cell[0], p1);
      existingPoints->GetPoint(cell[1], p2);

      v1[0] = p2[0]-p1[0];
      v1[1] = p2[1]-p1[1];
      v1[2] = p2[2]-p1[2];

      vtkMath::Cross(v1,polygonNormal,vertexNormal);

      vtkMath::Normalize(vertexNormal);

      vertexNormal[0] = (vertexNormal[0] + vertexNormalTemp[0])*0.5;
      vertexNormal[1] = (vertexNormal[1] + vertexNormalTemp[1])*0.5;
      vertexNormal[2] = (vertexNormal[2] + vertexNormalTemp[2])*0.5;

      vtkIdType id = cell[0];
      normals->SetTuple(id,vertexNormal);
      id = cell[cellSize-1];
      normals->SetTuple(id,vertexNormal);

      if(m_NegativeNormalCounter > m_PositiveNormalCounter)
      {
          for(vtkIdType n = 0; n < cellSize; n++)
          {
              double normal[3];
              normals->GetTuple(offSet+n, normal);
              normal[0] = (-1)*normal[0];
              normal[1] = (-1)*normal[1];
              normal[2] = (-1)*normal[2];
              normals->SetTuple(offSet+n, normal);
          }
      }

      m_NegativeNormalCounter = 0;
      m_PositiveNormalCounter = 0;
      offSet += cellSize;

    }//end for all cells

    Surface::Pointer surface = this->GetOutput(i);
    surface->GetVtkPolyData()->GetCellData()->SetNormals(normals);
  }//end for all inputs

  //Setting progressbar
  if (this->m_UseProgressBar)
    mitk::ProgressBar::GetInstance()->Progress(this->m_ProgressStepSize);
}

mitk::Surface::Pointer mitk::ComputeContourSetNormalsFilter::GetNormalsAsSurface()
{
  //Just for debugging:
  vtkSmartPointer<vtkPolyData> newPolyData = vtkSmartPointer<vtkPolyData>::New();
  vtkSmartPointer<vtkCellArray> newLines = vtkSmartPointer<vtkCellArray>::New();
  vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New();
  unsigned int idCounter (0);
  //Debug end

  for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs(); i++)
  {
    Surface* currentSurface = const_cast<Surface*>( this->GetOutput(i) );
    vtkPolyData* polyData = currentSurface->GetVtkPolyData();

    vtkSmartPointer<vtkDoubleArray> currentCellNormals = vtkDoubleArray::SafeDownCast(polyData->GetCellData()->GetNormals());

    vtkSmartPointer<vtkCellArray> existingPolys = polyData->GetPolys();

    vtkSmartPointer<vtkPoints> existingPoints = polyData->GetPoints();

    existingPolys->InitTraversal();

    vtkIdType* cell (NULL);
    vtkIdType cellSize (0);

    for( existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
    {
      for ( vtkIdType j = 0; j < cellSize; j++ )
      {
        double currentNormal[3];
        currentCellNormals->GetTuple(cell[j], currentNormal);
        vtkSmartPointer<vtkLine> line = vtkSmartPointer<vtkLine>::New();
        line->GetPointIds()->SetNumberOfIds(2);
        double newPoint[3];
        double p0[3];
        existingPoints->GetPoint(cell[j], p0);
        newPoint[0] = p0[0] + currentNormal[0];
        newPoint[1] = p0[1] + currentNormal[1];
        newPoint[2] = p0[2] + currentNormal[2];

        line->GetPointIds()->SetId(0, idCounter);
        newPoints->InsertPoint(idCounter, p0);
        idCounter++;

        line->GetPointIds()->SetId(1, idCounter);
        newPoints->InsertPoint(idCounter, newPoint);
        idCounter++;

        newLines->InsertNextCell(line);
      }//end for all points
    }//end for all cells
  }//end for all outputs

  newPolyData->SetPoints(newPoints);
  newPolyData->SetLines(newLines);
  newPolyData->BuildCells();

  mitk::Surface::Pointer surface = mitk::Surface::New();
  surface->SetVtkPolyData(newPolyData);

  return surface;

}

void mitk::ComputeContourSetNormalsFilter::SetMaxSpacing(double maxSpacing)
{
    m_MaxSpacing = maxSpacing;
}

void mitk::ComputeContourSetNormalsFilter::GenerateOutputInformation()
{
  Superclass::GenerateOutputInformation();
}

void mitk::ComputeContourSetNormalsFilter::Reset()
{
  for (unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); i++)
  {
    this->PopBackInput();
  }
  this->SetNumberOfIndexedInputs(0);
  this->SetNumberOfIndexedOutputs(0);

  mitk::Surface::Pointer output = mitk::Surface::New();
  this->SetNthOutput(0, output.GetPointer());
}

void mitk::ComputeContourSetNormalsFilter::SetUseProgressBar(bool status)
{
  this->m_UseProgressBar = status;
}

void mitk::ComputeContourSetNormalsFilter::SetProgressStepSize(unsigned int stepSize)
{
  this->m_ProgressStepSize = stepSize;
}
<|endoftext|>


<commit_before><commit_msg>Fix loading screen_ratio_pixel_count lod strategy from mesh<commit_after><|endoftext|>


<commit_before>#include "../include/Slider.hpp"

int main(int argc, char** argv)
{
	Console::Init(argv);
	Lua::Init(Console::Path);
	printf("aldhaksdh");
	bool instructions_closed;
	Lua::RunAsync(Console::Path+"..\\bin\\Lua\\instructions.lua", NULL, &instructions_closed);

	std::vector<char *> ellipses_anim = {".", ".", ".", "\b \b", "\b \b", "\b \b"};
	while (!instructions_closed)
	{
		for (auto i:ellipses_anim)
		{
			printf(i);
			if (!instructions_closed)
			{
				std::this_thread::sleep_for(std::chrono::microseconds(200000));
			}
		}
	}

	system("cls");
	//Lua::RunSync(path+"..\\bin\\Lua\\rulesets.lua");

	Console::PromptMenu("Main Menu", {
		{"Default", []()
			{
				printf("Test\n");
			}
		},
		{"Other", []()
			{
			}
		}
	}, []() {
		});

	return 0;
}<commit_msg>Accepted<commit_after>#include "../include/Slider.hpp"

int main(int argc, char** argv)
{
	Console::Init(argv);
	Lua::Init(Console::Path);
	printf("aldhaksdh");
	bool instructions_closed;
	Lua::RunAsync(Console::Path+"..\\bin\\Lua\\instructions.lua", NULL, &instructions_closed);

	std::vector<char *> ellipses_anim = {".", ".", ".", "\b \b", "\b \b", "\b \b"};
	while (!instructions_closed)
	{
		for (auto i:ellipses_anim)
		{
			printf(i);
			if (!instructions_closed)
			{
				std::this_thread::sleep_for(std::chrono::microseconds(200000));
			}
		}
	}

	system("cls");
	//Lua::RunSync(path+"..\\bin\\Lua\\rulesets.lua");

	Console::PromptMenu("Main Menu", {
		{"Default", []()
	{
		printf("Test\n");
	}
		},
		{"Other", []()
	{
	}
		}
	}, []() {
	});

	return 0;
}<|endoftext|>


<commit_before>#include "solver.h"

// Solver helper function
static bool satisfyAlready(const vector<int> &cls) {
    unordered_set<int> checker;
    for(auto &v : cls) {
        if( checker.find(-v) != checker.end() )
            return true;
        checker.insert(v);
    }
    return false;
}

// Init solver with cnf file
void solver::init(const char *filename) {

    // Init with empty solver
    *this = solver();

    // Get raw clause from cnf file
    vector< vector<int> > raw;
    parse_DIMACS_CNF(raw, maxVarIndex, filename);

    // Init assignment stack
    var = opStack(maxVarIndex+4);

    // Init database with all clause which has 2 or more literal in raw database
    // Eliminate all unit clause and check whether there is empty clause
    vector<int> unit;
    for(auto &cls : raw) {
        if( cls.empty() ) unsatAfterInit = 1;
        else if( cls.size() == 1 ) unit.emplace_back(cls[0]);
        else if( !satisfyAlready(cls) ) {
            clauses.push_back(Clause());
            clauses.back().watcher[0] = 0;
            clauses.back().watcher[1] = (cls.size() >> 1);
            clauses.back().lit = move(cls);
        }
    }

    // Init two watching check list
    pos = vector< vector<WatcherInfo> >(maxVarIndex+4);
    neg = vector< vector<WatcherInfo> >(maxVarIndex+4);
    int cid = 0;
    for(auto &cls : clauses) {
        int id = cls.getWatchVar(0);
        if( cls.getWatchSign(0) )
            pos[id].emplace_back(WatcherInfo(cid, 0));
        else
            neg[id].emplace_back(WatcherInfo(cid, 0));

        id = cls.getWatchVar(1);
        if( cls.getWatchSign(1) )
            pos[id].emplace_back(WatcherInfo(cid, 1));
        else
            neg[id].emplace_back(WatcherInfo(cid, 1));
        ++cid;
    }

    // Assign and run BCP for all unit clause
    for(auto lit : unit)
        unsatAfterInit |= !set(abs(lit), lit>0);

    // Identify independent subproblem via disjoint set
    dset.init(maxVarIndex+4);
    for(auto &cls : clauses) {
        int id = 0;
        while( id<cls.size() && var.getVal(cls.getVar(id))!=2 )
            ++id;
        for(int i=id+1; i<cls.size(); ++i)
            if( var.getVal(cls.getVar(i))==2 )
                dset.unionSet(cls.getVar(i), cls.getVar(id));
    }

}

// Assign id=val@nowLevel and run BCP recursively
bool solver::set(int id, bool val, int src) {

    // If id is already set, check consistency
    if( var.getVal(id) != 2 ) {
        conflictingClsID = -1;
        return var.getVal(id) == val;
    }

    // Set id=val@nowLevel
    var.set(id, val, nowLevel, src);

    // Update 2 literal watching
    vector<WatcherInfo> &lst = (val ? neg[id] : pos[id]);
    for(int i=lst.size()-1; i>=0; --i) {

        // Update watcher
        updateClauseWatcher(lst[i]);
        if( getVal(lst[i]) == 2 || eval(lst[i]) ) {
            // Watcher reaches an pending/satisfied variable

            // Push this watcher to corresponding check list
            if( getSign(lst[i]) )
                pos[getVar(lst[i])].emplace_back(lst[i]);
            else
                neg[getVar(lst[i])].emplace_back(lst[i]);

            // Delete this watcher from current check list
            swap(lst[i], lst.back());
            lst.pop_back();

        }
        else {
            // Watcher run through all clause back to original one
            // Can't find next literal to watch

            // b = alternative watcher in this clause
            WatcherInfo b(lst[i].clsid, lst[i].wid^1);
            if( getVal(b) == 2 ) {
                if( !set(getVar(b), getSign(b), lst[i].clsid) )
                    return false;
            }
            else if( !eval(b) ) {
                conflictingClsID = lst[i].clsid;
                return false;
            }

        }

    }

    // BCP done successfully without conflict
    return true;

}

bool solver::solve(int mode) {

    // Init statistic and start timer
    statistic.init();
    if( unsatAfterInit ) return false;

    // Init DPLL
    litMarker.init(maxVarIndex+4);
    sat = true;
    nowLevel = 0;

    // Solve each independent subproblems
    for(int i=1; i<=maxVarIndex && sat; ++i) {

        if( dset.findRoot(i) != i ) continue;

        nowSetID = i;

        // Init for specific heuristic
        // This must be done before each subproblems
        if( mode == HEURISTIC_NO ) {
            heuristicInit_no();
            pickUnassignedVar = &solver::heuristic_static;
        }
        else if( mode == HEURISTIC_MOM ) {
            heuristicInit_MOM();
            pickUnassignedVar = &solver::heuristic_static;
        }
        else {
            fprintf(stderr, "Unknown solver mode\n");
            exit(1);
        }

        sat &= _solve();

    }
    statistic.stopTimer();

    return sat;

}

bool solver::_solve() {

    // This subproblem startting stack index
    const int bound = nowLevel;

    // Main loop for DPLL
    while( true ) {

        ++nowLevel;
        statistic.maxDepth = max(statistic.maxDepth, nowLevel);
        staticOrderFrom = 0;
        pii decision = (this->*pickUnassignedVar)();
        if( decision.first == -1 )
            return true;
        int vid = decision.first;
        int sign = decision.second;

        while( !set(vid, sign) ) {

            if( conflictingClsID == -1 )
                return false;

            vector<int> learnt = firstUIP();
            if( learnt.empty() )
                return false;

            // Determined cronological backtracking
            int backlv = bound;
            int towatch = -1;
            for(int i=learnt.size()-2; i>=0; --i)
                if( var.getLv(abs(learnt[i])) > backlv ) {
                    backlv = var.getLv(abs(learnt[i]));
                    towatch = i;
                }

            // Learn one assignment
            if( learnt.size() == 1 || backlv == bound ) {
                ++statistic.backtrackNum;
                ++statistic.learnAssignment;
                var.backToLevel(bound);
                statistic.maxJumpBack = max(statistic.maxJumpBack, nowLevel-bound);
                nowLevel = bound;
                int uip = learnt.back();
                if( !set(abs(uip), uip>0) )
                    return false;
                break;
            }

            // Add conflict clause
            statistic.maxLearntSz = max(statistic.maxLearntSz, int(learnt.size()));
            clauses.push_back(Clause());
            clauses.back().watcher[0] = towatch;
            clauses.back().watcher[1] = learnt.size() - 1;
            clauses.back().lit = move(learnt);

            int cid = clauses.size() - 1;
            int id = clauses.back().getWatchVar(0);
            if( clauses.back().getWatchSign(0) )
                pos[id].emplace_back(WatcherInfo(cid, 0));
            else
                neg[id].emplace_back(WatcherInfo(cid, 0));

            id = clauses.back().getWatchVar(1);
            if( clauses.back().getWatchSign(1) )
                pos[id].emplace_back(WatcherInfo(cid, 1));
            else
                neg[id].emplace_back(WatcherInfo(cid, 1));

            ++statistic.backtrackNum;
            ++statistic.learnCls;
            statistic.maxJumpBack = max(statistic.maxJumpBack, nowLevel-backlv);
            var.backToLevel(backlv-1);
            nowLevel = backlv;
            vid = var.topNext().var;
            sign = var.topNext().val;

        }

    }

    return false;
}

/******************************************************
    Implementing Conflict Clause Learning Heuristic
******************************************************/
vector<int> solver::firstUIP() {

    // Init
    litMarker.clear();
    vector<int> learnt;
    int todoNum = _resolve(conflictingClsID, -1, learnt);
    if( todoNum == -1 )
        return vector<int>();

    // Resolve and find 1UIP
    int top = var._top;
    while( todoNum > 1 ) {
        while( litMarker.get(var.stk[top].var) == -1 )
            --top;
        int nowNum = _resolve(var.stk[top].src, var.stk[top].var, learnt);
        if( nowNum == -1 )
            return vector<int>();
        todoNum += nowNum - 1;
        --top;
    }
    while( litMarker.get(var.stk[top].var) == -1 )
        --top;
    int uip = (var.stk[top].val > 0 ? -var.stk[top].var : var.stk[top].var);
    learnt.emplace_back(uip);

    return learnt;

}

/******************************************************
    Implementing Branching Heuristic
******************************************************/
void solver::heuristicInit_no() {
    staticOrderFrom = 0;
    staticOrder.resize(maxVarIndex);
    for(int i=1; i<=maxVarIndex; ++i)
        staticOrder[i-1] = {i, 1};
}

void solver::heuristicInit_MOM() {
    staticOrderFrom = 0;
    staticOrder.resize(maxVarIndex);
    for(int i=1; i<=maxVarIndex; ++i)
        staticOrder[i-1] = {i, 1};

    vector<long long> scorePos(maxVarIndex + 4, 0);
    vector<long long> scoreNeg(maxVarIndex + 4, 0);
    vector<long long> score(maxVarIndex + 4, 0);
    for(auto &cls : clauses) {
        if( cls.size() > 3 )
            continue;
        for(int i=0; i<cls.size(); ++i)
            if( cls.getSign(i) )
                ++scorePos[cls.getVar(i)];
            else
                ++scoreNeg[cls.getVar(i)];
    }
    for(int i=1; i<=maxVarIndex; ++i) {
        if( dset.sameSet(i, nowSetID) )
            score[i] = scorePos[i] + scoreNeg[i];
        else
            score[i] = -1;
    }
    sort(staticOrder.begin(), staticOrder.end(), [&score](const pii &l, const pii &r) {
        return score[l.first] > score[r.first];
    });
    for(auto &v : staticOrder)
        if( scoreNeg[v.first] > scorePos[v.first] )
            v.second = 0;
}

pair<int,int> solver::heuristic_static() {
    for(int i=staticOrderFrom; i<staticOrder.size(); ++i)
        if( var.getVal(staticOrder[i].first)==2 &&
                dset.sameSet(staticOrder[i].first, nowSetID) ) {
            staticOrderFrom = i+1;
            return staticOrder[i];
        }
    return {-1, 0};
}
<commit_msg>Optimize ordering of bcp<commit_after>#include "solver.h"

// Solver helper function
static bool satisfyAlready(const vector<int> &cls) {
    unordered_set<int> checker;
    for(auto &v : cls) {
        if( checker.find(-v) != checker.end() )
            return true;
        checker.insert(v);
    }
    return false;
}

// Init solver with cnf file
void solver::init(const char *filename) {

    // Init with empty solver
    *this = solver();

    // Get raw clause from cnf file
    vector< vector<int> > raw;
    parse_DIMACS_CNF(raw, maxVarIndex, filename);

    // Init assignment stack
    var = opStack(maxVarIndex+4);

    // Init database with all clause which has 2 or more literal in raw database
    // Eliminate all unit clause and check whether there is empty clause
    vector<int> unit;
    for(auto &cls : raw) {
        if( cls.empty() ) unsatAfterInit = 1;
        else if( cls.size() == 1 ) unit.emplace_back(cls[0]);
        else if( !satisfyAlready(cls) ) {
            clauses.push_back(Clause());
            clauses.back().watcher[0] = 0;
            clauses.back().watcher[1] = (cls.size() >> 1);
            clauses.back().lit = move(cls);
        }
    }

    // Init two watching check list
    pos = vector< vector<WatcherInfo> >(maxVarIndex+4);
    neg = vector< vector<WatcherInfo> >(maxVarIndex+4);
    int cid = 0;
    for(auto &cls : clauses) {
        int id = cls.getWatchVar(0);
        if( cls.getWatchSign(0) )
            pos[id].emplace_back(WatcherInfo(cid, 0));
        else
            neg[id].emplace_back(WatcherInfo(cid, 0));

        id = cls.getWatchVar(1);
        if( cls.getWatchSign(1) )
            pos[id].emplace_back(WatcherInfo(cid, 1));
        else
            neg[id].emplace_back(WatcherInfo(cid, 1));
        ++cid;
    }

    // Assign and run BCP for all unit clause
    for(auto lit : unit)
        unsatAfterInit |= !set(abs(lit), lit>0);

    // Identify independent subproblem via disjoint set
    dset.init(maxVarIndex+4);
    for(auto &cls : clauses) {
        int id = 0;
        while( id<cls.size() && var.getVal(cls.getVar(id))!=2 )
            ++id;
        for(int i=id+1; i<cls.size(); ++i)
            if( var.getVal(cls.getVar(i))==2 )
                dset.unionSet(cls.getVar(i), cls.getVar(id));
    }

}

// Assign id=val@nowLevel and run BCP recursively
bool solver::set(int id, bool val, int src) {

    // If id is already set, check consistency
    if( var.getVal(id) != 2 ) {
        conflictingClsID = -1;
        return var.getVal(id) == val;
    }

    // Set id=val@nowLevel
    var.set(id, val, nowLevel, src);

    // Update 2 literal watching
    vector<WatcherInfo> &lst = (val ? neg[id] : pos[id]);
    int i = 0;
    while( i<lst.size() ) {

        // Update watcher
        updateClauseWatcher(lst[i]);
        if( getVal(lst[i]) == 2 || eval(lst[i]) ) {
            // Watcher reaches an pending/satisfied variable

            // Push this watcher to corresponding check list
            if( getSign(lst[i]) )
                pos[getVar(lst[i])].emplace_back(lst[i]);
            else
                neg[getVar(lst[i])].emplace_back(lst[i]);

            // Delete this watcher from current check list
            swap(lst[i], lst.back());
            lst.pop_back();

        }
        else {
            // Watcher run through all clause back to original one
            // Can't find next literal to watch

            // b = alternative watcher in this clause
            WatcherInfo b(lst[i].clsid, lst[i].wid^1);
            if( getVal(b) == 2 ) {
                if( !set(getVar(b), getSign(b), lst[i].clsid) )
                    return false;
            }
            else if( !eval(b) ) {
                conflictingClsID = lst[i].clsid;
                return false;
            }

            ++i;

        }

    }

    // BCP done successfully without conflict
    return true;

}

bool solver::solve(int mode) {

    // Init statistic and start timer
    statistic.init();
    if( unsatAfterInit ) return false;

    // Init DPLL
    litMarker.init(maxVarIndex+4);
    sat = true;
    nowLevel = 0;

    // Solve each independent subproblems
    for(int i=1; i<=maxVarIndex && sat; ++i) {

        if( dset.findRoot(i) != i ) continue;

        nowSetID = i;

        // Init for specific heuristic
        // This must be done before each subproblems
        if( mode == HEURISTIC_NO ) {
            heuristicInit_no();
            pickUnassignedVar = &solver::heuristic_static;
        }
        else if( mode == HEURISTIC_MOM ) {
            heuristicInit_MOM();
            pickUnassignedVar = &solver::heuristic_static;
        }
        else {
            fprintf(stderr, "Unknown solver mode\n");
            exit(1);
        }

        sat &= _solve();

    }
    statistic.stopTimer();

    return sat;

}

bool solver::_solve() {

    // This subproblem startting stack index
    const int bound = nowLevel;

    // Main loop for DPLL
    while( true ) {

        ++nowLevel;
        statistic.maxDepth = max(statistic.maxDepth, nowLevel);
        staticOrderFrom = 0;
        pii decision = (this->*pickUnassignedVar)();
        if( decision.first == -1 )
            return true;
        int vid = decision.first;
        int sign = decision.second;

        while( !set(vid, sign) ) {

            if( conflictingClsID == -1 )
                return false;

            vector<int> learnt = firstUIP();
            if( learnt.empty() )
                return false;

            // Determined cronological backtracking
            int backlv = bound;
            int towatch = -1;
            for(int i=learnt.size()-2; i>=0; --i)
                if( var.getLv(abs(learnt[i])) > backlv ) {
                    backlv = var.getLv(abs(learnt[i]));
                    towatch = i;
                }

            // Learn one assignment
            if( learnt.size() == 1 || backlv == bound ) {
                ++statistic.backtrackNum;
                ++statistic.learnAssignment;
                var.backToLevel(bound);
                statistic.maxJumpBack = max(statistic.maxJumpBack, nowLevel-bound);
                nowLevel = bound;
                int uip = learnt.back();
                if( !set(abs(uip), uip>0) )
                    return false;
                break;
            }

            // Add conflict clause
            statistic.maxLearntSz = max(statistic.maxLearntSz, int(learnt.size()));
            clauses.push_back(Clause());
            clauses.back().watcher[0] = towatch;
            clauses.back().watcher[1] = learnt.size() - 1;
            clauses.back().lit = move(learnt);

            int cid = clauses.size() - 1;
            int id = clauses.back().getWatchVar(0);
            if( clauses.back().getWatchSign(0) )
                pos[id].emplace_back(WatcherInfo(cid, 0));
            else
                neg[id].emplace_back(WatcherInfo(cid, 0));

            id = clauses.back().getWatchVar(1);
            if( clauses.back().getWatchSign(1) )
                pos[id].emplace_back(WatcherInfo(cid, 1));
            else
                neg[id].emplace_back(WatcherInfo(cid, 1));

            ++statistic.backtrackNum;
            ++statistic.learnCls;
            statistic.maxJumpBack = max(statistic.maxJumpBack, nowLevel-backlv);
            var.backToLevel(backlv-1);
            nowLevel = backlv;
            vid = var.topNext().var;
            sign = var.topNext().val;

        }

    }

    return false;
}

/******************************************************
    Implementing Conflict Clause Learning Heuristic
******************************************************/
vector<int> solver::firstUIP() {

    // Init
    litMarker.clear();
    vector<int> learnt;
    int todoNum = _resolve(conflictingClsID, -1, learnt);
    if( todoNum == -1 )
        return vector<int>();

    // Resolve and find 1UIP
    int top = var._top;
    while( todoNum > 1 ) {
        while( litMarker.get(var.stk[top].var) == -1 )
            --top;
        int nowNum = _resolve(var.stk[top].src, var.stk[top].var, learnt);
        if( nowNum == -1 )
            return vector<int>();
        todoNum += nowNum - 1;
        --top;
    }
    while( litMarker.get(var.stk[top].var) == -1 )
        --top;
    int uip = (var.stk[top].val > 0 ? -var.stk[top].var : var.stk[top].var);
    learnt.emplace_back(uip);

    return learnt;

}

/******************************************************
    Implementing Branching Heuristic
******************************************************/
void solver::heuristicInit_no() {
    staticOrderFrom = 0;
    staticOrder.resize(maxVarIndex);
    for(int i=1; i<=maxVarIndex; ++i)
        staticOrder[i-1] = {i, 1};
}

void solver::heuristicInit_MOM() {
    staticOrderFrom = 0;
    staticOrder.resize(maxVarIndex);
    for(int i=1; i<=maxVarIndex; ++i)
        staticOrder[i-1] = {i, 1};

    vector<long long> scorePos(maxVarIndex + 4, 0);
    vector<long long> scoreNeg(maxVarIndex + 4, 0);
    vector<long long> score(maxVarIndex + 4, 0);
    for(auto &cls : clauses) {
        if( cls.size() > 3 )
            continue;
        for(int i=0; i<cls.size(); ++i)
            if( cls.getSign(i) )
                ++scorePos[cls.getVar(i)];
            else
                ++scoreNeg[cls.getVar(i)];
    }
    for(int i=1; i<=maxVarIndex; ++i) {
        if( dset.sameSet(i, nowSetID) )
            score[i] = scorePos[i] + scoreNeg[i];
        else
            score[i] = -1;
    }
    sort(staticOrder.begin(), staticOrder.end(), [&score](const pii &l, const pii &r) {
        return score[l.first] > score[r.first];
    });
    for(auto &v : staticOrder)
        if( scoreNeg[v.first] > scorePos[v.first] )
            v.second = 0;
}

pair<int,int> solver::heuristic_static() {
    for(int i=staticOrderFrom; i<staticOrder.size(); ++i)
        if( var.getVal(staticOrder[i].first)==2 &&
                dset.sameSet(staticOrder[i].first, nowSetID) ) {
            staticOrderFrom = i+1;
            return staticOrder[i];
        }
    return {-1, 0};
}
<|endoftext|>