<commit_before>/* rest_service_endpoint.cc
   Jeremy Barnes, 11 November 2012
   Copyright (c) 2012 Datacratic.  All rights reserved.

   Endpoint to talk with a REST service.
*/

#include "rest_service_endpoint.h"
#include "jml/utils/vector_utils.h"
#include "jml/utils/pair_utils.h"
#include "city.h"

using namespace std;

namespace Datacratic {

/*****************************************************************************/
/* REST REQUEST                                                              */
/*****************************************************************************/

std::ostream & operator << (std::ostream & stream, const RestRequest & request)
{
    return stream << request.verb << " " << request.resource << endl
                  << request.params << endl
                  << request.payload;
}

/*****************************************************************************/
/* REST SERVICE ENDPOINT CONNECTION ID                                       */
/*****************************************************************************/

void
RestServiceEndpoint::ConnectionId::
sendResponse(int responseCode,
             const std::string & response,
             const std::string & contentType) const
{
    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, response,
                                   contentType);

    if (itl->http)
        itl->http->sendResponse(responseCode, response, contentType);
    else {
        std::vector<std::string> message;
        message.push_back(itl->zmqAddress);
        message.push_back(itl->requestId);
        message.push_back(std::to_string(responseCode));
        message.push_back(response);

        //std::cerr << "sending response to " << itl->requestId
        //          << std::endl;
        itl->endpoint->zmqEndpoint.sendMessage(message);
    }

    itl->responseSent = true;
}

void
RestServiceEndpoint::ConnectionId::
sendResponse(int responseCode,
                  const Json::Value & response,
                  const std::string & contentType) const
{
    using namespace std;
    //cerr << "sent response " << responseCode << " " << response
    //     << endl;

    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, response.toString(),
                                   contentType);

    if (itl->http)
        itl->http->sendResponse(responseCode, response, contentType);
    else {
        std::vector<std::string> message;
        message.push_back(itl->zmqAddress);
        message.push_back(itl->requestId);
        message.push_back(std::to_string(responseCode));
        message.push_back(response.toString());
        itl->endpoint->zmqEndpoint.sendMessage(message);
    }

    itl->responseSent = true;
}

void
RestServiceEndpoint::ConnectionId::
sendErrorResponse(int responseCode,
                       const std::string & error,
                       const std::string & contentType) const
{
    using namespace std;
    cerr << "sent error response " << responseCode << " " << error
         << endl;

    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, error,
                                   contentType);

    if (itl->http)
        itl->http->sendResponse(responseCode, error);
    else {
        std::vector<std::string> message;
        message.push_back(itl->zmqAddress);
        message.push_back(itl->requestId);
        message.push_back(std::to_string(responseCode));
        message.push_back(error);
        itl->endpoint->zmqEndpoint.sendMessage(message);
    }

    itl->responseSent = true;
}

void
RestServiceEndpoint::ConnectionId::
sendErrorResponse(int responseCode, const Json::Value & error) const
{
    using namespace std;
    cerr << "sent error response " << responseCode << " " << error
         << endl;

    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, error.toString(),
                                   "application/json");

    if (itl->http)
        itl->http->sendResponse(responseCode, error);
    else {
        std::vector<std::string> message;
        message.push_back(itl->zmqAddress);
        message.push_back(itl->requestId);
        message.push_back(std::to_string(responseCode));
        message.push_back(error.toString());
        itl->endpoint->zmqEndpoint.sendMessage(message);
    }

    itl->responseSent = true;
}

void
RestServiceEndpoint::ConnectionId::
sendRedirect(int responseCode, const std::string & location) const
{
    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, location,
                                   "REDIRECT");

    if (itl->http)
        itl->http->sendResponse(responseCode, string(""), "",
                                { { "Location", location } });
    else {
        throw ML::Exception("zeromq redirects not done yet");
    }

    itl->responseSent = true;
}

void
RestServiceEndpoint::ConnectionId::
sendHttpResponse(int responseCode,
                 const std::string & response,
                 const std::string & contentType,
                 const RestParams & headers) const
{
    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, response,
                                   contentType);

    if (itl->http)
        itl->http->sendResponse(responseCode, response, contentType,
                                headers);
    else {
        throw ML::Exception("zeromq redirects not done yet");
    }

    itl->responseSent = true;
}

void
RestServiceEndpoint::ConnectionId::
sendHttpResponseHeader(int responseCode,
                       const std::string & contentType,
                       ssize_t contentLength,
                       const RestParams & headers_) const
{
    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (!itl->http)
        throw ML::Exception("sendHttpResponseHeader only works on HTTP connections");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, "", contentType);

    RestParams headers = headers_;
    if (contentLength == CHUNKED_ENCODING) {
        itl->chunkedEncoding = true;
        headers.push_back({"Transfer-Encoding", "chunked"});
    }
    else if (contentLength >= 0) {
        headers.push_back({"Content-Length", to_string(contentLength) });
    }
    else {
        itl->keepAlive = false;
    }

    itl->http->sendResponseHeader(responseCode, contentType, headers);
}

void
RestServiceEndpoint::ConnectionId::
sendPayload(const std::string & payload)
{
    if (itl->chunkedEncoding) {
        if (payload.empty()) {
            throw ML::Exception("Can't send empty chunk over a chunked connection");
        }
        string length = ML::format("%llx\r\n", (long long)payload.length());
        itl->http->sendHttpChunk(payload, HttpConnectionHandler::NEXT_CONTINUE);
    }
    else itl->http->send(payload);
}

void
RestServiceEndpoint::ConnectionId::
finishResponse()
{
    if (itl->chunkedEncoding) {
        itl->http->sendHttpChunk("", HttpConnectionHandler::NEXT_RECYCLE);
    }
    else if (!itl->keepAlive) {
        itl->http->closeConnection();
    }

    itl->responseSent = true;
}

/*****************************************************************************/
/* REST SERVICE ENDPOINT                                                     */
/*****************************************************************************/

RestServiceEndpoint::
RestServiceEndpoint(std::shared_ptr<zmq::context_t> context)
    : zmqEndpoint(context)
{
}

RestServiceEndpoint::
~RestServiceEndpoint()
{
    shutdown();
}

void
RestServiceEndpoint::
shutdown()
{
    // 1.  Shut down the http endpoint, since it needs our threads to
    //     complete its shutdown
    httpEndpoint.shutdown();

    // 2.  Shut down the message loop
    MessageLoop::shutdown();

    // 3.  Shut down the zmq endpoint now we know that the message loop is not using
    //     it.
    zmqEndpoint.shutdown();
}

void
RestServiceEndpoint::
init(std::shared_ptr<ConfigurationService> config,
     const std::string & endpointName,
     double maxAddedLatency,
     int numThreads)
{
    MessageLoop::init(numThreads, maxAddedLatency);
    zmqEndpoint.init(config, ZMQ_XREP, endpointName + "/zeromq");
    httpEndpoint.init(config, endpointName + "/http");

    auto zmqHandler = [=] (std::vector<std::string> && message)
        {
            using namespace std;

            if (message.size() < 6) {
                cerr << "ignored message with invalid number of members:"
                     << message.size()
                     << endl;
                return;
            }
            //cerr << "got REST message at " << this << " " << message << endl;
            this->doHandleRequest(ConnectionId(message.at(0),
                                               message.at(1),
                                               this),
                                  RestRequest(message.at(2),
                                              message.at(3),
                                              RestParams::fromBinary(message.at(4)),
                                              message.at(5)));
        };

    zmqEndpoint.messageHandler = zmqHandler;

    httpEndpoint.onRequest
        = [=] (std::shared_ptr<HttpNamedEndpoint::RestConnectionHandler> connection,
               const HttpHeader & header,
               const std::string & payload)
        {
            std::string requestId = this->getHttpRequestId();
            this->doHandleRequest(ConnectionId(connection, requestId, this),
                                  RestRequest(header, payload));
        };

    addSource("RestServiceEndpoint::zmqEndpoint", zmqEndpoint);
    addSource("RestServiceEndpoint::httpEndpoint", httpEndpoint);

}

std::pair<std::string, std::string>
RestServiceEndpoint::
bindTcp(PortRange const & zmqRange, PortRange const & httpRange,
        std::string host)
{
    std::string httpAddr = httpEndpoint.bindTcp(httpRange, host);
    std::string zmqAddr = zmqEndpoint.bindTcp(zmqRange, host);
    return std::make_pair(zmqAddr, httpAddr);
}

void
RestServiceEndpoint::
handleRequest(const ConnectionId & connection,
                           const RestRequest & request) const
{
    using namespace std;

    //cerr << "got request " << request << endl;
    if (onHandleRequest) {
        onHandleRequest(connection, request);
    }
    else {
        throw ML::Exception("need to override handleRequest or assign to "
                            "onHandleRequest");
    }
}

std::string
RestServiceEndpoint::
getHttpRequestId() const
{
    std::string s = Date::now().print(9) + ML::format("%d", random());
    uint64_t jobId = CityHash64(s.c_str(), s.size());
    return ML::format("%016llx", jobId);
}

void
RestServiceEndpoint::
logToStream(std::ostream & stream)
{
    auto logLock = std::make_shared<std::mutex>();

    logRequest = [=,&stream] (const ConnectionId & conn, const RestRequest & req)
        {
            std::unique_lock<std::mutex> guard(*logLock);

            stream << "--> ------------------------- new request "
            << conn.itl->requestId
            << " at " << conn.itl->startDate.print(9) << endl;
            stream << req << endl << endl;
        };

    logResponse = [=,&stream] (const ConnectionId & conn,
                       int code,
                       const std::string & resp,
                       const std::string & contentType)
        {
            std::unique_lock<std::mutex> guard(*logLock);

            Date now = Date::now();

            stream << "<-- ========================= finished request "
            << conn.itl->requestId
            << " at " << now.print(9)
            << ML::format(" (%.3fms)", conn.itl->startDate.secondsUntil(now) * 1000)
            << endl;
            stream << code << " " << contentType << " " << resp.length() << " bytes" << endl;;

            if (resp.size() <= 16384)
                stream << resp;
            else {
                stream << string(resp, 0, 16386) << "...";
            }
            stream << endl << endl;
        };
}

} // namespace Datacratic
<commit_msg>Removed dead code from RestServiceEndpoint (TRIVIAL)<commit_after>/* rest_service_endpoint.cc
   Jeremy Barnes, 11 November 2012
   Copyright (c) 2012 Datacratic.  All rights reserved.

   Endpoint to talk with a REST service.
*/

