<commit_before>// Copyright (c) 2009, Google Inc.
// 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
// OWNER 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.

// The ExceptionHandler object installs signal handlers for a number of
// signals. We rely on the signal handler running on the thread which crashed
// in order to identify it. This is true of the synchronous signals (SEGV etc),
// but not true of ABRT. Thus, if you send ABRT to yourself in a program which
// uses ExceptionHandler, you need to use tgkill to direct it to the current
// thread.
//
// The signal flow looks like this:
//
//   SignalHandler (uses a global stack of ExceptionHandler objects to find
//        |         one to handle the signal. If the first rejects it, try
//        |         the second etc...)
//        V
//   HandleSignal ----------------------------| (clones a new process which
//        |                                   |  shares an address space with
//   (wait for cloned                         |  the crashed process. This
//     process)                               |  allows us to ptrace the crashed
//        |                                   |  process)
//        V                                   V
//   (set signal handler to             ThreadEntry (static function to bounce
//    SIG_DFL and rethrow,                    |      back into the object)
//    killing the crashed                     |
//    process)                                V
//                                          DoDump  (writes minidump)
//                                            |
//                                            V
//                                         sys_exit
//

// This code is a little fragmented. Different functions of the ExceptionHandler
// class run in a number of different contexts. Some of them run in a normal
// context and are easy to code, others run in a compromised context and the
// restrictions at the top of minidump_writer.cc apply: no libc and use the
// alternative malloc. Each function should have comment above it detailing the
// context which it runs in.

#include "breakpad/linux/exception_handler.h"

#include <errno.h>
#include <fcntl.h>
#include <linux/limits.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/signal.h>
#include <sys/syscall.h>
#include <sys/ucontext.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <unistd.h>

#include "breakpad/linux/linux_syscall_support.h"
#include "breakpad/linux/memory.h"
#include "breakpad/linux/minidump_writer.h"
#include "common/linux/guid_creator.h"

// A wrapper for the tgkill syscall: send a signal to a specific thread.
static int tgkill(pid_t tgid, pid_t tid, int sig) {
  syscall(__NR_tgkill, tgid, tid, sig);
}

namespace google_breakpad {

// The list of signals which we consider to be crashes. The default action for
// all these signals must be Core (see man 7 signal) because we rethrow the
// signal after handling it and expect that it'll be fatal.
static const int kExceptionSignals[] = {
  SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, -1
};

// We can stack multiple exception handlers. In that case, this is the global
// which holds the stack.
std::vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL;
unsigned ExceptionHandler::handler_stack_index_ = 0;
pthread_mutex_t ExceptionHandler::handler_stack_mutex_ =
    PTHREAD_MUTEX_INITIALIZER;

// Runs before crashing: normal context.
ExceptionHandler::ExceptionHandler(const std::string &dump_path,
                                   FilterCallback filter,
                                   MinidumpCallback callback,
                                   void *callback_context,
                                   bool install_handler)
    : filter_(filter),
      callback_(callback),
      callback_context_(callback_context),
      dump_path_(),
      handler_installed_(install_handler),
      crash_handler_(NULL) {
  set_dump_path(dump_path);

  if (install_handler) {
    InstallHandlers();

    pthread_mutex_lock(&handler_stack_mutex_);
      if (handler_stack_ == NULL)
        handler_stack_ = new std::vector<ExceptionHandler *>;
      handler_stack_->push_back(this);
    pthread_mutex_unlock(&handler_stack_mutex_);
  }
}

// Runs before crashing: normal context.
ExceptionHandler::~ExceptionHandler() {
  UninstallHandlers();
}

// Runs before crashing: normal context.
bool ExceptionHandler::InstallHandlers() {
  // We run the signal handlers on an alternative stack because we might have
  // crashed because of a stack overflow.

  // We use this value rather than SIGSTKSZ because we would end up overrunning
  // such a small stack.
  static const unsigned kSigStackSize = 8192;

  signal_stack = malloc(kSigStackSize);
  stack_t stack;
  memset(&stack, 0, sizeof(stack));
  stack.ss_sp = signal_stack;
  stack.ss_size = kSigStackSize;

  if (sigaltstack(&stack, NULL) == -1)
    return false;

  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sigemptyset(&sa.sa_mask);

  // mask all exception signals when we're handling one of them.
  for (unsigned i = 0; kExceptionSignals[i] != -1; ++i)
    sigaddset(&sa.sa_mask, kExceptionSignals[i]);

  sa.sa_sigaction = SignalHandler;
  sa.sa_flags = SA_ONSTACK | SA_SIGINFO;

  for (unsigned i = 0; kExceptionSignals[i] != -1; ++i) {
    struct sigaction* old = new struct sigaction;
    if (sigaction(kExceptionSignals[i], &sa, old) == -1)
      return false;
    old_handlers_.push_back(std::make_pair(kExceptionSignals[i], old));
  }
}

// Runs before crashing: normal context.
void ExceptionHandler::UninstallHandlers() {
  for (unsigned i = 0; i < old_handlers_.size(); ++i) {
    struct sigaction *action =
        reinterpret_cast<struct sigaction*>(old_handlers_[i].second);
    sigaction(old_handlers_[i].first, action, NULL);
    delete action;
  }

  old_handlers_.clear();
}

// Runs before crashing: normal context.
void ExceptionHandler::UpdateNextID() {
  GUID guid;
  char guid_str[kGUIDStringLength + 1];
  if (CreateGUID(&guid) && GUIDToString(&guid, guid_str, sizeof(guid_str))) {
    next_minidump_id_ = guid_str;
    next_minidump_id_c_ = next_minidump_id_.c_str();

    char minidump_path[PATH_MAX];
    snprintf(minidump_path, sizeof(minidump_path), "%s/%s.dmp",
             dump_path_c_,
             guid_str);

    next_minidump_path_ = minidump_path;
    next_minidump_path_c_ = next_minidump_path_.c_str();
  }
}

// This function runs in a compromised context: see the top of the file.
// Runs on the crashing thread.
// static
void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
  // All the exception signals are blocked at this point.

  pthread_mutex_lock(&handler_stack_mutex_);

  if (!handler_stack_->size()) {
    pthread_mutex_unlock(&handler_stack_mutex_);
    return;
  }

  for (int i = handler_stack_->size() - 1; i >= 0; --i) {
    if ((*handler_stack_)[i]->HandleSignal(sig, info, uc)) {
      // successfully handled: We are in an invalid state since an exception
      // signal has been delivered. We don't call the exit handlers because
      // they could end up corrupting on-disk state.
      break;
    }
  }

  pthread_mutex_unlock(&handler_stack_mutex_);

  // Terminate ourselves with the same signal so that our parent knows that we
  // crashed. The default action for all the signals which we catch is Core, so
  // this is the end of us.
  signal(sig, SIG_DFL);
  tgkill(getpid(), sys_gettid(), sig);

  // not reached.
}

struct ThreadArgument {
  pid_t pid;  // the crashing process
  ExceptionHandler* handler;
  const void* context;  // a CrashContext structure
  size_t context_size;
};

// This is the entry function for the cloned process. We are in a compromised
// context here: see the top of the file.
// static
int ExceptionHandler::ThreadEntry(void *arg) {
  const ThreadArgument *thread_arg = reinterpret_cast<ThreadArgument*>(arg);
  return thread_arg->handler->DoDump(thread_arg->pid, thread_arg->context,
                                     thread_arg->context_size) == false;
}

// This function runs in a compromised context: see the top of the file.
// Runs on the crashing thread.
bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) {
  if (filter_ && !filter_(callback_context_))
    return false;

  CrashContext context;
  memcpy(&context.siginfo, info, sizeof(siginfo_t));
  memcpy(&context.context, uc, sizeof(struct ucontext));
  context.tid = sys_gettid();

  if (crash_handler_ && crash_handler_(&context, sizeof(context),
                                       callback_context_))
    return true;

  PageAllocator allocator;
  void* const stack = allocator.Alloc(8000);

  ThreadArgument thread_arg;
  thread_arg.handler = this;
  thread_arg.pid = getpid();
  thread_arg.context = &context;
  thread_arg.context_size = sizeof(context);

  const pid_t child = sys_clone(
      ThreadEntry, stack, CLONE_FILES | CLONE_FS | CLONE_UNTRACED,
      &thread_arg, NULL, NULL, NULL);
  int r, status;
  do {
    r = sys_waitpid(child, &status, __WALL);
  } while (r == -1 && errno == EINTR);

  if (r == -1) {
    static const char msg[] = "ExceptionHandler::HandleSignal: waitpid failed:";
    sys_write(2, msg, sizeof(msg) - 1);
    sys_write(2, strerror(errno), strlen(strerror(errno)));
    sys_write(2, "\n", 1);
  }

  bool success = r != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0;

  if (callback_)
    success = callback_(dump_path_c_, next_minidump_id_c_,
                        callback_context_, success);

  return success;
}

// This function runs in a compromised context: see the top of the file.
// Runs on the cloned process.
bool ExceptionHandler::DoDump(pid_t crashing_process, const void* context,
                              size_t context_size) {
  return google_breakpad::WriteMinidump(
      next_minidump_path_c_, crashing_process, context, context_size);
}

}  // namespace google_breakpad
<commit_msg>In Linux Breakpad, point the child stack at the top-most address rather than the bottom-most address before calling clone().<commit_after>// Copyright (c) 2009, Google Inc.
// 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
// OWNER 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.

// The ExceptionHandler object installs signal handlers for a number of
// signals. We rely on the signal handler running on the thread which crashed
// in order to identify it. This is true of the synchronous signals (SEGV etc),
// but not true of ABRT. Thus, if you send ABRT to yourself in a program which
// uses ExceptionHandler, you need to use tgkill to direct it to the current
// thread.
//
// The signal flow looks like this:
//
//   SignalHandler (uses a global stack of ExceptionHandler objects to find
//        |         one to handle the signal. If the first rejects it, try
//        |         the second etc...)
//        V
//   HandleSignal ----------------------------| (clones a new process which
//        |                                   |  shares an address space with
//   (wait for cloned                         |  the crashed process. This
//     process)                               |  allows us to ptrace the crashed
//        |                                   |  process)
//        V                                   V
//   (set signal handler to             ThreadEntry (static function to bounce
//    SIG_DFL and rethrow,                    |      back into the object)
//    killing the crashed                     |
//    process)                                V
//                                          DoDump  (writes minidump)
//                                            |
//                                            V
//                                         sys_exit
//

// This code is a little fragmented. Different functions of the ExceptionHandler
// class run in a number of different contexts. Some of them run in a normal
// context and are easy to code, others run in a compromised context and the
// restrictions at the top of minidump_writer.cc apply: no libc and use the
// alternative malloc. Each function should have comment above it detailing the
// context which it runs in.

#include "breakpad/linux/exception_handler.h"

#include <errno.h>
#include <fcntl.h>
#include <linux/limits.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/signal.h>
#include <sys/syscall.h>
#include <sys/ucontext.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <unistd.h>

#include "breakpad/linux/linux_libc_support.h"
#include "breakpad/linux/linux_syscall_support.h"
#include "breakpad/linux/memory.h"
#include "breakpad/linux/minidump_writer.h"
#include "common/linux/guid_creator.h"

