<commit_before>#include "gtest/gtest.h"

#include "../../lib/storage/table.hpp"

class StorageTableTest : public ::testing::Test {
 protected:
  virtual void SetUp() {
    t.add_column("col_1", "int");
    t.add_column("col_2", "string");
  }

  opossum::Table t{2};
};

TEST_F(StorageTableTest, HasOneChunkAfterCreation) { EXPECT_EQ(t.chunk_count(), 1u); }

TEST_F(StorageTableTest, AppendToTable) {
  t.append({4, "Hello,"});
  t.append({6, "world"});
  t.append({3, "!"});
}

TEST_F(StorageTableTest, Getters) {
  // test col count
  EXPECT_EQ(t.col_count(), 2u);

  // test row count
  EXPECT_EQ(t.row_count(), 0u);
  t.append({4, "Hello,"});
  t.append({6, "world"});
  t.append({3, "!"});
  EXPECT_EQ(t.row_count(), 3u);

  // test chunk count after append
  EXPECT_EQ(t.chunk_count(), 2u);

  // test get_column*
  EXPECT_EQ(t.get_column_name(0), "col_1");
  EXPECT_EQ(t.get_column_type(0), "int");

  EXPECT_EQ(t.get_column_name(1), "col_2");
  EXPECT_EQ(t.get_column_type(1), "string");

  // TODO(anyone): Do we want checks here?
  // EXPECT_THROW(t.get_column_name(2), std::exception);
  // EXPECT_THROW(t.get_column_type(2), std::exception);

  EXPECT_EQ(t.get_column_id_by_name("col_2"), 1u);

  EXPECT_THROW(t.get_column_id_by_name("no_column_name"), std::exception);

  // test get_chunk_size
  EXPECT_EQ(t.get_chunk_size(), 2u);
}
<commit_msg>Splitted up StorageTableTest into multiple testcases<commit_after>#include "gtest/gtest.h"

#include "../../lib/storage/table.hpp"

class StorageTableTest : public ::testing::Test {
 protected:
  virtual void SetUp() {
    t.add_column("col_1", "int");
    t.add_column("col_2", "string");
  }

  opossum::Table t{2};
};

TEST_F(StorageTableTest, ChunkCount) {
  EXPECT_EQ(t.chunk_count(), 1u);
  t.append({4, "Hello,"});
  t.append({6, "world"});
  t.append({3, "!"});
  EXPECT_EQ(t.chunk_count(), 2u);
}

TEST_F(StorageTableTest, GetChunk) {
  t.get_chunk(0);
  // TODO(anyone): Do we want checks here?
  // EXPECT_THROW(t.get_chunk(1), std::exception);
  t.append({4, "Hello,"});
  t.append({6, "world"});
  t.append({3, "!"});
  t.get_chunk(1);
}

TEST_F(StorageTableTest, ColCount) { EXPECT_EQ(t.col_count(), 2u); }

TEST_F(StorageTableTest, RowCount) {
  EXPECT_EQ(t.row_count(), 0u);
  t.append({4, "Hello,"});
  t.append({6, "world"});
  t.append({3, "!"});
  EXPECT_EQ(t.row_count(), 3u);
}

TEST_F(StorageTableTest, GetColumnName) {
  EXPECT_EQ(t.get_column_name(0), "col_1");
  EXPECT_EQ(t.get_column_name(1), "col_2");
  // TODO(anyone): Do we want checks here?
  // EXPECT_THROW(t.get_column_name(2), std::exception);
}

TEST_F(StorageTableTest, GetColumnType) {
  EXPECT_EQ(t.get_column_type(0), "int");
  EXPECT_EQ(t.get_column_type(1), "string");
  // TODO(anyone): Do we want checks here?
  // EXPECT_THROW(t.get_column_type(2), std::exception);
}

TEST_F(StorageTableTest, GetColumnIdByName) {
  EXPECT_EQ(t.get_column_id_by_name("col_2"), 1u);
  EXPECT_THROW(t.get_column_id_by_name("no_column_name"), std::exception);
}

TEST_F(StorageTableTest, GetChunkSize) { EXPECT_EQ(t.get_chunk_size(), 2u); }
<|endoftext|>


<commit_before>#ifndef HARDWARE_PIN_HPP_
#define HARDWARE_PIN_HPP_

#include "../memory/observer_ptr.hpp"

#include <memory>
#include <type_traits>

struct analog_tag { };
struct digital_tag { };

enum pin_mode_e
{
  pin_output = 0,
  pin_input,
  pin_pullup,
};

extern pin_mode_e mode(int, pin_mode_e);

template<typename /* Tag */, int /* Voltage */, int /* Bits */>
class basic_pin;

template<typename>
struct is_pin : std::false_type { };

template<typename Tag, int Voltage, int Bits>
struct is_pin<basic_pin<Tag, Voltage, Bits>> : std::true_type { };

template<typename Tag, int Voltage, int Bits>
class basic_pin
{
public:
  typedef basic_pin this_type;
  typedef int handle_type;
  typedef Tag tag_type;

public:
  basic_pin(handle_type p)
  : pin_(p)
  { }

  basic_pin(handle_type p, pin_mode_e m)
  : pin_(p)
  { mode(m); }

  handle_type handle() const { return pin_; }

  pin_mode_e mode() const { return mode_; }
  void mode(pin_mode_e m) { mode_ = ::mode(pin_, m); }

  int read()
  {
    return ::read(Tag(), pin_);
  }

  int write(int v)
  {
    return ::write(Tag(), pin_, v);
  }

public:
  friend int read(basic_pin &self)
  {
    return self.read();
  }

  friend int write(basic_pin &self, int v)
  {
    return self.write(v);
  }

private:
  handle_type pin_;
  pin_mode_e mode_;
};

class any_pin
{
public:
  template<typename Pin>
  any_pin(Pin &pin)
  : self_(new holder<Pin>(pin))
  { }

  int read()
  {
    return self_->read();
  }

  int write(int v)
  {
    return self_->write(v);
  }

public:
  friend int read(any_pin &self)
  {
    return self.read();
  }

  friend int write(any_pin &self, int v)
  {
    return self.write(v);
  }

private:
  struct impl
  {
    virtual int read() = 0;
    virtual int write(int) = 0;
  };

  template<typename Pin>
  struct holder : impl
  {
  public:
    holder(cxx::observer_ptr<Pin> ptr)
    : self_(ptr)
    { }

    int read() { return ::read(*self_); }
    int write(int v) { return ::write(*self_, v); }

  private:
    cxx::observer_ptr<Pin> self_;
  };

  std::unique_ptr<impl> self_;
};

#endif
<commit_msg>latest version<commit_after>#ifndef HARDWARE_PIN_HPP_
#define HARDWARE_PIN_HPP_

#include "../memory/observer_ptr.hpp"

#include <memory>
#include <type_traits>

struct analog_tag { };
struct digital_tag { };

enum pin_mode_e
{
  pin_output = 0,
  pin_input,
  pin_pullup,
};

extern pin_mode_e mode(analog_tag, int, pin_mode_e);
extern pin_mode_e mode(digital_tag, int, pin_mode_e);

template<typename /* Tag */, int /* Voltage */, int /* Bits */>
class basic_pin;

template<typename>
struct is_pin : std::false_type { };

template<typename Tag, int Voltage, int Bits>
struct is_pin<basic_pin<Tag, Voltage, Bits>> : std::true_type { };

template<typename Tag, int Voltage, int Bits>
class basic_pin
{
public:
  typedef basic_pin this_type;
  typedef int handle_type;
  typedef Tag tag_type;

public:
  basic_pin(handle_type p)
  : pin_(p)
  { }

  basic_pin(handle_type p, pin_mode_e m)
  : pin_(p)
  { mode(m); }

  handle_type handle() const { return pin_; }

  pin_mode_e mode() const { return mode_; }
  void mode(pin_mode_e m) { mode_ = ::mode(Tag(), pin_, m); }

  int read()
  {
    return ::read(Tag(), pin_);
  }

  int write(int v)
  {
    return ::write(Tag(), pin_, v);
  }

public:
  friend int read(basic_pin &self)
  {
    return self.read();
  }

  friend int write(basic_pin &self, int v)
  {
    return self.write(v);
  }

private:
  handle_type pin_;
  pin_mode_e mode_;
};

class any_pin
{
public:
  template<typename Pin>
  any_pin(Pin &pin)
  : self_(new holder<Pin>(pin))
  { }

  int read()
  {
    return self_->read();
  }

  int write(int v)
  {
    return self_->write(v);
  }

public:
  friend int read(any_pin &self)
  {
    return self.read();
  }

  friend int write(any_pin &self, int v)
  {
    return self.write(v);
  }

private:
  struct impl
  {
    virtual int read() = 0;
    virtual int write(int) = 0;
  };

  template<typename Pin>
  struct holder : impl
  {
  public:
    holder(cxx::observer_ptr<Pin> ptr)
    : self_(ptr)
    { }

    int read() { return ::read(*self_); }
    int write(int v) { return ::write(*self_, v); }

  private:
    cxx::observer_ptr<Pin> self_;
  };

  std::unique_ptr<impl> self_;
};

#endif
<|endoftext|>


