<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/base/resource/resource_bundle.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/stl_util.h"
#include "base/string_piece.h"
#include "base/synchronization/lock.h"
#include "base/utf_string_conversions.h"
#include "build/build_config.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/data_pack.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/font.h"
#include "ui/gfx/image/image.h"

namespace ui {

namespace {

// Font sizes relative to base font.
#if defined(OS_CHROMEOS) && defined(CROS_FONTS_USING_BCI)
const int kSmallFontSizeDelta = -3;
const int kMediumFontSizeDelta = 2;
const int kLargeFontSizeDelta = 7;
#else
const int kSmallFontSizeDelta = -2;
const int kMediumFontSizeDelta = 3;
const int kLargeFontSizeDelta = 8;
#endif

}  // namespace

ResourceBundle* ResourceBundle::g_shared_instance_ = NULL;

// static
const SkColor ResourceBundle::toolbar_color =
     SkColorSetRGB(210, 225, 246);
const SkColor ResourceBundle::toolbar_separator_color =
     SkColorSetRGB(182, 186, 192);

// static
std::string ResourceBundle::InitSharedInstance(
    const std::string& pref_locale) {
  DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice";
  g_shared_instance_ = new ResourceBundle();

  g_shared_instance_->LoadCommonResources();
  return g_shared_instance_->LoadLocaleResources(pref_locale);
}

// static
void ResourceBundle::InitSharedInstanceForTest(const FilePath& path) {
  DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice";
  g_shared_instance_ = new ResourceBundle();

  g_shared_instance_->LoadTestResources(path);
}

// static
DataPack* ResourceBundle::LoadResourcesDataPak(const FilePath& path) {
  DataPack* datapack = new DataPack;
  bool success = datapack->Load(path);
  if (!success) {
    delete datapack;
    datapack = NULL;
  }
  return datapack;
}

// static
void ResourceBundle::AddDataPackToSharedInstance(const FilePath& path) {
  DCHECK(g_shared_instance_ != NULL) << "ResourceBundle not initialized";
  g_shared_instance_->data_packs_.push_back(new LoadedDataPack(path));
}

// static
void ResourceBundle::CleanupSharedInstance() {
  if (g_shared_instance_) {
    delete g_shared_instance_;
    g_shared_instance_ = NULL;
  }
}

// static
bool ResourceBundle::HasSharedInstance() {
  return g_shared_instance_ != NULL;
}

// static
ResourceBundle& ResourceBundle::GetSharedInstance() {
  // Must call InitSharedInstance before this function.
  CHECK(g_shared_instance_ != NULL);
  return *g_shared_instance_;
}

// static
bool ResourceBundle::LocaleDataPakExists(const std::string& locale) {
  return !GetLocaleFilePath(locale).empty();
}

#if !defined(OS_MACOSX)
// static
FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale) {
  FilePath locale_file_path;
  PathService::Get(ui::DIR_LOCALES, &locale_file_path);
  if (locale_file_path.empty())
    return locale_file_path;
  if (app_locale.empty())
    return FilePath();
  locale_file_path = locale_file_path.AppendASCII(app_locale + ".pak");
  if (!file_util::PathExists(locale_file_path))
    return FilePath();
  return locale_file_path;
}
#endif

std::string ResourceBundle::LoadLocaleResources(
    const std::string& pref_locale) {
  DCHECK(!locale_resources_data_.get()) << "locale.pak already loaded";
  std::string app_locale = l10n_util::GetApplicationLocale(pref_locale);
  FilePath locale_file_path = GetOverriddenPakPath();
  if (locale_file_path.empty()) {
    CommandLine *command_line = CommandLine::ForCurrentProcess();
    if (command_line->HasSwitch(switches::kLocalePak)) {
      locale_file_path =
          command_line->GetSwitchValuePath(switches::kLocalePak);
    } else {
      locale_file_path = GetLocaleFilePath(app_locale);
    }
  }
  if (locale_file_path.empty()) {
    // It's possible that there is no locale.pak.
    NOTREACHED();
    return std::string();
  }
  locale_resources_data_.reset(LoadResourcesDataPak(locale_file_path));
  if (!locale_resources_data_.get()) {
    UMA_HISTOGRAM_ENUMERATION("ResourceBundle.LoadLocaleResourcesError",
                              logging::GetLastSystemErrorCode(), 16000);
    NOTREACHED() << "failed to load locale.pak";
    return std::string();
  }
  return app_locale;
}

void ResourceBundle::UnloadLocaleResources() {
  locale_resources_data_.reset();
}

string16 ResourceBundle::GetLocalizedString(int message_id) {
  // Ensure that ReloadLocaleResources() doesn't drop the resources while
  // we're using them.
  base::AutoLock lock_scope(*locale_resources_data_lock_);

  // If for some reason we were unable to load the resources , return an empty
  // string (better than crashing).
  if (!locale_resources_data_.get()) {
    LOG(WARNING) << "locale resources are not loaded";
    return string16();
  }

  base::StringPiece data;
  if (!locale_resources_data_->GetStringPiece(message_id, &data)) {
    // Fall back on the main data pack (shouldn't be any strings here except in
    // unittests).
    data = GetRawDataResource(message_id);
    if (data.empty()) {
      NOTREACHED() << "unable to find resource: " << message_id;
      return string16();
    }
  }

  // Strings should not be loaded from a data pack that contains binary data.
  DCHECK(locale_resources_data_->GetTextEncodingType() == DataPack::UTF16 ||
         locale_resources_data_->GetTextEncodingType() == DataPack::UTF8)
      << "requested localized string from binary pack file";

  // Data pack encodes strings as either UTF8 or UTF16.
  string16 msg;
  if (locale_resources_data_->GetTextEncodingType() == DataPack::UTF16) {
    msg = string16(reinterpret_cast<const char16*>(data.data()),
                   data.length() / 2);
  } else if (locale_resources_data_->GetTextEncodingType() == DataPack::UTF8) {
    msg = UTF8ToUTF16(data);
  }
  return msg;
}

void ResourceBundle::OverrideLocalePakForTest(const FilePath& pak_path) {
  overridden_pak_path_ = pak_path;
}

const FilePath& ResourceBundle::GetOverriddenPakPath() {
  return overridden_pak_path_;
}

std::string ResourceBundle::ReloadLocaleResources(
    const std::string& pref_locale) {
  base::AutoLock lock_scope(*locale_resources_data_lock_);
  UnloadLocaleResources();
  return LoadLocaleResources(pref_locale);
}

SkBitmap* ResourceBundle::GetBitmapNamed(int resource_id) {
  const SkBitmap* bitmap =
      static_cast<const SkBitmap*>(GetImageNamed(resource_id));
  return const_cast<SkBitmap*>(bitmap);
}

gfx::Image& ResourceBundle::GetImageNamed(int resource_id) {
  // Check to see if the image is already in the cache.
  {
    base::AutoLock lock_scope(*images_and_fonts_lock_);
    ImageMap::const_iterator found = images_.find(resource_id);
    if (found != images_.end())
      return *found->second;
  }

  DCHECK(resources_data_) << "Missing call to SetResourcesDataDLL?";
  scoped_ptr<SkBitmap> bitmap(LoadBitmap(resources_data_, resource_id));
  if (bitmap.get()) {
    // Check if there's a large version of the image as well.
    scoped_ptr<SkBitmap> large_bitmap;
    if (large_icon_resources_data_)
      large_bitmap.reset(LoadBitmap(large_icon_resources_data_, resource_id));

    // The load was successful, so cache the image.
    base::AutoLock lock_scope(*images_and_fonts_lock_);

    // Another thread raced the load and has already cached the image.
    if (images_.count(resource_id))
      return *images_[resource_id];

    std::vector<const SkBitmap*> bitmaps;
    bitmaps.push_back(bitmap.release());
    if (large_bitmap.get())
      bitmaps.push_back(large_bitmap.release());
    gfx::Image* image = new gfx::Image(bitmaps);
    images_[resource_id] = image;
    return *image;
  }

  // The load failed to retrieve the image; show a debugging red square.
  LOG(WARNING) << "Unable to load image with id " << resource_id;
  NOTREACHED();  // Want to assert in debug mode.
  return *GetEmptyImage();
}

RefCountedStaticMemory* ResourceBundle::LoadDataResourceBytes(
    int resource_id) const {
  RefCountedStaticMemory* bytes =
      LoadResourceBytes(resources_data_, resource_id);

  // Check all our additional data packs for the resources if it wasn't loaded
  // from our main source.
  for (std::vector<LoadedDataPack*>::const_iterator it = data_packs_.begin();
       !bytes && it != data_packs_.end(); ++it) {
    bytes = (*it)->GetStaticMemory(resource_id);
  }

  return bytes;
}

const gfx::Font& ResourceBundle::GetFont(FontStyle style) {
  {
    base::AutoLock lock_scope(*images_and_fonts_lock_);
    LoadFontsIfNecessary();
  }
  switch (style) {
    case BoldFont:
      return *bold_font_;
    case SmallFont:
      return *small_font_;
    case MediumFont:
      return *medium_font_;
    case MediumBoldFont:
      return *medium_bold_font_;
    case LargeFont:
      return *large_font_;
    case LargeBoldFont:
      return *large_bold_font_;
    default:
      return *base_font_;
  }
}

void ResourceBundle::ReloadFonts() {
  base::AutoLock lock_scope(*images_and_fonts_lock_);
  base_font_.reset();
  LoadFontsIfNecessary();
}