// A wrapper for the tgkill syscall: send a signal to a specific thread.
static int tgkill(pid_t tgid, pid_t tid, int sig) {
  syscall(__NR_tgkill, tgid, tid, sig);
}

namespace google_breakpad {

// The list of signals which we consider to be crashes. The default action for
// all these signals must be Core (see man 7 signal) because we rethrow the
// signal after handling it and expect that it'll be fatal.
static const int kExceptionSignals[] = {
  SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, -1
};

// We can stack multiple exception handlers. In that case, this is the global
// which holds the stack.
std::vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL;
unsigned ExceptionHandler::handler_stack_index_ = 0;
pthread_mutex_t ExceptionHandler::handler_stack_mutex_ =
    PTHREAD_MUTEX_INITIALIZER;

// Runs before crashing: normal context.
ExceptionHandler::ExceptionHandler(const std::string &dump_path,
                                   FilterCallback filter,
                                   MinidumpCallback callback,
                                   void *callback_context,
                                   bool install_handler)
    : filter_(filter),
      callback_(callback),
      callback_context_(callback_context),
      dump_path_(),
      handler_installed_(install_handler),
      crash_handler_(NULL) {
  set_dump_path(dump_path);

  if (install_handler) {
    InstallHandlers();

    pthread_mutex_lock(&handler_stack_mutex_);
      if (handler_stack_ == NULL)
        handler_stack_ = new std::vector<ExceptionHandler *>;
      handler_stack_->push_back(this);
    pthread_mutex_unlock(&handler_stack_mutex_);
  }
}

// Runs before crashing: normal context.
ExceptionHandler::~ExceptionHandler() {
  UninstallHandlers();
}

// Runs before crashing: normal context.
bool ExceptionHandler::InstallHandlers() {
  // We run the signal handlers on an alternative stack because we might have
  // crashed because of a stack overflow.

  // We use this value rather than SIGSTKSZ because we would end up overrunning
  // such a small stack.
  static const unsigned kSigStackSize = 8192;

  signal_stack = malloc(kSigStackSize);
  stack_t stack;
  memset(&stack, 0, sizeof(stack));
  stack.ss_sp = signal_stack;
  stack.ss_size = kSigStackSize;

  if (sigaltstack(&stack, NULL) == -1)
    return false;

  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sigemptyset(&sa.sa_mask);

  // mask all exception signals when we're handling one of them.
  for (unsigned i = 0; kExceptionSignals[i] != -1; ++i)
    sigaddset(&sa.sa_mask, kExceptionSignals[i]);

  sa.sa_sigaction = SignalHandler;
  sa.sa_flags = SA_ONSTACK | SA_SIGINFO;

  for (unsigned i = 0; kExceptionSignals[i] != -1; ++i) {
    struct sigaction* old = new struct sigaction;
    if (sigaction(kExceptionSignals[i], &sa, old) == -1)
      return false;
    old_handlers_.push_back(std::make_pair(kExceptionSignals[i], old));
  }
}

// Runs before crashing: normal context.
void ExceptionHandler::UninstallHandlers() {
  for (unsigned i = 0; i < old_handlers_.size(); ++i) {
    struct sigaction *action =
        reinterpret_cast<struct sigaction*>(old_handlers_[i].second);
    sigaction(old_handlers_[i].first, action, NULL);
    delete action;
  }

  old_handlers_.clear();
}

// Runs before crashing: normal context.
void ExceptionHandler::UpdateNextID() {
  GUID guid;
  char guid_str[kGUIDStringLength + 1];
  if (CreateGUID(&guid) && GUIDToString(&guid, guid_str, sizeof(guid_str))) {
    next_minidump_id_ = guid_str;
    next_minidump_id_c_ = next_minidump_id_.c_str();

    char minidump_path[PATH_MAX];
    snprintf(minidump_path, sizeof(minidump_path), "%s/%s.dmp",
             dump_path_c_,
             guid_str);

    next_minidump_path_ = minidump_path;
    next_minidump_path_c_ = next_minidump_path_.c_str();
  }
}

// This function runs in a compromised context: see the top of the file.
// Runs on the crashing thread.
// static
void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
  // All the exception signals are blocked at this point.

  pthread_mutex_lock(&handler_stack_mutex_);

  if (!handler_stack_->size()) {
    pthread_mutex_unlock(&handler_stack_mutex_);
    return;
  }

  for (int i = handler_stack_->size() - 1; i >= 0; --i) {
    if ((*handler_stack_)[i]->HandleSignal(sig, info, uc)) {
      // successfully handled: We are in an invalid state since an exception
      // signal has been delivered. We don't call the exit handlers because
      // they could end up corrupting on-disk state.
      break;
    }
  }

  pthread_mutex_unlock(&handler_stack_mutex_);

  // Terminate ourselves with the same signal so that our parent knows that we
  // crashed. The default action for all the signals which we catch is Core, so
  // this is the end of us.
  signal(sig, SIG_DFL);
  tgkill(getpid(), sys_gettid(), sig);

  // not reached.
}

struct ThreadArgument {
  pid_t pid;  // the crashing process
  ExceptionHandler* handler;
  const void* context;  // a CrashContext structure
  size_t context_size;
};

// This is the entry function for the cloned process. We are in a compromised
// context here: see the top of the file.
// static
int ExceptionHandler::ThreadEntry(void *arg) {
  const ThreadArgument *thread_arg = reinterpret_cast<ThreadArgument*>(arg);
  return thread_arg->handler->DoDump(thread_arg->pid, thread_arg->context,
                                     thread_arg->context_size) == false;
}

// This function runs in a compromised context: see the top of the file.
// Runs on the crashing thread.
bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) {
  if (filter_ && !filter_(callback_context_))
    return false;

  CrashContext context;
  memcpy(&context.siginfo, info, sizeof(siginfo_t));
  memcpy(&context.context, uc, sizeof(struct ucontext));
  context.tid = sys_gettid();

  if (crash_handler_ && crash_handler_(&context, sizeof(context),
                                       callback_context_))
    return true;

  static const unsigned kChildStackSize = 8000;
  PageAllocator allocator;
  uint8_t* stack = (uint8_t*) allocator.Alloc(kChildStackSize);
  if (!stack)
    return false;
  // clone() needs the top-most address. (scrub just to be safe)
  stack += kChildStackSize;
  my_memset(stack - 16, 0, 16);

  ThreadArgument thread_arg;
  thread_arg.handler = this;
  thread_arg.pid = getpid();
  thread_arg.context = &context;
  thread_arg.context_size = sizeof(context);

  const pid_t child = sys_clone(
      ThreadEntry, stack, CLONE_FILES | CLONE_FS | CLONE_UNTRACED,
      &thread_arg, NULL, NULL, NULL);
  int r, status;
  do {
    r = sys_waitpid(child, &status, __WALL);
  } while (r == -1 && errno == EINTR);

  if (r == -1) {
    static const char msg[] = "ExceptionHandler::HandleSignal: waitpid failed:";
    sys_write(2, msg, sizeof(msg) - 1);
    sys_write(2, strerror(errno), strlen(strerror(errno)));
    sys_write(2, "\n", 1);
  }

  bool success = r != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0;

  if (callback_)
    success = callback_(dump_path_c_, next_minidump_id_c_,
                        callback_context_, success);

  return success;
}

// This function runs in a compromised context: see the top of the file.
// Runs on the cloned process.
bool ExceptionHandler::DoDump(pid_t crashing_process, const void* context,
                              size_t context_size) {
  return google_breakpad::WriteMinidump(
      next_minidump_path_c_, crashing_process, context, context_size);
}

}  // namespace google_breakpad
<|endoftext|>


<commit_before>#ifndef _CAIROCANVAS_CAIRO_HXX
#define _CAIROCANVAS_CAIRO_HXX

namespace cairo {

#include <cairo.h>

    typedef cairo_t Cairo;
    typedef cairo_matrix_t Matrix;
    typedef cairo_format_t Format;
    typedef cairo_content_t Content;
    typedef cairo_pattern_t Pattern;

    class Surface {
        const void* mpSysData;
        void* mpDisplay;
        long mhDrawable;
        void *mpRenderFormat;
        int mnRefCount;
        bool mbFreePixmap;
    public:
        cairo_surface_t* mpSurface;

        Surface( const void* pSysData, void* pDisplay, long hDrawable, void* pRenderFormat, cairo_surface_t* pSurface )
            : mpSysData( pSysData ),
              mpDisplay( pDisplay ),
              mhDrawable( hDrawable ),
              mpRenderFormat( pRenderFormat ),
              mpSurface( pSurface ),
              mbFreePixmap( true ),
              mnRefCount( 1 )
        {
        }

        Surface( cairo_surface_t* pSurface )
            : mpSurface( pSurface ),
              mpDisplay( NULL ),
              mhDrawable( 0 ),
              mpSysData( NULL ),
              mbFreePixmap( false ),
              mnRefCount( 1 )
        {
        }

        Surface( const void* pSysData, int x, int y, int width, int height );
        Surface( const void* pSysData, void *pBmpData, int width, int height );

        ~Surface();

        void Ref()
        {
            mnRefCount ++;
        }

        void Unref()
        {
            mnRefCount --;
            if( mnRefCount <= 0 )
                delete this;
        }

        Cairo* getCairo()
        {
            return cairo_create( mpSurface );
        }

        Surface* getSimilar( Content aContent, int width, int height );

        long getPixmap()
        {
            return mhDrawable;
        }

        void* getRenderFormat()
        {
            return mpRenderFormat;
        }
    };
}

#endif
<commit_msg>INTEGRATION: CWS cairofixes01 (1.2.2); FILE MERGED 2006/03/02 17:56:17 radekdoulik 1.2.2.2: Issue number:  62722 Submitted by:  radekdoulik Reviewed by:   radekdoulik 2006-02-22  Radek Doulik  <rodo@novell.com><commit_after>#ifndef _CAIROCANVAS_CAIRO_HXX
#define _CAIROCANVAS_CAIRO_HXX

namespace cairo {

#include <cairo.h>

    typedef cairo_t Cairo;
    typedef cairo_matrix_t Matrix;
    typedef cairo_format_t Format;
    typedef cairo_content_t Content;
    typedef cairo_pattern_t Pattern;

    class Surface {
        const void* mpSysData;
        void* mpDisplay;
        long mhDrawable;
        void *mpRenderFormat;
        int mnRefCount;
        bool mbFreePixmap;
    public:
        cairo_surface_t* mpSurface;

        Surface( const void* pSysData, void* pDisplay, long hDrawable, void* pRenderFormat, cairo_surface_t* pSurface )
            : mpSysData( pSysData ),
              mpDisplay( pDisplay ),
              mhDrawable( hDrawable ),
              mpRenderFormat( pRenderFormat ),
              mpSurface( pSurface ),
              mbFreePixmap( true ),
              mnRefCount( 1 )
        {
        }

        Surface( cairo_surface_t* pSurface )
            : mpSurface( pSurface ),
              mpDisplay( NULL ),
              mhDrawable( 0 ),
              mpSysData( NULL ),
              mpRenderFormat( NULL ),
              mbFreePixmap( false ),
              mnRefCount( 1 )
        {
        }

        Surface( const void* pSysData, int x, int y, int width, int height );
        Surface( const void* pSysData, void *pBmpData, int width, int height );

        ~Surface();

        void Ref()
        {
            mnRefCount ++;
        }