<commit_before>/*
 * copyright (C) 2011 The Android Open Source Project
 *
 * 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 <dlfcn.h>
#include <signal.h>

#include <cstdio>
#include <cstring>
#include <string>

#include "jni.h"
#include "ScopedLocalRef.h"
#include "toStringArray.h"
#include "UniquePtr.h"

namespace art {

// Determine whether or not the specified method is public.
static bool IsMethodPublic(JNIEnv* env, jclass c, jmethodID method_id) {
  ScopedLocalRef<jobject> reflected(env, env->ToReflectedMethod(c, method_id, JNI_FALSE));
  if (reflected.get() == NULL) {
    fprintf(stderr, "Failed to get reflected method\n");
    return false;
  }
  // We now have a Method instance.  We need to call its
  // getModifiers() method.
  jclass method_class = env->FindClass("java/lang/reflect/Method");
  if (method_class == NULL) {
    fprintf(stderr, "Failed to find class java.lang.reflect.Method\n");
    return false;
  }
  jmethodID mid = env->GetMethodID(method_class, "getModifiers", "()I");
  if (mid == NULL) {
    fprintf(stderr, "Failed to find java.lang.reflect.Method.getModifiers\n");
    return false;
  }
  int modifiers = env->CallIntMethod(reflected.get(), mid);
  static const int PUBLIC = 0x0001;  // java.lang.reflect.Modifiers.PUBLIC
  if ((modifiers & PUBLIC) == 0) {
    return false;
  }
  return true;
}

static int InvokeMain(JNIEnv* env, char** argv) {
  // We want to call main() with a String array with our arguments in
  // it.  Create an array and populate it.  Note argv[0] is not
  // included.
  ScopedLocalRef<jobjectArray> args(env, toStringArray(env, argv + 1));
  if (args.get() == NULL) {
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  // Find [class].main(String[]).

  // Convert "com.android.Blah" to "com/android/Blah".
  std::string class_name(argv[0]);
  std::replace(class_name.begin(), class_name.end(), '.', '/');

  ScopedLocalRef<jclass> klass(env, env->FindClass(class_name.c_str()));
  if (klass.get() == NULL) {
    fprintf(stderr, "Unable to locate class '%s'\n", class_name.c_str());
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  jmethodID method = env->GetStaticMethodID(klass.get(), "main", "([Ljava/lang/String;)V");
  if (method == NULL) {
    fprintf(stderr, "Unable to find static main(String[]) in '%s'\n", class_name.c_str());
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  // Make sure the method is public.  JNI doesn't prevent us from
  // calling a private method, so we have to check it explicitly.
  if (!IsMethodPublic(env, klass.get(), method)) {
    fprintf(stderr, "Sorry, main() is not public in '%s'\n", class_name.c_str());
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  // Invoke main().
  env->CallStaticVoidMethod(klass.get(), method, args.get());

  // Check whether there was an uncaught exception. We don't log any uncaught exception here;
  // detaching this thread will do that for us, but it will clear the exception (and invalidate
  // our JNIEnv), so we need to check here.
  return env->ExceptionCheck() ? EXIT_FAILURE : EXIT_SUCCESS;
}

// Parse arguments.  Most of it just gets passed through to the runtime.
// The JNI spec defines a handful of standard arguments.
static int dalvikvm(int argc, char** argv) {
  setvbuf(stdout, NULL, _IONBF, 0);

  // Skip over argv[0].
  argv++;
  argc--;

  // If we're adding any additional stuff, e.g. function hook specifiers,
  // add them to the count here.
  //
  // We're over-allocating, because this includes the options to the runtime
  // plus the options to the program.
  int option_count = argc;
  UniquePtr<JavaVMOption[]> options(new JavaVMOption[option_count]());

  // Copy options over.  Everything up to the name of the class starts
  // with a '-' (the function hook stuff is strictly internal).
  //
  // [Do we need to catch & handle "-jar" here?]
  bool need_extra = false;
  const char* lib = "libdvm.so";
  const char* debug = NULL;
  const char* what = NULL;
  int curr_opt, arg_idx;
  for (curr_opt = arg_idx = 0; arg_idx < argc; arg_idx++) {
    if (argv[arg_idx][0] != '-' && !need_extra) {
      break;
    }
    if (strncmp(argv[arg_idx], "-XXlib:", strlen("-XXlib:")) == 0) {
      lib = argv[arg_idx] + strlen("-XXlib:");
      continue;
    }

    options[curr_opt++].optionString = argv[arg_idx];

    // Some options require an additional argument.
    need_extra = false;
    if (strcmp(argv[arg_idx], "-classpath") == 0 || strcmp(argv[arg_idx], "-cp") == 0) {
      need_extra = true;
      what = argv[arg_idx];
    }
  }

  if (need_extra) {
    fprintf(stderr, "%s must be followed by an additional argument giving a value\n", what);
    return EXIT_FAILURE;
  }

  // Make sure they provided a class name.
  if (arg_idx == argc) {
    fprintf(stderr, "Class name required\n");
    return EXIT_FAILURE;
  }

  // insert additional internal options here

  if (curr_opt >= option_count) {
    fprintf(stderr, "curr_opt(%d) >= option_count(%d)\n", curr_opt, option_count);
    abort();
    return EXIT_FAILURE;
  }

  // Find the JNI_CreateJavaVM implementation.
  std::string library(lib);
  if (debug != NULL) {
    library += debug;
  }
  void* handle = dlopen(library.c_str(), RTLD_NOW);
  if (handle == NULL) {
    fprintf(stderr, "Failed to dlopen library %s: %s\n", library.c_str(), dlerror());
    return EXIT_FAILURE;
  }
  const char* symbol = "JNI_CreateJavaVM";
  void* sym = dlsym(handle, symbol);
  if (handle == NULL) {
    fprintf(stderr, "Failed to find symbol %s: %s\n", symbol, dlerror());
    return EXIT_FAILURE;
  }
  typedef int (*Fn)(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
  Fn JNI_CreateJavaVM = reinterpret_cast<Fn>(sym);

  JavaVMInitArgs init_args;
  init_args.version = JNI_VERSION_1_6;
  init_args.options = options.get();
  init_args.nOptions = curr_opt;
  init_args.ignoreUnrecognized = JNI_FALSE;

  // Start the runtime. The current thread becomes the main thread.
  JavaVM* vm = NULL;
  JNIEnv* env = NULL;
  if (JNI_CreateJavaVM(&vm, &env, &init_args) != JNI_OK) {
    fprintf(stderr, "Failed to initialize runtime (check log for details)\n");
    return EXIT_FAILURE;
  }

  int rc = InvokeMain(env, &argv[arg_idx]);

#if defined(NDEBUG)
  // The DestroyJavaVM call will detach this thread for us. In debug builds, we don't want to
  // detach because detaching disables the CheckSafeToLockOrUnlock checking.
  if (vm->DetachCurrentThread() != JNI_OK) {
    fprintf(stderr, "Warning: unable to detach main thread\n");
    rc = EXIT_FAILURE;
  }
#endif

  if (vm->DestroyJavaVM() != 0) {
    fprintf(stderr, "Warning: runtime did not shut down cleanly\n");
    rc = EXIT_FAILURE;
  }

  return rc;
}

} // namespace art

int main(int argc, char** argv) {
  return art::dalvikvm(argc, argv);
}
<commit_msg>am ad27f28f: Add missing dlclose<commit_after>/*
 * copyright (C) 2011 The Android Open Source Project
 *
 * 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 <dlfcn.h>
#include <signal.h>

#include <cstdio>
#include <cstring>
#include <string>

#include "jni.h"
#include "ScopedLocalRef.h"
#include "toStringArray.h"
#include "UniquePtr.h"

namespace art {

// Determine whether or not the specified method is public.
static bool IsMethodPublic(JNIEnv* env, jclass c, jmethodID method_id) {
  ScopedLocalRef<jobject> reflected(env, env->ToReflectedMethod(c, method_id, JNI_FALSE));
  if (reflected.get() == NULL) {
    fprintf(stderr, "Failed to get reflected method\n");
    return false;
  }
  // We now have a Method instance.  We need to call its
  // getModifiers() method.
  jclass method_class = env->FindClass("java/lang/reflect/Method");
  if (method_class == NULL) {
    fprintf(stderr, "Failed to find class java.lang.reflect.Method\n");
    return false;
  }
  jmethodID mid = env->GetMethodID(method_class, "getModifiers", "()I");
  if (mid == NULL) {
    fprintf(stderr, "Failed to find java.lang.reflect.Method.getModifiers\n");
    return false;
  }
  int modifiers = env->CallIntMethod(reflected.get(), mid);
  static const int PUBLIC = 0x0001;  // java.lang.reflect.Modifiers.PUBLIC
  if ((modifiers & PUBLIC) == 0) {
    return false;
  }
  return true;
}

static int InvokeMain(JNIEnv* env, char** argv) {
  // We want to call main() with a String array with our arguments in
  // it.  Create an array and populate it.  Note argv[0] is not
  // included.
  ScopedLocalRef<jobjectArray> args(env, toStringArray(env, argv + 1));
  if (args.get() == NULL) {
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  // Find [class].main(String[]).

  // Convert "com.android.Blah" to "com/android/Blah".
  std::string class_name(argv[0]);
  std::replace(class_name.begin(), class_name.end(), '.', '/');

  ScopedLocalRef<jclass> klass(env, env->FindClass(class_name.c_str()));
  if (klass.get() == NULL) {
    fprintf(stderr, "Unable to locate class '%s'\n", class_name.c_str());
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  jmethodID method = env->GetStaticMethodID(klass.get(), "main", "([Ljava/lang/String;)V");
  if (method == NULL) {
    fprintf(stderr, "Unable to find static main(String[]) in '%s'\n", class_name.c_str());
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  // Make sure the method is public.  JNI doesn't prevent us from
  // calling a private method, so we have to check it explicitly.
  if (!IsMethodPublic(env, klass.get(), method)) {
    fprintf(stderr, "Sorry, main() is not public in '%s'\n", class_name.c_str());
    env->ExceptionDescribe();
    return EXIT_FAILURE;
  }

  // Invoke main().
  env->CallStaticVoidMethod(klass.get(), method, args.get());

  // Check whether there was an uncaught exception. We don't log any uncaught exception here;
  // detaching this thread will do that for us, but it will clear the exception (and invalidate
  // our JNIEnv), so we need to check here.
  return env->ExceptionCheck() ? EXIT_FAILURE : EXIT_SUCCESS;
}

// Parse arguments.  Most of it just gets passed through to the runtime.
// The JNI spec defines a handful of standard arguments.
static int dalvikvm(int argc, char** argv) {
  setvbuf(stdout, NULL, _IONBF, 0);

  // Skip over argv[0].
  argv++;
  argc--;

  // If we're adding any additional stuff, e.g. function hook specifiers,
  // add them to the count here.
  //
  // We're over-allocating, because this includes the options to the runtime
  // plus the options to the program.
  int option_count = argc;
  UniquePtr<JavaVMOption[]> options(new JavaVMOption[option_count]());

  // Copy options over.  Everything up to the name of the class starts
  // with a '-' (the function hook stuff is strictly internal).
  //
  // [Do we need to catch & handle "-jar" here?]
  bool need_extra = false;
  const char* lib = "libdvm.so";
  const char* debug = NULL;
  const char* what = NULL;
  int curr_opt, arg_idx;
  for (curr_opt = arg_idx = 0; arg_idx < argc; arg_idx++) {
    if (argv[arg_idx][0] != '-' && !need_extra) {
      break;
    }
    if (strncmp(argv[arg_idx], "-XXlib:", strlen("-XXlib:")) == 0) {
      lib = argv[arg_idx] + strlen("-XXlib:");
      continue;
    }

    options[curr_opt++].optionString = argv[arg_idx];

    // Some options require an additional argument.
    need_extra = false;
    if (strcmp(argv[arg_idx], "-classpath") == 0 || strcmp(argv[arg_idx], "-cp") == 0) {
      need_extra = true;
      what = argv[arg_idx];
    }
  }

  if (need_extra) {
    fprintf(stderr, "%s must be followed by an additional argument giving a value\n", what);
    return EXIT_FAILURE;
  }

  // Make sure they provided a class name.
  if (arg_idx == argc) {
    fprintf(stderr, "Class name required\n");
    return EXIT_FAILURE;
  }

  // insert additional internal options here

  if (curr_opt >= option_count) {
    fprintf(stderr, "curr_opt(%d) >= option_count(%d)\n", curr_opt, option_count);
    abort();
    return EXIT_FAILURE;
  }

  // Find the JNI_CreateJavaVM implementation.
  std::string library(lib);
  if (debug != NULL) {
    library += debug;
  }
  void* handle = dlopen(library.c_str(), RTLD_NOW);
  if (handle == NULL) {
    fprintf(stderr, "Failed to dlopen library %s: %s\n", library.c_str(), dlerror());
    return EXIT_FAILURE;
  }
  const char* symbol = "JNI_CreateJavaVM";
  void* sym = dlsym(handle, symbol);
  if (handle == NULL) {
    fprintf(stderr, "Failed to find symbol %s: %s\n", symbol, dlerror());
    return EXIT_FAILURE;
  }
  typedef int (*Fn)(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
  Fn JNI_CreateJavaVM = reinterpret_cast<Fn>(sym);

  JavaVMInitArgs init_args;
  init_args.version = JNI_VERSION_1_6;
  init_args.options = options.get();
  init_args.nOptions = curr_opt;
  init_args.ignoreUnrecognized = JNI_FALSE;

  // Start the runtime. The current thread becomes the main thread.
  JavaVM* vm = NULL;
  JNIEnv* env = NULL;
  if (JNI_CreateJavaVM(&vm, &env, &init_args) != JNI_OK) {
    fprintf(stderr, "Failed to initialize runtime (check log for details)\n");
    return EXIT_FAILURE;
  }

  int rc = InvokeMain(env, &argv[arg_idx]);

#if defined(NDEBUG)
  // The DestroyJavaVM call will detach this thread for us. In debug builds, we don't want to
  // detach because detaching disables the CheckSafeToLockOrUnlock checking.
  if (vm->DetachCurrentThread() != JNI_OK) {
    fprintf(stderr, "Warning: unable to detach main thread\n");
    rc = EXIT_FAILURE;
  }
#endif

  if (vm->DestroyJavaVM() != 0) {
    fprintf(stderr, "Warning: runtime did not shut down cleanly\n");
    rc = EXIT_FAILURE;
  }

  dlclose(handle);
  return rc;
}

} // namespace art

int main(int argc, char** argv) {
  return art::dalvikvm(argc, argv);
}
<|endoftext|>


<commit_before>// -*-c++-*-

/*
 * demonstrates usage of osg::TextureRectangle.
 *
 * Actually there isn't much difference to the rest of the osg::Texture*
 * bunch only this:
 * - texture coordinates for texture rectangles must be in image
 *   coordinates instead of normalized coordinates (0-1). So for a 500x250
 *   image the coordinates for the entire image would be
 *   0,250 0,0 500,0 500,250 instead of 0,1 0,0 1,0 1,1
 * - only the following wrap modes are supported (but not enforced)
 *   CLAMP, CLAMP_TO_EDGE, CLAMP_TO_BORDER
 * - a border is not supported
 * - mipmap is not supported
 */