ResourceBundle::ResourceBundle()
    : images_and_fonts_lock_(new base::Lock),
      locale_resources_data_lock_(new base::Lock),
      resources_data_(NULL),
      large_icon_resources_data_(NULL) {
}

void ResourceBundle::FreeImages() {
  STLDeleteContainerPairSecondPointers(images_.begin(),
                                       images_.end());
  images_.clear();
}

void ResourceBundle::LoadFontsIfNecessary() {
  images_and_fonts_lock_->AssertAcquired();
  if (!base_font_.get()) {
    base_font_.reset(new gfx::Font());

    bold_font_.reset(new gfx::Font());
    *bold_font_ =
        base_font_->DeriveFont(0, base_font_->GetStyle() | gfx::Font::BOLD);

    small_font_.reset(new gfx::Font());
    *small_font_ = base_font_->DeriveFont(kSmallFontSizeDelta);

    medium_font_.reset(new gfx::Font());
    *medium_font_ = base_font_->DeriveFont(kMediumFontSizeDelta);

    medium_bold_font_.reset(new gfx::Font());
    *medium_bold_font_ =
        base_font_->DeriveFont(kMediumFontSizeDelta,
                               base_font_->GetStyle() | gfx::Font::BOLD);

    large_font_.reset(new gfx::Font());
    *large_font_ = base_font_->DeriveFont(kLargeFontSizeDelta);

    large_bold_font_.reset(new gfx::Font());
    *large_bold_font_ =
        base_font_->DeriveFont(kLargeFontSizeDelta,
                               base_font_->GetStyle() | gfx::Font::BOLD);
  }
}

// static
SkBitmap* ResourceBundle::LoadBitmap(DataHandle data_handle, int resource_id) {
  scoped_refptr<RefCountedMemory> memory(
      LoadResourceBytes(data_handle, resource_id));
  if (!memory)
    return NULL;

  SkBitmap bitmap;
  if (!gfx::PNGCodec::Decode(memory->front(), memory->size(), &bitmap)) {
    NOTREACHED() << "Unable to decode theme image resource " << resource_id;
    return NULL;
  }

  return new SkBitmap(bitmap);
}

gfx::Image* ResourceBundle::GetEmptyImage() {
  base::AutoLock lock(*images_and_fonts_lock_);

  static gfx::Image* empty_image = NULL;
  if (!empty_image) {
    // The placeholder bitmap is bright red so people notice the problem.
    // This bitmap will be leaked, but this code should never be hit.
    SkBitmap* bitmap = new SkBitmap();
    bitmap->setConfig(SkBitmap::kARGB_8888_Config, 32, 32);
    bitmap->allocPixels();
    bitmap->eraseARGB(255, 255, 0, 0);
    empty_image = new gfx::Image(bitmap);
  }
  return empty_image;
}

// LoadedDataPack -------------------------------------------------------------

ResourceBundle::LoadedDataPack::LoadedDataPack(const FilePath& path)
    : path_(path) {
  // Always preload the data packs so we can maintain constness.
  Load();
}

ResourceBundle::LoadedDataPack::~LoadedDataPack() {
}

void ResourceBundle::LoadedDataPack::Load() {
  DCHECK(!data_pack_.get());
  data_pack_.reset(new ui::DataPack);
  bool success = data_pack_->Load(path_);
  LOG_IF(ERROR, !success) << "Failed to load " << path_.value()
      << "\nSome features may not be available.";
  if (!success)
    data_pack_.reset();
}

bool ResourceBundle::LoadedDataPack::GetStringPiece(
    int resource_id, base::StringPiece* data) const {
  if (!data_pack_.get())
    return false;
  return data_pack_->GetStringPiece(static_cast<uint32>(resource_id), data);
}

RefCountedStaticMemory* ResourceBundle::LoadedDataPack::GetStaticMemory(
    int resource_id) const {
  if (!data_pack_.get())
    return NULL;
  return data_pack_->GetStaticMemory(resource_id);
}

}  // namespace ui
<commit_msg>Don't build the general ResourceBundle::GetLocaleFilePath for Android either.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/base/resource/resource_bundle.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/stl_util.h"
#include "base/string_piece.h"
#include "base/synchronization/lock.h"
#include "base/utf_string_conversions.h"
#include "build/build_config.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/data_pack.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/font.h"
#include "ui/gfx/image/image.h"

namespace ui {

namespace {

// Font sizes relative to base font.
#if defined(OS_CHROMEOS) && defined(CROS_FONTS_USING_BCI)
const int kSmallFontSizeDelta = -3;
const int kMediumFontSizeDelta = 2;
const int kLargeFontSizeDelta = 7;
#else
const int kSmallFontSizeDelta = -2;
const int kMediumFontSizeDelta = 3;
const int kLargeFontSizeDelta = 8;
#endif

}  // namespace

ResourceBundle* ResourceBundle::g_shared_instance_ = NULL;

// static
const SkColor ResourceBundle::toolbar_color =
     SkColorSetRGB(210, 225, 246);
const SkColor ResourceBundle::toolbar_separator_color =
     SkColorSetRGB(182, 186, 192);

// static
std::string ResourceBundle::InitSharedInstance(
    const std::string& pref_locale) {
  DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice";
  g_shared_instance_ = new ResourceBundle();

  g_shared_instance_->LoadCommonResources();
  return g_shared_instance_->LoadLocaleResources(pref_locale);
}

// static
void ResourceBundle::InitSharedInstanceForTest(const FilePath& path) {
  DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice";
  g_shared_instance_ = new ResourceBundle();

  g_shared_instance_->LoadTestResources(path);
}

// static
DataPack* ResourceBundle::LoadResourcesDataPak(const FilePath& path) {
  DataPack* datapack = new DataPack;
  bool success = datapack->Load(path);
  if (!success) {
    delete datapack;
    datapack = NULL;
  }
  return datapack;
}

// static
void ResourceBundle::AddDataPackToSharedInstance(const FilePath& path) {
  DCHECK(g_shared_instance_ != NULL) << "ResourceBundle not initialized";
  g_shared_instance_->data_packs_.push_back(new LoadedDataPack(path));
}

// static
void ResourceBundle::CleanupSharedInstance() {
  if (g_shared_instance_) {
    delete g_shared_instance_;
    g_shared_instance_ = NULL;
  }
}

// static
bool ResourceBundle::HasSharedInstance() {
  return g_shared_instance_ != NULL;
}

// static
ResourceBundle& ResourceBundle::GetSharedInstance() {
  // Must call InitSharedInstance before this function.
  CHECK(g_shared_instance_ != NULL);
  return *g_shared_instance_;
}

// static
bool ResourceBundle::LocaleDataPakExists(const std::string& locale) {
  return !GetLocaleFilePath(locale).empty();
}

#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
// static
FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale) {
  FilePath locale_file_path;
  PathService::Get(ui::DIR_LOCALES, &locale_file_path);
  if (locale_file_path.empty())
    return locale_file_path;
  if (app_locale.empty())
    return FilePath();
  locale_file_path = locale_file_path.AppendASCII(app_locale + ".pak");
  if (!file_util::PathExists(locale_file_path))
    return FilePath();
  return locale_file_path;
}
#endif

std::string ResourceBundle::LoadLocaleResources(
    const std::string& pref_locale) {
  DCHECK(!locale_resources_data_.get()) << "locale.pak already loaded";
  std::string app_locale = l10n_util::GetApplicationLocale(pref_locale);
  FilePath locale_file_path = GetOverriddenPakPath();
  if (locale_file_path.empty()) {
    CommandLine *command_line = CommandLine::ForCurrentProcess();
    if (command_line->HasSwitch(switches::kLocalePak)) {
      locale_file_path =
          command_line->GetSwitchValuePath(switches::kLocalePak);
    } else {
      locale_file_path = GetLocaleFilePath(app_locale);
    }
  }
  if (locale_file_path.empty()) {
    // It's possible that there is no locale.pak.
    NOTREACHED();
    return std::string();
  }
  locale_resources_data_.reset(LoadResourcesDataPak(locale_file_path));
  if (!locale_resources_data_.get()) {
    UMA_HISTOGRAM_ENUMERATION("ResourceBundle.LoadLocaleResourcesError",
                              logging::GetLastSystemErrorCode(), 16000);
    NOTREACHED() << "failed to load locale.pak";
    return std::string();
  }
  return app_locale;
}

void ResourceBundle::UnloadLocaleResources() {
  locale_resources_data_.reset();
}

string16 ResourceBundle::GetLocalizedString(int message_id) {
  // Ensure that ReloadLocaleResources() doesn't drop the resources while
  // we're using them.
  base::AutoLock lock_scope(*locale_resources_data_lock_);

  // If for some reason we were unable to load the resources , return an empty
  // string (better than crashing).
  if (!locale_resources_data_.get()) {
    LOG(WARNING) << "locale resources are not loaded";
    return string16();
  }

  base::StringPiece data;
  if (!locale_resources_data_->GetStringPiece(message_id, &data)) {
    // Fall back on the main data pack (shouldn't be any strings here except in
    // unittests).
    data = GetRawDataResource(message_id);
    if (data.empty()) {
      NOTREACHED() << "unable to find resource: " << message_id;
      return string16();
    }
  }

  // Strings should not be loaded from a data pack that contains binary data.
  DCHECK(locale_resources_data_->GetTextEncodingType() == DataPack::UTF16 ||
         locale_resources_data_->GetTextEncodingType() == DataPack::UTF8)
      << "requested localized string from binary pack file";

  // Data pack encodes strings as either UTF8 or UTF16.
  string16 msg;
  if (locale_resources_data_->GetTextEncodingType() == DataPack::UTF16) {
    msg = string16(reinterpret_cast<const char16*>(data.data()),
                   data.length() / 2);
  } else if (locale_resources_data_->GetTextEncodingType() == DataPack::UTF8) {
    msg = UTF8ToUTF16(data);
  }
  return msg;
}