        void Unref()
        {
            mnRefCount --;
            if( mnRefCount <= 0 )
                delete this;
        }

        Cairo* getCairo()
        {
            return cairo_create( mpSurface );
        }

        Surface* getSimilar( Content aContent, int width, int height );

        long getPixmap()
        {
            return mhDrawable;
        }

        void* getRenderFormat()
        {
            return mpRenderFormat;
        }

        // use only for surfaces made on X Drawables
        void Resize( int width, int height );

        int getDepth();
    };
}

#endif
<|endoftext|>


<commit_before><commit_msg>Replicate r59512 for localtime_r<commit_after><|endoftext|>


<commit_before>/*
Unity build file using SDL2
 */

#include <assert.h>
#include <time.h> // used by log
#include <float.h> // for FLT_MAX
#include <stdio.h> // for printf

#include <sys/stat.h> // fstat

#include <SDL.h>
#ifndef __APPLE__
	#include <GL/glew.h>
#endif
#define GL_GLEXT_PROTOTYPES
#include <SDL_opengl.h>
#include <SDL_opengl_glext.h>

#define COMPANY_NAME "FabioWare"
#define APPLICATION_NAME "TwoTriangles"
#define WINDOW_TITLE "Two Triangles"
SDL_Window *sdl_window;
SDL_GLContext sdl_gl_context;

bool windowIsFullscreen();
void windowToggleFullscreen();

// ImGui
#include <imgui.h>
#include "imgui_impl_sdl2_gl2.h" // the impl we want to use

// nativfiledialog
#include <nfd.h>

// stb_image
#include <stb_image.h>

#include "system/defines.h"
#include "system/log.h"
#include "system/files.h"
#include "system/frametime.h"

#include "math/vector_math.h"
#include "math/transform.h"

#include "video/shader.h"
#include "video/texture.h"
#include "video/model_mdl.h"
#include "video/font_bitmap.h"
#include "video/video_mode.h"
#include "video/camera.h"
//#include "video/renderer.h"

#include "video/shader_uniform.h"
#include "app/app.h"

#include "system/log.cpp"
#include "system/files.cpp"
#include "system/frametime_sdl2.cpp"

#include "math/transform.cpp"

#include "video/shader.cpp"
#include "video/texture.cpp"
//#include "video/texture_dds.cpp"
//#include "video/model_mdl.cpp"
#include "video/font_bitmap.cpp"
#include "video/camera.cpp"
//#include "video/renderer.cpp"

#include "video/shader_uniform.cpp"
#include "app/app.cpp"

/* inits sdl and creates an opengl window */
static void initSDL(VideoMode *video) {
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) {
		LOGE("Failed to init SDL2: %s", SDL_GetError());
		exit(1);
	}

	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
	//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
	//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);

#ifdef EMSCRIPTEN
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
						SDL_GL_CONTEXT_PROFILE_ES);
#else
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
						SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
#endif

	int window_flags =
		  SDL_WINDOW_SHOWN
		| SDL_WINDOW_RESIZABLE
		| SDL_WINDOW_OPENGL
		//| SDL_WINDOW_ALLOW_HIGHDPI
		;

	sdl_window = SDL_CreateWindow(WINDOW_TITLE,
		SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
		video->width, video->height, window_flags);
	if (!sdl_window) {
		LOGE("Failed to create an OpenGL window: %s", SDL_GetError());
		exit(1);
	}

	sdl_gl_context = SDL_GL_CreateContext(sdl_window);
	if (!sdl_gl_context) {
		LOGE("Failed to create an OpenGL context: %s", SDL_GetError());
		exit(1);
	}

	int drawable_width, drawable_height;
	SDL_GL_GetDrawableSize(sdl_window, &drawable_width, &drawable_height);
	if (drawable_width != video->width) {
		LOGI("Created high DPI window. (%dx%d)", drawable_width, drawable_height);
		video->pixel_scale = (float)drawable_width / (float)video->width;
	} else {
		video->pixel_scale = 1.0f;
	}

	if (SDL_GL_SetSwapInterval(1) == -1) { // sync with monitor refresh rate
		LOGW("Could not enable VSync.");
	}

	#ifndef __APPLE__
	glewInit();
	#endif
}

void quitSDL() {
	SDL_DestroyWindow(sdl_window);
	SDL_GL_DeleteContext(sdl_gl_context);
	SDL_Quit();
}

void FrameTime::drawInfo() {
	char fps_text[64];
	sprintf(fps_text, "FPS: %d\nframe time: %.3f ms", frames_per_second, 1000.0*smoothed_frame_time);
	bitmapfont.drawText(fps_text, 8, 8);
}

App *app = nullptr;

bool windowIsFullscreen() {
	return !!(SDL_GetWindowFlags(sdl_window)&SDL_WINDOW_FULLSCREEN_DESKTOP);
}

void windowToggleFullscreen() {
	SDL_SetWindowFullscreen(sdl_window,
		windowIsFullscreen() ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
}

u64 mouse_timer = 0;

void mainLoop() {
	ImGuiIO& io = ImGui::GetIO();
	SDL_Event sdl_event;
	while (SDL_PollEvent(&sdl_event)) {
		ImGui_ImplSdlGL2_ProcessEvent(&sdl_event);
		switch (sdl_event.type) {
			case SDL_WINDOWEVENT:
				switch (sdl_event.window.event) {
		        	case SDL_WINDOWEVENT_SIZE_CHANGED: {
						app->video.width  = sdl_event.window.data1;
						app->video.height = sdl_event.window.data2;
						// update opengl viewport
						int drawable_width, drawable_height;
						SDL_GL_GetDrawableSize(sdl_window, &drawable_width, &drawable_height);
						glViewport(0, 0, drawable_width, drawable_height);
						break;
					}
				}
				break;
			case SDL_MOUSEMOTION:
				mouse_timer = 0;
				break;
			case SDL_QUIT:
				app->quit = true;
				break;
			case SDL_KEYDOWN: {
				if (!io.WantCaptureKeyboard) {
					if (sdl_event.key.keysym.sym == SDLK_SPACE) {
						app->toggleAnimation();
					}
				}

				// handle hotkeys
				bool ctrl_key_down = io.OSXBehaviors ? io.KeySuper : io.KeyCtrl;
				bool shift_key_down = io.KeyShift;
				if (ctrl_key_down) {
					switch (sdl_event.key.keysym.sym) {
						case SDLK_1: case SDLK_2: case SDLK_3:
							app->toggleWindow(sdl_event.key.keysym.sym-SDLK_1);
							break;
						case SDLK_f: // fullscreen
							windowToggleFullscreen();
							break;
						case SDLK_h: // hide gui
							if (!io.OSXBehaviors || shift_key_down) app->hide_gui = !app->hide_gui; // toggle imgui
							break;
						case SDLK_o: // open
							app->openShaderDialog();
							break;
						case SDLK_q: // quit
							app->quit = true;
							break;
						case SDLK_s: // save
							if (shift_key_down) app->saveShaderDialog();
							else app->saveShader();
							break;
						default: break;
					}
				}
				if (sdl_event.key.keysym.sym == SDLK_F11) {
					windowToggleFullscreen();
				}
				break;
			}
		}
	}

	// TODO: make use of mouse_timer
	// doesn't seam to work on OS X?
	SDL_ShowCursor(app->hide_gui ? SDL_DISABLE : SDL_ENABLE);

	// TODO: better keyboard handling
	// update input commands
	// TODO: move this to some function
	// this also depends on the game state
	// when do we want a movement command?
	const Uint8 *key_state = SDL_GetKeyboardState(NULL);
	app->movement_command.move = v3(
		- (key_state[SDL_SCANCODE_A] == SDL_PRESSED ? 1.0f : 0.0f)
		+ (key_state[SDL_SCANCODE_D] == SDL_PRESSED ? 1.0f : 0.0f),
		- (key_state[SDL_SCANCODE_S] == SDL_PRESSED ? 1.0f : 0.0f)
		+ (key_state[SDL_SCANCODE_W] == SDL_PRESSED ? 1.0f : 0.0f),
		- (key_state[SDL_SCANCODE_Q] == SDL_PRESSED ? 1.0f : 0.0f)
		+ (key_state[SDL_SCANCODE_E] == SDL_PRESSED ? 1.0f : 0.0f));
	app->movement_command.rotate = v2(
		- (key_state[SDL_SCANCODE_UP   ] == SDL_PRESSED ? 1.0f : 0.0f)
		+ (key_state[SDL_SCANCODE_DOWN ] == SDL_PRESSED ? 1.0f : 0.0f),
		- (key_state[SDL_SCANCODE_LEFT ] == SDL_PRESSED ? 1.0f : 0.0f)
		+ (key_state[SDL_SCANCODE_RIGHT] == SDL_PRESSED ? 1.0f : 0.0f));

	if (!app->hide_gui && io.WantCaptureKeyboard) { // null movement
		app->movement_command.move = v3(0.0f);
		app->movement_command.rotate = v2(0.0f);
	}

	ImGui_ImplSdlGL2_NewFrame();

	app->update((float)frametime.smoothed_frame_time);

	ImGui::Render();

	SDL_GL_SwapWindow(sdl_window);
	frametime.update();
}

int main(int argc, char *argv[]) {
	app = new App();
	app->video.width = 1024;
	app->video.height = 640;
	app->video.pixel_scale = 1.0f;

	// set preferences_filepath and read preferences
	char *pref_path = SDL_GetPrefPath(COMPANY_NAME, APPLICATION_NAME);

	size_t preferences_ini_str_len = strlen(pref_path)+strlen("preferences.ini")+1;
	app->preferences_filepath = new char[preferences_ini_str_len];
	strcpy(app->preferences_filepath, pref_path);
	strcat(app->preferences_filepath, "preferences.ini");
	size_t session_ini_str_len = strlen(pref_path)+strlen("session.ini")+1;
	app->session_filepath = new char[session_ini_str_len];
	strcpy(app->session_filepath, pref_path);
	strcat(app->session_filepath, "session.ini");
	size_t imgui_ini_str_len = strlen(pref_path)+strlen("imgui.ini")+1;
	ImGuiIO& io = ImGui::GetIO();
	char *imgui_ini_filepath = new char[imgui_ini_str_len];
	strcpy(imgui_ini_filepath, pref_path);
	strcat(imgui_ini_filepath, "imgui.ini");
	io.IniFilename = imgui_ini_filepath;

	SDL_free(pref_path);
	app->readPreferences();
	app->readSession();

	initSDL(&app->video);

	ImGui_ImplSdlGL2_Init(sdl_window);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	app->init();

	// init this last for sake of last_ticks
	frametime.init();

	do {
		Uint32 beginTicks = SDL_GetTicks();
		mainLoop();
		// hack for when vsync isn't working
		Uint32 elapsedTicks = SDL_GetTicks() - beginTicks;
		if (elapsedTicks < 16) {
			SDL_Delay(16 - elapsedTicks);
		}
	} while(!app->quit);

	app->beforeQuit();

	ImGui_ImplSdlGL2_Shutdown();
	quitSDL();

	return 0;
}
<commit_msg>Update main_sdl2_ub.cpp<commit_after>/*
Unity build file using SDL2
 */

#include <assert.h>
#include <time.h> // used by log
#include <float.h> // for FLT_MAX
#include <stdio.h> // for printf
#include <stdlib.h> // for atoi

#include <sys/stat.h> // fstat

#include <SDL.h>
#ifndef __APPLE__
	#include <GL/glew.h>
#endif
#define GL_GLEXT_PROTOTYPES
#include <SDL_opengl.h>
#include <SDL_opengl_glext.h>

#define COMPANY_NAME "FabioWare"
#define APPLICATION_NAME "TwoTriangles"
#define WINDOW_TITLE "Two Triangles"
SDL_Window *sdl_window;
SDL_GLContext sdl_gl_context;

bool windowIsFullscreen();
void windowToggleFullscreen();

// ImGui
#include <imgui.h>
#include "imgui_impl_sdl2_gl2.h" // the impl we want to use

// nativfiledialog
#include <nfd.h>

// stb_image
#include <stb_image.h>

#include "system/defines.h"
#include "system/log.h"
#include "system/files.h"
#include "system/frametime.h"

#include "math/vector_math.h"
#include "math/transform.h"

#include "video/shader.h"
#include "video/texture.h"
#include "video/model_mdl.h"
#include "video/font_bitmap.h"
#include "video/video_mode.h"
#include "video/camera.h"
//#include "video/renderer.h"

#include "video/shader_uniform.h"
#include "app/app.h"

#include "system/log.cpp"
#include "system/files.cpp"
#include "system/frametime_sdl2.cpp"

#include "math/transform.cpp"

#include "video/shader.cpp"
#include "video/texture.cpp"
//#include "video/texture_dds.cpp"
//#include "video/model_mdl.cpp"
#include "video/font_bitmap.cpp"
#include "video/camera.cpp"
//#include "video/renderer.cpp"

#include "video/shader_uniform.cpp"
#include "app/app.cpp"

/* inits sdl and creates an opengl window */
static void initSDL(VideoMode *video) {
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) {
		LOGE("Failed to init SDL2: %s", SDL_GetError());
		exit(1);
	}

	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
	//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
	//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);

#ifdef EMSCRIPTEN
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
						SDL_GL_CONTEXT_PROFILE_ES);