#include <osg/Notify>
#include <osg/TextureRectangle>
#include <osg/Geometry>
#include <osg/Geode>

#include <osg/Group>
#include <osg/Projection>
#include <osg/MatrixTransform>
#include <osgText/Text>

#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <osgProducer/Viewer>

/**********************************************************************
 *
 * Texture pan animation callback
 *
 **********************************************************************/

class TexturePanCallback : public osg::NodeCallback
{
public:
    TexturePanCallback(osg::Geometry* geom, osg::Image* img,
                       double delay = 0.05) :
        _geom(geom),
        _img(img),
        _phaseS(35.0f),
        _phaseT(18.0f),
        _phaseScale(5.0f),
        _delay(delay),
        _prevTime(0.0)
    {
    }

    virtual void operator()(osg::Node*, osg::NodeVisitor* nv)
    {
        if (!_geom || !_img)
            return;

        if (nv->getFrameStamp()) {
            double currTime = nv->getFrameStamp()->getReferenceTime();
            if (currTime - _prevTime > _delay) {

                float rad = osg::DegreesToRadians(currTime);

                // zoom scale (0.2 - 1.0)
                float scale = sin(rad * _phaseScale) * 0.4f + 0.6f;
                float scaleR = 1.0f - scale;

                // calculate new texture coordinates
                float s, t;
                s = ((sin(rad * _phaseS) + 1) * 0.5f) * (_img->s() * scaleR);
                t = ((sin(rad * _phaseT) + 1) * 0.5f) * (_img->t() * scaleR);

                // set new texture coordinate array
                osg::Vec2Array* texcoords = (osg::Vec2Array*) _geom->getTexCoordArray(0);
                float w = _img->s() * scale, h = _img->t() * scale;
                (*texcoords)[0].set(s, t+h);
                (*texcoords)[1].set(s, t);
                (*texcoords)[2].set(s+w, t);
                (*texcoords)[3].set(s+w, t+h);

                // record time
                _prevTime = currTime;
            }
        }
    }

private:
    osg::Geometry* _geom;
    osg::Image* _img;

    float _phaseS, _phaseT, _phaseScale;

    double _delay;
    double _prevTime;
};

osg::Node* createRectangle(osg::BoundingBox& bb,
                           const std::string& filename)
{
    osg::Vec3 top_left(bb.xMin(),bb.yMax(),bb.zMax());
    osg::Vec3 bottom_left(bb.xMin(),bb.yMax(),bb.zMin());
    osg::Vec3 bottom_right(bb.xMax(),bb.yMax(),bb.zMin());
    osg::Vec3 top_right(bb.xMax(),bb.yMax(),bb.zMax());

    // create geometry
    osg::Geometry* geom = new osg::Geometry;

    osg::Vec3Array* vertices = new osg::Vec3Array(4);
    (*vertices)[0] = top_left;
    (*vertices)[1] = bottom_left;
    (*vertices)[2] = bottom_right;
    (*vertices)[3] = top_right;
    geom->setVertexArray(vertices);

    osg::Vec2Array* texcoords = new osg::Vec2Array(4);
    (*texcoords)[0].set(0.0f, 0.0f);
    (*texcoords)[1].set(1.0f, 0.0f);
    (*texcoords)[2].set(1.0f, 1.0f);
    (*texcoords)[3].set(0.0f, 1.0f);
    geom->setTexCoordArray(0,texcoords);

    osg::Vec3Array* normals = new osg::Vec3Array(1);
    (*normals)[0].set(-1.0f,0.0f,0.0f);
    geom->setNormalArray(normals);
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

    osg::Vec4Array* colors = new osg::Vec4Array(1);
    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
    geom->setColorArray(colors);
    geom->setColorBinding(osg::Geometry::BIND_OVERALL);

    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));

    // disable display list so our modified tex coordinates show up
    geom->setUseDisplayList(false);

    // setup texture
    osg::TextureRectangle* texture = new osg::TextureRectangle;

    // load image
    osg::Image* img = osgDB::readImageFile(filename);
    texture->setImage(img);

    // setup state
    osg::StateSet* state = geom->getOrCreateStateSet();
    state->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);

    // turn off lighting
    state->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

    // install 'update' callback
    osg::Geode* geode = new osg::Geode;
    geode->addDrawable(geom);
    geode->setUpdateCallback(new TexturePanCallback(geom, img));

    return geode;
}

osg::Geode* createText(const std::string& str,
                       const osg::Vec3& pos)
{
    static std::string font("fonts/arial.ttf");

    osg::Geode* geode = new osg::Geode;

    osgText::Text* text = new osgText::Text;
    geode->addDrawable(text);

    text->setFont(font);
    text->setPosition(pos);
    text->setText(str);

    return geode;
}

osg::Node* createHUD()
{
    osg::Group* group = new osg::Group;

    // turn off lighting and depth test
    osg::StateSet* state = group->getOrCreateStateSet();
    state->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
    state->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);

    // add text
    osg::Vec3 pos(120.0f, 800.0f, 0.0f);
    const osg::Vec3 delta(0.0f, -80.0f, 0.0f);

    const char* text[] = {
        "TextureRectangle Mini-HOWTO",
        "- essentially behaves like Texture2D, *except* that:",
        "- tex coords must be non-normalized (0..pixel) instead of (0..1)",
        "- wrap modes must be CLAMP, CLAMP_TO_EDGE, or CLAMP_TO_BORDER\n  repeating wrap modes are not supported",
        "- filter modes must be NEAREST or LINEAR since\n  mipmaps are not supported",
        "- texture borders are not supported",
        "- defaults should be fine",
        NULL
    };
    const char** t = text;
    while (*t) {
        group->addChild(createText(*t++, pos));
        pos += delta;
    }

    // create HUD
    osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
    modelview_abs->setReferenceFrame(osg::Transform::RELATIVE_TO_ABSOLUTE);
    modelview_abs->setMatrix(osg::Matrix::identity());
    modelview_abs->addChild(group);

    osg::Projection* projection = new osg::Projection;
    projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
    projection->addChild(modelview_abs);

    return projection;
}

osg::Node* createModel(const std::string& filename)
{
    osg::Group* root = new osg::Group;

    if (filename != "X") {
        osg::BoundingBox bb(0.0f,0.0f,0.0f,1.0f,1.0f,1.0f);
        root->addChild(createRectangle(bb, filename)); // XXX
    }

    root->addChild(createHUD());

    return root;
}

int main(int argc, char** argv)
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is a demo which demonstrates use of osg::TextureRectangle.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] <image> ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    // create a model from the images.
    osg::Node* rootNode = createModel((arguments.argc() > 1 ? arguments[1] : "lz.rgb"));

    // add model to viewer.
    viewer.setSceneData(rootNode);

    // create the windows and run the threads.
    viewer.realize();

    while (!viewer.done())
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();
    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;
}
<commit_msg>Added Images/ infront of lz.rgb path.<commit_after>// -*-c++-*-

/*
 * demonstrates usage of osg::TextureRectangle.
 *
 * Actually there isn't much difference to the rest of the osg::Texture*
 * bunch only this:
 * - texture coordinates for texture rectangles must be in image
 *   coordinates instead of normalized coordinates (0-1). So for a 500x250
 *   image the coordinates for the entire image would be
 *   0,250 0,0 500,0 500,250 instead of 0,1 0,0 1,0 1,1
 * - only the following wrap modes are supported (but not enforced)
 *   CLAMP, CLAMP_TO_EDGE, CLAMP_TO_BORDER
 * - a border is not supported
 * - mipmap is not supported
 */

#include <osg/Notify>
#include <osg/TextureRectangle>
#include <osg/Geometry>
#include <osg/Geode>

#include <osg/Group>
#include <osg/Projection>
#include <osg/MatrixTransform>
#include <osgText/Text>

#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <osgProducer/Viewer>

/**********************************************************************
 *
 * Texture pan animation callback
 *
 **********************************************************************/

class TexturePanCallback : public osg::NodeCallback
{
public:
    TexturePanCallback(osg::Geometry* geom, osg::Image* img,
                       double delay = 0.05) :
        _geom(geom),
        _img(img),
        _phaseS(35.0f),
        _phaseT(18.0f),
        _phaseScale(5.0f),
        _delay(delay),
        _prevTime(0.0)
    {
    }