void ResourceBundle::OverrideLocalePakForTest(const FilePath& pak_path) {
  overridden_pak_path_ = pak_path;
}

const FilePath& ResourceBundle::GetOverriddenPakPath() {
  return overridden_pak_path_;
}

std::string ResourceBundle::ReloadLocaleResources(
    const std::string& pref_locale) {
  base::AutoLock lock_scope(*locale_resources_data_lock_);
  UnloadLocaleResources();
  return LoadLocaleResources(pref_locale);
}

SkBitmap* ResourceBundle::GetBitmapNamed(int resource_id) {
  const SkBitmap* bitmap =
      static_cast<const SkBitmap*>(GetImageNamed(resource_id));
  return const_cast<SkBitmap*>(bitmap);
}

gfx::Image& ResourceBundle::GetImageNamed(int resource_id) {
  // Check to see if the image is already in the cache.
  {
    base::AutoLock lock_scope(*images_and_fonts_lock_);
    ImageMap::const_iterator found = images_.find(resource_id);
    if (found != images_.end())
      return *found->second;
  }

  DCHECK(resources_data_) << "Missing call to SetResourcesDataDLL?";
  scoped_ptr<SkBitmap> bitmap(LoadBitmap(resources_data_, resource_id));
  if (bitmap.get()) {
    // Check if there's a large version of the image as well.
    scoped_ptr<SkBitmap> large_bitmap;
    if (large_icon_resources_data_)
      large_bitmap.reset(LoadBitmap(large_icon_resources_data_, resource_id));

    // The load was successful, so cache the image.
    base::AutoLock lock_scope(*images_and_fonts_lock_);

    // Another thread raced the load and has already cached the image.
    if (images_.count(resource_id))
      return *images_[resource_id];

    std::vector<const SkBitmap*> bitmaps;
    bitmaps.push_back(bitmap.release());
    if (large_bitmap.get())
      bitmaps.push_back(large_bitmap.release());
    gfx::Image* image = new gfx::Image(bitmaps);
    images_[resource_id] = image;
    return *image;
  }

  // The load failed to retrieve the image; show a debugging red square.
  LOG(WARNING) << "Unable to load image with id " << resource_id;
  NOTREACHED();  // Want to assert in debug mode.
  return *GetEmptyImage();
}

RefCountedStaticMemory* ResourceBundle::LoadDataResourceBytes(
    int resource_id) const {
  RefCountedStaticMemory* bytes =
      LoadResourceBytes(resources_data_, resource_id);

  // Check all our additional data packs for the resources if it wasn't loaded
  // from our main source.
  for (std::vector<LoadedDataPack*>::const_iterator it = data_packs_.begin();
       !bytes && it != data_packs_.end(); ++it) {
    bytes = (*it)->GetStaticMemory(resource_id);
  }

  return bytes;
}

const gfx::Font& ResourceBundle::GetFont(FontStyle style) {
  {
    base::AutoLock lock_scope(*images_and_fonts_lock_);
    LoadFontsIfNecessary();
  }
  switch (style) {
    case BoldFont:
      return *bold_font_;
    case SmallFont:
      return *small_font_;
    case MediumFont:
      return *medium_font_;
    case MediumBoldFont:
      return *medium_bold_font_;
    case LargeFont:
      return *large_font_;
    case LargeBoldFont:
      return *large_bold_font_;
    default:
      return *base_font_;
  }
}

void ResourceBundle::ReloadFonts() {
  base::AutoLock lock_scope(*images_and_fonts_lock_);
  base_font_.reset();
  LoadFontsIfNecessary();
}

ResourceBundle::ResourceBundle()
    : images_and_fonts_lock_(new base::Lock),
      locale_resources_data_lock_(new base::Lock),
      resources_data_(NULL),
      large_icon_resources_data_(NULL) {
}

void ResourceBundle::FreeImages() {
  STLDeleteContainerPairSecondPointers(images_.begin(),
                                       images_.end());
  images_.clear();
}

void ResourceBundle::LoadFontsIfNecessary() {
  images_and_fonts_lock_->AssertAcquired();
  if (!base_font_.get()) {
    base_font_.reset(new gfx::Font());

    bold_font_.reset(new gfx::Font());
    *bold_font_ =
        base_font_->DeriveFont(0, base_font_->GetStyle() | gfx::Font::BOLD);

    small_font_.reset(new gfx::Font());
    *small_font_ = base_font_->DeriveFont(kSmallFontSizeDelta);

    medium_font_.reset(new gfx::Font());
    *medium_font_ = base_font_->DeriveFont(kMediumFontSizeDelta);

    medium_bold_font_.reset(new gfx::Font());
    *medium_bold_font_ =
        base_font_->DeriveFont(kMediumFontSizeDelta,
                               base_font_->GetStyle() | gfx::Font::BOLD);

    large_font_.reset(new gfx::Font());
    *large_font_ = base_font_->DeriveFont(kLargeFontSizeDelta);

    large_bold_font_.reset(new gfx::Font());
    *large_bold_font_ =
        base_font_->DeriveFont(kLargeFontSizeDelta,
                               base_font_->GetStyle() | gfx::Font::BOLD);
  }
}

// static
SkBitmap* ResourceBundle::LoadBitmap(DataHandle data_handle, int resource_id) {
  scoped_refptr<RefCountedMemory> memory(
      LoadResourceBytes(data_handle, resource_id));
  if (!memory)
    return NULL;

  SkBitmap bitmap;
  if (!gfx::PNGCodec::Decode(memory->front(), memory->size(), &bitmap)) {
    NOTREACHED() << "Unable to decode theme image resource " << resource_id;
    return NULL;
  }

  return new SkBitmap(bitmap);
}

gfx::Image* ResourceBundle::GetEmptyImage() {
  base::AutoLock lock(*images_and_fonts_lock_);

  static gfx::Image* empty_image = NULL;
  if (!empty_image) {
    // The placeholder bitmap is bright red so people notice the problem.
    // This bitmap will be leaked, but this code should never be hit.
    SkBitmap* bitmap = new SkBitmap();
    bitmap->setConfig(SkBitmap::kARGB_8888_Config, 32, 32);
    bitmap->allocPixels();
    bitmap->eraseARGB(255, 255, 0, 0);
    empty_image = new gfx::Image(bitmap);
  }
  return empty_image;
}

// LoadedDataPack -------------------------------------------------------------

ResourceBundle::LoadedDataPack::LoadedDataPack(const FilePath& path)
    : path_(path) {
  // Always preload the data packs so we can maintain constness.
  Load();
}

ResourceBundle::LoadedDataPack::~LoadedDataPack() {
}

void ResourceBundle::LoadedDataPack::Load() {
  DCHECK(!data_pack_.get());
  data_pack_.reset(new ui::DataPack);
  bool success = data_pack_->Load(path_);
  LOG_IF(ERROR, !success) << "Failed to load " << path_.value()
      << "\nSome features may not be available.";
  if (!success)
    data_pack_.reset();
}

bool ResourceBundle::LoadedDataPack::GetStringPiece(
    int resource_id, base::StringPiece* data) const {
  if (!data_pack_.get())
    return false;
  return data_pack_->GetStringPiece(static_cast<uint32>(resource_id), data);
}

RefCountedStaticMemory* ResourceBundle::LoadedDataPack::GetStaticMemory(
    int resource_id) const {
  if (!data_pack_.get())
    return NULL;
  return data_pack_->GetStaticMemory(resource_id);
}

}  // namespace ui
<|endoftext|>


<commit_before>/// HEADER
#include "register_plugin.h"

/// COMPONENT
#include <csapex_scan_2d/scan_message.h>
#include <csapex_scan_2d/labeled_scan_message.h>

/// PROJECT
#include <csapex/msg/message_factory.h>
#include <csapex/model/tag.h>
#include <csapex_ros/ros_message_conversion.h>
#include <csapex/utility/register_apex_plugin.h>
#include <utils_laser_processing/data/segment.h>

/// SYSTEM
#include <sensor_msgs/LaserScan.h>

CSAPEX_REGISTER_CLASS(csapex::RegisterScan2DPlugin, csapex::CorePlugin)

using namespace csapex;

Q_DECLARE_METATYPE(lib_laser_processing::Scan)
Q_DECLARE_METATYPE(lib_laser_processing::LabeledScan)

struct ConvertScan
{
    template <typename A, typename B>
    static void copy(A& a, B& b) {
        b.header.frame_id = a.header.frame_id;
        b.header.seq      = a.header.seq;
        b.angle_min       = a.angle_min;
        b.angle_max       = a.angle_max;
        b.angle_increment = a.angle_increment;
        b.range_min       = a.range_min;
        b.range_max       = a.range_max;
    }

    static connection_types::ScanMessage::Ptr ros2apex(const sensor_msgs::LaserScan::ConstPtr &ros_msg) {
        connection_types::ScanMessage::Ptr out(new connection_types::ScanMessage);
        copy(*ros_msg, out->value);
        out->value = lib_laser_processing::Scan(ros_msg->ranges, ros_msg->angle_min, ros_msg->angle_increment);
        out->value.header.stamp_nsec = ros_msg->header.stamp.toNSec();
        return out;
    }
    static sensor_msgs::LaserScan::Ptr apex2ros(const connection_types::ScanMessage::Ptr& apex_msg) {
        sensor_msgs::LaserScan::Ptr out(new sensor_msgs::LaserScan);
        copy(apex_msg->value, *out);
        apex_msg->value.getRanges(out->ranges);
        out->header.stamp = out->header.stamp.fromNSec(apex_msg->value.header.stamp_nsec);
        return out;
    }
};