#include "rest_service_endpoint.h"
#include "jml/utils/vector_utils.h"
#include "jml/utils/pair_utils.h"
#include "city.h"

using namespace std;

namespace Datacratic {

/*****************************************************************************/
/* REST REQUEST                                                              */
/*****************************************************************************/

std::ostream & operator << (std::ostream & stream, const RestRequest & request)
{
    return stream << request.verb << " " << request.resource << endl
                  << request.params << endl
                  << request.payload;
}

/*****************************************************************************/
/* REST SERVICE ENDPOINT CONNECTION ID                                       */
/*****************************************************************************/

void
RestServiceEndpoint::ConnectionId::
sendResponse(int responseCode,
             const std::string & response,
             const std::string & contentType) const
{
    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, response,
                                   contentType);

    if (itl->http)
        itl->http->sendResponse(responseCode, response, contentType);
    else {
        std::vector<std::string> message;
        message.push_back(itl->zmqAddress);
        message.push_back(itl->requestId);
        message.push_back(std::to_string(responseCode));
        message.push_back(response);

        //std::cerr << "sending response to " << itl->requestId
        //          << std::endl;
        itl->endpoint->zmqEndpoint.sendMessage(message);
    }

    itl->responseSent = true;
}

void
RestServiceEndpoint::ConnectionId::
sendResponse(int responseCode,
                  const Json::Value & response,
                  const std::string & contentType) const
{
    using namespace std;
    //cerr << "sent response " << responseCode << " " << response
    //     << endl;

    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, response.toString(),
                                   contentType);

    if (itl->http)
        itl->http->sendResponse(responseCode, response, contentType);
    else {
        std::vector<std::string> message;
        message.push_back(itl->zmqAddress);
        message.push_back(itl->requestId);
        message.push_back(std::to_string(responseCode));
        message.push_back(response.toString());
        itl->endpoint->zmqEndpoint.sendMessage(message);
    }

    itl->responseSent = true;
}

void
RestServiceEndpoint::ConnectionId::
sendErrorResponse(int responseCode,
                       const std::string & error,
                       const std::string & contentType) const
{
    using namespace std;
    cerr << "sent error response " << responseCode << " " << error
         << endl;

    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, error,
                                   contentType);

    if (itl->http)
        itl->http->sendResponse(responseCode, error);
    else {
        std::vector<std::string> message;
        message.push_back(itl->zmqAddress);
        message.push_back(itl->requestId);
        message.push_back(std::to_string(responseCode));
        message.push_back(error);
        itl->endpoint->zmqEndpoint.sendMessage(message);
    }

    itl->responseSent = true;
}

void
RestServiceEndpoint::ConnectionId::
sendErrorResponse(int responseCode, const Json::Value & error) const
{
    using namespace std;
    cerr << "sent error response " << responseCode << " " << error
         << endl;

    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, error.toString(),
                                   "application/json");

    if (itl->http)
        itl->http->sendResponse(responseCode, error);
    else {
        std::vector<std::string> message;
        message.push_back(itl->zmqAddress);
        message.push_back(itl->requestId);
        message.push_back(std::to_string(responseCode));
        message.push_back(error.toString());
        itl->endpoint->zmqEndpoint.sendMessage(message);
    }

    itl->responseSent = true;
}

void
RestServiceEndpoint::ConnectionId::
sendRedirect(int responseCode, const std::string & location) const
{
    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, location,
                                   "REDIRECT");

    if (itl->http)
        itl->http->sendResponse(responseCode, string(""), "",
                                { { "Location", location } });
    else {
        throw ML::Exception("zeromq redirects not done yet");
    }

    itl->responseSent = true;
}

void
RestServiceEndpoint::ConnectionId::
sendHttpResponse(int responseCode,
                 const std::string & response,
                 const std::string & contentType,
                 const RestParams & headers) const
{
    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, response,
                                   contentType);

    if (itl->http)
        itl->http->sendResponse(responseCode, response, contentType,
                                headers);
    else {
        throw ML::Exception("zeromq redirects not done yet");
    }

    itl->responseSent = true;
}

void
RestServiceEndpoint::ConnectionId::
sendHttpResponseHeader(int responseCode,
                       const std::string & contentType,
                       ssize_t contentLength,
                       const RestParams & headers_) const
{
    if (itl->responseSent)
        throw ML::Exception("response already sent");

    if (!itl->http)
        throw ML::Exception("sendHttpResponseHeader only works on HTTP connections");

    if (itl->endpoint->logResponse)
        itl->endpoint->logResponse(*this, responseCode, "", contentType);

    RestParams headers = headers_;
    if (contentLength == CHUNKED_ENCODING) {
        itl->chunkedEncoding = true;
        headers.push_back({"Transfer-Encoding", "chunked"});
    }
    else if (contentLength >= 0) {
        headers.push_back({"Content-Length", to_string(contentLength) });
    }
    else {
        itl->keepAlive = false;
    }

    itl->http->sendResponseHeader(responseCode, contentType, headers);
}

void
RestServiceEndpoint::ConnectionId::
sendPayload(const std::string & payload)
{
    if (itl->chunkedEncoding) {
        if (payload.empty()) {
            throw ML::Exception("Can't send empty chunk over a chunked connection");
        }
        itl->http->sendHttpChunk(payload, HttpConnectionHandler::NEXT_CONTINUE);
    }
    else itl->http->send(payload);
}

void
RestServiceEndpoint::ConnectionId::
finishResponse()
{
    if (itl->chunkedEncoding) {
        itl->http->sendHttpChunk("", HttpConnectionHandler::NEXT_RECYCLE);
    }
    else if (!itl->keepAlive) {
        itl->http->closeConnection();
    }

    itl->responseSent = true;
}

/*****************************************************************************/
/* REST SERVICE ENDPOINT                                                     */
/*****************************************************************************/

RestServiceEndpoint::
RestServiceEndpoint(std::shared_ptr<zmq::context_t> context)
    : zmqEndpoint(context)
{
}

RestServiceEndpoint::
~RestServiceEndpoint()
{
    shutdown();
}

void
RestServiceEndpoint::
shutdown()
{
    // 1.  Shut down the http endpoint, since it needs our threads to
    //     complete its shutdown
    httpEndpoint.shutdown();

    // 2.  Shut down the message loop
    MessageLoop::shutdown();

    // 3.  Shut down the zmq endpoint now we know that the message loop is not using
    //     it.
    zmqEndpoint.shutdown();
}

void
RestServiceEndpoint::
init(std::shared_ptr<ConfigurationService> config,
     const std::string & endpointName,
     double maxAddedLatency,
     int numThreads)
{
    MessageLoop::init(numThreads, maxAddedLatency);
    zmqEndpoint.init(config, ZMQ_XREP, endpointName + "/zeromq");
    httpEndpoint.init(config, endpointName + "/http");

    auto zmqHandler = [=] (std::vector<std::string> && message)
        {
            using namespace std;

            if (message.size() < 6) {
                cerr << "ignored message with invalid number of members:"
                     << message.size()
                     << endl;
                return;
            }
            //cerr << "got REST message at " << this << " " << message << endl;
            this->doHandleRequest(ConnectionId(message.at(0),
                                               message.at(1),
                                               this),
                                  RestRequest(message.at(2),
                                              message.at(3),
                                              RestParams::fromBinary(message.at(4)),
                                              message.at(5)));
        };

    zmqEndpoint.messageHandler = zmqHandler;

    httpEndpoint.onRequest
        = [=] (std::shared_ptr<HttpNamedEndpoint::RestConnectionHandler> connection,
               const HttpHeader & header,
               const std::string & payload)
        {
            std::string requestId = this->getHttpRequestId();
            this->doHandleRequest(ConnectionId(connection, requestId, this),
                                  RestRequest(header, payload));
        };

    addSource("RestServiceEndpoint::zmqEndpoint", zmqEndpoint);
    addSource("RestServiceEndpoint::httpEndpoint", httpEndpoint);

}

std::pair<std::string, std::string>
RestServiceEndpoint::
bindTcp(PortRange const & zmqRange, PortRange const & httpRange,
        std::string host)
{
    std::string httpAddr = httpEndpoint.bindTcp(httpRange, host);
    std::string zmqAddr = zmqEndpoint.bindTcp(zmqRange, host);
    return std::make_pair(zmqAddr, httpAddr);
}

void
RestServiceEndpoint::
handleRequest(const ConnectionId & connection,
                           const RestRequest & request) const
{
    using namespace std;

    //cerr << "got request " << request << endl;
    if (onHandleRequest) {
        onHandleRequest(connection, request);
    }
    else {
        throw ML::Exception("need to override handleRequest or assign to "
                            "onHandleRequest");
    }
}

std::string
RestServiceEndpoint::
getHttpRequestId() const
{
    std::string s = Date::now().print(9) + ML::format("%d", random());
    uint64_t jobId = CityHash64(s.c_str(), s.size());
    return ML::format("%016llx", jobId);
}