    virtual void operator()(osg::Node*, osg::NodeVisitor* nv)
    {
        if (!_geom || !_img)
            return;

        if (nv->getFrameStamp()) {
            double currTime = nv->getFrameStamp()->getReferenceTime();
            if (currTime - _prevTime > _delay) {

                float rad = osg::DegreesToRadians(currTime);

                // zoom scale (0.2 - 1.0)
                float scale = sin(rad * _phaseScale) * 0.4f + 0.6f;
                float scaleR = 1.0f - scale;

                // calculate new texture coordinates
                float s, t;
                s = ((sin(rad * _phaseS) + 1) * 0.5f) * (_img->s() * scaleR);
                t = ((sin(rad * _phaseT) + 1) * 0.5f) * (_img->t() * scaleR);

                // set new texture coordinate array
                osg::Vec2Array* texcoords = (osg::Vec2Array*) _geom->getTexCoordArray(0);
                float w = _img->s() * scale, h = _img->t() * scale;
                (*texcoords)[0].set(s, t+h);
                (*texcoords)[1].set(s, t);
                (*texcoords)[2].set(s+w, t);
                (*texcoords)[3].set(s+w, t+h);

                // record time
                _prevTime = currTime;
            }
        }
    }

private:
    osg::Geometry* _geom;
    osg::Image* _img;

    float _phaseS, _phaseT, _phaseScale;

    double _delay;
    double _prevTime;
};

osg::Node* createRectangle(osg::BoundingBox& bb,
                           const std::string& filename)
{
    osg::Vec3 top_left(bb.xMin(),bb.yMax(),bb.zMax());
    osg::Vec3 bottom_left(bb.xMin(),bb.yMax(),bb.zMin());
    osg::Vec3 bottom_right(bb.xMax(),bb.yMax(),bb.zMin());
    osg::Vec3 top_right(bb.xMax(),bb.yMax(),bb.zMax());

    // create geometry
    osg::Geometry* geom = new osg::Geometry;

    osg::Vec3Array* vertices = new osg::Vec3Array(4);
    (*vertices)[0] = top_left;
    (*vertices)[1] = bottom_left;
    (*vertices)[2] = bottom_right;
    (*vertices)[3] = top_right;
    geom->setVertexArray(vertices);

    osg::Vec2Array* texcoords = new osg::Vec2Array(4);
    (*texcoords)[0].set(0.0f, 0.0f);
    (*texcoords)[1].set(1.0f, 0.0f);
    (*texcoords)[2].set(1.0f, 1.0f);
    (*texcoords)[3].set(0.0f, 1.0f);
    geom->setTexCoordArray(0,texcoords);

    osg::Vec3Array* normals = new osg::Vec3Array(1);
    (*normals)[0].set(-1.0f,0.0f,0.0f);
    geom->setNormalArray(normals);
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

    osg::Vec4Array* colors = new osg::Vec4Array(1);
    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
    geom->setColorArray(colors);
    geom->setColorBinding(osg::Geometry::BIND_OVERALL);

    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));

    // disable display list so our modified tex coordinates show up
    geom->setUseDisplayList(false);

    // setup texture
    osg::TextureRectangle* texture = new osg::TextureRectangle;

    // load image
    osg::Image* img = osgDB::readImageFile(filename);
    texture->setImage(img);

    // setup state
    osg::StateSet* state = geom->getOrCreateStateSet();
    state->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);

    // turn off lighting
    state->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

    // install 'update' callback
    osg::Geode* geode = new osg::Geode;
    geode->addDrawable(geom);
    geode->setUpdateCallback(new TexturePanCallback(geom, img));

    return geode;
}

osg::Geode* createText(const std::string& str,
                       const osg::Vec3& pos)
{
    static std::string font("fonts/arial.ttf");

    osg::Geode* geode = new osg::Geode;

    osgText::Text* text = new osgText::Text;
    geode->addDrawable(text);

    text->setFont(font);
    text->setPosition(pos);
    text->setText(str);

    return geode;
}

osg::Node* createHUD()
{
    osg::Group* group = new osg::Group;

    // turn off lighting and depth test
    osg::StateSet* state = group->getOrCreateStateSet();
    state->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
    state->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);

    // add text
    osg::Vec3 pos(120.0f, 800.0f, 0.0f);
    const osg::Vec3 delta(0.0f, -80.0f, 0.0f);

    const char* text[] = {
        "TextureRectangle Mini-HOWTO",
        "- essentially behaves like Texture2D, *except* that:",
        "- tex coords must be non-normalized (0..pixel) instead of (0..1)",
        "- wrap modes must be CLAMP, CLAMP_TO_EDGE, or CLAMP_TO_BORDER\n  repeating wrap modes are not supported",
        "- filter modes must be NEAREST or LINEAR since\n  mipmaps are not supported",
        "- texture borders are not supported",
        "- defaults should be fine",
        NULL
    };
    const char** t = text;
    while (*t) {
        group->addChild(createText(*t++, pos));
        pos += delta;
    }

    // create HUD
    osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
    modelview_abs->setReferenceFrame(osg::Transform::RELATIVE_TO_ABSOLUTE);
    modelview_abs->setMatrix(osg::Matrix::identity());
    modelview_abs->addChild(group);

    osg::Projection* projection = new osg::Projection;
    projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
    projection->addChild(modelview_abs);

    return projection;
}

osg::Node* createModel(const std::string& filename)
{
    osg::Group* root = new osg::Group;

    if (filename != "X") {
        osg::BoundingBox bb(0.0f,0.0f,0.0f,1.0f,1.0f,1.0f);
        root->addChild(createRectangle(bb, filename)); // XXX
    }

    root->addChild(createHUD());

    return root;
}

int main(int argc, char** argv)
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is a demo which demonstrates use of osg::TextureRectangle.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] <image> ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    // create a model from the images.
    osg::Node* rootNode = createModel((arguments.argc() > 1 ? arguments[1] : "Images/lz.rgb"));

    // add model to viewer.
    viewer.setSceneData(rootNode);

    // create the windows and run the threads.
    viewer.realize();

    while (!viewer.done())
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();
    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;
}
<|endoftext|>


<commit_before>#line 2 "togo/resource/resource_package.cpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <togo/config.hpp>
#include <togo/utility/utility.hpp>
#include <togo/error/assert.hpp>
#include <togo/log/log.hpp>
#include <togo/hash/hash.hpp>
#include <togo/collection/hash_map.hpp>
#include <togo/io/io.hpp>
#include <togo/io/file_stream.hpp>
#include <togo/resource/types.hpp>
#include <togo/resource/resource.hpp>
#include <togo/resource/resource_package.hpp>
#include <togo/resource/resource_manager.hpp>
#include <togo/serialization/serializer.hpp>
#include <togo/serialization/support.hpp>
#include <togo/serialization/binary_serializer.hpp>
#include <togo/serialization/array.hpp>
#include <togo/serialization/resource/resource_metadata.hpp>

namespace togo {

ResourcePackage::ResourcePackage(
	StringRef const& name,
	StringRef const& path,
	Allocator& allocator
)
	: _name_hash(resource::hash_package_name(name))
	, _open_resource_id(0)
	, _stream()
	, _lookup(allocator)
	, _manifest(allocator)
	, _name()
	, _path()
{
	string::copy(_name, name);
	string::copy(_path, path);
}

void resource_package::open(
	ResourcePackage& pkg,
	ResourceManager const& rm
) {
	TOGO_ASSERT(!pkg._stream.is_open(), "package is already open");

	StringRef const name{pkg._name};
	StringRef const path{pkg._path};
	TOGO_ASSERTF(
		pkg._stream.open(path),
		"failed to open package '%.*s' at '%.*s'",
		name.size, name.data,
		path.size, path.data
	);

	BinaryInputSerializer ser{pkg._stream};
	u32 format_version = 0;
	ser % format_version;
	TOGO_ASSERTF(
		format_version == SER_FORMAT_VERSION_PKG_MANIFEST,
		"manifest version %u unsupported from package '%.*s' at '%.*s'",
		format_version,
		name.size, name.data,
		path.size, path.data
	);

	ser % make_ser_collection<u32>(pkg._manifest);
	for (u32 i = 0; i < array::size(pkg._manifest); ++i) {
		auto& metadata = pkg._manifest[i];
		if (metadata.type == RES_TYPE_NULL) {
			metadata.id = 0;
			continue;
		}
		metadata.id = i + 1;
		hash_map::push(pkg._lookup, metadata.name_hash, metadata.id);
		TOGO_ASSERTF(
			resource_manager::has_handler(rm, metadata.type),
			"no handler registered for resource %16lx's type %08x",
			metadata.name_hash, metadata.type
		);
	}
}

void resource_package::close(
	ResourcePackage& pkg
) {
	TOGO_ASSERT(pkg._stream.is_open(), "package is already closed");
	pkg._stream.close();
}

ResourceMetadata const& resource_package::resource_metadata(
	ResourcePackage const& pkg,
	u32 const id
) {
	TOGO_ASSERTE(id > 0 && id <= array::size(pkg._manifest));
	return pkg._manifest[id - 1];
}

ResourcePackage::LookupNode* resource_package::find_resource(
	ResourcePackage& pkg,
	ResourceType const type,
	ResourceNameHash const name_hash
) {
	auto* const node = hash_map::get_node(pkg._lookup, name_hash);
	return (node && pkg._manifest[node->value - 1].type == type) ? node : nullptr;
}

IReader* resource_package::open_resource_stream(
	ResourcePackage& pkg,
	u32 const id
) {
	TOGO_ASSERT(pkg._stream.is_open(), "package is not open");
	TOGO_ASSERT(pkg._open_resource_id == 0, "a resource stream is already open");
	TOGO_ASSERT(id > 0 && id <= array::size(pkg._manifest), "invalid ID");
	auto const& metadata = pkg._manifest[id - 1];
	TOGO_ASSERTE(io::seek_to(pkg._stream, metadata.data_offset));
	pkg._open_resource_id = id;
	return &pkg._stream;
}

void resource_package::close_resource_stream(
	ResourcePackage& pkg
) {
	TOGO_ASSERT(pkg._stream.is_open(), "package is not open");
	TOGO_ASSERT(pkg._open_resource_id != 0, "invalid ID");
	#if defined(TOGO_DEBUG)
		auto const& metadata = pkg._manifest[pkg._open_resource_id - 1];
		auto const stream_pos = io::position(pkg._stream);
		TOGO_DEBUG_ASSERTE(
			stream_pos >= metadata.data_offset &&
			stream_pos <= metadata.data_offset + metadata.data_size
		);
	#endif
	pkg._open_resource_id = 0;
}

} // namespace togo
<commit_msg>resource/resource_package: added null entry check to resource_metadata() & assertion message.<commit_after>#line 2 "togo/resource/resource_package.cpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <togo/config.hpp>
#include <togo/utility/utility.hpp>
#include <togo/error/assert.hpp>
#include <togo/log/log.hpp>
#include <togo/hash/hash.hpp>
#include <togo/collection/hash_map.hpp>
#include <togo/io/io.hpp>
#include <togo/io/file_stream.hpp>
#include <togo/resource/types.hpp>
#include <togo/resource/resource.hpp>
#include <togo/resource/resource_package.hpp>
#include <togo/resource/resource_manager.hpp>
#include <togo/serialization/serializer.hpp>
#include <togo/serialization/support.hpp>
#include <togo/serialization/binary_serializer.hpp>
#include <togo/serialization/array.hpp>
#include <togo/serialization/resource/resource_metadata.hpp>