RegisterScan2DPlugin::RegisterScan2DPlugin()
{
}

void RegisterScan2DPlugin::init(CsApexCore& core)
{
    qRegisterMetaType < lib_laser_processing::Scan::Ptr > ("lib_laser_processing::Scan::Ptr");
    qRegisterMetaType < lib_laser_processing::LabeledScan::Ptr > ("lib_laser_processing::LabeledScan::Ptr");

    Tag::createIfNotExists("Features");

    RosMessageConversion::registerConversion<sensor_msgs::LaserScan, connection_types::ScanMessage, ConvertScan>();
}
<commit_msg>bugfix right initialization of scans<commit_after>/// HEADER
#include "register_plugin.h"

/// COMPONENT
#include <csapex_scan_2d/scan_message.h>
#include <csapex_scan_2d/labeled_scan_message.h>

/// PROJECT
#include <csapex/msg/message_factory.h>
#include <csapex/model/tag.h>
#include <csapex_ros/ros_message_conversion.h>
#include <csapex/utility/register_apex_plugin.h>
#include <utils_laser_processing/data/segment.h>

/// SYSTEM
#include <sensor_msgs/LaserScan.h>

CSAPEX_REGISTER_CLASS(csapex::RegisterScan2DPlugin, csapex::CorePlugin)

using namespace csapex;

Q_DECLARE_METATYPE(lib_laser_processing::Scan)
Q_DECLARE_METATYPE(lib_laser_processing::LabeledScan)

struct ConvertScan
{
    template <typename A, typename B>
    static void copy(A& a, B& b) {
        b.header.frame_id = a.header.frame_id;
        b.header.seq      = a.header.seq;
        b.angle_min       = a.angle_min;
        b.angle_max       = a.angle_max;
        b.angle_increment = a.angle_increment;
        b.range_min       = a.range_min;
        b.range_max       = a.range_max;
    }

    static connection_types::ScanMessage::Ptr ros2apex(const sensor_msgs::LaserScan::ConstPtr &ros_msg) {
        connection_types::ScanMessage::Ptr out(new connection_types::ScanMessage);
        out->value = lib_laser_processing::Scan(ros_msg->ranges, ros_msg->angle_min, ros_msg->angle_increment);
        copy(*ros_msg, out->value);
        out->value.header.stamp_nsec = ros_msg->header.stamp.toNSec();
        return out;
    }
    static sensor_msgs::LaserScan::Ptr apex2ros(const connection_types::ScanMessage::Ptr& apex_msg) {
        sensor_msgs::LaserScan::Ptr out(new sensor_msgs::LaserScan);
        copy(apex_msg->value, *out);
        apex_msg->value.getRanges(out->ranges);
        out->header.stamp = out->header.stamp.fromNSec(apex_msg->value.header.stamp_nsec);
        return out;
    }
};

RegisterScan2DPlugin::RegisterScan2DPlugin()
{
}

void RegisterScan2DPlugin::init(CsApexCore& core)
{
    qRegisterMetaType < lib_laser_processing::Scan::Ptr > ("lib_laser_processing::Scan::Ptr");
    qRegisterMetaType < lib_laser_processing::LabeledScan::Ptr > ("lib_laser_processing::LabeledScan::Ptr");

    Tag::createIfNotExists("Features");

    RosMessageConversion::registerConversion<sensor_msgs::LaserScan, connection_types::ScanMessage, ConvertScan>();
}
<|endoftext|>


<commit_before>#include "Wrapper.h"

#include <vector>

void CWrapper::Expose(void)
{
  py::class_<CJavascriptObject>("JSObject", py::no_init)
    .def("__getattr__", &CJavascriptObject::GetAttr)
    .def("__setattr__", &CJavascriptObject::SetAttr)
    .def("__delattr__", &CJavascriptObject::DelAttr)

    .def(int_(py::self))
    .def(float_(py::self))
    .def(str(py::self))

    .def("invoke", &CJavascriptObject::Invoke)
    ;

  py::objects::class_value_wrapper<boost::shared_ptr<CJavascriptObject>,
    py::objects::make_ptr_instance<CJavascriptObject,
    py::objects::pointer_holder<boost::shared_ptr<CJavascriptObject>,CJavascriptObject> > >();
}

py::object CWrapper::Cast(v8::Handle<v8::Value> obj)
{
  assert(v8::Context::InContext());

  v8::HandleScope handle_scope;

  if (obj->IsNull()) return py::object();
  if (obj->IsTrue()) return py::object(py::handle<>(Py_True));
  if (obj->IsFalse()) return py::object(py::handle<>(Py_False));

  if (obj->IsInt32()) return py::object(obj->Int32Value());
  if (obj->IsString()) return py::str(*obj->ToString());
  if (obj->IsBoolean()) return py::object(py::handle<>(obj->BooleanValue() ? Py_True : Py_False));
  if (obj->IsNumber()) return py::object(py::handle<>(::PyFloat_FromDouble(obj->NumberValue())));

  return py::object();
}

#define TRY_CONVERT(type, cls) { py::extract<type> value(obj); \
  if (value.check()) return handle_scope.Close(cls::New(value())); }

v8::Handle<v8::Value> CWrapper::Cast(py::object obj)
{
  assert(v8::Context::InContext());

  v8::HandleScope handle_scope;

  if (obj.ptr() == Py_None) return v8::Null();
  if (obj.ptr() == Py_True) return v8::True();
  if (obj.ptr() == Py_False) return v8::False();

  TRY_CONVERT(int, v8::Int32);
  TRY_CONVERT(const char *, v8::String);
  TRY_CONVERT(bool, v8::Boolean);
  TRY_CONVERT(double, v8::Number);

  return v8::Undefined();
}

v8::Handle<v8::Value> CPythonWrapper::Getter(
  v8::Local<v8::String> prop, const v8::AccessorInfo& info)
{
  v8::HandleScope handle_scope;

  CPythonWrapper *pThis = static_cast<CPythonWrapper *>(v8::Handle<v8::External>::Cast(info.Data())->Value());

  v8::Context::Scope context_scope(pThis->m_context);

  py::object obj = pThis->Unwrap(info.Holder());

  v8::String::AsciiValue name(prop);

  return handle_scope.Close(pThis->Wrap(obj.attr(*name)));
}

v8::Handle<v8::Value> CPythonWrapper::Setter(
  v8::Local<v8::String> prop, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
{
  v8::HandleScope handle_scope;

  CPythonWrapper *pThis = static_cast<CPythonWrapper *>(v8::Handle<v8::External>::Cast(info.Data())->Value());

  v8::Context::Scope context_scope(pThis->m_context);

  py::object obj = pThis->Unwrap(info.Holder());

  v8::String::AsciiValue name(prop), data(value);

  obj.attr(*name) = *data;

  return handle_scope.Close(pThis->Wrap(obj.attr(*name)));
}

v8::Handle<v8::Value> CPythonWrapper::Caller(const v8::Arguments& args)
{
  v8::HandleScope handle_scope;

  CPythonWrapper *pThis = static_cast<CPythonWrapper *>(v8::Handle<v8::External>::Cast(args.Data())->Value());

  v8::Handle<v8::Context> context(pThis->m_context);

  py::object self = pThis->Unwrap(args.This());

  py::object result;

  switch (args.Length())
  {
  case 0: result = self(); break;
  case 1: result = self(pThis->Unwrap(args[0])); break;
  case 2: result = self(pThis->Unwrap(args[0]), pThis->Unwrap(args[1])); break;
  case 3: result = self(pThis->Unwrap(args[0]), pThis->Unwrap(args[1]),
                        pThis->Unwrap(args[2])); break;
  case 4: result = self(pThis->Unwrap(args[0]), pThis->Unwrap(args[1]),
                        pThis->Unwrap(args[2]), pThis->Unwrap(args[3])); break;
  case 5: result = self(pThis->Unwrap(args[0]), pThis->Unwrap(args[1]),
                        pThis->Unwrap(args[2]), pThis->Unwrap(args[3]),
                        pThis->Unwrap(args[4])); break;
  case 6: result = self(pThis->Unwrap(args[0]), pThis->Unwrap(args[1]),
                        pThis->Unwrap(args[2]), pThis->Unwrap(args[3]),
                        pThis->Unwrap(args[4]), pThis->Unwrap(args[5])); break;
  default:
    throw CWrapperException("too many arguments");
  }

  return pThis->Wrap(result);
}

v8::Persistent<v8::ObjectTemplate> CPythonWrapper::SetupTemplate(void)
{
  v8::HandleScope handle_scope;

  v8::Handle<v8::ObjectTemplate> clazz = v8::ObjectTemplate::New();

  v8::Handle<v8::External> cookie = v8::External::New(this);

  clazz->SetInternalFieldCount(1);
  clazz->SetNamedPropertyHandler(Getter, Setter, 0, 0, 0, cookie);
  clazz->SetCallAsFunctionHandler(Caller, cookie);

  return v8::Persistent<v8::ObjectTemplate>::New(clazz);
}

v8::Handle<v8::Value> CPythonWrapper::Wrap(py::object obj)
{
  assert(v8::Context::InContext());

  v8::HandleScope handle_scope;

  v8::Handle<v8::Value> result = Cast(obj);

  if (!result->IsUndefined()) return handle_scope.Close(result);

  v8::Handle<v8::Object> instance = m_template->NewInstance();
  v8::Handle<v8::External> payload = v8::External::New(new py::object(obj));

  instance->SetInternalField(0, payload);

  return handle_scope.Close(instance);
}
py::object CPythonWrapper::Unwrap(v8::Handle<v8::Value> obj)
{
  assert(v8::Context::InContext());

  v8::HandleScope handle_scope;

  py::object result = Cast(obj);

  if (result) return result;

  if (obj->IsObject())
  {
    v8::Handle<v8::External> field = v8::Handle<v8::External>::Cast(obj->ToObject()->GetInternalField(0));

    return *static_cast<py::object *>(field->Value());
  }

  throw CWrapperException("unknown object type");
}

void CJavascriptObject::CheckAttr(v8::Handle<v8::String> name) const
{
  assert(v8::Context::InContext());

  if (!m_obj->Has(name))
  {
    std::ostringstream msg;

    msg << "'" << *m_obj->GetPrototype()->ToString() << "' object has no attribute '" << *name << "'";

    throw CWrapperException(msg.str(), ::PyExc_AttributeError);
  }
}

CJavascriptObjectPtr CJavascriptObject::GetAttr(const std::string& name)
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  v8::TryCatch try_catch;

  v8::Handle<v8::String> attr_name = v8::String::New(name.c_str());

  CheckAttr(attr_name);

  v8::Handle<v8::Value> attr_obj = m_obj->Get(attr_name);

  return CJavascriptObjectPtr(new CJavascriptObject(m_context, attr_obj->ToObject()));
}
void CJavascriptObject::SetAttr(const std::string& name, py::object value)
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  v8::Handle<v8::String> attr_name = v8::String::New(name.c_str());

  CheckAttr(attr_name);

  v8::Handle<v8::Value> attr_obj = Cast(value);

  m_obj->Set(attr_name, attr_obj);
}
void CJavascriptObject::DelAttr(const std::string& name)
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  v8::Handle<v8::String> attr_name = v8::String::New(name.c_str());

  CheckAttr(attr_name);

  m_obj->Delete(attr_name);
}

