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

/**
 * @file   gnuwrapper.cpp
 * @brief  Replaces malloc family on GNU/Linux with custom versions.
 * @author Emery Berger <http://www.cs.umass.edu/~emery>
 * @note   Copyright (C) 2010 by Emery Berger, University of Massachusetts Amherst.
 */

#ifndef __GNUC__
#error "This file requires the GNU compiler."
#endif

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <new>

#include "heaplayers.h"

/*
  To use this library,
  you only need to define the following allocation functions:

  - xxmalloc
  - xxfree
  - xxmalloc_usable_size
  - xxmalloc_lock
  - xxmalloc_unlock

  See the extern "C" block below for function prototypes and more
  details. YOU SHOULD NOT NEED TO MODIFY ANY OF THE CODE HERE TO
  SUPPORT ANY ALLOCATOR.

  LIMITATIONS:

  - This wrapper assumes that the underlying allocator will do "the
    right thing" when xxfree() is called with a pointer internal to an
    allocated object. Header-based allocators, for example, need not
    apply.

*/

static bool initialized = false;

extern "C" {

  void * xxmalloc (size_t);
  void   xxfree (void *);
  size_t xxmalloc_usable_size (void *);
  void   xxmalloc_lock (void);
  void   xxmalloc_unlock (void);

  static void my_init_hook (void);

  // New hooks for allocation functions.
  static void * my_malloc_hook (size_t, const void *);
  static void   my_free_hook (void *, const void *);
  static void * my_realloc_hook (void *, size_t, const void *);
  static void * my_memalign_hook (size_t, size_t, const void *);

  // Store the old hooks just in case.
  static void * (*old_malloc_hook) (size_t, const void *);
  static void   (*old_free_hook) (void *, const void *);
  static void * (*old_realloc_hook)(void *ptr, size_t size, const void *caller);
  static void * (*old_memalign_hook)(size_t alignment, size_t size, const void *caller);

// From GNU libc 2.14 this macro is defined, to declare
// hook variables as volatile. Define it as empty for
// older glibc versions
#ifndef __MALLOC_HOOK_VOLATILE
 #define __MALLOC_HOOK_VOLATILE
#endif

  void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) = my_init_hook;

  static void my_init_hook (void) {
    if (!initialized) {
      // Store the old hooks.
      old_malloc_hook = __malloc_hook;
      old_free_hook = __free_hook;
      old_realloc_hook = __realloc_hook;
      old_memalign_hook = __memalign_hook;

      // Point the hooks to the replacement functions.
      __malloc_hook = my_malloc_hook;
      __free_hook = my_free_hook;
      __realloc_hook = my_realloc_hook;
      __memalign_hook = my_memalign_hook;

      // Set up everything so that fork behaves properly.
      pthread_atfork(xxmalloc_lock, xxmalloc_unlock, xxmalloc_unlock);

      initialized = true;

    }

  }

  static void * my_malloc_hook (size_t size, const void *) {
    return xxmalloc(size);
  }

  static void my_free_hook (void * ptr, const void *) {
    xxfree(ptr);
  }

  static void * my_realloc_hook (void * ptr, size_t sz, const void *) {
    // NULL ptr = malloc.
    if (ptr == NULL) {
      return xxmalloc(sz);
    }

    if (sz == 0) {
      xxfree (ptr);
#if defined(__APPLE__)
      // 0 size = free. We return a small object.  This behavior is
      // apparently required under Mac OS X and optional under POSIX.
      return xxmalloc(1);
#else
      // For POSIX, don't return anything.
      return NULL;
#endif
    }

    size_t objSize = xxmalloc_usable_size(ptr);

#if 0
    // Custom logic here to ensure we only do a logarithmic number of
    // reallocations (with a constant space overhead).

    // Don't change size if the object is shrinking by less than half.
    if ((objSize / 2 < sz) && (sz <= objSize)) {
      // Do nothing.
      return ptr;
    }
    // If the object is growing by less than 2X, double it.
    if ((objSize < sz) && (sz < objSize * 2)) {
      sz = objSize * 2;
    }
#endif

    void * buf = xxmalloc(sz);

    if (buf != NULL) {
      // Successful malloc.
      // Copy the contents of the original object
      // up to the size of the new block.
      size_t minSize = (objSize < sz) ? objSize : sz;
      memcpy (buf, ptr, minSize);
      xxfree (ptr);
    }

    // Return a pointer to the new one.
    return buf;
  }

  static void * my_memalign_hook (size_t size, size_t alignment, const void *) {
    // Check for non power-of-two alignment, or mistake in size.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return NULL;
      }

    // Try to just allocate an object of the requested size.
    // If it happens to be aligned properly, just return it.
    void * ptr = xxmalloc (size);
    if (((size_t) ptr & (alignment - 1)) == (size_t) ptr) {
      // It is already aligned just fine; return it.
      return ptr;
    }

    // It was not aligned as requested: free the object.
    xxfree (ptr);

    // Now get a big chunk of memory and align the object within it.
    // NOTE: this REQUIRES that the underlying allocator be able
    // to free the aligned object, or ignore the free request.
    void * buf = xxmalloc (2 * alignment + size);
    void * alignedPtr = (void *) (((size_t) buf + alignment - 1) & ~(alignment - 1));

    return alignedPtr;
  }

  ////// END OF HOOK FUNCTIONS

  // This is here because, for some reason, the GNU hooks don't
  // necessarily replace all memory operations as they should.

  int posix_memalign (void **memptr, size_t alignment, size_t size) throw()
  {
    if (!initialized) {
      my_init_hook();
    }
    // Check for non power-of-two alignment.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return EINVAL;
      }
    void * ptr = my_memalign_hook (size, alignment, NULL);
    if (!ptr) {
      return ENOMEM;
    } else {
      *memptr = ptr;
      return 0;
    }
  }

  //// DIRECT REPLACEMENTS FOR MALLOC FAMILY.

  size_t malloc_usable_size (void * ptr) throw() {
    return xxmalloc_usable_size (ptr);
  }

  int mallopt (int param, int value) throw() {
    // NOP.
    param = param;
    value = value;
    return 1; // success.
  }

  int malloc_trim (size_t pad) throw() {
    // NOP.
    pad = pad;
    return 0; // no memory returned to OS.
  }

  void malloc_stats (void) throw() {
    // NOP.
  }

  void * malloc_get_state (void) throw() {
    return NULL; // always returns "error".
  }

  int malloc_set_state (void * ptr) throw() {
    ptr = ptr;
    return 0; // success.
  }

  struct mallinfo mallinfo(void) throw() {
    // For now, we return useless stats.
    struct mallinfo m;
    m.arena = 0;
    m.ordblks = 0;
    m.smblks = 0;
    m.hblks = 0;
    m.hblkhd = 0;
    m.usmblks = 0;
    m.fsmblks = 0;
    m.uordblks = 0;
    m.fordblks = 0;
    m.keepcost = 0;
    return m;
  }

  void * malloc (size_t sz) throw () {
    return xxmalloc (sz);
  }

  void free (void * ptr) throw() {
    xxfree (ptr);
  }

  void * realloc (void * ptr, size_t sz) throw () {
    return my_realloc_hook (ptr, sz, NULL);
  }

  void * memalign (size_t sz, size_t alignment) throw() {
    return my_memalign_hook (sz, alignment, NULL);
  }

  void cfree (void * ptr) throw () {
    xxfree (ptr);
  }

  size_t malloc_size (void * p) {
    return xxmalloc_usable_size (p);
  }

  void * valloc (size_t sz) throw() {
    return my_memalign_hook (sz, HL::CPUInfo::PageSize, NULL);
  }

  void * pvalloc (size_t sz) throw() {
    return valloc ((sz + HL::CPUInfo::PageSize - 1) & ~(HL::CPUInfo::PageSize - 1));
  }

}

void * operator new (size_t sz) throw (std::bad_alloc)
{
  void * ptr = xxmalloc (sz);
  if (ptr == NULL) {
    throw std::bad_alloc();
  } else {
    return ptr;
  }
}

void operator delete (void * ptr)
  throw ()
{
  xxfree (ptr);
}

void * operator new (size_t sz, const std::nothrow_t&) throw() {
  return xxmalloc(sz);
}

void * operator new[] (size_t size)
  throw (std::bad_alloc)
{
  void * ptr = xxmalloc(size);
  if (ptr == NULL) {
    throw std::bad_alloc();
  } else {
    return ptr;
  }
}

void * operator new[] (size_t sz, const std::nothrow_t&)
  throw()
 {
  return xxmalloc(sz);
}

void operator delete[] (void * ptr)
  throw ()
{
  xxfree (ptr);
}

<commit_msg>Added missing pthread.h include.<commit_after>// -*- C++ -*-

/**
 * @file   gnuwrapper.cpp
 * @brief  Replaces malloc family on GNU/Linux with custom versions.
 * @author Emery Berger <http://www.cs.umass.edu/~emery>
 * @note   Copyright (C) 2010 by Emery Berger, University of Massachusetts Amherst.
 */

#ifndef __GNUC__
#error "This file requires the GNU compiler."
#endif

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <new>
#include <pthread.h>

#include "heaplayers.h"

/*
  To use this library,
  you only need to define the following allocation functions:

  - xxmalloc
  - xxfree
  - xxmalloc_usable_size
  - xxmalloc_lock
  - xxmalloc_unlock

  See the extern "C" block below for function prototypes and more
  details. YOU SHOULD NOT NEED TO MODIFY ANY OF THE CODE HERE TO
  SUPPORT ANY ALLOCATOR.

  LIMITATIONS:

  - This wrapper assumes that the underlying allocator will do "the
    right thing" when xxfree() is called with a pointer internal to an
    allocated object. Header-based allocators, for example, need not
    apply.

*/

static bool initialized = false;

