<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/common/pepper_plugin_registry.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/native_library.h"
#include "base/path_service.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "remoting/client/plugin/pepper_entrypoints.h"

namespace {

const char* kPDFPluginName = "Chrome PDF Viewer";
const char* kPDFPluginMimeType = "application/pdf";
const char* kPDFPluginExtension = "pdf";
const char* kPDFPluginDescription = "Portable Document Format";

const char* kNaClPluginName = "Chrome NaCl";
const char* kNaClPluginMimeType = "application/x-nacl";
const char* kNaClPluginExtension = "nexe";
const char* kNaClPluginDescription = "Native Client Executable";

#if defined(ENABLE_REMOTING)
const char* kRemotingPluginMimeType = "pepper-application/x-chromoting";
#endif

// Appends the known built-in plugins to the given vector. Some built-in
// plugins are "internal" which means they are compiled into the Chrome binary,
// and some are extra shared libraries distributed with the browser (these are
// not marked internal, aside from being automatically registered, they're just
// regular plugins).
void ComputeBuiltInPlugins(std::vector<PepperPluginInfo>* plugins) {
  // PDF.
  //
  // Once we're sandboxed, we can't know if the PDF plugin is available or not;
  // but (on Linux) this function is always called once before we're sandboxed.
  // So the first time through test if the file is available and then skip the
  // check on subsequent calls if yes.
  static bool skip_pdf_file_check = false;
  FilePath path;
  if (PathService::Get(chrome::FILE_PDF_PLUGIN, &path)) {
    if (skip_pdf_file_check || file_util::PathExists(path)) {
      PepperPluginInfo pdf;
      pdf.path = path;
      pdf.name = kPDFPluginName;
      pdf.mime_types.push_back(kPDFPluginMimeType);
      pdf.file_extensions = kPDFPluginExtension;
      pdf.type_descriptions = kPDFPluginDescription;
      plugins->push_back(pdf);

      skip_pdf_file_check = true;
    }
  }

  // Native client.
  //
  // Verify that we enable nacl on the command line. The name of the switch
  // varies between the browser and renderer process.
  if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path) &&
      file_util::PathExists(path)) {
    PepperPluginInfo nacl;
    nacl.path = path;
    nacl.name = kNaClPluginName;
    nacl.mime_types.push_back(kNaClPluginMimeType);

    // TODO(bbudge) Remove this mime type after NaCl tree has been updated.
    const char* kNaClPluginOldMimeType = "application/x-ppapi-nacl-srpc";
    nacl.mime_types.push_back(kNaClPluginOldMimeType);

    nacl.file_extensions = kNaClPluginExtension;
    nacl.type_descriptions = kNaClPluginDescription;
    plugins->push_back(nacl);
  }

  // Remoting.
#if defined(ENABLE_REMOTING)
  if (CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableRemoting)) {
    PepperPluginInfo info;
    info.is_internal = true;
    info.path = FilePath(FILE_PATH_LITERAL("internal-chromoting"));
    info.mime_types.push_back(kRemotingPluginMimeType);
    info.internal_entry_points.get_interface = remoting::PPP_GetInterface;
    info.internal_entry_points.initialize_module =
        remoting::PPP_InitializeModule;
    info.internal_entry_points.shutdown_module = remoting::PPP_ShutdownModule;

    plugins->push_back(info);
  }
#endif
}

// Appends any plugins from the command line to the given vector.
void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) {
  const std::string value =
      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          switches::kRegisterPepperPlugins);
  if (value.empty())
    return;

  bool out_of_process =
      CommandLine::ForCurrentProcess()->HasSwitch(switches::kPpapiOutOfProcess);

  // FORMAT:
  // command-line = <plugin-entry> + *( LWS + "," + LWS + <plugin-entry> )
  // plugin-entry = <file-path> + ["#" + <name> + ["#" + <description>]] +
  //                *1( LWS + ";" + LWS + <mime-type> )

  std::vector<std::string> modules;
  base::SplitString(value, ',', &modules);
  for (size_t i = 0; i < modules.size(); ++i) {
    std::vector<std::string> parts;
    base::SplitString(modules[i], ';', &parts);
    if (parts.size() < 2) {
      DLOG(ERROR) << "Required mime-type not found";
      continue;
    }

    std::vector<std::string> name_parts;
    base::SplitString(parts[0], '#', &name_parts);

    PepperPluginInfo plugin;
    plugin.is_out_of_process = out_of_process;
#if defined(OS_WIN)
    // This means we can't provide plugins from non-ASCII paths, but
    // since this switch is only for development I don't think that's
    // too awful.
    plugin.path = FilePath(ASCIIToUTF16(name_parts[0]));
#else
    plugin.path = FilePath(name_parts[0]);
#endif
    if (name_parts.size() > 1)
      plugin.name = name_parts[1];
    if (name_parts.size() > 2) {
      plugin.description = name_parts[2];
      plugin.type_descriptions = name_parts[2];
    }
    for (size_t j = 1; j < parts.size(); ++j)
      plugin.mime_types.push_back(parts[j]);

    plugins->push_back(plugin);
  }
}

}  // namespace

const char* PepperPluginRegistry::kPDFPluginName = ::kPDFPluginName;

PepperPluginInfo::PepperPluginInfo()
    : is_internal(false),
      is_out_of_process(false) {
}

PepperPluginInfo::~PepperPluginInfo() {}

// static
PepperPluginRegistry* PepperPluginRegistry::GetInstance() {
  static PepperPluginRegistry* registry = NULL;
  // This object leaks.  It is a temporary hack to work around a crash.
  // http://code.google.com/p/chromium/issues/detail?id=63234
  if (!registry)
    registry = new PepperPluginRegistry;
  return registry;
}

// static
void PepperPluginRegistry::ComputeList(std::vector<PepperPluginInfo>* plugins) {
  ComputeBuiltInPlugins(plugins);
  ComputePluginsFromCommandLine(plugins);
}

// static
void PepperPluginRegistry::PreloadModules() {
  std::vector<PepperPluginInfo> plugins;
  ComputeList(&plugins);
  for (size_t i = 0; i < plugins.size(); ++i) {
    if (!plugins[i].is_internal && !plugins[i].is_out_of_process) {
      base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path);
      LOG_IF(WARNING, !library) << "Unable to load plugin "
                                << plugins[i].path.value();
    }
  }
}

const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin(
    const FilePath& path) const {
  for (size_t i = 0; i < plugin_list_.size(); ++i) {
    if (path == plugin_list_[i].path)
      return &plugin_list_[i];
  }
  return NULL;
}

webkit::ppapi::PluginModule* PepperPluginRegistry::GetLiveModule(
    const FilePath& path) {
  NonOwningModuleMap::iterator it = live_modules_.find(path);
  if (it == live_modules_.end())
    return NULL;
  return it->second;
}

void PepperPluginRegistry::AddLiveModule(const FilePath& path,
                                         webkit::ppapi::PluginModule* module) {
  DCHECK(live_modules_.find(path) == live_modules_.end());
  live_modules_[path] = module;
}

void PepperPluginRegistry::PluginModuleDestroyed(
    webkit::ppapi::PluginModule* destroyed_module) {
  // Modules aren't destroyed very often and there are normally at most a
  // couple of them. So for now we just do a brute-force search.
  for (NonOwningModuleMap::iterator i = live_modules_.begin();
       i != live_modules_.end(); ++i) {
    if (i->second == destroyed_module) {
      live_modules_.erase(i);
      return;
    }
  }
  NOTREACHED();  // Should have always found the module above.
}

PepperPluginRegistry::~PepperPluginRegistry() {
  // Explicitly clear all preloaded modules first. This will cause callbacks
  // to erase these modules from the live_modules_ list, and we don't want
  // that to happen implicitly out-of-order.
  preloaded_modules_.clear();

  DCHECK(live_modules_.empty());
}

PepperPluginRegistry::PepperPluginRegistry() {
  ComputeList(&plugin_list_);

  // Note that in each case, AddLiveModule must be called before completing
  // initialization. If we bail out (in the continue clauses) before saving
  // the initialized module, it will still try to unregister itself in its
  // destructor.
  for (size_t i = 0; i < plugin_list_.size(); i++) {
    const PepperPluginInfo& current = plugin_list_[i];
    if (current.is_out_of_process)
      continue;  // Out of process plugins need no special pre-initialization.

    scoped_refptr<webkit::ppapi::PluginModule> module =
        new webkit::ppapi::PluginModule(current.name, this);
    AddLiveModule(current.path, module);
    if (current.is_internal) {
      if (!module->InitAsInternalPlugin(current.internal_entry_points)) {
        DLOG(ERROR) << "Failed to load pepper module: " << current.path.value();
        continue;
      }
    } else {
      // Preload all external plugins we're not running out of process.
      module = new webkit::ppapi::PluginModule(current.name, this);
      AddLiveModule(current.path, module);
      if (!module->InitAsLibrary(current.path)) {
        DLOG(ERROR) << "Failed to load pepper module: " << current.path.value();
        continue;
      }
    }
    preloaded_modules_[current.path] = module;
  }
}
<commit_msg>Remove double-initialization for plugin modules.<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/common/pepper_plugin_registry.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/native_library.h"
#include "base/path_service.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "remoting/client/plugin/pepper_entrypoints.h"