void CJavascriptObject::dump(std::ostream& os) const
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  if (m_obj->IsInt32())
    os << m_obj->Int32Value();
  else if (m_obj->IsNumber())
    os << m_obj->NumberValue();
  else if (m_obj->IsBoolean())
    os << m_obj->BooleanValue();
  else if (m_obj->IsNull())
    os << "None";
  else if (m_obj->IsUndefined())
    os << "N/A";
  else if (m_obj->IsString())
    os << *v8::String::AsciiValue(v8::Handle<v8::String>::Cast(m_obj));
  else
    os << *v8::String::AsciiValue(m_obj->ToString());
}

CJavascriptObject::operator long() const
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  return m_obj->Int32Value();
}
CJavascriptObject::operator double() const
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  return m_obj->NumberValue();
}

CJavascriptObjectPtr CJavascriptObject::Invoke(py::list args)
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(m_obj);

  std::vector< v8::Handle<v8::Value> > params(::PyList_Size(args.ptr()));

  for (size_t i=0; i<params.size(); i++)
  {

  }

  v8::Handle<v8::Value> result = func->Call(m_context->Global(), params.size(), &params[0]);

  return CJavascriptObjectPtr(new CJavascriptObject(m_context, result->ToObject()));
}

std::ostream& operator <<(std::ostream& os, const CJavascriptObject& obj)
{
  obj.dump(os);

  return os;
}
<commit_msg>#1, python wrapper's getter return null when attribute doesn't exist<commit_after>#include "Wrapper.h"

#include <vector>

void CWrapper::Expose(void)
{
  py::class_<CJavascriptObject>("JSObject", py::no_init)
    .def("__getattr__", &CJavascriptObject::GetAttr)
    .def("__setattr__", &CJavascriptObject::SetAttr)
    .def("__delattr__", &CJavascriptObject::DelAttr)

    .def(int_(py::self))
    .def(float_(py::self))
    .def(str(py::self))

    .def("invoke", &CJavascriptObject::Invoke)
    ;

  py::objects::class_value_wrapper<boost::shared_ptr<CJavascriptObject>,
    py::objects::make_ptr_instance<CJavascriptObject,
    py::objects::pointer_holder<boost::shared_ptr<CJavascriptObject>,CJavascriptObject> > >();
}

py::object CWrapper::Cast(v8::Handle<v8::Value> obj)
{
  assert(v8::Context::InContext());

  v8::HandleScope handle_scope;

  if (obj->IsNull()) return py::object();
  if (obj->IsTrue()) return py::object(py::handle<>(Py_True));
  if (obj->IsFalse()) return py::object(py::handle<>(Py_False));

  if (obj->IsInt32()) return py::object(obj->Int32Value());
  if (obj->IsString()) return py::str(*obj->ToString());
  if (obj->IsBoolean()) return py::object(py::handle<>(obj->BooleanValue() ? Py_True : Py_False));
  if (obj->IsNumber()) return py::object(py::handle<>(::PyFloat_FromDouble(obj->NumberValue())));

  return py::object();
}

#define TRY_CONVERT(type, cls) { py::extract<type> value(obj); \
  if (value.check()) return handle_scope.Close(cls::New(value())); }

v8::Handle<v8::Value> CWrapper::Cast(py::object obj)
{
  assert(v8::Context::InContext());

  v8::HandleScope handle_scope;

  if (obj.ptr() == Py_None) return v8::Null();
  if (obj.ptr() == Py_True) return v8::True();
  if (obj.ptr() == Py_False) return v8::False();

  TRY_CONVERT(int, v8::Int32);
  TRY_CONVERT(const char *, v8::String);
  TRY_CONVERT(bool, v8::Boolean);
  TRY_CONVERT(double, v8::Number);

  return v8::Undefined();
}

v8::Handle<v8::Value> CPythonWrapper::Getter(
  v8::Local<v8::String> prop, const v8::AccessorInfo& info)
{
  v8::HandleScope handle_scope;

  CPythonWrapper *pThis = static_cast<CPythonWrapper *>(v8::Handle<v8::External>::Cast(info.Data())->Value());

  v8::Context::Scope context_scope(pThis->m_context);

  py::object obj = pThis->Unwrap(info.Holder());

  v8::String::AsciiValue name(prop);

  py::str attr_name(*name, name.length());

  if (!::PyObject_HasAttr(obj.ptr(), attr_name.ptr()))
    return v8::Local<v8::Value>();

  return handle_scope.Close(pThis->Wrap(obj.attr(*name)));
}

v8::Handle<v8::Value> CPythonWrapper::Setter(
  v8::Local<v8::String> prop, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
{
  v8::HandleScope handle_scope;

  CPythonWrapper *pThis = static_cast<CPythonWrapper *>(v8::Handle<v8::External>::Cast(info.Data())->Value());

  v8::Context::Scope context_scope(pThis->m_context);

  py::object obj = pThis->Unwrap(info.Holder());

  v8::String::AsciiValue name(prop), data(value);

  obj.attr(*name) = *data;

  return handle_scope.Close(pThis->Wrap(obj.attr(*name)));
}

v8::Handle<v8::Value> CPythonWrapper::Caller(const v8::Arguments& args)
{
  v8::HandleScope handle_scope;

  CPythonWrapper *pThis = static_cast<CPythonWrapper *>(v8::Handle<v8::External>::Cast(args.Data())->Value());

  v8::Handle<v8::Context> context(pThis->m_context);

  py::object self = pThis->Unwrap(args.This());

  py::object result;

  switch (args.Length())
  {
  case 0: result = self(); break;
  case 1: result = self(pThis->Unwrap(args[0])); break;
  case 2: result = self(pThis->Unwrap(args[0]), pThis->Unwrap(args[1])); break;
  case 3: result = self(pThis->Unwrap(args[0]), pThis->Unwrap(args[1]),
                        pThis->Unwrap(args[2])); break;
  case 4: result = self(pThis->Unwrap(args[0]), pThis->Unwrap(args[1]),
                        pThis->Unwrap(args[2]), pThis->Unwrap(args[3])); break;
  case 5: result = self(pThis->Unwrap(args[0]), pThis->Unwrap(args[1]),
                        pThis->Unwrap(args[2]), pThis->Unwrap(args[3]),
                        pThis->Unwrap(args[4])); break;
  case 6: result = self(pThis->Unwrap(args[0]), pThis->Unwrap(args[1]),
                        pThis->Unwrap(args[2]), pThis->Unwrap(args[3]),
                        pThis->Unwrap(args[4]), pThis->Unwrap(args[5])); break;
  default:
    throw CWrapperException("too many arguments");
  }

  return pThis->Wrap(result);
}

v8::Persistent<v8::ObjectTemplate> CPythonWrapper::SetupTemplate(void)
{
  v8::HandleScope handle_scope;

  v8::Handle<v8::ObjectTemplate> clazz = v8::ObjectTemplate::New();

  v8::Handle<v8::External> cookie = v8::External::New(this);

  clazz->SetInternalFieldCount(1);
  clazz->SetNamedPropertyHandler(Getter, Setter, 0, 0, 0, cookie);
  clazz->SetCallAsFunctionHandler(Caller, cookie);

  return v8::Persistent<v8::ObjectTemplate>::New(clazz);
}

v8::Handle<v8::Value> CPythonWrapper::Wrap(py::object obj)
{
  assert(v8::Context::InContext());

  v8::HandleScope handle_scope;

  v8::Handle<v8::Value> result = Cast(obj);

  if (!result->IsUndefined()) return handle_scope.Close(result);

  v8::Handle<v8::Object> instance = m_template->NewInstance();
  v8::Handle<v8::External> payload = v8::External::New(new py::object(obj));

  instance->SetInternalField(0, payload);

  return handle_scope.Close(instance);
}
py::object CPythonWrapper::Unwrap(v8::Handle<v8::Value> obj)
{
  assert(v8::Context::InContext());

  v8::HandleScope handle_scope;

  py::object result = Cast(obj);

  if (result) return result;

  if (obj->IsObject())
  {
    v8::Handle<v8::External> field = v8::Handle<v8::External>::Cast(obj->ToObject()->GetInternalField(0));

    return *static_cast<py::object *>(field->Value());
  }

  throw CWrapperException("unknown object type");
}

void CJavascriptObject::CheckAttr(v8::Handle<v8::String> name) const
{
  assert(v8::Context::InContext());

  if (!m_obj->Has(name))
  {
    std::ostringstream msg;

    msg << "'" << *m_obj->GetPrototype()->ToString() << "' object has no attribute '" << *name << "'";

    throw CWrapperException(msg.str(), ::PyExc_AttributeError);
  }
}

CJavascriptObjectPtr CJavascriptObject::GetAttr(const std::string& name)
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  v8::TryCatch try_catch;

  v8::Handle<v8::String> attr_name = v8::String::New(name.c_str());

  CheckAttr(attr_name);

  v8::Handle<v8::Value> attr_obj = m_obj->Get(attr_name);

  return CJavascriptObjectPtr(new CJavascriptObject(m_context, attr_obj->ToObject()));
}
void CJavascriptObject::SetAttr(const std::string& name, py::object value)
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  v8::Handle<v8::String> attr_name = v8::String::New(name.c_str());

  CheckAttr(attr_name);

  v8::Handle<v8::Value> attr_obj = Cast(value);

  m_obj->Set(attr_name, attr_obj);
}
void CJavascriptObject::DelAttr(const std::string& name)
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  v8::Handle<v8::String> attr_name = v8::String::New(name.c_str());

  CheckAttr(attr_name);

  m_obj->Delete(attr_name);
}

