<commit_before>// Copyright (c) 2010 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 "app/resource_bundle.h"

#include "app/data_pack.h"
#include "base/lock.h"
#include "base/logging.h"
#include "base/string_piece.h"
#include "build/build_config.h"
#include "gfx/codec/png_codec.h"
#include "gfx/font.h"
#include "third_party/skia/include/core/SkBitmap.h"

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 */
// TODO(glen): Finish moving these into theme provider (dialogs still
//    depend on these colors).
const SkColor ResourceBundle::frame_color =
     SkColorSetRGB(66, 116, 201);
const SkColor ResourceBundle::frame_color_inactive =
     SkColorSetRGB(161, 182, 228);
const SkColor ResourceBundle::frame_color_app_panel =
     SK_ColorWHITE;
const SkColor ResourceBundle::frame_color_app_panel_inactive =
     SK_ColorWHITE;
const SkColor ResourceBundle::frame_color_incognito =
     SkColorSetRGB(83, 106, 139);
const SkColor ResourceBundle::frame_color_incognito_inactive =
     SkColorSetRGB(126, 139, 156);
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 */
std::string ResourceBundle::ReloadSharedInstance(
    const std::string& pref_locale) {
  DCHECK(g_shared_instance_ != NULL) << "ResourceBundle not initialized";

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

/* 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 */
ResourceBundle& ResourceBundle::GetSharedInstance() {
  // Must call InitSharedInstance before this function.
  CHECK(g_shared_instance_ != NULL);
  return *g_shared_instance_;
}

ResourceBundle::ResourceBundle()
    : lock_(new Lock),
      resources_data_(NULL),
      locale_resources_data_(NULL) {
}

void ResourceBundle::FreeImages() {
  for (SkImageMap::iterator i = skia_images_.begin();
       i != skia_images_.end(); i++) {
    delete i->second;
  }
  skia_images_.clear();
}

/* 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);
}

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;
}

SkBitmap* ResourceBundle::GetBitmapNamed(int resource_id) {
  // Check to see if we already have the Skia image in the cache.
  {
    AutoLock lock_scope(*lock_);
    SkImageMap::const_iterator found = skia_images_.find(resource_id);
    if (found != skia_images_.end())
      return found->second;
  }

  scoped_ptr<SkBitmap> bitmap;

  bitmap.reset(LoadBitmap(resources_data_, resource_id));

  if (bitmap.get()) {
    // We loaded successfully.  Cache the Skia version of the bitmap.
    AutoLock lock_scope(*lock_);

    // Another thread raced us, and has already cached the skia image.
    if (skia_images_.count(resource_id))
      return skia_images_[resource_id];

    skia_images_[resource_id] = bitmap.get();
    return bitmap.release();
  }

  // We failed to retrieve the bitmap, show a debugging red square.
  {
    LOG(WARNING) << "Unable to load bitmap with id " << resource_id;
    NOTREACHED();  // Want to assert in debug mode.

    AutoLock lock_scope(*lock_);  // Guard empty_bitmap initialization.

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

void ResourceBundle::LoadFontsIfNecessary() {
  AutoLock lock_scope(*lock_);
  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);
  }
}

const gfx::Font& ResourceBundle::GetFont(FontStyle style) {
  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_;
    default:
      return *base_font_;
  }
}

gfx::NativeImage ResourceBundle::GetNativeImageNamed(int resource_id) {
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
#if defined(OS_MACOSX)
  return rb.GetNSImageNamed(resource_id);
#elif defined(USE_X11) && !defined(TOOLKIT_VIEWS)
  return rb.GetPixbufNamed(resource_id);
#else
  return rb.GetBitmapNamed(resource_id);
#endif
}

// LoadedDataPack implementation
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 app::DataPack);
  bool success = data_pack_->Load(path_);
  CHECK(success) << "Failed to load " << path_.value();
}

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

RefCountedStaticMemory* ResourceBundle::LoadedDataPack::GetStaticMemory(
    int resource_id) const {
  return data_pack_->GetStaticMemory(resource_id);
}
<commit_msg>Downgrade a CHECK to a LOG(ERROR) so we don't crash if we fail to load resources.pak.  This allows us to collect more UMA stats.<commit_after>// Copyright (c) 2010 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 "app/resource_bundle.h"

#include "app/data_pack.h"
#include "base/lock.h"
#include "base/logging.h"
#include "base/string_piece.h"
#include "build/build_config.h"
#include "gfx/codec/png_codec.h"
#include "gfx/font.h"
#include "third_party/skia/include/core/SkBitmap.h"

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 */
// TODO(glen): Finish moving these into theme provider (dialogs still
//    depend on these colors).
const SkColor ResourceBundle::frame_color =
     SkColorSetRGB(66, 116, 201);
const SkColor ResourceBundle::frame_color_inactive =
     SkColorSetRGB(161, 182, 228);
const SkColor ResourceBundle::frame_color_app_panel =
     SK_ColorWHITE;
const SkColor ResourceBundle::frame_color_app_panel_inactive =
     SK_ColorWHITE;
const SkColor ResourceBundle::frame_color_incognito =
     SkColorSetRGB(83, 106, 139);
const SkColor ResourceBundle::frame_color_incognito_inactive =
     SkColorSetRGB(126, 139, 156);
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 */
std::string ResourceBundle::ReloadSharedInstance(
    const std::string& pref_locale) {
  DCHECK(g_shared_instance_ != NULL) << "ResourceBundle not initialized";

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

/* 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 */
ResourceBundle& ResourceBundle::GetSharedInstance() {
  // Must call InitSharedInstance before this function.
  CHECK(g_shared_instance_ != NULL);
  return *g_shared_instance_;
}

ResourceBundle::ResourceBundle()
    : lock_(new Lock),
      resources_data_(NULL),
      locale_resources_data_(NULL) {
}

void ResourceBundle::FreeImages() {
  for (SkImageMap::iterator i = skia_images_.begin();
       i != skia_images_.end(); i++) {
    delete i->second;
  }
  skia_images_.clear();
}

/* 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);
}

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;
}

SkBitmap* ResourceBundle::GetBitmapNamed(int resource_id) {
  // Check to see if we already have the Skia image in the cache.
  {
    AutoLock lock_scope(*lock_);
    SkImageMap::const_iterator found = skia_images_.find(resource_id);
    if (found != skia_images_.end())
      return found->second;
  }

  scoped_ptr<SkBitmap> bitmap;

  bitmap.reset(LoadBitmap(resources_data_, resource_id));

  if (bitmap.get()) {
    // We loaded successfully.  Cache the Skia version of the bitmap.
    AutoLock lock_scope(*lock_);

    // Another thread raced us, and has already cached the skia image.
    if (skia_images_.count(resource_id))
      return skia_images_[resource_id];

    skia_images_[resource_id] = bitmap.get();
    return bitmap.release();
  }

  // We failed to retrieve the bitmap, show a debugging red square.
  {
    LOG(WARNING) << "Unable to load bitmap with id " << resource_id;
    NOTREACHED();  // Want to assert in debug mode.

    AutoLock lock_scope(*lock_);  // Guard empty_bitmap initialization.

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

void ResourceBundle::LoadFontsIfNecessary() {
  AutoLock lock_scope(*lock_);
  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);
  }
}

const gfx::Font& ResourceBundle::GetFont(FontStyle style) {
  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_;
    default:
      return *base_font_;
  }
}

gfx::NativeImage ResourceBundle::GetNativeImageNamed(int resource_id) {
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
#if defined(OS_MACOSX)
  return rb.GetNSImageNamed(resource_id);
#elif defined(USE_X11) && !defined(TOOLKIT_VIEWS)
  return rb.GetPixbufNamed(resource_id);
#else
  return rb.GetBitmapNamed(resource_id);
#endif
}

// LoadedDataPack implementation
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 app::DataPack);
  bool success = data_pack_->Load(path_);
  LOG_IF(ERROR, !success) << "Failed to load " << path_.value()
      << "\nYou will not be able to use the Bookmarks Manager or "
      << "about:net-internals.";
}

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

RefCountedStaticMemory* ResourceBundle::LoadedDataPack::GetStaticMemory(
    int resource_id) const {
  return data_pack_->GetStaticMemory(resource_id);
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cinttypes>
#include <cstdarg>
#include <cerrno>
#include <cassert>
#include <algorithm>
#include <functional>
#include <limits>
#include <memory>
#include <string>
#include <vector>
#include <deque>
#include <map>
#include <set>

#include <unistd.h>

#include "riscv-types.h"
#include "riscv-endian.h"
#include "riscv-format.h"
#include "riscv-meta.h"
#include "riscv-util.h"
#include "riscv-cmdline.h"
#include "riscv-color.h"
#include "riscv-imm.h"
#include "riscv-decode.h"
#include "riscv-disasm.h"
#include "riscv-elf.h"
#include "riscv-elf-file.h"
#include "riscv-elf-format.h"

struct riscv_parse_elf
{
	elf_file elf;
	std::string filename;
	std::map<riscv_ptr,std::string> branch_labels;

	bool enable_color = false;
	bool elf_header = false;
	bool section_headers = false;
	bool program_headers = false;
	bool symbol_table = false;
	bool disassebly = false;
	bool help_or_error = false;

	const char* colorize(const char *type)
	{
		if (!enable_color || !isatty(fileno(stdout))) {
			return "";
		} else if (strcmp(type, "header") == 0) {
			return _COLOR_BEGIN _COLOR_BOLD _COLOR_END;
		} else if (strcmp(type, "title") == 0) {
			return _COLOR_BEGIN _COLOR_BOLD _COLOR_SEP _COLOR_FG_CYAN _COLOR_END;
		} else if (strcmp(type, "legend") == 0) {
			return _COLOR_BEGIN _COLOR_BOLD _COLOR_SEP _COLOR_FG_MAGENTA _COLOR_END;
		} else if (strcmp(type, "opcode") == 0) {
			return _COLOR_BEGIN _COLOR_BOLD _COLOR_SEP _COLOR_FG_CYAN _COLOR_END;
		} else if (strcmp(type, "location") == 0) {
			return _COLOR_BEGIN _COLOR_FG_GREEN _COLOR_END;
		} else if (strcmp(type, "address") == 0) {
			return _COLOR_BEGIN _COLOR_FG_YELLOW _COLOR_END;
		} else if (strcmp(type, "symbol") == 0) {
			return _COLOR_BEGIN _COLOR_UNDERSCORE _COLOR_END;
		} else if (strcmp(type, "reset") == 0) {
			return _COLOR_RESET;
		}
		return "";
	}

	const char* symlookup(riscv_ptr addr, bool nearest)
	{
		auto sym = elf_sym_by_addr(elf, (Elf64_Addr)addr);
		if (sym) return elf_sym_name(elf, sym);
		auto bli = branch_labels.find(addr);
		if (bli != branch_labels.end()) return bli->second.c_str();
		if (nearest) {
			sym = elf_sym_by_nearest_addr(elf, (Elf64_Addr)addr);
			if (sym) {
				static char symbol_tmpname[256];
				int64_t offset = int64_t(addr) - sym->st_value;
				snprintf(symbol_tmpname, sizeof(symbol_tmpname),
					"%s%s0x%" PRIx64, elf_sym_name(elf, sym),
					offset < 0 ? "-" : "+", offset < 0 ? -offset : offset);
				return symbol_tmpname;
			}
		}
		return nullptr;
	}

	void scan_branch_labels(riscv_ptr start, riscv_ptr end, riscv_ptr pc_offset)
	{
		ssize_t branch_num = 1;
		char branch_label[32];

		riscv_disasm dec;
		riscv_ptr pc = start, next_pc;
		uint64_t addr = 0;
		while (pc < end) {
			dec.pc = pc;
			dec.inst = riscv_get_instruction(pc, &next_pc);
			riscv_decode_instruction<riscv_disasm>(dec, dec.inst);
			switch (dec.codec) {
				case riscv_codec_sb:
				case riscv_codec_uj:
				{
					addr = pc - pc_offset + dec.imm;
					snprintf(branch_label, sizeof(branch_label), "LOC_%06lu", branch_num++);
					branch_labels[(riscv_ptr)addr] = branch_label;
					break;
				}
				default:
					break;
			}
			pc = next_pc;
		}
	}

	void scan_branch_labels()
	{
		branch_labels.clear();
		for (size_t i = 0; i < elf.shdrs.size(); i++) {
			Elf64_Shdr &shdr = elf.shdrs[i];
			if (shdr.sh_flags & SHF_EXECINSTR) {
				uint8_t *offset = elf.offset(shdr.sh_offset);
				scan_branch_labels(offset, offset + shdr.sh_size, offset- shdr.sh_addr);
			}
		}
	}

	void print_disassembly(riscv_ptr start, riscv_ptr end, riscv_ptr pc_offset, riscv_ptr gp)
	{
		riscv_disasm dec;
		std::deque<riscv_disasm> dec_hist;
		riscv_ptr pc = start, next_pc;
		while (pc < end) {
			dec.pc = pc;
			dec.inst = riscv_get_instruction(pc, &next_pc);
			riscv_decode_instruction<riscv_disasm>(dec, dec.inst);
			riscv_disasm_instruction(dec, dec_hist, pc, next_pc, pc_offset, gp,
				std::bind(&riscv_parse_elf::symlookup, this, std::placeholders::_1, std::placeholders::_2),
				std::bind(&riscv_parse_elf::colorize, this, std::placeholders::_1));
			pc = next_pc;
		}
	}

	void print_disassembly()
	{
		const Elf64_Sym *gp_sym = elf_sym_by_name(elf, "_gp");
		for (size_t i = 0; i < elf.shdrs.size(); i++) {
			Elf64_Shdr &shdr = elf.shdrs[i];
			if (shdr.sh_flags & SHF_EXECINSTR) {
				uint8_t *offset = elf.offset(shdr.sh_offset);
				printf("%sSection[%2lu] %-111s%s\n", colorize("title"), i, elf_shdr_name(elf, i), colorize("reset"));
				print_disassembly(offset, offset + shdr.sh_size, offset- shdr.sh_addr,
					riscv_ptr(gp_sym ? gp_sym->st_value : 0));
			}
		}
	}

	void parse_commandline(int argc, const char *argv[])
	{
		cmdline_option options[] =
		{
			{ "-c", "--color", cmdline_arg_type_none,
				"Enable Color",
				[&](std::string s) { return (enable_color = true); } },
			{ "-e", "--print-elf-header", cmdline_arg_type_none,
				"Print ELF header",
				[&](std::string s) { return (elf_header = true); } },
			{ "-s", "--print-section-headers", cmdline_arg_type_none,
				"Print Section headers",
				[&](std::string s) { return (section_headers = true); } },
			{ "-p", "--print-program-headers", cmdline_arg_type_none,
				"Print Program headers",
				[&](std::string s) { return (program_headers = true); } },
			{ "-t", "--print-symbol-table", cmdline_arg_type_none,
				"Print Symbol Table",
				[&](std::string s) { return (symbol_table = true); } },
			{ "-d", "--print-disassembly", cmdline_arg_type_none,
				"Print Disassembly",
				[&](std::string s) { return (disassebly = true); } },
			{ "-a", "--print-all", cmdline_arg_type_none,
				"Print All",
				[&](std::string s) { return (elf_header = section_headers = program_headers = symbol_table = disassebly = true); } },
			{ "-h", "--help", cmdline_arg_type_none,
				"Show help",
				[&](std::string s) { return (help_or_error = true); } },
			{ nullptr, nullptr, cmdline_arg_type_none,   nullptr, nullptr }
		};

		auto result = cmdline_option::process_options(options, argc, argv);
		if (!result.second) {
			help_or_error = true;
		} else if (result.first.size() != 1) {
			printf("%s: wrong number of arguments\n", argv[0]);
			help_or_error = true;
		}

		if ((help_or_error |= !elf_header && !section_headers &&
			!program_headers && !symbol_table && !disassebly))
		{
			printf("usage: %s [<options>] <elf_file>\n", argv[0]);
			cmdline_option::print_options(options);
			exit(9);
		}

		filename = result.first[0];
	}

	void print_heading(std::string heading)
	{
		printf("\n%s███ %s ", colorize("header"), heading.c_str());
		for (size_t i = 0; i < 118 - heading.length(); i++) printf("█");
		printf("%s\n\n", colorize("reset"));
	}

	void run()
	{
		elf.load(filename);
		if (elf_header) {
			print_heading("ELF Header");
			elf_print_header_info(elf, std::bind(&riscv_parse_elf::colorize, this, std::placeholders::_1));
		}
		if (section_headers) {
			print_heading("Section Headers");
			elf_print_section_headers(elf, std::bind(&riscv_parse_elf::colorize, this, std::placeholders::_1));
		}
		if (program_headers) {
			print_heading("Program Headers");
			elf_print_program_headers(elf, std::bind(&riscv_parse_elf::colorize, this, std::placeholders::_1));
		}
		if (symbol_table) {
			print_heading("Symbol Table");
			elf_print_symbol_table(elf, std::bind(&riscv_parse_elf::colorize, this, std::placeholders::_1));
		}
		if (disassebly && elf.ehdr.e_machine == EM_RISCV) {
			print_heading("Disassembly");
			scan_branch_labels();
			print_disassembly();
		}
		printf("\n");
	}
};

int main(int argc, const char *argv[])
{
	riscv_parse_elf elf_parser;
	elf_parser.parse_commandline(argc, argv);
	elf_parser.run();
	return 0;
}
<commit_msg>Improve layout when disassembling multiple sections<commit_after>#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cinttypes>
#include <cstdarg>
#include <cerrno>
#include <cassert>
#include <algorithm>
#include <functional>
#include <limits>
#include <memory>
#include <string>
#include <vector>
#include <deque>
#include <map>
#include <set>

#include <unistd.h>

#include "riscv-types.h"
#include "riscv-endian.h"
#include "riscv-format.h"
#include "riscv-meta.h"
#include "riscv-util.h"
#include "riscv-cmdline.h"
#include "riscv-color.h"
#include "riscv-imm.h"
#include "riscv-decode.h"
#include "riscv-disasm.h"
#include "riscv-elf.h"
#include "riscv-elf-file.h"
#include "riscv-elf-format.h"

struct riscv_parse_elf
{
	elf_file elf;
	std::string filename;
	std::map<riscv_ptr,std::string> branch_labels;

	bool enable_color = false;
	bool elf_header = false;
	bool section_headers = false;
	bool program_headers = false;
	bool symbol_table = false;
	bool disassebly = false;
	bool help_or_error = false;

	const char* colorize(const char *type)
	{
		if (!enable_color || !isatty(fileno(stdout))) {
			return "";
		} else if (strcmp(type, "header") == 0) {
			return _COLOR_BEGIN _COLOR_BOLD _COLOR_END;
		} else if (strcmp(type, "title") == 0) {
			return _COLOR_BEGIN _COLOR_BOLD _COLOR_SEP _COLOR_FG_CYAN _COLOR_END;
		} else if (strcmp(type, "legend") == 0) {
			return _COLOR_BEGIN _COLOR_BOLD _COLOR_SEP _COLOR_FG_MAGENTA _COLOR_END;
		} else if (strcmp(type, "opcode") == 0) {
			return _COLOR_BEGIN _COLOR_BOLD _COLOR_SEP _COLOR_FG_CYAN _COLOR_END;
		} else if (strcmp(type, "location") == 0) {
			return _COLOR_BEGIN _COLOR_FG_GREEN _COLOR_END;
		} else if (strcmp(type, "address") == 0) {
			return _COLOR_BEGIN _COLOR_FG_YELLOW _COLOR_END;
		} else if (strcmp(type, "symbol") == 0) {
			return _COLOR_BEGIN _COLOR_UNDERSCORE _COLOR_END;
		} else if (strcmp(type, "reset") == 0) {
			return _COLOR_RESET;
		}
		return "";
	}

	const char* symlookup(riscv_ptr addr, bool nearest)
	{
		auto sym = elf_sym_by_addr(elf, (Elf64_Addr)addr);
		if (sym) return elf_sym_name(elf, sym);
		auto bli = branch_labels.find(addr);
		if (bli != branch_labels.end()) return bli->second.c_str();
		if (nearest) {
			sym = elf_sym_by_nearest_addr(elf, (Elf64_Addr)addr);
			if (sym) {
				static char symbol_tmpname[256];
				int64_t offset = int64_t(addr) - sym->st_value;
				snprintf(symbol_tmpname, sizeof(symbol_tmpname),
					"%s%s0x%" PRIx64, elf_sym_name(elf, sym),
					offset < 0 ? "-" : "+", offset < 0 ? -offset : offset);
				return symbol_tmpname;
			}
		}
		return nullptr;
	}

	void scan_branch_labels(riscv_ptr start, riscv_ptr end, riscv_ptr pc_offset)
	{
		ssize_t branch_num = 1;
		char branch_label[32];

		riscv_disasm dec;
		riscv_ptr pc = start, next_pc;
		uint64_t addr = 0;
		while (pc < end) {
			dec.pc = pc;
			dec.inst = riscv_get_instruction(pc, &next_pc);
			riscv_decode_instruction<riscv_disasm>(dec, dec.inst);
			switch (dec.codec) {
				case riscv_codec_sb:
				case riscv_codec_uj:
				{
					addr = pc - pc_offset + dec.imm;
					snprintf(branch_label, sizeof(branch_label), "LOC_%06lu", branch_num++);
					branch_labels[(riscv_ptr)addr] = branch_label;
					break;
				}
				default:
					break;
			}
			pc = next_pc;
		}
	}

	void scan_branch_labels()
	{
		branch_labels.clear();
		for (size_t i = 0; i < elf.shdrs.size(); i++) {
			Elf64_Shdr &shdr = elf.shdrs[i];
			if (shdr.sh_flags & SHF_EXECINSTR) {
				uint8_t *offset = elf.offset(shdr.sh_offset);
				scan_branch_labels(offset, offset + shdr.sh_size, offset- shdr.sh_addr);
			}
		}
	}

	void print_disassembly(riscv_ptr start, riscv_ptr end, riscv_ptr pc_offset, riscv_ptr gp)
	{
		riscv_disasm dec;
		std::deque<riscv_disasm> dec_hist;
		riscv_ptr pc = start, next_pc;
		while (pc < end) {
			dec.pc = pc;
			dec.inst = riscv_get_instruction(pc, &next_pc);
			riscv_decode_instruction<riscv_disasm>(dec, dec.inst);
			riscv_disasm_instruction(dec, dec_hist, pc, next_pc, pc_offset, gp,
				std::bind(&riscv_parse_elf::symlookup, this, std::placeholders::_1, std::placeholders::_2),
				std::bind(&riscv_parse_elf::colorize, this, std::placeholders::_1));
			pc = next_pc;
		}
	}

	void print_disassembly()
	{
		const Elf64_Sym *gp_sym = elf_sym_by_name(elf, "_gp");
		for (size_t i = 0; i < elf.shdrs.size(); i++) {
			Elf64_Shdr &shdr = elf.shdrs[i];
			if (shdr.sh_flags & SHF_EXECINSTR) {
				uint8_t *offset = elf.offset(shdr.sh_offset);
				printf("%sSection[%2lu] %-111s%s\n", colorize("title"), i, elf_shdr_name(elf, i), colorize("reset"));
				print_disassembly(offset, offset + shdr.sh_size, offset- shdr.sh_addr,
					riscv_ptr(gp_sym ? gp_sym->st_value : 0));
				printf("\n");
			}
		}
	}

	void parse_commandline(int argc, const char *argv[])
	{
		cmdline_option options[] =
		{
			{ "-c", "--color", cmdline_arg_type_none,
				"Enable Color",
				[&](std::string s) { return (enable_color = true); } },
			{ "-e", "--print-elf-header", cmdline_arg_type_none,
				"Print ELF header",
				[&](std::string s) { return (elf_header = true); } },
			{ "-s", "--print-section-headers", cmdline_arg_type_none,
				"Print Section headers",
				[&](std::string s) { return (section_headers = true); } },
			{ "-p", "--print-program-headers", cmdline_arg_type_none,
				"Print Program headers",
				[&](std::string s) { return (program_headers = true); } },
			{ "-t", "--print-symbol-table", cmdline_arg_type_none,
				"Print Symbol Table",
				[&](std::string s) { return (symbol_table = true); } },
			{ "-d", "--print-disassembly", cmdline_arg_type_none,
				"Print Disassembly",
				[&](std::string s) { return (disassebly = true); } },
			{ "-a", "--print-all", cmdline_arg_type_none,
				"Print All",
				[&](std::string s) { return (elf_header = section_headers = program_headers = symbol_table = disassebly = true); } },
			{ "-h", "--help", cmdline_arg_type_none,
				"Show help",
				[&](std::string s) { return (help_or_error = true); } },
			{ nullptr, nullptr, cmdline_arg_type_none,   nullptr, nullptr }
		};

		auto result = cmdline_option::process_options(options, argc, argv);
		if (!result.second) {
			help_or_error = true;
		} else if (result.first.size() != 1) {
			printf("%s: wrong number of arguments\n", argv[0]);
			help_or_error = true;
		}

		if ((help_or_error |= !elf_header && !section_headers &&
			!program_headers && !symbol_table && !disassebly))
		{
			printf("usage: %s [<options>] <elf_file>\n", argv[0]);
			cmdline_option::print_options(options);
			exit(9);
		}

		filename = result.first[0];
	}

	void print_heading(std::string heading)
	{
		printf("\n%s███ %s ", colorize("header"), heading.c_str());
		for (size_t i = 0; i < 118 - heading.length(); i++) printf("█");
		printf("%s\n\n", colorize("reset"));
	}

	void run()
	{
		elf.load(filename);
		if (elf_header) {
			print_heading("ELF Header");
			elf_print_header_info(elf, std::bind(&riscv_parse_elf::colorize, this, std::placeholders::_1));
		}
		if (section_headers) {
			print_heading("Section Headers");
			elf_print_section_headers(elf, std::bind(&riscv_parse_elf::colorize, this, std::placeholders::_1));
		}
		if (program_headers) {
			print_heading("Program Headers");
			elf_print_program_headers(elf, std::bind(&riscv_parse_elf::colorize, this, std::placeholders::_1));
		}
		if (symbol_table) {
			print_heading("Symbol Table");
			elf_print_symbol_table(elf, std::bind(&riscv_parse_elf::colorize, this, std::placeholders::_1));
		}
		if (disassebly && elf.ehdr.e_machine == EM_RISCV) {
			print_heading("Disassembly");
			scan_branch_labels();
			print_disassembly();
		}
	}
};

int main(int argc, const char *argv[])
{
	riscv_parse_elf elf_parser;
	elf_parser.parse_commandline(argc, argv);
	elf_parser.run();
	return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 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 "chrome/browser/chromeos/cros/cros_library.h"

#include "chrome/browser/chromeos/cros/cros_library_loader.h"
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "chrome/browser/chromeos/cros/keyboard_library.h"
#include "chrome/browser/chromeos/cros/language_library.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/cros/mount_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/cros/power_library.h"
#include "chrome/browser/chromeos/cros/screen_lock_library.h"
#include "chrome/browser/chromeos/cros/speech_synthesis_library.h"
#include "chrome/browser/chromeos/cros/synaptics_library.h"
#include "chrome/browser/chromeos/cros/syslogs_library.h"

namespace chromeos {

CrosLibrary::CrosLibrary() : library_loader_(NULL),
                             crypto_lib_(NULL),
                             keyboard_lib_(NULL),
                             language_lib_(NULL),
                             login_lib_(NULL),
                             mount_lib_(NULL),
                             network_lib_(NULL),
                             power_lib_(NULL),
                             screen_lock_lib_(NULL),
                             speech_synthesis_lib_(NULL),
                             synaptics_lib_(NULL),
                             syslogs_lib_(NULL),
                             own_library_loader_(true),
                             own_cryptohome_lib_(true),
                             own_language_lib_(true),
                             own_login_lib_(true),
                             own_mount_lib_(true),
                             own_network_lib_(true),
                             own_power_lib_(true),
                             own_screen_lock_lib_(true),
                             own_speech_synthesis_lib_(true),
                             own_synaptics_lib_(true),
                             own_syslogs_lib_(true),
                             loaded_(false),
                             load_error_(false),
                             test_api_(NULL) {

}

CrosLibrary::~CrosLibrary() {
  if (own_library_loader_)
    delete library_loader_;
  if (own_cryptohome_lib_)
    delete crypto_lib_;
  if (own_keyboard_lib_)
    delete keyboard_lib_;
  if (own_language_lib_)
    delete language_lib_;
  if (own_login_lib_)
    delete login_lib_;
  if (own_mount_lib_)
    delete mount_lib_;
  if (own_network_lib_)
    delete network_lib_;
  if (own_power_lib_)
    delete power_lib_;
  if (own_screen_lock_lib_)
    delete screen_lock_lib_;
  if (own_speech_synthesis_lib_)
    delete speech_synthesis_lib_;
  if (own_synaptics_lib_)
    delete synaptics_lib_;
  if (own_syslogs_lib_)
    delete syslogs_lib_;
  delete test_api_;
}

// static
CrosLibrary* CrosLibrary::Get() {
  return Singleton<CrosLibrary>::get();
}

CryptohomeLibrary* CrosLibrary::GetCryptohomeLibrary() {
  if (!crypto_lib_)
    crypto_lib_ = new CryptohomeLibraryImpl();
  return crypto_lib_;
}

KeyboardLibrary* CrosLibrary::GetKeyboardLibrary() {
  if (!keyboard_lib_)
    keyboard_lib_ = new KeyboardLibraryImpl();
  return keyboard_lib_;
}

LanguageLibrary* CrosLibrary::GetLanguageLibrary() {
  if (!language_lib_)
    language_lib_ = new LanguageLibraryImpl();
  return language_lib_;
}

LoginLibrary* CrosLibrary::GetLoginLibrary() {
  if (!login_lib_)
    login_lib_ = new LoginLibraryImpl();
  return login_lib_;
}

MountLibrary* CrosLibrary::GetMountLibrary() {
  if (!mount_lib_)
    mount_lib_ = new MountLibraryImpl();
  return mount_lib_;
}

NetworkLibrary* CrosLibrary::GetNetworkLibrary() {
  if (!network_lib_)
    network_lib_ = new NetworkLibraryImpl();
  return network_lib_;
}

PowerLibrary* CrosLibrary::GetPowerLibrary() {
  if (!power_lib_)
    power_lib_ = new PowerLibraryImpl();
  return power_lib_;
}

ScreenLockLibrary* CrosLibrary::GetScreenLockLibrary() {
  if (!screen_lock_lib_)
    screen_lock_lib_ = new ScreenLockLibraryImpl();
  return screen_lock_lib_;
}

SpeechSynthesisLibrary* CrosLibrary::GetSpeechSynthesisLibrary() {
  if (!speech_synthesis_lib_)
    speech_synthesis_lib_ = new SpeechSynthesisLibraryImpl();
  return speech_synthesis_lib_;
}

SynapticsLibrary* CrosLibrary::GetSynapticsLibrary() {
  if (!synaptics_lib_)
    synaptics_lib_ = new SynapticsLibraryImpl();
  return synaptics_lib_;
}

SyslogsLibrary* CrosLibrary::GetSyslogsLibrary() {
  if (!syslogs_lib_)
    syslogs_lib_ = new SyslogsLibraryImpl();
  return syslogs_lib_;
}

bool CrosLibrary::EnsureLoaded() {
  if (!loaded_ && !load_error_) {
    if (!library_loader_)
      library_loader_ = new CrosLibraryLoader();
    loaded_ = library_loader_->Load(&load_error_string_);
    load_error_ = !loaded_;
  }
  return loaded_;
}

CrosLibrary::TestApi* CrosLibrary::GetTestApi() {
  if (!test_api_)
    test_api_ = new TestApi(this);
  return test_api_;
}

void CrosLibrary::TestApi::SetLibraryLoader(LibraryLoader* loader, bool own) {
  if (library_->library_loader_ == loader)
    return;
  if (library_->own_library_loader_)
    delete library_->library_loader_;
  library_->own_library_loader_ = own;
  library_->library_loader_ = loader;
  // Reset load flags when loader changes. Otherwise some tests are really not
  // going to be happy.
  library_->loaded_ = false;
  library_->load_error_ = false;
}

void CrosLibrary::TestApi::SetCryptohomeLibrary(CryptohomeLibrary* library,
                                                bool own) {
  if (library_->own_cryptohome_lib_)
    delete library_->crypto_lib_;
  library_->own_cryptohome_lib_ = own;
  library_->crypto_lib_ = library;
}

void CrosLibrary::TestApi::SetKeyboardLibrary(KeyboardLibrary* library,
                                              bool own) {
  if (library_->own_keyboard_lib_)
    delete library_->keyboard_lib_;
  library_->own_keyboard_lib_ = own;
  library_->keyboard_lib_ = library;
}

void CrosLibrary::TestApi::SetLanguageLibrary(LanguageLibrary* library,
                                              bool own) {
  if (library_->own_language_lib_)
    delete library_->language_lib_;
  library_->own_language_lib_ = own;
  library_->language_lib_ = library;
}

void CrosLibrary::TestApi::SetLoginLibrary(LoginLibrary* library, bool own) {
  if (library_->own_login_lib_)
    delete library_->login_lib_;
  library_->own_login_lib_ = own;
  library_->login_lib_ = library;
}

void CrosLibrary::TestApi::SetMountLibrary(MountLibrary* library, bool own) {
  if (library_->own_mount_lib_)
    delete library_->mount_lib_;
  library_->own_mount_lib_ = own;
  library_->mount_lib_ = library;
}

void CrosLibrary::TestApi::SetNetworkLibrary(NetworkLibrary* library,
                                             bool own) {
  if (library_->own_network_lib_)
    delete library_->network_lib_;
  library_->own_network_lib_ = own;
  library_->network_lib_ = library;
}

void CrosLibrary::TestApi::SetPowerLibrary(PowerLibrary* library, bool own) {
  if (library_->own_power_lib_)
    delete library_->power_lib_;
  library_->own_power_lib_ = own;
  library_->power_lib_ = library;
}

void CrosLibrary::TestApi::SetScreenLockLibrary(ScreenLockLibrary* library,
                                                bool own) {
  if (library_->own_screen_lock_lib_)
    delete library_->screen_lock_lib_;
  library_->own_screen_lock_lib_ = own;
  library_->screen_lock_lib_ = library;
}

void CrosLibrary::TestApi::SetSpeechSynthesisLibrary(
    SpeechSynthesisLibrary* library, bool own) {
  if (library_->own_speech_synthesis_lib_)
    delete library_->speech_synthesis_lib_;
  library_->own_speech_synthesis_lib_ = own;
  library_->speech_synthesis_lib_ = library;
}

void CrosLibrary::TestApi::SetSynapticsLibrary(SynapticsLibrary* library,
                                               bool own) {
  if (library_->own_synaptics_lib_)
    delete library_->synaptics_lib_;
  library_->own_synaptics_lib_ = own;
  library_->synaptics_lib_ = library;
}

void CrosLibrary::TestApi::SetSyslogsLibrary(SyslogsLibrary* library,
                                             bool own) {
  if (library_->syslogs_lib_)
    delete library_->syslogs_lib_;
  library_->own_syslogs_lib_ = own;
  library_->syslogs_lib_ = library;
}

} // namespace chromeos
<commit_msg>Initialize |own_keyboard_lib_| correctly in the constructor to fix memory leak  (and the valgrind errors below.)<commit_after>// Copyright (c) 2010 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 "chrome/browser/chromeos/cros/cros_library.h"

#include "chrome/browser/chromeos/cros/cros_library_loader.h"
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "chrome/browser/chromeos/cros/keyboard_library.h"
#include "chrome/browser/chromeos/cros/language_library.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/cros/mount_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/cros/power_library.h"
#include "chrome/browser/chromeos/cros/screen_lock_library.h"
#include "chrome/browser/chromeos/cros/speech_synthesis_library.h"
#include "chrome/browser/chromeos/cros/synaptics_library.h"
#include "chrome/browser/chromeos/cros/syslogs_library.h"

namespace chromeos {

CrosLibrary::CrosLibrary() : library_loader_(NULL),
                             crypto_lib_(NULL),
                             keyboard_lib_(NULL),
                             language_lib_(NULL),
                             login_lib_(NULL),
                             mount_lib_(NULL),
                             network_lib_(NULL),
                             power_lib_(NULL),
                             screen_lock_lib_(NULL),
                             speech_synthesis_lib_(NULL),
                             synaptics_lib_(NULL),
                             syslogs_lib_(NULL),
                             own_library_loader_(true),
                             own_cryptohome_lib_(true),
                             own_keyboard_lib_(true),
                             own_language_lib_(true),
                             own_login_lib_(true),
                             own_mount_lib_(true),
                             own_network_lib_(true),
                             own_power_lib_(true),
                             own_screen_lock_lib_(true),
                             own_speech_synthesis_lib_(true),
                             own_synaptics_lib_(true),
                             own_syslogs_lib_(true),
                             loaded_(false),
                             load_error_(false),
                             test_api_(NULL) {

}

CrosLibrary::~CrosLibrary() {
  if (own_library_loader_)
    delete library_loader_;
  if (own_cryptohome_lib_)
    delete crypto_lib_;
  if (own_keyboard_lib_)
    delete keyboard_lib_;
  if (own_language_lib_)
    delete language_lib_;
  if (own_login_lib_)
    delete login_lib_;
  if (own_mount_lib_)
    delete mount_lib_;
  if (own_network_lib_)
    delete network_lib_;
  if (own_power_lib_)
    delete power_lib_;
  if (own_screen_lock_lib_)
    delete screen_lock_lib_;
  if (own_speech_synthesis_lib_)
    delete speech_synthesis_lib_;
  if (own_synaptics_lib_)
    delete synaptics_lib_;
  if (own_syslogs_lib_)
    delete syslogs_lib_;
  delete test_api_;
}

// static
CrosLibrary* CrosLibrary::Get() {
  return Singleton<CrosLibrary>::get();
}

CryptohomeLibrary* CrosLibrary::GetCryptohomeLibrary() {
  if (!crypto_lib_)
    crypto_lib_ = new CryptohomeLibraryImpl();
  return crypto_lib_;
}

KeyboardLibrary* CrosLibrary::GetKeyboardLibrary() {
  if (!keyboard_lib_)
    keyboard_lib_ = new KeyboardLibraryImpl();
  return keyboard_lib_;
}

LanguageLibrary* CrosLibrary::GetLanguageLibrary() {
  if (!language_lib_)
    language_lib_ = new LanguageLibraryImpl();
  return language_lib_;
}

LoginLibrary* CrosLibrary::GetLoginLibrary() {
  if (!login_lib_)
    login_lib_ = new LoginLibraryImpl();
  return login_lib_;
}

MountLibrary* CrosLibrary::GetMountLibrary() {
  if (!mount_lib_)
    mount_lib_ = new MountLibraryImpl();
  return mount_lib_;
}

NetworkLibrary* CrosLibrary::GetNetworkLibrary() {
  if (!network_lib_)
    network_lib_ = new NetworkLibraryImpl();
  return network_lib_;
}

PowerLibrary* CrosLibrary::GetPowerLibrary() {
  if (!power_lib_)
    power_lib_ = new PowerLibraryImpl();
  return power_lib_;
}

ScreenLockLibrary* CrosLibrary::GetScreenLockLibrary() {
  if (!screen_lock_lib_)
    screen_lock_lib_ = new ScreenLockLibraryImpl();
  return screen_lock_lib_;
}

SpeechSynthesisLibrary* CrosLibrary::GetSpeechSynthesisLibrary() {
  if (!speech_synthesis_lib_)
    speech_synthesis_lib_ = new SpeechSynthesisLibraryImpl();
  return speech_synthesis_lib_;
}

SynapticsLibrary* CrosLibrary::GetSynapticsLibrary() {
  if (!synaptics_lib_)
    synaptics_lib_ = new SynapticsLibraryImpl();
  return synaptics_lib_;
}

SyslogsLibrary* CrosLibrary::GetSyslogsLibrary() {
  if (!syslogs_lib_)
    syslogs_lib_ = new SyslogsLibraryImpl();
  return syslogs_lib_;
}

bool CrosLibrary::EnsureLoaded() {
  if (!loaded_ && !load_error_) {
    if (!library_loader_)
      library_loader_ = new CrosLibraryLoader();
    loaded_ = library_loader_->Load(&load_error_string_);
    load_error_ = !loaded_;
  }
  return loaded_;
}

CrosLibrary::TestApi* CrosLibrary::GetTestApi() {
  if (!test_api_)
    test_api_ = new TestApi(this);
  return test_api_;
}

void CrosLibrary::TestApi::SetLibraryLoader(LibraryLoader* loader, bool own) {
  if (library_->library_loader_ == loader)
    return;
  if (library_->own_library_loader_)
    delete library_->library_loader_;
  library_->own_library_loader_ = own;
  library_->library_loader_ = loader;
  // Reset load flags when loader changes. Otherwise some tests are really not
  // going to be happy.
  library_->loaded_ = false;
  library_->load_error_ = false;
}

void CrosLibrary::TestApi::SetCryptohomeLibrary(CryptohomeLibrary* library,
                                                bool own) {
  if (library_->own_cryptohome_lib_)
    delete library_->crypto_lib_;
  library_->own_cryptohome_lib_ = own;
  library_->crypto_lib_ = library;
}

void CrosLibrary::TestApi::SetKeyboardLibrary(KeyboardLibrary* library,
                                              bool own) {
  if (library_->own_keyboard_lib_)
    delete library_->keyboard_lib_;
  library_->own_keyboard_lib_ = own;
  library_->keyboard_lib_ = library;
}

void CrosLibrary::TestApi::SetLanguageLibrary(LanguageLibrary* library,
                                              bool own) {
  if (library_->own_language_lib_)
    delete library_->language_lib_;
  library_->own_language_lib_ = own;
  library_->language_lib_ = library;
}

void CrosLibrary::TestApi::SetLoginLibrary(LoginLibrary* library, bool own) {
  if (library_->own_login_lib_)
    delete library_->login_lib_;
  library_->own_login_lib_ = own;
  library_->login_lib_ = library;
}

void CrosLibrary::TestApi::SetMountLibrary(MountLibrary* library, bool own) {
  if (library_->own_mount_lib_)
    delete library_->mount_lib_;
  library_->own_mount_lib_ = own;
  library_->mount_lib_ = library;
}

void CrosLibrary::TestApi::SetNetworkLibrary(NetworkLibrary* library,
                                             bool own) {
  if (library_->own_network_lib_)
    delete library_->network_lib_;
  library_->own_network_lib_ = own;
  library_->network_lib_ = library;
}

void CrosLibrary::TestApi::SetPowerLibrary(PowerLibrary* library, bool own) {
  if (library_->own_power_lib_)
    delete library_->power_lib_;
  library_->own_power_lib_ = own;
  library_->power_lib_ = library;
}

void CrosLibrary::TestApi::SetScreenLockLibrary(ScreenLockLibrary* library,
                                                bool own) {
  if (library_->own_screen_lock_lib_)
    delete library_->screen_lock_lib_;
  library_->own_screen_lock_lib_ = own;
  library_->screen_lock_lib_ = library;
}

void CrosLibrary::TestApi::SetSpeechSynthesisLibrary(
    SpeechSynthesisLibrary* library, bool own) {
  if (library_->own_speech_synthesis_lib_)
    delete library_->speech_synthesis_lib_;
  library_->own_speech_synthesis_lib_ = own;
  library_->speech_synthesis_lib_ = library;
}

void CrosLibrary::TestApi::SetSynapticsLibrary(SynapticsLibrary* library,
                                               bool own) {
  if (library_->own_synaptics_lib_)
    delete library_->synaptics_lib_;
  library_->own_synaptics_lib_ = own;
  library_->synaptics_lib_ = library;
}

void CrosLibrary::TestApi::SetSyslogsLibrary(SyslogsLibrary* library,
                                             bool own) {
  if (library_->syslogs_lib_)
    delete library_->syslogs_lib_;
  library_->own_syslogs_lib_ = own;
  library_->syslogs_lib_ = library;
}

} // namespace chromeos
<|endoftext|>


<commit_before>#include "mbed.h"

#include "imu.h"
#include "latch.h"
#include "distance.h"
#include "motor.h"
#include "wireless.h"
#include "config.h"

Serial pc(USBTX, USBRX); // tx, rx

#define FLAG_RECEIVING_BODY 1
#define FLAG_HEAD_FINDING 0
#define FLAG_RECEIVING_CHECKSUM1 2
#define FLAG_RECEIVING_CHECKSUM2 3

char buffer[BUFFER_SIZE] = {0};
int iBufferW = 0;
char flag = FLAG_HEAD_FINDING;

#define WARNING_REPEATED_START_HEAD_FINDING 0

void warning(int warning_num){
    if(warning_num == WARNING_REPEATED_START_HEAD_FINDING){

    }

}

char hex2nibble(char c){
    if(c >= 'a' && c <= 'f'){
        return c - 'a' + 10;
    }else if(c >= '0' && c <= '9'){
        return c - '0';
    }else{
        return -1;
    }
}

bool validateChecksum(){

    // Calculate sum
    uint8_t sum = 0;
    for(int i = 0; i<(iBufferW - 3); i++)
        // $ 1 2 3 # a b
        //               ^
        // So use index - 3
        sum += buffer[i];

    // Extract sum from last 2 hexadecimal
    uint8_t recv_sum = (
        (uint8_t)hex2nibble(buffer[iBufferW - 2]) << 4 |
        (uint8_t)hex2nibble(buffer[iBufferW - 1])
    );

    if(sum == recv_sum){
        return true;
    }else{
        return false;
    }
}

const char HEX_LOOKUP_TABLE[] = "0123456789abcdef";
void reply(char *message){
    // Calculate char sum of message
    char *input = message;
    uint8_t sum = '+' + '$';
    for(; (*input)!='\0' ; input++){
        sum += *input;
    }

    static uint8_t sum_s[3] = {0};
    sum_s[0] = HEX_LOOKUP_TABLE[ sum>>4 & 0x0F ];
    sum_s[1] = HEX_LOOKUP_TABLE[ sum & 0x0F ];

    pc.printf("+$%s#%s", message, sum_s);
}

/**
 All supported commands:
 * g: gyroscope yaw.
    "g"
    return angle in float
 * u: ultrasonic ranging.
    "u?" (? is integer id)
    return distance in milimeter
    return "!DISTANCE" if distance invalid
    return "!ID" if id invalid

 * m: control speed.
    "m? ? ? ?" (? is float in range [-1,1])
    return loop backed speeds in form "%.2f,%.2f,%.2f,%.2f"

 * c: test acknowledge.
    "c"
    return "RECEIVED"

 * t: loop test. return what sent back
    "t?" (? is string that should loop back)
    return ?

 * w: wireless send.
    "w?" (? is message)
    return "SEND_OK"

 * r: wireless read.
    "r"
    return received message

 * a: 3-axes accelerometer
    "a"
    return "?,?,?"
        where ?s are head, right and down accelerometer readings in unit g
 */
void response(){
    char rdata[RESPONSE_BUFFER_SIZE] = {0};
    if(buffer[1]=='g'){
    // Request gyroscope angle
        sprintf(rdata, "%.2f", yaw);
        reply(rdata);
    }else if(buffer[1] == 'u'){
    // Request ultrasonic sensor data
        int sensor_id = buffer[2] - '0';
        if(sensor_id >= 0 && sensor_id <= 9){
            int distance = get_distance(sensor_id);
            if(distance != -1){
                sprintf(rdata, "%d", distance);
                reply(rdata);
            }else{
                reply("!DISTANCE");
            }

        }else{
            reply("!ID");
        }

    }else if(buffer[1] == 'm'){
    // Test 74HC573
        float q,a,w,s;
        sscanf(buffer+2, "%f %f %f %f", &q, &a, &w, &s);
        set_speeds(q,a,w,s);
        // if(buffer[2] == '0'){
        //     latch_enable_o2 = LATCH_OUTPUT_ENABLE;
        //     latched_bus.output();
        //     latched_bus[0] = 0;
        //     latch_enable_o2 = LATCH_OUTPUT_DISABLE;
        // }else if(buffer[2] == '1'){
        //     latch_enable_o2 = LATCH_OUTPUT_ENABLE;
        //     latched_bus.output();
        //     latched_bus[0] = 1;
        //     latch_enable_o2 = LATCH_OUTPUT_DISABLE;
        // }
        // sprintf(rdata, "%.2f,%.2f,%.2f,%.2f", q,a,w,s);
        reply("OK");
    // }else if(buffer[1] == '0'){
    //     latched_bus[6] = !latched_bus[6];
    //     reply("OK");
    // }else if(buffer[1] == '9'){
    //     latched_bus[7] = !latched_bus[7];
    //     reply("OK");
    }
    else if(buffer[1]=='c'){
    // Test Acknowledge
        reply("RECEIVED");
    }else if(buffer[1] == 't'){
    // Test Loop
        char *dupli = rdata;
        for(char *origin=(buffer+2); *origin!='\0'; origin++, dupli++){
            *dupli = *origin;
        }
        *dupli = '\0';
        reply(rdata);
    }else if(buffer[1] == 'w'){
    // Wireless Send
        // Prepare message:
        // Copy data segment to rdata
        char *dupli = rdata;
        for(char *origin=(buffer+2); *origin!='\0'; origin++, dupli++){
            *dupli = *origin;
        }
        // Append '\0' after all
        *dupli = '\0';

        // Send message througe wireless_uart
        wireless_send(rdata);
        reply("SEND_OK");
    }else if(buffer[1] == 'r'){
        int status = wireless_get(rdata);
        if(status == WIRELESS_RECEIVED){
            reply(rdata);
        }else{
            reply("!NO_DATA");
        }
    }else if(buffer[1] == 'a'){
    // Request acceleration of 3 axis
        sprintf(rdata, "%.3f,%.3f,%.3f", a_x, a_y, a_z);
        reply(rdata);
    }
}

int main(){
    init_latch();
    init_gyro();
    init_motor();

    while(1){
        char c = pc.getc();

        if(c == '$'){
        // Case: FLAG_HEAD_FINDING
            iBufferW = 0;
            buffer[iBufferW++] = c;
            if(flag != FLAG_HEAD_FINDING){
                warning(WARNING_REPEATED_START_HEAD_FINDING);
            }
            flag = FLAG_RECEIVING_BODY;

        }else if(flag == FLAG_RECEIVING_BODY){
        // Case: FLAG_RECEIVING_BODY
            if(c == '#'){
            // Char '#'' means start of checksum
                buffer[iBufferW++] = c;
                flag = FLAG_RECEIVING_CHECKSUM1;
            }else{
            // Or it is just part of body
                buffer[iBufferW++] = c;
            }
        }else if(flag == FLAG_RECEIVING_CHECKSUM1){
        // Case: FLAG_RECEIVING_CHECKSUM1
            buffer[iBufferW++] = c;
            flag = FLAG_RECEIVING_CHECKSUM2;
        }else if(flag == FLAG_RECEIVING_CHECKSUM2){
        // Case: FLAG_RECEIVING_CHECKSUM2
            buffer[iBufferW++] = c;

            if(validateChecksum()){
                buffer[iBufferW - 3] = '\0';
                response();
            }else{
                pc.printf("+$!SUM#65");
            }

            iBufferW = 0;
            flag = FLAG_HEAD_FINDING;
        }
    }
}
<commit_msg>Add command title for solving packet dislocation<commit_after>#include "mbed.h"

#include "imu.h"
#include "latch.h"
#include "distance.h"
#include "motor.h"
#include "wireless.h"
#include "config.h"

Serial pc(USBTX, USBRX); // tx, rx

#define FLAG_RECEIVING_BODY 1
#define FLAG_HEAD_FINDING 0
#define FLAG_RECEIVING_CHECKSUM1 2
#define FLAG_RECEIVING_CHECKSUM2 3

char buffer[BUFFER_SIZE] = {0};
int iBufferW = 0;
char flag = FLAG_HEAD_FINDING;

#define WARNING_REPEATED_START_HEAD_FINDING 0

void warning(int warning_num){
    if(warning_num == WARNING_REPEATED_START_HEAD_FINDING){

    }

}

char hex2nibble(char c){
    if(c >= 'a' && c <= 'f'){
        return c - 'a' + 10;
    }else if(c >= '0' && c <= '9'){
        return c - '0';
    }else{
        return -1;
    }
}

bool validateChecksum(){

    // Calculate sum
    uint8_t sum = 0;
    for(int i = 0; i<(iBufferW - 3); i++)
        // $ 1 2 3 # a b
        //               ^
        // So use index - 3
        sum += buffer[i];

    // Extract sum from last 2 hexadecimal
    uint8_t recv_sum = (
        (uint8_t)hex2nibble(buffer[iBufferW - 2]) << 4 |
        (uint8_t)hex2nibble(buffer[iBufferW - 1])
    );

    if(sum == recv_sum){
        return true;
    }else{
        return false;
    }
}

const char HEX_LOOKUP_TABLE[] = "0123456789abcdef";
void reply(char *message){
    // Calculate char sum of message
    char *input = message;
    uint8_t sum = '+' + '$';
    for(; (*input)!='\0' ; input++){
        sum += *input;
    }

    static uint8_t sum_s[3] = {0};
    sum_s[0] = HEX_LOOKUP_TABLE[ sum>>4 & 0x0F ];
    sum_s[1] = HEX_LOOKUP_TABLE[ sum & 0x0F ];

    pc.printf("+$%s#%s", message, sum_s);
}

/**
 All supported commands:
 * g: gyroscope yaw.
    "g"
    return angle in float
 * u: ultrasonic ranging.
    "u?" (? is integer id)
    return distance in milimeter
    return "!DISTANCE" if distance invalid
    return "!ID" if id invalid

 * m: control speed.
    "m? ? ? ?" (? is float in range [-1,1])
    return loop backed speeds in form "%.2f,%.2f,%.2f,%.2f"

 * c: test acknowledge.
    "c"
    return "RECEIVED"

 * t: loop test. return what sent back
    "t?" (? is string that should loop back)
    return ?

 * w: wireless send.
    "w?" (? is message)
    return "SEND_OK"

 * r: wireless read.
    "r"
    return received message

 * a: 3-axes accelerometer
    "a"
    return "?,?,?"
        where ?s are head, right and down accelerometer readings in unit g
 */
void response(){
    char rdata[RESPONSE_BUFFER_SIZE+1] = {0};
    if(buffer[1]=='g'){
    // Request gyroscope angle
        sprintf(rdata, "g%.2f", yaw);
        reply(rdata);
    }else if(buffer[1] == 'u'){
    // Request ultrasonic sensor data
        int sensor_id = buffer[2] - '0';
        if(sensor_id >= 0 && sensor_id <= 9){
            int distance = get_distance(sensor_id);
            if(distance != -1){
                sprintf(rdata, "u%d", distance);
                reply(rdata);
            }else{
                reply("u!DISTANCE");
            }

        }else{
            reply("u!ID");
        }

    }else if(buffer[1] == 'm'){
    // Test 74HC573
        float q,a,w,s;
        sscanf(buffer+2, "%f %f %f %f", &q, &a, &w, &s);
        set_speeds(q,a,w,s);
        // if(buffer[2] == '0'){
        //     latch_enable_o2 = LATCH_OUTPUT_ENABLE;
        //     latched_bus.output();
        //     latched_bus[0] = 0;
        //     latch_enable_o2 = LATCH_OUTPUT_DISABLE;
        // }else if(buffer[2] == '1'){
        //     latch_enable_o2 = LATCH_OUTPUT_ENABLE;
        //     latched_bus.output();
        //     latched_bus[0] = 1;
        //     latch_enable_o2 = LATCH_OUTPUT_DISABLE;
        // }
        sprintf(rdata, "m%.2f,%.2f,%.2f,%.2f", q,a,w,s);
        reply(rdata);
        // reply("mOK");
    // }else if(buffer[1] == '0'){
    //     latched_bus[6] = !latched_bus[6];
    //     reply("OK");
    // }else if(buffer[1] == '9'){
    //     latched_bus[7] = !latched_bus[7];
    //     reply("OK");
    }
    else if(buffer[1]=='c'){
    // Test Acknowledge
        reply("cRECEIVED");
    }else if(buffer[1] == 't'){
    // Test Loop
        rdata[0] = 't';
        // skip the first char which is the command title
        char *dupli = rdata + 1;
        for(char *origin=(buffer+2); *origin!='\0'; origin++, dupli++){
            *dupli = *origin;
        }
        *dupli = '\0';
        reply(rdata);
    }else if(buffer[1] == 'w'){
    // Wireless Send
        // Prepare message:
        // Copy data segment to rdata
        char *dupli = rdata;
        for(char *origin=(buffer+2); *origin!='\0'; origin++, dupli++){
            *dupli = *origin;
        }
        // Append '\0' after all
        *dupli = '\0';

        // Send message througe wireless_uart
        wireless_send(rdata);
        reply("wSEND_OK");
    }else if(buffer[1] == 'r'){
        rdata[0] = 'r';
        int status = wireless_get(rdata+1);
        if(status == WIRELESS_RECEIVED){
            reply(rdata);
        }else{
            reply("r!NO_DATA");
        }
    }else if(buffer[1] == 'a'){
    // Request acceleration of 3 axis
        sprintf(rdata, "a%.3f,%.3f,%.3f", a_x, a_y, a_z);
        reply(rdata);
    }
}

int main(){
    init_latch();
    init_gyro();
    init_motor();

    while(1){
        char c = pc.getc();

        if(c == '$'){
        // Case: FLAG_HEAD_FINDING
            iBufferW = 0;
            buffer[iBufferW++] = c;
            if(flag != FLAG_HEAD_FINDING){
                warning(WARNING_REPEATED_START_HEAD_FINDING);
            }
            flag = FLAG_RECEIVING_BODY;

        }else if(flag == FLAG_RECEIVING_BODY){
        // Case: FLAG_RECEIVING_BODY
            if(c == '#'){
            // Char '#'' means start of checksum
                buffer[iBufferW++] = c;
                flag = FLAG_RECEIVING_CHECKSUM1;
            }else{
            // Or it is just part of body
                buffer[iBufferW++] = c;
            }
        }else if(flag == FLAG_RECEIVING_CHECKSUM1){
        // Case: FLAG_RECEIVING_CHECKSUM1
            buffer[iBufferW++] = c;
            flag = FLAG_RECEIVING_CHECKSUM2;
        }else if(flag == FLAG_RECEIVING_CHECKSUM2){
        // Case: FLAG_RECEIVING_CHECKSUM2
            buffer[iBufferW++] = c;

            if(validateChecksum()){
                buffer[iBufferW - 3] = '\0';
                response();
            }else{
                pc.printf("+$!SUM#65");
            }

            iBufferW = 0;
            flag = FLAG_HEAD_FINDING;
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 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 "chrome/browser/prefs/pref_member.h"

#include "base/message_loop.h"
#include "chrome/browser/prefs/pref_value_store.h"
#include "chrome/test/testing_pref_service.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_details.h"
#include "content/common/notification_source.h"
#include "content/common/notification_type.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

const char kBoolPref[] = "bool";
const char kIntPref[] = "int";
const char kDoublePref[] = "double";
const char kStringPref[] = "string";

void RegisterTestPrefs(PrefService* prefs) {
  prefs->RegisterBooleanPref(kBoolPref, false);
  prefs->RegisterIntegerPref(kIntPref, 0);
  prefs->RegisterDoublePref(kDoublePref, 0.0);
  prefs->RegisterStringPref(kStringPref, "default");
}

class GetPrefValueCallback
    : public base::RefCountedThreadSafe<GetPrefValueCallback> {
 public:
  GetPrefValueCallback() : value_(false) {}

  void Init(const char* pref_name, PrefService* prefs) {
    pref_.Init(pref_name, prefs, NULL);
    pref_.MoveToThread(BrowserThread::IO);
  }

  bool FetchValue() {
    if (!BrowserThread::PostTask(
        BrowserThread::IO, FROM_HERE,
        NewRunnableMethod(this,
                          &GetPrefValueCallback::GetPrefValueOnIOThread))) {
      return false;
    }
    MessageLoop::current()->Run();
    return true;
  }

  bool value() { return value_; }

 private:
  friend class base::RefCountedThreadSafe<GetPrefValueCallback>;
  ~GetPrefValueCallback() {}

  void GetPrefValueOnIOThread() {
    value_ = pref_.GetValue();
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                            new MessageLoop::QuitTask());
  }

  BooleanPrefMember pref_;
  bool value_;
};

class PrefMemberTestClass : public NotificationObserver {
 public:
  explicit PrefMemberTestClass(PrefService* prefs)
      : observe_cnt_(0), prefs_(prefs) {
    str_.Init(kStringPref, prefs, this);
  }

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    DCHECK(NotificationType::PREF_CHANGED == type);
    PrefService* prefs_in = Source<PrefService>(source).ptr();
    EXPECT_EQ(prefs_in, prefs_);
    std::string* pref_name_in = Details<std::string>(details).ptr();
    EXPECT_EQ(*pref_name_in, kStringPref);
    EXPECT_EQ(str_.GetValue(), prefs_->GetString(kStringPref));
    ++observe_cnt_;
  }

  StringPrefMember str_;
  int observe_cnt_;

 private:
  PrefService* prefs_;
};

}  // anonymous namespace

TEST(PrefMemberTest, BasicGetAndSet) {
  TestingPrefService prefs;
  RegisterTestPrefs(&prefs);

  // Test bool
  BooleanPrefMember boolean;
  boolean.Init(kBoolPref, &prefs, NULL);

  // Check the defaults
  EXPECT_FALSE(prefs.GetBoolean(kBoolPref));
  EXPECT_FALSE(boolean.GetValue());
  EXPECT_FALSE(*boolean);

  // Try changing through the member variable.
  boolean.SetValue(true);
  EXPECT_TRUE(boolean.GetValue());
  EXPECT_TRUE(prefs.GetBoolean(kBoolPref));
  EXPECT_TRUE(*boolean);

  // Try changing back through the pref.
  prefs.SetBoolean(kBoolPref, false);
  EXPECT_FALSE(prefs.GetBoolean(kBoolPref));
  EXPECT_FALSE(boolean.GetValue());
  EXPECT_FALSE(*boolean);

  // Test int
  IntegerPrefMember integer;
  integer.Init(kIntPref, &prefs, NULL);

  // Check the defaults
  EXPECT_EQ(0, prefs.GetInteger(kIntPref));
  EXPECT_EQ(0, integer.GetValue());
  EXPECT_EQ(0, *integer);

  // Try changing through the member variable.
  integer.SetValue(5);
  EXPECT_EQ(5, integer.GetValue());
  EXPECT_EQ(5, prefs.GetInteger(kIntPref));
  EXPECT_EQ(5, *integer);

  // Try changing back through the pref.
  prefs.SetInteger(kIntPref, 2);
  EXPECT_EQ(2, prefs.GetInteger(kIntPref));
  EXPECT_EQ(2, integer.GetValue());
  EXPECT_EQ(2, *integer);

  // Test double
  DoublePrefMember double_member;
  double_member.Init(kDoublePref, &prefs, NULL);

  // Check the defaults
  EXPECT_EQ(0.0, prefs.GetDouble(kDoublePref));
  EXPECT_EQ(0.0, double_member.GetValue());
  EXPECT_EQ(0.0, *double_member);

  // Try changing through the member variable.
  double_member.SetValue(1.0);
  EXPECT_EQ(1.0, double_member.GetValue());
  EXPECT_EQ(1.0, prefs.GetDouble(kDoublePref));
  EXPECT_EQ(1.0, *double_member);

  // Try changing back through the pref.
  prefs.SetDouble(kDoublePref, 3.0);
  EXPECT_EQ(3.0, prefs.GetDouble(kDoublePref));
  EXPECT_EQ(3.0, double_member.GetValue());
  EXPECT_EQ(3.0, *double_member);

  // Test string
  StringPrefMember string;
  string.Init(kStringPref, &prefs, NULL);

  // Check the defaults
  EXPECT_EQ("default", prefs.GetString(kStringPref));
  EXPECT_EQ("default", string.GetValue());
  EXPECT_EQ("default", *string);

  // Try changing through the member variable.
  string.SetValue("foo");
  EXPECT_EQ("foo", string.GetValue());
  EXPECT_EQ("foo", prefs.GetString(kStringPref));
  EXPECT_EQ("foo", *string);

  // Try changing back through the pref.
  prefs.SetString(kStringPref, "bar");
  EXPECT_EQ("bar", prefs.GetString(kStringPref));
  EXPECT_EQ("bar", string.GetValue());
  EXPECT_EQ("bar", *string);
}

TEST(PrefMemberTest, TwoPrefs) {
  // Make sure two DoublePrefMembers stay in sync.
  TestingPrefService prefs;
  RegisterTestPrefs(&prefs);

  DoublePrefMember pref1;
  pref1.Init(kDoublePref, &prefs, NULL);
  DoublePrefMember pref2;
  pref2.Init(kDoublePref, &prefs, NULL);

  pref1.SetValue(2.3);
  EXPECT_EQ(2.3, *pref2);

  pref2.SetValue(3.5);
  EXPECT_EQ(3.5, *pref1);

  prefs.SetDouble(kDoublePref, 4.2);
  EXPECT_EQ(4.2, *pref1);
  EXPECT_EQ(4.2, *pref2);
}

TEST(PrefMemberTest, Observer) {
  TestingPrefService prefs;
  RegisterTestPrefs(&prefs);

  PrefMemberTestClass test_obj(&prefs);
  EXPECT_EQ("default", *test_obj.str_);

  // Calling SetValue should not fire the observer.
  test_obj.str_.SetValue("hello");
  EXPECT_EQ(0, test_obj.observe_cnt_);
  EXPECT_EQ("hello", prefs.GetString(kStringPref));

  // Changing the pref does fire the observer.
  prefs.SetString(kStringPref, "world");
  EXPECT_EQ(1, test_obj.observe_cnt_);
  EXPECT_EQ("world", *(test_obj.str_));

  // Not changing the value should not fire the observer.
  prefs.SetString(kStringPref, "world");
  EXPECT_EQ(1, test_obj.observe_cnt_);
  EXPECT_EQ("world", *(test_obj.str_));

  prefs.SetString(kStringPref, "hello");
  EXPECT_EQ(2, test_obj.observe_cnt_);
  EXPECT_EQ("hello", prefs.GetString(kStringPref));
}

TEST(PrefMemberTest, NoInit) {
  // Make sure not calling Init on a PrefMember doesn't cause problems.
  IntegerPrefMember pref;
}

// Flakily triggers an assertion, http://crbug.com/74386.
TEST(PrefMemberTest, DISABLED_MoveToThread) {
  MessageLoop message_loop;
  BrowserThread ui_thread(BrowserThread::UI, &message_loop);
  BrowserThread io_thread(BrowserThread::IO);
  ASSERT_TRUE(io_thread.Start());
  TestingPrefService prefs;
  RegisterTestPrefs(&prefs);
  scoped_refptr<GetPrefValueCallback> callback =
      make_scoped_refptr(new GetPrefValueCallback());
  callback->Init(kBoolPref, &prefs);

  ASSERT_TRUE(callback->FetchValue());
  EXPECT_FALSE(callback->value());

  prefs.SetBoolean(kBoolPref, true);

  ASSERT_TRUE(callback->FetchValue());
  EXPECT_TRUE(callback->value());
}
<commit_msg>Tear down objects in PrefMemberTest.MoveToThread in the right order.<commit_after>// Copyright (c) 2011 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 "chrome/browser/prefs/pref_member.h"

#include "base/message_loop.h"
#include "chrome/browser/prefs/pref_value_store.h"
#include "chrome/test/testing_pref_service.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_details.h"
#include "content/common/notification_source.h"
#include "content/common/notification_type.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

const char kBoolPref[] = "bool";
const char kIntPref[] = "int";
const char kDoublePref[] = "double";
const char kStringPref[] = "string";

void RegisterTestPrefs(PrefService* prefs) {
  prefs->RegisterBooleanPref(kBoolPref, false);
  prefs->RegisterIntegerPref(kIntPref, 0);
  prefs->RegisterDoublePref(kDoublePref, 0.0);
  prefs->RegisterStringPref(kStringPref, "default");
}

class GetPrefValueCallback
    : public base::RefCountedThreadSafe<GetPrefValueCallback> {
 public:
  GetPrefValueCallback() : value_(false) {}

  void Init(const char* pref_name, PrefService* prefs) {
    pref_.Init(pref_name, prefs, NULL);
    pref_.MoveToThread(BrowserThread::IO);
  }

  bool FetchValue() {
    if (!BrowserThread::PostTask(
        BrowserThread::IO, FROM_HERE,
        NewRunnableMethod(this,
                          &GetPrefValueCallback::GetPrefValueOnIOThread))) {
      return false;
    }
    MessageLoop::current()->Run();
    return true;
  }

  bool value() { return value_; }

 private:
  friend class base::RefCountedThreadSafe<GetPrefValueCallback>;
  ~GetPrefValueCallback() {}

  void GetPrefValueOnIOThread() {
    value_ = pref_.GetValue();
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                            new MessageLoop::QuitTask());
  }

  BooleanPrefMember pref_;
  bool value_;
};

class PrefMemberTestClass : public NotificationObserver {
 public:
  explicit PrefMemberTestClass(PrefService* prefs)
      : observe_cnt_(0), prefs_(prefs) {
    str_.Init(kStringPref, prefs, this);
  }

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    DCHECK(NotificationType::PREF_CHANGED == type);
    PrefService* prefs_in = Source<PrefService>(source).ptr();
    EXPECT_EQ(prefs_in, prefs_);
    std::string* pref_name_in = Details<std::string>(details).ptr();
    EXPECT_EQ(*pref_name_in, kStringPref);
    EXPECT_EQ(str_.GetValue(), prefs_->GetString(kStringPref));
    ++observe_cnt_;
  }

  StringPrefMember str_;
  int observe_cnt_;

 private:
  PrefService* prefs_;
};

}  // anonymous namespace