void
RestServiceEndpoint::
logToStream(std::ostream & stream)
{
    auto logLock = std::make_shared<std::mutex>();

    logRequest = [=,&stream] (const ConnectionId & conn, const RestRequest & req)
        {
            std::unique_lock<std::mutex> guard(*logLock);

            stream << "--> ------------------------- new request "
            << conn.itl->requestId
            << " at " << conn.itl->startDate.print(9) << endl;
            stream << req << endl << endl;
        };

    logResponse = [=,&stream] (const ConnectionId & conn,
                       int code,
                       const std::string & resp,
                       const std::string & contentType)
        {
            std::unique_lock<std::mutex> guard(*logLock);

            Date now = Date::now();

            stream << "<-- ========================= finished request "
            << conn.itl->requestId
            << " at " << now.print(9)
            << ML::format(" (%.3fms)", conn.itl->startDate.secondsUntil(now) * 1000)
            << endl;
            stream << code << " " << contentType << " " << resp.length() << " bytes" << endl;;

            if (resp.size() <= 16384)
                stream << resp;
            else {
                stream << string(resp, 0, 16386) << "...";
            }
            stream << endl << endl;
        };
}

} // namespace Datacratic
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017-2018 dresden elektronik ingenieurtechnik gmbh.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 *
 */

#ifdef USE_WEBSOCKETS

#include "deconz/dbg_trace.h"
#include "websocket_server.h"

/*! Constructor.
 */
WebSocketServer::WebSocketServer(QObject *parent, quint16 port) :
    QObject(parent)
{
    srv = new QWebSocketServer("deconz", QWebSocketServer::NonSecureMode, this);

    quint16 p = 0;
    quint16 ports[] = { 443, 443, 8080, 8088, 20877, 0 }; // start with proxy frinedly ports first, use random port as fallback
    if (port > 0)
    {
        ports[0] = port;
    }

    while (!srv->listen(QHostAddress::AnyIPv4, ports[p]))
    {
        if (ports[p] == 0)
        {
            DBG_Printf(DBG_ERROR, "giveup starting websocket server on port %u. error: %s\n", ports[p], qPrintable(srv->errorString()));
            break;
        }

        DBG_Printf(DBG_ERROR, "failed to start websocket server on port %u. error: %s\n", ports[p], qPrintable(srv->errorString()));
        p++;
    }

    if (srv->isListening())
    {
        DBG_Printf(DBG_INFO, "started websocket server at port %u\n", srv->serverPort());
        connect(srv, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
    }
}

/*! Returns the websocket server port.
    \return the active server port, or 0 if not active
 */
quint16 WebSocketServer::port() const
{
    return srv->isListening() ? srv->serverPort() : 0;
}

/*! Handler for new client connections.
 */
void WebSocketServer::onNewConnection()
{
    while (srv->hasPendingConnections())
    {
        QWebSocket *sock = srv->nextPendingConnection();
        DBG_Printf(DBG_INFO, "New websocket %s:%u (state: %d) \n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), sock->state());
        connect(sock, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
        connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onSocketError(QAbstractSocket::SocketError)));
        clients.push_back(sock);
    }
}

/*! Handle websocket disconnected signal.
 */
void WebSocketServer::onSocketDisconnected()
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = qobject_cast<QWebSocket*>(sender());
        DBG_Assert(sock);
        if (sock && clients[i] == sock)
        {
            DBG_Printf(DBG_INFO, "Websocket disconnected %s:%u (state: %d) \n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), sock->state());
            sock->deleteLater();
            clients[i] = clients.back();
            clients.pop_back();
        }
    }
}

/*! Handle websocket error signal.
    \param err - the error which occured
 */
void WebSocketServer::onSocketError(QAbstractSocket::SocketError err)
{
    Q_UNUSED(err);
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = qobject_cast<QWebSocket*>(sender());
        DBG_Assert(sock);
        if (sock && clients[i] == sock)
        {
            DBG_Printf(DBG_INFO, "Remove websocket %s:%u after error %s\n",
                       qPrintable(sock->peerAddress().toString()), sock->peerPort(), qPrintable(sock->errorString()));
            sock->deleteLater();
            clients[i] = clients.back();
            clients.pop_back();
        }
    }
}

/*! Broadcasts a message to all connected clients.
    \param msg the message as JSON string
 */
void WebSocketServer::broadcastTextMessage(const QString &msg)
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = clients[i];

        if (sock->state() != QAbstractSocket::ConnectedState)
        {
            DBG_Printf(DBG_INFO, "Websocket %s:%u unexpected state: %d\n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), sock->state());
        }

        qint64 ret = sock->sendTextMessage(msg);
        DBG_Printf(DBG_INFO_L2, "Websocket %s:%u send message: %s (ret = %d)\n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), qPrintable(msg), ret);
        sock->flush();
    }
}

/*! Flush the sockets of all connected clients.
 */
void WebSocketServer::flush()
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = clients[i];

        if (sock->state() == QAbstractSocket::ConnectedState)
        {
            sock->flush();
        }
    }
}

#else // no websockets
  WebSocketServer::WebSocketServer(QObject *parent) :
      QObject(parent)
  { }
  void WebSocketServer::onNewConnection() { }
  void WebSocketServer::broadcastTextMessage(const QString &) { }
  quint16 WebSocketServer::port() const {  return 0; }
#endif
<commit_msg>Websocket print close reason on close and error events<commit_after>/*
 * Copyright (c) 2017-2018 dresden elektronik ingenieurtechnik gmbh.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 *
 */

#ifdef USE_WEBSOCKETS

#include "deconz/dbg_trace.h"
#include "websocket_server.h"

/*! Constructor.
 */
WebSocketServer::WebSocketServer(QObject *parent, quint16 port) :
    QObject(parent)
{
    srv = new QWebSocketServer("deconz", QWebSocketServer::NonSecureMode, this);

    quint16 p = 0;
    quint16 ports[] = { 443, 443, 8080, 8088, 20877, 0 }; // start with proxy frinedly ports first, use random port as fallback
    if (port > 0)
    {
        ports[0] = port;
    }

    while (!srv->listen(QHostAddress::AnyIPv4, ports[p]))
    {
        if (ports[p] == 0)
        {
            DBG_Printf(DBG_ERROR, "giveup starting websocket server on port %u. error: %s\n", ports[p], qPrintable(srv->errorString()));
            break;
        }

        DBG_Printf(DBG_ERROR, "failed to start websocket server on port %u. error: %s\n", ports[p], qPrintable(srv->errorString()));
        p++;
    }

    if (srv->isListening())
    {
        DBG_Printf(DBG_INFO, "started websocket server at port %u\n", srv->serverPort());
        connect(srv, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
    }
}

/*! Returns the websocket server port.
    \return the active server port, or 0 if not active
 */
quint16 WebSocketServer::port() const
{
    return srv->isListening() ? srv->serverPort() : 0;
}

/*! Handler for new client connections.
 */
void WebSocketServer::onNewConnection()
{
    while (srv->hasPendingConnections())
    {
        QWebSocket *sock = srv->nextPendingConnection();
        DBG_Printf(DBG_INFO, "New websocket %s:%u (state: %d) \n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), sock->state());
        connect(sock, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
        connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onSocketError(QAbstractSocket::SocketError)));
        clients.push_back(sock);
    }
}

/*! Handle websocket disconnected signal.
 */
void WebSocketServer::onSocketDisconnected()
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = qobject_cast<QWebSocket*>(sender());
        DBG_Assert(sock);
        if (sock && clients[i] == sock)
        {
            DBG_Printf(DBG_INFO, "Websocket disconnected %s:%u, state: %d, close-code: %d, reason: %s\n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), sock->state(), sock->closeCode(), qPrintable(sock->closeReason()));
            sock->deleteLater();
            clients[i] = clients.back();
            clients.pop_back();
        }
    }
}

/*! Handle websocket error signal.
    \param err - the error which occured
 */
void WebSocketServer::onSocketError(QAbstractSocket::SocketError err)
{
    Q_UNUSED(err);
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = qobject_cast<QWebSocket*>(sender());
        DBG_Assert(sock);
        if (sock && clients[i] == sock)
        {
            DBG_Printf(DBG_INFO, "Remove websocket %s:%u after error %s, close-code: %d, reason: %s\n",
                       qPrintable(sock->peerAddress().toString()), sock->peerPort(), qPrintable(sock->errorString()), sock->closeCode(), qPrintable(sock->closeReason()));
            sock->deleteLater();
            clients[i] = clients.back();
            clients.pop_back();
        }
    }
}

/*! Broadcasts a message to all connected clients.
    \param msg the message as JSON string
 */
void WebSocketServer::broadcastTextMessage(const QString &msg)
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = clients[i];

        if (sock->state() != QAbstractSocket::ConnectedState)
        {
            DBG_Printf(DBG_INFO, "Websocket %s:%u unexpected state: %d\n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), sock->state());
        }

        qint64 ret = sock->sendTextMessage(msg);
        DBG_Printf(DBG_INFO_L2, "Websocket %s:%u send message: %s (ret = %d)\n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), qPrintable(msg), ret);
        sock->flush();
    }
}

/*! Flush the sockets of all connected clients.
 */
void WebSocketServer::flush()
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = clients[i];

        if (sock->state() == QAbstractSocket::ConnectedState)
        {
            sock->flush();
        }
    }
}

#else // no websockets
  WebSocketServer::WebSocketServer(QObject *parent) :
      QObject(parent)
  { }
  void WebSocketServer::onNewConnection() { }
  void WebSocketServer::broadcastTextMessage(const QString &) { }
  quint16 WebSocketServer::port() const {  return 0; }
#endif
<|endoftext|>


<commit_before>#ifdef USE_WEBSOCKETS
#include <QWebSocket>
#include <QWebSocketServer>

#include "deconz/dbg_trace.h"
#include "websocket_server.h"

#define MAX_ATTEMPS 50
#define WS_PORT 20877

/*! Constructor.
 */