extern "C" {

  void * xxmalloc (size_t);
  void   xxfree (void *);
  size_t xxmalloc_usable_size (void *);
  void   xxmalloc_lock (void);
  void   xxmalloc_unlock (void);

  static void my_init_hook (void);

  // New hooks for allocation functions.
  static void * my_malloc_hook (size_t, const void *);
  static void   my_free_hook (void *, const void *);
  static void * my_realloc_hook (void *, size_t, const void *);
  static void * my_memalign_hook (size_t, size_t, const void *);

  // Store the old hooks just in case.
  static void * (*old_malloc_hook) (size_t, const void *);
  static void   (*old_free_hook) (void *, const void *);
  static void * (*old_realloc_hook)(void *ptr, size_t size, const void *caller);
  static void * (*old_memalign_hook)(size_t alignment, size_t size, const void *caller);

// From GNU libc 2.14 this macro is defined, to declare
// hook variables as volatile. Define it as empty for
// older glibc versions
#ifndef __MALLOC_HOOK_VOLATILE
 #define __MALLOC_HOOK_VOLATILE
#endif

  void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) = my_init_hook;

  static void my_init_hook (void) {
    if (!initialized) {
      // Store the old hooks.
      old_malloc_hook = __malloc_hook;
      old_free_hook = __free_hook;
      old_realloc_hook = __realloc_hook;
      old_memalign_hook = __memalign_hook;

      // Point the hooks to the replacement functions.
      __malloc_hook = my_malloc_hook;
      __free_hook = my_free_hook;
      __realloc_hook = my_realloc_hook;
      __memalign_hook = my_memalign_hook;

      // Set up everything so that fork behaves properly.
      pthread_atfork(xxmalloc_lock, xxmalloc_unlock, xxmalloc_unlock);

      initialized = true;

    }

  }

  static void * my_malloc_hook (size_t size, const void *) {
    return xxmalloc(size);
  }

  static void my_free_hook (void * ptr, const void *) {
    xxfree(ptr);
  }

  static void * my_realloc_hook (void * ptr, size_t sz, const void *) {
    // NULL ptr = malloc.
    if (ptr == NULL) {
      return xxmalloc(sz);
    }

    if (sz == 0) {
      xxfree (ptr);
#if defined(__APPLE__)
      // 0 size = free. We return a small object.  This behavior is
      // apparently required under Mac OS X and optional under POSIX.
      return xxmalloc(1);
#else
      // For POSIX, don't return anything.
      return NULL;
#endif
    }

    size_t objSize = xxmalloc_usable_size(ptr);

#if 0
    // Custom logic here to ensure we only do a logarithmic number of
    // reallocations (with a constant space overhead).

    // Don't change size if the object is shrinking by less than half.
    if ((objSize / 2 < sz) && (sz <= objSize)) {
      // Do nothing.
      return ptr;
    }
    // If the object is growing by less than 2X, double it.
    if ((objSize < sz) && (sz < objSize * 2)) {
      sz = objSize * 2;
    }
#endif

    void * buf = xxmalloc(sz);

    if (buf != NULL) {
      // Successful malloc.
      // Copy the contents of the original object
      // up to the size of the new block.
      size_t minSize = (objSize < sz) ? objSize : sz;
      memcpy (buf, ptr, minSize);
      xxfree (ptr);
    }

    // Return a pointer to the new one.
    return buf;
  }

  static void * my_memalign_hook (size_t size, size_t alignment, const void *) {
    // Check for non power-of-two alignment, or mistake in size.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return NULL;
      }

    // Try to just allocate an object of the requested size.
    // If it happens to be aligned properly, just return it.
    void * ptr = xxmalloc (size);
    if (((size_t) ptr & (alignment - 1)) == (size_t) ptr) {
      // It is already aligned just fine; return it.
      return ptr;
    }

    // It was not aligned as requested: free the object.
    xxfree (ptr);

    // Now get a big chunk of memory and align the object within it.
    // NOTE: this REQUIRES that the underlying allocator be able
    // to free the aligned object, or ignore the free request.
    void * buf = xxmalloc (2 * alignment + size);
    void * alignedPtr = (void *) (((size_t) buf + alignment - 1) & ~(alignment - 1));

    return alignedPtr;
  }

  ////// END OF HOOK FUNCTIONS

  // This is here because, for some reason, the GNU hooks don't
  // necessarily replace all memory operations as they should.

  int posix_memalign (void **memptr, size_t alignment, size_t size) throw()
  {
    if (!initialized) {
      my_init_hook();
    }
    // Check for non power-of-two alignment.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return EINVAL;
      }
    void * ptr = my_memalign_hook (size, alignment, NULL);
    if (!ptr) {
      return ENOMEM;
    } else {
      *memptr = ptr;
      return 0;
    }
  }

  //// DIRECT REPLACEMENTS FOR MALLOC FAMILY.

  size_t malloc_usable_size (void * ptr) throw() {
    return xxmalloc_usable_size (ptr);
  }

  int mallopt (int param, int value) throw() {
    // NOP.
    param = param;
    value = value;
    return 1; // success.
  }

  int malloc_trim (size_t pad) throw() {
    // NOP.
    pad = pad;
    return 0; // no memory returned to OS.
  }

  void malloc_stats (void) throw() {
    // NOP.
  }

  void * malloc_get_state (void) throw() {
    return NULL; // always returns "error".
  }

  int malloc_set_state (void * ptr) throw() {
    ptr = ptr;
    return 0; // success.
  }

  struct mallinfo mallinfo(void) throw() {
    // For now, we return useless stats.
    struct mallinfo m;
    m.arena = 0;
    m.ordblks = 0;
    m.smblks = 0;
    m.hblks = 0;
    m.hblkhd = 0;
    m.usmblks = 0;
    m.fsmblks = 0;
    m.uordblks = 0;
    m.fordblks = 0;
    m.keepcost = 0;
    return m;
  }

  void * malloc (size_t sz) throw () {
    return xxmalloc (sz);
  }

  void free (void * ptr) throw() {
    xxfree (ptr);
  }

  void * realloc (void * ptr, size_t sz) throw () {
    return my_realloc_hook (ptr, sz, NULL);
  }

  void * memalign (size_t sz, size_t alignment) throw() {
    return my_memalign_hook (sz, alignment, NULL);
  }

  void cfree (void * ptr) throw () {
    xxfree (ptr);
  }

  size_t malloc_size (void * p) {
    return xxmalloc_usable_size (p);
  }

  void * valloc (size_t sz) throw() {
    return my_memalign_hook (sz, HL::CPUInfo::PageSize, NULL);
  }

  void * pvalloc (size_t sz) throw() {
    return valloc ((sz + HL::CPUInfo::PageSize - 1) & ~(HL::CPUInfo::PageSize - 1));
  }

}

void * operator new (size_t sz) throw (std::bad_alloc)
{
  void * ptr = xxmalloc (sz);
  if (ptr == NULL) {
    throw std::bad_alloc();
  } else {
    return ptr;
  }
}

void operator delete (void * ptr)
  throw ()
{
  xxfree (ptr);
}

void * operator new (size_t sz, const std::nothrow_t&) throw() {
  return xxmalloc(sz);
}

void * operator new[] (size_t size)
  throw (std::bad_alloc)
{
  void * ptr = xxmalloc(size);
  if (ptr == NULL) {
    throw std::bad_alloc();
  } else {
    return ptr;
  }
}

void * operator new[] (size_t sz, const std::nothrow_t&)
  throw()
 {
  return xxmalloc(sz);
}

void operator delete[] (void * ptr)
  throw ()
{
  xxfree (ptr);
}

<|endoftext|>


<commit_before>#include "tracing.h"

namespace couchnode
{

RequestTracer *unwrapTracer(const lcbtrace_TRACER *procs)
{
    return reinterpret_cast<RequestTracer *>(procs->cookie);
}

RequestSpan *unwrapSpan(const lcbxtrace_SPAN *procs)
{
    return reinterpret_cast<RequestSpan *>((void *)procs);
}

static lcbxtrace_SPAN *lcbTracerStartSpan(lcbtrace_TRACER *procs,
                                          const char *name,
                                          lcbxtrace_SPAN *parent)
{
    RequestTracer *tracer = unwrapTracer(procs);
    if (tracer) {
        return tracer->requestSpan(name, parent);
    }
    return nullptr;
}

static void lcbSpanEnd(lcbxtrace_SPAN *procs)
{
    RequestSpan *span = unwrapSpan(procs);
    if (span) {
        span->end();
    }
}

static void lcbSpanDestroy(lcbxtrace_SPAN *procs)
{
    RequestSpan *span = unwrapSpan(procs);
    if (span) {
        RequestSpan::destroy(span);
    }
}

static void lcbSpanAddTagString(lcbxtrace_SPAN *procs, const char *name,
                                const char *value, size_t nvalue)
{
    RequestSpan *span = unwrapSpan(procs);
    if (span) {
        span->addTagString(name, value, nvalue);
    }
}

static void lcbSpanAddTagUint64(lcbxtrace_SPAN *procs, const char *name,
                                uint64_t value)
{
    RequestSpan *span = unwrapSpan(procs);
    if (span) {
        span->addTagUint64(name, value);
    }
}

RequestTracer::RequestTracer(Local<Object> impl)
{
    _lcbTracer = lcbtrace_new(nullptr, LCBTRACE_F_EXTERNAL);
    _lcbTracer->version = 1;
    _lcbTracer->v.v1.start_span = lcbTracerStartSpan;
    _lcbTracer->v.v1.end_span = lcbSpanEnd;
    _lcbTracer->v.v1.destroy_span = lcbSpanDestroy;
    _lcbTracer->v.v1.add_tag_string = lcbSpanAddTagString;
    _lcbTracer->v.v1.add_tag_uint64 = lcbSpanAddTagUint64;
    _lcbTracer->cookie = reinterpret_cast<void *>(this);

    _impl.Reset(impl);
    _requestSpanImpl.Reset(
        Nan::Get(impl, Nan::New("requestSpan").ToLocalChecked())
            .ToLocalChecked()
            .As<Function>());
}

RequestTracer::~RequestTracer()
{
    _requestSpanImpl.Reset();
    _impl.Reset();
    lcbtrace_destroy(_lcbTracer);
    _lcbTracer = nullptr;
}

lcbtrace_TRACER *RequestTracer::lcbProcs() const
{
    return _lcbTracer;
}

lcbxtrace_SPAN *RequestTracer::requestSpan(const char *name,
                                           const lcbxtrace_SPAN *parent)
{
    Nan::HandleScope scope;
    Local<Object> impl = Nan::New(_impl);
    Local<Function> requestSpanImpl = Nan::New(_requestSpanImpl);
    if (impl.IsEmpty() || requestSpanImpl.IsEmpty()) {
        return nullptr;
    }

    Local<String> nameVal = Nan::New<String>(name).ToLocalChecked();
    Local<Value> parentVal = Nan::Undefined();
    if (parent) {
        RequestSpan *parentSpan = unwrapSpan(parent);
        if (parentSpan) {
            parentVal = Nan::New(parentSpan->impl());
        }
    }
    Local<Value> argv[] = {nameVal, parentVal};
    Local<Value> res =
        Nan::Call(requestSpanImpl, impl, 2, argv).ToLocalChecked();
    if (res.IsEmpty() || !res->IsObject()) {
        return nullptr;
    }

    return (new RequestSpan(res.As<Object>()))->lcbProcs();
}

RequestSpan::RequestSpan(Local<Object> impl, bool isWrapped)
    : _lcbSpan(this)
    , _isWrapped(isWrapped)
{
    _addTagImpl.Reset(Nan::Get(impl, Nan::New("addTag").ToLocalChecked())
                          .ToLocalChecked()
                          .As<Function>());
    _endImpl.Reset(Nan::Get(impl, Nan::New("end").ToLocalChecked())
                       .ToLocalChecked()
                       .As<Function>());
    _impl.Reset(impl);
}

RequestSpan::~RequestSpan()
{
    _addTagImpl.Reset();
    _endImpl.Reset();
    _impl.Reset();
}

lcbxtrace_SPAN *RequestSpan::lcbProcs() const
{
    return _lcbSpan;
}

void RequestSpan::destroy(const RequestSpan *span)
{
    if (span->_isWrapped) {
        // if its wrapped, the owner is responsible for cleanup
        return;
    }

    delete span;
}

const Nan::Persistent<Object> &RequestSpan::impl() const
{
    return _impl;
}

void RequestSpan::addTagString(const char *key, const char *value,
                               size_t nvalue)
{
    if (_isWrapped) {
        return;
    }

    Nan::HandleScope scope;
    Local<Object> impl = Nan::New(_impl);
    Local<Function> addTagImpl = Nan::New(_addTagImpl);
    if (impl.IsEmpty() || addTagImpl.IsEmpty()) {
        return;
    }

    Local<String> keyVal = Nan::New<String>(key).ToLocalChecked();
    Local<String> valueVal = Nan::New<String>(value, nvalue).ToLocalChecked();
    Local<Value> argv[] = {keyVal, valueVal};
    Nan::Call(addTagImpl, impl, 2, argv);
}

void RequestSpan::addTagUint64(const char *key, uint64_t value)
{
    if (_isWrapped) {
        return;
    }

    Nan::HandleScope scope;
    Local<Object> impl = Nan::New(_impl);
    Local<Function> addTagImpl = Nan::New(_addTagImpl);
    if (impl.IsEmpty() || addTagImpl.IsEmpty()) {
        return;
    }

    Local<String> keyVal = Nan::New<String>(key).ToLocalChecked();
    Local<Number> valueVal = Nan::New<Number>(value);
    Local<Value> argv[] = {keyVal, valueVal};
    Nan::Call(addTagImpl, impl, 2, argv);
}

void RequestSpan::end()
{
    if (_isWrapped) {
        return;
    }

    Nan::HandleScope scope;
    Local<Object> impl = Nan::New(_impl);
    Local<Function> endImpl = Nan::New(_endImpl);
    if (impl.IsEmpty() || endImpl.IsEmpty()) {
        return;
    }

    Nan::Call(endImpl, impl, 0, nullptr);
}

} // namespace couchnode
<commit_msg>JSCBC-936: Segfault in lcbtrace_destroy when closing cluster using custom tracer<commit_after>#include "tracing.h"