TEST(PrefMemberTest, BasicGetAndSet) {
  TestingPrefService prefs;
  RegisterTestPrefs(&prefs);

  // Test bool
  BooleanPrefMember boolean;
  boolean.Init(kBoolPref, &prefs, NULL);

  // Check the defaults
  EXPECT_FALSE(prefs.GetBoolean(kBoolPref));
  EXPECT_FALSE(boolean.GetValue());
  EXPECT_FALSE(*boolean);

  // Try changing through the member variable.
  boolean.SetValue(true);
  EXPECT_TRUE(boolean.GetValue());
  EXPECT_TRUE(prefs.GetBoolean(kBoolPref));
  EXPECT_TRUE(*boolean);

  // Try changing back through the pref.
  prefs.SetBoolean(kBoolPref, false);
  EXPECT_FALSE(prefs.GetBoolean(kBoolPref));
  EXPECT_FALSE(boolean.GetValue());
  EXPECT_FALSE(*boolean);

  // Test int
  IntegerPrefMember integer;
  integer.Init(kIntPref, &prefs, NULL);

  // Check the defaults
  EXPECT_EQ(0, prefs.GetInteger(kIntPref));
  EXPECT_EQ(0, integer.GetValue());
  EXPECT_EQ(0, *integer);

  // Try changing through the member variable.
  integer.SetValue(5);
  EXPECT_EQ(5, integer.GetValue());
  EXPECT_EQ(5, prefs.GetInteger(kIntPref));
  EXPECT_EQ(5, *integer);

  // Try changing back through the pref.
  prefs.SetInteger(kIntPref, 2);
  EXPECT_EQ(2, prefs.GetInteger(kIntPref));
  EXPECT_EQ(2, integer.GetValue());
  EXPECT_EQ(2, *integer);

  // Test double
  DoublePrefMember double_member;
  double_member.Init(kDoublePref, &prefs, NULL);

  // Check the defaults
  EXPECT_EQ(0.0, prefs.GetDouble(kDoublePref));
  EXPECT_EQ(0.0, double_member.GetValue());
  EXPECT_EQ(0.0, *double_member);

  // Try changing through the member variable.
  double_member.SetValue(1.0);
  EXPECT_EQ(1.0, double_member.GetValue());
  EXPECT_EQ(1.0, prefs.GetDouble(kDoublePref));
  EXPECT_EQ(1.0, *double_member);

  // Try changing back through the pref.
  prefs.SetDouble(kDoublePref, 3.0);
  EXPECT_EQ(3.0, prefs.GetDouble(kDoublePref));
  EXPECT_EQ(3.0, double_member.GetValue());
  EXPECT_EQ(3.0, *double_member);

  // Test string
  StringPrefMember string;
  string.Init(kStringPref, &prefs, NULL);

  // Check the defaults
  EXPECT_EQ("default", prefs.GetString(kStringPref));
  EXPECT_EQ("default", string.GetValue());
  EXPECT_EQ("default", *string);

  // Try changing through the member variable.
  string.SetValue("foo");
  EXPECT_EQ("foo", string.GetValue());
  EXPECT_EQ("foo", prefs.GetString(kStringPref));
  EXPECT_EQ("foo", *string);

  // Try changing back through the pref.
  prefs.SetString(kStringPref, "bar");
  EXPECT_EQ("bar", prefs.GetString(kStringPref));
  EXPECT_EQ("bar", string.GetValue());
  EXPECT_EQ("bar", *string);
}