namespace {

const char* kPDFPluginName = "Chrome PDF Viewer";
const char* kPDFPluginMimeType = "application/pdf";
const char* kPDFPluginExtension = "pdf";
const char* kPDFPluginDescription = "Portable Document Format";

const char* kNaClPluginName = "Chrome NaCl";
const char* kNaClPluginMimeType = "application/x-nacl";
const char* kNaClPluginExtension = "nexe";
const char* kNaClPluginDescription = "Native Client Executable";

#if defined(ENABLE_REMOTING)
const char* kRemotingPluginMimeType = "pepper-application/x-chromoting";
#endif

// Appends the known built-in plugins to the given vector. Some built-in
// plugins are "internal" which means they are compiled into the Chrome binary,
// and some are extra shared libraries distributed with the browser (these are
// not marked internal, aside from being automatically registered, they're just
// regular plugins).
void ComputeBuiltInPlugins(std::vector<PepperPluginInfo>* plugins) {
  // PDF.
  //
  // Once we're sandboxed, we can't know if the PDF plugin is available or not;
  // but (on Linux) this function is always called once before we're sandboxed.
  // So the first time through test if the file is available and then skip the
  // check on subsequent calls if yes.
  static bool skip_pdf_file_check = false;
  FilePath path;
  if (PathService::Get(chrome::FILE_PDF_PLUGIN, &path)) {
    if (skip_pdf_file_check || file_util::PathExists(path)) {
      PepperPluginInfo pdf;
      pdf.path = path;
      pdf.name = kPDFPluginName;
      pdf.mime_types.push_back(kPDFPluginMimeType);
      pdf.file_extensions = kPDFPluginExtension;
      pdf.type_descriptions = kPDFPluginDescription;
      plugins->push_back(pdf);

      skip_pdf_file_check = true;
    }
  }

  // Native client.
  //
  // Verify that we enable nacl on the command line. The name of the switch
  // varies between the browser and renderer process.
  if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path) &&
      file_util::PathExists(path)) {
    PepperPluginInfo nacl;
    nacl.path = path;
    nacl.name = kNaClPluginName;
    nacl.mime_types.push_back(kNaClPluginMimeType);

    // TODO(bbudge) Remove this mime type after NaCl tree has been updated.
    const char* kNaClPluginOldMimeType = "application/x-ppapi-nacl-srpc";
    nacl.mime_types.push_back(kNaClPluginOldMimeType);

    nacl.file_extensions = kNaClPluginExtension;
    nacl.type_descriptions = kNaClPluginDescription;
    plugins->push_back(nacl);
  }

  // Remoting.
#if defined(ENABLE_REMOTING)
  if (CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableRemoting)) {
    PepperPluginInfo info;
    info.is_internal = true;
    info.path = FilePath(FILE_PATH_LITERAL("internal-chromoting"));
    info.mime_types.push_back(kRemotingPluginMimeType);
    info.internal_entry_points.get_interface = remoting::PPP_GetInterface;
    info.internal_entry_points.initialize_module =
        remoting::PPP_InitializeModule;
    info.internal_entry_points.shutdown_module = remoting::PPP_ShutdownModule;

    plugins->push_back(info);
  }
#endif
}

// Appends any plugins from the command line to the given vector.
void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) {
  const std::string value =
      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          switches::kRegisterPepperPlugins);
  if (value.empty())
    return;

  bool out_of_process =
      CommandLine::ForCurrentProcess()->HasSwitch(switches::kPpapiOutOfProcess);

  // FORMAT:
  // command-line = <plugin-entry> + *( LWS + "," + LWS + <plugin-entry> )
  // plugin-entry = <file-path> + ["#" + <name> + ["#" + <description>]] +
  //                *1( LWS + ";" + LWS + <mime-type> )

  std::vector<std::string> modules;
  base::SplitString(value, ',', &modules);
  for (size_t i = 0; i < modules.size(); ++i) {
    std::vector<std::string> parts;
    base::SplitString(modules[i], ';', &parts);
    if (parts.size() < 2) {
      DLOG(ERROR) << "Required mime-type not found";
      continue;
    }

    std::vector<std::string> name_parts;
    base::SplitString(parts[0], '#', &name_parts);

    PepperPluginInfo plugin;
    plugin.is_out_of_process = out_of_process;
#if defined(OS_WIN)
    // This means we can't provide plugins from non-ASCII paths, but
    // since this switch is only for development I don't think that's
    // too awful.
    plugin.path = FilePath(ASCIIToUTF16(name_parts[0]));
#else
    plugin.path = FilePath(name_parts[0]);
#endif
    if (name_parts.size() > 1)
      plugin.name = name_parts[1];
    if (name_parts.size() > 2) {
      plugin.description = name_parts[2];
      plugin.type_descriptions = name_parts[2];
    }
    for (size_t j = 1; j < parts.size(); ++j)
      plugin.mime_types.push_back(parts[j]);

    plugins->push_back(plugin);
  }
}

}  // namespace

const char* PepperPluginRegistry::kPDFPluginName = ::kPDFPluginName;

PepperPluginInfo::PepperPluginInfo()
    : is_internal(false),
      is_out_of_process(false) {
}

PepperPluginInfo::~PepperPluginInfo() {}

// static
PepperPluginRegistry* PepperPluginRegistry::GetInstance() {
  static PepperPluginRegistry* registry = NULL;
  // This object leaks.  It is a temporary hack to work around a crash.
  // http://code.google.com/p/chromium/issues/detail?id=63234
  if (!registry)
    registry = new PepperPluginRegistry;
  return registry;
}

// static
void PepperPluginRegistry::ComputeList(std::vector<PepperPluginInfo>* plugins) {
  ComputeBuiltInPlugins(plugins);
  ComputePluginsFromCommandLine(plugins);
}

// static
void PepperPluginRegistry::PreloadModules() {
  std::vector<PepperPluginInfo> plugins;
  ComputeList(&plugins);
  for (size_t i = 0; i < plugins.size(); ++i) {
    if (!plugins[i].is_internal && !plugins[i].is_out_of_process) {
      base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path);
      LOG_IF(WARNING, !library) << "Unable to load plugin "
                                << plugins[i].path.value();
    }
  }
}

const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin(
    const FilePath& path) const {
  for (size_t i = 0; i < plugin_list_.size(); ++i) {
    if (path == plugin_list_[i].path)
      return &plugin_list_[i];
  }
  return NULL;
}

webkit::ppapi::PluginModule* PepperPluginRegistry::GetLiveModule(
    const FilePath& path) {
  NonOwningModuleMap::iterator it = live_modules_.find(path);
  if (it == live_modules_.end())
    return NULL;
  return it->second;
}

void PepperPluginRegistry::AddLiveModule(const FilePath& path,
                                         webkit::ppapi::PluginModule* module) {
  DCHECK(live_modules_.find(path) == live_modules_.end());
  live_modules_[path] = module;
}

void PepperPluginRegistry::PluginModuleDestroyed(
    webkit::ppapi::PluginModule* destroyed_module) {
  // Modules aren't destroyed very often and there are normally at most a
  // couple of them. So for now we just do a brute-force search.
  for (NonOwningModuleMap::iterator i = live_modules_.begin();
       i != live_modules_.end(); ++i) {
    if (i->second == destroyed_module) {
      live_modules_.erase(i);
      return;
    }
  }
  NOTREACHED();  // Should have always found the module above.
}

PepperPluginRegistry::~PepperPluginRegistry() {
  // Explicitly clear all preloaded modules first. This will cause callbacks
  // to erase these modules from the live_modules_ list, and we don't want
  // that to happen implicitly out-of-order.
  preloaded_modules_.clear();

  DCHECK(live_modules_.empty());
}

PepperPluginRegistry::PepperPluginRegistry() {
  ComputeList(&plugin_list_);

  // Note that in each case, AddLiveModule must be called before completing
  // initialization. If we bail out (in the continue clauses) before saving
  // the initialized module, it will still try to unregister itself in its
  // destructor.
  for (size_t i = 0; i < plugin_list_.size(); i++) {
    const PepperPluginInfo& current = plugin_list_[i];
    if (current.is_out_of_process)
      continue;  // Out of process plugins need no special pre-initialization.

    scoped_refptr<webkit::ppapi::PluginModule> module =
        new webkit::ppapi::PluginModule(current.name, this);
    AddLiveModule(current.path, module);
    if (current.is_internal) {
      if (!module->InitAsInternalPlugin(current.internal_entry_points)) {
        DLOG(ERROR) << "Failed to load pepper module: " << current.path.value();
        continue;
      }
    } else {
      // Preload all external plugins we're not running out of process.
      if (!module->InitAsLibrary(current.path)) {
        DLOG(ERROR) << "Failed to load pepper module: " << current.path.value();
        continue;
      }
    }
    preloaded_modules_[current.path] = module;
  }
}
<|endoftext|>