namespace couchnode
{

RequestTracer *unwrapTracer(const lcbtrace_TRACER *procs)
{
    return reinterpret_cast<RequestTracer *>(procs->cookie);
}

RequestSpan *unwrapSpan(const lcbxtrace_SPAN *procs)
{
    return reinterpret_cast<RequestSpan *>((void *)procs);
}

static lcbxtrace_SPAN *lcbTracerStartSpan(lcbtrace_TRACER *procs,
                                          const char *name,
                                          lcbxtrace_SPAN *parent)
{
    RequestTracer *tracer = unwrapTracer(procs);
    if (tracer) {
        return tracer->requestSpan(name, parent);
    }
    return nullptr;
}

static void lcbSpanEnd(lcbxtrace_SPAN *procs)
{
    RequestSpan *span = unwrapSpan(procs);
    if (span) {
        span->end();
    }
}

static void lcbSpanDestroy(lcbxtrace_SPAN *procs)
{
    RequestSpan *span = unwrapSpan(procs);
    if (span) {
        RequestSpan::destroy(span);
    }
}

static void lcbSpanAddTagString(lcbxtrace_SPAN *procs, const char *name,
                                const char *value, size_t nvalue)
{
    RequestSpan *span = unwrapSpan(procs);
    if (span) {
        span->addTagString(name, value, nvalue);
    }
}

static void lcbSpanAddTagUint64(lcbxtrace_SPAN *procs, const char *name,
                                uint64_t value)
{
    RequestSpan *span = unwrapSpan(procs);
    if (span) {
        span->addTagUint64(name, value);
    }
}

RequestTracer::RequestTracer(Local<Object> impl)
{
    _lcbTracer = lcbtrace_new(nullptr, LCBTRACE_F_EXTERNAL);
    _lcbTracer->version = 1;
    _lcbTracer->destructor = nullptr;
    _lcbTracer->v.v1.start_span = lcbTracerStartSpan;
    _lcbTracer->v.v1.end_span = lcbSpanEnd;
    _lcbTracer->v.v1.destroy_span = lcbSpanDestroy;
    _lcbTracer->v.v1.add_tag_string = lcbSpanAddTagString;
    _lcbTracer->v.v1.add_tag_uint64 = lcbSpanAddTagUint64;
    _lcbTracer->cookie = reinterpret_cast<void *>(this);

    _impl.Reset(impl);
    _requestSpanImpl.Reset(
        Nan::Get(impl, Nan::New("requestSpan").ToLocalChecked())
            .ToLocalChecked()
            .As<Function>());
}

RequestTracer::~RequestTracer()
{
    _requestSpanImpl.Reset();
    _impl.Reset();
    lcbtrace_destroy(_lcbTracer);
    _lcbTracer = nullptr;
}

lcbtrace_TRACER *RequestTracer::lcbProcs() const
{
    return _lcbTracer;
}

lcbxtrace_SPAN *RequestTracer::requestSpan(const char *name,
                                           const lcbxtrace_SPAN *parent)
{
    Nan::HandleScope scope;
    Local<Object> impl = Nan::New(_impl);
    Local<Function> requestSpanImpl = Nan::New(_requestSpanImpl);
    if (impl.IsEmpty() || requestSpanImpl.IsEmpty()) {
        return nullptr;
    }

    Local<String> nameVal = Nan::New<String>(name).ToLocalChecked();
    Local<Value> parentVal = Nan::Undefined();
    if (parent) {
        RequestSpan *parentSpan = unwrapSpan(parent);
        if (parentSpan) {
            parentVal = Nan::New(parentSpan->impl());
        }
    }
    Local<Value> argv[] = {nameVal, parentVal};
    Local<Value> res =
        Nan::Call(requestSpanImpl, impl, 2, argv).ToLocalChecked();
    if (res.IsEmpty() || !res->IsObject()) {
        return nullptr;
    }

    return (new RequestSpan(res.As<Object>()))->lcbProcs();
}

RequestSpan::RequestSpan(Local<Object> impl, bool isWrapped)
    : _lcbSpan(this)
    , _isWrapped(isWrapped)
{
    _addTagImpl.Reset(Nan::Get(impl, Nan::New("addTag").ToLocalChecked())
                          .ToLocalChecked()
                          .As<Function>());
    _endImpl.Reset(Nan::Get(impl, Nan::New("end").ToLocalChecked())
                       .ToLocalChecked()
                       .As<Function>());
    _impl.Reset(impl);
}

RequestSpan::~RequestSpan()
{
    _addTagImpl.Reset();
    _endImpl.Reset();
    _impl.Reset();
}

lcbxtrace_SPAN *RequestSpan::lcbProcs() const
{
    return _lcbSpan;
}

void RequestSpan::destroy(const RequestSpan *span)
{
    if (span->_isWrapped) {
        // if its wrapped, the owner is responsible for cleanup
        return;
    }

    delete span;
}

const Nan::Persistent<Object> &RequestSpan::impl() const
{
    return _impl;
}

void RequestSpan::addTagString(const char *key, const char *value,
                               size_t nvalue)
{
    if (_isWrapped) {
        return;
    }

    Nan::HandleScope scope;
    Local<Object> impl = Nan::New(_impl);
    Local<Function> addTagImpl = Nan::New(_addTagImpl);
    if (impl.IsEmpty() || addTagImpl.IsEmpty()) {
        return;
    }

    Local<String> keyVal = Nan::New<String>(key).ToLocalChecked();
    Local<String> valueVal = Nan::New<String>(value, nvalue).ToLocalChecked();
    Local<Value> argv[] = {keyVal, valueVal};
    Nan::Call(addTagImpl, impl, 2, argv);
}

void RequestSpan::addTagUint64(const char *key, uint64_t value)
{
    if (_isWrapped) {
        return;
    }

    Nan::HandleScope scope;
    Local<Object> impl = Nan::New(_impl);
    Local<Function> addTagImpl = Nan::New(_addTagImpl);
    if (impl.IsEmpty() || addTagImpl.IsEmpty()) {
        return;
    }

    Local<String> keyVal = Nan::New<String>(key).ToLocalChecked();
    Local<Number> valueVal = Nan::New<Number>(value);
    Local<Value> argv[] = {keyVal, valueVal};
    Nan::Call(addTagImpl, impl, 2, argv);
}

void RequestSpan::end()
{
    if (_isWrapped) {
        return;
    }

    Nan::HandleScope scope;
    Local<Object> impl = Nan::New(_impl);
    Local<Function> endImpl = Nan::New(_endImpl);
    if (impl.IsEmpty() || endImpl.IsEmpty()) {
        return;
    }

    Nan::Call(endImpl, impl, 0, nullptr);
}

} // namespace couchnode
<|endoftext|>


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

#ifndef _BGFX_RANGE_B2IRANGE_HXX
#define _BGFX_RANGE_B2IRANGE_HXX

#ifndef _BGFX_POINT_B2IPOINT_HXX
#include <basegfx/point/b2ipoint.hxx>
#endif
#ifndef _BGFX_POINT_B2DPOINT_HXX
#include <basegfx/point/b2dpoint.hxx>
#endif
#ifndef _BGFX_TUPLE_B2ITUPLE_HXX
#include <basegfx/tuple/b2ituple.hxx>
#endif
#ifndef _BGFX_TUPLE_B2I64TUPLE_HXX
#include <basegfx/tuple/b2i64tuple.hxx>
#endif

#ifndef _BGFX_RANGE_BASICRANGE_HXX
#include <basegfx/range/basicrange.hxx>
#endif

namespace basegfx
{
    class B2IRange
    {
        typedef ::basegfx::BasicRange< sal_Int32, Int32Traits > MyBasicRange;

        MyBasicRange        maRangeX;
        MyBasicRange        maRangeY;

    public:
        B2IRange()
        {
        }

        explicit B2IRange(const B2ITuple& rTuple)
        :   maRangeX(rTuple.getX()),
            maRangeY(rTuple.getY())
        {
        }

        B2IRange(sal_Int32 x1,
                 sal_Int32 y1,
                 sal_Int32 x2,
                 sal_Int32 y2)
        :   maRangeX(x1),
            maRangeY(y1)
        {
            maRangeX.expand(x2);
            maRangeY.expand(y2);
        }

        B2IRange(const B2ITuple& rTuple1,
                 const B2ITuple& rTuple2)
        :   maRangeX(rTuple1.getX()),
            maRangeY(rTuple1.getY())
        {
            expand( rTuple2 );
        }

        B2IRange(const B2IRange& rRange)
        :   maRangeX(rRange.maRangeX),
            maRangeY(rRange.maRangeY)
        {
        }

        bool isEmpty() const
        {
            return maRangeX.isEmpty() || maRangeY.isEmpty();
        }

        void reset()
        {
            maRangeX.reset();
            maRangeY.reset();
        }

        bool operator==( const B2IRange& rRange ) const
        {
            return (maRangeX == rRange.maRangeX
                && maRangeY == rRange.maRangeY);
        }

        bool operator!=( const B2IRange& rRange ) const
        {
            return (maRangeX != rRange.maRangeX
                || maRangeY != rRange.maRangeY);
        }

        void operator=(const B2IRange& rRange)
        {
            maRangeX = rRange.maRangeX;
            maRangeY = rRange.maRangeY;
        }

        sal_Int32 getMinX() const
        {
            return maRangeX.getMinimum();
        }

        sal_Int32 getMinY() const
        {
            return maRangeY.getMinimum();
        }

        sal_Int32 getMaxX() const
        {
            return maRangeX.getMaximum();
        }

        sal_Int32 getMaxY() const
        {
            return maRangeY.getMaximum();
        }

        sal_Int64 getWidth() const
        {
            return maRangeX.getRange();
        }

        sal_Int64 getHeight() const
        {
            return maRangeY.getRange();
        }

        B2IPoint getMinimum() const
        {
            return B2IPoint(
                maRangeX.getMinimum(),
                maRangeY.getMinimum()
                );
        }

        B2IPoint getMaximum() const
        {
            return B2IPoint(
                maRangeX.getMaximum(),
                maRangeY.getMaximum()
                );
        }

        B2I64Tuple getRange() const
        {
            return B2I64Tuple(
                maRangeX.getRange(),
                maRangeY.getRange()
                );
        }

        B2DPoint getCenter() const
        {
            return B2DPoint(
                maRangeX.getCenter(),
                maRangeY.getCenter()
                );
        }

        bool isInside(const B2ITuple& rTuple) const
        {
            return (
                maRangeX.isInside(rTuple.getX())
                && maRangeY.isInside(rTuple.getY())
                );
        }

        bool isInside(const B2IRange& rRange) const
        {
            return (
                maRangeX.isInside(rRange.maRangeX)
                && maRangeY.isInside(rRange.maRangeY)
                );
        }

        bool overlaps(const B2IRange& rRange) const
        {
            return (
                maRangeX.overlaps(rRange.maRangeX)
                && maRangeY.overlaps(rRange.maRangeY)
                );
        }