TEST(PrefMemberTest, TwoPrefs) {
  // Make sure two DoublePrefMembers stay in sync.
  TestingPrefService prefs;
  RegisterTestPrefs(&prefs);

  DoublePrefMember pref1;
  pref1.Init(kDoublePref, &prefs, NULL);
  DoublePrefMember pref2;
  pref2.Init(kDoublePref, &prefs, NULL);

  pref1.SetValue(2.3);
  EXPECT_EQ(2.3, *pref2);

  pref2.SetValue(3.5);
  EXPECT_EQ(3.5, *pref1);

  prefs.SetDouble(kDoublePref, 4.2);
  EXPECT_EQ(4.2, *pref1);
  EXPECT_EQ(4.2, *pref2);
}

TEST(PrefMemberTest, Observer) {
  TestingPrefService prefs;
  RegisterTestPrefs(&prefs);

  PrefMemberTestClass test_obj(&prefs);
  EXPECT_EQ("default", *test_obj.str_);

  // Calling SetValue should not fire the observer.
  test_obj.str_.SetValue("hello");
  EXPECT_EQ(0, test_obj.observe_cnt_);
  EXPECT_EQ("hello", prefs.GetString(kStringPref));

  // Changing the pref does fire the observer.
  prefs.SetString(kStringPref, "world");
  EXPECT_EQ(1, test_obj.observe_cnt_);
  EXPECT_EQ("world", *(test_obj.str_));

  // Not changing the value should not fire the observer.
  prefs.SetString(kStringPref, "world");
  EXPECT_EQ(1, test_obj.observe_cnt_);
  EXPECT_EQ("world", *(test_obj.str_));

  prefs.SetString(kStringPref, "hello");
  EXPECT_EQ(2, test_obj.observe_cnt_);
  EXPECT_EQ("hello", prefs.GetString(kStringPref));
}