#else
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
						SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
#endif

	int window_flags =
		  SDL_WINDOW_SHOWN
		| SDL_WINDOW_RESIZABLE
		| SDL_WINDOW_OPENGL
		//| SDL_WINDOW_ALLOW_HIGHDPI
		;

	sdl_window = SDL_CreateWindow(WINDOW_TITLE,
		SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
		video->width, video->height, window_flags);
	if (!sdl_window) {
		LOGE("Failed to create an OpenGL window: %s", SDL_GetError());
		exit(1);
	}

	sdl_gl_context = SDL_GL_CreateContext(sdl_window);
	if (!sdl_gl_context) {
		LOGE("Failed to create an OpenGL context: %s", SDL_GetError());
		exit(1);
	}

	int drawable_width, drawable_height;
	SDL_GL_GetDrawableSize(sdl_window, &drawable_width, &drawable_height);
	if (drawable_width != video->width) {
		LOGI("Created high DPI window. (%dx%d)", drawable_width, drawable_height);
		video->pixel_scale = (float)drawable_width / (float)video->width;
	} else {
		video->pixel_scale = 1.0f;
	}

	if (SDL_GL_SetSwapInterval(1) == -1) { // sync with monitor refresh rate
		LOGW("Could not enable VSync.");
	}

	#ifndef __APPLE__
	glewInit();
	#endif
}

void quitSDL() {
	SDL_DestroyWindow(sdl_window);
	SDL_GL_DeleteContext(sdl_gl_context);
	SDL_Quit();
}

void FrameTime::drawInfo() {
	char fps_text[64];
	sprintf(fps_text, "FPS: %d\nframe time: %.3f ms", frames_per_second, 1000.0*smoothed_frame_time);
	bitmapfont.drawText(fps_text, 8, 8);
}

App *app = nullptr;

bool windowIsFullscreen() {
	return !!(SDL_GetWindowFlags(sdl_window)&SDL_WINDOW_FULLSCREEN_DESKTOP);
}

void windowToggleFullscreen() {
	SDL_SetWindowFullscreen(sdl_window,
		windowIsFullscreen() ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
}

u64 mouse_timer = 0;

void mainLoop() {
	ImGuiIO& io = ImGui::GetIO();
	SDL_Event sdl_event;
	while (SDL_PollEvent(&sdl_event)) {
		ImGui_ImplSdlGL2_ProcessEvent(&sdl_event);
		switch (sdl_event.type) {
			case SDL_WINDOWEVENT:
				switch (sdl_event.window.event) {
		        	case SDL_WINDOWEVENT_SIZE_CHANGED: {
						app->video.width  = sdl_event.window.data1;
						app->video.height = sdl_event.window.data2;
						// update opengl viewport
						int drawable_width, drawable_height;
						SDL_GL_GetDrawableSize(sdl_window, &drawable_width, &drawable_height);
						glViewport(0, 0, drawable_width, drawable_height);
						break;
					}
				}
				break;
			case SDL_MOUSEMOTION:
				mouse_timer = 0;
				break;
			case SDL_QUIT:
				app->quit = true;
				break;
			case SDL_KEYDOWN: {
				if (!io.WantCaptureKeyboard) {
					if (sdl_event.key.keysym.sym == SDLK_SPACE) {
						app->toggleAnimation();
					}
				}

				// handle hotkeys
				bool ctrl_key_down = io.OSXBehaviors ? io.KeySuper : io.KeyCtrl;
				bool shift_key_down = io.KeyShift;
				if (ctrl_key_down) {
					switch (sdl_event.key.keysym.sym) {
						case SDLK_1: case SDLK_2: case SDLK_3:
							app->toggleWindow(sdl_event.key.keysym.sym-SDLK_1);
							break;
						case SDLK_f: // fullscreen
							windowToggleFullscreen();
							break;
						case SDLK_h: // hide gui
							if (!io.OSXBehaviors || shift_key_down) app->hide_gui = !app->hide_gui; // toggle imgui
							break;
						case SDLK_o: // open
							app->openShaderDialog();
							break;
						case SDLK_q: // quit
							app->quit = true;
							break;
						case SDLK_s: // save
							if (shift_key_down) app->saveShaderDialog();
							else app->saveShader();
							break;
						default: break;
					}
				}
				if (sdl_event.key.keysym.sym == SDLK_F11) {
					windowToggleFullscreen();
				}
				break;
			}
		}
	}

	// TODO: make use of mouse_timer
	// doesn't seam to work on OS X?
	SDL_ShowCursor(app->hide_gui ? SDL_DISABLE : SDL_ENABLE);

	// TODO: better keyboard handling
	// update input commands
	// TODO: move this to some function
	// this also depends on the game state
	// when do we want a movement command?
	const Uint8 *key_state = SDL_GetKeyboardState(NULL);
	app->movement_command.move = v3(
		- (key_state[SDL_SCANCODE_A] == SDL_PRESSED ? 1.0f : 0.0f)
		+ (key_state[SDL_SCANCODE_D] == SDL_PRESSED ? 1.0f : 0.0f),
		- (key_state[SDL_SCANCODE_S] == SDL_PRESSED ? 1.0f : 0.0f)
		+ (key_state[SDL_SCANCODE_W] == SDL_PRESSED ? 1.0f : 0.0f),
		- (key_state[SDL_SCANCODE_Q] == SDL_PRESSED ? 1.0f : 0.0f)
		+ (key_state[SDL_SCANCODE_E] == SDL_PRESSED ? 1.0f : 0.0f));
	app->movement_command.rotate = v2(
		- (key_state[SDL_SCANCODE_UP   ] == SDL_PRESSED ? 1.0f : 0.0f)
		+ (key_state[SDL_SCANCODE_DOWN ] == SDL_PRESSED ? 1.0f : 0.0f),
		- (key_state[SDL_SCANCODE_LEFT ] == SDL_PRESSED ? 1.0f : 0.0f)
		+ (key_state[SDL_SCANCODE_RIGHT] == SDL_PRESSED ? 1.0f : 0.0f));

	if (!app->hide_gui && io.WantCaptureKeyboard) { // null movement
		app->movement_command.move = v3(0.0f);
		app->movement_command.rotate = v2(0.0f);
	}

	ImGui_ImplSdlGL2_NewFrame();

	app->update((float)frametime.smoothed_frame_time);

	ImGui::Render();

	SDL_GL_SwapWindow(sdl_window);
	frametime.update();
}

int main(int argc, char *argv[]) {
	app = new App();
	app->video.width = 1024;
	app->video.height = 640;
	app->video.pixel_scale = 1.0f;

	// set preferences_filepath and read preferences
	char *pref_path = SDL_GetPrefPath(COMPANY_NAME, APPLICATION_NAME);

	size_t preferences_ini_str_len = strlen(pref_path)+strlen("preferences.ini")+1;
	app->preferences_filepath = new char[preferences_ini_str_len];
	strcpy(app->preferences_filepath, pref_path);
	strcat(app->preferences_filepath, "preferences.ini");
	size_t session_ini_str_len = strlen(pref_path)+strlen("session.ini")+1;
	app->session_filepath = new char[session_ini_str_len];
	strcpy(app->session_filepath, pref_path);
	strcat(app->session_filepath, "session.ini");
	size_t imgui_ini_str_len = strlen(pref_path)+strlen("imgui.ini")+1;
	ImGuiIO& io = ImGui::GetIO();
	char *imgui_ini_filepath = new char[imgui_ini_str_len];
	strcpy(imgui_ini_filepath, pref_path);
	strcat(imgui_ini_filepath, "imgui.ini");
	io.IniFilename = imgui_ini_filepath;

	SDL_free(pref_path);
	app->readPreferences();
	app->readSession();

	initSDL(&app->video);

	ImGui_ImplSdlGL2_Init(sdl_window);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	app->init();

	// init this last for sake of last_ticks
	frametime.init();

	do {
		Uint32 beginTicks = SDL_GetTicks();
		mainLoop();
		// hack for when vsync isn't working
		Uint32 elapsedTicks = SDL_GetTicks() - beginTicks;
		if (elapsedTicks < 16) {
			SDL_Delay(16 - elapsedTicks);
		}
	} while(!app->quit);

	app->beforeQuit();

	ImGui_ImplSdlGL2_Shutdown();
	quitSDL();

	return 0;
}
<|endoftext|>


<commit_before>/* local_banker.cc
   Michael Burkat, 9 February 2015
   Copyright (c) 2015 Datacratic Inc.  All rights reserved.

   Local banker implementation.
*/

#include <algorithm>
#include "local_banker.h"
#include "soa/service/http_header.h"
#include "soa/types/date.h"

using namespace std;
using namespace Datacratic;

namespace RTBKIT {

LocalBanker::LocalBanker(shared_ptr<ServiceProxies> services, GoAccountType type,
        const string & accountSuffix)
        : ServiceBase(accountSuffix + ".localBanker", services),
          type(type),
          accountSuffix(accountSuffix),
          accountSuffixNoDot(accountSuffix),
          accounts(),
          spendRate(MicroUSD(100000))
{
    replace(accountSuffixNoDot.begin(), accountSuffixNoDot.end(), '.', '_');
}

void
LocalBanker::init(const string & bankerUrl,
                  double timeout,
                  int numConnections,
                  bool tcpNoDelay)
{
    httpClient = std::make_shared<HttpClient>(bankerUrl, numConnections);
    httpClient->sendExpect100Continue(false);
    addSource("LocalBanker:HttpClient", httpClient);

    auto reauthorizePeriodic = [&] (uint64_t wakeups) {
        reauthorize();
    };
    auto spendUpdatePeriodic = [&] (uint64_t wakeups) {
        spendUpdate();
    };
    auto initializeAccountsPeriodic = [&] (uint64_t wakeups) {
        unordered_set<AccountKey> tempUninitialized;
        {
            std::lock_guard<std::mutex> guard(this->mutex);
            swap(uninitializedAccounts, tempUninitialized);
            this->recordCount(accounts.accounts.size(), "accounts");
        }
        for (auto &key : tempUninitialized) {
            addAccountImpl(key);
        }
    };

    if (type == ROUTER)
        addPeriodic("localBanker::reauthorize", 1.0, reauthorizePeriodic);

    if (type == POST_AUCTION)
        addPeriodic("localBanker::spendUpdate", 0.5, spendUpdatePeriodic);

    addPeriodic("uninitializedAccounts", 1.0, initializeAccountsPeriodic);
}

void
LocalBanker::setSpendRate(Amount newSpendRate)
{
    spendRate = newSpendRate;
}

void
LocalBanker::start()
{
    MessageLoop::start();
}

void
LocalBanker::shutdown()
{
    MessageLoop::shutdown();
}

void
LocalBanker::addAccount(const AccountKey &key)
{
    const AccountKey fullKey(key.toString() + ":" + accountSuffix);
    addAccountImpl(fullKey);
}

void
LocalBanker::addAccountImpl(const AccountKey &key)
{
    if (accounts.exists(key)) {
        std::lock_guard<std::mutex> guard(this->mutex);
        if (uninitializedAccounts.find(key) != uninitializedAccounts.end())
            uninitializedAccounts.erase(key);
        return;
    } else {
        std::lock_guard<std::mutex> guard(this->mutex);
        uninitializedAccounts.insert(key);
    }

    this->recordHit("addAccount.attempts");
    const Date sentTime = Date::now();

    auto onResponse = [&, key, sentTime] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        const Date recieveTime = Date::now();
        double latencyMs = recieveTime.secondsSince(sentTime) * 1000;
        this->recordLevel(latencyMs, "addAccountLatencyMs");

        if (status != 200) {
            cout << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl
                 << "url:    " << req.url_ << endl
                 << "cont_str: " << req.content_.str << endl;
            this->recordHit("addAccount.failure");
        } else {
            cout << body << endl;
            std::lock_guard<std::mutex> guard(this->mutex);
            accounts.addFromJsonString(body);
            if (uninitializedAccounts.find(key) != uninitializedAccounts.end())
                uninitializedAccounts.erase(key);
            this->recordHit("addAccount.success");
        }
    };
    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::objectValue);
    payload["accountName"] = key.toString();
    switch (type) {
        case ROUTER:
            payload["accountType"] = "Router";
            break;
        case POST_AUCTION:
            payload["accountType"] = "PostAuction";
            break;
    };
    cout << "calling add go banker account: " << key.toString() << endl;
    httpClient->post("/accounts", cbs, payload, {}, {}, 1);
}