void CJavascriptObject::dump(std::ostream& os) const
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  if (m_obj->IsInt32())
    os << m_obj->Int32Value();
  else if (m_obj->IsNumber())
    os << m_obj->NumberValue();
  else if (m_obj->IsBoolean())
    os << m_obj->BooleanValue();
  else if (m_obj->IsNull())
    os << "None";
  else if (m_obj->IsUndefined())
    os << "N/A";
  else if (m_obj->IsString())
    os << *v8::String::AsciiValue(v8::Handle<v8::String>::Cast(m_obj));
  else
    os << *v8::String::AsciiValue(m_obj->ToString());
}

CJavascriptObject::operator long() const
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  return m_obj->Int32Value();
}
CJavascriptObject::operator double() const
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  return m_obj->NumberValue();
}

CJavascriptObjectPtr CJavascriptObject::Invoke(py::list args)
{
  v8::HandleScope handle_scope;

  v8::Context::Scope context_scope(m_context);

  v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(m_obj);

  std::vector< v8::Handle<v8::Value> > params(::PyList_Size(args.ptr()));

  for (size_t i=0; i<params.size(); i++)
  {

  }

  v8::Handle<v8::Value> result = func->Call(m_context->Global(), params.size(), &params[0]);

  return CJavascriptObjectPtr(new CJavascriptObject(m_context, result->ToObject()));
}

std::ostream& operator <<(std::ostream& os, const CJavascriptObject& obj)
{
  obj.dump(os);

  return os;
}
<|endoftext|>


<commit_before>#pragma once

#include "mmu.h"
#include "atomic.hh"

struct cilkframe;
using std::atomic;

extern atomic<u64> tlbflush_req;

// Per-CPU state
struct cpu {
  cpuid_t id;                  // Index into cpus[] below
  hwid_t hwid;                 // Local APIC ID
  int ncli;                    // Depth of pushcli nesting.
  int intena;                  // Were interrupts enabled before pushcli?
  struct segdesc gdt[NSEGS];   // x86 global descriptor table
  struct taskstate ts;         // Used by x86 to find stack for interrupt
  struct context *scheduler;   // swtch() here to enter scheduler
  struct cilkframe *cilkframe;
  int timer_printpc;
  atomic<u64> tlbflush_done;   // last tlb flush req done on this cpu
  struct proc *prev;           // The previously-running process

  // Cpu-local storage variables; see below
  struct cpu *cpu;
  struct proc *proc;           // The currently-running process.
  struct kmem *kmem;           // The per-core memory table
} __mpalign__;

extern struct cpu cpus[NCPU];

// Per-CPU variables, holding pointers to the
// current cpu and to the current process.
// XXX(sbw) asm labels default to RIP-relative and
// I don't know how to force absolute addressing.
static inline struct cpu *
mycpu(void)
{
  u64 val;
  __asm volatile("movq %%gs:0, %0" : "=r" (val));
  return (struct cpu *)val;
}

static inline struct proc *
myproc(void)
{
  u64 val;
  __asm volatile("movq %%gs:8, %0" : "=r" (val));
  return (struct proc *)val;
}

static inline struct kmem *
mykmem(void)
{
  u64 val;
  __asm volatile("movq %%gs:16, %0" : "=r" (val));
  return (struct kmem *)val;
}

static inline cpuid_t
myid(void)
{
  return mycpu()->id;
}
<commit_msg>move cpus::hwid to a separate cache line to avoid false sharing, as detected by mtrace.<commit_after>#pragma once

#include "mmu.h"
#include "atomic.hh"

struct cilkframe;
using std::atomic;

extern atomic<u64> tlbflush_req;

// Per-CPU state
struct cpu {
  cpuid_t id;                  // Index into cpus[] below
  int ncli;                    // Depth of pushcli nesting.
  int intena;                  // Were interrupts enabled before pushcli?
  struct segdesc gdt[NSEGS];   // x86 global descriptor table
  struct taskstate ts;         // Used by x86 to find stack for interrupt
  struct context *scheduler;   // swtch() here to enter scheduler
  struct cilkframe *cilkframe;
  int timer_printpc;
  atomic<u64> tlbflush_done;   // last tlb flush req done on this cpu
  struct proc *prev;           // The previously-running process

  hwid_t hwid __mpalign__;     // Local APIC ID, accessed by other CPUs

  // Cpu-local storage variables; see below
  struct cpu *cpu;
  struct proc *proc;           // The currently-running process.
  struct kmem *kmem;           // The per-core memory table
} __mpalign__;

extern struct cpu cpus[NCPU];

// Per-CPU variables, holding pointers to the
// current cpu and to the current process.
// XXX(sbw) asm labels default to RIP-relative and
// I don't know how to force absolute addressing.
static inline struct cpu *
mycpu(void)
{
  u64 val;
  __asm volatile("movq %%gs:0, %0" : "=r" (val));
  return (struct cpu *)val;
}

static inline struct proc *
myproc(void)
{
  u64 val;
  __asm volatile("movq %%gs:8, %0" : "=r" (val));
  return (struct proc *)val;
}

static inline struct kmem *
mykmem(void)
{
  u64 val;
  __asm volatile("movq %%gs:16, %0" : "=r" (val));
  return (struct kmem *)val;
}

static inline cpuid_t
myid(void)
{
  return mycpu()->id;
}
<|endoftext|>


<commit_before>#ifdef WIN32
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <windows.h>
#endif

#include "allocation_monitor.h"
#include "cor_algorithm/sources/bit_operation.h"
#include <mutex>
#include <string.h>

//#define COR_ALLOCATION_MONITOR_INDEX_COUNT
//#define COR_ALLOCATION_MONITOR_LEAK_CHECK

//#define COR_ALLOCATION_MONITOR_CAPTURE_MODE

#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
#include <typeinfo.h>
#include <iostream>
#endif

namespace cor
{
    namespace system
    {
        struct AllocationMonitorItnl
        {
            struct AllocInfo;
            typedef AllocInfo* AllocInfoPtr;
            struct AllocInfo
            {
                void* ptr;
                size_t n;
                AllocInfoPtr next;
                AllocInfoPtr prev;

                void init(void* ptr, size_t n)
                {
                    this->n = n;
                    this->ptr = ptr;
                    this->next = this;
                    this->prev = this;
                }

                void remove() {
                    this->next->prev = this->prev;
                    this->prev->next = this->next;

                    this->prev = this;
                    this->next = this;
                }

                void insert(AllocInfoPtr p) {
                    p->remove();
                    p->prev = this->prev;
                    p->next = this;
                    this->prev->next = p;
                    this->prev = p;
                }
            };

            static const size_t AllocInfoTableSize = 4049;
            struct AllocInfoTable
            {
                AllocInfo table[AllocInfoTableSize];

                AllocInfoTable() {
                    for(size_t i = 0; i < AllocInfoTableSize; i++)
                    {
                        table[i].init(nullptr, 0);
                    }
                }

                size_t hash(void* p)
                {
                    return ((size_t)p) % AllocInfoTableSize;
                }

                AllocInfoPtr insert(void* p, size_t n)
                {
                    AllocInfoPtr ap = static_cast<AllocInfoPtr>(::malloc(sizeof(AllocInfo)));
                    ap->init(p, n);
                    auto k = hash(p);
                    table[k].insert(ap);
                    return ap;
                }

                AllocInfoPtr find(void* p)
                {
                    auto k = hash(p);
                    auto ap = table[k].next;
                    while(ap != &table[k])
                    {
                        if(p == ap->ptr)
                        {
                            return ap;
                        }
                        ap = ap->next;
                    }
                    return nullptr;
                }