TEST(PrefMemberTest, NoInit) {
  // Make sure not calling Init on a PrefMember doesn't cause problems.
  IntegerPrefMember pref;
}

TEST(PrefMemberTest, MoveToThread) {
  TestingPrefService prefs;
  scoped_refptr<GetPrefValueCallback> callback =
      make_scoped_refptr(new GetPrefValueCallback());
  MessageLoop message_loop;
  BrowserThread ui_thread(BrowserThread::UI, &message_loop);
  BrowserThread io_thread(BrowserThread::IO);
  ASSERT_TRUE(io_thread.Start());
  RegisterTestPrefs(&prefs);
  callback->Init(kBoolPref, &prefs);

  ASSERT_TRUE(callback->FetchValue());
  EXPECT_FALSE(callback->value());

  prefs.SetBoolean(kBoolPref, true);

  ASSERT_TRUE(callback->FetchValue());
  EXPECT_TRUE(callback->value());
}
<|endoftext|>


<commit_before>#ifndef MEGINGJORD_SIMD_PACK
#define MEGINGJORD_SIMD_PACK
#include <megingjord/util/aligned_array.hpp>
#include <cmath>

namespace megingjord
{
namespace simd
{

template<typename, std::size_t> struct pack;
template<typename, std::size_t, typename> struct packed_array;

template<typename> struct is_simd : public std::false_type{};

template<typename> struct single_type_of;
template<typename T, std::size_t N>
struct single_type_of<pack<T, N>>
{
    typedef T type;
};
template<typename T, std::size_t N, std::size_t align>
struct single_type_of<aligned_array<T, N, align>>
{
    typedef T type;
};
template<typename T, std::size_t N, typename trait>
struct single_type_of<packed_array<T, N, trait>>
{
    typedef T type;
};

template<typename> struct set_impl;
template<typename> struct load_impl;
template<typename> struct broadcast_impl;
template<typename> struct store_impl;

template<typename T> struct add_impl
{
    constexpr static inline
    T invoke(T lhs, T rhs) {return lhs + rhs;}
};

template<typename T> struct sub_impl
{
    constexpr static inline
    T invoke(T lhs, T rhs) {return lhs - rhs;}
};

template<typename T> struct mul_impl
{
    constexpr static inline
    T invoke(T lhs, T rhs) {return lhs * rhs;}
};

template<typename T> struct div_impl
{
    constexpr static inline
    T invoke(T lhs, T rhs) {return lhs / rhs;}
};

template<typename T> struct rcp_impl
{
    constexpr static inline
    T invoke(T a) {return 1 / a;}
};

template<typename T> struct rsqrt_impl
{
    static inline
    T invoke(T a) {return 1 / std::sqrt(a);}
};

template<typename T> struct sqrt_impl
{
    static inline
    T invoke(T a) {return std::sqrt(a);}
};

template<typename T> struct floor_impl
{
    static inline
    T invoke(T a) {return std::floor(a);}
};

template<typename T> struct ceil_impl
{
    static inline
    T invoke(T a) {return std::ceil(a);}
};

template<typename T> struct fmadd_impl
{
    constexpr static inline
    T invoke(T a, T b, T c) {return a * b + c;}
};

template<typename T> struct fnmadd_impl
{
    constexpr static inline
    T invoke(T a, T b, T c) {return -a * b + c;}
};

template<typename T> struct fmsub_impl
{
    constexpr static inline
    T invoke(T a, T b, T c) {return a * b - c;}
};

template<typename T> struct fnmsub_impl
{
    constexpr static inline
    T invoke(T a, T b, T c) {return -a * b - c;}
};

} // simd
} // megingjord