void
LocalBanker::spendUpdate()
{
    const Date sentTime = Date::now();
    this->recordHit("spendUpdate.attempt");

    auto onResponse = [&, sentTime] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        const Date recieveTime = Date::now();
        double latencyMs = recieveTime.secondsSince(sentTime) * 1000;
        this->recordLevel(latencyMs, "spendUpdateLatencyMs");

        if (status != 200) {
            cout << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl;
            this->recordHit("spendUpdate.failure");
        } else {
            this->recordHit("spendUpdate.success");
            //cout << "status: " << status << endl
            //     << "body:   " << body << endl;
        }
    };
    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::arrayValue);
//    int i = 0;
    {
        std::lock_guard<std::mutex> guard(this->mutex);
        for (auto it : accounts.accounts) {
//         cout << "i: " << i++ << "\n"
//              << "name: " << it.first.toString() << "\n"
//              << "info: " << it.second.toJson() << endl;
            payload.append(it.second.toJson());
        }
    }
    httpClient->post("/spendupdate", cbs, payload, {}, {}, 0.5);
}

void
LocalBanker::reauthorize()
{
    const Date sentTime = Date::now();
    this->recordHit("reauthorize.attempt");

    auto onResponse = [&, sentTime] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        const Date recieveTime = Date::now();
        double latencyMs = recieveTime.secondsSince(sentTime) * 1000;
        this->recordLevel(latencyMs, "reauthorizeLatencyMs");

        if (status != 200) {
            cout << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl
                 << "url:    " << req.url_ << endl
                 << "cont_str: " << req.content_.str << endl;
            this->recordHit("reauthorize.failure");
        } else {
            Json::Value jsonAccounts = Json::parse(body);
            for ( auto jsonAccount : jsonAccounts ) {
                auto key = AccountKey(jsonAccount["name"].asString());
                int64_t newBalance = jsonAccount["balance"].asInt();
                //cout << "account: " << key.toString() << "\n"
                //     << "new bal: " << newBalance << endl;
                accounts.updateBalance(key, newBalance);
                int64_t rate = jsonAccount["rate"].asInt();
                if (rate != spendRate.value) {
                    setRate(key);
                }
            }
            this->recordHit("reauthorize.success");
        }
    };

    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::arrayValue);
//    int i = 0;
    {
        std::lock_guard<std::mutex> guard(this->mutex);
        for (auto it : accounts.accounts) {
//         cout << "i: " << i++ << "\n"
//              << "name: " << it.first.toString() << "\n"
//              << "info: " << it.second.toJson() << endl;
            payload.append(it.first.toString());
        }
    }
    httpClient->post("/reauthorize/1", cbs, payload, {}, {}, 1.0);
}

void
LocalBanker::setRate(const AccountKey &key)
{
    const Date sentTime = Date::now();
    this->recordHit("setRate.attempt");

    auto onResponse = [&, sentTime] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        const Date recieveTime = Date::now();
        double latencyMs = recieveTime.secondsSince(sentTime) * 1000;
        this->recordLevel(latencyMs, "setRateLatencyMs");

        if (status != 200) {
            cout << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl;
            this->recordHit("setRate.failure");
        } else {
            this->recordHit("setRate.success");
        }
    };
    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::objectValue);
    payload["USD/1M"] = spendRate.value;
    httpClient->post("/accounts/" + key.toString() + "/rate", cbs, payload, {}, {}, 1.0);
}

bool
LocalBanker::bid(const AccountKey &key, Amount bidPrice)
{
    bool canBid = accounts.bid(key.toString() + ":" + accountSuffix, bidPrice);

    if (canBid)
        this->recordHit("account." + key.toString() + ":" + accountSuffixNoDot + ".Bid");
    else
        this->recordHit("account." + key.toString() + ":" + accountSuffixNoDot + ".noBid");
    return canBid;
}

bool
LocalBanker::win(const AccountKey &key, Amount winPrice)
{
    bool winAccounted = accounts.win(key.toString() + ":" + accountSuffix, winPrice);
    if (winAccounted)
        this->recordHit("account." + key.toString() + ":" + accountSuffixNoDot + ".Win");
    else
        this->recordHit("account." + key.toString() + ":" + accountSuffixNoDot + ".noWin");
    return winAccounted;

}

} // namespace RTBKIT
<commit_msg>added cout<commit_after>/* local_banker.cc
   Michael Burkat, 9 February 2015
   Copyright (c) 2015 Datacratic Inc.  All rights reserved.

   Local banker implementation.
*/

#include <algorithm>
#include "local_banker.h"
#include "soa/service/http_header.h"
#include "soa/types/date.h"

using namespace std;
using namespace Datacratic;

namespace RTBKIT {

LocalBanker::LocalBanker(shared_ptr<ServiceProxies> services, GoAccountType type,
        const string & accountSuffix)
        : ServiceBase(accountSuffix + ".localBanker", services),
          type(type),
          accountSuffix(accountSuffix),
          accountSuffixNoDot(accountSuffix),
          accounts(),
          spendRate(MicroUSD(100000))
{
    replace(accountSuffixNoDot.begin(), accountSuffixNoDot.end(), '.', '_');
}

void
LocalBanker::init(const string & bankerUrl,
                  double timeout,
                  int numConnections,
                  bool tcpNoDelay)
{
    httpClient = std::make_shared<HttpClient>(bankerUrl, numConnections);
    httpClient->sendExpect100Continue(false);
    addSource("LocalBanker:HttpClient", httpClient);

    auto reauthorizePeriodic = [&] (uint64_t wakeups) {
        reauthorize();
    };
    auto spendUpdatePeriodic = [&] (uint64_t wakeups) {
        spendUpdate();
    };
    auto initializeAccountsPeriodic = [&] (uint64_t wakeups) {
        unordered_set<AccountKey> tempUninitialized;
        {
            std::lock_guard<std::mutex> guard(this->mutex);
            swap(uninitializedAccounts, tempUninitialized);
            this->recordCount(accounts.accounts.size(), "accounts");
        }
        for (auto &key : tempUninitialized) {
            addAccountImpl(key);
        }
    };

    if (type == ROUTER)
        addPeriodic("localBanker::reauthorize", 1.0, reauthorizePeriodic);

    if (type == POST_AUCTION)
        addPeriodic("localBanker::spendUpdate", 0.5, spendUpdatePeriodic);

    addPeriodic("uninitializedAccounts", 1.0, initializeAccountsPeriodic);
}

void
LocalBanker::setSpendRate(Amount newSpendRate)
{
    spendRate = newSpendRate;
}

void
LocalBanker::start()
{
    MessageLoop::start();
}

void
LocalBanker::shutdown()
{
    MessageLoop::shutdown();
}

void
LocalBanker::addAccount(const AccountKey &key)
{
    const AccountKey fullKey(key.toString() + ":" + accountSuffix);
    addAccountImpl(fullKey);
}

void
LocalBanker::addAccountImpl(const AccountKey &key)
{
    if (accounts.exists(key)) {
        std::lock_guard<std::mutex> guard(this->mutex);
        if (uninitializedAccounts.find(key) != uninitializedAccounts.end())
            uninitializedAccounts.erase(key);
        return;
    } else {
        std::lock_guard<std::mutex> guard(this->mutex);
        uninitializedAccounts.insert(key);
    }

    this->recordHit("addAccount.attempts");
    const Date sentTime = Date::now();

    auto onResponse = [&, key, sentTime] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        const Date recieveTime = Date::now();
        double latencyMs = recieveTime.secondsSince(sentTime) * 1000;
        this->recordLevel(latencyMs, "addAccountLatencyMs");

        if (status != 200) {
            cout << "addAccount::" << endl
                 << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl
                 << "url:    " << req.url_ << endl
                 << "cont_str: " << req.content_.str << endl;
            this->recordHit("addAccount.failure");
        } else {
            cout << body << endl;
            std::lock_guard<std::mutex> guard(this->mutex);
            accounts.addFromJsonString(body);
            if (uninitializedAccounts.find(key) != uninitializedAccounts.end())
                uninitializedAccounts.erase(key);
            this->recordHit("addAccount.success");
        }
    };
    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::objectValue);
    payload["accountName"] = key.toString();
    switch (type) {
        case ROUTER:
            payload["accountType"] = "Router";
            break;
        case POST_AUCTION:
            payload["accountType"] = "PostAuction";
            break;
    };
    cout << "calling add go banker account: " << key.toString() << endl;
    httpClient->post("/accounts", cbs, payload, {}, {}, 1);
}