<commit_before>// scope_exchange.C -- Exchange values with external models.
//
// Copyright 2007 Per Abrahamsen and KVL.
//
// This file is part of Daisy.
//
// Daisy is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// Daisy is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with Daisy; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "scope.h"
#include "block.h"
#include "alist.h"
#include "memutils.h"

class Exchange
{
  // Content.
public:
  static const char *const description;

  // Use.
  virtual bool is_number () const
  { return false; }
  virtual symbol name () const = 0;
  virtual double number () const
  { daisy_notreached (); }
  virtual bool has_number () const
  { return false; }
  virtual symbol dimension () const
  { daisy_notreached (); }
  virtual bool has_identifier () const
  { return false; }
  virtual symbol identifier () const
  { daisy_notreached (); }
  virtual symbol get_description () const = 0;
  virtual void set_number (const double)
  { daisy_notreached (); }

  // Create and Destroy.
public:
  Exchange ()
  { }
  virtual ~Exchange ()
  { }
};

#ifdef FORWARD_TEMPLATES
template<>
Librarian<Exchange>::Content* Librarian<Exchange>::content;
#endif

static Librarian<Exchange> Exchange_init ("exchange");

template<>
Librarian<Exchange>::Content* Librarian<Exchange>::content = NULL;

const char *const
Exchange::description = "\
A named value to exchange with external models.";

struct ExchangeNumber : public Exchange
{
  // Content.
  const symbol name_;
  const symbol dimension_;
  const symbol description;
  bool has_value;
  double value;

  // Use
  bool is_number () const
  { return true; }
  symbol name () const
  { return name_; }
  double number () const
  { return value; }
  bool has_number () const
  { return has_value; }
  symbol dimension () const
  { return dimension_; }
  symbol get_description () const
  { return description; }
  void set_number (const double val)
  { value = val; has_value = true; }

  // Create and Destroy.
  ExchangeNumber (Block& al)
    : name_ (al.identifier ("name")),
      dimension_ (al.identifier ("dimension")),
      description (al.identifier ("description")),
      has_value (al.check ("value")),
      value (al.number ("value", -42.42e42))
  { }
  ~ExchangeNumber ()
  { }
};

static struct ExchangeNumberSyntax
{
  static Exchange& make (Block& al)
  { return *new ExchangeNumber (al); }
  ExchangeNumberSyntax ()
  {
    Syntax& syntax = *new Syntax ();
    AttributeList& alist = *new AttributeList ();
    syntax.add ("description", Syntax::String, Syntax::Const, "\
Description of value to exchange.");
    alist.add ("description", "Exchange a numeric value.");
    syntax.add ("name", Syntax::String, Syntax::Const, "\
Name of value to exchange.");
    syntax.add ("dimension", Syntax::String, Syntax::Const, "\
Dimension of value to exchange.");
    syntax.add ("value", Syntax::Unknown (), Syntax::OptionalState, "\
Current value to exchange.");
    Librarian<Exchange>::add_type ("number", alist, syntax, &make);
  }
} ExchangeNumber_syntax;

struct ExchangeName : public Exchange
{
  // Content.
  const symbol name_;
  const symbol description;
  const symbol value;

  // Use
  symbol name () const
  { return name_; }
  bool has_identifier () const
  { return true; }
  symbol identifier () const
  { return value; }
  symbol get_description () const
  { return description; }

  // Create and Destroy.
  ExchangeName (Block& al)
    : name_ (al.identifier ("name")),
      description (al.identifier ("description")),
      value (al.identifier ("value"))
  { }
  ~ExchangeName ()
  { }
};

static struct ExchangeNameSyntax
{
  static Exchange& make (Block& al)
  { return *new ExchangeName (al); }
  ExchangeNameSyntax ()
  {
    Syntax& syntax = *new Syntax ();
    AttributeList& alist = *new AttributeList ();
    syntax.add ("description", Syntax::String, Syntax::Const, "\
Description of value to exchange.");
    alist.add ("description", "Exchange a numeric value.");
    syntax.add ("name", Syntax::String, Syntax::Const, "\
Name of value to exchange.");
    syntax.add ("value", Syntax::String, Syntax::Const, "\
Current value to exchange.");
    Librarian<Exchange>::add_type ("name", alist, syntax, &make);
  }
} ExchangeName_syntax;

class ScopeExchange : public WScope
{
  // Parameters.
private:
  const auto_vector<Exchange*> entries;
  const std::vector<symbol> all_numbers_;
  const std::map<symbol, Exchange*> named;

  // Scope.
public:
  const std::vector<symbol>& all_numbers () const
  { return all_numbers_; }
  bool has_number (symbol tag) const
  {
    const std::map<symbol, Exchange*>::const_iterator i = named.find (tag);
    daisy_assert (i != named.end ());
    return (*i).second->has_number ();
  }
  double number (symbol tag) const
  {
    const std::map<symbol, Exchange*>::const_iterator i = named.find (tag);
    daisy_assert (i != named.end ());
    return (*i).second->number ();
  }
  symbol dimension (symbol tag) const
  {
    const std::map<symbol, Exchange*>::const_iterator i = named.find (tag);
    daisy_assert (i != named.end ());
    return (*i).second->dimension ();
  }
  symbol get_description (symbol tag) const
  {
    const std::map<symbol, Exchange*>::const_iterator i = named.find (tag);
    daisy_assert (i != named.end ());
    return (*i).second->get_description ();
  }

  // WScope.
public:
  void set_number (symbol tag, double value)
  {
    const std::map<symbol, Exchange*>::const_iterator i = named.find (tag);
    daisy_assert (i != named.end ());
    (*i).second->set_number (value);
  }

  // Create.
private:
  static std::vector<symbol>
  /**/ find_all_numbers (const std::vector<Exchange*>& entries)
  {
    std::vector<symbol> result;
    for (size_t i = 0; i < entries.size (); i++)
      if (entries[i]->is_number ())
        result.push_back (entries[i]->name ());
    return result;
  }
  static std::map<symbol, Exchange*>
  /**/ find_named (const std::vector<Exchange*>& entries)
  {
    std::map<symbol, Exchange*> result;
    for (size_t i = 0; i < entries.size (); i++)
      result[entries[i]->name ()] = entries[i];
    return result;
  }
public:
  ScopeExchange (Block& al)
    : entries (Librarian<Exchange>::build_vector (al, "entries")),
      all_numbers_ (find_all_numbers (entries)),
      named (find_named (entries))
  { }
};

static struct ScopeExchangeSyntax
{
  static Scope&
  make (Block& al)
  { return *new ScopeExchange (al); }
  ScopeExchangeSyntax ()
  {
    Syntax& syntax = *new Syntax ();
    AttributeList& alist = *new AttributeList ();
    alist.add ("description",
               "Exchange values with an external model.");

    syntax.add ("entries", Librarian<Exchange>::library (),
                Syntax::Const, Syntax::Sequence,
                "List of items to exchange.");
    Librarian<Scope>::add_type ("exchange", alist, syntax, &make);
  }
} ScopeExchange_syntax;
<commit_msg>x40<commit_after>// scope_exchange.C -- Exchange values with external models.
//
// Copyright 2007 Per Abrahamsen and KVL.
//
// This file is part of Daisy.
//
// Daisy is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// Daisy is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with Daisy; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "scope.h"
#include "block.h"
#include "alist.h"
#include "memutils.h"

class Exchange
{
  // Content.
public:
  static const char *const description;

  // Use.
  virtual bool is_number () const
  { return false; }
  virtual symbol name () const = 0;
  virtual double number () const
  { daisy_notreached (); }
  virtual bool has_number () const
  { return false; }
  virtual symbol dimension () const
  { daisy_notreached (); }
  virtual bool has_identifier () const
  { return false; }
  virtual symbol identifier () const
  { daisy_notreached (); }
  virtual symbol get_description () const = 0;
  virtual void set_number (const double)
  { daisy_notreached (); }

  // Create and Destroy.
public:
  Exchange ()
  { }
  virtual ~Exchange ()
  { }
};

#ifdef FORWARD_TEMPLATES
template<>
Librarian<Exchange>::Content* Librarian<Exchange>::content;
#endif

static Librarian<Exchange> Exchange_init ("exchange");

template<>
Librarian<Exchange>::Content* Librarian<Exchange>::content = NULL;

const char *const
Exchange::description = "\
A named value to exchange with external models.";

struct ExchangeNumber : public Exchange
{
  // Content.
  const symbol name_;
  const symbol dimension_;
  const symbol description;
  bool has_value;
  double value;