#ifdef MJOLNIR_HAVE_AVX
#include <immintrin.h>
#include "avx/pack_avx.hpp"
#include "avx/functor_avx.hpp"
#define MEGINGJORD_DEFAULT_SIMD avx_traits
#endif

#include "packable_array.hpp"
#include "operation_pack.hpp"
#include "operation_array.hpp"

#endif /* MEGINGJORD_SIMD_PACK */
<commit_msg>add is_packable meta func<commit_after>#ifndef MEGINGJORD_SIMD_PACK
#define MEGINGJORD_SIMD_PACK
#include <megingjord/util/aligned_array.hpp>
#include <cmath>

namespace megingjord
{
namespace simd
{

template<typename, std::size_t> struct pack;
template<typename, std::size_t, typename> struct packed_array;

template<typename> struct is_simd : public std::false_type{};
template<typename> struct is_packable : public std::false_type{};
template<> struct is_packable<float>  : public std::true_type{};
template<> struct is_packable<double> : public std::true_type{};

template<typename> struct single_type_of;
template<typename T, std::size_t N>
struct single_type_of<pack<T, N>>
{
    typedef T type;
};
template<typename T, std::size_t N, std::size_t align>
struct single_type_of<aligned_array<T, N, align>>
{
    typedef T type;
};
template<typename T, std::size_t N, typename trait>
struct single_type_of<packed_array<T, N, trait>>
{
    typedef T type;
};

template<typename> struct set_impl;
template<typename> struct load_impl;
template<typename> struct broadcast_impl;
template<typename> struct store_impl;

template<typename T> struct add_impl
{
    constexpr static inline
    T invoke(T lhs, T rhs) {return lhs + rhs;}
};

template<typename T> struct sub_impl
{
    constexpr static inline
    T invoke(T lhs, T rhs) {return lhs - rhs;}
};

template<typename T> struct mul_impl
{
    constexpr static inline
    T invoke(T lhs, T rhs) {return lhs * rhs;}
};

template<typename T> struct div_impl
{
    constexpr static inline
    T invoke(T lhs, T rhs) {return lhs / rhs;}
};

template<typename T> struct rcp_impl
{
    constexpr static inline
    T invoke(T a) {return 1 / a;}
};

template<typename T> struct rsqrt_impl
{
    static inline
    T invoke(T a) {return 1 / std::sqrt(a);}
};

template<typename T> struct sqrt_impl
{
    static inline
    T invoke(T a) {return std::sqrt(a);}
};

template<typename T> struct floor_impl
{
    static inline
    T invoke(T a) {return std::floor(a);}
};

template<typename T> struct ceil_impl
{
    static inline
    T invoke(T a) {return std::ceil(a);}
};

template<typename T> struct fmadd_impl
{
    constexpr static inline
    T invoke(T a, T b, T c) {return a * b + c;}
};

template<typename T> struct fnmadd_impl
{
    constexpr static inline
    T invoke(T a, T b, T c) {return -a * b + c;}
};

template<typename T> struct fmsub_impl
{
    constexpr static inline
    T invoke(T a, T b, T c) {return a * b - c;}
};

template<typename T> struct fnmsub_impl
{
    constexpr static inline
    T invoke(T a, T b, T c) {return -a * b - c;}
};

} // simd
} // megingjord

