<commit_before>/*
 * ngtcp2
 *
 * Copyright (c) 2020 ngtcp2 contributors
 *
 * 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 "tls_server_context_openssl.h"

#include <iostream>
#include <fstream>
#include <limits>

#include <ngtcp2/ngtcp2_crypto_openssl.h>

#include <openssl/err.h>

#include "server_base.h"
#include "template.h"

extern Config config;

TLSServerContext::TLSServerContext() : ssl_ctx_{nullptr} {}

TLSServerContext::~TLSServerContext() {
  if (ssl_ctx_) {
    SSL_CTX_free(ssl_ctx_);
  }
}

SSL_CTX *TLSServerContext::get_native_handle() const { return ssl_ctx_; }

namespace {
int alpn_select_proto_h3_cb(SSL *ssl, const unsigned char **out,
                            unsigned char *outlen, const unsigned char *in,
                            unsigned int inlen, void *arg) {
  auto conn_ref = static_cast<ngtcp2_crypto_conn_ref *>(SSL_get_app_data(ssl));
  auto h = static_cast<HandlerBase *>(conn_ref->user_data);
  const uint8_t *alpn;
  size_t alpnlen;
  // This should be the negotiated version, but we have not set the
  // negotiated version when this callback is called.
  auto version = ngtcp2_conn_get_client_chosen_version(h->conn());

  switch (version) {
  case QUIC_VER_DRAFT29:
    alpn = reinterpret_cast<const uint8_t *>(H3_ALPN_DRAFT29);
    alpnlen = str_size(H3_ALPN_DRAFT29);
    break;
  case QUIC_VER_DRAFT30:
    alpn = reinterpret_cast<const uint8_t *>(H3_ALPN_DRAFT30);
    alpnlen = str_size(H3_ALPN_DRAFT30);
    break;
  case QUIC_VER_DRAFT31:
    alpn = reinterpret_cast<const uint8_t *>(H3_ALPN_DRAFT31);
    alpnlen = str_size(H3_ALPN_DRAFT31);
    break;
  case QUIC_VER_DRAFT32:
    alpn = reinterpret_cast<const uint8_t *>(H3_ALPN_DRAFT32);
    alpnlen = str_size(H3_ALPN_DRAFT32);
    break;
  case NGTCP2_PROTO_VER_V1:
  case NGTCP2_PROTO_VER_V2_DRAFT:
    alpn = reinterpret_cast<const uint8_t *>(H3_ALPN_V1);
    alpnlen = str_size(H3_ALPN_V1);
    break;
  default:
    if (!config.quiet) {
      std::cerr << "Unexpected quic protocol version: " << std::hex << "0x"
                << version << std::dec << std::endl;
    }
    return SSL_TLSEXT_ERR_ALERT_FATAL;
  }

  for (auto p = in, end = in + inlen; p + alpnlen <= end; p += *p + 1) {
    if (std::equal(alpn, alpn + alpnlen, p)) {
      *out = p + 1;
      *outlen = *p;
      return SSL_TLSEXT_ERR_OK;
    }
  }

  if (!config.quiet) {
    std::cerr << "Client did not present ALPN " << &alpn[1] << std::endl;
  }

  return SSL_TLSEXT_ERR_ALERT_FATAL;
}
} // namespace

namespace {
int alpn_select_proto_hq_cb(SSL *ssl, const unsigned char **out,
                            unsigned char *outlen, const unsigned char *in,
                            unsigned int inlen, void *arg) {
  auto conn_ref = static_cast<ngtcp2_crypto_conn_ref *>(SSL_get_app_data(ssl));
  auto h = static_cast<HandlerBase *>(conn_ref->user_data);
  const uint8_t *alpn;
  size_t alpnlen;
  // This should be the negotiated version, but we have not set the
  // negotiated version when this callback is called.
  auto version = ngtcp2_conn_get_client_chosen_version(h->conn());

  switch (version) {
  case QUIC_VER_DRAFT29:
    alpn = reinterpret_cast<const uint8_t *>(HQ_ALPN_DRAFT29);
    alpnlen = str_size(HQ_ALPN_DRAFT29);
    break;
  case QUIC_VER_DRAFT30:
    alpn = reinterpret_cast<const uint8_t *>(HQ_ALPN_DRAFT30);
    alpnlen = str_size(HQ_ALPN_DRAFT30);
    break;
  case QUIC_VER_DRAFT31:
    alpn = reinterpret_cast<const uint8_t *>(HQ_ALPN_DRAFT31);
    alpnlen = str_size(HQ_ALPN_DRAFT31);
    break;
  case QUIC_VER_DRAFT32:
    alpn = reinterpret_cast<const uint8_t *>(HQ_ALPN_DRAFT32);
    alpnlen = str_size(HQ_ALPN_DRAFT32);
    break;
  case NGTCP2_PROTO_VER_V1:
  case NGTCP2_PROTO_VER_V2_DRAFT:
    alpn = reinterpret_cast<const uint8_t *>(HQ_ALPN_V1);
    alpnlen = str_size(HQ_ALPN_V1);
    break;
  default:
    if (!config.quiet) {
      std::cerr << "Unexpected quic protocol version: " << std::hex << "0x"
                << version << std::dec << std::endl;
    }
    return SSL_TLSEXT_ERR_ALERT_FATAL;
  }

  for (auto p = in, end = in + inlen; p + alpnlen <= end; p += *p + 1) {
    if (std::equal(alpn, alpn + alpnlen, p)) {
      *out = p + 1;
      *outlen = *p;
      return SSL_TLSEXT_ERR_OK;
    }
  }

  if (!config.quiet) {
    std::cerr << "Client did not present ALPN " << &alpn[1] << std::endl;
  }

  return SSL_TLSEXT_ERR_ALERT_FATAL;
}
} // namespace

namespace {
int alpn_select_proto_perf_cb(SSL *ssl, const unsigned char **out,
                              unsigned char *outlen, const unsigned char *in,
                              unsigned int inlen, void *arg) {
  constexpr static uint8_t alpn[] = "\x4perf";
  size_t alpnlen = str_size(alpn);

  for (auto p = in, end = in + inlen; p + alpnlen <= end; p += *p + 1) {
    if (std::equal(alpn, alpn + alpnlen, p)) {
      *out = p + 1;
      *outlen = *p;
      return SSL_TLSEXT_ERR_OK;
    }
  }

  if (!config.quiet) {
    std::cerr << "Client did not present ALPN " << &alpn[1] << std::endl;
  }

  return SSL_TLSEXT_ERR_ALERT_FATAL;
}
} // namespace

namespace {
int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) {
  // We don't verify the client certificate.  Just request it for the
  // testing purpose.
  return 1;
}
} // namespace

namespace {
int gen_ticket_cb(SSL *ssl, void *arg) {
  auto conn_ref = static_cast<ngtcp2_crypto_conn_ref *>(SSL_get_app_data(ssl));
  auto h = static_cast<HandlerBase *>(conn_ref->user_data);
  auto ver = htonl(ngtcp2_conn_get_negotiated_version(h->conn()));

  if (!SSL_SESSION_set1_ticket_appdata(SSL_get0_session(ssl), &ver,
                                       sizeof(ver))) {
    return 0;
  }

  return 1;
}
} // namespace

namespace {
SSL_TICKET_RETURN decrypt_ticket_cb(SSL *ssl, SSL_SESSION *session,
                                    const unsigned char *keyname,
                                    size_t keynamelen, SSL_TICKET_STATUS status,
                                    void *arg) {
  switch (status) {
  case SSL_TICKET_EMPTY:
  case SSL_TICKET_NO_DECRYPT:
    return SSL_TICKET_RETURN_IGNORE_RENEW;
  }

  uint32_t *pver;
  size_t verlen;

  if (!SSL_SESSION_get0_ticket_appdata(
          session, reinterpret_cast<void **>(&pver), &verlen) ||
      verlen != sizeof(*pver)) {
    switch (status) {
    case SSL_TICKET_SUCCESS:
      return SSL_TICKET_RETURN_IGNORE;
    case SSL_TICKET_SUCCESS_RENEW:
    default:
      return SSL_TICKET_RETURN_IGNORE_RENEW;
    }
  }

  auto conn_ref = static_cast<ngtcp2_crypto_conn_ref *>(SSL_get_app_data(ssl));
  auto h = static_cast<HandlerBase *>(conn_ref->user_data);

  if (ngtcp2_conn_get_client_chosen_version(h->conn()) != ntohl(*pver)) {
    switch (status) {
    case SSL_TICKET_SUCCESS:
      return SSL_TICKET_RETURN_IGNORE;
    case SSL_TICKET_SUCCESS_RENEW:
    default:
      return SSL_TICKET_RETURN_IGNORE_RENEW;
    }
  }

  switch (status) {
  case SSL_TICKET_SUCCESS:
    return SSL_TICKET_RETURN_USE;
  case SSL_TICKET_SUCCESS_RENEW:
  default:
    return SSL_TICKET_RETURN_USE_RENEW;
  }
}
} // namespace

int TLSServerContext::init(const char *private_key_file, const char *cert_file,
                           AppProtocol app_proto) {
  constexpr static unsigned char sid_ctx[] = "ngtcp2 server";

  ssl_ctx_ = SSL_CTX_new(TLS_server_method());
  if (!ssl_ctx_) {
    std::cerr << "SSSL_CTX_new: " << ERR_error_string(ERR_get_error(), nullptr)
              << std::endl;
    return -1;
  }

  if (ngtcp2_crypto_openssl_configure_server_context(ssl_ctx_) != 0) {
    std::cerr << "ngtcp2_crypto_openssl_configure_server_context failed"
              << std::endl;
    return -1;
  }

  SSL_CTX_set_max_early_data(ssl_ctx_, UINT32_MAX);

  constexpr auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
                            SSL_OP_SINGLE_ECDH_USE |
                            SSL_OP_CIPHER_SERVER_PREFERENCE |
                            SSL_OP_NO_ANTI_REPLAY;

  SSL_CTX_set_options(ssl_ctx_, ssl_opts);

  if (SSL_CTX_set_ciphersuites(ssl_ctx_, config.ciphers) != 1) {
    std::cerr << "SSL_CTX_set_ciphersuites: "
              << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
    return -1;
  }

  if (SSL_CTX_set1_groups_list(ssl_ctx_, config.groups) != 1) {
    std::cerr << "SSL_CTX_set1_groups_list failed" << std::endl;
    return -1;
  }

  SSL_CTX_set_mode(ssl_ctx_, SSL_MODE_RELEASE_BUFFERS);

  switch (app_proto) {
  case AppProtocol::H3:
    SSL_CTX_set_alpn_select_cb(ssl_ctx_, alpn_select_proto_h3_cb, nullptr);
    break;
  case AppProtocol::HQ:
    SSL_CTX_set_alpn_select_cb(ssl_ctx_, alpn_select_proto_hq_cb, nullptr);
    break;
  case AppProtocol::Perf:
    SSL_CTX_set_alpn_select_cb(ssl_ctx_, alpn_select_proto_perf_cb, nullptr);
    break;
  }

  SSL_CTX_set_default_verify_paths(ssl_ctx_);

  if (SSL_CTX_use_PrivateKey_file(ssl_ctx_, private_key_file,
                                  SSL_FILETYPE_PEM) != 1) {
    std::cerr << "SSL_CTX_use_PrivateKey_file: "
              << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
    return -1;
  }

  if (SSL_CTX_use_certificate_chain_file(ssl_ctx_, cert_file) != 1) {
    std::cerr << "SSL_CTX_use_certificate_chain_file: "
              << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
    return -1;
  }

  if (SSL_CTX_check_private_key(ssl_ctx_) != 1) {
    std::cerr << "SSL_CTX_check_private_key: "
              << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
    return -1;
  }

  SSL_CTX_set_session_id_context(ssl_ctx_, sid_ctx, sizeof(sid_ctx) - 1);

  if (config.verify_client) {
    SSL_CTX_set_verify(ssl_ctx_,
                       SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE |
                           SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                       verify_cb);
  }

  SSL_CTX_set_session_ticket_cb(ssl_ctx_, gen_ticket_cb, decrypt_ticket_cb,
                                nullptr);

  return 0;
}

extern std::ofstream keylog_file;

namespace {
void keylog_callback(const SSL *ssl, const char *line) {
  keylog_file.write(line, strlen(line));
  keylog_file.put('\n');
  keylog_file.flush();
}
} // namespace

void TLSServerContext::enable_keylog() {
  SSL_CTX_set_keylog_callback(ssl_ctx_, keylog_callback);
}
<commit_msg>server: Fix alignment issue in session ticket QUIC version<commit_after>/*
 * ngtcp2
 *
 * Copyright (c) 2020 ngtcp2 contributors
 *
 * 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 "tls_server_context_openssl.h"

#include <cstring>
#include <iostream>
#include <fstream>
#include <limits>

#include <ngtcp2/ngtcp2_crypto_openssl.h>

#include <openssl/err.h>

#include "server_base.h"
#include "template.h"

extern Config config;

TLSServerContext::TLSServerContext() : ssl_ctx_{nullptr} {}

TLSServerContext::~TLSServerContext() {
  if (ssl_ctx_) {
    SSL_CTX_free(ssl_ctx_);
  }
}

SSL_CTX *TLSServerContext::get_native_handle() const { return ssl_ctx_; }

namespace {
int alpn_select_proto_h3_cb(SSL *ssl, const unsigned char **out,
                            unsigned char *outlen, const unsigned char *in,
                            unsigned int inlen, void *arg) {
  auto conn_ref = static_cast<ngtcp2_crypto_conn_ref *>(SSL_get_app_data(ssl));
  auto h = static_cast<HandlerBase *>(conn_ref->user_data);
  const uint8_t *alpn;
  size_t alpnlen;
  // This should be the negotiated version, but we have not set the
  // negotiated version when this callback is called.
  auto version = ngtcp2_conn_get_client_chosen_version(h->conn());

  switch (version) {
  case QUIC_VER_DRAFT29:
    alpn = reinterpret_cast<const uint8_t *>(H3_ALPN_DRAFT29);
    alpnlen = str_size(H3_ALPN_DRAFT29);
    break;
  case QUIC_VER_DRAFT30:
    alpn = reinterpret_cast<const uint8_t *>(H3_ALPN_DRAFT30);
    alpnlen = str_size(H3_ALPN_DRAFT30);
    break;
  case QUIC_VER_DRAFT31:
    alpn = reinterpret_cast<const uint8_t *>(H3_ALPN_DRAFT31);
    alpnlen = str_size(H3_ALPN_DRAFT31);
    break;
  case QUIC_VER_DRAFT32:
    alpn = reinterpret_cast<const uint8_t *>(H3_ALPN_DRAFT32);
    alpnlen = str_size(H3_ALPN_DRAFT32);
    break;
  case NGTCP2_PROTO_VER_V1:
  case NGTCP2_PROTO_VER_V2_DRAFT:
    alpn = reinterpret_cast<const uint8_t *>(H3_ALPN_V1);
    alpnlen = str_size(H3_ALPN_V1);
    break;
  default:
    if (!config.quiet) {
      std::cerr << "Unexpected quic protocol version: " << std::hex << "0x"
                << version << std::dec << std::endl;
    }
    return SSL_TLSEXT_ERR_ALERT_FATAL;
  }

  for (auto p = in, end = in + inlen; p + alpnlen <= end; p += *p + 1) {
    if (std::equal(alpn, alpn + alpnlen, p)) {
      *out = p + 1;
      *outlen = *p;
      return SSL_TLSEXT_ERR_OK;
    }
  }

  if (!config.quiet) {
    std::cerr << "Client did not present ALPN " << &alpn[1] << std::endl;
  }

  return SSL_TLSEXT_ERR_ALERT_FATAL;
}
} // namespace

namespace {
int alpn_select_proto_hq_cb(SSL *ssl, const unsigned char **out,
                            unsigned char *outlen, const unsigned char *in,
                            unsigned int inlen, void *arg) {
  auto conn_ref = static_cast<ngtcp2_crypto_conn_ref *>(SSL_get_app_data(ssl));
  auto h = static_cast<HandlerBase *>(conn_ref->user_data);
  const uint8_t *alpn;
  size_t alpnlen;
  // This should be the negotiated version, but we have not set the
  // negotiated version when this callback is called.
  auto version = ngtcp2_conn_get_client_chosen_version(h->conn());

  switch (version) {
  case QUIC_VER_DRAFT29:
    alpn = reinterpret_cast<const uint8_t *>(HQ_ALPN_DRAFT29);
    alpnlen = str_size(HQ_ALPN_DRAFT29);
    break;
  case QUIC_VER_DRAFT30:
    alpn = reinterpret_cast<const uint8_t *>(HQ_ALPN_DRAFT30);
    alpnlen = str_size(HQ_ALPN_DRAFT30);
    break;
  case QUIC_VER_DRAFT31:
    alpn = reinterpret_cast<const uint8_t *>(HQ_ALPN_DRAFT31);
    alpnlen = str_size(HQ_ALPN_DRAFT31);
    break;
  case QUIC_VER_DRAFT32:
    alpn = reinterpret_cast<const uint8_t *>(HQ_ALPN_DRAFT32);
    alpnlen = str_size(HQ_ALPN_DRAFT32);
    break;
  case NGTCP2_PROTO_VER_V1:
  case NGTCP2_PROTO_VER_V2_DRAFT:
    alpn = reinterpret_cast<const uint8_t *>(HQ_ALPN_V1);
    alpnlen = str_size(HQ_ALPN_V1);
    break;
  default:
    if (!config.quiet) {
      std::cerr << "Unexpected quic protocol version: " << std::hex << "0x"
                << version << std::dec << std::endl;
    }
    return SSL_TLSEXT_ERR_ALERT_FATAL;
  }

  for (auto p = in, end = in + inlen; p + alpnlen <= end; p += *p + 1) {
    if (std::equal(alpn, alpn + alpnlen, p)) {
      *out = p + 1;
      *outlen = *p;
      return SSL_TLSEXT_ERR_OK;
    }
  }

  if (!config.quiet) {
    std::cerr << "Client did not present ALPN " << &alpn[1] << std::endl;
  }

  return SSL_TLSEXT_ERR_ALERT_FATAL;
}
} // namespace

namespace {
int alpn_select_proto_perf_cb(SSL *ssl, const unsigned char **out,
                              unsigned char *outlen, const unsigned char *in,
                              unsigned int inlen, void *arg) {
  constexpr static uint8_t alpn[] = "\x4perf";
  size_t alpnlen = str_size(alpn);

  for (auto p = in, end = in + inlen; p + alpnlen <= end; p += *p + 1) {
    if (std::equal(alpn, alpn + alpnlen, p)) {
      *out = p + 1;
      *outlen = *p;
      return SSL_TLSEXT_ERR_OK;
    }
  }

  if (!config.quiet) {
    std::cerr << "Client did not present ALPN " << &alpn[1] << std::endl;
  }

  return SSL_TLSEXT_ERR_ALERT_FATAL;
}
} // namespace

namespace {
int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) {
  // We don't verify the client certificate.  Just request it for the
  // testing purpose.
  return 1;
}
} // namespace

namespace {
int gen_ticket_cb(SSL *ssl, void *arg) {
  auto conn_ref = static_cast<ngtcp2_crypto_conn_ref *>(SSL_get_app_data(ssl));
  auto h = static_cast<HandlerBase *>(conn_ref->user_data);
  auto ver = htonl(ngtcp2_conn_get_negotiated_version(h->conn()));

  if (!SSL_SESSION_set1_ticket_appdata(SSL_get0_session(ssl), &ver,
                                       sizeof(ver))) {
    return 0;
  }

  return 1;
}
} // namespace

namespace {
SSL_TICKET_RETURN decrypt_ticket_cb(SSL *ssl, SSL_SESSION *session,
                                    const unsigned char *keyname,
                                    size_t keynamelen, SSL_TICKET_STATUS status,
                                    void *arg) {
  switch (status) {
  case SSL_TICKET_EMPTY:
  case SSL_TICKET_NO_DECRYPT:
    return SSL_TICKET_RETURN_IGNORE_RENEW;
  }

  uint8_t *pver;
  uint32_t ver;
  size_t verlen;

  if (!SSL_SESSION_get0_ticket_appdata(
          session, reinterpret_cast<void **>(&pver), &verlen) ||
      verlen != sizeof(ver)) {
    switch (status) {
    case SSL_TICKET_SUCCESS:
      return SSL_TICKET_RETURN_IGNORE;
    case SSL_TICKET_SUCCESS_RENEW:
    default:
      return SSL_TICKET_RETURN_IGNORE_RENEW;
    }
  }

  memcpy(&ver, pver, sizeof(ver));

  auto conn_ref = static_cast<ngtcp2_crypto_conn_ref *>(SSL_get_app_data(ssl));
  auto h = static_cast<HandlerBase *>(conn_ref->user_data);

  if (ngtcp2_conn_get_client_chosen_version(h->conn()) != ntohl(ver)) {
    switch (status) {
    case SSL_TICKET_SUCCESS:
      return SSL_TICKET_RETURN_IGNORE;
    case SSL_TICKET_SUCCESS_RENEW:
    default:
      return SSL_TICKET_RETURN_IGNORE_RENEW;
    }
  }

  switch (status) {
  case SSL_TICKET_SUCCESS:
    return SSL_TICKET_RETURN_USE;
  case SSL_TICKET_SUCCESS_RENEW:
  default:
    return SSL_TICKET_RETURN_USE_RENEW;
  }
}
} // namespace

int TLSServerContext::init(const char *private_key_file, const char *cert_file,
                           AppProtocol app_proto) {
  constexpr static unsigned char sid_ctx[] = "ngtcp2 server";

  ssl_ctx_ = SSL_CTX_new(TLS_server_method());
  if (!ssl_ctx_) {
    std::cerr << "SSSL_CTX_new: " << ERR_error_string(ERR_get_error(), nullptr)
              << std::endl;
    return -1;
  }

  if (ngtcp2_crypto_openssl_configure_server_context(ssl_ctx_) != 0) {
    std::cerr << "ngtcp2_crypto_openssl_configure_server_context failed"
              << std::endl;
    return -1;
  }

  SSL_CTX_set_max_early_data(ssl_ctx_, UINT32_MAX);

  constexpr auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
                            SSL_OP_SINGLE_ECDH_USE |
                            SSL_OP_CIPHER_SERVER_PREFERENCE |
                            SSL_OP_NO_ANTI_REPLAY;

  SSL_CTX_set_options(ssl_ctx_, ssl_opts);

  if (SSL_CTX_set_ciphersuites(ssl_ctx_, config.ciphers) != 1) {
    std::cerr << "SSL_CTX_set_ciphersuites: "
              << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
    return -1;
  }

  if (SSL_CTX_set1_groups_list(ssl_ctx_, config.groups) != 1) {
    std::cerr << "SSL_CTX_set1_groups_list failed" << std::endl;
    return -1;
  }

  SSL_CTX_set_mode(ssl_ctx_, SSL_MODE_RELEASE_BUFFERS);

  switch (app_proto) {
  case AppProtocol::H3:
    SSL_CTX_set_alpn_select_cb(ssl_ctx_, alpn_select_proto_h3_cb, nullptr);
    break;
  case AppProtocol::HQ:
    SSL_CTX_set_alpn_select_cb(ssl_ctx_, alpn_select_proto_hq_cb, nullptr);
    break;
  case AppProtocol::Perf:
    SSL_CTX_set_alpn_select_cb(ssl_ctx_, alpn_select_proto_perf_cb, nullptr);
    break;
  }

  SSL_CTX_set_default_verify_paths(ssl_ctx_);

  if (SSL_CTX_use_PrivateKey_file(ssl_ctx_, private_key_file,
                                  SSL_FILETYPE_PEM) != 1) {
    std::cerr << "SSL_CTX_use_PrivateKey_file: "
              << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
    return -1;
  }

  if (SSL_CTX_use_certificate_chain_file(ssl_ctx_, cert_file) != 1) {
    std::cerr << "SSL_CTX_use_certificate_chain_file: "
              << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
    return -1;
  }

  if (SSL_CTX_check_private_key(ssl_ctx_) != 1) {
    std::cerr << "SSL_CTX_check_private_key: "
              << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
    return -1;
  }

  SSL_CTX_set_session_id_context(ssl_ctx_, sid_ctx, sizeof(sid_ctx) - 1);

  if (config.verify_client) {
    SSL_CTX_set_verify(ssl_ctx_,
                       SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE |
                           SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                       verify_cb);
  }

  SSL_CTX_set_session_ticket_cb(ssl_ctx_, gen_ticket_cb, decrypt_ticket_cb,
                                nullptr);

  return 0;
}

extern std::ofstream keylog_file;

namespace {
void keylog_callback(const SSL *ssl, const char *line) {
  keylog_file.write(line, strlen(line));
  keylog_file.put('\n');
  keylog_file.flush();
}
} // namespace

void TLSServerContext::enable_keylog() {
  SSL_CTX_set_keylog_callback(ssl_ctx_, keylog_callback);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "softkeys.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    central = new QWidget(this);
    setCentralWidget(central);
    infoLabel = new QLabel(tr("Funky stuff in menu!"));

    layout = new QVBoxLayout;
    layout->addWidget(infoLabel);
    central->setLayout(layout);
    central->setFocusPolicy(Qt::TabFocus);

    fileMenu = menuBar()->addMenu(tr("&File"));
    openDialogAct = new QAction(tr("&Open Dialog"), this);
    addSoftKeysAct = new QAction(tr("&Add Softkeys"), this);
    clearSoftKeysAct = new QAction(tr("&Clear Softkeys"), this);
    fileMenu->addAction(openDialogAct);
    fileMenu->addAction(addSoftKeysAct);
    fileMenu->addAction(clearSoftKeysAct);
    connect(openDialogAct, SIGNAL(triggered()), this, SLOT(openDialog()));
    connect(addSoftKeysAct, SIGNAL(triggered()), this, SLOT(addSoftKeys()));
    connect(clearSoftKeysAct, SIGNAL(triggered()), this, SLOT(clearSoftKeys()));
}

MainWindow::~MainWindow()
{
}

void MainWindow::openDialog()
{
    QFileDialog::getOpenFileName(this);
}

void MainWindow::addSoftKeys()
{
    ok = new QAction(tr("Ok"), this);
    ok->setSoftKeyRole(QAction::OkSoftKey);
    connect(ok, SIGNAL(triggered()), this, SLOT(okPressed()));

    cancel = new QAction(tr("Cancel"), this);
    cancel->setSoftKeyRole(QAction::OkSoftKey);
    connect(cancel, SIGNAL(triggered()), this, SLOT(cancelPressed()));

    QList<QAction*> softkeys;
    softkeys.append(ok);
    softkeys.append(cancel);
    central->setSoftKeys(softkeys);
    central->setFocus();

}

void MainWindow::clearSoftKeys()
{
    central->setSoftKey(0);
}

void MainWindow::okPressed()
{
    infoLabel->setText(tr("OK pressed"));
    central->setSoftKey(0);
}

void MainWindow::cancelPressed()
{
    infoLabel->setText(tr("Cancel pressed"));
    central->setSoftKey(0);
}
<commit_msg>Better text to label<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "softkeys.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    central = new QWidget(this);
    setCentralWidget(central);
    infoLabel = new QLabel(tr("Open menu to start!"));

    layout = new QVBoxLayout;
    layout->addWidget(infoLabel);
    central->setLayout(layout);
    central->setFocusPolicy(Qt::TabFocus);

    fileMenu = menuBar()->addMenu(tr("&File"));
    openDialogAct = new QAction(tr("&Open Dialog"), this);
    addSoftKeysAct = new QAction(tr("&Add Softkeys"), this);
    clearSoftKeysAct = new QAction(tr("&Clear Softkeys"), this);
    fileMenu->addAction(openDialogAct);
    fileMenu->addAction(addSoftKeysAct);
    fileMenu->addAction(clearSoftKeysAct);
    connect(openDialogAct, SIGNAL(triggered()), this, SLOT(openDialog()));
    connect(addSoftKeysAct, SIGNAL(triggered()), this, SLOT(addSoftKeys()));
    connect(clearSoftKeysAct, SIGNAL(triggered()), this, SLOT(clearSoftKeys()));
}

MainWindow::~MainWindow()
{
}

void MainWindow::openDialog()
{
    QFileDialog::getOpenFileName(this);
}

void MainWindow::addSoftKeys()
{
    ok = new QAction(tr("Ok"), this);
    ok->setSoftKeyRole(QAction::OkSoftKey);
    connect(ok, SIGNAL(triggered()), this, SLOT(okPressed()));

    cancel = new QAction(tr("Cancel"), this);
    cancel->setSoftKeyRole(QAction::OkSoftKey);
    connect(cancel, SIGNAL(triggered()), this, SLOT(cancelPressed()));

    QList<QAction*> softkeys;
    softkeys.append(ok);
    softkeys.append(cancel);
    central->setSoftKeys(softkeys);
    central->setFocus();

}

void MainWindow::clearSoftKeys()
{
    central->setSoftKey(0);
}

void MainWindow::okPressed()
{
    infoLabel->setText(tr("OK pressed"));
    central->setSoftKey(0);
}

void MainWindow::cancelPressed()
{
    infoLabel->setText(tr("Cancel pressed"));
    central->setSoftKey(0);
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkGeoTreeNodeCache.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include "vtkGeoTreeNodeCache.h"

#include "vtkGeoTreeNode.h"
#include "vtkObjectFactory.h"
#include "vtkSmartPointer.h"

vtkStandardNewMacro(vtkGeoTreeNodeCache);
vtkCxxRevisionMacro(vtkGeoTreeNodeCache, "1.3");
//----------------------------------------------------------------------------
vtkGeoTreeNodeCache::vtkGeoTreeNodeCache()
{
  this->Oldest = 0;
  this->Newest = 0;
  this->Size = 0;
  this->CacheMaximumLimit = 500;
  this->CacheMinimumLimit = 250;
}

//----------------------------------------------------------------------------
vtkGeoTreeNodeCache::~vtkGeoTreeNodeCache()
{
  // Break reference loops by explicitly setting all prev/next pointers to null.
  vtkGeoTreeNode* cur;
  for (cur = this->Newest; cur; cur = cur->GetOlder())
    {
    cur->SetOlder(0);
    cur->SetNewer(0);
    }
}

//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::SendToFront(vtkGeoTreeNode* node)
{
  if (node == this->Newest)
    {
    return;
    }

  // Remove from the list if in the list already
  this->RemoveNode(node);

  // Add to the beginning of the list
  if (this->Size > 0)
    {
    node->SetNewer(0);
    node->SetOlder(this->Newest);
    this->Newest->SetNewer(node);
    this->Newest = node;
    }
  else
    {
    node->SetNewer(0);
    node->SetOlder(0);
    this->Newest = node;
    this->Oldest = node;
    }
  this->Size++;
  if (this->Size > this->CacheMaximumLimit)
    {
    this->TrimToCacheMinimum();
    }
}

//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::TrimToCacheMinimum()
{
  cerr << "Trimming cache ... " << endl;
  while (this->Size > this->CacheMinimumLimit)
    {
    vtkGeoTreeNode* node = this->Oldest;
    node->GetNewer()->SetOlder(0);
    this->Oldest = node->GetNewer();
    node->SetOlder(0);
    node->SetNewer(0);

    // If this was the last of a set of siblings to leave the list,
    // delete data from all siblings.
    this->DeleteDataFromSiblings(node);

    this->Size--;
    }
}

//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::DeleteDataFromSiblings(vtkGeoTreeNode* node)
{
  // Delete data from node or siblings if possible.
  vtkGeoTreeNode* parent = node->GetParentTreeNode();
  if (!parent)
    {
    return;
    }
  bool canDeleteSiblings = true;
  for (int c = 0; c < 4; ++c)
    {
    vtkGeoTreeNode* child = parent->GetChildTreeNode(c);
    if (!child || child->GetOlder() || child->GetNewer() || child == this->Newest)
      {
      canDeleteSiblings = false;
      break;
      }
    }
  if (canDeleteSiblings)
    {
    cerr << "Actually deleting data." << endl;
    for (int c = 0; c < 4; ++c)
      {
      vtkGeoTreeNode* child = parent->GetChildTreeNode(c);
      child->DeleteData();
      }
    }
}

//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::RemoveNode(vtkGeoTreeNode* node)
{
  if (!node->GetNewer() && !node->GetOlder() && node != this->Newest)
    {
    // The node is not in the list
    return;
    }

  if (!node->GetNewer())
    {
    this->Newest = node->GetOlder();
    }
  else
    {
    node->GetNewer()->SetOlder(node->GetOlder());
    }
  if (!node->GetOlder())
    {
    this->Oldest = node->GetNewer();
    }
  else
    {
    node->GetOlder()->SetNewer(node->GetNewer());
    }
  node->SetOlder(0);
  node->SetNewer(0);
  this->Size--;
}

//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::PrintSelf(ostream & os, vtkIndent indent)
{
  this->Superclass::PrintSelf( os, indent );
  os << indent << "CacheMinimumLimit: " << this->CacheMinimumLimit << endl;
  os << indent << "CacheMaximumLimit: " << this->CacheMaximumLimit << endl;
  os << indent << "Size: " << this->Size << endl;
}
<commit_msg>BUG: Remove cerr statements.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkGeoTreeNodeCache.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include "vtkGeoTreeNodeCache.h"

#include "vtkGeoTreeNode.h"
#include "vtkObjectFactory.h"
#include "vtkSmartPointer.h"

vtkStandardNewMacro(vtkGeoTreeNodeCache);
vtkCxxRevisionMacro(vtkGeoTreeNodeCache, "1.4");
//----------------------------------------------------------------------------
vtkGeoTreeNodeCache::vtkGeoTreeNodeCache()
{
  this->Oldest = 0;
  this->Newest = 0;
  this->Size = 0;
  this->CacheMaximumLimit = 500;
  this->CacheMinimumLimit = 250;
}

//----------------------------------------------------------------------------
vtkGeoTreeNodeCache::~vtkGeoTreeNodeCache()
{
  // Break reference loops by explicitly setting all prev/next pointers to null.
  vtkGeoTreeNode* cur;
  for (cur = this->Newest; cur; cur = cur->GetOlder())
    {
    cur->SetOlder(0);
    cur->SetNewer(0);
    }
}

//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::SendToFront(vtkGeoTreeNode* node)
{
  if (node == this->Newest)
    {
    return;
    }

  // Remove from the list if in the list already
  this->RemoveNode(node);

  // Add to the beginning of the list
  if (this->Size > 0)
    {
    node->SetNewer(0);
    node->SetOlder(this->Newest);
    this->Newest->SetNewer(node);
    this->Newest = node;
    }
  else
    {
    node->SetNewer(0);
    node->SetOlder(0);
    this->Newest = node;
    this->Oldest = node;
    }
  this->Size++;
  if (this->Size > this->CacheMaximumLimit)
    {
    this->TrimToCacheMinimum();
    }
}

//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::TrimToCacheMinimum()
{
  while (this->Size > this->CacheMinimumLimit)
    {
    vtkGeoTreeNode* node = this->Oldest;
    node->GetNewer()->SetOlder(0);
    this->Oldest = node->GetNewer();
    node->SetOlder(0);
    node->SetNewer(0);

    // If this was the last of a set of siblings to leave the list,
    // delete data from all siblings.
    this->DeleteDataFromSiblings(node);

    this->Size--;
    }
}

//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::DeleteDataFromSiblings(vtkGeoTreeNode* node)
{
  // Delete data from node or siblings if possible.
  vtkGeoTreeNode* parent = node->GetParentTreeNode();
  if (!parent)
    {
    return;
    }
  bool canDeleteSiblings = true;
  for (int c = 0; c < 4; ++c)
    {
    vtkGeoTreeNode* child = parent->GetChildTreeNode(c);
    if (!child || child->GetOlder() || child->GetNewer() || child == this->Newest)
      {
      canDeleteSiblings = false;
      break;
      }
    }
  if (canDeleteSiblings)
    {
    for (int c = 0; c < 4; ++c)
      {
      vtkGeoTreeNode* child = parent->GetChildTreeNode(c);
      child->DeleteData();
      }
    }
}

//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::RemoveNode(vtkGeoTreeNode* node)
{
  if (!node->GetNewer() && !node->GetOlder() && node != this->Newest)
    {
    // The node is not in the list
    return;
    }

  if (!node->GetNewer())
    {
    this->Newest = node->GetOlder();
    }
  else
    {
    node->GetNewer()->SetOlder(node->GetOlder());
    }
  if (!node->GetOlder())
    {
    this->Oldest = node->GetNewer();
    }
  else
    {
    node->GetOlder()->SetNewer(node->GetNewer());
    }
  node->SetOlder(0);
  node->SetNewer(0);
  this->Size--;
}

//----------------------------------------------------------------------------
void vtkGeoTreeNodeCache::PrintSelf(ostream & os, vtkIndent indent)
{
  this->Superclass::PrintSelf( os, indent );
  os << indent << "CacheMinimumLimit: " << this->CacheMinimumLimit << endl;
  os << indent << "CacheMaximumLimit: " << this->CacheMaximumLimit << endl;
  os << indent << "Size: " << this->Size << endl;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qwaylandshmbackingstore.h"

#include <QtCore/qdebug.h>

#include "qwaylanddisplay.h"
#include "qwaylandshmwindow.h"
#include "qwaylandscreen.h"
#include "qwaylanddecoration.h"

#include <QtGui/QPainter>

#include <wayland-client.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>

QT_BEGIN_NAMESPACE

QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
                     const QSize &size, QImage::Format format)
    : mMarginsImage(0)
{
    int stride = size.width() * 4;
    int alloc = stride * size.height();
    char filename[] = "/tmp/wayland-shm-XXXXXX";
    int fd = mkstemp(filename);
    if (fd < 0) {
        qWarning("mkstemp %s failed: %s", filename, strerror(errno));
        return;
    }
    int flags = fcntl(fd, F_GETFD);
    if (flags != -1)
        fcntl(fd, F_SETFD, flags | FD_CLOEXEC);

    if (ftruncate(fd, alloc) < 0) {
        qWarning("ftruncate failed: %s", strerror(errno));
        close(fd);
        return;
    }
    uchar *data = (uchar *)
            mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    unlink(filename);

    if (data == (uchar *) MAP_FAILED) {
        qWarning("mmap /dev/zero failed: %s", strerror(errno));
        close(fd);
        return;
    }

    mImage = QImage(data, size.width(), size.height(), stride, format);
    mShmPool = wl_shm_create_pool(display->shm(), fd, alloc);
    mBuffer = wl_shm_pool_create_buffer(mShmPool,0, size.width(), size.height(),
                                       stride, WL_SHM_FORMAT_ARGB8888);
    close(fd);
}

QWaylandShmBuffer::~QWaylandShmBuffer(void)
{
    munmap((void *) mImage.constBits(), mImage.byteCount());
    wl_buffer_destroy(mBuffer);
    wl_shm_pool_destroy(mShmPool);
}

QImage *QWaylandShmBuffer::imageInsideMargins(const QMargins &margins)
{
    if (!margins.isNull() && margins != mMargins) {
        if (mMarginsImage) {
            delete mMarginsImage;
        }
        uchar *bits = const_cast<uchar *>(mImage.constBits());
        uchar *b_s_data = bits + margins.top() * mImage.bytesPerLine() + margins.left() * 4;
        int b_s_width = mImage.size().width() - margins.left() - margins.right();
        int b_s_height = mImage.size().height() - margins.top() - margins.bottom();
        mMarginsImage = new QImage(b_s_data, b_s_width,b_s_height,mImage.bytesPerLine(),mImage.format());
    }
    if (margins.isNull()) {
        delete mMarginsImage;
        mMarginsImage = 0;
    }

    mMargins = margins;
    if (!mMarginsImage)
        return &mImage;

    return mMarginsImage;

}

QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window)
    : QPlatformBackingStore(window)
    , mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display())
    , mFrontBuffer(0)
    , mBackBuffer(0)
    , mFrontBufferIsDirty(false)
    , mPainting(false)
    , mFrameCallback(0)
{

}

QWaylandShmBackingStore::~QWaylandShmBackingStore()
{
    if (mFrameCallback)
        wl_callback_destroy(mFrameCallback);

//    if (mFrontBuffer == waylandWindow()->attached())
//        waylandWindow()->attach(0);

    if (mFrontBuffer != mBackBuffer)
        delete mFrontBuffer;

    delete mBackBuffer;
}

QPaintDevice *QWaylandShmBackingStore::paintDevice()
{
    if (!windowDecoration())
        return mBackBuffer->image();
    return mBackBuffer->imageInsideMargins(windowDecorationMargins());
}

void QWaylandShmBackingStore::beginPaint(const QRegion &)
{
    mPainting = true;
    ensureSize();

    if (waylandWindow()->attached() && mBackBuffer == waylandWindow()->attached()) {
        QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->handle());
        Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm);
        waylandWindow->waitForFrameSync();
    }

}

void QWaylandShmBackingStore::endPaint()
{
    mPainting = false;
}

void QWaylandShmBackingStore::ensureSize()
{
    waylandWindow()->setBackingStore(this);
    waylandWindow()->createDecoration();
    resize(mRequestedSize);
}

void QWaylandShmBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
    Q_UNUSED(window);
    Q_UNUSED(offset);
    Q_ASSERT(waylandWindow()->windowType() == QWaylandWindow::Shm);

    mFrontBuffer = mBackBuffer;

    if (mFrameCallback) {
        mFrontBufferIsDirty = true;
        return;
    }

    mFrameCallback = wl_surface_frame(waylandWindow()->wl_surface());
    wl_callback_add_listener(mFrameCallback,&frameCallbackListener,this);
    QMargins margins = windowDecorationMargins();

    if (waylandWindow()->attached() != mFrontBuffer) {
        delete waylandWindow()->attached();
        waylandWindow()->attach(mFrontBuffer);
    }

    QVector<QRect> rects = region.rects();
    for (int i = 0; i < rects.size(); i++) {
        QRect rect = rects.at(i);
        rect.translate(margins.left(),margins.top());
        waylandWindow()->damage(rect);
    }
    mFrontBufferIsDirty = false;
}

void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &)
{
    mRequestedSize = size;
}

void QWaylandShmBackingStore::resize(const QSize &size)
{

    QMargins margins = windowDecorationMargins();
    QSize sizeWithMargins = size + QSize(margins.left()+margins.right(),margins.top()+margins.bottom());

    QImage::Format format = QPlatformScreen::platformScreenForWindow(window())->format();

    if (mBackBuffer != NULL && mBackBuffer->size() == sizeWithMargins)
        return;

    if (mBackBuffer != mFrontBuffer) {
        delete mBackBuffer; //we delete the attached buffer when we flush
    }

    mBackBuffer = new QWaylandShmBuffer(mDisplay, sizeWithMargins, format);

    if (windowDecoration())
        windowDecoration()->paintDecoration();
}

QImage *QWaylandShmBackingStore::entireSurface() const
{
    return mBackBuffer->image();
}

void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t time)
{
    Q_UNUSED(time);
    QWaylandShmBackingStore *self =
            static_cast<QWaylandShmBackingStore *>(data);
    if (callback != self->mFrameCallback) // others, like QWaylandWindow, may trigger callbacks too
        return;
    QWaylandWindow *window = self->waylandWindow();
    wl_callback_destroy(self->mFrameCallback);
    self->mFrameCallback = 0;
    if (self->mFrontBuffer != window->attached()) {
        delete window->attached();
        window->attach(self->mFrontBuffer);
    }

    if (self->mFrontBufferIsDirty && !self->mPainting) {
        self->mFrontBufferIsDirty = false;
        self->mFrameCallback = wl_surface_frame(window->wl_surface());
        wl_callback_add_listener(self->mFrameCallback,&self->frameCallbackListener,self);
        window->damage(QRect(QPoint(0,0),self->mFrontBuffer->size()));
    }
}

const struct wl_callback_listener QWaylandShmBackingStore::frameCallbackListener = {
    QWaylandShmBackingStore::done
};

QT_END_NAMESPACE
<commit_msg>Fix issue where hidden menus were never shown again<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qwaylandshmbackingstore.h"

#include <QtCore/qdebug.h>

#include "qwaylanddisplay.h"
#include "qwaylandshmwindow.h"
#include "qwaylandscreen.h"
#include "qwaylanddecoration.h"

#include <QtGui/QPainter>

#include <wayland-client.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>

QT_BEGIN_NAMESPACE

QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
                     const QSize &size, QImage::Format format)
    : mMarginsImage(0)
{
    int stride = size.width() * 4;
    int alloc = stride * size.height();
    char filename[] = "/tmp/wayland-shm-XXXXXX";
    int fd = mkstemp(filename);
    if (fd < 0) {
        qWarning("mkstemp %s failed: %s", filename, strerror(errno));
        return;
    }
    int flags = fcntl(fd, F_GETFD);
    if (flags != -1)
        fcntl(fd, F_SETFD, flags | FD_CLOEXEC);

    if (ftruncate(fd, alloc) < 0) {
        qWarning("ftruncate failed: %s", strerror(errno));
        close(fd);
        return;
    }
    uchar *data = (uchar *)
            mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    unlink(filename);

    if (data == (uchar *) MAP_FAILED) {
        qWarning("mmap /dev/zero failed: %s", strerror(errno));
        close(fd);
        return;
    }

    mImage = QImage(data, size.width(), size.height(), stride, format);
    mShmPool = wl_shm_create_pool(display->shm(), fd, alloc);
    mBuffer = wl_shm_pool_create_buffer(mShmPool,0, size.width(), size.height(),
                                       stride, WL_SHM_FORMAT_ARGB8888);
    close(fd);
}

QWaylandShmBuffer::~QWaylandShmBuffer(void)
{
    munmap((void *) mImage.constBits(), mImage.byteCount());
    wl_buffer_destroy(mBuffer);
    wl_shm_pool_destroy(mShmPool);
}

QImage *QWaylandShmBuffer::imageInsideMargins(const QMargins &margins)
{
    if (!margins.isNull() && margins != mMargins) {
        if (mMarginsImage) {
            delete mMarginsImage;
        }
        uchar *bits = const_cast<uchar *>(mImage.constBits());
        uchar *b_s_data = bits + margins.top() * mImage.bytesPerLine() + margins.left() * 4;
        int b_s_width = mImage.size().width() - margins.left() - margins.right();
        int b_s_height = mImage.size().height() - margins.top() - margins.bottom();
        mMarginsImage = new QImage(b_s_data, b_s_width,b_s_height,mImage.bytesPerLine(),mImage.format());
    }
    if (margins.isNull()) {
        delete mMarginsImage;
        mMarginsImage = 0;
    }

    mMargins = margins;
    if (!mMarginsImage)
        return &mImage;

    return mMarginsImage;

}

QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window)
    : QPlatformBackingStore(window)
    , mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display())
    , mFrontBuffer(0)
    , mBackBuffer(0)
    , mFrontBufferIsDirty(false)
    , mPainting(false)
    , mFrameCallback(0)
{

}

QWaylandShmBackingStore::~QWaylandShmBackingStore()
{
    if (mFrameCallback)
        wl_callback_destroy(mFrameCallback);

//    if (mFrontBuffer == waylandWindow()->attached())
//        waylandWindow()->attach(0);

    if (mFrontBuffer != mBackBuffer)
        delete mFrontBuffer;

    delete mBackBuffer;
}

QPaintDevice *QWaylandShmBackingStore::paintDevice()
{
    if (!windowDecoration())
        return mBackBuffer->image();
    return mBackBuffer->imageInsideMargins(windowDecorationMargins());
}

void QWaylandShmBackingStore::beginPaint(const QRegion &)
{
    mPainting = true;
    ensureSize();

    if (waylandWindow()->attached() && mBackBuffer == waylandWindow()->attached() && mFrameCallback) {
        QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->handle());
        Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm);
        waylandWindow->waitForFrameSync();
    }

}

void QWaylandShmBackingStore::endPaint()
{
    mPainting = false;
}

void QWaylandShmBackingStore::ensureSize()
{
    waylandWindow()->setBackingStore(this);
    waylandWindow()->createDecoration();
    resize(mRequestedSize);
}

void QWaylandShmBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
    Q_UNUSED(window);
    Q_UNUSED(offset);
    Q_ASSERT(waylandWindow()->windowType() == QWaylandWindow::Shm);

    mFrontBuffer = mBackBuffer;

    if (mFrameCallback) {
        mFrontBufferIsDirty = true;
        return;
    }

    mFrameCallback = wl_surface_frame(waylandWindow()->wl_surface());
    wl_callback_add_listener(mFrameCallback,&frameCallbackListener,this);
    QMargins margins = windowDecorationMargins();

    if (waylandWindow()->attached() != mFrontBuffer) {
        delete waylandWindow()->attached();
        waylandWindow()->attach(mFrontBuffer);
    }

    QVector<QRect> rects = region.rects();
    for (int i = 0; i < rects.size(); i++) {
        QRect rect = rects.at(i);
        rect.translate(margins.left(),margins.top());
        waylandWindow()->damage(rect);
    }
    mFrontBufferIsDirty = false;
}

void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &)
{
    mRequestedSize = size;
}

void QWaylandShmBackingStore::resize(const QSize &size)
{

    QMargins margins = windowDecorationMargins();
    QSize sizeWithMargins = size + QSize(margins.left()+margins.right(),margins.top()+margins.bottom());

    QImage::Format format = QPlatformScreen::platformScreenForWindow(window())->format();

    if (mBackBuffer != NULL && mBackBuffer->size() == sizeWithMargins)
        return;

    if (mBackBuffer != mFrontBuffer) {
        delete mBackBuffer; //we delete the attached buffer when we flush
    }

    mBackBuffer = new QWaylandShmBuffer(mDisplay, sizeWithMargins, format);

    if (windowDecoration())
        windowDecoration()->paintDecoration();
}

QImage *QWaylandShmBackingStore::entireSurface() const
{
    return mBackBuffer->image();
}

void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t time)
{
    Q_UNUSED(time);
    QWaylandShmBackingStore *self =
            static_cast<QWaylandShmBackingStore *>(data);
    if (callback != self->mFrameCallback) // others, like QWaylandWindow, may trigger callbacks too
        return;
    QWaylandWindow *window = self->waylandWindow();
    wl_callback_destroy(self->mFrameCallback);
    self->mFrameCallback = 0;
    if (self->mFrontBuffer != window->attached()) {
        delete window->attached();
        window->attach(self->mFrontBuffer);
    }

    if (self->mFrontBufferIsDirty && !self->mPainting) {
        self->mFrontBufferIsDirty = false;
        self->mFrameCallback = wl_surface_frame(window->wl_surface());
        wl_callback_add_listener(self->mFrameCallback,&self->frameCallbackListener,self);
        window->damage(QRect(QPoint(0,0),self->mFrontBuffer->size()));
    }
}

const struct wl_callback_listener QWaylandShmBackingStore::frameCallbackListener = {
    QWaylandShmBackingStore::done
};

QT_END_NAMESPACE
<|endoftext|>


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

  This source file is part of the Avogadro project.

  Copyright 2012 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

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

#include "pluginmanager.h"
#include "avogadrostaticqtplugins.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QMutex>
#include <QtCore/QPluginLoader>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>

#include <QtCore/QDebug>

namespace Avogadro {
namespace QtGui {

PluginManager::PluginManager(QObject *p)
  : QObject(p), m_staticPluginsLoaded(false)
{
  // http://doc.qt.digia.com/qt/deployment-plugins.html#debugging-plugins
  bool debugPlugins = !qgetenv("QT_DEBUG_PLUGINS").isEmpty();

  // The usual base directory is the parent directory of the executable's
  // location. (exe is in "bin" or "MacOS" and plugins are under the parent
  // directory at "lib/avogadro2/plugins"...)
  //
  QDir baseDir(QCoreApplication::applicationDirPath() + "/..");
  if (debugPlugins)
    qDebug() << "  baseDir:" << baseDir.absolutePath();

#ifdef __APPLE__
  // But if NOT running from the installed bundle on the Mac, the plugins are
  // relative to the build directory instead:
  //
  if (!QFileInfo(baseDir.absolutePath() + "/Resources/qt.conf").exists()) {
    QDir buildDir(QCoreApplication::applicationDirPath() + "/../../../..");
    baseDir = buildDir;
    if (debugPlugins)
      qDebug() << "  using buildDir:" << buildDir.absolutePath();
  }
#endif

  QDir pluginsDir(baseDir.absolutePath() + "/lib/avogadro2/plugins");
  m_pluginDirs.append(pluginsDir.absolutePath());

  if (debugPlugins) {
    qDebug() << "  pluginsDir:" << pluginsDir.absolutePath();
    int count = 0;
    foreach(const QString &pluginPath, pluginsDir.entryList(QDir::Files)) {
      ++count;
      qDebug() << " " << pluginsDir.absolutePath() + "/" + pluginPath;
    }

    if (count > 0)
      qDebug() << " " << count << "files found in" << pluginsDir.absolutePath();
    else
      qDebug() << "  no plugin files found in" << pluginsDir.absolutePath();
  }
}

PluginManager::~PluginManager()
{
}

PluginManager * PluginManager::instance()
{
  static QMutex mutex;
  // Compiler initializes this static pointer to 0.
  static PluginManager *pluginManagerInstance;
  if (!pluginManagerInstance) {
    mutex.lock();
    if (!pluginManagerInstance)
      pluginManagerInstance = new PluginManager(QCoreApplication::instance());
    mutex.unlock();
  }
  return pluginManagerInstance;
}

void PluginManager::load()
{
  foreach(const QString &dir, m_pluginDirs)
    load(dir);
}

void PluginManager::load(const QString &path)
{
  // Load any static plugins first.
  if (!m_staticPluginsLoaded) {
    QObjectList staticPlugins = QPluginLoader::staticInstances();
    foreach (QObject *pluginInstance, staticPlugins)
      m_plugins.append(pluginInstance);
    m_staticPluginsLoaded = true;
  }

  QDir dir(path);
  foreach (const QString &pluginPath, dir.entryList(QDir::Files)) {
    QPluginLoader pluginLoader(dir.absolutePath() + "/" + pluginPath);

    // We only want to count plugins once, the || should not be necessary but
    // I found that on the Mac at least isLoaded was not always reliable (and
    // if it is we skip the second in the short-circuit).
    if (pluginLoader.isLoaded() || m_plugins.contains(pluginLoader.instance()))
      continue;

    QObject *pluginInstance = pluginLoader.instance();

    // Check if the plugin loaded correctly. Keep debug output for now, should
    // go away once we have verified this (or added to a logger).
    if (!pluginInstance) {
      qDebug() << "Failed to load" << pluginPath << "error"
               << pluginLoader.errorString();
      continue;
    }

    m_plugins.append(pluginInstance);
  }
}

} // End QtGui namespace
} // End Avogadro namespace
<commit_msg>Added AVOGADRO_PLUGIN_DIR as an env variable<commit_after>/******************************************************************************

  This source file is part of the Avogadro project.

  Copyright 2012 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

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

#include "pluginmanager.h"
#include "avogadrostaticqtplugins.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QMutex>
#include <QtCore/QPluginLoader>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>

#include <QtCore/QDebug>

namespace Avogadro {
namespace QtGui {

PluginManager::PluginManager(QObject *p)
  : QObject(p), m_staticPluginsLoaded(false)
{
  // http://doc.qt.digia.com/qt/deployment-plugins.html#debugging-plugins
  bool debugPlugins = !qgetenv("QT_DEBUG_PLUGINS").isEmpty();

  // The usual base directory is the parent directory of the executable's
  // location. (exe is in "bin" or "MacOS" and plugins are under the parent
  // directory at "lib/avogadro2/plugins"...)
  QDir baseDir(QCoreApplication::applicationDirPath() + "/..");

#ifdef __APPLE__
  // But if NOT running from the installed bundle on the Mac, the plugins are
  // relative to the build directory instead:
  //
  if (!QFileInfo(baseDir.absolutePath() + "/Resources/qt.conf").exists()) {
    QDir buildDir(QCoreApplication::applicationDirPath() + "/../../../..");
    baseDir = buildDir;
    if (debugPlugins)
      qDebug() << "  using buildDir:" << buildDir.absolutePath();
  }
#endif

  // If the environment variable is set, use that as the base directory.
  QByteArray pluginDir = qgetenv("AVOGADRO_PLUGIN_DIR");
  if (!pluginDir.isEmpty())
    baseDir.setPath(pluginDir);
  if (debugPlugins)
    qDebug() << "  baseDir:" << baseDir.absolutePath();

  QDir pluginsDir(baseDir.absolutePath() + "/lib/avogadro2/plugins");
  m_pluginDirs.append(pluginsDir.absolutePath());

  if (debugPlugins) {
    qDebug() << "  pluginsDir:" << pluginsDir.absolutePath();
    int count = 0;
    foreach(const QString &pluginPath, pluginsDir.entryList(QDir::Files)) {
      ++count;
      qDebug() << " " << pluginsDir.absolutePath() + "/" + pluginPath;
    }

    if (count > 0)
      qDebug() << " " << count << "files found in" << pluginsDir.absolutePath();
    else
      qDebug() << "  no plugin files found in" << pluginsDir.absolutePath();
  }
}

PluginManager::~PluginManager()
{
}

PluginManager * PluginManager::instance()
{
  static QMutex mutex;
  // Compiler initializes this static pointer to 0.
  static PluginManager *pluginManagerInstance;
  if (!pluginManagerInstance) {
    mutex.lock();
    if (!pluginManagerInstance)
      pluginManagerInstance = new PluginManager(QCoreApplication::instance());
    mutex.unlock();
  }
  return pluginManagerInstance;
}

void PluginManager::load()
{
  foreach(const QString &dir, m_pluginDirs)
    load(dir);
}

void PluginManager::load(const QString &path)
{
  // Load any static plugins first.
  if (!m_staticPluginsLoaded) {
    QObjectList staticPlugins = QPluginLoader::staticInstances();
    foreach (QObject *pluginInstance, staticPlugins)
      m_plugins.append(pluginInstance);
    m_staticPluginsLoaded = true;
  }

  QDir dir(path);
  foreach (const QString &pluginPath, dir.entryList(QDir::Files)) {
    QPluginLoader pluginLoader(dir.absolutePath() + "/" + pluginPath);

    // We only want to count plugins once, the || should not be necessary but
    // I found that on the Mac at least isLoaded was not always reliable (and
    // if it is we skip the second in the short-circuit).
    if (pluginLoader.isLoaded() || m_plugins.contains(pluginLoader.instance()))
      continue;

    QObject *pluginInstance = pluginLoader.instance();

    // Check if the plugin loaded correctly. Keep debug output for now, should
    // go away once we have verified this (or added to a logger).
    if (!pluginInstance) {
      qDebug() << "Failed to load" << pluginPath << "error"
               << pluginLoader.errorString();
      continue;
    }

    m_plugins.append(pluginInstance);
  }
}

} // End QtGui namespace
} // End Avogadro namespace
<|endoftext|>


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

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

Copyright (c) 2001 Insight Consortium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "mydefs.h"
#include "imageutils.h"
#include "OptionList.h"
#include "itkMRASlabIdentifier.h"

typedef itk::MRASlabIdentifier<ImageType> SlabIdentifier ;

void print_usage()
{
  print_line("MRIBiasCorrection 1.0 (21.June.2001)");

  print_line("usage: SlabIdentifier --input file" ) ;
  print_line("       --samples-per-slice int" ) ;
  print_line("       --slice-direction [0-2]" ) ;

  print_line("");

  print_line("--input file") ;
  print_line("        input image file name [meta image format]" );
  print_line("--samples-per-slice int") ;
  print_line("        specifies how many pixels per pixel will be") ;
  print_line("        included for identification purpose.") ;
  print_line("--slice-direction [0-2]" ) ;
  print_line("        slice creation direction ( 0 - x axis, 1 - y axis") ;
  print_line("        2 - z axis)") ;

  print_line("");

  print_line("example: SlabIdentifier --input sample.mhd") ;
  print_line("         --samples-per-slice 10 --slice-direction 2") ;
}

int main(int argc, char* argv[])
{
  if (argc < 2)
    {
      print_usage() ;
      exit(0) ;
    }

  OptionList options(argc, argv) ;

  std::string inputFileName ;
  int sliceDirection ;
  int samplesPerSlice ;
  try
    {
      // get image file options
      options.GetStringOption("input", &inputFileName, true) ;
      samplesPerSlice = options.GetIntOption("samples-per-slice", 10, true) ;
      sliceDirection = options.GetIntOption("slice-direction", 2, true) ;
    }
  catch(OptionList::RequiredOptionMissing e)
    {
      std::cout << "Error: The '" << e.OptionTag
                << "' option is required but missing."
                << std::endl ;
      exit(0) ;
    }

  ImagePointer image = ImageType::New() ;

  std::cout << "Loading image..." << std::endl ;
  loadImage(inputFileName, image) ;
  std::cout << "Image loaded..." << std::endl ;
  SlabIdentifier::Pointer identifier = SlabIdentifier::New() ;

  identifier->SetImage(image) ;
  identifier->SetNumberOfMinimumsPerSlice(samplesPerSlice) ;
  identifier->SetSlicingDirection(sliceDirection) ;
  std::cout << "Searching slabs..." << std::endl ;
  identifier->GenerateSlabRegions() ;
  std::cout << "Search finished..." << std::endl ;
  SlabIdentifier::SlabRegionVectorType ranges =
    identifier->GetSlabRegionVector() ;
  SlabIdentifier::SlabRegionVectorType::iterator iter = ranges.begin() ;
  int count = 0 ;
  std::cout << "slab\t\tfirst slice\t\tlength" << std::endl ;
  while (iter != ranges.end())
    {
      std::cout << count << "\t\t" << iter->GetIndex()[sliceDirection]
                << "\t\t" << iter->GetSize()[sliceDirection]
                << std::endl ;
      count++ ;
      iter++ ;
    }
}
<commit_msg>ENH: 'return' was missing from main().<commit_after>/*=========================================================================

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

Copyright (c) 2001 Insight Consortium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "mydefs.h"
#include "imageutils.h"
#include "OptionList.h"
#include "itkMRASlabIdentifier.h"

typedef itk::MRASlabIdentifier<ImageType> SlabIdentifier ;

void print_usage()
{
  print_line("MRIBiasCorrection 1.0 (21.June.2001)");

  print_line("usage: SlabIdentifier --input file" ) ;
  print_line("       --samples-per-slice int" ) ;
  print_line("       --slice-direction [0-2]" ) ;

  print_line("");

  print_line("--input file") ;
  print_line("        input image file name [meta image format]" );
  print_line("--samples-per-slice int") ;
  print_line("        specifies how many pixels per pixel will be") ;
  print_line("        included for identification purpose.") ;
  print_line("--slice-direction [0-2]" ) ;
  print_line("        slice creation direction ( 0 - x axis, 1 - y axis") ;
  print_line("        2 - z axis)") ;

  print_line("");

  print_line("example: SlabIdentifier --input sample.mhd") ;
  print_line("         --samples-per-slice 10 --slice-direction 2") ;
}

int main(int argc, char* argv[])
{
  if (argc < 2)
    {
      print_usage() ;
      exit(0) ;
    }

  OptionList options(argc, argv) ;

  std::string inputFileName ;
  int sliceDirection ;
  int samplesPerSlice ;
  try
    {
      // get image file options
      options.GetStringOption("input", &inputFileName, true) ;
      samplesPerSlice = options.GetIntOption("samples-per-slice", 10, true) ;
      sliceDirection = options.GetIntOption("slice-direction", 2, true) ;
    }
  catch(OptionList::RequiredOptionMissing e)
    {
      std::cout << "Error: The '" << e.OptionTag
                << "' option is required but missing."
                << std::endl ;
      exit(0) ;
    }

  ImagePointer image = ImageType::New() ;

  std::cout << "Loading image..." << std::endl ;
  loadImage(inputFileName, image) ;
  std::cout << "Image loaded..." << std::endl ;
  SlabIdentifier::Pointer identifier = SlabIdentifier::New() ;

  identifier->SetImage(image) ;
  identifier->SetNumberOfMinimumsPerSlice(samplesPerSlice) ;
  identifier->SetSlicingDirection(sliceDirection) ;
  std::cout << "Searching slabs..." << std::endl ;
  identifier->GenerateSlabRegions() ;
  std::cout << "Search finished..." << std::endl ;
  SlabIdentifier::SlabRegionVectorType ranges =
    identifier->GetSlabRegionVector() ;
  SlabIdentifier::SlabRegionVectorType::iterator iter = ranges.begin() ;
  int count = 0 ;
  std::cout << "slab\t\tfirst slice\t\tlength" << std::endl ;
  while (iter != ranges.end())
    {
      std::cout << count << "\t\t" << iter->GetIndex()[sliceDirection]
                << "\t\t" << iter->GetSize()[sliceDirection]
                << std::endl ;
      count++ ;
      iter++ ;
    }
  return 0;
}
<|endoftext|>


<commit_before>// tutorial illustrating the use of TMath::Binomial
//  can be run with:
// root > .x binomial.C
// root > .x binomial.C+ with ACLIC

#include <TMath.h>
#include <TRandom.h>

void binomialSimple() {
  //
  // Simple test for the binomial distribution
  //
  printf("\nTMath::Binomial simple test\n");
  printf("Build the Tartaglia triangle\n");
  printf("============================\n");
  const Int_t max=13;
  Int_t j;
  for(Int_t i=0;i<max;i++) {
    printf("n=%2d",i);
    for(j=0;j<(max-i);j++) printf("  ");
    for(j=0;j<i+1;j++) printf("%4d",TMath::Binomial(i,j));
    printf("\n");
  }
}

void binomialFancy() {
  Double_t x;
  Double_t y;
  Double_t res1;
  Double_t res2;
  Double_t err;
  Double_t serr=0;
  const Int_t nmax=10000;
  printf("\nTMath::Binomial fancy test\n");
  printf("Verify Newton formula for (x+y)^n\n");
  printf("x,y in [-2,2] and n from 0 to 9  \n");
  printf("=================================\n");
  TRandom r;
  for(Int_t i=0; i<nmax; i++) {
    do {
        x=2*(1-2*r.Rndm());
        y=2*(1-2*r.Rndm());
    } while (TMath::Abs(x+y)<0.75); //Avoid large cancellations
    for(Int_t j=0; j<10; j++) {
       res1=TMath::Power(x+y,j);
       res2=0;
       for(Int_t k=0; k<=j; k++)
          res2+=TMath::Power(x,k)*TMath::Power(y,j-k)*TMath::Binomial(j,k);
       if((err=TMath::Abs(res1-res2)/TMath::Abs(res1))>1e-10)
 	      printf("res1=%e res2=%e x=%e y=%e err=%e j=%d\n",res1,res2,x,y,err,j);
       serr +=err;
     }
  }
  printf("Average Error = %e\n",serr/nmax);
}

void binomial () {
   binomialSimple();
   binomialFancy();
}

<commit_msg>Change print format following the change of return type of TMath::Binomial<commit_after>// tutorial illustrating the use of TMath::Binomial
//  can be run with:
// root > .x binomial.C
// root > .x binomial.C+ with ACLIC

#include <TMath.h>
#include <TRandom.h>

void binomialSimple() {
  //
  // Simple test for the binomial distribution
  //
  printf("\nTMath::Binomial simple test\n");
  printf("Build the Tartaglia triangle\n");
  printf("============================\n");
  const Int_t max=13;
  Int_t j;
  for(Int_t i=0;i<max;i++) {
    printf("n=%2d",i);
    for(j=0;j<(max-i);j++) printf("  ");
    for(j=0;j<i+1;j++) printf("%4d",TMath::Nint(TMath::Binomial(i,j)));
    printf("\n");
  }
}

void binomialFancy() {
  Double_t x;
  Double_t y;
  Double_t res1;
  Double_t res2;
  Double_t err;
  Double_t serr=0;
  const Int_t nmax=10000;
  printf("\nTMath::Binomial fancy test\n");
  printf("Verify Newton formula for (x+y)^n\n");
  printf("x,y in [-2,2] and n from 0 to 9  \n");
  printf("=================================\n");
  TRandom r;
  for(Int_t i=0; i<nmax; i++) {
    do {
        x=2*(1-2*r.Rndm());
        y=2*(1-2*r.Rndm());
    } while (TMath::Abs(x+y)<0.75); //Avoid large cancellations
    for(Int_t j=0; j<10; j++) {
       res1=TMath::Power(x+y,j);
       res2=0;
       for(Int_t k=0; k<=j; k++)
          res2+=TMath::Power(x,k)*TMath::Power(y,j-k)*TMath::Binomial(j,k);
       if((err=TMath::Abs(res1-res2)/TMath::Abs(res1))>1e-10)
 	      printf("res1=%e res2=%e x=%e y=%e err=%e j=%d\n",res1,res2,x,y,err,j);
       serr +=err;
     }
  }
  printf("Average Error = %e\n",serr/nmax);
}

void binomial () {
   binomialSimple();
   binomialFancy();
}

<|endoftext|>


<commit_before>#include <taichi/taichi>

#if defined(__GNUC__)
// Ensure we get the 64-bit variants of the CRT's file I/O calls
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE 1
#endif
#endif

#include "miniz.h"

TC_NAMESPACE_BEGIN

namespace zip {

void write(std::string fn, const uint8 *data, std::size_t len) {
  mz_bool status;
  TC_ERROR_UNLESS(taichi::ends_with(fn, ".tcb.zip"),
                  "Filename must end with .tcb.zip");
  std::string fn_uncompressed(fn.begin(), fn.end() - 4);  // remove .zip
  std::remove(fn.c_str());

  auto s_pComment = "Taichi Binary File";

  status = mz_zip_add_mem_to_archive_file_in_place(
      fn.c_str(), fn_uncompressed.c_str(),
      reinterpret_cast<char *>(const_cast<uint8 *>(data)), len, s_pComment,
      (uint16)strlen(s_pComment), MZ_BEST_COMPRESSION);
  if (!status) {
    TC_ERROR("mz_zip_add_mem_to_archive_file_in_place failed!\n");
  }
}

void write(const std::string &fn, const std::string &data) {
  write(fn, reinterpret_cast<const uint8 *>(data.c_str()),
                   data.size() + 1);
}

std::vector<uint8> read(const std::string fn, bool verbose) {
  TC_ERROR_UNLESS(taichi::ends_with(fn, ".tcb.zip"),
                  "Filename must end with .tcb.zip");

  mz_zip_archive zip_archive;
  mz_zip_archive_file_stat file_stat;
  mz_bool status;

  memset(&zip_archive, 0, sizeof(zip_archive));
  status = mz_zip_reader_init_file(&zip_archive, fn.c_str(), 0);
  if (!status) {
    TC_ERROR("mz_zip_reader_init_file() failed!\n");
  }
  if (!mz_zip_reader_file_stat(&zip_archive, 0, &file_stat)) {
    mz_zip_reader_end(&zip_archive);
    TC_ERROR("mz_zip_reader_file_stat() failed!\n");
  }

  if (verbose) {
    TC_TRACE(
        "Filename: {}, Comment: {}, Uncompressed size: {}, Compressed size: "
        "{}, Is Dir: {}\n",
        file_stat.m_filename, file_stat.m_comment,
        (uint)file_stat.m_uncomp_size, (uint)file_stat.m_comp_size,
        mz_zip_reader_is_file_a_directory(&zip_archive, 0));
  }

  // Close the archive, freeing any resources it was using
  mz_zip_reader_end(&zip_archive);

  size_t uncomp_size;
  memset(&zip_archive, 0, sizeof(zip_archive));
  status = mz_zip_reader_init_file(&zip_archive, fn.c_str(), 0);
  if (!status) {
    TC_ERROR("mz_zip_reader_init_file() failed!\n");
  }

  auto archive_filename = std::string(fn.begin(), fn.end() - 4);  // remove .zip
  auto p = reinterpret_cast<const uint8 *>(mz_zip_reader_extract_file_to_heap(
      &zip_archive, archive_filename.c_str(), &uncomp_size, 0));

  if (!p) {
    mz_zip_reader_end(&zip_archive);
    TC_ERROR("mz_zip_reader_extract_file_to_heap() failed!");
  }

  if (verbose) {
    TC_TRACE("Successfully extracted file {}, size {}", archive_filename,
             (uint)uncomp_size);
    TC_TRACE("File data: {}", (const char *)p);
  }

  std::vector<uint8> ret(p, p + file_stat.m_uncomp_size);
  mz_free((void *)p);
  return ret;
}

} // namespace zip

TC_NAMESPACE_END
<commit_msg>Fixed zip for long path<commit_after>#include <taichi/taichi>

#if defined(__GNUC__)
// Ensure we get the 64-bit variants of the CRT's file I/O calls
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE 1
#endif
#endif

#include "miniz.h"

TC_NAMESPACE_BEGIN

namespace zip {

inline std::string get_file_name_from_whole_path(const std::string &fn) {
  std::size_t start_index = 0;
  if (fn.rfind("/") != std::string::npos) {
    start_index = fn.rfind("/") + 1;
  }
  return std::string(fn.begin() + start_index, fn.end());
}

void write(std::string fn, const uint8 *data, std::size_t len) {
  mz_bool status;
  TC_ERROR_UNLESS(taichi::ends_with(fn, ".tcb.zip"),
                  "Filename must end with .tcb.zip");

  std::string fn_uncompressed = get_file_name_from_whole_path(fn);
  fn_uncompressed = std::string(fn_uncompressed.begin(),
                                fn_uncompressed.end() - 4);  // remove .zip
  std::remove(fn.c_str());

  auto s_pComment = "Taichi Binary File";

  status = mz_zip_add_mem_to_archive_file_in_place(
      fn.c_str(), fn_uncompressed.c_str(),
      reinterpret_cast<char *>(const_cast<uint8 *>(data)), len, s_pComment,
      (uint16)strlen(s_pComment), MZ_BEST_COMPRESSION);
  if (!status) {
    TC_ERROR("mz_zip_add_mem_to_archive_file_in_place failed!\n");
  }
}

void write(const std::string &fn, const std::string &data) {
  write(fn, reinterpret_cast<const uint8 *>(data.c_str()), data.size() + 1);
}

std::vector<uint8> read(const std::string fn, bool verbose) {
  TC_ERROR_UNLESS(taichi::ends_with(fn, ".tcb.zip"),
                  "Filename must end with .tcb.zip");

  mz_zip_archive zip_archive;
  mz_zip_archive_file_stat file_stat;
  mz_bool status;

  memset(&zip_archive, 0, sizeof(zip_archive));
  status = mz_zip_reader_init_file(&zip_archive, fn.c_str(), 0);
  if (!status) {
    TC_ERROR("mz_zip_reader_init_file() failed!\n");
  }
  if (!mz_zip_reader_file_stat(&zip_archive, 0, &file_stat)) {
    mz_zip_reader_end(&zip_archive);
    TC_ERROR("mz_zip_reader_file_stat() failed!\n");
  }

  if (verbose) {
    TC_TRACE(
        "Filename: {}, Comment: {}, Uncompressed size: {}, Compressed size: "
        "{}, Is Dir: {}\n",
        file_stat.m_filename, file_stat.m_comment,
        (uint)file_stat.m_uncomp_size, (uint)file_stat.m_comp_size,
        mz_zip_reader_is_file_a_directory(&zip_archive, 0));
  }

  // Close the archive, freeing any resources it was using
  mz_zip_reader_end(&zip_archive);

  size_t uncomp_size;
  memset(&zip_archive, 0, sizeof(zip_archive));
  status = mz_zip_reader_init_file(&zip_archive, fn.c_str(), 0);
  if (!status) {
    TC_ERROR("mz_zip_reader_init_file() failed!\n");
  }

  std::string fn_uncompressed = get_file_name_from_whole_path(fn);
  fn_uncompressed = std::string(fn_uncompressed.begin(),
                                fn_uncompressed.end() - 4);  // remove .zip
  auto archive_filename = fn_uncompressed;
  auto p = reinterpret_cast<const uint8 *>(mz_zip_reader_extract_file_to_heap(
      &zip_archive, archive_filename.c_str(), &uncomp_size, 0));

  if (!p) {
    mz_zip_reader_end(&zip_archive);
    TC_ERROR("mz_zip_reader_extract_file_to_heap() failed!");
  }

  if (verbose) {
    TC_TRACE("Successfully extracted file {}, size {}", archive_filename,
             (uint)uncomp_size);
    TC_TRACE("File data: {}", (const char *)p);
  }

  std::vector<uint8> ret(p, p + file_stat.m_uncomp_size);
  mz_free((void *)p);
  return ret;
}

}  // namespace zip

TC_NAMESPACE_END
<|endoftext|>


<commit_before>/** @file
 *
 * @ingroup modularLibrary
 *
 * @brief TTModular Library
 *
 * @details
 *
 * @authors Théo de la Hogue
 *
 * @copyright Copyright © 2010, Théo de la Hogue @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTModular.h"
#include "TTInput.h"
#include "TTInputAudio.h"
#include "TTOutput.h"
#include "TTOutputAudio.h"

// file system needed to retreive the path of JamomaModular.dylib
#ifdef TT_PLATFORM_MAC
#include <dlfcn.h>
#include <sys/types.h>
#include <dirent.h>
#elif TT_PLATFORM_LINUX
#include <dlfcn.h>
#elif TT_PLATFORM_WIN
#include <ShlObj.h>
#endif

// Statics and Globals
static bool TTModularHasInitialized = false;

TTApplicationManagerPtr	TTModularApplications = NULL;

TTHashPtr TTModularNamespaces = NULL;

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

TTString TTModularInit()
{
    TTString    path;

	// Initialized Foundation framework
	TTFoundationInit();

//#define TO_DEBUG
#ifdef TO_DEBUG

	TTObjectBasePtr test = NULL;
	TTValue v;

	TTObjectBaseInstantiate(TTSymbol("nodelib.test"), &test, kTTValNONE);
	test->test(v);

#endif // TO_DEBUG

	if (!TTModularHasInitialized) {

		TTModularHasInitialized = true;

		// register classes -- both internal and external
		TTApplication::registerClass();
		TTApplicationManager::registerClass();
		TTContainer::registerClass();
		TTCue::registerClass();
		TTCueManager::registerClass();
		TTData::registerClass();
		TTExplorer::registerClass();
		TTInput::registerClass();
		TTInputAudio::registerClass();
		TTMapper::registerClass();
		TTMapperManager::registerClass();
		TTMirror::registerClass();
		TTOutput::registerClass();
		TTOutputAudio::registerClass();
		TTPreset::registerClass();
		TTPresetManager::registerClass();
        TTRamp::registerClass();
		TTReceiver::registerClass();
		TTSender::registerClass();
		TTScript::registerClass();
		TTSubscriber::registerClass();
		TTTextHandler::registerClass();
		TTViewer::registerClass();
		TTXmlHandler::registerClass();

		//TTModularValueCacheInit();

		// to - this a very strange bug : the two first toString() parsing on number failed !?!
		// so here are two parsing to avoid this strange bug for instant ...
		TTString s;
		TTValue v;

		s = "0.001";
		v = s;
		v.fromString();

		v.clear();
		s = "1";
		v = s;
		v.fromString();

		// Create the Modular application manager with no application inside
		TTObjectBaseInstantiate(kTTSym_ApplicationManager, TTObjectBaseHandle(&TTModularApplications), kTTValNONE);

		// Create a hash table to manage namespace selections
		TTModularNamespaces = new TTHash();

#ifdef TT_DEBUG
		TTLogMessage("Modular -- Version %s -- Debugging Enabled\n", TTMODULAR_VERSION_STRING);
#else
		TTLogMessage("Modular -- Version %s\n", TTMODULAR_VERSION_STRING);
#endif

        // Return where is the JamomaModular.dylib
        // to : this could be return by the TTFoundationInit method (?)
        Dl_info     info;
        char		temp[4096];
        char*       c = 0;

        if (dladdr((const void*)TTModularInit, &info)) {

            // chop the "/JamomaModular.dylib off of the path
            strncpy(temp, info.dli_fname, 4096);
            c = strrchr(temp, '/');
            if (c)
                *c = 0;

            path = temp;
        }
	}

    return path;
}

void TTModularCreateLocalApplication(TTString applicationStr, TTString xmlConfigFilePath)
{
	TTValue				args;
	TTApplicationPtr	anApplication = NULL;

	if (TTModularApplications) {

		// if the local application doesn't exist yet
		if (!getLocalApplication) {

			// create the application
			args = TTValue(TTSymbol(applicationStr));
			TTObjectBaseInstantiate(kTTSym_Application, TTObjectBaseHandle(&anApplication), args);

			// set it as local application
			args = TTValue(anApplication);
			TTModularApplications->setAttributeValue(TTSymbol("localApplication"), args);

			// Read xml configuration file
			TTXmlHandlerPtr anXmlHandler = NULL;
			TTObjectBaseInstantiate(kTTSym_XmlHandler, TTObjectBaseHandle(&anXmlHandler), kTTValNONE);

			anXmlHandler->setAttributeValue(kTTSym_object, args);

			args = TTValue(TTSymbol(xmlConfigFilePath));
			anXmlHandler->sendMessage(kTTSym_Read, args, kTTValNONE);
		}
		else
			TTLogMessage("Modular -- \"%s\" application already exists", getLocalApplicationName.c_str());
	}
}

TTAddressItemPtr	TTModularNamespacesLookup(TTSymbol namespaceName)
{
	TTAddressItemPtr	aNamespace = NULL;
	TTValue				v;

	if (namespaceName != kTTSymEmpty && namespaceName != kTTSym_none) {

		if (!TTModularNamespaces->lookup(namespaceName, v))
			aNamespace = TTAddressItemPtr((TTPtr)v[0]);

		else {
			aNamespace = new TTAddressItem();

			v = TTValue((TTPtr)aNamespace);
			TTModularNamespaces->append(namespaceName, v);
		}
	}

	return aNamespace;
}

#ifdef TT_PLATFORM_LINUX
int main(void)
{
	// TODO: should we call TTModularInit() here?
	return 0;
}
#endif<commit_msg>minor<commit_after>/** @file
 *
 * @ingroup modularLibrary
 *
 * @brief TTModular Library
 *
 * @details
 *
 * @authors Théo de la Hogue
 *
 * @copyright Copyright © 2010, Théo de la Hogue @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTModular.h"
#include "TTInput.h"
#include "TTInputAudio.h"
#include "TTOutput.h"
#include "TTOutputAudio.h"

// file system needed to retreive the path of JamomaModular.dylib
#ifdef TT_PLATFORM_MAC
#include <dlfcn.h>
#include <sys/types.h>
#include <dirent.h>
#elif TT_PLATFORM_LINUX
#include <dlfcn.h>
#elif TT_PLATFORM_WIN
#include <ShlObj.h>
#endif

// Statics and Globals
static bool TTModularHasInitialized = false;

TTApplicationManagerPtr	TTModularApplications = NULL;

TTHashPtr TTModularNamespaces = NULL;

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

TTString TTModularInit()
{
    TTString    path;

	// Initialized Foundation framework
	TTFoundationInit();

//#define TO_DEBUG
#ifdef TO_DEBUG

	TTObjectBasePtr test = NULL;
	TTValue v;

	TTObjectBaseInstantiate(TTSymbol("dictionary.test"), TTObjectBaseHandle(&test), kTTValNONE);
	test->sendMessage("test", v, kTTValNONE);

#endif // TO_DEBUG

	if (!TTModularHasInitialized) {

		TTModularHasInitialized = true;

		// register classes -- both internal and external
		TTApplication::registerClass();
		TTApplicationManager::registerClass();
		TTContainer::registerClass();
		TTCue::registerClass();
		TTCueManager::registerClass();
		TTData::registerClass();
		TTExplorer::registerClass();
		TTInput::registerClass();
		TTInputAudio::registerClass();
		TTMapper::registerClass();
		TTMapperManager::registerClass();
		TTMirror::registerClass();
		TTOutput::registerClass();
		TTOutputAudio::registerClass();
		TTPreset::registerClass();
		TTPresetManager::registerClass();
        TTRamp::registerClass();
		TTReceiver::registerClass();
		TTSender::registerClass();
		TTScript::registerClass();
		TTSubscriber::registerClass();
		TTTextHandler::registerClass();
		TTViewer::registerClass();
		TTXmlHandler::registerClass();

		//TTModularValueCacheInit();

		// to - this a very strange bug : the two first toString() parsing on number failed !?!
		// so here are two parsing to avoid this strange bug for instant ...
		TTString s;
		TTValue v;

		s = "0.001";
		v = s;
		v.fromString();

		v.clear();
		s = "1";
		v = s;
		v.fromString();

		// Create the Modular application manager with no application inside
		TTObjectBaseInstantiate(kTTSym_ApplicationManager, TTObjectBaseHandle(&TTModularApplications), kTTValNONE);

		// Create a hash table to manage namespace selections
		TTModularNamespaces = new TTHash();

#ifdef TT_DEBUG
		TTLogMessage("Modular -- Version %s -- Debugging Enabled\n", TTMODULAR_VERSION_STRING);
#else
		TTLogMessage("Modular -- Version %s\n", TTMODULAR_VERSION_STRING);
#endif

        // Return where is the JamomaModular.dylib
        // to : this could be return by the TTFoundationInit method (?)
        Dl_info     info;
        char		temp[4096];
        char*       c = 0;

        if (dladdr((const void*)TTModularInit, &info)) {

            // chop the "/JamomaModular.dylib off of the path
            strncpy(temp, info.dli_fname, 4096);
            c = strrchr(temp, '/');
            if (c)
                *c = 0;

            path = temp;
        }
	}

    return path;
}

void TTModularCreateLocalApplication(TTString applicationStr, TTString xmlConfigFilePath)
{
	TTValue				args;
	TTApplicationPtr	anApplication = NULL;

	if (TTModularApplications) {

		// if the local application doesn't exist yet
		if (!getLocalApplication) {

			// create the application
			args = TTValue(TTSymbol(applicationStr));
			TTObjectBaseInstantiate(kTTSym_Application, TTObjectBaseHandle(&anApplication), args);

			// set it as local application
			args = TTValue(anApplication);
			TTModularApplications->setAttributeValue(TTSymbol("localApplication"), args);

			// Read xml configuration file
			TTXmlHandlerPtr anXmlHandler = NULL;
			TTObjectBaseInstantiate(kTTSym_XmlHandler, TTObjectBaseHandle(&anXmlHandler), kTTValNONE);

			anXmlHandler->setAttributeValue(kTTSym_object, args);

			args = TTValue(TTSymbol(xmlConfigFilePath));
			anXmlHandler->sendMessage(kTTSym_Read, args, kTTValNONE);
		}
		else
			TTLogMessage("Modular -- \"%s\" application already exists", getLocalApplicationName.c_str());
	}
}

TTAddressItemPtr	TTModularNamespacesLookup(TTSymbol namespaceName)
{
	TTAddressItemPtr	aNamespace = NULL;
	TTValue				v;

	if (namespaceName != kTTSymEmpty && namespaceName != kTTSym_none) {

		if (!TTModularNamespaces->lookup(namespaceName, v))
			aNamespace = TTAddressItemPtr((TTPtr)v[0]);

		else {
			aNamespace = new TTAddressItem();

			v = TTValue((TTPtr)aNamespace);
			TTModularNamespaces->append(namespaceName, v);
		}
	}

	return aNamespace;
}

#ifdef TT_PLATFORM_LINUX
int main(void)
{
	// TODO: should we call TTModularInit() here?
	return 0;
}
#endif<|endoftext|>