  // Use
  bool is_number () const
  { return true; }
  symbol name () const
  { return name_; }
  double number () const
  { return value; }
  bool has_number () const
  { return has_value; }
  symbol dimension () const
  { return dimension_; }
  symbol get_description () const
  { return description; }
  void set_number (const double val)
  { value = val; has_value = true; }

  // Create and Destroy.
  ExchangeNumber (Block& al)
    : name_ (al.identifier ("name")),
      dimension_ (al.identifier ("dimension")),
      description (al.identifier ("description")),
      has_value (al.check ("value")),
      value (al.number ("value", -42.42e42))
  { }
  ~ExchangeNumber ()
  { }
};

static struct ExchangeNumberSyntax
{
  static Exchange& make (Block& al)
  { return *new ExchangeNumber (al); }
  ExchangeNumberSyntax ()
  {
    Syntax& syntax = *new Syntax ();
    AttributeList& alist = *new AttributeList ();
    syntax.add ("description", Syntax::String, Syntax::Const, "\
Description of value to exchange.");
    alist.add ("description", "Exchange a numeric value.");
    syntax.add ("name", Syntax::String, Syntax::Const, "\
Name of value to exchange.");
    syntax.add ("dimension", Syntax::String, Syntax::Const, "\
Dimension of value to exchange.");
    syntax.add ("value", Syntax::Unknown (), Syntax::OptionalState, "\
Current value to exchange.");
    Librarian<Exchange>::add_type ("number", alist, syntax, &make);
  }
} ExchangeNumber_syntax;

struct ExchangeName : public Exchange
{
  // Content.
  const symbol name_;
  const symbol description;
  const symbol value;

  // Use
  symbol name () const
  { return name_; }
  bool has_identifier () const
  { return true; }
  symbol identifier () const
  { return value; }
  symbol get_description () const
  { return description; }

  // Create and Destroy.
  ExchangeName (Block& al)
    : name_ (al.identifier ("name")),
      description (al.identifier ("description")),
      value (al.identifier ("value"))
  { }
  ~ExchangeName ()
  { }
};

static struct ExchangeNameSyntax
{
  static Exchange& make (Block& al)
  { return *new ExchangeName (al); }
  ExchangeNameSyntax ()
  {
    Syntax& syntax = *new Syntax ();
    AttributeList& alist = *new AttributeList ();
    syntax.add ("description", Syntax::String, Syntax::Const, "\
Description of value to exchange.");
    alist.add ("description", "Exchange a numeric value.");
    syntax.add ("name", Syntax::String, Syntax::Const, "\
Name of value to exchange.");
    syntax.add ("value", Syntax::String, Syntax::Const, "\
Current value to exchange.");
    Librarian<Exchange>::add_type ("name", alist, syntax, &make);
  }
} ExchangeName_syntax;

class ScopeExchange : public WScope
{
  // Parameters.
private:
  const auto_vector<Exchange*> entries;
  const std::vector<symbol> all_numbers_;
  const std::map<symbol, Exchange*> named;

  // Scope.
public:
  const std::vector<symbol>& all_numbers () const
  { return all_numbers_; }
  bool has_number (symbol tag) const
  {
    const std::map<symbol, Exchange*>::const_iterator i = named.find (tag);
    if (i == named.end ())
      return false;
    return (*i).second->has_number ();
  }
  double number (symbol tag) const
  {
    const std::map<symbol, Exchange*>::const_iterator i = named.find (tag);
    daisy_assert (i != named.end ());
    return (*i).second->number ();
  }
  symbol dimension (symbol tag) const
  {
    const std::map<symbol, Exchange*>::const_iterator i = named.find (tag);
    daisy_assert (i != named.end ());
    return (*i).second->dimension ();
  }
  symbol get_description (symbol tag) const
  {
    const std::map<symbol, Exchange*>::const_iterator i = named.find (tag);
    daisy_assert (i != named.end ());
    return (*i).second->get_description ();
  }

  // WScope.
public:
  void set_number (symbol tag, double value)
  {
    const std::map<symbol, Exchange*>::const_iterator i = named.find (tag);
    daisy_assert (i != named.end ());
    (*i).second->set_number (value);
  }

  // Create.
private:
  static std::vector<symbol>
  /**/ find_all_numbers (const std::vector<Exchange*>& entries)
  {
    std::vector<symbol> result;
    for (size_t i = 0; i < entries.size (); i++)
      if (entries[i]->is_number ())
        result.push_back (entries[i]->name ());
    return result;
  }
  static std::map<symbol, Exchange*>
  /**/ find_named (const std::vector<Exchange*>& entries)
  {
    std::map<symbol, Exchange*> result;
    for (size_t i = 0; i < entries.size (); i++)
      result[entries[i]->name ()] = entries[i];
    return result;
  }
public:
  ScopeExchange (Block& al)
    : entries (Librarian<Exchange>::build_vector (al, "entries")),
      all_numbers_ (find_all_numbers (entries)),
      named (find_named (entries))
  { }
};

static struct ScopeExchangeSyntax
{
  static Scope&
  make (Block& al)
  { return *new ScopeExchange (al); }
  ScopeExchangeSyntax ()
  {
    Syntax& syntax = *new Syntax ();
    AttributeList& alist = *new AttributeList ();
    alist.add ("description",
               "Exchange values with an external model.");

    syntax.add ("entries", Librarian<Exchange>::library (),
                Syntax::Const, Syntax::Sequence,
                "List of items to exchange.");
    Librarian<Scope>::add_type ("exchange", alist, syntax, &make);
  }
} ScopeExchange_syntax;
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "../lest/include/lest/lest.hpp"
#include "../../route/path_to_regex.cpp"

using namespace std;
using namespace route;

// ------------ TESTING PATH_TO_REGEX WITH OPTIONS --------------

const lest::test test_path_to_regex_options[] =
{
  SCENARIO("Calling path_to_regex with options")
  {
    // Create with option strict

    GIVEN("An empty vector of Tokens (keys) and option strict set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true} };

      WHEN("Calling path_to_regex with path '/:test'")
      {
        std::regex r = PathToRegex::path_to_regex("/:test", keys, options);

        THEN("")
        {

        }
      }
    }/*,

    GIVEN("An empty vector of Tokens (keys) and option strict set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    // Create with option sensitive

    GIVEN("An empty vector of Tokens (keys) and option sensitive set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"sensitive", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option sensitive set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"sensitive", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    // Create with option end

    GIVEN("An empty vector of Tokens (keys) and option end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    // Create with options strict and sensitive

    GIVEN("An empty vector of Tokens (keys) and options strict and sensitive set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"sensitive", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and options strict and sensitive set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"sensitive", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to true and option sensitive set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"sensitive", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to false and option sensitive set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"sensitive", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    // Create with options strict and end

    GIVEN("An empty vector of Tokens (keys) and options strict and end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and options strict and end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to true and option end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to false and option end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    // Create with options sensitive and end

    GIVEN("An empty vector of Tokens (keys) and options sensitive and end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"sensitive", true}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and options sensitive and end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"sensitive", false}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option sensitive set to true and option end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"sensitive", true}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option sensitive set to false and option end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"sensitive", false}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    // Create with options strict, sensitive and end

    GIVEN("An empty vector of Tokens (keys) and options strict, sensitive and end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"sensitive", true}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and options strict, sensitive and end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"sensitive", false}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to true, sensitive set to true and end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"sensitive", true}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to true, sensitive set to false and end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"sensitive", false}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to true, sensitive set to false and end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"sensitive", false}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to false, sensitive set to false and end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"sensitive", false}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to false, sensitive set to true and end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"sensitive", true}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to false, sensitive set to true and end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"sensitive", true}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    }*/
  } // < SCENARIO (with options)
};

int main(int argc, char * argv[])
{
  printf("Running tests of path_to_regex with options...\n");

  int res = lest::run(test_path_to_regex_options, argc, argv);

  printf("Path_to_regex-tests (with options) completed.\n");

  return res;
}
<commit_msg>Updated include for path_to_regex_options.cpp<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "../lest/include/lest/lest.hpp"
#include "../../route/path_to_regex.hpp"

using namespace std;
using namespace route;

// ------------ TESTING PATH_TO_REGEX WITH OPTIONS --------------