#ifdef MJOLNIR_HAVE_AVX
#include <immintrin.h>
#include "avx/pack_avx.hpp"
#include "avx/functor_avx.hpp"
#define MEGINGJORD_DEFAULT_SIMD avx_traits
#endif

#include "packable_array.hpp"
#include "operation_pack.hpp"
#include "operation_array.hpp"

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


<commit_before>#ifndef RAY_BUW_HPP
#define RAY_BUW_HPP
#include <glm/vec3.hpp>

struct Ray
{
    Ray() :
    origin_{0.0,0.0,0.0},
    direction_{0.0,0.0,0.0},
    inv_direction_{-0.0,-0.0,-0.0} {}

    Ray(glm::vec3 const& o, glm::vec3 const& d) :
    origin_{o},
    direction_{d},
    inv_direction_{1.0/d.x,1.0/d.y,1.0/d.z} {}

    ~Ray() {}

    glm::vec3 origin_;
    glm::vec3 direction_;
    glm::vec3 inv_direction_;
};

#endif
<commit_msg>adding ray <<operator<commit_after>#ifndef RAY_BUW_HPP
#define RAY_BUW_HPP
#include <glm/vec3.hpp>

struct Ray
{
    Ray() :
    origin_{0.0,0.0,0.0},
    direction_{0.0,0.0,0.0},
    inv_direction_{-0.0,-0.0,-0.0} {}