void
LocalBanker::spendUpdate()
{
    const Date sentTime = Date::now();
    this->recordHit("spendUpdate.attempt");

    auto onResponse = [&, sentTime] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        const Date recieveTime = Date::now();
        double latencyMs = recieveTime.secondsSince(sentTime) * 1000;
        this->recordLevel(latencyMs, "spendUpdateLatencyMs");

        if (status != 200) {
            cout << "spendUpdate::" << endl
                 << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl;
            this->recordHit("spendUpdate.failure");
        } else {
            this->recordHit("spendUpdate.success");
            //cout << "status: " << status << endl
            //     << "body:   " << body << endl;
        }
    };
    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::arrayValue);
//    int i = 0;
    {
        std::lock_guard<std::mutex> guard(this->mutex);
        for (auto it : accounts.accounts) {
//         cout << "i: " << i++ << "\n"
//              << "name: " << it.first.toString() << "\n"
//              << "info: " << it.second.toJson() << endl;
            payload.append(it.second.toJson());
        }
    }
    httpClient->post("/spendupdate", cbs, payload, {}, {}, 0.5);
}

void
LocalBanker::reauthorize()
{
    const Date sentTime = Date::now();
    this->recordHit("reauthorize.attempt");

    auto onResponse = [&, sentTime] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        const Date recieveTime = Date::now();
        double latencyMs = recieveTime.secondsSince(sentTime) * 1000;
        this->recordLevel(latencyMs, "reauthorizeLatencyMs");

        if (status != 200) {
            cout << "reauthorize::" << endl
                 << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl
                 << "url:    " << req.url_ << endl
                 << "cont_str: " << req.content_.str << endl;
            this->recordHit("reauthorize.failure");
        } else {
            Json::Value jsonAccounts = Json::parse(body);
            for ( auto jsonAccount : jsonAccounts ) {
                auto key = AccountKey(jsonAccount["name"].asString());
                int64_t newBalance = jsonAccount["balance"].asInt();
                //cout << "account: " << key.toString() << "\n"
                //     << "new bal: " << newBalance << endl;
                accounts.updateBalance(key, newBalance);
                int64_t rate = jsonAccount["rate"].asInt();
                if (rate != spendRate.value) {
                    setRate(key);
                }
            }
            this->recordHit("reauthorize.success");
        }
    };

    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::arrayValue);
//    int i = 0;
    {
        std::lock_guard<std::mutex> guard(this->mutex);
        for (auto it : accounts.accounts) {
//         cout << "i: " << i++ << "\n"
//              << "name: " << it.first.toString() << "\n"
//              << "info: " << it.second.toJson() << endl;
            payload.append(it.first.toString());
        }
    }
    httpClient->post("/reauthorize/1", cbs, payload, {}, {}, 1.0);
}

void
LocalBanker::setRate(const AccountKey &key)
{
    const Date sentTime = Date::now();
    this->recordHit("setRate.attempt");

    auto onResponse = [&, sentTime] (const HttpRequest &req,
            HttpClientError error,
            int status,
            string && headers,
            string && body)
    {
        const Date recieveTime = Date::now();
        double latencyMs = recieveTime.secondsSince(sentTime) * 1000;
        this->recordLevel(latencyMs, "setRateLatencyMs");

        if (status != 200) {
            cout << "setRate::" << endl
                 << "status: " << status << endl
                 << "error:  " << error << endl
                 << "body:   " << body << endl;
            this->recordHit("setRate.failure");
        } else {
            this->recordHit("setRate.success");
        }
    };
    auto const &cbs = make_shared<HttpClientSimpleCallbacks>(onResponse);
    Json::Value payload(Json::objectValue);
    payload["USD/1M"] = spendRate.value;
    httpClient->post("/accounts/" + key.toString() + "/rate", cbs, payload, {}, {}, 1.0);
}

bool
LocalBanker::bid(const AccountKey &key, Amount bidPrice)
{
    bool canBid = accounts.bid(key.toString() + ":" + accountSuffix, bidPrice);

    if (canBid)
        this->recordHit("account." + key.toString() + ":" + accountSuffixNoDot + ".Bid");
    else
        this->recordHit("account." + key.toString() + ":" + accountSuffixNoDot + ".noBid");
    return canBid;
}

bool
LocalBanker::win(const AccountKey &key, Amount winPrice)
{
    bool winAccounted = accounts.win(key.toString() + ":" + accountSuffix, winPrice);
    if (winAccounted)
        this->recordHit("account." + key.toString() + ":" + accountSuffixNoDot + ".Win");
    else
        this->recordHit("account." + key.toString() + ":" + accountSuffixNoDot + ".noWin");
    return winAccounted;

}

} // namespace RTBKIT
<|endoftext|>


<commit_before>// Copyright (C) 2010 - 2012 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2008 - 2009 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2005 - 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include "CQOptimizationWidget.h"

#include <QtCore/QVariant>

#include "UI/CQTaskBtnWidget.h"
#include "UI/CQTaskHeaderWidget.h"
#include "CQTaskMethodWidget.h"
#include "CQTaskMethodWidget.h"
#include "UI/CQFittingItemWidget.h"
#include "UI/CProgressBar.h"
#include "UI/CCopasiSelectionDialog.h"
#include "UI/qtUtilities.h"
#include "UI/CQExpressionWidget.h"

#include "report/CKeyFactory.h"
#include "optimization/COptTask.h"
#include "optimization/COptItem.h"
#include "optimization/COptMethod.h"
#include "optimization/COptProblem.h"
#include "utilities/CCopasiException.h"
#include "report/CCopasiRootContainer.h"

/*
 *  Constructs a CQOptimizationWidget which is a child of 'parent', with the
 *  name 'name'.'
 */
CQOptimizationWidget::CQOptimizationWidget(QWidget* parent, const char* name)
  : TaskWidget(parent, name)
{
  setupUi(this);

  init();
}

/*
 *  Destroys the object and frees any allocated resources
 */
CQOptimizationWidget::~CQOptimizationWidget()
{
  destroy();
  // no need to delete child widgets, Qt does it all for us
}

bool CQOptimizationWidget::saveTask()
{
  COptTask * pTask =
    dynamic_cast< COptTask * >(mpTask);

  if (!pTask) return false;

  saveCommon();
  saveMethod();

  COptProblem * pProblem =
    dynamic_cast<COptProblem *>(mpTask->getProblem());

  if (!pProblem) return false;

  // expression
  if (pProblem->getObjectiveFunction() != mpExpressionEMW->mpExpressionWidget->getExpression())
    {
      if (!pProblem->setObjectiveFunction(mpExpressionEMW->mpExpressionWidget->getExpression()))
        {
          CCopasiMessage(CCopasiMessage::ERROR, MCOptimization + 5);
          return false;
        }

      mChanged = true;
    }

  if (mpBoxSubtask->currentText() != FROM_UTF8(CCopasiTask::TypeName[pProblem->getSubtaskType()]))
    {
      mChanged = true;
      pProblem->setSubtaskType((CCopasiTask::Type) mSubtaskMap[TO_UTF8(mpBoxSubtask->currentText())]);
    }

  if (mpBtnMaximize->isChecked() != pProblem->maximize())
    {
      mChanged = true;
      pProblem->setMaximize(mpBtnMaximize->isChecked());
    }

  if (mpCheckRandomize->isChecked() != pProblem->getRandomizeStartValues())
    {
      mChanged = true;
      pProblem->setRandomizeStartValues(mpCheckRandomize->isChecked());
    }

  if (mpCheckStatistics->isChecked() != pProblem->getCalculateStatistics())
    {
      mChanged = true;
      pProblem->setCalculateStatistics(mpCheckStatistics->isChecked());
    }

  mChanged |= mpParameters->save(NULL, NULL);
  mChanged |= mpConstraints->save(NULL, NULL);

  if (mChanged)
    {
      assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
      (*CCopasiRootContainer::getDatamodelList())[0]->changed();
    }

  mChanged = false;

  return true;
}

bool CQOptimizationWidget::loadTask()
{
  COptTask * pTask =
    dynamic_cast< COptTask * >(mpTask);

  if (!pTask) return false;

  loadCommon();
  loadMethod();

  COptProblem * pProblem =
    dynamic_cast<COptProblem *>(mpTask->getProblem());

  if (!pProblem) return false;

  // expression
  mpExpressionEMW->mpExpressionWidget->setExpression(pProblem->getObjectiveFunction());
  mpExpressionEMW->updateWidget();

  mpBtnMaximize->setChecked(pProblem->maximize());
  mpBtnMinimize->setChecked(!pProblem->maximize());

  mpCheckRandomize->setChecked(pProblem->getRandomizeStartValues());
  mpCheckStatistics->setChecked(pProblem->getCalculateStatistics());

  mpBoxSubtask->setCurrentIndex(mpBoxSubtask->findText(FROM_UTF8(CCopasiTask::TypeName[pProblem->getSubtaskType()])));

  mpParameters->load(mpDataModel, pProblem->getGroup("OptimizationItemList"), NULL, NULL);

  mpConstraints->load(mpDataModel, pProblem->getGroup("OptimizationConstraintList"), NULL, NULL);

  mChanged = false;

  return true;
}

bool CQOptimizationWidget::runTask()
{
  // --- expression

  mpExpressionEMW->updateWidget();

  // ----

  COptTask * pTask =
    dynamic_cast< COptTask * >(CCopasiRootContainer::getKeyFactory()->get(mKey));

  if (!pTask) return false;

  if (!commonBeforeRunTask()) return false;

  return commonRunTask();
}

void CQOptimizationWidget::slotPageChange(QWidget * currentPage)
{
  if (mpTabWidget->tabText(mpTabWidget->indexOf(currentPage)).contains("Parameters", Qt::CaseSensitive))
    mpCurrentList = mpParameters;
  else
    mpCurrentList = mpConstraints;
}

CCopasiMethod * CQOptimizationWidget::createMethod(const CCopasiMethod::SubType & type)
{return COptMethod::createMethod(type);}

void CQOptimizationWidget::slotParameterNumberChanged(int number)
{
  QString TabLabel = "Parameters (" + QString::number(number) + ")";
  mpTabWidget->setTabText(mpTabWidget->indexOf(mpParameters), TabLabel);
}

void CQOptimizationWidget::slotConstraintNumberChanged(int number)
{
  QString TabLabel = "Constraints (" + QString::number(number) + ")";
  mpTabWidget->setTabText(mpTabWidget->indexOf(mpConstraints), TabLabel);
}