        void expand(const B2ITuple& rTuple)
        {
            maRangeX.expand(rTuple.getX());
            maRangeY.expand(rTuple.getY());
        }

        void expand(const B2IRange& rRange)
        {
            maRangeX.expand(rRange.maRangeX);
            maRangeY.expand(rRange.maRangeY);
        }

        void grow(sal_Int32 nValue)
        {
            maRangeX.grow(nValue);
            maRangeY.grow(nValue);
        }
    };
} // end of namespace basegfx

#endif /* _BGFX_RANGE_B2IRANGE_HXX */
<commit_msg>INTEGRATION: CWS presentationengine01 (1.5.12); FILE MERGED 2004/11/17 18:53:49 thb 1.5.12.2: RESYNC: (1.5-1.6); FILE MERGED 2004/09/23 20:19:06 thb 1.5.12.1: #110496# Added intersect method to all range types<commit_after>/*************************************************************************
 *
 *  $RCSfile: b2irange.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2004-11-26 18:35:11 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _BGFX_RANGE_B2IRANGE_HXX
#define _BGFX_RANGE_B2IRANGE_HXX

#ifndef _BGFX_POINT_B2IPOINT_HXX
#include <basegfx/point/b2ipoint.hxx>
#endif
#ifndef _BGFX_POINT_B2DPOINT_HXX
#include <basegfx/point/b2dpoint.hxx>
#endif
#ifndef _BGFX_TUPLE_B2ITUPLE_HXX
#include <basegfx/tuple/b2ituple.hxx>
#endif
#ifndef _BGFX_TUPLE_B2I64TUPLE_HXX
#include <basegfx/tuple/b2i64tuple.hxx>
#endif

#ifndef _BGFX_RANGE_BASICRANGE_HXX
#include <basegfx/range/basicrange.hxx>
#endif

namespace basegfx
{
    class B2IRange
    {
        typedef ::basegfx::BasicRange< sal_Int32, Int32Traits > MyBasicRange;

        MyBasicRange        maRangeX;
        MyBasicRange        maRangeY;

    public:
        B2IRange()
        {
        }

        explicit B2IRange(const B2ITuple& rTuple)
        :   maRangeX(rTuple.getX()),
            maRangeY(rTuple.getY())
        {
        }

        B2IRange(sal_Int32 x1,
                 sal_Int32 y1,
                 sal_Int32 x2,
                 sal_Int32 y2)
        :   maRangeX(x1),
            maRangeY(y1)
        {
            maRangeX.expand(x2);
            maRangeY.expand(y2);
        }

        B2IRange(const B2ITuple& rTuple1,
                 const B2ITuple& rTuple2)
        :   maRangeX(rTuple1.getX()),
            maRangeY(rTuple1.getY())
        {
            expand( rTuple2 );
        }

        B2IRange(const B2IRange& rRange)
        :   maRangeX(rRange.maRangeX),
            maRangeY(rRange.maRangeY)
        {
        }

        bool isEmpty() const
        {
            return maRangeX.isEmpty() || maRangeY.isEmpty();
        }

        void reset()
        {
            maRangeX.reset();
            maRangeY.reset();
        }

        bool operator==( const B2IRange& rRange ) const
        {
            return (maRangeX == rRange.maRangeX
                && maRangeY == rRange.maRangeY);
        }

        bool operator!=( const B2IRange& rRange ) const
        {
            return (maRangeX != rRange.maRangeX
                || maRangeY != rRange.maRangeY);
        }

        void operator=(const B2IRange& rRange)
        {
            maRangeX = rRange.maRangeX;
            maRangeY = rRange.maRangeY;
        }

        sal_Int32 getMinX() const
        {
            return maRangeX.getMinimum();
        }

        sal_Int32 getMinY() const
        {
            return maRangeY.getMinimum();
        }

        sal_Int32 getMaxX() const
        {
            return maRangeX.getMaximum();
        }

        sal_Int32 getMaxY() const
        {
            return maRangeY.getMaximum();
        }

        sal_Int64 getWidth() const
        {
            return maRangeX.getRange();
        }

        sal_Int64 getHeight() const
        {
            return maRangeY.getRange();
        }

        B2IPoint getMinimum() const
        {
            return B2IPoint(
                maRangeX.getMinimum(),
                maRangeY.getMinimum()
                );
        }

        B2IPoint getMaximum() const
        {
            return B2IPoint(
                maRangeX.getMaximum(),
                maRangeY.getMaximum()
                );
        }

        B2I64Tuple getRange() const
        {
            return B2I64Tuple(
                maRangeX.getRange(),
                maRangeY.getRange()
                );
        }

        B2DPoint getCenter() const
        {
            return B2DPoint(
                maRangeX.getCenter(),
                maRangeY.getCenter()
                );
        }

        bool isInside(const B2ITuple& rTuple) const
        {
            return (
                maRangeX.isInside(rTuple.getX())
                && maRangeY.isInside(rTuple.getY())
                );
        }

        bool isInside(const B2IRange& rRange) const
        {
            return (
                maRangeX.isInside(rRange.maRangeX)
                && maRangeY.isInside(rRange.maRangeY)
                );
        }

        bool overlaps(const B2IRange& rRange) const
        {
            return (
                maRangeX.overlaps(rRange.maRangeX)
                && maRangeY.overlaps(rRange.maRangeY)
                );
        }

        void expand(const B2ITuple& rTuple)
        {
            maRangeX.expand(rTuple.getX());
            maRangeY.expand(rTuple.getY());
        }

        void expand(const B2IRange& rRange)
        {
            maRangeX.expand(rRange.maRangeX);
            maRangeY.expand(rRange.maRangeY);
        }

        void intersect(const B2IRange& rRange)
        {
            maRangeX.intersect(rRange.maRangeX);
            maRangeY.intersect(rRange.maRangeY);
        }

        void grow(sal_Int32 nValue)
        {
            maRangeX.grow(nValue);
            maRangeY.grow(nValue);
        }
    };
} // end of namespace basegfx

#endif /* _BGFX_RANGE_B2IRANGE_HXX */
<|endoftext|>


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

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif

#ifndef _HOMMATRIX_TEMPLATE_HXX
#include <hommatrixtemplate.hxx>
#endif

#ifndef _BGFX_MATRIX_B3DHOMMATRIX_HXX
#include <basegfx/matrix/b3dhommatrix.hxx>
#endif

#ifndef _BGFX_TUPLE_B3DTUPLE_HXX
#include <basegfx/tuple/b3dtuple.hxx>
#endif

#ifndef _BGFX_TUPLE_B2DTUPLE_HXX
#include <basegfx/tuple/b2dtuple.hxx>
#endif

namespace basegfx
{
    class Impl2DHomMatrix : public ::basegfx::internal::ImplHomMatrixTemplate< 3 >
    {
    };

    static Impl2DHomMatrix& get2DIdentityMatrix()
    {
        static Impl2DHomMatrix maStatic2DIdentityHomMatrix;
        return maStatic2DIdentityHomMatrix;
    }

    void B2DHomMatrix::implPrepareChange()
    {
        if(mpM->getRefCount())
        {
            mpM->decRefCount();
            mpM = new Impl2DHomMatrix(*mpM);
        }
    }

    B2DHomMatrix::B2DHomMatrix()
    :   mpM(&get2DIdentityMatrix())
    {
        mpM->incRefCount();
    }

    B2DHomMatrix::B2DHomMatrix(const B2DHomMatrix& rMat)
    :   mpM(rMat.mpM)
    {
        mpM->incRefCount();
    }

    B2DHomMatrix::~B2DHomMatrix()
    {
        if(mpM->getRefCount())
            mpM->decRefCount();
        else
            delete mpM;
    }

    B2DHomMatrix& B2DHomMatrix::operator=(const B2DHomMatrix& rMat)
    {
        if(mpM->getRefCount())
            mpM->decRefCount();
        else
            delete mpM;

        mpM = rMat.mpM;
        mpM->incRefCount();

        return *this;
    }

    double B2DHomMatrix::get(sal_uInt16 nRow, sal_uInt16 nColumn) const
    {
        return mpM->get(nRow, nColumn);
    }