WebSocketServer::WebSocketServer(QObject *parent) :
    QObject(parent)
{
    srv = new QWebSocketServer("deconz", QWebSocketServer::NonSecureMode, this);

    quint16 p = WS_PORT;

    while (!srv->listen(QHostAddress::AnyIPv4, p))
    {
        if (p == 0)
        {
            DBG_Printf(DBG_ERROR, "giveup starting websocket server on port %u. error: %s\n", qPrintable(srv->errorString()));
            break;
        }

        DBG_Printf(DBG_ERROR, "failed to start websocket server on port %u. error: %s\n", qPrintable(srv->errorString()));

        if (p < (WS_PORT  + MAX_ATTEMPS))
        { p++; }
        else
        { p = 0; }
    }

    if (srv->isListening())
    {
        DBG_Printf(DBG_INFO, "started websocket server at port %u\n", srv->serverPort());
        connect(srv, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
    }
}

/*! Returns the websocket server port.
    \return the active server port, or 0 if not active
 */
quint16 WebSocketServer::port() const
{
    return srv->isListening() ? srv->serverPort() : 0;
}

/*! Handler for new client connections.
 */
void WebSocketServer::onNewConnection()
{
    while (srv->hasPendingConnections())
    {
        QWebSocket *sock = srv->nextPendingConnection();
        clients.push_back(sock);
    }
}

/*! Broadcasts a message to all connected clients.
    \param msg the message as JSON string
 */
void WebSocketServer::broadcastTextMessage(const QString &msg)
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = clients[i];

        if (sock->state() == QAbstractSocket::ConnectedState)
        {
            sock->sendTextMessage(msg);
        }
        else
        {
            DBG_Printf(DBG_INFO, "Remove websocket %s:%u\n", sock->peerAddress().toString(), sock->peerPort());
            sock->deleteLater();
            clients[i] = clients.back();
            clients.pop_back();
        }
    }
}
#else // no websockets
  WebSocketServer::WebSocketServer(QObject *parent) :
      QObject(parent)
  { }
  void WebSocketServer::onNewConnection() { }
  void WebSocketServer::broadcastTextMessage(const QString &) { }
  quint16 WebSocketServer::port() const {  return 0; }
#endif
<commit_msg>Fix compilation of websockets<commit_after>#ifdef USE_WEBSOCKETS
#include <QWebSocket>
#include <QWebSocketServer>

#include "deconz/dbg_trace.h"
#include "websocket_server.h"

#define MAX_ATTEMPS 50
#define WS_PORT 20877

/*! Constructor.
 */
WebSocketServer::WebSocketServer(QObject *parent) :
    QObject(parent)
{
    srv = new QWebSocketServer("deconz", QWebSocketServer::NonSecureMode, this);

    quint16 p = WS_PORT;

    while (!srv->listen(QHostAddress::AnyIPv4, p))
    {
        if (p == 0)
        {
            DBG_Printf(DBG_ERROR, "giveup starting websocket server on port %u. error: %s\n", qPrintable(srv->errorString()));
            break;
        }

        DBG_Printf(DBG_ERROR, "failed to start websocket server on port %u. error: %s\n", qPrintable(srv->errorString()));

        if (p < (WS_PORT  + MAX_ATTEMPS))
        { p++; }
        else
        { p = 0; }
    }

    if (srv->isListening())
    {
        DBG_Printf(DBG_INFO, "started websocket server at port %u\n", srv->serverPort());
        connect(srv, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
    }
}

/*! Returns the websocket server port.
    \return the active server port, or 0 if not active
 */
quint16 WebSocketServer::port() const
{
    return srv->isListening() ? srv->serverPort() : 0;
}

/*! Handler for new client connections.
 */
void WebSocketServer::onNewConnection()
{
    while (srv->hasPendingConnections())
    {
        QWebSocket *sock = srv->nextPendingConnection();
        clients.push_back(sock);
    }
}

/*! Broadcasts a message to all connected clients.
    \param msg the message as JSON string
 */
void WebSocketServer::broadcastTextMessage(const QString &msg)
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = clients[i];

        if (sock->state() == QAbstractSocket::ConnectedState)
        {
            sock->sendTextMessage(msg);
        }
        else
        {
            DBG_Printf(DBG_INFO, "Remove websocket %s:%u\n", qPrintable(sock->peerAddress().toString()), sock->peerPort());
            sock->deleteLater();
            clients[i] = clients.back();
            clients.pop_back();
        }
    }
}
#else // no websockets
  WebSocketServer::WebSocketServer(QObject *parent) :
      QObject(parent)
  { }
  void WebSocketServer::onNewConnection() { }
  void WebSocketServer::broadcastTextMessage(const QString &) { }
  quint16 WebSocketServer::port() const {  return 0; }
#endif
<|endoftext|>


<commit_before><commit_msg>switch AttrListPtr::get to take an ArrayRef, simplifying a lot of clients.<commit_after><|endoftext|>


<commit_before>/*********************************************************************
** Author: Zach Colbert
** Date: 27 September 2017
** Description: A simple input/output program with mathematical operations. By prompting the user for three floats, the program will calculate and output a sum.
*********************************************************************/

#include <iostream>
using namespace std;

// A simple input/output program with mathematical operations.
int main()
{

}
<commit_msg>Added comments to outline the program<commit_after>/*********************************************************************
** Author: Zach Colbert
** Date: 27 September 2017
** Description: A simple input/output program with mathematical operations. By prompting the user for three floats, the program will calculate and output a sum.
*********************************************************************/

#include <iostream>
using namespace std;

// A simple input/output program with mathematical operations.
int main()
{
  // Declare variables for each of the input and output values

  // Prompt the user, get the soil cost

  // Prompt the user, get the seed cost

  // Prompt the user, get the fence cost

  // Calculate the total cost of the three items

  // Display the total cost

}
<|endoftext|>