                void remove(void* p)
                {
                    auto k = hash(p);
                    auto ap = find(p);
                    if(ap)
                    {
                        ap->remove();
                        ::free(static_cast<void*>(ap));
                    }

                }

                void remove(AllocInfoPtr ap)
                {
                    if(ap)
                    {
                        ap->remove();
                        ::free(static_cast<void*>(ap));
                    }
                }
            };

            struct Header;
            typedef Header* HeaderPtr;
            struct Header
            {
#ifdef COR_ALLOCATION_MONITOR_INDEX_COUNT
                size_t count;
#endif
#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
                RInt32 mark;
                RInt32 captured_index;
#endif
                size_t size;
                size_t n;
                HeaderPtr next;
                RBool freed;
            };

            AllocInfoTable alloc_info_table;

            RSize new_count;
            RSize delete_count;
            RSize alloced_size;
            RSize illigal_free_count;
            RSize alloc_size;
            RBool available;

            static const RSize freed_table_size = 64 + 1;
            HeaderPtr freed_table[freed_table_size];

#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
            RSize captured_count;
            RInt32 captured_status;
            struct Captured
            {
                HeaderPtr p;
                RInt32 status;
            };
            Captured captured_list[1024 * 1024 * 20];
#endif

            std::recursive_mutex mutex;

        };

        PAllocationMonitor& AllocationMonitor::ref_instance_pointer()
        {
            //static AllocationMonitor amo;
            static PAllocationMonitor am;
            return am;
        }

        AllocationMonitor::AllocationMonitor()
        {
            static AllocationMonitorItnl itnl_;
            itnl = &itnl_;
            //ref_instance_pointer() = this;

            itnl->new_count = 0;
            itnl->delete_count = 0;
            itnl->alloc_size = 0;
            itnl->available = rtrue;

            RSize i, isz;
            isz = AllocationMonitorItnl::freed_table_size;
            for(i = 0; i < isz; i++)
            {
                itnl->freed_table[i] = nullptr;
            }
#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
            itnl->captured_count = 0;
            itnl->captured_status = 0;
#endif
        }

        AllocationMonitor::~AllocationMonitor()
        {
            RSize i, isz;
            isz = AllocationMonitorItnl::freed_table_size;
            for(i = 0; i < isz; i++)
            {
                while(itnl->freed_table[i])
                {
                    auto h = itnl->freed_table[i];
                    itnl->freed_table[i] = h->next;
                    ::free(h);
                }
            }

            itnl->available = rfalse;

            //ref_instance_pointer() = NULL;
        }

        RSize AllocationMonitor::get_new_count()
        {
            return itnl->new_count;
        }

        RSize AllocationMonitor::get_delete_count()
        {
            return itnl->delete_count;
        }

        RSize AllocationMonitor::get_alloc_count()
        {
            return itnl->new_count - itnl->delete_count;
        }

        RSize AllocationMonitor::get_alloc_size()
        {
            return itnl->alloc_size;
        }

        RString AllocationMonitor::get_status_text()
        {
            RStringStream s;
            //s << "new_count " << get_new_count();
            //s << ", delete_count " << get_delete_count();
            //s << ", alloc_count " << get_alloc_count();
            s << "alloc_count " << get_alloc_count();
            s << ", alloc_size " << get_alloc_size();
            return s.str();
        }

        void AllocationMonitor::set_captured_status(RInt32 captured_status)
        {
#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
            itnl->captured_status = captured_status;
#endif
        }

        RInt32 AllocationMonitor::get_captured_status()
        {
#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
            return itnl->captured_status;
#else
            return 0;
#endif
        }

#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
        class AllocationMonitorBaseT
        {
            AllocationMonitorBaseT(){}
            virtual ~AllocationMonitorBaseT(){}
        };
#endif

        RString AllocationMonitor::get_captured_data()
        {
#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE

            std::vector<RString> data;
            RSize sz = itnl->captured_count;
            for(RSize i = 0 ; i < sz ; i++)
            {
                if(itnl->captured_list[i].p)
                {
                    RStringStream s;
                    RBytePtr bp = (RBytePtr)itnl->captured_list[i].p;
                    bp += sizeof(AllocationMonitorItnl::Header);
                    //s << (RSize)bp;
                    //s << ":";
                    s << i;
                    s << ":";
                    s << itnl->captured_list[i].p->captured_index;
                    s << ":";
                    s << itnl->captured_list[i].p->n;
                    s << ":";
                    //try
                    //{
                    //    s << typeid(*(AllocationMonitorBaseT*)bp).name();
                    //    s << ":";
                    //}
                    //catch(std::__non_rtti_object& bt)
                    //{
                    //    s << "no rtti";
                    //    s << ":";
                    //}
                    //catch(std::bad_typeid& bt)
                    //{
                    //    s << "no name";
                    //    s << ":";
                    //}
                    s << itnl->captured_list[i].status;
                    OutputDebugStringA((s.str() + "\n").c_str());
                    data.push_back(s.str());
                }

            }
            RString str;
            for(auto i : data)
            {
                str += i;
                str += "\n";
            }
            return str;
#else
            return RString();
#endif
        }

        void AllocationMonitor::clear_caputred_data()
        {
#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
            itnl->captured_count = 0;
#endif
        }

        PAllocationMonitor AllocationMonitor::get_instance()
        {
            //PAllocationMonitor& am = ref_instance_pointer();
            static AllocationMonitor amo;
            return &amo;
        }

#ifdef COR_ALLOCATION_MONITOR_LEAK_CHECK
#ifdef WIN32
        struct LeakCheck
        {
            LeakCheck()
            {
                _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
            }

            ~LeakCheck()
            {
                //_CrtDumpMemoryLeaks();
            }
        };
        LeakCheck lc;
#endif
#endif

        void* AllocationMonitor::alloc(size_t n)
        {
            PAllocationMonitor am = get_instance();
            AllocationMonitorItnl* itnl = am->itnl;
            if(am && itnl->available)
            {
                itnl->mutex.lock();

            }

            void* p = nullptr;
            p = ::malloc(n);

            itnl->alloc_info_table.insert(p, n);

            if(am && itnl->available)
            {

                itnl->alloc_size += n;
                itnl->new_count++;
                itnl->mutex.unlock();

            }

            return p;

        }

        void AllocationMonitor::al_free(void* p)
        {
            if(!p)
            {
                return;
            }

            PAllocationMonitor am = get_instance();
            AllocationMonitorItnl* itnl = am->itnl;
            if(am && itnl->available)
            {
                itnl->mutex.lock();

                auto ap = itnl->alloc_info_table.find(p);
                if(ap)
                {
                    itnl->alloc_size -= ap->n;
                    itnl->alloc_info_table.remove(ap);
                }

            }

            ::free(p);

            if(am && itnl->available)
            {
                itnl->delete_count++;
                itnl->mutex.unlock();
            }

        }

        void* AllocationMonitor::al_realloc(void* p, size_t n)
        {
            PAllocationMonitor am = get_instance();
            AllocationMonitorItnl* itnl = am->itnl;
            if(am && itnl->available)
            {
                itnl->mutex.lock();

                auto ap = itnl->alloc_info_table.find(p);
                if(ap)
                {
                    itnl->alloc_size -= ap->n;
                    itnl->alloc_info_table.remove(ap);
                }

            }

            void* np;

            np = ::realloc(p, n);

            if(am && itnl->available)
            {
                if(!p || !np)
                {
                    if(p)
                    {
                        itnl->delete_count++;
                    }
                    if(np)
                    {
                        itnl->alloc_info_table.insert(np, n);
                        itnl->new_count++;
                    }
                }
                itnl->mutex.unlock();

                //itnl->alloc_size -= sz;
                //itnl->delete_count++;

            }

            return np;
        }

    }
}

//#if 0
//#ifdef COR_CUSTOM_NEW_OPERATOR
void* operator new(size_t n) throw(std::bad_alloc)
{
    return cor::system::AllocationMonitor::alloc(n);
}

void operator delete(void* p) throw()
{
    return cor::system::AllocationMonitor::al_free(p);
}

void* operator new[](size_t n) throw(std::bad_alloc)
{
    return cor::system::AllocationMonitor::alloc(n);
}

void operator delete[](void* p) throw()
{
    return cor::system::AllocationMonitor::al_free(p);
}
//#endif
//#endif

<commit_msg>fix: allocation<commit_after>#ifdef WIN32
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <windows.h>
#endif

#include "allocation_monitor.h"
#include "cor_algorithm/sources/bit_operation.h"
#include <mutex>
#include <string.h>

//#define COR_ALLOCATION_MONITOR_INDEX_COUNT
//#define COR_ALLOCATION_MONITOR_LEAK_CHECK

//#define COR_ALLOCATION_MONITOR_CAPTURE_MODE

#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
#include <typeinfo.h>
#include <iostream>
#endif

namespace cor
{
    namespace system
    {
        struct AllocationMonitorItnl
        {
            struct AllocInfo;
            typedef AllocInfo* AllocInfoPtr;
            struct AllocInfo
            {
                void* ptr;
                size_t n;
                AllocInfoPtr next;
                AllocInfoPtr prev;

                void init(void* ptr, size_t n)
                {
                    this->n = n;
                    this->ptr = ptr;
                    this->next = this;
                    this->prev = this;
                }

                void remove() {
                    this->next->prev = this->prev;
                    this->prev->next = this->next;

                    this->prev = this;
                    this->next = this;
                }