void CQOptimizationWidget::init()
{
  std::string taskName = "Optimization";

  mpHeaderWidget->setTaskName(taskName);

  verticalLayout->insertWidget(0, mpHeaderWidget);
  // verticalLayout->insertSpacing(1, 14);      // space between header and body

  mpMethodWidget->setValidMethods(COptTask::ValidMethods);
  mpMethodWidget->showMethodParameters(true);
  verticalLayout->addWidget(mpMethodWidget);

  verticalLayout->addWidget(mpBtnWidget);

  mpExpressionEMW->mpExpressionWidget->setExpressionType(CQExpressionWidget::ObjectiveFunctions);

  //mpBtnMaximize->setMinimumWidth(mpLblExpression->width());

  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::steadyState]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::steadyState]] = CCopasiTask::steadyState;
  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::timeCourse]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::timeCourse]] = CCopasiTask::timeCourse;
  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::mca]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::mca]] = CCopasiTask::mca;
  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::lna]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::lna]] = CCopasiTask::lna;
  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::lyap]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::lyap]] = CCopasiTask::lyap;
  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::sens]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::sens]] = CCopasiTask::sens;

  mpParameters->setItemType(CQFittingItemWidget::OPT_ITEM);

  connect(mpParameters, SIGNAL(numberChanged(int)), this, SLOT(slotParameterNumberChanged(int)));

  mpConstraints->setItemType(CQFittingItemWidget::OPT_CONSTRAINT);

  connect(mpConstraints, SIGNAL(numberChanged(int)), this, SLOT(slotConstraintNumberChanged(int)));

  mpCurrentList = mpParameters;
}

void CQOptimizationWidget::destroy()
{}

void CQOptimizationWidget::slotExpressionValid(bool valid)
{
  mpBtnWidget->mpBtnRun->setEnabled(valid);
}

/*!
    The slot to activate the editor page of type CQExpressionWidget
    for being able to type a new mathematical expression or edit the existing one
 */
void CQOptimizationWidget::slotEditExpression()
{}

void CQOptimizationWidget::slotSubtaskChanged(const QString & /* subtask */)
{}
<commit_msg>For experimenting, enable optimization of fitting (only in debug builds)<commit_after>// Copyright (C) 2010 - 2012 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2008 - 2009 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2005 - 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include "CQOptimizationWidget.h"

#include <QtCore/QVariant>

#include "UI/CQTaskBtnWidget.h"
#include "UI/CQTaskHeaderWidget.h"
#include "CQTaskMethodWidget.h"
#include "CQTaskMethodWidget.h"
#include "UI/CQFittingItemWidget.h"
#include "UI/CProgressBar.h"
#include "UI/CCopasiSelectionDialog.h"
#include "UI/qtUtilities.h"
#include "UI/CQExpressionWidget.h"

#include "report/CKeyFactory.h"
#include "optimization/COptTask.h"
#include "optimization/COptItem.h"
#include "optimization/COptMethod.h"
#include "optimization/COptProblem.h"
#include "utilities/CCopasiException.h"
#include "report/CCopasiRootContainer.h"

/*
 *  Constructs a CQOptimizationWidget which is a child of 'parent', with the
 *  name 'name'.'
 */
CQOptimizationWidget::CQOptimizationWidget(QWidget* parent, const char* name)
  : TaskWidget(parent, name)
{
  setupUi(this);

  init();
}

/*
 *  Destroys the object and frees any allocated resources
 */
CQOptimizationWidget::~CQOptimizationWidget()
{
  destroy();
  // no need to delete child widgets, Qt does it all for us
}

bool CQOptimizationWidget::saveTask()
{
  COptTask * pTask =
    dynamic_cast< COptTask * >(mpTask);

  if (!pTask) return false;

  saveCommon();
  saveMethod();

  COptProblem * pProblem =
    dynamic_cast<COptProblem *>(mpTask->getProblem());

  if (!pProblem) return false;

  // expression
  if (pProblem->getObjectiveFunction() != mpExpressionEMW->mpExpressionWidget->getExpression())
    {
      if (!pProblem->setObjectiveFunction(mpExpressionEMW->mpExpressionWidget->getExpression()))
        {
          CCopasiMessage(CCopasiMessage::ERROR, MCOptimization + 5);
          return false;
        }

      mChanged = true;
    }

  if (mpBoxSubtask->currentText() != FROM_UTF8(CCopasiTask::TypeName[pProblem->getSubtaskType()]))
    {
      mChanged = true;
      pProblem->setSubtaskType((CCopasiTask::Type) mSubtaskMap[TO_UTF8(mpBoxSubtask->currentText())]);
    }

  if (mpBtnMaximize->isChecked() != pProblem->maximize())
    {
      mChanged = true;
      pProblem->setMaximize(mpBtnMaximize->isChecked());
    }

  if (mpCheckRandomize->isChecked() != pProblem->getRandomizeStartValues())
    {
      mChanged = true;
      pProblem->setRandomizeStartValues(mpCheckRandomize->isChecked());
    }

  if (mpCheckStatistics->isChecked() != pProblem->getCalculateStatistics())
    {
      mChanged = true;
      pProblem->setCalculateStatistics(mpCheckStatistics->isChecked());
    }

  mChanged |= mpParameters->save(NULL, NULL);
  mChanged |= mpConstraints->save(NULL, NULL);

  if (mChanged)
    {
      assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
      (*CCopasiRootContainer::getDatamodelList())[0]->changed();
    }

  mChanged = false;

  return true;
}

bool CQOptimizationWidget::loadTask()
{
  COptTask * pTask =
    dynamic_cast< COptTask * >(mpTask);

  if (!pTask) return false;

  loadCommon();
  loadMethod();

  COptProblem * pProblem =
    dynamic_cast<COptProblem *>(mpTask->getProblem());

  if (!pProblem) return false;

  // expression
  mpExpressionEMW->mpExpressionWidget->setExpression(pProblem->getObjectiveFunction());
  mpExpressionEMW->updateWidget();

  mpBtnMaximize->setChecked(pProblem->maximize());
  mpBtnMinimize->setChecked(!pProblem->maximize());

  mpCheckRandomize->setChecked(pProblem->getRandomizeStartValues());
  mpCheckStatistics->setChecked(pProblem->getCalculateStatistics());

  mpBoxSubtask->setCurrentIndex(mpBoxSubtask->findText(FROM_UTF8(CCopasiTask::TypeName[pProblem->getSubtaskType()])));

  mpParameters->load(mpDataModel, pProblem->getGroup("OptimizationItemList"), NULL, NULL);

  mpConstraints->load(mpDataModel, pProblem->getGroup("OptimizationConstraintList"), NULL, NULL);

  mChanged = false;

  return true;
}

bool CQOptimizationWidget::runTask()
{
  // --- expression

  mpExpressionEMW->updateWidget();

  // ----

  COptTask * pTask =
    dynamic_cast< COptTask * >(CCopasiRootContainer::getKeyFactory()->get(mKey));

  if (!pTask) return false;

  if (!commonBeforeRunTask()) return false;

  return commonRunTask();
}

void CQOptimizationWidget::slotPageChange(QWidget * currentPage)
{
  if (mpTabWidget->tabText(mpTabWidget->indexOf(currentPage)).contains("Parameters", Qt::CaseSensitive))
    mpCurrentList = mpParameters;
  else
    mpCurrentList = mpConstraints;
}

CCopasiMethod * CQOptimizationWidget::createMethod(const CCopasiMethod::SubType & type)
{return COptMethod::createMethod(type);}

void CQOptimizationWidget::slotParameterNumberChanged(int number)
{
  QString TabLabel = "Parameters (" + QString::number(number) + ")";
  mpTabWidget->setTabText(mpTabWidget->indexOf(mpParameters), TabLabel);
}

void CQOptimizationWidget::slotConstraintNumberChanged(int number)
{
  QString TabLabel = "Constraints (" + QString::number(number) + ")";
  mpTabWidget->setTabText(mpTabWidget->indexOf(mpConstraints), TabLabel);
}

void CQOptimizationWidget::init()
{
  std::string taskName = "Optimization";

  mpHeaderWidget->setTaskName(taskName);

  verticalLayout->insertWidget(0, mpHeaderWidget);
  // verticalLayout->insertSpacing(1, 14);      // space between header and body

  mpMethodWidget->setValidMethods(COptTask::ValidMethods);
  mpMethodWidget->showMethodParameters(true);
  verticalLayout->addWidget(mpMethodWidget);

  verticalLayout->addWidget(mpBtnWidget);

  mpExpressionEMW->mpExpressionWidget->setExpressionType(CQExpressionWidget::ObjectiveFunctions);

  //mpBtnMaximize->setMinimumWidth(mpLblExpression->width());

  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::steadyState]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::steadyState]] = CCopasiTask::steadyState;
  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::timeCourse]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::timeCourse]] = CCopasiTask::timeCourse;
  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::mca]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::mca]] = CCopasiTask::mca;
  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::lna]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::lna]] = CCopasiTask::lna;
  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::lyap]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::lyap]] = CCopasiTask::lyap;
  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::sens]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::sens]] = CCopasiTask::sens;
#ifdef COPASI_DEBUG
  mpBoxSubtask->insertItem(mpBoxSubtask->count(), FROM_UTF8(CCopasiTask::TypeName[CCopasiTask::parameterFitting]));
  mSubtaskMap[CCopasiTask::TypeName[CCopasiTask::parameterFitting]] = CCopasiTask::parameterFitting;
#endif
  mpParameters->setItemType(CQFittingItemWidget::OPT_ITEM);

  connect(mpParameters, SIGNAL(numberChanged(int)), this, SLOT(slotParameterNumberChanged(int)));

  mpConstraints->setItemType(CQFittingItemWidget::OPT_CONSTRAINT);

  connect(mpConstraints, SIGNAL(numberChanged(int)), this, SLOT(slotConstraintNumberChanged(int)));

  mpCurrentList = mpParameters;
}

void CQOptimizationWidget::destroy()
{}

void CQOptimizationWidget::slotExpressionValid(bool valid)
{
  mpBtnWidget->mpBtnRun->setEnabled(valid);
}

/*!
    The slot to activate the editor page of type CQExpressionWidget
    for being able to type a new mathematical expression or edit the existing one
 */
void CQOptimizationWidget::slotEditExpression()
{}

void CQOptimizationWidget::slotSubtaskChanged(const QString & /* subtask */)
{}
<|endoftext|>


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

#include "providerwrapper.hxx"

#ifndef CONFIGMGR_BOOTSTRAP_HXX_
#include "bootstrap.hxx"
#endif

#ifndef CONFIGMGR_BOOTSTRAPCONTEXT_HXX_
#include "bootstrapcontext.hxx"
#endif

#ifndef _COM_SUN_STAR_LANG_NULLPOINTEREXCEPTION_HPP_
#include <com/sun/star/lang/NullPointerException.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
#include <com/sun/star/lang/DisposedException.hpp>
#endif

#include <algorithm>

namespace configmgr
{
    //==========================================================================
    namespace uno = com::sun::star::uno;
    namespace lang = com::sun::star::lang;
    using rtl::OUString;
    //==========================================================================
    //= ProviderWrapper
    //==========================================================================

    uno::Reference< uno::XInterface > ProviderWrapper::create( uno::Reference< uno::XInterface > xDelegate, NamedValues const & aPresets)
    {
        Provider xProvDelegate(xDelegate, uno::UNO_QUERY);
        if (!xProvDelegate.is())
        {
            OUString sMsg(RTL_CONSTASCII_USTRINGPARAM("ProviderWrapper: Cannot wrap a NULL provider"));
            throw lang::NullPointerException(sMsg,NULL);
        }
        //Strip prefixes
        NamedValues aStrippedPresets = aPresets;

        for (sal_Int32 i = 0; i < aPresets.getLength(); ++i)
        {
            if(aPresets[i].Name.matchAsciiL(RTL_CONSTASCII_STRINGPARAM(CONTEXT_ITEM_PREFIX_ )))
            {
                aStrippedPresets[i].Name = aPresets[i].Name.copy(RTL_CONSTASCII_LENGTH(CONTEXT_ITEM_PREFIX_ ));
            }
        }

        Provider xResult( new ProviderWrapper(xProvDelegate,aStrippedPresets) );

        typedef uno::Reference< lang::XComponent > Comp;
        DisposingForwarder::forward( Comp::query(xProvDelegate),Comp::query(xResult) );
        return xResult;
    }