<commit_before>/* Copyright (c) 2014 Quanta Research Cambridge, Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <stdio.h>
#include <stdint.h>
#include <semaphore.h>

#include "dmaManager.h"
#include "StdDmaIndication.h"
#include "MemServerRequest.h"
#include "MMURequest.h"
#include "MemcopyIndication.h"
#include "MemcopyRequest.h"

static void memdump(unsigned char *p, int len, const char *title)
{
int i;

    i = 0;
    while (len > 0) {
        if (!(i & 0xf)) {
            if (i > 0)
                printf("\n");
            printf("%s: ",title);
        }
        printf("%02x ", *p++);
        i++;
        len--;
    }
    printf("\n");
}

static sem_t done_sem;
class MemcopyIndication : public MemcopyIndicationWrapper
{
public:
  MemcopyIndication(int id) : MemcopyIndicationWrapper(id){}

  virtual void copyDone ( uint32_t srcGen ){
    fprintf(stderr, "Memcopy::writeDone (%08x)\n", srcGen);
    sem_post(&done_sem);
  }
  virtual void copyProgress ( uint32_t numtodo ){
    fprintf(stderr, "Memcopy::writeProgress (%08x)\n", numtodo);
  }
};

int main(int argc, const char **argv)
{
  size_t alloc_sz = 4096;
  MemcopyRequestProxy *device = new MemcopyRequestProxy(IfcNames_MemcopyRequestS2H);
  MemcopyIndication *deviceIndication = new MemcopyIndication(IfcNames_MemcopyIndicationH2S);
  MemServerRequestProxy *memServerRequest = new MemServerRequestProxy(IfcNames_MemServerRequestS2H);
  MMURequestProxy *dmap = new MMURequestProxy(IfcNames_MMURequestS2H);
  DmaManager *dma = new DmaManager(dmap);
  MemServerIndication *memServerIndication = new MemServerIndication(memServerRequest, IfcNames_MemServerIndicationH2S);
  MMUIndication *mmuIndication = new MMUIndication(dma, IfcNames_MMUIndicationH2S);

  sem_init(&done_sem, 1, 0);
  portalExec_start();

  int srcAlloc = portalAllocCached(alloc_sz, 1);
  unsigned int *srcBuffer = (unsigned int *)portalMmap(srcAlloc, alloc_sz);
  int dstAlloc = portalAllocCached(alloc_sz, 1);
  unsigned int *dstBuffer = (unsigned int *)portalMmap(dstAlloc, alloc_sz);

  for (int i = 0; i < alloc_sz/sizeof(uint32_t); i++) {
    srcBuffer[i] = 7*i-3;
    dstBuffer[i] = 0xDEADBEEF;
  }

#ifndef USE_ACP
  fprintf(stderr, "flushing cache\n");
  portalDCacheFlushInval(dstAlloc, alloc_sz, dstBuffer);
#endif

  fprintf(stderr, "parent::starting write\n");
  unsigned int ref_srcAlloc = dma->reference(srcAlloc);
  unsigned int ref_dstAlloc = dma->reference(dstAlloc);
  int burstLenBytes = 16*sizeof(uint32_t);
  device->startCopy(ref_srcAlloc, ref_dstAlloc, alloc_sz, alloc_sz / burstLenBytes, burstLenBytes);

  sem_wait(&done_sem);
  memdump((unsigned char *)dstBuffer, 32, "MEM");
  int mismatchCount = 0;
  for (int i = 0; i < alloc_sz/sizeof(uint32_t); i++) {
    if (dstBuffer[i] != srcBuffer[i])
      mismatchCount++;
  }
  fprintf(stderr, "%s: done mismatchCount=%d\n", __FUNCTION__, mismatchCount);
  return (mismatchCount == 0) ? 0 : 1;
}
<commit_msg>fixed compilation of memserver_copy<commit_after>/* Copyright (c) 2014 Quanta Research Cambridge, Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <stdio.h>
#include <stdint.h>
#include <semaphore.h>

#include "dmaManager.h"
#include "StdDmaIndication.h"
#include "MemServerRequest.h"
#include "MMURequest.h"
#include "MemcopyIndication.h"
#include "MemcopyRequest.h"

static void memdump(unsigned char *p, int len, const char *title)
{
int i;

    i = 0;
    while (len > 0) {
        if (!(i & 0xf)) {
            if (i > 0)
                printf("\n");
            printf("%s: ",title);
        }
        printf("%02x ", *p++);
        i++;
        len--;
    }
    printf("\n");
}

static sem_t done_sem;
class MemcopyIndication : public MemcopyIndicationWrapper
{
public:
  MemcopyIndication(int id) : MemcopyIndicationWrapper(id){}

  virtual void copyDone ( uint32_t srcGen ){
    fprintf(stderr, "Memcopy::writeDone (%08x)\n", srcGen);
    sem_post(&done_sem);
  }
  virtual void copyProgress ( uint32_t numtodo ){
    fprintf(stderr, "Memcopy::writeProgress (%08x)\n", numtodo);
  }
};

int main(int argc, const char **argv)
{
  size_t alloc_sz = 4096;
  MemcopyRequestProxy *device = new MemcopyRequestProxy(IfcNames_MemcopyRequestS2H);
  MemcopyIndication deviceIndication(IfcNames_MemcopyIndicationH2S);
  MemServerRequestProxy *memServerRequest = new MemServerRequestProxy(IfcNames_MemServerRequestS2H);
  MMURequestProxy *dmap = new MMURequestProxy(IfcNames_MMURequestS2H);
  DmaManager *dma = new DmaManager(dmap);
  MemServerIndication memServerIndication(memServerRequest, IfcNames_MemServerIndicationH2S);
  MMUIndication mmuIndication(dma, IfcNames_MMUIndicationH2S);

  sem_init(&done_sem, 1, 0);
  portalExec_start();

  int srcAlloc = portalAllocCached(alloc_sz, 1);
  unsigned int *srcBuffer = (unsigned int *)portalMmap(srcAlloc, alloc_sz);
  int dstAlloc = portalAllocCached(alloc_sz, 1);
  unsigned int *dstBuffer = (unsigned int *)portalMmap(dstAlloc, alloc_sz);

  for (size_t i = 0; i < alloc_sz/sizeof(uint32_t); i++) {
    srcBuffer[i] = 7*i-3;
    dstBuffer[i] = 0xDEADBEEF;
  }

#ifndef USE_ACP
  fprintf(stderr, "flushing cache\n");
  portalDCacheFlushInval(dstAlloc, alloc_sz, dstBuffer);
#endif

  fprintf(stderr, "parent::starting write\n");
  unsigned int ref_srcAlloc = dma->reference(srcAlloc);
  unsigned int ref_dstAlloc = dma->reference(dstAlloc);
  int burstLenBytes = 16*sizeof(uint32_t);
  device->startCopy(ref_srcAlloc, ref_dstAlloc, alloc_sz, alloc_sz / burstLenBytes, burstLenBytes);

  sem_wait(&done_sem);
  memdump((unsigned char *)dstBuffer, 32, "MEM");
  int mismatchCount = 0;
  for (size_t i = 0; i < alloc_sz/sizeof(uint32_t); i++) {
    if (dstBuffer[i] != srcBuffer[i])
      mismatchCount++;
  }
  fprintf(stderr, "%s: done mismatchCount=%d\n", __FUNCTION__, mismatchCount);
  return (mismatchCount == 0) ? 0 : 1;
}
<|endoftext|>


<commit_before><commit_msg>tdf#39468 Translate German Comments - filter/source/graphicfilter/eps/eps.cxx<commit_after><|endoftext|>


<commit_before>#include "signal.h"
#include "FGlib.h"
#include "matrix/kmeans.h"
#include "libgraph-algs/sem_kmeans.h"

using namespace fg;

static bool is_file_exist(const char *fileName) {
    std::ifstream infile(fileName);
    return infile.good();
}

static void int_handler(int sig_num) { exit(0); }
static void print_usage();

int main(int argc, char* argv[]) {

    if (argc < 5) {
        print_usage();
        exit(EXIT_FAILURE);
    }

	int opt;
    std::string datafn = std::string(argv[1]);
    unsigned nrow = atol(argv[2]);
    unsigned ncol = atol(argv[3]);
    unsigned k = atol(argv[4]);

    std::string dist_type = "eucl";
    std::string centersfn = "";
	unsigned max_iters=std::numeric_limits<unsigned>::max();
	std::string init = "kmeanspp";
	unsigned nthread = 1024;
	int num_opts = 0;
	double tolerance = -1;

    // Increase by 3 -- getopt ignores argv[0]
	argv += 3;
	argc -= 3;

	signal(SIGINT, int_handler);
	while ((opt = getopt(argc, argv, "l:i:t:T:d:C:")) != -1) {
		num_opts++;
		switch (opt) {
			case 'l':
				tolerance = atof(optarg);
				num_opts++;
				break;
			case 'i':
				max_iters = atol(optarg);
				num_opts++;
				break;
			case 't':
				init = optarg;
				num_opts++;
				break;
			case 'T':
				nthread = atoi(optarg);
				num_opts++;
				break;
			case 'd':
				dist_type = std::string(optarg);
				num_opts++;
				break;
			case 'C':
				centersfn = std::string(optarg);
                BOOST_ASSERT_MSG(is_file_exist(centersfn.c_str()), "Centers file name doesn't exit!");
				num_opts++;
				break;
			default:
				print_usage();
		}
	}

    bin_reader<double> br(datafn, nrow, ncol);
    double* p_data = new double [nrow*ncol];
    br.read(p_data);
    printf("Read data!\n");

    double* p_centers = new double [k*ncol];

    if (is_file_exist(centersfn.c_str())) {
        bin_reader<double> br2(centersfn, k, ncol);
        br2.read(p_centers);
        printf("Read centers!\n");
    } else
        printf("No centers to read ..\n");

    unsigned* p_clust_asgns = new unsigned [nrow];
    unsigned* p_clust_asgn_cnt = new unsigned [k];

    compute_kmeans(p_data, p_centers, p_clust_asgns,
            p_clust_asgn_cnt, nrow, ncol, k, max_iters,
            nthread, init, tolerance, dist_type);

    delete [] p_clust_asgns;
    delete [] p_clust_asgn_cnt;

    delete [] p_data;
    delete [] p_centers;

    return EXIT_SUCCESS;
}

void print_usage() {
	fprintf(stderr,
        "test-kmeans data-file num-rows num-cols k [alg-options]\n");
    fprintf(stderr, "-t type: type of initialization for kmeans"
           " ['random', 'forgy', 'kmeanspp', 'none']\n");
    fprintf(stderr, "-T num_thread: The number of OMP threads to run\n");
    fprintf(stderr, "-i iters: maximum number of iterations\n");
    fprintf(stderr, "-C File with initial clusters in same format as data\n");
    fprintf(stderr, "-l tolerance for convergence (1E-6)\n");
    fprintf(stderr, "-d Distance matric [eucl,cos]\n");
}
<commit_msg>[Test]: Test that he centers filename exists if no init type is provided<commit_after>#include "signal.h"
#include "FGlib.h"
#include "matrix/kmeans.h"
#include "libgraph-algs/sem_kmeans.h"

using namespace fg;

static bool is_file_exist(const char *fileName) {
    std::ifstream infile(fileName);
    return infile.good();
}

static void int_handler(int sig_num) { exit(0); }
static void print_usage();

int main(int argc, char* argv[]) {

    if (argc < 5) {
        print_usage();
        exit(EXIT_FAILURE);
    }

	int opt;
    std::string datafn = std::string(argv[1]);
    unsigned nrow = atol(argv[2]);
    unsigned ncol = atol(argv[3]);
    unsigned k = atol(argv[4]);

    std::string dist_type = "eucl";
    std::string centersfn = "";
	unsigned max_iters=std::numeric_limits<unsigned>::max();
	std::string init = "kmeanspp";
	unsigned nthread = 1024;
	int num_opts = 0;
	double tolerance = -1;

    // Increase by 3 -- getopt ignores argv[0]
	argv += 3;
	argc -= 3;

	signal(SIGINT, int_handler);
	while ((opt = getopt(argc, argv, "l:i:t:T:d:C:")) != -1) {
		num_opts++;
		switch (opt) {
			case 'l':
				tolerance = atof(optarg);
				num_opts++;
				break;
			case 'i':
				max_iters = atol(optarg);
				num_opts++;
				break;
			case 't':
				init = optarg;
				num_opts++;
				break;
			case 'T':
				nthread = atoi(optarg);
				num_opts++;
				break;
			case 'd':
				dist_type = std::string(optarg);
				num_opts++;
				break;
			case 'C':
				centersfn = std::string(optarg);
                BOOST_ASSERT_MSG(is_file_exist(centersfn.c_str()), "Centers file name doesn't exit!");
				num_opts++;
				break;
			default:
				print_usage();
		}
	}

    BOOST_ASSERT_MSG(!(init=="none" && centersfn.empty()),
            "Centers file name doesn't exit!");

    bin_reader<double> br(datafn, nrow, ncol);
    double* p_data = new double [nrow*ncol];
    br.read(p_data);
    printf("Read data!\n");

    double* p_centers = new double [k*ncol];

    if (is_file_exist(centersfn.c_str())) {
        bin_reader<double> br2(centersfn, k, ncol);
        br2.read(p_centers);
        printf("Read centers!\n");
    } else
        printf("No centers to read ..\n");

    unsigned* p_clust_asgns = new unsigned [nrow];
    unsigned* p_clust_asgn_cnt = new unsigned [k];

    compute_kmeans(p_data, p_centers, p_clust_asgns,
            p_clust_asgn_cnt, nrow, ncol, k, max_iters,
            nthread, init, tolerance, dist_type);

    delete [] p_clust_asgns;
    delete [] p_clust_asgn_cnt;

    delete [] p_data;
    delete [] p_centers;

    return EXIT_SUCCESS;
}

void print_usage() {
	fprintf(stderr,
        "test-kmeans data-file num-rows num-cols k [alg-options]\n");
    fprintf(stderr, "-t type: type of initialization for kmeans"
           " ['random', 'forgy', 'kmeanspp', 'none']\n");
    fprintf(stderr, "-T num_thread: The number of OMP threads to run\n");
    fprintf(stderr, "-i iters: maximum number of iterations\n");
    fprintf(stderr, "-C File with initial clusters in same format as data\n");
    fprintf(stderr, "-l tolerance for convergence (1E-6)\n");
    fprintf(stderr, "-d Distance matric [eucl,cos]\n");
}
<|endoftext|>


<commit_before>// apt_signs.cxx -- build airport signs on the fly
//
// Written by Curtis Olson, started July 2001.
//
// Copyright (C) 2001  Curtis L. Olson  - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//
// $Id$

#ifdef HAVE_CONFIG_H
#  include <simgear_config.h>
#endif

#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_types.hxx>
#include <simgear/scene/tgdb/leaf.hxx>
#include <simgear/scene/material/mat.hxx>
#include <simgear/scene/material/matlib.hxx>

#include "apt_signs.hxx"

#define TAXI "OBJECT_TAXI_SIGN: "
#define RWY "OBJECT_RUNWAY_SIGN: "

// for temporary storage of sign elements
struct element_info {
    element_info(SGMaterial *m, SGMaterialGlyph *g, double h, bool l)
        : material(m), glyph(g), height(h), lighted(l)
    {
        scale = h * m->get_xsize()
                / (m->get_ysize() < 0.001 ? 1.0 : m->get_ysize());
    }
    SGMaterial *material;
    SGMaterialGlyph *glyph;
    double height;
    double scale;
    bool lighted;
};

// standard panel height sizes
const double HT[5] = {0.460, 0.610, 0.760, 1.220, 0.760};

// translation table for "command" to "glyph name"
struct pair {
    const char *keyword;
    const char *glyph_name;
} cmds[] = {
    {"@u",       "up"},
    {"@d",       "down"},
    {"@l",       "left"},
    {"@lu",      "left-up"},
    {"@ul",      "left-up"},
    {"@ld",      "left-down"},
    {"@dl",      "left-down"},
    {"@r",       "right"},
    {"@ru",      "right-up"},
    {"@ur",      "right-up"},
    {"@rd",      "right-down"},
    {"@dr",      "right-down"},
    {0, 0},
};

// Y ... black on yellow            -> direction, destination, boundary
// R ... white on red               -> mandatory instruction
// L ... yellow on black with frame -> runway/taxiway location
// B ... white on black             -> runway distance remaining
//
// u/d/l/r     ... up/down/left/right arrow or two-letter combinations
//                 thereof (ur, dl, ...)
//
// Example: {l}E|{L}[T]|{Y,ur}L|E{r}
//
ssgBranch *sgMakeTaxiSign( SGMaterialLib *matlib,
                           const string path, const string content )
{
    double sign_height = 1.0;  // meter
    bool lighted = true;

    vector<element_info *> elements;
    element_info *close = 0;
    double total_width = 0.0;
    bool cmd = false;
    char *newmat = "BlackSign";
    int size = -1;
    char oldtype = 0, newtype = 0;

    ssgBranch *object = new ssgBranch();
    object->setName((char *)content.c_str());
    SGMaterial *material = matlib->find(newmat);

    // Part I: parse & measure
    for (const char *s = content.data(); *s; s++) {
        string name;
        const char *newmat = 0;

        if (*s == '{') {
            if (cmd)
                SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unexpected { in sign contents");
            cmd = true;
            continue;

        } else if (*s == '}') {
            if (!cmd)
                SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unexpected } in sign contents");
            cmd = false;
            continue;

        } else if (!cmd) {
            name = *s;

        } else {
            if (*s == ',')
                continue;

            string value;
            for (; *s; s++) {
                name += *s;
                if (s[1] == ',' || s[1] == '}' || s[1] == '=')
                    break;
            }
            if (!*s) {
                SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unclosed { in sign contents");
            } else if (s[1] == '=') {
                for (s += 2; *s; s++) {
                    value += *s;
                    if (s[1] == ',' || s[1] == '}')
                        break;
                }
                if (!*s)
                    SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unclosed { in sign contents");
            }

            if (name == "@size") {
                sign_height = strtod(value.data(), 0);
                continue;
            }

            if (name == "@light") {
                lighted = (value != "0" && value != "no" && value != "off" && value != "false");
                continue;
            }

            if (name == "@material")
                newmat = value.data();
            else if (name.size() == 2 || name.size() == 3) {
                if (name.size() == 3 && name[2] >= '1' && name[2] <= '5') {
                    size = name[2] - '1';
                    name = name.substr(0, 2);
                }

                if (name == "@Y") {
                    if (size < 3) {
                        sign_height = HT[size < 0 ? 2 : size];
                        newmat = "YellowSign";
                        newtype = 'Y';
                    }
                } else if (name == "@R") {
                    if (size < 3) {
                        sign_height = HT[size < 0 ? 2 : size];
                        newmat = "RedSign";
                        newtype = 'R';
                    }
                } else if (name == "@L") {
                    if (size < 3) {
                        sign_height = HT[size < 0 ? 2 : size];
                        newmat = "FramedSign";
                        newtype = 'L';
                    }
                } else if (name == "@B") {
                    if (size < 0 || size == 3 || size == 4) {
                        sign_height = HT[size < 0 ? 3 : size];
                        newmat = "BlackSign";
                        newtype = 'B';
                    }
                }
            }

            if (newmat) {
                material = matlib->find(newmat);
                continue;
            }

            for (int i = 0; cmds[i].keyword; i++) {
                if (name == cmds[i].keyword) {
                    name = cmds[i].glyph_name;
                    break;
                }
            }

            if (name[0] == '@') {
                SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "ignoring unknown command `" << name << '\'');
                continue;
            }
        }

        if (!material) {
            SG_LOG( SG_TERRAIN, SG_ALERT, TAXI "material doesn't exit");
            continue;
        }

        SGMaterialGlyph *glyph = material->get_glyph(name);
        if (!glyph) {
            SG_LOG( SG_TERRAIN, SG_ALERT, TAXI "unsupported glyph `" << *s << '\'');
            continue;
        }

        // in managed mode push frame stop and frame start first
        element_info *e;
        if (newtype && newtype != oldtype) {
            if (close) {
                elements.push_back(close);
                total_width += close->glyph->get_width() * close->scale;
                close = 0;
            }
            oldtype = newtype;
            SGMaterialGlyph *g = material->get_glyph("stop-frame");
            if (g)
                close = new element_info(material, g, sign_height, lighted);
            g = material->get_glyph("start-frame");
            if (g) {
                e = new element_info(material, g, sign_height, lighted);
                elements.push_back(e);
                total_width += e->glyph->get_width() * e->scale;
            }
        }
        // now the actually requested glyph
        e = new element_info(material, glyph, sign_height, lighted);
        elements.push_back(e);
        total_width += e->glyph->get_width() * e->scale;
    }

    // in managed mode close frame
    if (close) {
        elements.push_back(close);
        total_width += close->glyph->get_width() * close->scale;
        close = 0;
    }

    // Part II: typeset
    double hpos = -total_width / 2;
    const double dist = 0.25;        // hard-code distance from surface for now

    sgVec3 normal;
    sgSetVec3(normal, 0, -1, 0);

    sgVec4 color;
    sgSetVec4(color, 1.0, 1.0, 1.0, 1.0);

    for (unsigned int i = 0; i < elements.size(); i++) {
        element_info *element = elements[i];

        double xoffset = element->glyph->get_left();
        double height = element->height;
        double width = element->glyph->get_width();
        double abswidth = width * element->scale;

        // vertices
        ssgVertexArray *vl = new ssgVertexArray(4);
        vl->add(hpos,            0, dist);
        vl->add(hpos + abswidth, 0, dist);
        vl->add(hpos,            0, dist + height);
        vl->add(hpos + abswidth, 0, dist + height);

        // texture coordinates
        ssgTexCoordArray *tl = new ssgTexCoordArray(4);
        tl->add(xoffset,         0);
        tl->add(xoffset + width, 0);
        tl->add(xoffset,         1);
        tl->add(xoffset + width, 1);

        // normals
        ssgNormalArray *nl = new ssgNormalArray(1);
        nl->add(normal);

        // colors
        ssgColourArray *cl = new ssgColourArray(1);
        cl->add(color);

        ssgLeaf *leaf = new ssgVtxTable(GL_TRIANGLE_STRIP, vl, nl, tl, cl);
        ssgSimpleState *state = element->material->get_state();
        if (!element->lighted) {
            // FIXME: clone state for unlighted elements only once per material
            state = (ssgSimpleState *)state->clone(SSG_CLONE_STATE);
            state->setMaterial(GL_EMISSION, 0.3, 0.3, 0.3, 1);
        }
        leaf->setState(state);

        object->addKid(leaf);
        hpos += abswidth;
        delete element;
    }

    // minimalistic backside
    ssgVertexArray *vl = new ssgVertexArray(4);
    vl->add(hpos,               0, dist);
    vl->add(hpos - total_width, 0, dist);
    vl->add(hpos,               0, dist + sign_height);
    vl->add(hpos - total_width, 0, dist + sign_height);

    ssgNormalArray *nl = new ssgNormalArray(1);
    nl->add(0, 1, 0);

    ssgLeaf *leaf = new ssgVtxTable(GL_TRIANGLE_STRIP, vl, nl, 0, 0);
    SGMaterial *mat = matlib->find("BlackSign");
    if (mat)
        leaf->setState(mat->get_state());
    object->addKid(leaf);

    return object;
}

ssgBranch *sgMakeRunwaySign( SGMaterialLib *matlib,
                             const string path, const string name )
{
    // for demo purposes we assume each element (letter) is 1x1 meter.
    // Sign is placed 0.25 meters above the ground

    ssgBranch *object = new ssgBranch();
    object->setName( (char *)name.c_str() );

    double width = name.length() / 3.0;

    string material = name;

    point_list nodes;
    point_list normals;
    point_list texcoords;
    int_list vertex_index;
    int_list normal_index;
    int_list tex_index;

    nodes.push_back( Point3D( -width, 0, 0.25 ) );
    nodes.push_back( Point3D( width + 1, 0, 0.25 ) );
    nodes.push_back( Point3D( -width, 0, 1.25 ) );
    nodes.push_back( Point3D( width + 1, 0, 1.25 ) );

    normals.push_back( Point3D( 0, -1, 0 ) );

    texcoords.push_back( Point3D( 0, 0, 0 ) );
    texcoords.push_back( Point3D( 1, 0, 0 ) );
    texcoords.push_back( Point3D( 0, 1, 0 ) );
    texcoords.push_back( Point3D( 1, 1, 0 ) );

    vertex_index.push_back( 0 );
    vertex_index.push_back( 1 );
    vertex_index.push_back( 2 );
    vertex_index.push_back( 3 );

    normal_index.push_back( 0 );
    normal_index.push_back( 0 );
    normal_index.push_back( 0 );
    normal_index.push_back( 0 );

    tex_index.push_back( 0 );
    tex_index.push_back( 1 );
    tex_index.push_back( 2 );
    tex_index.push_back( 3 );

    ssgLeaf *leaf = sgMakeLeaf( path, GL_TRIANGLE_STRIP, matlib, material,
                                nodes, normals, texcoords,
                                vertex_index, normal_index, tex_index,
                                false, NULL );

    object->addKid( leaf );

    return object;
}
<commit_msg>set sign orientation such, that when the sign heading=0, one looks straight on the sign face when looking North<commit_after>// apt_signs.cxx -- build airport signs on the fly
//
// Written by Curtis Olson, started July 2001.
//
// Copyright (C) 2001  Curtis L. Olson  - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//
// $Id$

#ifdef HAVE_CONFIG_H
#  include <simgear_config.h>
#endif

#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_types.hxx>
#include <simgear/scene/tgdb/leaf.hxx>
#include <simgear/scene/material/mat.hxx>
#include <simgear/scene/material/matlib.hxx>

#include "apt_signs.hxx"

#define TAXI "OBJECT_TAXI_SIGN: "
#define RWY "OBJECT_RUNWAY_SIGN: "

// for temporary storage of sign elements
struct element_info {
    element_info(SGMaterial *m, SGMaterialGlyph *g, double h, bool l)
        : material(m), glyph(g), height(h), lighted(l)
    {
        scale = h * m->get_xsize()
                / (m->get_ysize() < 0.001 ? 1.0 : m->get_ysize());
    }
    SGMaterial *material;
    SGMaterialGlyph *glyph;
    double height;
    double scale;
    bool lighted;
};

// standard panel height sizes
const double HT[5] = {0.460, 0.610, 0.760, 1.220, 0.760};

// translation table for "command" to "glyph name"
struct pair {
    const char *keyword;
    const char *glyph_name;
} cmds[] = {
    {"@u",       "up"},
    {"@d",       "down"},
    {"@l",       "left"},
    {"@lu",      "left-up"},
    {"@ul",      "left-up"},
    {"@ld",      "left-down"},
    {"@dl",      "left-down"},
    {"@r",       "right"},
    {"@ru",      "right-up"},
    {"@ur",      "right-up"},
    {"@rd",      "right-down"},
    {"@dr",      "right-down"},
    {0, 0},
};

// Y ... black on yellow            -> direction, destination, boundary
// R ... white on red               -> mandatory instruction
// L ... yellow on black with frame -> runway/taxiway location
// B ... white on black             -> runway distance remaining
//
// u/d/l/r     ... up/down/left/right arrow or two-letter combinations
//                 thereof (ur, dl, ...)
//
// Example: {l}E|{L}[T]|{Y,ur}L|E{r}
//
ssgBranch *sgMakeTaxiSign( SGMaterialLib *matlib,
                           const string path, const string content )
{
    double sign_height = 1.0;  // meter
    bool lighted = true;

    vector<element_info *> elements;
    element_info *close = 0;
    double total_width = 0.0;
    bool cmd = false;
    char *newmat = "BlackSign";
    int size = -1;
    char oldtype = 0, newtype = 0;

    ssgBranch *object = new ssgBranch();
    object->setName((char *)content.c_str());
    SGMaterial *material = matlib->find(newmat);

    // Part I: parse & measure
    for (const char *s = content.data(); *s; s++) {
        string name;
        const char *newmat = 0;

        if (*s == '{') {
            if (cmd)
                SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unexpected { in sign contents");
            cmd = true;
            continue;

        } else if (*s == '}') {
            if (!cmd)
                SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unexpected } in sign contents");
            cmd = false;
            continue;

        } else if (!cmd) {
            name = *s;

        } else {
            if (*s == ',')
                continue;

            string value;
            for (; *s; s++) {
                name += *s;
                if (s[1] == ',' || s[1] == '}' || s[1] == '=')
                    break;
            }
            if (!*s) {
                SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unclosed { in sign contents");
            } else if (s[1] == '=') {
                for (s += 2; *s; s++) {
                    value += *s;
                    if (s[1] == ',' || s[1] == '}')
                        break;
                }
                if (!*s)
                    SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unclosed { in sign contents");
            }

            if (name == "@size") {
                sign_height = strtod(value.data(), 0);
                continue;
            }

            if (name == "@light") {
                lighted = (value != "0" && value != "no" && value != "off" && value != "false");
                continue;
            }

            if (name == "@material")
                newmat = value.data();
            else if (name.size() == 2 || name.size() == 3) {
                if (name.size() == 3 && name[2] >= '1' && name[2] <= '5') {
                    size = name[2] - '1';
                    name = name.substr(0, 2);
                }

                if (name == "@Y") {
                    if (size < 3) {
                        sign_height = HT[size < 0 ? 2 : size];
                        newmat = "YellowSign";
                        newtype = 'Y';
                    }
                } else if (name == "@R") {
                    if (size < 3) {
                        sign_height = HT[size < 0 ? 2 : size];
                        newmat = "RedSign";
                        newtype = 'R';
                    }
                } else if (name == "@L") {
                    if (size < 3) {
                        sign_height = HT[size < 0 ? 2 : size];
                        newmat = "FramedSign";
                        newtype = 'L';
                    }
                } else if (name == "@B") {
                    if (size < 0 || size == 3 || size == 4) {
                        sign_height = HT[size < 0 ? 3 : size];
                        newmat = "BlackSign";
                        newtype = 'B';
                    }
                }
            }

            if (newmat) {
                material = matlib->find(newmat);
                continue;
            }

            for (int i = 0; cmds[i].keyword; i++) {
                if (name == cmds[i].keyword) {
                    name = cmds[i].glyph_name;
                    break;
                }
            }

            if (name[0] == '@') {
                SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "ignoring unknown command `" << name << '\'');
                continue;
            }
        }

        if (!material) {
            SG_LOG( SG_TERRAIN, SG_ALERT, TAXI "material doesn't exit");
            continue;
        }

        SGMaterialGlyph *glyph = material->get_glyph(name);
        if (!glyph) {
            SG_LOG( SG_TERRAIN, SG_ALERT, TAXI "unsupported glyph `" << *s << '\'');
            continue;
        }

        // in managed mode push frame stop and frame start first
        element_info *e;
        if (newtype && newtype != oldtype) {
            if (close) {
                elements.push_back(close);
                total_width += close->glyph->get_width() * close->scale;
                close = 0;
            }
            oldtype = newtype;
            SGMaterialGlyph *g = material->get_glyph("stop-frame");
            if (g)
                close = new element_info(material, g, sign_height, lighted);
            g = material->get_glyph("start-frame");
            if (g) {
                e = new element_info(material, g, sign_height, lighted);
                elements.push_back(e);
                total_width += e->glyph->get_width() * e->scale;
            }
        }
        // now the actually requested glyph
        e = new element_info(material, glyph, sign_height, lighted);
        elements.push_back(e);
        total_width += e->glyph->get_width() * e->scale;
    }

    // in managed mode close frame
    if (close) {
        elements.push_back(close);
        total_width += close->glyph->get_width() * close->scale;
        close = 0;
    }

    // Part II: typeset
    double hpos = -total_width / 2;
    const double dist = 0.25;        // hard-code distance from surface for now

    sgVec3 normal;
    sgSetVec3(normal, 0, -1, 0);

    sgVec4 color;
    sgSetVec4(color, 1.0, 1.0, 1.0, 1.0);

    for (unsigned int i = 0; i < elements.size(); i++) {
        element_info *element = elements[i];

        double xoffset = element->glyph->get_left();
        double height = element->height;
        double width = element->glyph->get_width();
        double abswidth = width * element->scale;

        // vertices
        ssgVertexArray *vl = new ssgVertexArray(4);
        vl->add(0, hpos,            dist);
        vl->add(0, hpos + abswidth, dist);
        vl->add(0, hpos,            dist + height);
        vl->add(0, hpos + abswidth, dist + height);

        // texture coordinates
        ssgTexCoordArray *tl = new ssgTexCoordArray(4);
        tl->add(xoffset,         0);
        tl->add(xoffset + width, 0);
        tl->add(xoffset,         1);
        tl->add(xoffset + width, 1);

        // normals
        ssgNormalArray *nl = new ssgNormalArray(1);
        nl->add(normal);

        // colors
        ssgColourArray *cl = new ssgColourArray(1);
        cl->add(color);

        ssgLeaf *leaf = new ssgVtxTable(GL_TRIANGLE_STRIP, vl, nl, tl, cl);
        ssgSimpleState *state = element->material->get_state();
        if (!element->lighted) {
            // FIXME: clone state for unlighted elements only once per material
            state = (ssgSimpleState *)state->clone(SSG_CLONE_STATE);
            state->setMaterial(GL_EMISSION, 0.3, 0.3, 0.3, 1);
        }
        leaf->setState(state);

        object->addKid(leaf);
        hpos += abswidth;
        delete element;
    }

    // minimalistic backside
    ssgVertexArray *vl = new ssgVertexArray(4);
    vl->add(0, hpos,               dist);
    vl->add(0, hpos - total_width, dist);
    vl->add(0, hpos,               dist + sign_height);
    vl->add(0, hpos - total_width, dist + sign_height);

    ssgNormalArray *nl = new ssgNormalArray(1);
    nl->add(0, 1, 0);

    ssgLeaf *leaf = new ssgVtxTable(GL_TRIANGLE_STRIP, vl, nl, 0, 0);
    SGMaterial *mat = matlib->find("BlackSign");
    if (mat)
        leaf->setState(mat->get_state());
    object->addKid(leaf);

    return object;
}

ssgBranch *sgMakeRunwaySign( SGMaterialLib *matlib,
                             const string path, const string name )
{
    // for demo purposes we assume each element (letter) is 1x1 meter.
    // Sign is placed 0.25 meters above the ground

    ssgBranch *object = new ssgBranch();
    object->setName( (char *)name.c_str() );

    double width = name.length() / 3.0;

    string material = name;

    point_list nodes;
    point_list normals;
    point_list texcoords;
    int_list vertex_index;
    int_list normal_index;
    int_list tex_index;

    nodes.push_back( Point3D( -width, 0, 0.25 ) );
    nodes.push_back( Point3D( width + 1, 0, 0.25 ) );
    nodes.push_back( Point3D( -width, 0, 1.25 ) );
    nodes.push_back( Point3D( width + 1, 0, 1.25 ) );

    normals.push_back( Point3D( 0, -1, 0 ) );

    texcoords.push_back( Point3D( 0, 0, 0 ) );
    texcoords.push_back( Point3D( 1, 0, 0 ) );
    texcoords.push_back( Point3D( 0, 1, 0 ) );
    texcoords.push_back( Point3D( 1, 1, 0 ) );

    vertex_index.push_back( 0 );
    vertex_index.push_back( 1 );
    vertex_index.push_back( 2 );
    vertex_index.push_back( 3 );

    normal_index.push_back( 0 );
    normal_index.push_back( 0 );
    normal_index.push_back( 0 );
    normal_index.push_back( 0 );

    tex_index.push_back( 0 );
    tex_index.push_back( 1 );
    tex_index.push_back( 2 );
    tex_index.push_back( 3 );

    ssgLeaf *leaf = sgMakeLeaf( path, GL_TRIANGLE_STRIP, matlib, material,
                                nodes, normals, texcoords,
                                vertex_index, normal_index, tex_index,
                                false, NULL );

    object->addKid( leaf );

    return object;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: vclxfont.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2001-09-28 09:38:18 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _TOOLKIT_AWT_VCLXFONT_HXX_
#define _TOOLKIT_AWT_VCLXFONT_HXX_

#ifndef _COM_SUN_STAR_AWT_XFONT_HPP_
#include <com/sun/star/awt/XFont.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_XDEVICE_HPP_
#include <com/sun/star/awt/XDevice.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif

#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#ifndef _SV_METRIC_HXX
#include <vcl/metric.hxx>
#endif

//  ----------------------------------------------------
//  class VCLXFont
//  ----------------------------------------------------

class VCLXFont :    public ::com::sun::star::awt::XFont,
                    public ::com::sun::star::lang::XTypeProvider,
                    public ::com::sun::star::lang::XUnoTunnel,
                    public ::cppu::OWeakObject
{
private:
    ::osl::Mutex    maMutex;
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice> mxDevice;
    Font            maFont;
    FontMetric*     mpFontMetric;

protected:
    BOOL            ImplAssertValidFontMetric();
    ::osl::Mutex&   GetMutex() { return maMutex; }

public:
                    VCLXFont();
                    ~VCLXFont();

    void            Init( ::com::sun::star::awt::XDevice& rxDev, const Font& rFont );
    const Font&     GetFont() const { return maFont; }

    // ::com::sun::star::uno::XInterface
    ::com::sun::star::uno::Any                  SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException);
    void                                        SAL_CALL acquire() throw()  { OWeakObject::acquire(); }
    void                                        SAL_CALL release() throw()  { OWeakObject::release(); }

    // ::com::sun::star::lang::XUnoTunnel
    static const ::com::sun::star::uno::Sequence< sal_Int8 >&   GetUnoTunnelId() throw();
    static VCLXFont*                                            GetImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIFace ) throw();
    sal_Int64                                                   SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rIdentifier ) throw(::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::lang::XTypeProvider
    ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type >  SAL_CALL getTypes() throw(::com::sun::star::uno::RuntimeException);
    ::com::sun::star::uno::Sequence< sal_Int8 >                     SAL_CALL getImplementationId() throw(::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::lang::XFont
    ::com::sun::star::awt::FontDescriptor           SAL_CALL getFontDescriptor(  ) throw(::com::sun::star::uno::RuntimeException);
    ::com::sun::star::awt::SimpleFontMetric         SAL_CALL getFontMetric(  ) throw(::com::sun::star::uno::RuntimeException);
    sal_Int16                                       SAL_CALL getCharWidth( sal_Unicode c ) throw(::com::sun::star::uno::RuntimeException);
    ::com::sun::star::uno::Sequence< sal_Int16 >    SAL_CALL getCharWidths( sal_Unicode nFirst, sal_Unicode nLast ) throw(::com::sun::star::uno::RuntimeException);
    sal_Int32                                       SAL_CALL getStringWidth( const ::rtl::OUString& str ) throw(::com::sun::star::uno::RuntimeException);
    sal_Int32                                       SAL_CALL getStringWidthArray( const ::rtl::OUString& str, ::com::sun::star::uno::Sequence< sal_Int32 >& rDXArray ) throw(::com::sun::star::uno::RuntimeException);
    void                                            SAL_CALL getKernPairs( ::com::sun::star::uno::Sequence< sal_Unicode >& rnChars1, ::com::sun::star::uno::Sequence< sal_Unicode >& rnChars2, ::com::sun::star::uno::Sequence< sal_Int16 >& rnKerns ) throw(::com::sun::star::uno::RuntimeException);
};

#endif // _TOOLKIT_AWT_VCLXFONT_HXX_

<commit_msg>INTEGRATION: CWS sb25 (1.2.332); FILE MERGED 2004/11/25 18:14:40 mt 1.2.332.1: #i37760# Less exports...<commit_after>/*************************************************************************
 *
 *  $RCSfile: vclxfont.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-01-11 14:03:30 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _TOOLKIT_AWT_VCLXFONT_HXX_
#define _TOOLKIT_AWT_VCLXFONT_HXX_

#ifndef TOOLKIT_DLLAPI_H
#include <toolkit/dllapi.h>
#endif

#ifndef _COM_SUN_STAR_AWT_XFONT_HPP_
#include <com/sun/star/awt/XFont.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_XDEVICE_HPP_
#include <com/sun/star/awt/XDevice.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif

#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#ifndef _SV_METRIC_HXX
#include <vcl/metric.hxx>
#endif

//  ----------------------------------------------------
//  class VCLXFont
//  ----------------------------------------------------

class TOOLKIT_DLLPUBLIC VCLXFont :  public ::com::sun::star::awt::XFont,
                    public ::com::sun::star::lang::XTypeProvider,
                    public ::com::sun::star::lang::XUnoTunnel,
                    public ::cppu::OWeakObject
{
private:
    ::osl::Mutex    maMutex;
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice> mxDevice;
    Font            maFont;
    FontMetric*     mpFontMetric;

protected:
    BOOL            ImplAssertValidFontMetric();
    ::osl::Mutex&   GetMutex() { return maMutex; }

public:
                    VCLXFont();
                    ~VCLXFont();

    void            Init( ::com::sun::star::awt::XDevice& rxDev, const Font& rFont );
    const Font&     GetFont() const { return maFont; }

    // ::com::sun::star::uno::XInterface
    ::com::sun::star::uno::Any                  SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException);
    void                                        SAL_CALL acquire() throw()  { OWeakObject::acquire(); }
    void                                        SAL_CALL release() throw()  { OWeakObject::release(); }

    // ::com::sun::star::lang::XUnoTunnel
    static const ::com::sun::star::uno::Sequence< sal_Int8 >&   GetUnoTunnelId() throw();
    static VCLXFont*                                            GetImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIFace ) throw();
    sal_Int64                                                   SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rIdentifier ) throw(::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::lang::XTypeProvider
    ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type >  SAL_CALL getTypes() throw(::com::sun::star::uno::RuntimeException);
    ::com::sun::star::uno::Sequence< sal_Int8 >                     SAL_CALL getImplementationId() throw(::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::lang::XFont
    ::com::sun::star::awt::FontDescriptor           SAL_CALL getFontDescriptor(  ) throw(::com::sun::star::uno::RuntimeException);
    ::com::sun::star::awt::SimpleFontMetric         SAL_CALL getFontMetric(  ) throw(::com::sun::star::uno::RuntimeException);
    sal_Int16                                       SAL_CALL getCharWidth( sal_Unicode c ) throw(::com::sun::star::uno::RuntimeException);
    ::com::sun::star::uno::Sequence< sal_Int16 >    SAL_CALL getCharWidths( sal_Unicode nFirst, sal_Unicode nLast ) throw(::com::sun::star::uno::RuntimeException);
    sal_Int32                                       SAL_CALL getStringWidth( const ::rtl::OUString& str ) throw(::com::sun::star::uno::RuntimeException);
    sal_Int32                                       SAL_CALL getStringWidthArray( const ::rtl::OUString& str, ::com::sun::star::uno::Sequence< sal_Int32 >& rDXArray ) throw(::com::sun::star::uno::RuntimeException);
    void                                            SAL_CALL getKernPairs( ::com::sun::star::uno::Sequence< sal_Unicode >& rnChars1, ::com::sun::star::uno::Sequence< sal_Unicode >& rnChars2, ::com::sun::star::uno::Sequence< sal_Int16 >& rnKerns ) throw(::com::sun::star::uno::RuntimeException);
};

#endif // _TOOLKIT_AWT_VCLXFONT_HXX_

<|endoftext|>


<commit_before><commit_msg>WaE: NULL used in arithmetic<commit_after><|endoftext|>