    void B2DHomMatrix::set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue)
    {
        implPrepareChange();
        mpM->set(nRow, nColumn, fValue);
    }

    bool B2DHomMatrix::isIdentity() const
    {
        if(mpM == &get2DIdentityMatrix())
            return true;

        return mpM->isIdentity();
    }

    void B2DHomMatrix::identity()
    {
        if(mpM->getRefCount())
            mpM->decRefCount();
        else
            delete mpM;

        mpM = &get2DIdentityMatrix();
        mpM->incRefCount();
    }

    bool B2DHomMatrix::isInvertible() const
    {
        return mpM->isInvertible();
    }

    bool B2DHomMatrix::invert()
    {
        Impl2DHomMatrix aWork(*mpM);
        sal_uInt16* pIndex = new sal_uInt16[mpM->getEdgeLength()];
        sal_Int16 nParity;

        if(aWork.ludcmp(pIndex, nParity))
        {
            implPrepareChange();
            mpM->doInvert(aWork, pIndex);
            delete[] pIndex;

            return true;
        }

        delete[] pIndex;
        return false;
    }

    bool B2DHomMatrix::isNormalized() const
    {
        return mpM->isNormalized();
    }

    void B2DHomMatrix::normalize()
    {
        if(!mpM->isNormalized())
        {
            implPrepareChange();
            mpM->doNormalize();
        }
    }

    double B2DHomMatrix::determinant() const
    {
        return mpM->doDeterminant();
    }

    double B2DHomMatrix::trace() const
    {
        return mpM->doTrace();
    }

    void B2DHomMatrix::transpose()
    {
        implPrepareChange();
        mpM->doTranspose();
    }

    B2DHomMatrix& B2DHomMatrix::operator+=(const B2DHomMatrix& rMat)
    {
        implPrepareChange();
        mpM->doAddMatrix(*rMat.mpM);

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator-=(const B2DHomMatrix& rMat)
    {
        implPrepareChange();
        mpM->doSubMatrix(*rMat.mpM);

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator*=(double fValue)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fValue))
        {
            implPrepareChange();
            mpM->doMulMatrix(fValue);
        }

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator/=(double fValue)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fValue))
        {
            implPrepareChange();
            mpM->doMulMatrix(1.0 / fValue);
        }

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator*=(const B2DHomMatrix& rMat)
    {
        if(!rMat.isIdentity())
        {
            implPrepareChange();
            mpM->doMulMatrix(*rMat.mpM);
        }

        return *this;
    }

    bool B2DHomMatrix::operator==(const B2DHomMatrix& rMat) const
    {
        if(mpM == rMat.mpM)
            return true;

        return mpM->isEqual(*rMat.mpM);
    }

    bool B2DHomMatrix::operator!=(const B2DHomMatrix& rMat) const
    {
        if(mpM == rMat.mpM)
            return false;

        return !mpM->isEqual(*rMat.mpM);
    }

    void B2DHomMatrix::rotate(double fRadiant)
    {
        if(!::basegfx::fTools::equalZero(fRadiant))
        {
            double fSin;
            double fCos;

            // is the rotation angle an approximate multiple of pi/2?
            // If yes, force fSin/fCos to -1/0/1, to maintain
            // orthogonality (which might also be advantageous for the
            // other cases, but: for multiples of pi/2, the exact
            // values _can_ be attained. It would be largely
            // unintuitive, if a 180 degrees rotation would introduce
            // slight roundoff errors, instead of exactly mirroring
            // the coordinate system).
            if( fTools::equalZero( fmod( fRadiant, F_PI2 ) ) )
            {
                // determine quadrant
                const sal_Int32 nQuad(
                    (4 + fround( 4/F_2PI*fmod( fRadiant, F_2PI ) )) % 4 );
                switch( nQuad )
                {
                    case 0: // -2pi,0,2pi
                        fSin = 0.0;
                        fCos = 1.0;
                        break;

                    case 1: // -3/2pi,1/2pi
                        fSin = 1.0;
                        fCos = 0.0;
                        break;

                    case 2: // -pi,pi
                        fSin = 0.0;
                        fCos = -1.0;
                        break;

                    case 3: // -1/2pi,3/2pi
                        fSin = -1.0;
                        fCos = 0.0;
                        break;

                    default:
                        OSL_ENSURE( false,
                                    "B2DHomMatrix::rotate(): Impossible case reached" );
                }
            }
            else
            {
                fSin = sin(fRadiant);
                fCos = cos(fRadiant);
            }

            Impl2DHomMatrix aRotMat(get2DIdentityMatrix());

            aRotMat.set(0, 0, fCos);
            aRotMat.set(1, 1, fCos);
            aRotMat.set(1, 0, fSin);
            aRotMat.set(0, 1, -fSin);

            implPrepareChange();
            mpM->doMulMatrix(aRotMat);
        }
    }

    void B2DHomMatrix::translate(double fX, double fY)
    {
        if(!::basegfx::fTools::equalZero(fX) || !::basegfx::fTools::equalZero(fY))
        {
            Impl2DHomMatrix aTransMat(get2DIdentityMatrix());

            aTransMat.set(0, 2, fX);
            aTransMat.set(1, 2, fY);

            implPrepareChange();
            mpM->doMulMatrix(aTransMat);
        }
    }

    void B2DHomMatrix::scale(double fX, double fY)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fX) || !::basegfx::fTools::equal(fOne, fY))
        {
            Impl2DHomMatrix aScaleMat(get2DIdentityMatrix());

            aScaleMat.set(0, 0, fX);
            aScaleMat.set(1, 1, fY);

            implPrepareChange();
            mpM->doMulMatrix(aScaleMat);
        }
    }

    void B2DHomMatrix::shearX(double fSx)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fSx))
        {
            Impl2DHomMatrix aShearXMat(get2DIdentityMatrix());

            aShearXMat.set(0, 1, fSx);

            implPrepareChange();
            mpM->doMulMatrix(aShearXMat);
        }
    }

    void B2DHomMatrix::shearY(double fSy)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fSy))
        {
            Impl2DHomMatrix aShearYMat(get2DIdentityMatrix());

            aShearYMat.set(1, 0, fSy);

            implPrepareChange();
            mpM->doMulMatrix(aShearYMat);
        }
    }

    // Decomposition
    bool B2DHomMatrix::decompose(B2DTuple& rScale, B2DTuple& rTranslate, double& rRotate, double& rShearX) const
    {
        // when perspective is used, decompose is not made here
        if(!mpM->isLastLineDefault())
            return false;

        // If determinant is zero, decomposition is not possible
        if(0.0 == mpM->doDeterminant())
            return false;

        // copy 2x2 matrix and translate vector to 3x3 matrix
        ::basegfx::B3DHomMatrix a3DHomMat;

        a3DHomMat.set(0, 0, get(0, 0));
        a3DHomMat.set(0, 1, get(0, 1));
        a3DHomMat.set(1, 0, get(1, 0));
        a3DHomMat.set(1, 1, get(1, 1));
        a3DHomMat.set(0, 3, get(0, 2));
        a3DHomMat.set(1, 3, get(1, 2));

        ::basegfx::B3DTuple r3DScale, r3DTranslate, r3DRotate, r3DShear;

        if(a3DHomMat.decompose(r3DScale, r3DTranslate, r3DRotate, r3DShear))
        {
            // copy scale values
            rScale.setX(r3DScale.getX());
            rScale.setY(r3DScale.getY());

            // copy shear
            rShearX = r3DShear.getX();

            // copy rotate
            rRotate = r3DRotate.getZ();

            // copy translate
            rTranslate.setX(r3DTranslate.getX());
            rTranslate.setY(r3DTranslate.getY());

            return true;
        }

        return false;
    }
} // end of namespace basegfx

// eof
<commit_msg>INTEGRATION: CWS ooo19126 (1.9.8); FILE MERGED 2005/09/05 17:38:36 rt 1.9.8.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: b2dhommatrix.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 20:42:20 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif

#ifndef _HOMMATRIX_TEMPLATE_HXX
#include <hommatrixtemplate.hxx>
#endif

#ifndef _BGFX_MATRIX_B3DHOMMATRIX_HXX
#include <basegfx/matrix/b3dhommatrix.hxx>
#endif

#ifndef _BGFX_TUPLE_B3DTUPLE_HXX
#include <basegfx/tuple/b3dtuple.hxx>
#endif

#ifndef _BGFX_TUPLE_B2DTUPLE_HXX
#include <basegfx/tuple/b2dtuple.hxx>
#endif

namespace basegfx
{
    class Impl2DHomMatrix : public ::basegfx::internal::ImplHomMatrixTemplate< 3 >
    {
    };

    static Impl2DHomMatrix& get2DIdentityMatrix()
    {
        static Impl2DHomMatrix maStatic2DIdentityHomMatrix;
        return maStatic2DIdentityHomMatrix;
    }

    void B2DHomMatrix::implPrepareChange()
    {
        if(mpM->getRefCount())
        {
            mpM->decRefCount();
            mpM = new Impl2DHomMatrix(*mpM);
        }
    }

    B2DHomMatrix::B2DHomMatrix()
    :   mpM(&get2DIdentityMatrix())
    {
        mpM->incRefCount();
    }

    B2DHomMatrix::B2DHomMatrix(const B2DHomMatrix& rMat)
    :   mpM(rMat.mpM)
    {
        mpM->incRefCount();
    }

    B2DHomMatrix::~B2DHomMatrix()
    {
        if(mpM->getRefCount())
            mpM->decRefCount();
        else
            delete mpM;
    }

    B2DHomMatrix& B2DHomMatrix::operator=(const B2DHomMatrix& rMat)
    {
        if(mpM->getRefCount())
            mpM->decRefCount();
        else
            delete mpM;

        mpM = rMat.mpM;
        mpM->incRefCount();

        return *this;
    }

    double B2DHomMatrix::get(sal_uInt16 nRow, sal_uInt16 nColumn) const
    {
        return mpM->get(nRow, nColumn);
    }

    void B2DHomMatrix::set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue)
    {
        implPrepareChange();
        mpM->set(nRow, nColumn, fValue);
    }

    bool B2DHomMatrix::isIdentity() const
    {
        if(mpM == &get2DIdentityMatrix())
            return true;

        return mpM->isIdentity();
    }

    void B2DHomMatrix::identity()
    {
        if(mpM->getRefCount())
            mpM->decRefCount();
        else
            delete mpM;

        mpM = &get2DIdentityMatrix();
        mpM->incRefCount();
    }

    bool B2DHomMatrix::isInvertible() const
    {
        return mpM->isInvertible();
    }

    bool B2DHomMatrix::invert()
    {
        Impl2DHomMatrix aWork(*mpM);
        sal_uInt16* pIndex = new sal_uInt16[mpM->getEdgeLength()];
        sal_Int16 nParity;

        if(aWork.ludcmp(pIndex, nParity))
        {
            implPrepareChange();
            mpM->doInvert(aWork, pIndex);
            delete[] pIndex;

            return true;
        }

        delete[] pIndex;
        return false;
    }

    bool B2DHomMatrix::isNormalized() const
    {
        return mpM->isNormalized();
    }

    void B2DHomMatrix::normalize()
    {
        if(!mpM->isNormalized())
        {
            implPrepareChange();
            mpM->doNormalize();
        }
    }

    double B2DHomMatrix::determinant() const
    {
        return mpM->doDeterminant();
    }

    double B2DHomMatrix::trace() const
    {
        return mpM->doTrace();
    }

    void B2DHomMatrix::transpose()
    {
        implPrepareChange();
        mpM->doTranspose();
    }

    B2DHomMatrix& B2DHomMatrix::operator+=(const B2DHomMatrix& rMat)
    {
        implPrepareChange();
        mpM->doAddMatrix(*rMat.mpM);

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator-=(const B2DHomMatrix& rMat)
    {
        implPrepareChange();
        mpM->doSubMatrix(*rMat.mpM);

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator*=(double fValue)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fValue))
        {
            implPrepareChange();
            mpM->doMulMatrix(fValue);
        }

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator/=(double fValue)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fValue))
        {
            implPrepareChange();
            mpM->doMulMatrix(1.0 / fValue);
        }

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator*=(const B2DHomMatrix& rMat)
    {
        if(!rMat.isIdentity())
        {
            implPrepareChange();
            mpM->doMulMatrix(*rMat.mpM);
        }

        return *this;
    }

    bool B2DHomMatrix::operator==(const B2DHomMatrix& rMat) const
    {
        if(mpM == rMat.mpM)
            return true;

        return mpM->isEqual(*rMat.mpM);
    }

    bool B2DHomMatrix::operator!=(const B2DHomMatrix& rMat) const
    {
        if(mpM == rMat.mpM)
            return false;

        return !mpM->isEqual(*rMat.mpM);
    }

    void B2DHomMatrix::rotate(double fRadiant)
    {
        if(!::basegfx::fTools::equalZero(fRadiant))
        {
            double fSin;
            double fCos;

            // is the rotation angle an approximate multiple of pi/2?
            // If yes, force fSin/fCos to -1/0/1, to maintain
            // orthogonality (which might also be advantageous for the
            // other cases, but: for multiples of pi/2, the exact
            // values _can_ be attained. It would be largely
            // unintuitive, if a 180 degrees rotation would introduce
            // slight roundoff errors, instead of exactly mirroring
            // the coordinate system).
            if( fTools::equalZero( fmod( fRadiant, F_PI2 ) ) )
            {
                // determine quadrant
                const sal_Int32 nQuad(
                    (4 + fround( 4/F_2PI*fmod( fRadiant, F_2PI ) )) % 4 );
                switch( nQuad )
                {
                    case 0: // -2pi,0,2pi
                        fSin = 0.0;
                        fCos = 1.0;
                        break;

                    case 1: // -3/2pi,1/2pi
                        fSin = 1.0;
                        fCos = 0.0;
                        break;

                    case 2: // -pi,pi
                        fSin = 0.0;
                        fCos = -1.0;
                        break;

                    case 3: // -1/2pi,3/2pi
                        fSin = -1.0;
                        fCos = 0.0;
                        break;

                    default:
                        OSL_ENSURE( false,
                                    "B2DHomMatrix::rotate(): Impossible case reached" );
                }
            }
            else
            {
                fSin = sin(fRadiant);
                fCos = cos(fRadiant);
            }

            Impl2DHomMatrix aRotMat(get2DIdentityMatrix());

            aRotMat.set(0, 0, fCos);
            aRotMat.set(1, 1, fCos);
            aRotMat.set(1, 0, fSin);
            aRotMat.set(0, 1, -fSin);

            implPrepareChange();
            mpM->doMulMatrix(aRotMat);
        }
    }

    void B2DHomMatrix::translate(double fX, double fY)
    {
        if(!::basegfx::fTools::equalZero(fX) || !::basegfx::fTools::equalZero(fY))
        {
            Impl2DHomMatrix aTransMat(get2DIdentityMatrix());

            aTransMat.set(0, 2, fX);
            aTransMat.set(1, 2, fY);

            implPrepareChange();
            mpM->doMulMatrix(aTransMat);
        }
    }

    void B2DHomMatrix::scale(double fX, double fY)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fX) || !::basegfx::fTools::equal(fOne, fY))
        {
            Impl2DHomMatrix aScaleMat(get2DIdentityMatrix());

            aScaleMat.set(0, 0, fX);
            aScaleMat.set(1, 1, fY);

            implPrepareChange();
            mpM->doMulMatrix(aScaleMat);
        }
    }

    void B2DHomMatrix::shearX(double fSx)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fSx))
        {
            Impl2DHomMatrix aShearXMat(get2DIdentityMatrix());

            aShearXMat.set(0, 1, fSx);

            implPrepareChange();
            mpM->doMulMatrix(aShearXMat);
        }
    }

    void B2DHomMatrix::shearY(double fSy)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fSy))
        {
            Impl2DHomMatrix aShearYMat(get2DIdentityMatrix());

            aShearYMat.set(1, 0, fSy);

            implPrepareChange();
            mpM->doMulMatrix(aShearYMat);
        }
    }

    // Decomposition
    bool B2DHomMatrix::decompose(B2DTuple& rScale, B2DTuple& rTranslate, double& rRotate, double& rShearX) const
    {
        // when perspective is used, decompose is not made here
        if(!mpM->isLastLineDefault())
            return false;

        // If determinant is zero, decomposition is not possible
        if(0.0 == mpM->doDeterminant())
            return false;

        // copy 2x2 matrix and translate vector to 3x3 matrix
        ::basegfx::B3DHomMatrix a3DHomMat;

        a3DHomMat.set(0, 0, get(0, 0));
        a3DHomMat.set(0, 1, get(0, 1));
        a3DHomMat.set(1, 0, get(1, 0));
        a3DHomMat.set(1, 1, get(1, 1));
        a3DHomMat.set(0, 3, get(0, 2));
        a3DHomMat.set(1, 3, get(1, 2));

        ::basegfx::B3DTuple r3DScale, r3DTranslate, r3DRotate, r3DShear;

        if(a3DHomMat.decompose(r3DScale, r3DTranslate, r3DRotate, r3DShear))
        {
            // copy scale values
            rScale.setX(r3DScale.getX());
            rScale.setY(r3DScale.getY());

            // copy shear
            rShearX = r3DShear.getX();

            // copy rotate
            rRotate = r3DRotate.getZ();

            // copy translate
            rTranslate.setX(r3DTranslate.getX());
            rTranslate.setY(r3DTranslate.getY());

            return true;
        }

        return false;
    }
} // end of namespace basegfx