const lest::test test_path_to_regex_options[] =
{
  SCENARIO("Calling path_to_regex with options")
  {
    // Create with option strict

    GIVEN("An empty vector of Tokens (keys) and option strict set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true} };

      WHEN("Calling path_to_regex with path '/:test'")
      {
        std::regex r = PathToRegex::path_to_regex("/:test", keys, options);

        THEN("")
        {

        }
      }
    }/*,

    GIVEN("An empty vector of Tokens (keys) and option strict set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    // Create with option sensitive

    GIVEN("An empty vector of Tokens (keys) and option sensitive set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"sensitive", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option sensitive set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"sensitive", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    // Create with option end

    GIVEN("An empty vector of Tokens (keys) and option end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    // Create with options strict and sensitive

    GIVEN("An empty vector of Tokens (keys) and options strict and sensitive set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"sensitive", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and options strict and sensitive set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"sensitive", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to true and option sensitive set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"sensitive", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to false and option sensitive set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"sensitive", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    // Create with options strict and end

    GIVEN("An empty vector of Tokens (keys) and options strict and end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and options strict and end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to true and option end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to false and option end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    // Create with options sensitive and end

    GIVEN("An empty vector of Tokens (keys) and options sensitive and end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"sensitive", true}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and options sensitive and end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"sensitive", false}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option sensitive set to true and option end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"sensitive", true}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option sensitive set to false and option end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"sensitive", false}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    // Create with options strict, sensitive and end

    GIVEN("An empty vector of Tokens (keys) and options strict, sensitive and end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"sensitive", true}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and options strict, sensitive and end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"sensitive", false}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to true, sensitive set to true and end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"sensitive", true}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to true, sensitive set to false and end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"sensitive", false}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to true, sensitive set to false and end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", true}, {"sensitive", false}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to false, sensitive set to false and end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"sensitive", false}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to false, sensitive set to true and end set to true")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"sensitive", true}, {"end", true} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    },

    GIVEN("An empty vector of Tokens (keys) and option strict set to false, sensitive set to true and end set to false")
    {
      vector<Token> keys;
      map<string, bool> options{ {"strict", false}, {"sensitive", true}, {"end", false} };

      WHEN("Calling path_to_regex with path ''")
      {
        std::regex r = PathToRegex::path_to_regex("", keys, options);

      }
    }*/
  } // < SCENARIO (with options)
};

int main(int argc, char * argv[])
{
  printf("Running tests of path_to_regex with options...\n");

  int res = lest::run(test_path_to_regex_options, argc, argv);

  printf("Path_to_regex-tests (with options) completed.\n");

  return res;
}
<|endoftext|>


<commit_before>/* **********************************************************
 * Copyright (c) 2011 Google, Inc.  All rights reserved.
 * **********************************************************/

/* Dr. Memory: the memory debugger
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License, and no later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Library General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <windows.h>

#include <commctrl.h>
#include <winuser.h>

#include "gtest/gtest.h"

#pragma comment(lib, "comctl32.lib")

TEST(NtUserTests, SystemParametersInfo) {
    // Was: http://code.google.com/p/drmemory/issues/detail?id=10
    NONCLIENTMETRICS metrics;
    ZeroMemory(&metrics, sizeof(NONCLIENTMETRICS));
    metrics.cbSize = sizeof(NONCLIENTMETRICS);
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS),
                         &metrics, 0);
}

namespace Clipboard_Tests {
void WriteStringToClipboard(const std::string& str) {
    HWND hWnd = ::GetDesktopWindow();
    ASSERT_NE(0, ::OpenClipboard(hWnd));
    ::EmptyClipboard();
    HGLOBAL data = ::GlobalAlloc(2 /*GMEM_MOVABLE*/, str.size() + 1);
    ASSERT_NE((HGLOBAL)NULL, data);

    char* raw_data = (char*)::GlobalLock(data);
    memcpy(raw_data, str.data(), str.size() * sizeof(char));
    raw_data[str.size()] = '\0';
    ::GlobalUnlock(data);

    ASSERT_EQ(data, ::SetClipboardData(CF_TEXT, data));
    ::CloseClipboard();
}

void ReadAsciiStringFromClipboard(std::string *result) {
    assert(result != NULL);

    HWND hWnd = ::GetDesktopWindow();
    ASSERT_NE(0, ::OpenClipboard(hWnd));

    HANDLE data = ::GetClipboardData(CF_TEXT);
    ASSERT_NE((HANDLE)NULL, data);

    result->assign((const char*)::GlobalLock(data));

    ::GlobalUnlock(data);
    ::CloseClipboard();
}

TEST(NtUserTests, ClipboardPutGet) {
    // Was: http://code.google.com/p/drmemory/issues/detail?id=45
    std::string tmp, str = "ASCII";
    WriteStringToClipboard(str);
    ReadAsciiStringFromClipboard(&tmp);
    ASSERT_STREQ("ASCII", tmp.c_str());
}
}

TEST(NtUserTests, CoInitializeUninitialize) {
    // Was: http://code.google.com/p/drmemory/issues/detail?id=65
    CoInitialize(NULL);
    CoUninitialize();
}

TEST(NtUserTests, InitCommonControlsEx) {
    // Was: http://code.google.com/p/drmemory/issues/detail?id=362
    INITCOMMONCONTROLSEX InitCtrlEx;

    InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
    InitCtrlEx.dwICC  = ICC_PROGRESS_CLASS;
    InitCommonControlsEx(&InitCtrlEx);  // initialize common control sex
}
<commit_msg>Add a disabled GetAdaptersInfo test to app_suite tests.<commit_after>/* **********************************************************
 * Copyright (c) 2011 Google, Inc.  All rights reserved.
 * **********************************************************/

/* Dr. Memory: the memory debugger
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License, and no later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Library General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <windows.h>

#include <winuser.h>

#include "gtest/gtest.h"

// For InitCommonControlsEx
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")

// For GetAdaptersInfo
#include <iphlpapi.h>
#pragma comment(lib, "IPHLPAPI.lib")

// A potentially externally visible global.  Useful if you want to make a
// statement the compiler can't delete.
int global_for_side_effects;

TEST(NtUserTests, SystemParametersInfo) {
    // Was: http://code.google.com/p/drmemory/issues/detail?id=10
    NONCLIENTMETRICS metrics;
    ZeroMemory(&metrics, sizeof(NONCLIENTMETRICS));
    metrics.cbSize = sizeof(NONCLIENTMETRICS);
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS),
                         &metrics, 0);
}

namespace Clipboard_Tests {

void WriteStringToClipboard(const std::string& str) {
    HWND hWnd = ::GetDesktopWindow();
    ASSERT_NE(0, ::OpenClipboard(hWnd));
    ::EmptyClipboard();
    HGLOBAL data = ::GlobalAlloc(2 /*GMEM_MOVABLE*/, str.size() + 1);
    ASSERT_NE((HGLOBAL)NULL, data);

    char* raw_data = (char*)::GlobalLock(data);
    memcpy(raw_data, str.data(), str.size() * sizeof(char));
    raw_data[str.size()] = '\0';
    ::GlobalUnlock(data);

    ASSERT_EQ(data, ::SetClipboardData(CF_TEXT, data));
    ::CloseClipboard();
}

void ReadAsciiStringFromClipboard(std::string *result) {
    assert(result != NULL);

    HWND hWnd = ::GetDesktopWindow();
    ASSERT_NE(0, ::OpenClipboard(hWnd));

    HANDLE data = ::GetClipboardData(CF_TEXT);
    ASSERT_NE((HANDLE)NULL, data);

    result->assign((const char*)::GlobalLock(data));

    ::GlobalUnlock(data);
    ::CloseClipboard();
}

TEST(NtUserTests, ClipboardPutGet) {
    // Was: http://code.google.com/p/drmemory/issues/detail?id=45
    std::string tmp, str = "ASCII";
    WriteStringToClipboard(str);
    ReadAsciiStringFromClipboard(&tmp);
    ASSERT_STREQ("ASCII", tmp.c_str());
}

} /* Clipboard_Tests */

TEST(NtUserTests, CoInitializeUninitialize) {
    // Was: http://code.google.com/p/drmemory/issues/detail?id=65
    CoInitialize(NULL);
    CoUninitialize();
}

TEST(NtUserTests, InitCommonControlsEx) {
    // Was: http://code.google.com/p/drmemory/issues/detail?id=362
    INITCOMMONCONTROLSEX InitCtrlEx;

    InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
    InitCtrlEx.dwICC  = ICC_PROGRESS_CLASS;
    InitCommonControlsEx(&InitCtrlEx);  // initialize common control sex
}