namespace togo {

ResourcePackage::ResourcePackage(
	StringRef const& name,
	StringRef const& path,
	Allocator& allocator
)
	: _name_hash(resource::hash_package_name(name))
	, _open_resource_id(0)
	, _stream()
	, _lookup(allocator)
	, _manifest(allocator)
	, _name()
	, _path()
{
	string::copy(_name, name);
	string::copy(_path, path);
}

void resource_package::open(
	ResourcePackage& pkg,
	ResourceManager const& rm
) {
	TOGO_ASSERT(!pkg._stream.is_open(), "package is already open");

	StringRef const name{pkg._name};
	StringRef const path{pkg._path};
	TOGO_ASSERTF(
		pkg._stream.open(path),
		"failed to open package '%.*s' at '%.*s'",
		name.size, name.data,
		path.size, path.data
	);

	BinaryInputSerializer ser{pkg._stream};
	u32 format_version = 0;
	ser % format_version;
	TOGO_ASSERTF(
		format_version == SER_FORMAT_VERSION_PKG_MANIFEST,
		"manifest version %u unsupported from package '%.*s' at '%.*s'",
		format_version,
		name.size, name.data,
		path.size, path.data
	);

	ser % make_ser_collection<u32>(pkg._manifest);
	for (u32 i = 0; i < array::size(pkg._manifest); ++i) {
		auto& metadata = pkg._manifest[i];
		if (metadata.type == RES_TYPE_NULL) {
			metadata.id = 0;
			continue;
		}
		metadata.id = i + 1;
		hash_map::push(pkg._lookup, metadata.name_hash, metadata.id);
		TOGO_ASSERTF(
			resource_manager::has_handler(rm, metadata.type),
			"no handler registered for resource %16lx's type %08x",
			metadata.name_hash, metadata.type
		);
	}
}

void resource_package::close(
	ResourcePackage& pkg
) {
	TOGO_ASSERT(pkg._stream.is_open(), "package is already closed");
	pkg._stream.close();
}

ResourceMetadata const& resource_package::resource_metadata(
	ResourcePackage const& pkg,
	u32 const id
) {
	TOGO_ASSERT(id > 0 && id <= array::size(pkg._manifest), "invalid ID");
	auto const& metadata = pkg._manifest[id - 1];
	TOGO_DEBUG_ASSERT(metadata.id != 0, "null entry");
	return metadata;
}

ResourcePackage::LookupNode* resource_package::find_resource(
	ResourcePackage& pkg,
	ResourceType const type,
	ResourceNameHash const name_hash
) {
	auto* const node = hash_map::get_node(pkg._lookup, name_hash);
	return (node && pkg._manifest[node->value - 1].type == type) ? node : nullptr;
}

IReader* resource_package::open_resource_stream(
	ResourcePackage& pkg,
	u32 const id
) {
	TOGO_ASSERT(pkg._stream.is_open(), "package is not open");
	TOGO_ASSERT(pkg._open_resource_id == 0, "a resource stream is already open");
	TOGO_ASSERT(id > 0 && id <= array::size(pkg._manifest), "invalid ID");
	auto const& metadata = pkg._manifest[id - 1];
	TOGO_ASSERTE(io::seek_to(pkg._stream, metadata.data_offset));
	pkg._open_resource_id = id;
	return &pkg._stream;
}

void resource_package::close_resource_stream(
	ResourcePackage& pkg
) {
	TOGO_ASSERT(pkg._stream.is_open(), "package is not open");
	TOGO_ASSERT(pkg._open_resource_id != 0, "invalid ID");
	#if defined(TOGO_DEBUG)
		auto const& metadata = pkg._manifest[pkg._open_resource_id - 1];
		auto const stream_pos = io::position(pkg._stream);
		TOGO_DEBUG_ASSERTE(
			stream_pos >= metadata.data_offset &&
			stream_pos <= metadata.data_offset + metadata.data_size
		);
	#endif
	pkg._open_resource_id = 0;
}

} // namespace togo
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dsp_html_std.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 16:26:08 $
 *
 *  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 AUTODOC_DSP_HTML_STD_HXX
#define AUTODOC_DSP_HTML_STD_HXX

namespace ary
{
    namespace cpp
    {
        class DisplayGate;
    }
    namespace idl
    {
        class Gate;
    }
}

namespace display
{
    class CorporateFrame;
}

namespace autodoc
{

class HtmlDisplay_UdkStd
{
  public:
    virtual             ~HtmlDisplay_UdkStd() {}

    /** Displays the names of several C++ code entities within the
        given namespace (or the global namespace as default). All
        subnamespaces are included.

        Output has following format:

        =========================================================================
        OutputDirectory
            index.html
            def-all.html
            prj\
                sal\
                    index.html                      // Overview about project

                    f-FileName[1,2,...]             // Overview about file
                    f-OtherFileName[1,2,...]
                    ...
                    def-FileName[1,2,...]           // #defines and macros in file
                    def-OtherFileName[1,2,...]
                    ...
                rtl\
                    ...
                cppu\
                    ...
                cppuhelper\
                    ...
                ...
            ix\
                ix-a.html
                ix-b.html
                ...
                ix-z.html
                ix-_.html
                ix-other.html

            cpp\
                index.html                          // Overview about global namespace

                Namespace_A\
                    Namespace_C\
                        index.html                  // Overview about namespace C
                        ...
                    ...

                    index.html                      // Overview about namespace A

                    c-ClassName_X.html              // Description of class
                    ...
                    e-EnumName.html                 // Description of enum
                    ...
                    t-TypedefName.html              // Description of typedef
                    ...
                    o-Filename.html                 // Descriptions of operations in this file in this namespace
                    ...
                    d-Filename.html                 // Descriptions of data in this file in this namespace
                    ...

                    ClassName_X\
                        c-ClassName_Y.html
                        e-EnumName.html
                        t-TypedefName.html
                        o.html                      // Descriptions of operations in class X
                        d.html                      // Descriptions of data in class X

                        ClassName_Y\
                            ...
                ...

            idl\
                ...
            java\
                ...
        =========================================================================

        @param i_sOutputDirectory
            Directory for output. Path must be given in correct
            syntax for the actual operating system without final
            path delimiter. If this is 0 or "", the current
            working directory is chosen.
        @param i_rAryGate
            The access to the Autodoc Repository.
        @param i_rLayout
            Gives parameters for the appearance of the HTML output.
        @param i_pProjectList
            If this is != 0, then only code entities which are declared
            in this projects are displayed.
    */
    void                Run(
                            const char *        i_sOutputDirectory,
                            const ary::cpp::DisplayGate &
                                                i_rAryGate,
                            const display::CorporateFrame &
                                                i_rLayout,
                            const StringVector *
                                                i_pProjectList = 0 );
  private:
    virtual void        do_Run(
                            const char *        i_sOutputDirectory,
                            const ary::cpp::DisplayGate &
                                                i_rAryGate,
                            const display::CorporateFrame &
                                                i_rLayout,
                            const StringVector *
                                                i_pProjectList ) = 0;
};

// IMPLEMENTATION

inline void
HtmlDisplay_UdkStd::Run( const char *                    i_sOutputDirectory,
                         const ary::cpp::DisplayGate &   i_rAryGate,
                         const display::CorporateFrame & i_rLayout,
                         const StringVector *  i_pProjectList )
{
    do_Run( i_sOutputDirectory, i_rAryGate, i_rLayout, i_pProjectList );
}

// class HtmlDisplay_Idl_Ifc

class HtmlDisplay_Idl_Ifc
{
  public:
    virtual             ~HtmlDisplay_Idl_Ifc() {}

    void                Run(
                            const char *        i_sOutputDirectory,
                            const ary::idl::Gate &
                                                i_rAryGate,
                            const display::CorporateFrame &
                                                i_rLayout );
  private:
    virtual void        do_Run(
                            const char *        i_sOutputDirectory,
                            const ary::idl::Gate &
                                                i_rAryGate,
                            const display::CorporateFrame &
                                                i_rLayout ) = 0;
};

// IMPLEMENTATION

inline void
HtmlDisplay_Idl_Ifc::Run( const char *                    i_sOutputDirectory,
                          const ary::idl::Gate &          i_rAryGate,
                          const display::CorporateFrame & i_rLayout )
{
    do_Run( i_sOutputDirectory, i_rAryGate, i_rLayout );
}

} // namespace autodoc

#endif

<commit_msg>INTEGRATION: CWS adc18 (1.4.56); FILE MERGED 2007/10/18 15:23:11 np 1.4.56.1: #i81775#<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dsp_html_std.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-02 15:21:33 $
 *
 *  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 AUTODOC_DSP_HTML_STD_HXX
#define AUTODOC_DSP_HTML_STD_HXX

namespace ary
{
    namespace cpp
    {
        class Gate;
    }
    namespace idl
    {
        class Gate;
    }
}

namespace display
{
    class CorporateFrame;
}

namespace autodoc
{

class HtmlDisplay_UdkStd
{
  public:
    virtual             ~HtmlDisplay_UdkStd() {}

    /** Displays the names of several C++ code entities within the
        given namespace (or the global namespace as default). All
        subnamespaces are included.

        Output has following format:

        =========================================================================
        OutputDirectory
            index.html
            def-all.html
            prj\
                sal\
                    index.html                      // Overview about project

                    f-FileName[1,2,...]             // Overview about file
                    f-OtherFileName[1,2,...]
                    ...
                    def-FileName[1,2,...]           // #defines and macros in file
                    def-OtherFileName[1,2,...]
                    ...
                rtl\
                    ...
                cppu\
                    ...
                cppuhelper\
                    ...
                ...
            ix\
                ix-a.html
                ix-b.html
                ...
                ix-z.html
                ix-_.html
                ix-other.html

            cpp\
                index.html                          // Overview about global namespace

                Namespace_A\
                    Namespace_C\
                        index.html                  // Overview about namespace C
                        ...
                    ...

                    index.html                      // Overview about namespace A

                    c-ClassName_X.html              // Description of class
                    ...
                    e-EnumName.html                 // Description of enum
                    ...
                    t-TypedefName.html              // Description of typedef
                    ...
                    o-Filename.html                 // Descriptions of operations in this file in this namespace
                    ...
                    d-Filename.html                 // Descriptions of data in this file in this namespace
                    ...

                    ClassName_X\
                        c-ClassName_Y.html
                        e-EnumName.html
                        t-TypedefName.html
                        o.html                      // Descriptions of operations in class X
                        d.html                      // Descriptions of data in class X

                        ClassName_Y\
                            ...
                ...

            idl\
                ...
            java\
                ...
        =========================================================================

        @param i_sOutputDirectory
            Directory for output. Path must be given in correct
            syntax for the actual operating system without final
            path delimiter. If this is 0 or "", the current
            working directory is chosen.
        @param i_rAryGate
            The access to the Autodoc Repository.
        @param i_rLayout
            Gives parameters for the appearance of the HTML output.
        @param i_pProjectList
            If this is != 0, then only code entities which are declared
            in this projects are displayed.
    */
    void                Run(
                            const char *        i_sOutputDirectory,
                            const ary::cpp::Gate &
                                                i_rAryGate,
                            const display::CorporateFrame &
                                                i_rLayout );
  private:
    virtual void        do_Run(
                            const char *        i_sOutputDirectory,
                            const ary::cpp::Gate &
                                                i_rAryGate,
                            const display::CorporateFrame &
                                                i_rLayout ) = 0;
};

// IMPLEMENTATION

inline void
HtmlDisplay_UdkStd::Run( const char *                    i_sOutputDirectory,
                         const ary::cpp::Gate &          i_rAryGate,
                         const display::CorporateFrame & i_rLayout )
{
    do_Run( i_sOutputDirectory, i_rAryGate, i_rLayout );
}

// class HtmlDisplay_Idl_Ifc

class HtmlDisplay_Idl_Ifc
{
  public:
    virtual             ~HtmlDisplay_Idl_Ifc() {}