    ProviderWrapper::ProviderWrapper(Provider const & xDelegate, NamedValues const & aPresets)
    : ProviderWrapper_Base( PWMutexHolder::mutex )
    , m_xDelegate(xDelegate)
    , m_aDefaults(aPresets.getLength())
    {
        OSL_ASSERT(m_xDelegate.is());

        for (sal_Int32 i = 0; i<aPresets.getLength(); ++i)
        {
            m_aDefaults[i] <<= aPresets[i];
        }
    }

    ProviderWrapper::~ProviderWrapper() {}

    void SAL_CALL ProviderWrapper::disposing()
    {
        osl::MutexGuard lock(mutex);
        m_xDelegate.clear();
    }

    ProviderWrapper::Provider ProviderWrapper::getDelegate()
    {
        osl::MutexGuard lock(mutex);
        if (!m_xDelegate.is())
        {
            OUString sMsg(RTL_CONSTASCII_USTRINGPARAM("ProviderWrapper: Delegate Provider has been disposed"));
            throw lang::DisposedException(sMsg,*this);
        }
        return m_xDelegate;
    }

    uno::Reference<lang::XServiceInfo> ProviderWrapper::getDelegateInfo()
    {
        uno::Reference<lang::XServiceInfo> xDelegate( this->getDelegate(), uno::UNO_QUERY );
        if (!xDelegate.is())
        {
            OUString sMsg(RTL_CONSTASCII_USTRINGPARAM("ProviderWrapper: Delegate Provider has no service info"));
            throw uno::RuntimeException(sMsg,*this);
        }
        return xDelegate;
    }

    /// XMultiServiceFactory
    static inline uno::Any const * begin(ProviderWrapper::Arguments const & aArgs)
    { return aArgs.getConstArray(); }
    static inline uno::Any const * end(ProviderWrapper::Arguments const & aArgs)
    { return aArgs.getConstArray() + aArgs.getLength(); }
    static inline uno::Any * begin(ProviderWrapper::Arguments & aArgs)
    { return aArgs.getArray(); }
    static inline uno::Any * end(ProviderWrapper::Arguments & aArgs)
    { return aArgs.getArray() + aArgs.getLength(); }

    ProviderWrapper::Arguments ProviderWrapper::patchArguments(Arguments const & aArgs) const
    {
        // rely on evaluation order front to back
        if (m_aDefaults.getLength() == 0) return aArgs;

        Arguments aResult(m_aDefaults.getLength() + aArgs.getLength());

        uno::Any * pNext = std::copy(begin(m_aDefaults),end(m_aDefaults),begin(aResult));
        pNext = std::copy(begin(aArgs),end(aArgs),pNext);

        OSL_ASSERT(end(aResult) == pNext);

        return aResult;
    }

    uno::Reference< uno::XInterface > SAL_CALL
        ProviderWrapper::createInstance( const OUString& aServiceSpecifier )
            throw(uno::Exception, uno::RuntimeException)
    {
        return getDelegate()->createInstanceWithArguments(aServiceSpecifier,m_aDefaults);
    }

    uno::Reference< uno::XInterface > SAL_CALL
        ProviderWrapper::createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, const uno::Sequence< uno::Any >& Arguments )
            throw(uno::Exception, uno::RuntimeException)
    {
        return getDelegate()->createInstanceWithArguments(ServiceSpecifier,patchArguments(Arguments));
    }

    uno::Sequence< OUString > SAL_CALL
        ProviderWrapper::getAvailableServiceNames(  )
            throw(uno::RuntimeException)
    {
        return getDelegate()->getAvailableServiceNames(  );
    }

    /// XServiceInfo
    OUString SAL_CALL
        ProviderWrapper::getImplementationName(  )
            throw(uno::RuntimeException)
    {
        return OUString::createFromAscii("com.sun.star.comp.configuration.ConfigurationProviderWrapper");
    }

    sal_Bool SAL_CALL
        ProviderWrapper::supportsService( const ::rtl::OUString& ServiceName )
            throw(uno::RuntimeException)
    {
        return getDelegateInfo()->supportsService( ServiceName );
    }

    uno::Sequence< OUString > SAL_CALL
        ProviderWrapper::getSupportedServiceNames(  )
            throw(uno::RuntimeException)
    {
        return getDelegateInfo()->getSupportedServiceNames(  );
    }

} // namespace configmgr

<commit_msg>INTEGRATION: CWS ooo19126 (1.3.190); FILE MERGED 2005/09/05 17:04:58 rt 1.3.190.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: providerwrapper.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 04:11:52 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "providerwrapper.hxx"

#ifndef CONFIGMGR_BOOTSTRAP_HXX_
#include "bootstrap.hxx"
#endif

#ifndef CONFIGMGR_BOOTSTRAPCONTEXT_HXX_
#include "bootstrapcontext.hxx"
#endif

#ifndef _COM_SUN_STAR_LANG_NULLPOINTEREXCEPTION_HPP_
#include <com/sun/star/lang/NullPointerException.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
#include <com/sun/star/lang/DisposedException.hpp>
#endif

#include <algorithm>

namespace configmgr
{
    //==========================================================================
    namespace uno = com::sun::star::uno;
    namespace lang = com::sun::star::lang;
    using rtl::OUString;
    //==========================================================================
    //= ProviderWrapper
    //==========================================================================

    uno::Reference< uno::XInterface > ProviderWrapper::create( uno::Reference< uno::XInterface > xDelegate, NamedValues const & aPresets)
    {
        Provider xProvDelegate(xDelegate, uno::UNO_QUERY);
        if (!xProvDelegate.is())
        {
            OUString sMsg(RTL_CONSTASCII_USTRINGPARAM("ProviderWrapper: Cannot wrap a NULL provider"));
            throw lang::NullPointerException(sMsg,NULL);
        }
        //Strip prefixes
        NamedValues aStrippedPresets = aPresets;

        for (sal_Int32 i = 0; i < aPresets.getLength(); ++i)
        {
            if(aPresets[i].Name.matchAsciiL(RTL_CONSTASCII_STRINGPARAM(CONTEXT_ITEM_PREFIX_ )))
            {
                aStrippedPresets[i].Name = aPresets[i].Name.copy(RTL_CONSTASCII_LENGTH(CONTEXT_ITEM_PREFIX_ ));
            }
        }

        Provider xResult( new ProviderWrapper(xProvDelegate,aStrippedPresets) );

        typedef uno::Reference< lang::XComponent > Comp;
        DisposingForwarder::forward( Comp::query(xProvDelegate),Comp::query(xResult) );
        return xResult;
    }

    ProviderWrapper::ProviderWrapper(Provider const & xDelegate, NamedValues const & aPresets)
    : ProviderWrapper_Base( PWMutexHolder::mutex )
    , m_xDelegate(xDelegate)
    , m_aDefaults(aPresets.getLength())
    {
        OSL_ASSERT(m_xDelegate.is());

        for (sal_Int32 i = 0; i<aPresets.getLength(); ++i)
        {
            m_aDefaults[i] <<= aPresets[i];
        }
    }

    ProviderWrapper::~ProviderWrapper() {}

    void SAL_CALL ProviderWrapper::disposing()
    {
        osl::MutexGuard lock(mutex);
        m_xDelegate.clear();
    }

    ProviderWrapper::Provider ProviderWrapper::getDelegate()
    {
        osl::MutexGuard lock(mutex);
        if (!m_xDelegate.is())
        {
            OUString sMsg(RTL_CONSTASCII_USTRINGPARAM("ProviderWrapper: Delegate Provider has been disposed"));
            throw lang::DisposedException(sMsg,*this);
        }
        return m_xDelegate;
    }

    uno::Reference<lang::XServiceInfo> ProviderWrapper::getDelegateInfo()
    {
        uno::Reference<lang::XServiceInfo> xDelegate( this->getDelegate(), uno::UNO_QUERY );
        if (!xDelegate.is())
        {
            OUString sMsg(RTL_CONSTASCII_USTRINGPARAM("ProviderWrapper: Delegate Provider has no service info"));
            throw uno::RuntimeException(sMsg,*this);
        }
        return xDelegate;
    }

    /// XMultiServiceFactory
    static inline uno::Any const * begin(ProviderWrapper::Arguments const & aArgs)
    { return aArgs.getConstArray(); }
    static inline uno::Any const * end(ProviderWrapper::Arguments const & aArgs)
    { return aArgs.getConstArray() + aArgs.getLength(); }
    static inline uno::Any * begin(ProviderWrapper::Arguments & aArgs)
    { return aArgs.getArray(); }
    static inline uno::Any * end(ProviderWrapper::Arguments & aArgs)
    { return aArgs.getArray() + aArgs.getLength(); }

    ProviderWrapper::Arguments ProviderWrapper::patchArguments(Arguments const & aArgs) const
    {
        // rely on evaluation order front to back
        if (m_aDefaults.getLength() == 0) return aArgs;

        Arguments aResult(m_aDefaults.getLength() + aArgs.getLength());

        uno::Any * pNext = std::copy(begin(m_aDefaults),end(m_aDefaults),begin(aResult));
        pNext = std::copy(begin(aArgs),end(aArgs),pNext);

        OSL_ASSERT(end(aResult) == pNext);

        return aResult;
    }

    uno::Reference< uno::XInterface > SAL_CALL
        ProviderWrapper::createInstance( const OUString& aServiceSpecifier )
            throw(uno::Exception, uno::RuntimeException)
    {
        return getDelegate()->createInstanceWithArguments(aServiceSpecifier,m_aDefaults);
    }

    uno::Reference< uno::XInterface > SAL_CALL
        ProviderWrapper::createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, const uno::Sequence< uno::Any >& Arguments )
            throw(uno::Exception, uno::RuntimeException)
    {
        return getDelegate()->createInstanceWithArguments(ServiceSpecifier,patchArguments(Arguments));
    }

    uno::Sequence< OUString > SAL_CALL
        ProviderWrapper::getAvailableServiceNames(  )
            throw(uno::RuntimeException)
    {
        return getDelegate()->getAvailableServiceNames(  );
    }

    /// XServiceInfo
    OUString SAL_CALL
        ProviderWrapper::getImplementationName(  )
            throw(uno::RuntimeException)
    {
        return OUString::createFromAscii("com.sun.star.comp.configuration.ConfigurationProviderWrapper");
    }

    sal_Bool SAL_CALL
        ProviderWrapper::supportsService( const ::rtl::OUString& ServiceName )
            throw(uno::RuntimeException)
    {
        return getDelegateInfo()->supportsService( ServiceName );
    }

    uno::Sequence< OUString > SAL_CALL
        ProviderWrapper::getSupportedServiceNames(  )
            throw(uno::RuntimeException)
    {
        return getDelegateInfo()->getSupportedServiceNames(  );
    }

} // namespace configmgr

<|endoftext|>