TEST(NtUserTests, DISABLED_GetAdaptersInfoTest) {
    // http://code.google.com/p/drmemory/issues/detail?id=719
    IP_ADAPTER_INFO dummy;
    ULONG size = 0;  // force overflow
    ULONG res = GetAdaptersInfo(&dummy, &size);
    ASSERT_EQ(ERROR_BUFFER_OVERFLOW, res)
        << "Failed to determine number of networks available.";

    char *buffer = new char[size];
    IP_ADAPTER_INFO *infos = (IP_ADAPTER_INFO*)buffer;
    res = GetAdaptersInfo(infos, &size);
    ASSERT_EQ(NO_ERROR, res);
    // Verify that we don't get uninits from using the outputs in conditionals.
    if (size > 0) {
        MEMORY_BASIC_INFORMATION mbi;
        VirtualQuery(infos->Next, &mbi, sizeof(mbi));
    }
    delete [] buffer;
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <boost/version.hpp>
#include "libtorrent/pch.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/error_code.hpp"

namespace libtorrent
{
	boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p
		, int m, error_code& ec)
	{
		TORRENT_ASSERT(st != 0);
		TORRENT_ASSERT(p.is_complete());
		TORRENT_ASSERT((m & file::rw_mask) == file::read_only
			|| (m & file::rw_mask) == file::read_write);
		boost::mutex::scoped_lock l(m_mutex);
		file_set::iterator i = m_files.find(p.string());
		if (i != m_files.end())
		{
			lru_file_entry& e = i->second;
			e.last_use = time_now();

			if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
				|| (m & file::rw_mask) != file::read_only))
			{
				// this means that another instance of the storage
				// is using the exact same file.
#if BOOST_VERSION >= 103500
				ec = error_code(errors::file_collision, libtorrent_category);
#endif
				return boost::shared_ptr<file>();
			}

			e.key = st;
			// if we asked for a file in write mode,
			// and the cached file is is not opened in
			// write mode, re-open it
			if (((e.mode & file::rw_mask) != file::read_write)
				&& ((m & file::rw_mask) == file::read_write))
			{
				// close the file before we open it with
				// the new read/write privilages
				TORRENT_ASSERT(e.file_ptr.unique());
				e.file_ptr->close();
				if (!e.file_ptr->open(p, m, ec))
				{
					m_files.erase(i);
					return boost::shared_ptr<file>();
				}
				TORRENT_ASSERT(e.file_ptr->is_open());
				e.mode = m;
			}
			TORRENT_ASSERT((e.mode & file::no_buffer) == (m & file::no_buffer));
			return e.file_ptr;
		}
		// the file is not in our cache
		if ((int)m_files.size() >= m_size)
		{
			// the file cache is at its maximum size, close
			// the least recently used (lru) file from it
			remove_oldest();
		}
		lru_file_entry e;
		e.file_ptr.reset(new (std::nothrow)file);
		if (!e.file_ptr)
		{
			ec = error_code(ENOMEM, get_posix_category());
			return e.file_ptr;
		}
		if (!e.file_ptr->open(p, m, ec))
			return boost::shared_ptr<file>();
		e.mode = m;
		e.key = st;
		m_files.insert(std::make_pair(p.string(), e));
		TORRENT_ASSERT(e.file_ptr->is_open());
		return e.file_ptr;
	}

	void file_pool::remove_oldest()
	{
		file_set::iterator i = std::min_element(m_files.begin(), m_files.end()
			, boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _1))
				< boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _2)));
		if (i == m_files.end()) return;
		m_files.erase(i);
	}

	void file_pool::release(fs::path const& p)
	{
		boost::mutex::scoped_lock l(m_mutex);

		file_set::iterator i = m_files.find(p.string());
		if (i != m_files.end()) m_files.erase(i);
	}

	void file_pool::release(void* st)
	{
		boost::mutex::scoped_lock l(m_mutex);
		TORRENT_ASSERT(st != 0);

		for (file_set::iterator i = m_files.begin();
			i != m_files.end();)
		{
			if (i->second.key == st)
				m_files.erase(i++);
			else
				++i;
		}
	}

	void file_pool::resize(int size)
	{
		TORRENT_ASSERT(size > 0);
		if (size == m_size) return;
		boost::mutex::scoped_lock l(m_mutex);
		m_size = size;
		if (int(m_files.size()) <= m_size) return;

		// close the least recently used files
		while (int(m_files.size()) > m_size)
			remove_oldest();
	}

}
<commit_msg>added missing include<commit_after>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <boost/version.hpp>
#include <boost/bind.hpp>
#include "libtorrent/pch.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/error_code.hpp"

namespace libtorrent
{
	boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p
		, int m, error_code& ec)
	{
		TORRENT_ASSERT(st != 0);
		TORRENT_ASSERT(p.is_complete());
		TORRENT_ASSERT((m & file::rw_mask) == file::read_only
			|| (m & file::rw_mask) == file::read_write);
		boost::mutex::scoped_lock l(m_mutex);
		file_set::iterator i = m_files.find(p.string());
		if (i != m_files.end())
		{
			lru_file_entry& e = i->second;
			e.last_use = time_now();

			if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
				|| (m & file::rw_mask) != file::read_only))
			{
				// this means that another instance of the storage
				// is using the exact same file.
#if BOOST_VERSION >= 103500
				ec = error_code(errors::file_collision, libtorrent_category);
#endif
				return boost::shared_ptr<file>();
			}

			e.key = st;
			// if we asked for a file in write mode,
			// and the cached file is is not opened in
			// write mode, re-open it
			if (((e.mode & file::rw_mask) != file::read_write)
				&& ((m & file::rw_mask) == file::read_write))
			{
				// close the file before we open it with
				// the new read/write privilages
				TORRENT_ASSERT(e.file_ptr.unique());
				e.file_ptr->close();
				if (!e.file_ptr->open(p, m, ec))
				{
					m_files.erase(i);
					return boost::shared_ptr<file>();
				}
				TORRENT_ASSERT(e.file_ptr->is_open());
				e.mode = m;
			}
			TORRENT_ASSERT((e.mode & file::no_buffer) == (m & file::no_buffer));
			return e.file_ptr;
		}
		// the file is not in our cache
		if ((int)m_files.size() >= m_size)
		{
			// the file cache is at its maximum size, close
			// the least recently used (lru) file from it
			remove_oldest();
		}
		lru_file_entry e;
		e.file_ptr.reset(new (std::nothrow)file);
		if (!e.file_ptr)
		{
			ec = error_code(ENOMEM, get_posix_category());
			return e.file_ptr;
		}
		if (!e.file_ptr->open(p, m, ec))
			return boost::shared_ptr<file>();
		e.mode = m;
		e.key = st;
		m_files.insert(std::make_pair(p.string(), e));
		TORRENT_ASSERT(e.file_ptr->is_open());
		return e.file_ptr;
	}

	void file_pool::remove_oldest()
	{
		file_set::iterator i = std::min_element(m_files.begin(), m_files.end()
			, boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _1))
				< boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _2)));
		if (i == m_files.end()) return;
		m_files.erase(i);
	}

	void file_pool::release(fs::path const& p)
	{
		boost::mutex::scoped_lock l(m_mutex);

		file_set::iterator i = m_files.find(p.string());
		if (i != m_files.end()) m_files.erase(i);
	}

	void file_pool::release(void* st)
	{
		boost::mutex::scoped_lock l(m_mutex);
		TORRENT_ASSERT(st != 0);

		for (file_set::iterator i = m_files.begin();
			i != m_files.end();)
		{
			if (i->second.key == st)
				m_files.erase(i++);
			else
				++i;
		}
	}

	void file_pool::resize(int size)
	{
		TORRENT_ASSERT(size > 0);
		if (size == m_size) return;
		boost::mutex::scoped_lock l(m_mutex);
		m_size = size;
		if (int(m_files.size()) <= m_size) return;

		// close the least recently used files
		while (int(m_files.size()) > m_size)
			remove_oldest();
	}

}
<|endoftext|>


<commit_before>/*
 *   Copyright (C) 2011 by Hugo Stefan Kaus Puhmann
 *
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *   of this software and associated documentation files (the "Software"), to deal
 *   in the Software without restriction, including without limitation the rights
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *   copies of the Software, and to permit persons to whom the Software is
 *   furnished to do so, subject to the following conditions:
 */

#include <GL/glfw.h>
#include "GameWorld.hpp"
#include <ctime>
#include <cstdlib>

#ifdef __unix__
#include <sys/time.h>
#endif

#ifdef __unix__
struct timespec last_update;
#else
std::clock_t last_update = 0;
#endif

int main(int argc, char* argv[])
{
#ifdef __unix__
   clock_gettime(CLOCK_REALTIME, &last_update);
#else
   last_update = std::clock();
#endif

   glfwInit();
   glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE, GL_TRUE);
   glfwOpenWindow(800, 450, 8, 8, 8, 8, 24, 8, GLFW_WINDOW);

   using hstefan::game::GameWorld;

   GameWorld* world = GameWorld::getInstance();

   bool running = true;

   while(running)
   {
      if(glfwGetKey(GLFW_KEY_ESC) == GLFW_PRESS)
         break;

#ifdef __unix__
      static const double UPDATE_INTERVAL = 1. / 30.;
      static const time_t UPDATE_INTERVAL_SEC = UPDATE_INTERVAL;
      static const unsigned long UPDATE_INTERVAL_NS = (UPDATE_INTERVAL-UPDATE_INTERVAL_SEC) * 1E9;

      struct timespec update_time;
      clock_gettime(CLOCK_REALTIME, &update_time);

      if (update_time.tv_sec - last_update.tv_sec >= UPDATE_INTERVAL_SEC &&
         (unsigned long)update_time.tv_nsec - (unsigned long)last_update.tv_nsec >= UPDATE_INTERVAL_NS)
      {
         world->update();
         clock_gettime(CLOCK_REALTIME, &last_update);
      }
#else
      static const std::clock_t UPDATE_INTERVAL = CLOCKS_PER_SEC / 30;
      world->update();

      if (std::clock() >= last_update + UPDATE_INTERVAL)
      {
         world->render();
         last_update += UPDATE_INTERVAL;
      }
#endif

      glfwSwapBuffers();
      running = glfwGetWindowParam(GLFW_OPENED) != 0;
   }

   glfwTerminate();
}<commit_msg>Better update/rendering management.<commit_after>/*
 *   Copyright (C) 2011 by Hugo Stefan Kaus Puhmann
 *
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *   of this software and associated documentation files (the "Software"), to deal
 *   in the Software without restriction, including without limitation the rights
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *   copies of the Software, and to permit persons to whom the Software is
 *   furnished to do so, subject to the following conditions:
 */