    void                Run(
                            const char *        i_sOutputDirectory,
                            const ary::idl::Gate &
                                                i_rAryGate,
                            const display::CorporateFrame &
                                                i_rLayout );
  private:
    virtual void        do_Run(
                            const char *        i_sOutputDirectory,
                            const ary::idl::Gate &
                                                i_rAryGate,
                            const display::CorporateFrame &
                                                i_rLayout ) = 0;
};

// IMPLEMENTATION
inline void
HtmlDisplay_Idl_Ifc::Run( const char *                    i_sOutputDirectory,
                          const ary::idl::Gate &          i_rAryGate,
                          const display::CorporateFrame & i_rLayout )
{
    do_Run( i_sOutputDirectory, i_rAryGate, i_rLayout );
}

} // namespace autodoc
#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: manager.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: vg $ $Date: 2007-12-07 11:41:50 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "manager.hxx"
#include "player.hxx"

#ifndef _URLOBJ_HXX //autogen wg. INetURLObject
#include <tools/urlobj.hxx>
#endif

using namespace ::com::sun::star;

namespace avmedia { namespace quicktime {
// ----------------
// - Manager -
// ----------------

Manager::Manager( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) :
    mxMgr( rxMgr )
{
    OSL_TRACE( "avmediaquicktime: Manager::Manager" );
}

// ------------------------------------------------------------------------------

Manager::~Manager()
{
}

// ------------------------------------------------------------------------------

uno::Reference< media::XPlayer > SAL_CALL Manager::createPlayer( const ::rtl::OUString& rURL )
    throw (uno::RuntimeException)
{
    Player*                             pPlayer( new Player( mxMgr ) );
    uno::Reference< media::XPlayer >    xRet( pPlayer );
    INetURLObject                       aURL( rURL );

    OSL_TRACE( "avmediaquicktime: Manager::createPlayer" );

    if( !pPlayer->create( aURL.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ) )  )
        xRet = uno::Reference< media::XPlayer >();

    return xRet;
}

// ------------------------------------------------------------------------------

::rtl::OUString SAL_CALL Manager::getImplementationName(  )
    throw (uno::RuntimeException)
{
    return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_QUICKTIME_MANAGER_IMPLEMENTATIONNAME ) );
}

// ------------------------------------------------------------------------------

sal_Bool SAL_CALL Manager::supportsService( const ::rtl::OUString& ServiceName )
    throw (uno::RuntimeException)
{
    return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_QUICKTIME_MANAGER_SERVICENAME ) );
}

// ------------------------------------------------------------------------------

uno::Sequence< ::rtl::OUString > SAL_CALL Manager::getSupportedServiceNames(  )
    throw (uno::RuntimeException)
{
    uno::Sequence< ::rtl::OUString > aRet(1);
    aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_QUICKTIME_MANAGER_SERVICENAME ) );

    return aRet;
}

} // namespace quicktime
} // namespace avmedia
<commit_msg>INTEGRATION: CWS changefileheader (1.2.30); FILE MERGED 2008/04/01 15:00:18 thb 1.2.30.2: #i85898# Stripping all external header guards 2008/03/28 16:03:58 rt 1.2.30.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: manager.cxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "manager.hxx"
#include "player.hxx"
#include <tools/urlobj.hxx>

using namespace ::com::sun::star;

namespace avmedia { namespace quicktime {
// ----------------
// - Manager -
// ----------------

Manager::Manager( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) :
    mxMgr( rxMgr )
{
    OSL_TRACE( "avmediaquicktime: Manager::Manager" );
}

// ------------------------------------------------------------------------------

Manager::~Manager()
{
}

// ------------------------------------------------------------------------------

uno::Reference< media::XPlayer > SAL_CALL Manager::createPlayer( const ::rtl::OUString& rURL )
    throw (uno::RuntimeException)
{
    Player*                             pPlayer( new Player( mxMgr ) );
    uno::Reference< media::XPlayer >    xRet( pPlayer );
    INetURLObject                       aURL( rURL );

    OSL_TRACE( "avmediaquicktime: Manager::createPlayer" );

    if( !pPlayer->create( aURL.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ) )  )
        xRet = uno::Reference< media::XPlayer >();

    return xRet;
}

// ------------------------------------------------------------------------------

::rtl::OUString SAL_CALL Manager::getImplementationName(  )
    throw (uno::RuntimeException)
{
    return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_QUICKTIME_MANAGER_IMPLEMENTATIONNAME ) );
}

// ------------------------------------------------------------------------------

sal_Bool SAL_CALL Manager::supportsService( const ::rtl::OUString& ServiceName )
    throw (uno::RuntimeException)
{
    return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_QUICKTIME_MANAGER_SERVICENAME ) );
}

// ------------------------------------------------------------------------------

uno::Sequence< ::rtl::OUString > SAL_CALL Manager::getSupportedServiceNames(  )
    throw (uno::RuntimeException)
{
    uno::Sequence< ::rtl::OUString > aRet(1);
    aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_QUICKTIME_MANAGER_SERVICENAME ) );

    return aRet;
}

} // namespace quicktime
} // namespace avmedia
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011 Matthew Iselin
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include <Widget.h>

#include <ipc/Ipc.h>

/// \todo GTFO libc!
#include <unistd.h>

/// \todo GTFO libc!
#include <string.h>
#include <stdlib.h>
#include <syslog.h>

#include <map>
#include <queue>

#include "protocol.h"

using namespace LibUiProtocol;

#define PEDIGREE_WINMAN_ENDPOINT "pedigree-winman"

/// Default event handler for new widgets.
static bool defaultEventHandler(WidgetMessages message, size_t dataSize, void *dataBuffer)
{
    return false;
}

static Widget *g_pWidget = 0;

std::map<uint64_t, widgetCallback_t> Widget::m_CallbackMap;
std::queue<PedigreeIpc::IpcMessage *> g_PendingMessages;

Widget::Widget() :
    m_bConstructed(false), m_pFramebuffer(0), m_Handle(0),
    m_EventCallback(defaultEventHandler), m_Endpoint(0),
    m_SharedFramebuffer(0)
{
}

Widget::~Widget()
{
    if(m_Endpoint) {
        free((void *) m_Endpoint);
    }
}

bool Widget::construct(const char *endpoint, const char *title, widgetCallback_t cb, PedigreeGraphics::Rect &dimensions)
{
    if(m_Handle)
    {
        // Already constructed!
        return false;
    }

    /// \todo Maybe we can get a decent way of having a default handler?
    if(!cb)
        return false;

    // Create endpoint, if not already created.
    /// \todo fail if endpoint already exists.
    PedigreeIpc::createEndpoint(endpoint);
    m_Endpoint = PedigreeIpc::getEndpoint(endpoint);
    PedigreeIpc::IpcEndpoint *winman = PedigreeIpc::getEndpoint(PEDIGREE_WINMAN_ENDPOINT);

    // Construct the handle first.
    uint64_t pid = getpid();
    uintptr_t widgetPointer = reinterpret_cast<uintptr_t>(this);
#ifdef BITS_64
    m_Handle = (pid << 32) | (((widgetPointer >> 32) | (widgetPointer & 0xFFFFFFFF)) & 0xFFFFFFFF);
#else
    m_Handle = (pid << 32) | (widgetPointer);
#endif

    PedigreeIpc::IpcMessage *pCreateMessage = new PedigreeIpc::IpcMessage();
    if(!pCreateMessage->initialise())
    {
        m_Handle = 0;
        return false;
    }

    // Prepare a message to send.
    size_t totalSize = sizeof(WindowManagerMessage) + sizeof(CreateMessage);
    char *messageData = static_cast<char *>(pCreateMessage->getBuffer());
    WindowManagerMessage *pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
    CreateMessage *pCreate = reinterpret_cast<CreateMessage*>(messageData + sizeof(WindowManagerMessage));

    // Fill.
    pWinMan->messageCode = Create;
    pWinMan->messageSize = sizeof(CreateMessage);
    pWinMan->widgetHandle = m_Handle;
    pWinMan->isResponse = false;
    strlcpy(pCreate->endpoint, endpoint, 256);
    strlcpy(pCreate->title, title, 256);
    pCreate->minWidth = dimensions.getW();
    pCreate->minHeight = dimensions.getH();
    pCreate->rigid = true;

    // Send the message off to the window manager and wait for a response. The
    // response will contain a GraphicsProvider that we can use to create our
    // Framebuffer for drawing on.
    if(!PedigreeIpc::send(winman, pCreateMessage, false))
    {
        m_Handle = 0;
        delete pCreateMessage;
        return false;
    }

    PedigreeIpc::IpcMessage *pResponse = 0;

    while(1)
    {
        if(!PedigreeIpc::recv(m_Endpoint, &pResponse, false))
        {
            m_Handle = 0;
            return false;
        }

        if(!(pResponse && pResponse->getBuffer()))
        {
            continue;
        }

        pWinMan = reinterpret_cast<WindowManagerMessage*>(pResponse->getBuffer());
        if(!(pWinMan->isResponse && (pWinMan->messageCode == Create)))
        {
            g_PendingMessages.push(pResponse);
        }
        else
        {
            messageData = static_cast<char *>(pResponse->getBuffer());
            break;
        }
    }

    // Grab the results and use them.
    CreateMessageResponse *pCreateResp = reinterpret_cast<CreateMessageResponse*>(messageData + sizeof(WindowManagerMessage));
    m_EventCallback = cb;
    m_CallbackMap[m_Handle] = cb;

    delete pResponse;

    g_pWidget = this;

    // Asynchronously check for any events in the pipeline. This should be an
    // initial reposition event that we really need to get out to the client
    // ASAP.
    checkForEvents(true);

    return true;
}