// eof
<|endoftext|>


<commit_before>// LAF OS Library
// Copyright (C) 2018  David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "base/memory.h"
#include "gfx/size.h"
#include "os/system.h"

namespace os {

class NoneSystem : public System {
public:
  void dispose() override { delete this; }
  void activateApp() override { }
  void finishLaunching() override { }
  Capabilities capabilities() const override { return (Capabilities)0; }
  void useWintabAPI(bool enable) override { }
  Logger* logger() override { return nullptr; }
  Menus* menus() override { return nullptr; }
  NativeDialogs* nativeDialogs() override { return nullptr; }
  EventQueue* eventQueue() override { return nullptr; }
  bool gpuAcceleration() const override { return false; }
  void setGpuAcceleration(bool state) override { }
  gfx::Size defaultNewDisplaySize() override { return gfx::Size(0, 0); }
  Display* defaultDisplay() override { return nullptr; }
  Display* createDisplay(int width, int height, int scale) override { return nullptr; }
  Surface* createSurface(int width, int height) override { return nullptr; }
  Surface* createRgbaSurface(int width, int height) override { return nullptr; }
  Surface* loadSurface(const char* filename) override { return nullptr; }
  Surface* loadRgbaSurface(const char* filename) override { return nullptr; }
  Font* loadSpriteSheetFont(const char* filename, int scale) override { return nullptr; }
  Font* loadTrueTypeFont(const char* filename, int height) override { return nullptr; }
  bool isKeyPressed(KeyScancode scancode) override { return false; }
  KeyModifiers keyModifiers() override { return kKeyNoneModifier; }
  int getUnicodeFromScancode(KeyScancode scancode) override { return 0; }
  void setTranslateDeadKeys(bool state) override { }
};

System* create_system_impl() {
  return new NoneSystem;
}

void error_message(const char* msg)
{
  fputs(msg, stderr);
  // TODO
}

} // namespace os

extern int app_main(int argc, char* argv[]);