#include <GL/glfw.h>
#include "GameWorld.hpp"
#include <ctime>
#include <cstdlib>

int main(int argc, char* argv[])
{
   glfwInit();
   glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE, GL_TRUE);
   glfwOpenWindow(800, 450, 8, 8, 8, 8, 24, 8, GLFW_WINDOW);

   using hstefan::game::GameWorld;

   GameWorld* world = GameWorld::getInstance();

   bool running = true;

   double last_render = 0;
   double last_update = 0;

   double frame_interval = 1.f/60.f;
   double update_interval = 1.f/90.f;

   double cur_time = 0;

   while(running)
   {
      cur_time = glfwGetTime();
      if(glfwGetKey(GLFW_KEY_ESC) == GLFW_PRESS)
         break;
      if(cur_time - last_render > frame_interval)
      {
         last_render = glfwGetTime();
         world->render();
      }

      if(cur_time - last_update > update_interval)
      {
         world->update();
         last_update = glfwGetTime();
      }

      glfwSleep(update_interval - (cur_time + glfwGetTime()));
      glfwSwapBuffers();
      running = glfwGetWindowParam(GLFW_OPENED) != 0;
   }

   glfwTerminate();
}<|endoftext|>


<commit_before>// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)

#include <gtest/internal/gtest-port.h>

#include <limits.h>
#ifdef GTEST_HAS_DEATH_TEST
#include <regex.h>
#endif  // GTEST_HAS_DEATH_TEST
#include <stdlib.h>
#include <stdio.h>

#include <gtest/gtest-spi.h>
#include <gtest/gtest-message.h>
#include <gtest/internal/gtest-string.h>

namespace testing {
namespace internal {

#ifdef GTEST_HAS_DEATH_TEST

// Implements RE.  Currently only needed for death tests.

RE::~RE() {
  regfree(&regex_);
  free(const_cast<char*>(pattern_));
}

// Returns true iff str contains regular expression re.
bool RE::PartialMatch(const char* str, const RE& re) {
  if (!re.is_valid_) return false;

  regmatch_t match;
  return regexec(&re.regex_, str, 1, &match, 0) == 0;
}

// Initializes an RE from its string representation.
void RE::Init(const char* regex) {
  pattern_ = strdup(regex);
  is_valid_ = regcomp(&regex_, regex, REG_EXTENDED) == 0;
  EXPECT_TRUE(is_valid_)
      << "Regular expression \"" << regex
      << "\" is not a valid POSIX Extended regular expression.";
}

#endif  // GTEST_HAS_DEATH_TEST

// Logs a message at the given severity level.
void GTestLog(GTestLogSeverity severity, const char* file,
              int line, const char* msg) {
  const char* const marker =
      severity == GTEST_INFO ?    "[  INFO ]" :
      severity == GTEST_WARNING ? "[WARNING]" :
      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
  fprintf(stderr, "\n%s %s:%d: %s\n", marker, file, line, msg);
  if (severity == GTEST_FATAL) {
    abort();
  }
}

#ifdef GTEST_HAS_DEATH_TEST

// Defines the stderr capturer.

class CapturedStderr {
 public:
  // The ctor redirects stderr to a temporary file.
  CapturedStderr() {
    uncaptured_fd_ = dup(STDERR_FILENO);

    char name_template[] = "captured_stderr.XXXXXX";
    const int captured_fd = mkstemp(name_template);
    filename_ = name_template;
    fflush(NULL);
    dup2(captured_fd, STDERR_FILENO);
    close(captured_fd);
  }

  ~CapturedStderr() {
    remove(filename_.c_str());
  }

  // Stops redirecting stderr.
  void StopCapture() {
    // Restores the original stream.
    fflush(NULL);
    dup2(uncaptured_fd_, STDERR_FILENO);
    close(uncaptured_fd_);
    uncaptured_fd_ = -1;
  }

  // Returns the name of the temporary file holding the stderr output.
  // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
  // can use it here.
  ::std::string filename() const { return filename_; }

 private:
  int uncaptured_fd_;
  ::std::string filename_;
};

static CapturedStderr* g_captured_stderr = NULL;

// Returns the size (in bytes) of a file.
static size_t GetFileSize(FILE * file) {
  fseek(file, 0, SEEK_END);
  return static_cast<size_t>(ftell(file));
}

// Reads the entire content of a file as a string.
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can
// use it here.
static ::std::string ReadEntireFile(FILE * file) {
  const size_t file_size = GetFileSize(file);
  char* const buffer = new char[file_size];

  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
  size_t bytes_read = 0;       // # of bytes read so far

  fseek(file, 0, SEEK_SET);

  // Keeps reading the file until we cannot read further or the
  // pre-determined file size is reached.
  do {
    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
    bytes_read += bytes_last_read;
  } while (bytes_last_read > 0 && bytes_read < file_size);

  const ::std::string content(buffer, buffer+bytes_read);
  delete[] buffer;

  return content;
}

// Starts capturing stderr.
void CaptureStderr() {
  if (g_captured_stderr != NULL) {
    GTEST_LOG(FATAL, "Only one stderr capturer can exist at one time.");
  }
  g_captured_stderr = new CapturedStderr;
}

// Stops capturing stderr and returns the captured string.
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can
// use it here.
::std::string GetCapturedStderr() {
  g_captured_stderr->StopCapture();
  FILE* const file = fopen(g_captured_stderr->filename().c_str(), "r");
  const ::std::string content = ReadEntireFile(file);
  fclose(file);

  delete g_captured_stderr;
  g_captured_stderr = NULL;

  return content;
}

// A copy of all command line arguments.  Set by InitGoogleTest().
::std::vector<String> g_argvs;

// Returns the command line as a vector of strings.
const ::std::vector<String>& GetArgvs() { return g_argvs; }

#endif  // GTEST_HAS_DEATH_TEST

// Returns the name of the environment variable corresponding to the
// given flag.  For example, FlagToEnvVar("foo") will return
// "GTEST_FOO" in the open-source version.
static String FlagToEnvVar(const char* flag) {
  const String full_flag = (Message() << GTEST_FLAG_PREFIX << flag).GetString();

  Message env_var;
  for (int i = 0; i != full_flag.GetLength(); i++) {
    env_var << static_cast<char>(toupper(full_flag.c_str()[i]));
  }

  return env_var.GetString();
}

// Reads and returns the Boolean environment variable corresponding to
// the given flag; if it's not set, returns default_value.
//
// The value is considered true iff it's not "0".
bool BoolFromGTestEnv(const char* flag, bool default_value) {
  const String env_var = FlagToEnvVar(flag);
  const char* const string_value = GetEnv(env_var.c_str());
  return string_value == NULL ?
      default_value : strcmp(string_value, "0") != 0;
}

// Parses 'str' for a 32-bit signed integer.  If successful, writes
// the result to *value and returns true; otherwise leaves *value
// unchanged and returns false.
bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
  // Parses the environment variable as a decimal integer.
  char* end = NULL;
  const long long_value = strtol(str, &end, 10);  // NOLINT

  // Has strtol() consumed all characters in the string?
  if (*end != '\0') {
    // No - an invalid character was encountered.
    Message msg;
    msg << "WARNING: " << src_text
        << " is expected to be a 32-bit integer, but actually"
        << " has value \"" << str << "\".\n";
    printf("%s", msg.GetString().c_str());
    fflush(stdout);
    return false;
  }

  // Is the parsed value in the range of an Int32?
  const Int32 result = static_cast<Int32>(long_value);
  if (long_value == LONG_MAX || long_value == LONG_MIN ||
      // The parsed value overflows as a long.  (strtol() returns
      // LONG_MAX or LONG_MIN when the input overflows.)
      result != long_value
      // The parsed value overflows as an Int32.
      ) {
    Message msg;
    msg << "WARNING: " << src_text
        << " is expected to be a 32-bit integer, but actually"
        << " has value " << str << ", which overflows.\n";
    printf("%s", msg.GetString().c_str());
    fflush(stdout);
    return false;
  }