bool Widget::setProperty(std::string propName, void *propVal, size_t maxSize)
{
    // Constructed yet?
    if(!m_Handle)
        return false;

    // Are the arguments sane?
    if(!propVal)
        return false;
    if(maxSize > 0x1000)
        return false;

    // Allocate the message.
    /// \todo Sanitise maxSize once large messages can be sent.
    size_t headerSize = sizeof(WindowManagerMessage) + sizeof(SetPropertyMessage);
    size_t totalSize = headerSize + maxSize;
    char *messageData = new char[totalSize];
    WindowManagerMessage *pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
    SetPropertyMessage *pMessage = reinterpret_cast<SetPropertyMessage*>(messageData + sizeof(WindowManagerMessage));

    // Fill the message.
    pWinMan->messageCode = SetProperty;
    pWinMan->messageSize = sizeof(SetPropertyMessage) + maxSize;
    pWinMan->widgetHandle = m_Handle;
    pWinMan->isResponse = false;

    propName.copy(pMessage->propertyName, sizeof pMessage->propertyName);
    pMessage->valueLength = maxSize;

    // Copy in the property data.
    memcpy(messageData + headerSize, propVal, maxSize);

    // Transmit.
    bool result = sendMessage(messageData, totalSize);

    // Clean up.
    delete [] messageData;

    return result;
}

bool Widget::getProperty(std::string propName, char **buffer, size_t maxSize)
{
    return false;
}

void Widget::setParent(Widget *pWidget)
{
}

Widget *Widget::getParent()
{
    return 0;
}

bool Widget::redraw(PedigreeGraphics::Rect &rt)
{
    // Constructed yet?
    if(!m_Handle)
        return false;

    // Allocate the message.
    size_t totalSize = sizeof(WindowManagerMessage) + sizeof(RequestRedrawMessage);
    char *messageData = new char[totalSize];
    WindowManagerMessage *pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
    RequestRedrawMessage *pMessage = reinterpret_cast<RequestRedrawMessage*>(messageData + sizeof(WindowManagerMessage));

    // Fill the message.
    pWinMan->messageCode = RequestRedraw;
    pWinMan->messageSize = sizeof(RequestRedrawMessage);
    pWinMan->widgetHandle = m_Handle;
    pWinMan->isResponse = false;
    pMessage->x = rt.getX();
    pMessage->y = rt.getY();
    pMessage->width = rt.getW();
    pMessage->height = rt.getH();

    // Transmit.
    bool result = sendMessage(messageData, totalSize);

    // Clean up.
    delete [] messageData;

    return result;
}

bool Widget::visibility(bool vis)
{
    // Constructed yet?
    if(!m_Handle)
        return false;

    // Allocate the message.
    size_t totalSize = sizeof(WindowManagerMessage) + sizeof(SetVisibilityMessage);
    char *messageData = new char[totalSize];
    WindowManagerMessage *pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
    SetVisibilityMessage *pMessage = reinterpret_cast<SetVisibilityMessage*>(messageData + sizeof(WindowManagerMessage));

    // Fill the message.
    pWinMan->messageCode = SetVisibility;
    pWinMan->messageSize = sizeof(SetVisibilityMessage);
    pWinMan->widgetHandle = m_Handle;
    pWinMan->isResponse = false;
    pMessage->bVisible = vis;

    // Transmit.
    bool result = sendMessage(messageData, totalSize);

    // Clean up.
    delete [] messageData;

    return result;
}

void Widget::destroy()
{
    // Constructed yet?
    if(!m_Handle)
        return;

    // Allocate the message.
    size_t totalSize = sizeof(WindowManagerMessage) + sizeof(DestroyMessage);
    char *messageData = new char[totalSize];
    WindowManagerMessage *pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
    DestroyMessage *pMessage = reinterpret_cast<DestroyMessage*>(messageData + sizeof(WindowManagerMessage));

    // Fill the message.
    pWinMan->messageCode = Destroy;
    pWinMan->messageSize = sizeof(DestroyMessage);
    pWinMan->widgetHandle = m_Handle;
    pWinMan->isResponse = false;

    // Transmit.
    sendMessage(messageData, totalSize);

    // Clean up.
    delete [] messageData;

    // Invalidate this widget now.
    delete m_pFramebuffer;
    m_Handle = 0;
}

PedigreeGraphics::Framebuffer *Widget::getFramebuffer()
{
    return 0;

    /*
    // Constructed yet?
    if(!m_Handle)
        return 0;

    // No framebuffer yet?
    if(!m_pFramebuffer)
        return 0;

    // Allocate the message.
    size_t totalSize = sizeof(WindowManagerMessage) + sizeof(SyncMessage);
    char *messageData = new char[totalSize];
    WindowManagerMessage *pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
    SyncMessage *pMessage = reinterpret_cast<SyncMessage*>(messageData + sizeof(WindowManagerMessage));

    // Fill the message.
    pWinMan->messageCode = Sync;
    pWinMan->messageSize = sizeof(SyncMessage);
    pWinMan->widgetHandle = m_Handle;
    pWinMan->isResponse = false;

    // Transmit, synchronously.
    syslog(LOG_INFO, "TX Sync [%d]", getpid());
    sendMessage(messageData, totalSize);
    syslog(LOG_INFO, "TX complete");

    delete [] messageData;

    // Get the response.
    totalSize = 1024;
    messageData = new char[totalSize];

    while(1)
    {
        if(!recvMessage(m_Endpoint, messageData, totalSize))
        {
            m_Handle = 0;
            delete [] messageData;
            return 0;
        }

        pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
        if(!(pWinMan->isResponse && (pWinMan->messageCode == Sync)))
        {
            g_PendingMessages.push(messageData);
            messageData = new char[totalSize];
        }
        else
        {
            break;
        }
    }

    SyncMessageResponse *pSyncResp = reinterpret_cast<SyncMessageResponse*>(messageData + sizeof(WindowManagerMessage));
    if(m_pFramebuffer->getProvider().contextId !=
        pSyncResp->provider.contextId)
    {
        delete m_pFramebuffer;
        m_pFramebuffer = new PedigreeGraphics::Framebuffer(pSyncResp->provider);
    }

    return m_pFramebuffer;
    */
}

void Widget::checkForEvents(bool bAsync)
{
    /// \todo ALL created widgets, not just one.
    if(g_pWidget)
    {
        char *buffer = 0;
        PedigreeIpc::IpcMessage *pMessage = 0;
        if(g_PendingMessages.empty())
        {
            PedigreeIpc::recv(g_pWidget->m_Endpoint, &pMessage, true);
        }
        else
        {
            pMessage = g_PendingMessages.front();
            g_PendingMessages.pop();
        }

        if(pMessage)
        {
            buffer = static_cast<char *>(pMessage->getBuffer());

            LibUiProtocol::WindowManagerMessage *pHeader =
                reinterpret_cast<LibUiProtocol::WindowManagerMessage*>(buffer);

            widgetCallback_t cb = m_CallbackMap[pHeader->widgetHandle];

            switch(pHeader->messageCode)
            {
                case LibUiProtocol::Reposition:
                {
                    LibUiProtocol::RepositionMessage *pReposition =
                        reinterpret_cast<LibUiProtocol::RepositionMessage*>(buffer + sizeof(LibUiProtocol::WindowManagerMessage));
                    delete g_pWidget->m_SharedFramebuffer;
                    g_pWidget->m_SharedFramebuffer =
                            new PedigreeIpc::SharedIpcMessage(pReposition->shmem_size, pReposition->shmem_handle);
                    g_pWidget->m_SharedFramebuffer->initialise();

                    // Run the callback now that the framebuffer is re-created.
                    cb(::Reposition, sizeof(pReposition->rt), &pReposition->rt);
                    break;
                }
                case LibUiProtocol::KeyEvent:
                {
                    LibUiProtocol::KeyEventMessage *pKeyEvent =
                        reinterpret_cast<LibUiProtocol::KeyEventMessage*>(buffer + sizeof(LibUiProtocol::WindowManagerMessage));

                    cb(::KeyUp, sizeof(pKeyEvent->key), &pKeyEvent->key);
                    break;
                }
                default:
                    syslog(LOG_INFO, "** unknown event");
            }
        }

        if(pMessage)
        {
            delete pMessage;
        }
    }
}
<commit_msg>libui: Widget::redraw is now copy-free and also doesn't call getEndpoint<commit_after>/*
 * Copyright (c) 2011 Matthew Iselin
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include <Widget.h>

#include <ipc/Ipc.h>

/// \todo GTFO libc!
#include <unistd.h>

/// \todo GTFO libc!
#include <string.h>
#include <stdlib.h>
#include <syslog.h>

#include <map>
#include <queue>

#include "protocol.h"

using namespace LibUiProtocol;

#define PEDIGREE_WINMAN_ENDPOINT "pedigree-winman"

/// Default event handler for new widgets.
static bool defaultEventHandler(WidgetMessages message, size_t dataSize, void *dataBuffer)
{
    return false;
}

static Widget *g_pWidget = 0;

static PedigreeIpc::IpcEndpoint *g_pWinmanEndpoint = 0;

std::map<uint64_t, widgetCallback_t> Widget::m_CallbackMap;
std::queue<PedigreeIpc::IpcMessage *> g_PendingMessages;

Widget::Widget() :
    m_bConstructed(false), m_pFramebuffer(0), m_Handle(0),
    m_EventCallback(defaultEventHandler), m_Endpoint(0),
    m_SharedFramebuffer(0)
{
}

Widget::~Widget()
{
    if(m_Endpoint) {
        free((void *) m_Endpoint);
    }
}