    Ray(glm::vec3 const& o, glm::vec3 const& d) :
    origin_{o},
    direction_{d},
    inv_direction_{1.0/d.x,1.0/d.y,1.0/d.z} {}

    ~Ray() {}

    friend std::ostream& operator<<(std::ostream& os, Ray const& ray) {
        os << "Origin: ("
            << ray.origin_.x << ","
            << ray.origin_.y << ","
            << ray.origin_.z << ") \n"
            << "Direction: ("
            << ray.direction_.x << ","
            << ray.direction_.y << ","
            << ray.direction_.z << ") \n";
        return os;
    }

    glm::vec3 origin_;
    glm::vec3 direction_;
    glm::vec3 inv_direction_;
};

#endif
<|endoftext|>


<commit_before>#include "SVector.h"

namespace sofa
{

namespace helper
{

/// reading specialization for std::string
/// SVector begins by [, ends by ] and separates elements with ,
/// string elements must be delimited by ' or " (like a list of strings in python).
///
/// Note this is a quick&dirty implementation and it could be improved
template<>
std::istream& SVector<std::string>::read( std::istream& in )
{
    this->clear();

    std::string s(std::istreambuf_iterator<char>(in), {});

    size_t f = s.find_first_of('[');
    if( f == std::string::npos )
    {
        // a '[' must be present
        msg_error("SVector") << "read : a '[' is expected as beginning marker.";
        return in;
    }
    else
    {
        std::size_t f2 = s.find_first_not_of(' ',f);
        if( f2!=std::string::npos && f2 < f )
        {
            // the '[' must be the first character
            msg_error("SVector") << "read : Bad begin character, expected [";
            return in;
        }
    }

    size_t e = s.find_last_of(']');
    if( e == std::string::npos )
    {
        // a ']' must be present
        msg_error("SVector") << "read : a ']' is expected as ending marker.";
        return in;
    }
    else
    {
        // the ']' must be the last character
        std::size_t e2 = s.find_last_not_of(' ');
        if( e2!=std::string::npos && e2 > e )
        {
            msg_error("SVector") << "read : Bad end character, expected ]";
            return in;
        }
    }

    // looking for elements in between '[' and ']' separated by ','
    while(f<e-1)
    {
        size_t i = s.find_first_of(',', f+1); // i is the ',' position after the previous ','

        if( i == std::string::npos ) // no more ',' => last element
            i=e;

        std::size_t f2 = s.find_first_of("\"'",f+1);
        if( f2==std::string::npos )
        {
            msg_error("SVector") << "read : Bad begin string character, expected \" or '";
            this->clear();
            return in;
        }

        std::size_t i2 = s.find_last_of(s[f2],i-1);
        if( i2==std::string::npos )
        {
            msg_error("SVector") << "read : Bad end string character, expected "<<s[f2];
            this->clear();
            return in;
        }

        if( i2-f2-1<=0 ) // empty string
            this->push_back( "" );
        else
            this->push_back( s.substr(f2+1,i2-f2-1) );

        f=i; // the next element will begin after the ','
    }

    return in;
}

template<>
std::ostream& SVector<std::string>::write( std::ostream& os ) const
{
    if ( !this->empty() )
    {
        typename SVector<std::string>::const_iterator i = this->begin(), iend=this->end();
        os << "[ '" << *i <<"'";
        ++i;
        for ( ; i!=iend; ++i )
            os << " , '" << *i <<"'";
        os << " ]";
    }
    else os << "[]"; // empty vector
    return os;
}

}
}
<commit_msg>[SofaKernel] try to fix VS linking<commit_after>#include "SVector.h"