  *value = result;
  return true;
}

// Reads and returns a 32-bit integer stored in the environment
// variable corresponding to the given flag; if it isn't set or
// doesn't represent a valid 32-bit integer, returns default_value.
Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
  const String env_var = FlagToEnvVar(flag);
  const char* const string_value = GetEnv(env_var.c_str());
  if (string_value == NULL) {
    // The environment variable is not set.
    return default_value;
  }

  Int32 result = default_value;
  if (!ParseInt32(Message() << "Environment variable " << env_var,
                  string_value, &result)) {
    printf("The default value %s is used.\n",
           (Message() << default_value).GetString().c_str());
    fflush(stdout);
    return default_value;
  }

  return result;
}

// Reads and returns the string environment variable corresponding to
// the given flag; if it's not set, returns default_value.
const char* StringFromGTestEnv(const char* flag, const char* default_value) {
  const String env_var = FlagToEnvVar(flag);
  const char* const value = GetEnv(env_var.c_str());
  return value == NULL ? default_value : value;
}

}  // namespace internal
}  // namespace testing
<commit_msg>Makes death tests create temporary files in /tmp instead of the current folder.<commit_after>// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)

#include <gtest/internal/gtest-port.h>

#include <limits.h>
#ifdef GTEST_HAS_DEATH_TEST
#include <regex.h>
#endif  // GTEST_HAS_DEATH_TEST
#include <stdlib.h>
#include <stdio.h>

#include <gtest/gtest-spi.h>
#include <gtest/gtest-message.h>
#include <gtest/internal/gtest-string.h>

namespace testing {
namespace internal {

#ifdef GTEST_HAS_DEATH_TEST

// Implements RE.  Currently only needed for death tests.

RE::~RE() {
  regfree(&regex_);
  free(const_cast<char*>(pattern_));
}

// Returns true iff str contains regular expression re.
bool RE::PartialMatch(const char* str, const RE& re) {
  if (!re.is_valid_) return false;

  regmatch_t match;
  return regexec(&re.regex_, str, 1, &match, 0) == 0;
}

// Initializes an RE from its string representation.
void RE::Init(const char* regex) {
  pattern_ = strdup(regex);
  is_valid_ = regcomp(&regex_, regex, REG_EXTENDED) == 0;
  EXPECT_TRUE(is_valid_)
      << "Regular expression \"" << regex
      << "\" is not a valid POSIX Extended regular expression.";
}

#endif  // GTEST_HAS_DEATH_TEST

// Logs a message at the given severity level.
void GTestLog(GTestLogSeverity severity, const char* file,
              int line, const char* msg) {
  const char* const marker =
      severity == GTEST_INFO ?    "[  INFO ]" :
      severity == GTEST_WARNING ? "[WARNING]" :
      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
  fprintf(stderr, "\n%s %s:%d: %s\n", marker, file, line, msg);
  if (severity == GTEST_FATAL) {
    abort();
  }
}

#ifdef GTEST_HAS_DEATH_TEST

// Defines the stderr capturer.

class CapturedStderr {
 public:
  // The ctor redirects stderr to a temporary file.
  CapturedStderr() {
    uncaptured_fd_ = dup(STDERR_FILENO);

    // There's no guarantee that a test has write access to the
    // current directory, so we create the temporary file in the /tmp
    // directory instead.
    char name_template[] = "/tmp/captured_stderr.XXXXXX";
    const int captured_fd = mkstemp(name_template);
    filename_ = name_template;
    fflush(NULL);
    dup2(captured_fd, STDERR_FILENO);
    close(captured_fd);
  }

  ~CapturedStderr() {
    remove(filename_.c_str());
  }

  // Stops redirecting stderr.
  void StopCapture() {
    // Restores the original stream.
    fflush(NULL);
    dup2(uncaptured_fd_, STDERR_FILENO);
    close(uncaptured_fd_);
    uncaptured_fd_ = -1;
  }

  // Returns the name of the temporary file holding the stderr output.
  // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
  // can use it here.
  ::std::string filename() const { return filename_; }

 private:
  int uncaptured_fd_;
  ::std::string filename_;
};

static CapturedStderr* g_captured_stderr = NULL;

// Returns the size (in bytes) of a file.
static size_t GetFileSize(FILE * file) {
  fseek(file, 0, SEEK_END);
  return static_cast<size_t>(ftell(file));
}

// Reads the entire content of a file as a string.
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can
// use it here.
static ::std::string ReadEntireFile(FILE * file) {
  const size_t file_size = GetFileSize(file);
  char* const buffer = new char[file_size];

  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
  size_t bytes_read = 0;       // # of bytes read so far

  fseek(file, 0, SEEK_SET);

  // Keeps reading the file until we cannot read further or the
  // pre-determined file size is reached.
  do {
    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
    bytes_read += bytes_last_read;
  } while (bytes_last_read > 0 && bytes_read < file_size);

  const ::std::string content(buffer, buffer+bytes_read);
  delete[] buffer;

  return content;
}

// Starts capturing stderr.
void CaptureStderr() {
  if (g_captured_stderr != NULL) {
    GTEST_LOG(FATAL, "Only one stderr capturer can exist at one time.");
  }
  g_captured_stderr = new CapturedStderr;
}

// Stops capturing stderr and returns the captured string.
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can
// use it here.
::std::string GetCapturedStderr() {
  g_captured_stderr->StopCapture();
  FILE* const file = fopen(g_captured_stderr->filename().c_str(), "r");
  const ::std::string content = ReadEntireFile(file);
  fclose(file);

  delete g_captured_stderr;
  g_captured_stderr = NULL;

  return content;
}

// A copy of all command line arguments.  Set by InitGoogleTest().
::std::vector<String> g_argvs;

// Returns the command line as a vector of strings.
const ::std::vector<String>& GetArgvs() { return g_argvs; }

#endif  // GTEST_HAS_DEATH_TEST

// Returns the name of the environment variable corresponding to the
// given flag.  For example, FlagToEnvVar("foo") will return
// "GTEST_FOO" in the open-source version.
static String FlagToEnvVar(const char* flag) {
  const String full_flag = (Message() << GTEST_FLAG_PREFIX << flag).GetString();

  Message env_var;
  for (int i = 0; i != full_flag.GetLength(); i++) {
    env_var << static_cast<char>(toupper(full_flag.c_str()[i]));
  }

  return env_var.GetString();
}

// Reads and returns the Boolean environment variable corresponding to
// the given flag; if it's not set, returns default_value.
//
// The value is considered true iff it's not "0".
bool BoolFromGTestEnv(const char* flag, bool default_value) {
  const String env_var = FlagToEnvVar(flag);
  const char* const string_value = GetEnv(env_var.c_str());
  return string_value == NULL ?
      default_value : strcmp(string_value, "0") != 0;
}

// Parses 'str' for a 32-bit signed integer.  If successful, writes
// the result to *value and returns true; otherwise leaves *value
// unchanged and returns false.
bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
  // Parses the environment variable as a decimal integer.
  char* end = NULL;
  const long long_value = strtol(str, &end, 10);  // NOLINT

  // Has strtol() consumed all characters in the string?
  if (*end != '\0') {
    // No - an invalid character was encountered.
    Message msg;
    msg << "WARNING: " << src_text
        << " is expected to be a 32-bit integer, but actually"
        << " has value \"" << str << "\".\n";
    printf("%s", msg.GetString().c_str());
    fflush(stdout);
    return false;
  }

  // Is the parsed value in the range of an Int32?
  const Int32 result = static_cast<Int32>(long_value);
  if (long_value == LONG_MAX || long_value == LONG_MIN ||
      // The parsed value overflows as a long.  (strtol() returns
      // LONG_MAX or LONG_MIN when the input overflows.)
      result != long_value
      // The parsed value overflows as an Int32.
      ) {
    Message msg;
    msg << "WARNING: " << src_text
        << " is expected to be a 32-bit integer, but actually"
        << " has value " << str << ", which overflows.\n";
    printf("%s", msg.GetString().c_str());
    fflush(stdout);
    return false;
  }

  *value = result;
  return true;
}

// Reads and returns a 32-bit integer stored in the environment
// variable corresponding to the given flag; if it isn't set or
// doesn't represent a valid 32-bit integer, returns default_value.
Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
  const String env_var = FlagToEnvVar(flag);
  const char* const string_value = GetEnv(env_var.c_str());
  if (string_value == NULL) {
    // The environment variable is not set.
    return default_value;
  }

  Int32 result = default_value;
  if (!ParseInt32(Message() << "Environment variable " << env_var,
                  string_value, &result)) {
    printf("The default value %s is used.\n",
           (Message() << default_value).GetString().c_str());
    fflush(stdout);
    return default_value;
  }

  return result;
}

// Reads and returns the string environment variable corresponding to
// the given flag; if it's not set, returns default_value.
const char* StringFromGTestEnv(const char* flag, const char* default_value) {
  const String env_var = FlagToEnvVar(flag);
  const char* const value = GetEnv(env_var.c_str());
  return value == NULL ? default_value : value;
}

}  // namespace internal
}  // namespace testing
<|endoftext|>