#if _WIN32
int wmain(int argc, wchar_t* wargv[], wchar_t* envp[]) {
  char** argv;
  if (wargv && argc > 0) {
    argv = new char*[argc];
    for (int i=0; i<argc; ++i)
      argv[i] = base_strdup(base::to_utf8(std::wstring(wargv[i])).c_str());
  }
  else {
    argv = new char*[1];
    argv[0] = base_strdup("");
    argc = 1;
  }
#else
int main(int argc, char* argv[]) {
#endif
  return app_main(argc, argv);
}
<commit_msg>base/string.h is required to use base::utf_8()<commit_after>// LAF OS Library
// Copyright (C) 2018  David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "base/memory.h"
#include "base/string.h"
#include "gfx/size.h"
#include "os/system.h"

namespace os {

class NoneSystem : public System {
public:
  void dispose() override { delete this; }
  void activateApp() override { }
  void finishLaunching() override { }
  Capabilities capabilities() const override { return (Capabilities)0; }
  void useWintabAPI(bool enable) override { }
  Logger* logger() override { return nullptr; }
  Menus* menus() override { return nullptr; }
  NativeDialogs* nativeDialogs() override { return nullptr; }
  EventQueue* eventQueue() override { return nullptr; }
  bool gpuAcceleration() const override { return false; }
  void setGpuAcceleration(bool state) override { }
  gfx::Size defaultNewDisplaySize() override { return gfx::Size(0, 0); }
  Display* defaultDisplay() override { return nullptr; }
  Display* createDisplay(int width, int height, int scale) override { return nullptr; }
  Surface* createSurface(int width, int height) override { return nullptr; }
  Surface* createRgbaSurface(int width, int height) override { return nullptr; }
  Surface* loadSurface(const char* filename) override { return nullptr; }
  Surface* loadRgbaSurface(const char* filename) override { return nullptr; }
  Font* loadSpriteSheetFont(const char* filename, int scale) override { return nullptr; }
  Font* loadTrueTypeFont(const char* filename, int height) override { return nullptr; }
  bool isKeyPressed(KeyScancode scancode) override { return false; }
  KeyModifiers keyModifiers() override { return kKeyNoneModifier; }
  int getUnicodeFromScancode(KeyScancode scancode) override { return 0; }
  void setTranslateDeadKeys(bool state) override { }
};

System* create_system_impl() {
  return new NoneSystem;
}

void error_message(const char* msg)
{
  fputs(msg, stderr);
  // TODO
}

} // namespace os

extern int app_main(int argc, char* argv[]);

#if _WIN32
int wmain(int argc, wchar_t* wargv[], wchar_t* envp[]) {
  char** argv;
  if (wargv && argc > 0) {
    argv = new char*[argc];
    for (int i=0; i<argc; ++i)
      argv[i] = base_strdup(base::to_utf8(std::wstring(wargv[i])).c_str());
  }
  else {
    argv = new char*[1];
    argv[0] = base_strdup("");
    argc = 1;
  }
#else
int main(int argc, char* argv[]) {
#endif
  return app_main(argc, argv);
}
<|endoftext|>


<commit_before>/***********************************************************************************************************************
 * Copyright (C) 2016 Andrew Zonenberg and contributors                                                                *
 *                                                                                *
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General   *
 * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) *
 * any later version.                                                                                *
 *                                                                                *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied  *
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for     *
 * more details.                                                                                *
 *                                                                                *
 * You should have received a copy of the GNU Lesser General Public License along with this program; if not, you may   *
 * find one here:                                                                                *
 * https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt                                                              *
 * or you may search the http://www.gnu.org website for the version 2.1 license, or you may write to the Free Software *
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA                                      *
 **********************************************************************************************************************/

#include <string.h>
#include "gp4prog.h"

using namespace std;

void ShowUsage();
void ShowVersion();

vector<uint8_t> ReadBitstream(string fname);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Entry point

int main(int argc, char* argv[])
{
	LogSink::Severity console_verbosity = LogSink::NOTICE;

	bool reset = false;
	string fname;
	double voltage = 0.0;
	vector<int> nets;

	//Parse command-line arguments
	for(int i=1; i<argc; i++)
	{
		string s(argv[i]);

		if(s == "--help")
		{
			ShowUsage();
			return 0;
		}
		else if(s == "--version")
		{
			ShowVersion();
			return 0;
		}
		else if(s == "--verbose")
		{
			console_verbosity = LogSink::VERBOSE;
		}
		else if(s == "-q" || s == "--quiet")
		{
			if(console_verbosity == LogSink::NOTICE)
				console_verbosity = LogSink::WARNING;
			else if(console_verbosity == LogSink::WARNING)
				console_verbosity = LogSink::ERROR;
		}
		else if(s == "-r" || s == "--reset")
		{
			reset = true;
		}
		else if(s == "-e" || s == "--emulate")
		{
			if(i+1 < argc)
			{
				fname = argv[++i];
			}
			else
			{
				printf("--nets requires an argument\n");
				return 1;
			}
		}
		else if(s == "-v" || s == "--voltage")
		{
			if(i+1 < argc)
			{
				char *endptr;
				voltage = strtod(argv[++i], &endptr);
				if(*endptr)
				{
					printf("--voltage must be a decimal value\n");
					return 1;
				}
				if(!(voltage == 0.0 || (voltage >= 1.71 && voltage <= 5.5)))
				{
					printf("--voltage %.3g outside of valid range\n", voltage);
					return 1;
				}
			}
			else
			{
				printf("--voltage requires an argument\n");
				return 1;
			}
		}
		else if(s == "-n" || s == "--nets")
		{
			if(i+1 < argc)
			{
				char *arg = argv[++i];
				do {
					long net = strtol(arg, &arg, 10);
					if(*arg && *arg != ',')
					{
						printf("--nets must be a comma-separate list of net numbers\n");
						return 1;
					}
					if(net < 1 || net > 20 || net == 11)
					{
						printf("--nets used with an invalid net %ld\n", net);
						return 1;
					}
					nets.push_back(net);
				} while(*arg++);
			}
			else
			{
				printf("--nets requires an argument\n");
				return 1;
			}
		}

		//assume it's the bitstream file if it's the first non-switch argument
		else if( (s[0] != '-') && (fname == "") )
		{
			fname = s;
		}

		else
		{
			printf("Unrecognized command-line argument \"%s\", use --help\n", s.c_str());
			return 1;
		}
	}

	//Set up logging
	g_log_sinks.emplace(g_log_sinks.begin(), new STDLogSink(console_verbosity));

	//Print header
	if(console_verbosity >= LogSink::NOTICE)
		ShowVersion();

	//Set up libusb
	USBSetup();

	// Try opening the board in "orange" mode
	LogNotice("\nSearching for developer board\n");
	hdevice hdev = OpenDevice(0x0f0f, 0x0006);
	if(!hdev) {
		// Try opening the board in "white" mode
 		hdev = OpenDevice(0x0f0f, 0x8006);
		if(!hdev) {
			LogError("No device found, giving up\n");
			return 1;
		}

		// Change the board into "orange" mode
		LogVerbose("Switching developer board from bootloader mode\n");
		SwitchMode(hdev);

		// Takes a while to switch and re-enumerate
		usleep(1200 * 1000);

		// Try opening the board in "orange" mode again
		hdev = OpenDevice(0x0f0f, 0x0006);
		if(!hdev) {
			LogError("Could not switch mode, giving up\n");
			return 1;
		}
	}

	//Get string descriptors
	string name = GetStringDescriptor(hdev, 1);			//board name
	string vendor = GetStringDescriptor(hdev, 2);		//manufacturer
	LogNotice("Found: %s %s\n", vendor.c_str(), name.c_str());
	//string 0x80 is 02 03 for this board... what does that mean? firmware rev or something?
	//it's read by emulator during startup but no "2" and "3" are printed anywhere...

	//If we're run with no bitstream and no reset flag, stop now without changing board configuration
	if(fname.empty() && voltage == 0.0 && nets.empty() && !reset)
	{
		LogNotice("No actions requested, exiting\n");
		return 0;
	}

	//Light up the status LED
	SetStatusLED(hdev, 1);

	//Select part (no other parts supported yet).
	//TODO: see if we can enumerate what's plugged in / check the bitstream supplied
	LogNotice("Selecting part SLG46620V\n");
	SetPart(hdev, SLG46620V);

	//If we're resetting, do just that
	if(reset)
	{
		LogNotice("Resetting board I/O and signal generators\n");
		IOConfig config;
		SetIOConfig(hdev, config);
		ResetAllSiggens(hdev);
	}

	//If we're programming, do that first
	if(!fname.empty())
	{
		vector<uint8_t> bitstream;
		bitstream = ReadBitstream(fname);
		if(bitstream.empty())
			return 1;

		//Load bitstream
		LogNotice("Loading bitstream into SRAM\n");
		LoadBitstream(hdev, bitstream);
	}

	if(voltage != 0.0)
	{
		//Configure the signal generator for Vdd
		LogNotice("Setting Vdd=%.3gV\n", voltage);
		ConfigureSiggen(hdev, 1, voltage);
		SetSiggenStatus(hdev, 1, SIGGEN_START);
	}

	if(!nets.empty())
	{
		//Set the I/O configuration on the test points
		//Expects a bitstream that does assign TP4=TP3;
		LogNotice("Setting I/O configuration\n");
		IOConfig config;
		for(int net : nets)
		{
			// Note: for unknown reasons, the net has to be driven (e.g. weakly) for the LED to become active.
			// For unknown reasons, the vendor tool does not seem to suffer from this issue, and it
			// lets the LED light up even with all pins as TP_FLOAT.
			config.driverConfigs[net] = TP_PULLDOWN;
			config.ledEnabled[net] = true;
			config.expansionEnabled[net] = true;
		}
		SetIOConfig(hdev, config);
	}

	//Done
	LogNotice("Done\n");
	SetStatusLED(hdev, 0);

	USBCleanup(hdev);
	return 0;
}

void ShowUsage()
{
	printf(//                                                                               v 80th column
		"Usage: gp4prog bitstream.txt\n"
		"    When run with no arguments, scans for the board but makes no config changes.\n"
		"    -q, --quiet\n"
		"        Causes only warnings and errors to be written to the console.\n"
		"        Specify twice to also silence warnings.\n"
		"\n"
		"    The following options are instructions for the developer board. They are\n"
		"    executed in the order listed here, regardless of their order on command line.\n"
		"    -r, --reset\n"
		"        Resets the board:\n"
		"          * disables every LED;\n"
		"          * disables every expansion connector passthrough;\n"
		"          * disables Vdd supply.\n"
		"    -e, --emulate        <bitstream>\n"
		"        Downloads the specified bitstream into volatile memory.\n"
		"        Implies --reset --voltage 3.3.\n"
		"    -v, --voltage        <voltage>\n"
		"        Adjusts Vdd to the specified value in volts (0V to 5.5V), ±70mV.\n"
		"    -n, --nets           <nets>\n"
		"        For every test point in the specified comma-separated list:\n"
		"          * enables a non-inverted LED, if any;\n"
		"          * enables expansion connector passthrough.\n");
}

void ShowVersion()
{
	printf(
		"Greenpak4 programmer by Andrew D. Zonenberg and whitequark.\n"
		"\n"
		"License: LGPL v2.1+\n"
		"This is free software: you are free to change and redistribute it.\n"
		"There is NO WARRANTY, to the extent permitted by law.\n");
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Bitstream reader

vector<uint8_t> ReadBitstream(string fname)
{
	//Open the file
	FILE* fp = fopen(fname.c_str(), "r");
	if(!fp)
	{
		LogError("Couldn't open %s for reading\n", fname.c_str());
		return {};
	}

	char signature[64];
	fgets(signature, sizeof(signature), fp);
	if(strcmp(signature, "index\t\tvalue\t\tcomment\n"))
	{
		LogError("%s is not a GreenPAK bitstream", fname.c_str());
		return {};
	}

	vector<uint8_t> bitstream;
	while(!feof(fp))
	{
		int index;
		int value;
		fscanf(fp, "%d\t\t%d\t\t//\n", &index, &value);

		int byteindex = index / 8;
		if(byteindex < 0 || (value != 0 && value != 1))
		{
			LogError("%s contains a malformed GreenPAK bitstream\n", fname.c_str());
			return {};
		}

		if(byteindex >= (int)bitstream.size())
			bitstream.resize(byteindex + 1, 0);
		bitstream[byteindex] |= (value << (index % 8));
	}

	fclose(fp);

	return bitstream;
}
<commit_msg>gp4prog: documented --verbose flag<commit_after>/***********************************************************************************************************************
 * Copyright (C) 2016 Andrew Zonenberg and contributors                                                                *
 *                                                                                *
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General   *
 * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) *
 * any later version.                                                                                *
 *                                                                                *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied  *
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for     *
 * more details.                                                                                *
 *                                                                                *
 * You should have received a copy of the GNU Lesser General Public License along with this program; if not, you may   *
 * find one here:                                                                                *
 * https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt                                                              *
 * or you may search the http://www.gnu.org website for the version 2.1 license, or you may write to the Free Software *
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA                                      *
 **********************************************************************************************************************/

#include <string.h>
#include "gp4prog.h"

using namespace std;

void ShowUsage();
void ShowVersion();

vector<uint8_t> ReadBitstream(string fname);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Entry point

int main(int argc, char* argv[])
{
	LogSink::Severity console_verbosity = LogSink::NOTICE;

	bool reset = false;
	string fname;
	double voltage = 0.0;
	vector<int> nets;

	//Parse command-line arguments
	for(int i=1; i<argc; i++)
	{
		string s(argv[i]);

		if(s == "--help")
		{
			ShowUsage();
			return 0;
		}
		else if(s == "--version")
		{
			ShowVersion();
			return 0;
		}
		else if(s == "--verbose")
		{
			console_verbosity = LogSink::VERBOSE;
		}
		else if(s == "-q" || s == "--quiet")
		{
			if(console_verbosity == LogSink::NOTICE)
				console_verbosity = LogSink::WARNING;
			else if(console_verbosity == LogSink::WARNING)
				console_verbosity = LogSink::ERROR;
		}
		else if(s == "-r" || s == "--reset")
		{
			reset = true;
		}
		else if(s == "-e" || s == "--emulate")
		{
			if(i+1 < argc)
			{
				fname = argv[++i];
			}
			else
			{
				printf("--nets requires an argument\n");
				return 1;
			}
		}
		else if(s == "-v" || s == "--voltage")
		{
			if(i+1 < argc)
			{
				char *endptr;
				voltage = strtod(argv[++i], &endptr);
				if(*endptr)
				{
					printf("--voltage must be a decimal value\n");
					return 1;
				}
				if(!(voltage == 0.0 || (voltage >= 1.71 && voltage <= 5.5)))
				{
					printf("--voltage %.3g outside of valid range\n", voltage);
					return 1;
				}
			}
			else
			{
				printf("--voltage requires an argument\n");
				return 1;
			}
		}
		else if(s == "-n" || s == "--nets")
		{
			if(i+1 < argc)
			{
				char *arg = argv[++i];
				do {
					long net = strtol(arg, &arg, 10);
					if(*arg && *arg != ',')
					{
						printf("--nets must be a comma-separate list of net numbers\n");
						return 1;
					}
					if(net < 1 || net > 20 || net == 11)
					{
						printf("--nets used with an invalid net %ld\n", net);
						return 1;
					}
					nets.push_back(net);
				} while(*arg++);
			}
			else
			{
				printf("--nets requires an argument\n");
				return 1;
			}
		}

		//assume it's the bitstream file if it's the first non-switch argument
		else if( (s[0] != '-') && (fname == "") )
		{
			fname = s;
		}

		else
		{
			printf("Unrecognized command-line argument \"%s\", use --help\n", s.c_str());
			return 1;
		}
	}

	//Set up logging
	g_log_sinks.emplace(g_log_sinks.begin(), new STDLogSink(console_verbosity));

	//Print header
	if(console_verbosity >= LogSink::NOTICE)
		ShowVersion();

	//Set up libusb
	USBSetup();

	// Try opening the board in "orange" mode
	LogNotice("\nSearching for developer board\n");
	hdevice hdev = OpenDevice(0x0f0f, 0x0006);
	if(!hdev) {
		// Try opening the board in "white" mode
 		hdev = OpenDevice(0x0f0f, 0x8006);
		if(!hdev) {
			LogError("No device found, giving up\n");
			return 1;
		}

		// Change the board into "orange" mode
		LogVerbose("Switching developer board from bootloader mode\n");
		SwitchMode(hdev);

		// Takes a while to switch and re-enumerate
		usleep(1200 * 1000);

		// Try opening the board in "orange" mode again
		hdev = OpenDevice(0x0f0f, 0x0006);
		if(!hdev) {
			LogError("Could not switch mode, giving up\n");
			return 1;
		}
	}

	//Get string descriptors
	string name = GetStringDescriptor(hdev, 1);			//board name
	string vendor = GetStringDescriptor(hdev, 2);		//manufacturer
	LogNotice("Found: %s %s\n", vendor.c_str(), name.c_str());
	//string 0x80 is 02 03 for this board... what does that mean? firmware rev or something?
	//it's read by emulator during startup but no "2" and "3" are printed anywhere...

	//If we're run with no bitstream and no reset flag, stop now without changing board configuration
	if(fname.empty() && voltage == 0.0 && nets.empty() && !reset)
	{
		LogNotice("No actions requested, exiting\n");
		return 0;
	}

	//Light up the status LED
	SetStatusLED(hdev, 1);

	//Select part (no other parts supported yet).
	//TODO: see if we can enumerate what's plugged in / check the bitstream supplied
	LogNotice("Selecting part SLG46620V\n");
	SetPart(hdev, SLG46620V);

	//If we're resetting, do just that
	if(reset)
	{
		LogNotice("Resetting board I/O and signal generators\n");
		IOConfig config;
		SetIOConfig(hdev, config);
		ResetAllSiggens(hdev);
	}

	//If we're programming, do that first
	if(!fname.empty())
	{
		vector<uint8_t> bitstream;
		bitstream = ReadBitstream(fname);
		if(bitstream.empty())
			return 1;

		//Load bitstream
		LogNotice("Loading bitstream into SRAM\n");
		LoadBitstream(hdev, bitstream);
	}

	if(voltage != 0.0)
	{
		//Configure the signal generator for Vdd
		LogNotice("Setting Vdd=%.3gV\n", voltage);
		ConfigureSiggen(hdev, 1, voltage);
		SetSiggenStatus(hdev, 1, SIGGEN_START);
	}

	if(!nets.empty())
	{
		//Set the I/O configuration on the test points
		//Expects a bitstream that does assign TP4=TP3;
		LogNotice("Setting I/O configuration\n");
		IOConfig config;
		for(int net : nets)
		{
			// Note: for unknown reasons, the net has to be driven (e.g. weakly) for the LED to become active.
			// For unknown reasons, the vendor tool does not seem to suffer from this issue, and it
			// lets the LED light up even with all pins as TP_FLOAT.
			config.driverConfigs[net] = TP_PULLDOWN;
			config.ledEnabled[net] = true;
			config.expansionEnabled[net] = true;
		}
		SetIOConfig(hdev, config);
	}

	//Done
	LogNotice("Done\n");
	SetStatusLED(hdev, 0);

	USBCleanup(hdev);
	return 0;
}

void ShowUsage()
{
	printf(//                                                                               v 80th column
		"Usage: gp4prog bitstream.txt\n"
		"    When run with no arguments, scans for the board but makes no config changes.\n"
		"    -q, --quiet\n"
		"        Causes only warnings and errors to be written to the console.\n"
		"        Specify twice to also silence warnings.\n"
		"    --verbose\n"
		"        Print lots of verbose debug information\n"
		"\n"
		"    The following options are instructions for the developer board. They are\n"
		"    executed in the order listed here, regardless of their order on command line.\n"
		"    -r, --reset\n"
		"        Resets the board:\n"
		"          * disables every LED;\n"
		"          * disables every expansion connector passthrough;\n"
		"          * disables Vdd supply.\n"
		"    -e, --emulate        <bitstream>\n"
		"        Downloads the specified bitstream into volatile memory.\n"
		"        Implies --reset --voltage 3.3.\n"
		"    -v, --voltage        <voltage>\n"
		"        Adjusts Vdd to the specified value in volts (0V to 5.5V), ±70mV.\n"
		"    -n, --nets           <nets>\n"
		"        For every test point in the specified comma-separated list:\n"
		"          * enables a non-inverted LED, if any;\n"
		"          * enables expansion connector passthrough.\n");
}

void ShowVersion()
{
	printf(
		"Greenpak4 programmer by Andrew D. Zonenberg and whitequark.\n"
		"\n"
		"License: LGPL v2.1+\n"
		"This is free software: you are free to change and redistribute it.\n"
		"There is NO WARRANTY, to the extent permitted by law.\n");
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Bitstream reader

vector<uint8_t> ReadBitstream(string fname)
{
	//Open the file
	FILE* fp = fopen(fname.c_str(), "r");
	if(!fp)
	{
		LogError("Couldn't open %s for reading\n", fname.c_str());
		return {};
	}

	char signature[64];
	fgets(signature, sizeof(signature), fp);
	if(strcmp(signature, "index\t\tvalue\t\tcomment\n"))
	{
		LogError("%s is not a GreenPAK bitstream", fname.c_str());
		return {};
	}

	vector<uint8_t> bitstream;
	while(!feof(fp))
	{
		int index;
		int value;
		fscanf(fp, "%d\t\t%d\t\t//\n", &index, &value);

		int byteindex = index / 8;
		if(byteindex < 0 || (value != 0 && value != 1))
		{
			LogError("%s contains a malformed GreenPAK bitstream\n", fname.c_str());
			return {};
		}

		if(byteindex >= (int)bitstream.size())
			bitstream.resize(byteindex + 1, 0);
		bitstream[byteindex] |= (value << (index % 8));
	}

	fclose(fp);

	return bitstream;
}
<|endoftext|>


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

#include "tcambin_tcamprop_impl.h"

#include "tcambin_data.h"
#include "tcamgstbase/tcamprop_helper.h"

#include <algorithm>
#include <gst-helper/gst_gvalue_helper.h>
#include <tcamprop1.0_consumer/tcamprop1_consumer.h>
#include <tcamprop1.0_gobject/tcam_gerror.h>
#include <tcamprop1.0_gobject/tcam_property_provider.h>
#include <tcamprop1.0_gobject/tcam_property_provider_simple_functions.h>

static GSList* gst_tcambin_get_tcam_property_names(TcamPropertyProvider* iface, GError** err)
{
    tcambin_data& self = *GST_TCAMBIN(iface)->data;

    if (self.src == nullptr)
    {
        tcamprop1_gobj::set_gerror(err, tcamprop1::status::device_not_opened);
        return nullptr;
    }

    std::vector<std::string> convert_name_list;
    // if dutils(-cuda) is present then first fetch the names from that
    // tcamconvert does not offer properties
    if (self.tcam_converter && TCAM_IS_PROPERTY_PROVIDER(self.tcam_converter))
    {
        convert_name_list = tcamprop1_consumer::get_property_names_noerror(
            TCAM_PROPERTY_PROVIDER(self.tcam_converter));
    }
    auto src_prop_list_res =
        tcamprop1_consumer::get_property_names(TCAM_PROPERTY_PROVIDER(self.src));
    if (src_prop_list_res.has_error())
    {
        tcamprop1_gobj::set_gerror(err, src_prop_list_res.error());
        return nullptr;
    }

    // merge both list;
    if (convert_name_list.empty())
    {
        return gst_helper::gst_string_vector_to_GSList(src_prop_list_res.value());
    }

    auto& merged_prop_list = src_prop_list_res.value();
    merged_prop_list.insert(
        merged_prop_list.end(), convert_name_list.begin(), convert_name_list.end());

    std::sort(merged_prop_list.begin(), merged_prop_list.end());
    merged_prop_list.erase(std::unique(merged_prop_list.begin(), merged_prop_list.end()),
                           merged_prop_list.end());

    return gst_helper::gst_string_vector_to_GSList(merged_prop_list);
}

static TcamPropertyBase* gst_tcambin_get_tcam_property(TcamPropertyProvider* iface,
                                                       const char* name,
                                                       GError** err)
{
    tcambin_data& self = *GST_TCAMBIN(iface)->data;

    if (name == nullptr)
    {
        tcamprop1_gobj::set_gerror(err, tcamprop1::status::parameter_null);
        return nullptr;
    }

    if (self.src == nullptr)
    {
        tcamprop1_gobj::set_gerror(err, tcamprop1::status::device_not_opened);
        return nullptr;
    }

    if (self.tcam_converter)
    {
        auto res = tcam_property_provider_get_tcam_property(
            TCAM_PROPERTY_PROVIDER(self.tcam_converter), name, nullptr);
        if (res)
        {
            return res;
        }
    }

    return tcam_property_provider_get_tcam_property(TCAM_PROPERTY_PROVIDER(self.src), name, err);
}

void tcam::gst::bin::gst_tcambin_tcamprop_init(TcamPropertyProviderInterface* iface)
{
    iface->get_tcam_property_names = gst_tcambin_get_tcam_property_names;
    iface->get_tcam_property = gst_tcambin_get_tcam_property;

    iface->set_tcam_boolean = tcamprop1_gobj::provider_set_tcam_boolean;
    iface->set_tcam_integer = tcamprop1_gobj::provider_set_tcam_integer;
    iface->set_tcam_float = tcamprop1_gobj::provider_set_tcam_float;
    iface->set_tcam_enumeration = tcamprop1_gobj::provider_set_tcam_enumeration;
    iface->set_tcam_command = tcamprop1_gobj::provider_set_tcam_command;

    iface->get_tcam_boolean = tcamprop1_gobj::provider_get_tcam_boolean;
    iface->get_tcam_integer = tcamprop1_gobj::provider_get_tcam_integer;
    iface->get_tcam_float = tcamprop1_gobj::provider_get_tcam_float;
    iface->get_tcam_enumeration = tcamprop1_gobj::provider_get_tcam_enumeration;
}
<commit_msg>tcambin: Fix bad include<commit_after>/*
 * Copyright 2021 The Imaging Source Europe GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "tcambin_tcamprop_impl.h"

#include "tcambin_data.h"

#include <algorithm>
#include <gst-helper/gst_gvalue_helper.h>
#include <tcamprop1.0_consumer/tcamprop1_consumer.h>
#include <tcamprop1.0_gobject/tcam_gerror.h>
#include <tcamprop1.0_gobject/tcam_property_provider.h>
#include <tcamprop1.0_gobject/tcam_property_provider_simple_functions.h>

static GSList* gst_tcambin_get_tcam_property_names(TcamPropertyProvider* iface, GError** err)
{
    tcambin_data& self = *GST_TCAMBIN(iface)->data;

    if (self.src == nullptr)
    {
        tcamprop1_gobj::set_gerror(err, tcamprop1::status::device_not_opened);
        return nullptr;
    }

    std::vector<std::string> convert_name_list;
    // if dutils(-cuda) is present then first fetch the names from that
    // tcamconvert does not offer properties
    if (self.tcam_converter && TCAM_IS_PROPERTY_PROVIDER(self.tcam_converter))
    {
        convert_name_list = tcamprop1_consumer::get_property_names_noerror(
            TCAM_PROPERTY_PROVIDER(self.tcam_converter));
    }
    auto src_prop_list_res =
        tcamprop1_consumer::get_property_names(TCAM_PROPERTY_PROVIDER(self.src));
    if (src_prop_list_res.has_error())
    {
        tcamprop1_gobj::set_gerror(err, src_prop_list_res.error());
        return nullptr;
    }

    // merge both list;
    if (convert_name_list.empty())
    {
        return gst_helper::gst_string_vector_to_GSList(src_prop_list_res.value());
    }

    auto& merged_prop_list = src_prop_list_res.value();
    merged_prop_list.insert(
        merged_prop_list.end(), convert_name_list.begin(), convert_name_list.end());

    std::sort(merged_prop_list.begin(), merged_prop_list.end());
    merged_prop_list.erase(std::unique(merged_prop_list.begin(), merged_prop_list.end()),
                           merged_prop_list.end());

    return gst_helper::gst_string_vector_to_GSList(merged_prop_list);
}

static TcamPropertyBase* gst_tcambin_get_tcam_property(TcamPropertyProvider* iface,
                                                       const char* name,
                                                       GError** err)
{
    tcambin_data& self = *GST_TCAMBIN(iface)->data;

    if (name == nullptr)
    {
        tcamprop1_gobj::set_gerror(err, tcamprop1::status::parameter_null);
        return nullptr;
    }

    if (self.src == nullptr)
    {
        tcamprop1_gobj::set_gerror(err, tcamprop1::status::device_not_opened);
        return nullptr;
    }

    if (self.tcam_converter)
    {
        auto res = tcam_property_provider_get_tcam_property(
            TCAM_PROPERTY_PROVIDER(self.tcam_converter), name, nullptr);
        if (res)
        {
            return res;
        }
    }

    return tcam_property_provider_get_tcam_property(TCAM_PROPERTY_PROVIDER(self.src), name, err);
}

void tcam::gst::bin::gst_tcambin_tcamprop_init(TcamPropertyProviderInterface* iface)
{
    iface->get_tcam_property_names = gst_tcambin_get_tcam_property_names;
    iface->get_tcam_property = gst_tcambin_get_tcam_property;

    iface->set_tcam_boolean = tcamprop1_gobj::provider_set_tcam_boolean;
    iface->set_tcam_integer = tcamprop1_gobj::provider_set_tcam_integer;
    iface->set_tcam_float = tcamprop1_gobj::provider_set_tcam_float;
    iface->set_tcam_enumeration = tcamprop1_gobj::provider_set_tcam_enumeration;
    iface->set_tcam_command = tcamprop1_gobj::provider_set_tcam_command;

    iface->get_tcam_boolean = tcamprop1_gobj::provider_get_tcam_boolean;
    iface->get_tcam_integer = tcamprop1_gobj::provider_get_tcam_integer;
    iface->get_tcam_float = tcamprop1_gobj::provider_get_tcam_float;
    iface->get_tcam_enumeration = tcamprop1_gobj::provider_get_tcam_enumeration;
}
<|endoftext|>