namespace sofa
{

namespace helper
{

/// reading specialization for std::string
/// SVector begins by [, ends by ] and separates elements with ,
/// string elements must be delimited by ' or " (like a list of strings in python).
///
/// Note this is a quick&dirty implementation and it could be improved
template<>
SOFA_HELPER_API std::istream& SVector<std::string>::read( std::istream& in )
{
    this->clear();

    std::string s(std::istreambuf_iterator<char>(in), {});

    size_t f = s.find_first_of('[');
    if( f == std::string::npos )
    {
        // a '[' must be present
        msg_error("SVector") << "read : a '[' is expected as beginning marker.";
        return in;
    }
    else
    {
        std::size_t f2 = s.find_first_not_of(' ',f);
        if( f2!=std::string::npos && f2 < f )
        {
            // the '[' must be the first character
            msg_error("SVector") << "read : Bad begin character, expected [";
            return in;
        }
    }

    size_t e = s.find_last_of(']');
    if( e == std::string::npos )
    {
        // a ']' must be present
        msg_error("SVector") << "read : a ']' is expected as ending marker.";
        return in;
    }
    else
    {
        // the ']' must be the last character
        std::size_t e2 = s.find_last_not_of(' ');
        if( e2!=std::string::npos && e2 > e )
        {
            msg_error("SVector") << "read : Bad end character, expected ]";
            return in;
        }
    }

    // looking for elements in between '[' and ']' separated by ','
    while(f<e-1)
    {
        size_t i = s.find_first_of(',', f+1); // i is the ',' position after the previous ','

        if( i == std::string::npos ) // no more ',' => last element
            i=e;

        std::size_t f2 = s.find_first_of("\"'",f+1);
        if( f2==std::string::npos )
        {
            msg_error("SVector") << "read : Bad begin string character, expected \" or '";
            this->clear();
            return in;
        }

        std::size_t i2 = s.find_last_of(s[f2],i-1);
        if( i2==std::string::npos )
        {
            msg_error("SVector") << "read : Bad end string character, expected "<<s[f2];
            this->clear();
            return in;
        }

        if( i2-f2-1<=0 ) // empty string
            this->push_back( "" );
        else
            this->push_back( s.substr(f2+1,i2-f2-1) );

        f=i; // the next element will begin after the ','
    }

    return in;
}

template<>
SOFA_HELPER_API std::ostream& SVector<std::string>::write( std::ostream& os ) const
{
    if ( !this->empty() )
    {
        typename SVector<std::string>::const_iterator i = this->begin(), iend=this->end();
        os << "[ '" << *i <<"'";
        ++i;
        for ( ; i!=iend; ++i )
            os << " , '" << *i <<"'";
        os << " ]";
    }
    else os << "[]"; // empty vector
    return os;
}

}
}
<|endoftext|>