                void insert(AllocInfoPtr p) {
                    p->remove();
                    p->prev = this->prev;
                    p->next = this;
                    this->prev->next = p;
                    this->prev = p;
                }
            };

            static const size_t AllocInfoTableSize = 4049;
            struct AllocInfoTable
            {
                AllocInfo table[AllocInfoTableSize];

                AllocInfoTable() {
                    for(size_t i = 0; i < AllocInfoTableSize; i++)
                    {
                        table[i].init(nullptr, 0);
                    }
                }

                size_t hash(void* p)
                {
                    return ((size_t)p) % AllocInfoTableSize;
                }

                AllocInfoPtr insert(void* p, size_t n)
                {
                    AllocInfoPtr ap = static_cast<AllocInfoPtr>(::malloc(sizeof(AllocInfo)));
                    ap->init(p, n);
                    auto k = hash(p);
                    table[k].insert(ap);
                    return ap;
                }

                AllocInfoPtr find(void* p)
                {
                    auto k = hash(p);
                    auto ap = table[k].next;
                    while(ap != &table[k])
                    {
                        if(p == ap->ptr)
                        {
                            return ap;
                        }
                        ap = ap->next;
                    }
                    return nullptr;
                }

                void remove(void* p)
                {
                    auto k = hash(p);
                    auto ap = find(p);
                    if(ap)
                    {
                        ap->remove();
                        ::free(static_cast<void*>(ap));
                    }

                }

                void remove(AllocInfoPtr ap)
                {
                    if(ap)
                    {
                        ap->remove();
                        ::free(static_cast<void*>(ap));
                    }
                }
            };

            struct Header;
            typedef Header* HeaderPtr;
            struct Header
            {
#ifdef COR_ALLOCATION_MONITOR_INDEX_COUNT
                size_t count;
#endif
#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
                RInt32 mark;
                RInt32 captured_index;
#endif
                size_t size;
                size_t n;
                HeaderPtr next;
                RBool freed;
            };

            AllocInfoTable alloc_info_table;

            RSize new_count;
            RSize delete_count;
            RSize alloced_size;
            RSize illigal_free_count;
            RSize alloc_size;
            RBool available;

            static const RSize freed_table_size = 64 + 1;
            HeaderPtr freed_table[freed_table_size];

#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
            RSize captured_count;
            RInt32 captured_status;
            struct Captured
            {
                HeaderPtr p;
                RInt32 status;
            };
            Captured captured_list[1024 * 1024 * 20];
#endif

            std::recursive_mutex mutex;

        };

        PAllocationMonitor& AllocationMonitor::ref_instance_pointer()
        {
            //static AllocationMonitor amo;
            static PAllocationMonitor am;
            return am;
        }

        AllocationMonitor::AllocationMonitor()
        {
            static AllocationMonitorItnl itnl_;
            itnl = &itnl_;
            //ref_instance_pointer() = this;

            itnl->new_count = 0;
            itnl->delete_count = 0;
            itnl->alloc_size = 0;
            itnl->available = rtrue;

            RSize i, isz;
            isz = AllocationMonitorItnl::freed_table_size;
            for(i = 0; i < isz; i++)
            {
                itnl->freed_table[i] = nullptr;
            }
#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
            itnl->captured_count = 0;
            itnl->captured_status = 0;
#endif
        }

        AllocationMonitor::~AllocationMonitor()
        {
            RSize i, isz;
            isz = AllocationMonitorItnl::freed_table_size;
            for(i = 0; i < isz; i++)
            {
                while(itnl->freed_table[i])
                {
                    auto h = itnl->freed_table[i];
                    itnl->freed_table[i] = h->next;
                    ::free(h);
                }
            }

            itnl->available = rfalse;

            //ref_instance_pointer() = NULL;
        }

        RSize AllocationMonitor::get_new_count()
        {
            return itnl->new_count;
        }

        RSize AllocationMonitor::get_delete_count()
        {
            return itnl->delete_count;
        }

        RSize AllocationMonitor::get_alloc_count()
        {
            return itnl->new_count - itnl->delete_count;
        }

        RSize AllocationMonitor::get_alloc_size()
        {
            return itnl->alloc_size;
        }

        RString AllocationMonitor::get_status_text()
        {
            RStringStream s;
            //s << "new_count " << get_new_count();
            //s << ", delete_count " << get_delete_count();
            //s << ", alloc_count " << get_alloc_count();
            s << "alloc_count " << get_alloc_count();
            s << ", alloc_size " << get_alloc_size();
            return s.str();
        }

        void AllocationMonitor::set_captured_status(RInt32 captured_status)
        {
#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
            itnl->captured_status = captured_status;
#endif
        }

        RInt32 AllocationMonitor::get_captured_status()
        {
#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
            return itnl->captured_status;
#else
            return 0;
#endif
        }

#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
        class AllocationMonitorBaseT
        {
            AllocationMonitorBaseT(){}
            virtual ~AllocationMonitorBaseT(){}
        };
#endif

        RString AllocationMonitor::get_captured_data()
        {
#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE

            std::vector<RString> data;
            RSize sz = itnl->captured_count;
            for(RSize i = 0 ; i < sz ; i++)
            {
                if(itnl->captured_list[i].p)
                {
                    RStringStream s;
                    RBytePtr bp = (RBytePtr)itnl->captured_list[i].p;
                    bp += sizeof(AllocationMonitorItnl::Header);
                    //s << (RSize)bp;
                    //s << ":";
                    s << i;
                    s << ":";
                    s << itnl->captured_list[i].p->captured_index;
                    s << ":";
                    s << itnl->captured_list[i].p->n;
                    s << ":";
                    //try
                    //{
                    //    s << typeid(*(AllocationMonitorBaseT*)bp).name();
                    //    s << ":";
                    //}
                    //catch(std::__non_rtti_object& bt)
                    //{
                    //    s << "no rtti";
                    //    s << ":";
                    //}
                    //catch(std::bad_typeid& bt)
                    //{
                    //    s << "no name";
                    //    s << ":";
                    //}
                    s << itnl->captured_list[i].status;
                    OutputDebugStringA((s.str() + "\n").c_str());
                    data.push_back(s.str());
                }

            }
            RString str;
            for(auto i : data)
            {
                str += i;
                str += "\n";
            }
            return str;
#else
            return RString();
#endif
        }

        void AllocationMonitor::clear_caputred_data()
        {
#ifdef COR_ALLOCATION_MONITOR_CAPTURE_MODE
            itnl->captured_count = 0;
#endif
        }

        PAllocationMonitor AllocationMonitor::get_instance()
        {
            //PAllocationMonitor& am = ref_instance_pointer();
            static AllocationMonitor amo;
            return &amo;
        }

#ifdef COR_ALLOCATION_MONITOR_LEAK_CHECK
#ifdef WIN32
        struct LeakCheck
        {
            LeakCheck()
            {
                _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
            }

            ~LeakCheck()
            {
                //_CrtDumpMemoryLeaks();
            }
        };
        LeakCheck lc;
#endif
#endif

        void* AllocationMonitor::alloc(size_t n)
        {
            PAllocationMonitor am = get_instance();
            AllocationMonitorItnl* itnl = am->itnl;
            if(am && itnl->available)
            {
                itnl->mutex.lock();

            }

            void* p = nullptr;
            p = ::malloc(n);

            if(am && itnl->available)
            {
                itnl->alloc_info_table.insert(p, n);
                itnl->alloc_size += n;
                itnl->new_count++;
                itnl->mutex.unlock();

            }

            return p;

        }

        void AllocationMonitor::al_free(void* p)
        {
            if(!p)
            {
                return;
            }

            PAllocationMonitor am = get_instance();
            AllocationMonitorItnl* itnl = am->itnl;
            if(am && itnl->available)
            {
                itnl->mutex.lock();

                auto ap = itnl->alloc_info_table.find(p);
                if(ap)
                {
                    itnl->alloc_size -= ap->n;
                    itnl->alloc_info_table.remove(ap);
                }

            }

            ::free(p);

            if(am && itnl->available)
            {
                itnl->delete_count++;
                itnl->mutex.unlock();
            }

        }

        void* AllocationMonitor::al_realloc(void* p, size_t n)
        {
            PAllocationMonitor am = get_instance();
            AllocationMonitorItnl* itnl = am->itnl;
            if(am && itnl->available)
            {
                itnl->mutex.lock();

                auto ap = itnl->alloc_info_table.find(p);
                if(ap)
                {
                    itnl->alloc_size -= ap->n;
                    itnl->alloc_info_table.remove(ap);
                }

            }

            void* np;

            np = ::realloc(p, n);

            if(am && itnl->available)
            {
                if(!p || !np)
                {
                    if(p)
                    {
                        itnl->delete_count++;
                    }
                    if(np)
                    {
                        itnl->alloc_size += n;
                        itnl->alloc_info_table.insert(np, n);
                        itnl->new_count++;
                    }
                }
                itnl->mutex.unlock();

            }

            return np;
        }

    }
}

//#if 0
//#ifdef COR_CUSTOM_NEW_OPERATOR
void* operator new(size_t n) throw(std::bad_alloc)
{
    return cor::system::AllocationMonitor::alloc(n);
}

void operator delete(void* p) throw()
{
    return cor::system::AllocationMonitor::al_free(p);
}

void* operator new[](size_t n) throw(std::bad_alloc)
{
    return cor::system::AllocationMonitor::alloc(n);
}

void operator delete[](void* p) throw()
{
    return cor::system::AllocationMonitor::al_free(p);
}
//#endif
//#endif

<|endoftext|>