bool Widget::construct(const char *endpoint, const char *title, widgetCallback_t cb, PedigreeGraphics::Rect &dimensions)
{
    if(m_Handle)
    {
        // Already constructed!
        return false;
    }

    /// \todo Maybe we can get a decent way of having a default handler?
    if(!cb)
        return false;

    // Create endpoint, if not already created.
    /// \todo fail if endpoint already exists.
    PedigreeIpc::createEndpoint(endpoint);
    m_Endpoint = PedigreeIpc::getEndpoint(endpoint);
    if(!g_pWinmanEndpoint)
    {
        g_pWinmanEndpoint = PedigreeIpc::getEndpoint(PEDIGREE_WINMAN_ENDPOINT);
    }

    // Construct the handle first.
    uint64_t pid = getpid();
    uintptr_t widgetPointer = reinterpret_cast<uintptr_t>(this);
#ifdef BITS_64
    m_Handle = (pid << 32) | (((widgetPointer >> 32) | (widgetPointer & 0xFFFFFFFF)) & 0xFFFFFFFF);
#else
    m_Handle = (pid << 32) | (widgetPointer);
#endif

    PedigreeIpc::IpcMessage *pCreateMessage = new PedigreeIpc::IpcMessage();
    if(!pCreateMessage->initialise())
    {
        m_Handle = 0;
        return false;
    }

    // Prepare a message to send.
    size_t totalSize = sizeof(WindowManagerMessage) + sizeof(CreateMessage);
    char *messageData = static_cast<char *>(pCreateMessage->getBuffer());
    WindowManagerMessage *pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
    CreateMessage *pCreate = reinterpret_cast<CreateMessage*>(messageData + sizeof(WindowManagerMessage));

    // Fill.
    pWinMan->messageCode = Create;
    pWinMan->messageSize = sizeof(CreateMessage);
    pWinMan->widgetHandle = m_Handle;
    pWinMan->isResponse = false;
    strlcpy(pCreate->endpoint, endpoint, 256);
    strlcpy(pCreate->title, title, 256);
    pCreate->minWidth = dimensions.getW();
    pCreate->minHeight = dimensions.getH();
    pCreate->rigid = true;

    // Send the message off to the window manager and wait for a response. The
    // response will contain a GraphicsProvider that we can use to create our
    // Framebuffer for drawing on.
    if(!PedigreeIpc::send(g_pWinmanEndpoint, pCreateMessage, false))
    {
        m_Handle = 0;
        delete pCreateMessage;
        return false;
    }

    PedigreeIpc::IpcMessage *pResponse = 0;

    while(1)
    {
        if(!PedigreeIpc::recv(m_Endpoint, &pResponse, false))
        {
            m_Handle = 0;
            return false;
        }

        if(!(pResponse && pResponse->getBuffer()))
        {
            continue;
        }

        pWinMan = reinterpret_cast<WindowManagerMessage*>(pResponse->getBuffer());
        if(!(pWinMan->isResponse && (pWinMan->messageCode == Create)))
        {
            g_PendingMessages.push(pResponse);
        }
        else
        {
            messageData = static_cast<char *>(pResponse->getBuffer());
            break;
        }
    }

    // Grab the results and use them.
    CreateMessageResponse *pCreateResp = reinterpret_cast<CreateMessageResponse*>(messageData + sizeof(WindowManagerMessage));
    m_EventCallback = cb;
    m_CallbackMap[m_Handle] = cb;

    delete pResponse;

    g_pWidget = this;

    // Asynchronously check for any events in the pipeline. This should be an
    // initial reposition event that we really need to get out to the client
    // ASAP.
    checkForEvents(true);

    return true;
}

bool Widget::setProperty(std::string propName, void *propVal, size_t maxSize)
{
    // Constructed yet?
    if(!m_Handle)
        return false;

    // Are the arguments sane?
    if(!propVal)
        return false;
    if(maxSize > 0x1000)
        return false;

    // Allocate the message.
    /// \todo Sanitise maxSize once large messages can be sent.
    size_t headerSize = sizeof(WindowManagerMessage) + sizeof(SetPropertyMessage);
    size_t totalSize = headerSize + maxSize;
    char *messageData = new char[totalSize];
    WindowManagerMessage *pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
    SetPropertyMessage *pMessage = reinterpret_cast<SetPropertyMessage*>(messageData + sizeof(WindowManagerMessage));

    // Fill the message.
    pWinMan->messageCode = SetProperty;
    pWinMan->messageSize = sizeof(SetPropertyMessage) + maxSize;
    pWinMan->widgetHandle = m_Handle;
    pWinMan->isResponse = false;

    propName.copy(pMessage->propertyName, sizeof pMessage->propertyName);
    pMessage->valueLength = maxSize;

    // Copy in the property data.
    memcpy(messageData + headerSize, propVal, maxSize);

    // Transmit.
    bool result = sendMessage(messageData, totalSize);

    // Clean up.
    delete [] messageData;

    return result;
}

bool Widget::getProperty(std::string propName, char **buffer, size_t maxSize)
{
    return false;
}

void Widget::setParent(Widget *pWidget)
{
}

Widget *Widget::getParent()
{
    return 0;
}

bool Widget::redraw(PedigreeGraphics::Rect &rt)
{
    // Constructed yet?
    if(!m_Handle)
        return false;

    // Allocate the message.
    PedigreeIpc::IpcMessage *pRedrawMessage = new PedigreeIpc::IpcMessage();
    if(!pRedrawMessage->initialise())
    {
        m_Handle = 0;
        return false;
    }

    size_t totalSize = sizeof(WindowManagerMessage) + sizeof(RequestRedrawMessage);
    char *messageData = static_cast<char *>(pRedrawMessage->getBuffer());
    WindowManagerMessage *pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
    RequestRedrawMessage *pMessage = reinterpret_cast<RequestRedrawMessage*>(messageData + sizeof(WindowManagerMessage));

    // Fill the message.
    pWinMan->messageCode = RequestRedraw;
    pWinMan->messageSize = sizeof(RequestRedrawMessage);
    pWinMan->widgetHandle = m_Handle;
    pWinMan->isResponse = false;
    pMessage->x = rt.getX();
    pMessage->y = rt.getY();
    pMessage->width = rt.getW();
    pMessage->height = rt.getH();

    // Transmit.
    if(!PedigreeIpc::send(g_pWinmanEndpoint, pRedrawMessage, false))
    {
        m_Handle = 0;
        delete pRedrawMessage;
        return false;
    }

    return true;
}

bool Widget::visibility(bool vis)
{
    // Constructed yet?
    if(!m_Handle)
        return false;

    // Allocate the message.
    size_t totalSize = sizeof(WindowManagerMessage) + sizeof(SetVisibilityMessage);
    char *messageData = new char[totalSize];
    WindowManagerMessage *pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
    SetVisibilityMessage *pMessage = reinterpret_cast<SetVisibilityMessage*>(messageData + sizeof(WindowManagerMessage));

    // Fill the message.
    pWinMan->messageCode = SetVisibility;
    pWinMan->messageSize = sizeof(SetVisibilityMessage);
    pWinMan->widgetHandle = m_Handle;
    pWinMan->isResponse = false;
    pMessage->bVisible = vis;

    // Transmit.
    bool result = sendMessage(messageData, totalSize);

    // Clean up.
    delete [] messageData;

    return result;
}

void Widget::destroy()
{
    // Constructed yet?
    if(!m_Handle)
        return;

    // Allocate the message.
    size_t totalSize = sizeof(WindowManagerMessage) + sizeof(DestroyMessage);
    char *messageData = new char[totalSize];
    WindowManagerMessage *pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
    DestroyMessage *pMessage = reinterpret_cast<DestroyMessage*>(messageData + sizeof(WindowManagerMessage));

    // Fill the message.
    pWinMan->messageCode = Destroy;
    pWinMan->messageSize = sizeof(DestroyMessage);
    pWinMan->widgetHandle = m_Handle;
    pWinMan->isResponse = false;

    // Transmit.
    sendMessage(messageData, totalSize);

    // Clean up.
    delete [] messageData;

    // Invalidate this widget now.
    delete m_pFramebuffer;
    m_Handle = 0;
}

PedigreeGraphics::Framebuffer *Widget::getFramebuffer()
{
    return 0;

    /*
    // Constructed yet?
    if(!m_Handle)
        return 0;

    // No framebuffer yet?
    if(!m_pFramebuffer)
        return 0;

    // Allocate the message.
    size_t totalSize = sizeof(WindowManagerMessage) + sizeof(SyncMessage);
    char *messageData = new char[totalSize];
    WindowManagerMessage *pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
    SyncMessage *pMessage = reinterpret_cast<SyncMessage*>(messageData + sizeof(WindowManagerMessage));

    // Fill the message.
    pWinMan->messageCode = Sync;
    pWinMan->messageSize = sizeof(SyncMessage);
    pWinMan->widgetHandle = m_Handle;
    pWinMan->isResponse = false;

    // Transmit, synchronously.
    syslog(LOG_INFO, "TX Sync [%d]", getpid());
    sendMessage(messageData, totalSize);
    syslog(LOG_INFO, "TX complete");

    delete [] messageData;

    // Get the response.
    totalSize = 1024;
    messageData = new char[totalSize];

    while(1)
    {
        if(!recvMessage(m_Endpoint, messageData, totalSize))
        {
            m_Handle = 0;
            delete [] messageData;
            return 0;
        }

        pWinMan = reinterpret_cast<WindowManagerMessage*>(messageData);
        if(!(pWinMan->isResponse && (pWinMan->messageCode == Sync)))
        {
            g_PendingMessages.push(messageData);
            messageData = new char[totalSize];
        }
        else
        {
            break;
        }
    }

    SyncMessageResponse *pSyncResp = reinterpret_cast<SyncMessageResponse*>(messageData + sizeof(WindowManagerMessage));
    if(m_pFramebuffer->getProvider().contextId !=
        pSyncResp->provider.contextId)
    {
        delete m_pFramebuffer;
        m_pFramebuffer = new PedigreeGraphics::Framebuffer(pSyncResp->provider);
    }

    return m_pFramebuffer;
    */
}

void Widget::checkForEvents(bool bAsync)
{
    /// \todo ALL created widgets, not just one.
    if(g_pWidget)
    {
        char *buffer = 0;
        PedigreeIpc::IpcMessage *pMessage = 0;
        if(g_PendingMessages.empty())
        {
            PedigreeIpc::recv(g_pWidget->m_Endpoint, &pMessage, bAsync);
        }
        else
        {
            pMessage = g_PendingMessages.front();
            g_PendingMessages.pop();
        }

        if(pMessage)
        {
            buffer = static_cast<char *>(pMessage->getBuffer());

            LibUiProtocol::WindowManagerMessage *pHeader =
                reinterpret_cast<LibUiProtocol::WindowManagerMessage*>(buffer);

            widgetCallback_t cb = m_CallbackMap[pHeader->widgetHandle];

            switch(pHeader->messageCode)
            {
                case LibUiProtocol::Reposition:
                {
                    LibUiProtocol::RepositionMessage *pReposition =
                        reinterpret_cast<LibUiProtocol::RepositionMessage*>(buffer + sizeof(LibUiProtocol::WindowManagerMessage));
                    delete g_pWidget->m_SharedFramebuffer;
                    g_pWidget->m_SharedFramebuffer =
                            new PedigreeIpc::SharedIpcMessage(pReposition->shmem_size, pReposition->shmem_handle);
                    g_pWidget->m_SharedFramebuffer->initialise();

                    // Run the callback now that the framebuffer is re-created.
                    cb(::Reposition, sizeof(pReposition->rt), &pReposition->rt);
                    break;
                }
                case LibUiProtocol::KeyEvent:
                {
                    LibUiProtocol::KeyEventMessage *pKeyEvent =
                        reinterpret_cast<LibUiProtocol::KeyEventMessage*>(buffer + sizeof(LibUiProtocol::WindowManagerMessage));

                    cb(::KeyUp, sizeof(pKeyEvent->key), &pKeyEvent->key);
                    break;
                }
                default:
                    syslog(LOG_INFO, "** unknown event");
            }
        }

        if(pMessage)
        {
            delete pMessage;
        }
    }
}
<|endoftext|>