<commit_before>/*************************************************
* Library Internal/Global State Source File      *
* (C) 1999-2006 The Botan Project                *
*************************************************/

#include <botan/libstate.h>
#include <botan/engine.h>
#include <botan/x509stat.h>
#include <botan/stl_util.h>
#include <botan/mutex.h>
#include <botan/timers.h>
#include <botan/charset.h>

namespace Botan {

/*************************************************
* Botan's global state                           *
*************************************************/
namespace {

Library_State* global_lib_state = 0;

}

Library_State& global_state()
   {
   if(!global_lib_state)
      throw Invalid_State("Library was not intialized correctly");
   return (*global_lib_state);
   }

void set_global_state(Library_State* new_state)
   {
   delete swap_global_state(new_state);
   }

Library_State* swap_global_state(Library_State* new_state)
   {
   Library_State* old_state = global_lib_state;
   global_lib_state = new_state;
   return old_state;
   }

namespace {

/*************************************************
* Named Mutex Holder                             *
*************************************************/
class Named_Mutex_Holder
   {
   public:
      Named_Mutex_Holder(const std::map<std::string, Mutex*>& mutexes,
                         const std::string& name)
         {
         mux = search_map<std::string, Mutex*>(mutexes, name, 0);

         if(!mux)
            throw Invalid_Argument("Named_Mutex_Holder: mutex not found");

         mux->lock();
         }

      ~Named_Mutex_Holder() { mux->unlock(); }
   private:
      Mutex* mux;
   };

}

/*************************************************
* Increment the Engine iterator                  *
*************************************************/
Engine* Library_State::Engine_Iterator::next()
   {
   return lib.get_engine_n(n++);
   }

/*************************************************
* Get a new mutex object                         *
*************************************************/
Mutex* Library_State::get_mutex() const
   {
   return mutex_factory->make();
   }

/*************************************************
* Get an allocator by its name                   *
*************************************************/
Allocator* Library_State::get_allocator(const std::string& type) const
   {
   Named_Mutex_Holder lock(locks, "allocator");

   if(type != "")
      return search_map<std::string, Allocator*>(alloc_factory, type, 0);

   if(!cached_default_allocator)
      {
      const std::string key_name = "conf/base/default_allocator";

      Named_Mutex_Holder lock(locks, "settings");
      std::string chosen = search_map(settings, key_name);

      if(chosen == "")
         chosen = "malloc";

      cached_default_allocator =
         search_map<std::string, Allocator*>(alloc_factory, chosen, 0);
      }

   return cached_default_allocator;
   }

/*************************************************
* Create a new name to object mapping            *
*************************************************/
void Library_State::add_allocator(const std::string& type,
                                  Allocator* allocator)
   {
   Named_Mutex_Holder lock(locks, "allocator");

   allocator->init();
   if(alloc_factory[type])
      delete alloc_factory[type];
   alloc_factory[type] = allocator;
   }

/*************************************************
* Read a high resolution clock                   *
*************************************************/
u64bit Library_State::system_clock() const
   {
   return timer->clock();
   }

/*************************************************
* Set the global PRNG                            *
*************************************************/
void Library_State::set_prng(RandomNumberGenerator* new_rng)
   {
   Named_Mutex_Holder lock(locks, "rng");

   delete rng;
   rng = new_rng;
   }

/*************************************************
* Get bytes from the global PRNG                 *
*************************************************/
void Library_State::randomize(byte out[], u32bit length)
   {
   Named_Mutex_Holder lock(locks, "rng");

   rng->randomize(out, length);
   }

/*************************************************
* Add a new entropy source to use                *
*************************************************/
void Library_State::add_entropy_source(EntropySource* src, bool last_in_list)
   {
   Named_Mutex_Holder lock(locks, "rng");

   if(last_in_list)
      entropy_sources.push_back(src);
   else
      entropy_sources.insert(entropy_sources.begin(), src);
   }

/*************************************************
* Add some bytes of entropy to the global PRNG   *
*************************************************/
void Library_State::add_entropy(const byte in[], u32bit length)
   {
   Named_Mutex_Holder lock(locks, "rng");

   rng->add_entropy(in, length);
   }

/*************************************************
* Add some bytes of entropy to the global PRNG   *
*************************************************/
void Library_State::add_entropy(EntropySource& source, bool slow_poll)
   {
   Named_Mutex_Holder lock(locks, "rng");

   rng->add_entropy(source, slow_poll);
   }

/*************************************************
* Gather entropy for our PRNG object             *
*************************************************/
u32bit Library_State::seed_prng(bool slow_poll, u32bit bits_to_get)
   {
   Named_Mutex_Holder lock(locks, "rng");

   u32bit bits = 0;
   for(u32bit j = 0; j != entropy_sources.size(); ++j)
      {
      bits += rng->add_entropy(*(entropy_sources[j]), slow_poll);

      if(bits_to_get && bits >= bits_to_get)
         return bits;
      }

   return bits;
   }

/*************************************************
* Set a named option                             *
*************************************************/
void Library_State::set_option(const std::string& section,
                               const std::string& name,
                               const std::string& value,
                               bool overwrite)
   {
   Named_Mutex_Holder lock(locks, "settings");

   std::map<std::string, std::string>::const_iterator i = settings.find(name);

   if(overwrite || i == settings.end() || i->second == "")
      {
      const std::string full_name = section + "/" + name;
      settings[full_name] = value;

      if(full_name == "base/default_allocator")
         cached_default_allocator = 0;
      }
   }

/*************************************************
* Get the value of the named option              *
*************************************************/
std::string Library_State::get_option(const std::string& section,
                                      const std::string& name) const
   {
   Named_Mutex_Holder lock(locks, "settings");

   return search_map<std::string, std::string>(settings,
                                               section + "/" + name, "");
   }

/*************************************************
* See if a particular option has been set        *
*************************************************/
bool Library_State::option_set(const std::string& section,
                               const std::string& name) const
   {
   Named_Mutex_Holder lock(locks, "settings");

   return search_map(settings, section + "/" + name, false, true);
   }

/*************************************************
* Get an engine out of the list                  *
*************************************************/
Engine* Library_State::get_engine_n(u32bit n) const
   {
   Named_Mutex_Holder lock(locks, "engine");

   if(n >= engines.size())
      return 0;
   return engines[n];
   }

/*************************************************
* Add a new engine to the list                   *
*************************************************/
void Library_State::add_engine(Engine* engine)
   {
   Named_Mutex_Holder lock(locks, "engine");
   engines.push_back(engine);
   }

/*************************************************
* Set the character set transcoder object        *
*************************************************/
void Library_State::set_transcoder(class Charset_Transcoder* transcoder)
   {
   if(this->transcoder)
      delete this->transcoder;
   this->transcoder = transcoder;
   }

/*************************************************
* Transcode a string from one charset to another *
*************************************************/
std::string Library_State::transcode(const std::string str,
                                     Character_Set to,
                                     Character_Set from) const
   {
   if(!transcoder)
      throw Invalid_State("Library_State::transcode: No transcoder set");

   return transcoder->transcode(str, to, from);
   }

/*************************************************
* Set the X509 global state class                *
*************************************************/
void Library_State::set_x509_state(X509_GlobalState* new_x509_state_obj)
   {
   delete x509_state_obj;
   x509_state_obj = new_x509_state_obj;
   }

/*************************************************
* Set the X509 global state class                *
*************************************************/
X509_GlobalState& Library_State::x509_state() const
   {
   if(!x509_state_obj)
      throw Invalid_State("Library_State::x509_state: No state set");

   return (*x509_state_obj);
   }

/*************************************************
* Library_State Constructor                      *
*************************************************/
Library_State::Library_State(Mutex_Factory* mutex_factory, Timer* timer)
   {
   if(!mutex_factory)
      mutex_factory = new Mutex_Factory;
   if(!timer)
      timer = new Timer;

   this->mutex_factory = mutex_factory;
   this->timer = timer;
   this->transcoder = 0;

   locks["settings"] = get_mutex();
   locks["allocator"] = get_mutex();
   locks["rng"] = get_mutex();
   locks["engine"] = get_mutex();
   rng = 0;
   cached_default_allocator = 0;
   x509_state_obj = new X509_GlobalState();

   set_default_policy();
   }

/*************************************************
* Library_State Destructor                       *
*************************************************/
Library_State::~Library_State()
   {
   cached_default_allocator = 0;
   delete rng;
   delete x509_state_obj;

   for(u32bit j = 0; j != entropy_sources.size(); ++j)
      delete entropy_sources[j];

   for(u32bit j = 0; j != engines.size(); ++j)
      delete engines[j];

   for(std::map<std::string, Allocator*>::iterator j = alloc_factory.begin();
       j != alloc_factory.end(); ++j)
      {
      j->second->destroy();
      delete j->second;
      }

   delete transcoder;
   delete mutex_factory;
   delete timer;

   for(std::map<std::string, Mutex*>::iterator j = locks.begin();
       j != locks.end(); ++j)
      delete j->second;
   }

}
<commit_msg>Have system_clock return 0, rather than crash, if no timer is set<commit_after>/*************************************************
* Library Internal/Global State Source File      *
* (C) 1999-2006 The Botan Project                *
*************************************************/

#include <botan/libstate.h>
#include <botan/engine.h>
#include <botan/x509stat.h>
#include <botan/stl_util.h>
#include <botan/mutex.h>
#include <botan/timers.h>
#include <botan/charset.h>

namespace Botan {

/*************************************************
* Botan's global state                           *
*************************************************/
namespace {

Library_State* global_lib_state = 0;

}

Library_State& global_state()
   {
   if(!global_lib_state)
      throw Invalid_State("Library was not intialized correctly");
   return (*global_lib_state);
   }

void set_global_state(Library_State* new_state)
   {
   delete swap_global_state(new_state);
   }

Library_State* swap_global_state(Library_State* new_state)
   {
   Library_State* old_state = global_lib_state;
   global_lib_state = new_state;
   return old_state;
   }

namespace {

/*************************************************
* Named Mutex Holder                             *
*************************************************/
class Named_Mutex_Holder
   {
   public:
      Named_Mutex_Holder(const std::map<std::string, Mutex*>& mutexes,
                         const std::string& name)
         {
         mux = search_map<std::string, Mutex*>(mutexes, name, 0);

         if(!mux)
            throw Invalid_Argument("Named_Mutex_Holder: mutex not found");

         mux->lock();
         }

      ~Named_Mutex_Holder() { mux->unlock(); }
   private:
      Mutex* mux;
   };

}

/*************************************************
* Increment the Engine iterator                  *
*************************************************/
Engine* Library_State::Engine_Iterator::next()
   {
   return lib.get_engine_n(n++);
   }

/*************************************************
* Get a new mutex object                         *
*************************************************/
Mutex* Library_State::get_mutex() const
   {
   return mutex_factory->make();
   }

/*************************************************
* Get an allocator by its name                   *
*************************************************/
Allocator* Library_State::get_allocator(const std::string& type) const
   {
   Named_Mutex_Holder lock(locks, "allocator");

   if(type != "")
      return search_map<std::string, Allocator*>(alloc_factory, type, 0);

   if(!cached_default_allocator)
      {
      const std::string key_name = "conf/base/default_allocator";

      Named_Mutex_Holder lock(locks, "settings");
      std::string chosen = search_map(settings, key_name);

      if(chosen == "")
         chosen = "malloc";

      cached_default_allocator =
         search_map<std::string, Allocator*>(alloc_factory, chosen, 0);
      }

   return cached_default_allocator;
   }

/*************************************************
* Create a new name to object mapping            *
*************************************************/
void Library_State::add_allocator(const std::string& type,
                                  Allocator* allocator)
   {
   Named_Mutex_Holder lock(locks, "allocator");

   allocator->init();
   if(alloc_factory[type])
      delete alloc_factory[type];
   alloc_factory[type] = allocator;
   }

/*************************************************
* Read a high resolution clock                   *
*************************************************/
u64bit Library_State::system_clock() const
   {
   return (timer) ? timer->clock() : 0;
   }

/*************************************************
* Set the global PRNG                            *
*************************************************/
void Library_State::set_prng(RandomNumberGenerator* new_rng)
   {
   Named_Mutex_Holder lock(locks, "rng");

   delete rng;
   rng = new_rng;
   }

/*************************************************
* Get bytes from the global PRNG                 *
*************************************************/
void Library_State::randomize(byte out[], u32bit length)
   {
   Named_Mutex_Holder lock(locks, "rng");

   rng->randomize(out, length);
   }

/*************************************************
* Add a new entropy source to use                *
*************************************************/
void Library_State::add_entropy_source(EntropySource* src, bool last_in_list)
   {
   Named_Mutex_Holder lock(locks, "rng");

   if(last_in_list)
      entropy_sources.push_back(src);
   else
      entropy_sources.insert(entropy_sources.begin(), src);
   }

/*************************************************
* Add some bytes of entropy to the global PRNG   *
*************************************************/
void Library_State::add_entropy(const byte in[], u32bit length)
   {
   Named_Mutex_Holder lock(locks, "rng");

   rng->add_entropy(in, length);
   }

/*************************************************
* Add some bytes of entropy to the global PRNG   *
*************************************************/
void Library_State::add_entropy(EntropySource& source, bool slow_poll)
   {
   Named_Mutex_Holder lock(locks, "rng");

   rng->add_entropy(source, slow_poll);
   }

/*************************************************
* Gather entropy for our PRNG object             *
*************************************************/
u32bit Library_State::seed_prng(bool slow_poll, u32bit bits_to_get)
   {
   Named_Mutex_Holder lock(locks, "rng");

   u32bit bits = 0;
   for(u32bit j = 0; j != entropy_sources.size(); ++j)
      {
      bits += rng->add_entropy(*(entropy_sources[j]), slow_poll);

      if(bits_to_get && bits >= bits_to_get)
         return bits;
      }

   return bits;
   }

/*************************************************
* Set a named option                             *
*************************************************/
void Library_State::set_option(const std::string& section,
                               const std::string& name,
                               const std::string& value,
                               bool overwrite)
   {
   Named_Mutex_Holder lock(locks, "settings");

   std::map<std::string, std::string>::const_iterator i = settings.find(name);

   if(overwrite || i == settings.end() || i->second == "")
      {
      const std::string full_name = section + "/" + name;
      settings[full_name] = value;

      if(full_name == "base/default_allocator")
         cached_default_allocator = 0;
      }
   }

/*************************************************
* Get the value of the named option              *
*************************************************/
std::string Library_State::get_option(const std::string& section,
                                      const std::string& name) const
   {
   Named_Mutex_Holder lock(locks, "settings");

   return search_map<std::string, std::string>(settings,
                                               section + "/" + name, "");
   }

/*************************************************
* See if a particular option has been set        *
*************************************************/
bool Library_State::option_set(const std::string& section,
                               const std::string& name) const
   {
   Named_Mutex_Holder lock(locks, "settings");

   return search_map(settings, section + "/" + name, false, true);
   }

/*************************************************
* Get an engine out of the list                  *
*************************************************/
Engine* Library_State::get_engine_n(u32bit n) const
   {
   Named_Mutex_Holder lock(locks, "engine");

   if(n >= engines.size())
      return 0;
   return engines[n];
   }

/*************************************************
* Add a new engine to the list                   *
*************************************************/
void Library_State::add_engine(Engine* engine)
   {
   Named_Mutex_Holder lock(locks, "engine");
   engines.push_back(engine);
   }

/*************************************************
* Set the character set transcoder object        *
*************************************************/
void Library_State::set_transcoder(class Charset_Transcoder* transcoder)
   {
   if(this->transcoder)
      delete this->transcoder;
   this->transcoder = transcoder;
   }

/*************************************************
* Transcode a string from one charset to another *
*************************************************/
std::string Library_State::transcode(const std::string str,
                                     Character_Set to,
                                     Character_Set from) const
   {
   if(!transcoder)
      throw Invalid_State("Library_State::transcode: No transcoder set");

   return transcoder->transcode(str, to, from);
   }

/*************************************************
* Set the X509 global state class                *
*************************************************/
void Library_State::set_x509_state(X509_GlobalState* new_x509_state_obj)
   {
   delete x509_state_obj;
   x509_state_obj = new_x509_state_obj;
   }

/*************************************************
* Set the X509 global state class                *
*************************************************/
X509_GlobalState& Library_State::x509_state() const
   {
   if(!x509_state_obj)
      x509_state_obj = new X509_GlobalState();

   return (*x509_state_obj);
   }

/*************************************************
* Library_State Constructor                      *
*************************************************/
Library_State::Library_State(Mutex_Factory* mutex_factory, Timer* timer)
   {
   if(!mutex_factory)
      mutex_factory = new Mutex_Factory;
   if(!timer)
      timer = new Timer;

   this->mutex_factory = mutex_factory;
   this->timer = timer;
   this->transcoder = 0;

   locks["settings"] = get_mutex();
   locks["allocator"] = get_mutex();
   locks["rng"] = get_mutex();
   locks["engine"] = get_mutex();
   rng = 0;
   cached_default_allocator = 0;
   x509_state_obj = 0;

   set_default_policy();
   }

/*************************************************
* Library_State Destructor                       *
*************************************************/
Library_State::~Library_State()
   {
   delete x509_state_obj;
   delete transcoder;
   for(u32bit j = 0; j != entropy_sources.size(); ++j)
      delete entropy_sources[j];

   delete rng;

   for(u32bit j = 0; j != engines.size(); ++j)
      delete engines[j];

   cached_default_allocator = 0;
   for(std::map<std::string, Allocator*>::iterator j = alloc_factory.begin();
       j != alloc_factory.end(); ++j)
      {
      j->second->destroy();
      delete j->second;
      }

   delete mutex_factory;
   delete timer;

   for(std::map<std::string, Mutex*>::iterator j = locks.begin();
       j != locks.end(); ++j)
      delete j->second;
   }

}
<|endoftext|>


<commit_before>//!@todo: performance: Review string formatting. Use attached stream.
//!@todo: api: Make elasticsearch frontend. Use swarm + asio and only index request with simple response checking.
//!@todo: files_t: Make file naming by pattern.
//!@todo: api: Ability to set global attribute mapper (?)
//!@todo: api: Global thread-safe guarantee. Do not lock if underlying class is thread-safe itself.

//!@todo: api: Make fallback logger. Make it configurable.
//!@todo: aux: Make internal exception class with attribute keeping, e.g. line, file or path.
//!@todo: msgpack_t: Attribute mappings.
//!@todo: socket_t: Make asynchronous TCP backend.

//!@todo: benchmark: File logging comparing with boost::log.
//!@todo: benchmark: Socket logging with json.
<commit_msg>One task less.<commit_after>//!@todo: performance: Review string formatting. Use attached stream.
//!@todo: api: Make elasticsearch frontend. Use swarm + asio and only index request with simple response checking.
//!@todo: api: Ability to set global attribute mapper (?)
//!@todo: api: Global thread-safe guarantee. Do not lock if underlying class is thread-safe itself.

//!@todo: api: Make fallback logger. Make it configurable.
//!@todo: aux: Make internal exception class with attribute keeping, e.g. line, file or path.
//!@todo: msgpack_t: Attribute mappings.
//!@todo: socket_t: Make asynchronous TCP backend.

//!@todo: benchmark: File logging comparing with boost::log.
//!@todo: benchmark: Socket logging with json.
<|endoftext|>


<commit_before>#ifndef BUILTIN_UTIL_I_HH
#define BUILTIN_UTIL_I_HH

#ifndef BUILTIN_UTIL_HH
#error "Please include via parent file"
#endif

#include <stack>
#include <vector>
#include <array>
#include <cstdio>

#include "util.hh"
#include "lisp_ptr.hh"
#include "cons.hh"
#include "vm.hh"

template<bool dot_list, typename StackT>
Lisp_ptr stack_to_list(StackT& st){
  Lisp_ptr argc = st.back();
  st.pop_back();

  if(argc.get<int>() == 0){
    return Cons::NIL;
  }

  Cons* c = new Cons;
  Cons* prev_c = c;
  Lisp_ptr ret = c;

  for(int i = 0; i < argc.get<int>(); ++i){
    c->rplaca(st.back());
    st.pop_back();

    Cons* newc = new Cons;
    c->rplacd(newc);
    prev_c = c;
    c = newc;
  }

  if(dot_list){
    if(c != prev_c){
      prev_c->rplacd(c->car());
    }else{
      ret = c->car();
    }
    delete c;
  }else{
    c->rplacd(Cons::NIL);
  }

  return ret;
}

template<typename StackT, typename VectorT>
void stack_to_vector(StackT& st, VectorT& v){
  Lisp_ptr argc = st.back();
  st.pop_back();

  for(int i = 0; i < argc.get<int>(); ++i){
    v.push_back(st.back());
    st.pop_back();
  }
}

template<typename StackT>
int list_to_stack(const char* opname, Lisp_ptr l, StackT& st){
  std::stack<Lisp_ptr, std::vector<Lisp_ptr>> tmp;

  do_list(l,
          [&](Cons* c) -> bool {
            tmp.push(c->car());
            return true;
          },
          [&](Lisp_ptr last_cdr){
            if(!nullp(last_cdr)){
              fprintf(zs::err, "eval warning: dot list has read as proper list. (in %s)\n",
                      opname);
              tmp.push(last_cdr);
            }
          });

  int ret = 0;

  while(!tmp.empty()){
    st.push_back(tmp.top());
    tmp.pop();
    ++ret;
  }

  return ret;
}

template<int size>
std::array<Lisp_ptr, size> pick_args(){
  Lisp_ptr argc = vm.stack.back();
  vm.stack.pop_back();

  auto ret = std::array<Lisp_ptr, size>();
  if(argc.get<int>() != size){
    ret.fill({});
    return ret;
  }

  for(int i = 0; i < size; ++i){
    ret[i] = vm.stack.back();
    vm.stack.pop_back();
  }

  return ret;
}

#endif //BUILTIN_UTIL_I_HH
<commit_msg>fixed arg passing<commit_after>#ifndef BUILTIN_UTIL_I_HH
#define BUILTIN_UTIL_I_HH

#ifndef BUILTIN_UTIL_HH
#error "Please include via parent file"
#endif

#include <stack>
#include <vector>
#include <array>
#include <cstdio>
#include <iterator>

#include "util.hh"
#include "lisp_ptr.hh"
#include "cons.hh"
#include "vm.hh"

template<bool dot_list, typename StackT>
Lisp_ptr stack_to_list(StackT& st){
  Lisp_ptr argc = st.back();
  st.pop_back();

  if(argc.get<int>() == 0){
    return Cons::NIL;
  }

  Cons* c = new Cons;
  Cons* prev_c = c;
  Lisp_ptr ret = c;

  for(int i = 0; i < argc.get<int>(); ++i){
    c->rplaca(st.back());
    st.pop_back();

    Cons* newc = new Cons;
    c->rplacd(newc);
    prev_c = c;
    c = newc;
  }

  if(dot_list){
    if(c != prev_c){
      prev_c->rplacd(c->car());
    }else{
      ret = c->car();
    }
    delete c;
  }else{
    c->rplacd(Cons::NIL);
  }

  return ret;
}

template<typename StackT, typename VectorT>
void stack_to_vector(StackT& st, VectorT& v){
  Lisp_ptr argc = st.back();
  st.pop_back();

  auto arg_start = st.end() - argc.get<int>();
  auto arg_end = st.end();

  for(auto i = arg_start; i != arg_end; ++i){
    v.push_back(*i);
  }

  st.erase(arg_start, arg_end);
}

template<typename StackT>
int list_to_stack(const char* opname, Lisp_ptr l, StackT& st){
  std::stack<Lisp_ptr> tmp;

  do_list(l,
          [&](Cons* c) -> bool {
            tmp.push(c->car());
            return true;
          },
          [&](Lisp_ptr last_cdr){
            if(!nullp(last_cdr)){
              fprintf(zs::err, "eval warning: dot list has read as proper list. (in %s)\n",
                      opname);
              tmp.push(last_cdr);
            }
          });

  int ret = 0;

  while(!tmp.empty()){
    st.push_back(tmp.top());
    tmp.pop();
    ++ret;
  }

  return ret;
}

template<int size>
std::array<Lisp_ptr, size> pick_args(){
  Lisp_ptr argc = vm.stack.back();
  vm.stack.pop_back();

  auto ret = std::array<Lisp_ptr, size>();
  if(argc.get<int>() != size){
    ret.fill({});
    return ret;
  }

  for(int i = 0; i < size; ++i){
    ret[i] = vm.stack[vm.stack.size() - size + i];
  }
  vm.stack.erase(vm.stack.end() - size, vm.stack.end());

  return ret;
}

#endif //BUILTIN_UTIL_I_HH
<|endoftext|>


<commit_before>#include "client_manager.hh"

#include "buffer_manager.hh"
#include "command_manager.hh"
#include "containers.hh"
#include "event_manager.hh"
#include "face_registry.hh"
#include "file.hh"
#include "user_interface.hh"
#include "window.hh"

namespace Kakoune
{

ClientManager::ClientManager() = default;
ClientManager::~ClientManager() = default;

String ClientManager::generate_name() const
{
    for (int i = 0; true; ++i)
    {
        String name = "unnamed" + to_string(i);
        if (validate_client_name(name))
            return name;
    }
}

Client* ClientManager::create_client(std::unique_ptr<UserInterface>&& ui,
                                     EnvVarMap env_vars,
                                     StringView init_commands)
{
    Buffer& buffer = **BufferManager::instance().begin();
    WindowAndSelections ws = get_free_window(buffer);
    Client* client = new Client{std::move(ui), std::move(ws.window),
                                std::move(ws.selections), std::move(env_vars),
                                generate_name()};
    m_clients.emplace_back(client);
    try
    {
        CommandManager::instance().execute(init_commands, client->context());
    }
    catch (Kakoune::runtime_error& error)
    {
        client->context().print_status({ error.what(), get_face("Error") });
        client->context().hooks().run_hook("RuntimeError", error.what(),
                                           client->context());
    }
    catch (Kakoune::client_removed&)
    {
        m_clients.pop_back();
        return nullptr;
    }

    client->ui().set_input_callback([client](EventMode mode) {
        client->handle_available_input(mode);
    });

    return client;
}

void ClientManager::handle_pending_inputs() const
{
    for (auto& client : m_clients)
        client->handle_available_input(EventMode::Pending);
}

void ClientManager::remove_client(Client& client)
{
    for (auto it = m_clients.begin(); it != m_clients.end(); ++it)
    {
        if (it->get() == &client)
        {
             m_clients.erase(it);
             return;
        }
    }
    kak_assert(false);
}

WindowAndSelections ClientManager::get_free_window(Buffer& buffer)
{
    for (auto it = m_free_windows.rbegin(), end = m_free_windows.rend();
         it != end; ++it)
    {
        auto& w = it->window;
        if (&w->buffer() == &buffer)
        {
            w->forget_timestamp();
            WindowAndSelections res = std::move(*it);
            m_free_windows.erase(it.base()-1);
            res.selections.update();
            return res;
        }
    }
    return WindowAndSelections{ std::unique_ptr<Window>{new Window{buffer}},
                                SelectionList{ buffer, Selection{} } };
}

void ClientManager::add_free_window(std::unique_ptr<Window>&& window, SelectionList selections)
{
    Buffer& buffer = window->buffer();
    m_free_windows.push_back({ std::move(window), SelectionList{ std::move(selections) }, buffer.timestamp() });
}

void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer)
{
    for (auto& client : m_clients)
    {
        client->context().forget_jumps_to_buffer(buffer);

        if (&client->context().buffer() != &buffer)
            continue;

        if (client->context().is_editing())
            throw runtime_error("client '" + client->context().name() + "' is inserting in '" +
                                buffer.display_name() + "'");

        // change client context to edit the first buffer which is not the
        // specified one. As BufferManager stores buffer according to last
        // access, this selects a sensible buffer to display.
        for (auto& buf : BufferManager::instance())
        {
            if (buf != &buffer)
            {
               client->context().change_buffer(*buf);
               break;
            }
        }
    }
    auto end = std::remove_if(m_free_windows.begin(), m_free_windows.end(),
                              [&buffer](const WindowAndSelections& ws)
                              { return &ws.window->buffer() == &buffer; });
    m_free_windows.erase(end, m_free_windows.end());
}

bool ClientManager::validate_client_name(StringView name) const
{
    auto it = find_if(m_clients, [&](const std::unique_ptr<Client>& client)
                                 { return client->context().name() == name; });
    return it == m_clients.end();
}

Client* ClientManager::get_client_ifp(StringView name)
{
    for (auto& client : m_clients)
    {
        if (client->context().name() == name)
            return client.get();
    }
    return nullptr;
}

Client& ClientManager::get_client(StringView name)
{
    Client* client = get_client_ifp(name);
    if (not client)
        throw runtime_error("no client named: " + name);
    return *client;
}

void ClientManager::redraw_clients() const
{
    for (auto& client : m_clients)
        client->redraw_ifn();
}

void ClientManager::clear_mode_trashes() const
{
    for (auto& client : m_clients)
        client->input_handler().clear_mode_trash();
}

CandidateList ClientManager::complete_client_name(StringView prefix,
                                                  ByteCount cursor_pos) const
{
    auto c = transformed(m_clients, [](const std::unique_ptr<Client>& c){ return c->context().name(); });
    return complete(prefix, cursor_pos, c, prefix_match, subsequence_match);
}

}
<commit_msg>Another stule tweak<commit_after>#include "client_manager.hh"

#include "buffer_manager.hh"
#include "command_manager.hh"
#include "containers.hh"
#include "event_manager.hh"
#include "face_registry.hh"
#include "file.hh"
#include "user_interface.hh"
#include "window.hh"

namespace Kakoune
{

ClientManager::ClientManager() = default;
ClientManager::~ClientManager() = default;

String ClientManager::generate_name() const
{
    for (int i = 0; true; ++i)
    {
        String name = "unnamed" + to_string(i);
        if (validate_client_name(name))
            return name;
    }
}

Client* ClientManager::create_client(std::unique_ptr<UserInterface>&& ui,
                                     EnvVarMap env_vars,
                                     StringView init_commands)
{
    Buffer& buffer = **BufferManager::instance().begin();
    WindowAndSelections ws = get_free_window(buffer);
    Client* client = new Client{std::move(ui), std::move(ws.window),
                                std::move(ws.selections), std::move(env_vars),
                                generate_name()};
    m_clients.emplace_back(client);
    try
    {
        CommandManager::instance().execute(init_commands, client->context());
    }
    catch (Kakoune::runtime_error& error)
    {
        client->context().print_status({ error.what(), get_face("Error") });
        client->context().hooks().run_hook("RuntimeError", error.what(),
                                           client->context());
    }
    catch (Kakoune::client_removed&)
    {
        m_clients.pop_back();
        return nullptr;
    }

    client->ui().set_input_callback([client](EventMode mode) {
        client->handle_available_input(mode);
    });

    return client;
}

void ClientManager::handle_pending_inputs() const
{
    for (auto& client : m_clients)
        client->handle_available_input(EventMode::Pending);
}

void ClientManager::remove_client(Client& client)
{
    for (auto it = m_clients.begin(); it != m_clients.end(); ++it)
    {
        if (it->get() == &client)
        {
             m_clients.erase(it);
             return;
        }
    }
    kak_assert(false);
}

WindowAndSelections ClientManager::get_free_window(Buffer& buffer)
{
    for (auto it = m_free_windows.rbegin(), end = m_free_windows.rend();
         it != end; ++it)
    {
        auto& w = it->window;
        if (&w->buffer() == &buffer)
        {
            w->forget_timestamp();
            WindowAndSelections res = std::move(*it);
            m_free_windows.erase(it.base()-1);
            res.selections.update();
            return res;
        }
    }
    return WindowAndSelections{ std::unique_ptr<Window>{new Window{buffer}},
                                SelectionList{ buffer, Selection{} } };
}

void ClientManager::add_free_window(std::unique_ptr<Window>&& window, SelectionList selections)
{
    Buffer& buffer = window->buffer();
    m_free_windows.push_back({ std::move(window), SelectionList{ std::move(selections) }, buffer.timestamp() });
}

void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer)
{
    for (auto& client : m_clients)
    {
        client->context().forget_jumps_to_buffer(buffer);

        if (&client->context().buffer() != &buffer)
            continue;

        if (client->context().is_editing())
            throw runtime_error("client '" + client->context().name() + "' is inserting in '" +
                                buffer.display_name() + "'");

        // change client context to edit the first buffer which is not the
        // specified one. As BufferManager stores buffer according to last
        // access, this selects a sensible buffer to display.
        for (auto& buf : BufferManager::instance())
        {
            if (buf != &buffer)
            {
               client->context().change_buffer(*buf);
               break;
            }
        }
    }
    auto end = std::remove_if(m_free_windows.begin(), m_free_windows.end(),
                              [&buffer](const WindowAndSelections& ws)
                              { return &ws.window->buffer() == &buffer; });
    m_free_windows.erase(end, m_free_windows.end());
}

bool ClientManager::validate_client_name(StringView name) const
{
    auto it = find_if(m_clients, [&](const std::unique_ptr<Client>& client)
                                 { return client->context().name() == name; });
    return it == m_clients.end();
}

Client* ClientManager::get_client_ifp(StringView name)
{
    for (auto& client : m_clients)
    {
        if (client->context().name() == name)
            return client.get();
    }
    return nullptr;
}

Client& ClientManager::get_client(StringView name)
{
    if (Client* client = get_client_ifp(name))
        return *client;
    throw runtime_error("no client named: " + name);
}

void ClientManager::redraw_clients() const
{
    for (auto& client : m_clients)
        client->redraw_ifn();
}

void ClientManager::clear_mode_trashes() const
{
    for (auto& client : m_clients)
        client->input_handler().clear_mode_trash();
}

CandidateList ClientManager::complete_client_name(StringView prefix,
                                                  ByteCount cursor_pos) const
{
    auto c = transformed(m_clients, [](const std::unique_ptr<Client>& c){ return c->context().name(); });
    return complete(prefix, cursor_pos, c, prefix_match, subsequence_match);
}

}
<|endoftext|>


<commit_before>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/elementaryFluxModes/CStepMatrix.cpp,v $
//   $Revision: 1.6 $
//   $Name:  $
//   $Author: shoops $
//   $Date: 2009/09/24 18:13:13 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include "copasi.h"

#include "CStepMatrix.h"
#include "CStepMatrixColumn.h"

#include "utilities/CMatrix.h"

CStepMatrix::CStepMatrix():
    std::list< CStepMatrixColumn * >(),
    mRows(0),
    mPivot(0),
    mFirstUnconvertedRow(0)
{}

CStepMatrix::CStepMatrix(CMatrix< C_INT32 > & nullspaceMatrix):
    std::list< CStepMatrixColumn * >(),
    mRows(nullspaceMatrix.numRows()),
    mPivot(nullspaceMatrix.numRows()),
    mFirstUnconvertedRow(0)
{
  size_t Cols = nullspaceMatrix.numCols();

  CVector< CStepMatrixColumn * > Columns(Cols);
  CStepMatrixColumn ** pColumn = Columns.array();
  CStepMatrixColumn ** pColumnEnd = pColumn + Cols;

  for (; pColumn != pColumnEnd; ++pColumn)
    {
      *pColumn = new CStepMatrixColumn(mRows);
      push_back(*pColumn);
    }

  size_t i;
  size_t j;
  const C_INT32 * pValue = nullspaceMatrix.array();
  size_t * pPivot = mPivot.array();

  std::vector< size_t > NegativeRows;
  bool hasNegative;
  bool hasPositive;

  for (i = 0; i < mRows; ++i, ++pPivot)
    {
      *pPivot = i;

      hasNegative = false;
      hasPositive = false;

      for (j = 0; j < Cols; ++j, ++pValue)
        {
          if (*pValue > 0.0)
            {
              hasPositive = true;
            }
          else if (*pValue < 0.0)
            {
              hasNegative = true;
            }
        }

      if ((hasNegative && !hasPositive) ||
          (!hasNegative && hasPositive))
        {
          convertRow(i, nullspaceMatrix);
        }
    }

  // We need to add the information of the unconverted rows of nullspace matrix
  // to the columns

  pValue = & nullspaceMatrix(mFirstUnconvertedRow, 0);

  for (i = mFirstUnconvertedRow; i < mRows; ++i)
    {
      pColumn = Columns.array();

      for (j = 0; j < Cols; ++j, ++pValue,  ++pColumn)
        {
          (*pColumn)->push_front(*pValue);
        }
    }
}

CStepMatrix::~CStepMatrix()
{
  iterator it = begin();
  const_iterator itEnd = end();

  for (; it != itEnd; ++it)
    {
      delete *it;
    }
}

void CStepMatrix::convertRow()
{
  CZeroSet::CIndex Index(mFirstUnconvertedRow);

  iterator it = begin();
  const_iterator itEnd = end();

  for (; it != itEnd; ++it)
    {
      if ((*it)->getMultiplier() != 0)
        {
          (*it)->unsetBit(Index);
        }

      (*it)->truncate();
    }

  mFirstUnconvertedRow++;
}

size_t CStepMatrix::getFirstUnconvertedRow() const
{
  return mFirstUnconvertedRow;
}

size_t CStepMatrix::getNumUnconvertedRows() const
{
  return mRows - mFirstUnconvertedRow;
}

CStepMatrixColumn * CStepMatrix::addColumn(const CZeroSet & set,
    CStepMatrixColumn const * pPositive,
    CStepMatrixColumn const * pNegative)
{
  CStepMatrixColumn * pColumn = new CStepMatrixColumn(set, pPositive, pNegative);
  push_back(pColumn);

  return pColumn;
}

bool CStepMatrix::splitColumns(std::list< CStepMatrixColumn * > & PositiveColumns,
                               std::list< CStepMatrixColumn * > & NegativeColumns,
                               std::list< CStepMatrixColumn * > & NullColumns)
{
  PositiveColumns.clear();
  NegativeColumns.clear();

  iterator it = begin();
  const_iterator itEnd = end();

  while (it != itEnd)
    {
      const C_FLOAT64 & Value = (*it)->getMultiplier();

      if (Value > 0.0)
        {
          PositiveColumns.push_back(*it);
          ++it;
        }
      else if (Value < 0.0)
        {
          NegativeColumns.push_back(*it);

          // Since all negative columns have to be removed this is the perfect place to do so.
          it = erase(it);
        }
      else
        {
          NullColumns.push_back(*it);
          ++it;
        }
    }

  if (NegativeColumns.empty())
    {
      convertRow();

      return false;
    }
  else if (PositiveColumns.empty())
    {
      // We can not remove the negative columns therefore we add them again.
      std::list< CStepMatrixColumn * >::const_iterator itNeg = NegativeColumns.begin();
      std::list< CStepMatrixColumn * >::const_iterator endNeg = NegativeColumns.end();

      for (; itNeg != endNeg; ++itNeg)
        {
          push_back(*itNeg);
        }

      convertRow();

      return false;
    }

  return true;
}

void CStepMatrix::removeInvalidColumns(const std::vector< CStepMatrixColumn * > & invalidColumns)
{
  std::vector< CStepMatrixColumn * >::const_iterator it = invalidColumns.begin();
  std::vector< CStepMatrixColumn * >::const_iterator end = invalidColumns.end();

  for (; it != end; ++it)
    {
      remove(*it);
      delete *it;
    }
}

void CStepMatrix::getUnsetBitIndexes(const CStepMatrixColumn * pColumn,
                                     CVector< size_t > & indexes) const
{
  const CZeroSet & ZeroSet = pColumn->getZeroSet();

  indexes.resize(ZeroSet.getNumberOfUnsetBits());
  size_t * pIndex = indexes.array();
  size_t * pIndexEnd = pIndex + indexes.size();

  CZeroSet::CIndex Bit = 0;
  size_t Index = 0;

  for (; pIndex != pIndexEnd; ++Bit, ++Index)
    {
      if (!ZeroSet.isSet(Bit))
        {
          // Apply pivot.
          *pIndex = mPivot[Index];
          pIndex++;
        }
    }

  return;
}

void CStepMatrix::convertRow(const size_t & index,
                             CMatrix< C_INT32 > & nullspaceMatrix)
{
  CZeroSet::CIndex Index(mFirstUnconvertedRow);

  iterator it = begin();
  const_iterator itEnd = end();
  C_INT32 * pValue = & nullspaceMatrix(index, 0);

  if (mFirstUnconvertedRow != index)
    {
      C_INT32 * pFirstUnconvertedValue = & nullspaceMatrix(mFirstUnconvertedRow, 0);

      for (; it != itEnd; ++it, ++pValue, ++pFirstUnconvertedValue)
        {
          if (*pValue != 0)
            {
              (*it)->unsetBit(Index);
            }

          *pValue = *pFirstUnconvertedValue;
        }

      // We need to remember the reordering.
      size_t tmp = mPivot[index];
      mPivot[index] = mPivot[mFirstUnconvertedRow];
      mPivot[mFirstUnconvertedRow] = tmp;
    }
  else
    {
      for (; it != itEnd; ++it, ++pValue)
        {
          if (*pValue != 0)
            {
              (*it)->unsetBit(Index);
            }
        }
    }

  mFirstUnconvertedRow++;
}

std::ostream & operator << (std::ostream & os, const CStepMatrix & m)
{
  os << m.mPivot << std::endl;

  size_t i;
  CZeroSet::CIndex Bit;

  CStepMatrix::const_iterator it;
  CStepMatrix::const_iterator end = m.end();

  for (i = 0, Bit = 0; i < m.mFirstUnconvertedRow; ++i, ++Bit)
    {
      for (it = m.begin(); it != end; ++it)
        {
          if ((*it)->getZeroSet().isSet(Bit))
            {
              os << "*\t";
            }
          else
            {
              os << ".\t";
            }
        }

      os << std::endl;
    }

  for (i = m.mRows - m.mFirstUnconvertedRow; i > 0;)
    {
      --i;

      for (it = m.begin(); it != end; ++it)
        {
          os << (*it)->getReaction()[i] << '\t';
        }

      os << std::endl;
    }

  return os;
}
<commit_msg>Fixed crash when the model does not contain any reactions.<commit_after>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/elementaryFluxModes/CStepMatrix.cpp,v $
//   $Revision: 1.7 $
//   $Name:  $
//   $Author: shoops $
//   $Date: 2009/09/29 16:33:48 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include "copasi.h"

#include "CStepMatrix.h"
#include "CStepMatrixColumn.h"

#include "utilities/CMatrix.h"

CStepMatrix::CStepMatrix():
    std::list< CStepMatrixColumn * >(),
    mRows(0),
    mPivot(0),
    mFirstUnconvertedRow(0)
{}

CStepMatrix::CStepMatrix(CMatrix< C_INT32 > & nullspaceMatrix):
    std::list< CStepMatrixColumn * >(),
    mRows(nullspaceMatrix.numRows()),
    mPivot(nullspaceMatrix.numRows()),
    mFirstUnconvertedRow(0)
{
  size_t Cols = nullspaceMatrix.numCols();

  CVector< CStepMatrixColumn * > Columns(Cols);
  CStepMatrixColumn ** pColumn = Columns.array();
  CStepMatrixColumn ** pColumnEnd = pColumn + Cols;

  for (; pColumn != pColumnEnd; ++pColumn)
    {
      *pColumn = new CStepMatrixColumn(mRows);
      push_back(*pColumn);
    }

  size_t i;
  size_t j;
  const C_INT32 * pValue = nullspaceMatrix.array();
  size_t * pPivot = mPivot.array();

  std::vector< size_t > NegativeRows;
  bool hasNegative;
  bool hasPositive;

  for (i = 0; i < mRows; ++i, ++pPivot)
    {
      *pPivot = i;

      hasNegative = false;
      hasPositive = false;

      for (j = 0; j < Cols; ++j, ++pValue)
        {
          if (*pValue > 0.0)
            {
              hasPositive = true;
            }
          else if (*pValue < 0.0)
            {
              hasNegative = true;
            }
        }

      if ((hasNegative && !hasPositive) ||
          (!hasNegative && hasPositive))
        {
          convertRow(i, nullspaceMatrix);
        }
    }

  // We need to add the information of the unconverted rows of nullspace matrix
  // to the columns

  if (nullspaceMatrix.size() != 0)
    {
      pValue = & nullspaceMatrix(mFirstUnconvertedRow, 0);
    }
  else
    {
      pValue = NULL;
    }

  for (i = mFirstUnconvertedRow; i < mRows; ++i)
    {
      pColumn = Columns.array();

      for (j = 0; j < Cols; ++j, ++pValue,  ++pColumn)
        {
          (*pColumn)->push_front(*pValue);
        }
    }
}

CStepMatrix::~CStepMatrix()
{
  iterator it = begin();
  const_iterator itEnd = end();

  for (; it != itEnd; ++it)
    {
      delete *it;
    }
}

void CStepMatrix::convertRow()
{
  CZeroSet::CIndex Index(mFirstUnconvertedRow);

  iterator it = begin();
  const_iterator itEnd = end();

  for (; it != itEnd; ++it)
    {
      if ((*it)->getMultiplier() != 0)
        {
          (*it)->unsetBit(Index);
        }

      (*it)->truncate();
    }

  mFirstUnconvertedRow++;
}

size_t CStepMatrix::getFirstUnconvertedRow() const
{
  return mFirstUnconvertedRow;
}

size_t CStepMatrix::getNumUnconvertedRows() const
{
  return mRows - mFirstUnconvertedRow;
}

CStepMatrixColumn * CStepMatrix::addColumn(const CZeroSet & set,
    CStepMatrixColumn const * pPositive,
    CStepMatrixColumn const * pNegative)
{
  CStepMatrixColumn * pColumn = new CStepMatrixColumn(set, pPositive, pNegative);
  push_back(pColumn);

  return pColumn;
}

bool CStepMatrix::splitColumns(std::list< CStepMatrixColumn * > & PositiveColumns,
                               std::list< CStepMatrixColumn * > & NegativeColumns,
                               std::list< CStepMatrixColumn * > & NullColumns)
{
  PositiveColumns.clear();
  NegativeColumns.clear();

  iterator it = begin();
  const_iterator itEnd = end();

  while (it != itEnd)
    {
      const C_FLOAT64 & Value = (*it)->getMultiplier();

      if (Value > 0.0)
        {
          PositiveColumns.push_back(*it);
          ++it;
        }
      else if (Value < 0.0)
        {
          NegativeColumns.push_back(*it);

          // Since all negative columns have to be removed this is the perfect place to do so.
          it = erase(it);
        }
      else
        {
          NullColumns.push_back(*it);
          ++it;
        }
    }

  if (NegativeColumns.empty())
    {
      convertRow();

      return false;
    }
  else if (PositiveColumns.empty())
    {
      // We can not remove the negative columns therefore we add them again.
      std::list< CStepMatrixColumn * >::const_iterator itNeg = NegativeColumns.begin();
      std::list< CStepMatrixColumn * >::const_iterator endNeg = NegativeColumns.end();

      for (; itNeg != endNeg; ++itNeg)
        {
          push_back(*itNeg);
        }

      convertRow();

      return false;
    }

  return true;
}

void CStepMatrix::removeInvalidColumns(const std::vector< CStepMatrixColumn * > & invalidColumns)
{
  std::vector< CStepMatrixColumn * >::const_iterator it = invalidColumns.begin();
  std::vector< CStepMatrixColumn * >::const_iterator end = invalidColumns.end();

  for (; it != end; ++it)
    {
      remove(*it);
      delete *it;
    }
}

void CStepMatrix::getUnsetBitIndexes(const CStepMatrixColumn * pColumn,
                                     CVector< size_t > & indexes) const
{
  const CZeroSet & ZeroSet = pColumn->getZeroSet();

  indexes.resize(ZeroSet.getNumberOfUnsetBits());
  size_t * pIndex = indexes.array();
  size_t * pIndexEnd = pIndex + indexes.size();

  CZeroSet::CIndex Bit = 0;
  size_t Index = 0;

  for (; pIndex != pIndexEnd; ++Bit, ++Index)
    {
      if (!ZeroSet.isSet(Bit))
        {
          // Apply pivot.
          *pIndex = mPivot[Index];
          pIndex++;
        }
    }

  return;
}

void CStepMatrix::convertRow(const size_t & index,
                             CMatrix< C_INT32 > & nullspaceMatrix)
{
  CZeroSet::CIndex Index(mFirstUnconvertedRow);

  iterator it = begin();
  const_iterator itEnd = end();
  C_INT32 * pValue = & nullspaceMatrix(index, 0);

  if (mFirstUnconvertedRow != index)
    {
      C_INT32 * pFirstUnconvertedValue = & nullspaceMatrix(mFirstUnconvertedRow, 0);

      for (; it != itEnd; ++it, ++pValue, ++pFirstUnconvertedValue)
        {
          if (*pValue != 0)
            {
              (*it)->unsetBit(Index);
            }

          *pValue = *pFirstUnconvertedValue;
        }

      // We need to remember the reordering.
      size_t tmp = mPivot[index];
      mPivot[index] = mPivot[mFirstUnconvertedRow];
      mPivot[mFirstUnconvertedRow] = tmp;
    }
  else
    {
      for (; it != itEnd; ++it, ++pValue)
        {
          if (*pValue != 0)
            {
              (*it)->unsetBit(Index);
            }
        }
    }

  mFirstUnconvertedRow++;
}

std::ostream & operator << (std::ostream & os, const CStepMatrix & m)
{
  os << m.mPivot << std::endl;

  size_t i;
  CZeroSet::CIndex Bit;

  CStepMatrix::const_iterator it;
  CStepMatrix::const_iterator end = m.end();

  for (i = 0, Bit = 0; i < m.mFirstUnconvertedRow; ++i, ++Bit)
    {
      for (it = m.begin(); it != end; ++it)
        {
          if ((*it)->getZeroSet().isSet(Bit))
            {
              os << "*\t";
            }
          else
            {
              os << ".\t";
            }
        }

      os << std::endl;
    }

  for (i = m.mRows - m.mFirstUnconvertedRow; i > 0;)
    {
      --i;

      for (it = m.begin(); it != end; ++it)
        {
          os << (*it)->getReaction()[i] << '\t';
        }

      os << std::endl;
    }

  return os;
}
<|endoftext|>


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

#include "perfetto/ext/base/file_utils.h"

#include <sys/stat.h>
#include <sys/types.h>

#include <algorithm>
#include <deque>
#include <string>
#include <vector>

#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/base/platform_handle.h"
#include "perfetto/base/status.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/utils.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <Windows.h>
#include <direct.h>
#include <io.h>
#else
#include <dirent.h>
#include <unistd.h>
#endif

namespace perfetto {
namespace base {
namespace {
constexpr size_t kBufSize = 2048;
}  // namespace

ssize_t Read(int fd, void* dst, size_t dst_size) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _read(fd, dst, static_cast<unsigned>(dst_size));
#else
  return PERFETTO_EINTR(read(fd, dst, dst_size));
#endif
}

bool ReadFileDescriptor(int fd, std::string* out) {
  // Do not override existing data in string.
  size_t i = out->size();

  struct stat buf {};
  if (fstat(fd, &buf) != -1) {
    if (buf.st_size > 0)
      out->resize(i + static_cast<size_t>(buf.st_size));
  }

  ssize_t bytes_read;
  for (;;) {
    if (out->size() < i + kBufSize)
      out->resize(out->size() + kBufSize);

    bytes_read = Read(fd, &((*out)[i]), kBufSize);
    if (bytes_read > 0) {
      i += static_cast<size_t>(bytes_read);
    } else {
      out->resize(i);
      return bytes_read == 0;
    }
  }
}

bool ReadPlatformHandle(PlatformHandle h, std::string* out) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Do not override existing data in string.
  size_t i = out->size();

  for (;;) {
    if (out->size() < i + kBufSize)
      out->resize(out->size() + kBufSize);
    DWORD bytes_read = 0;
    auto res = ::ReadFile(h, &((*out)[i]), kBufSize, &bytes_read, nullptr);
    if (res && bytes_read > 0) {
      i += static_cast<size_t>(bytes_read);
    } else {
      out->resize(i);
      const bool is_eof = res && bytes_read == 0;
      auto err = res ? 0 : GetLastError();
      // The "Broken pipe" error on Windows is slighly different than Unix:
      // On Unix: a "broken pipe" error can happen only on the writer side. On
      // the reader there is no broken pipe, just a EOF.
      // On windows: the reader also sees a broken pipe error.
      // Here we normalize on the Unix behavior, treating broken pipe as EOF.
      return is_eof || err == ERROR_BROKEN_PIPE;
    }
  }
#else
  return ReadFileDescriptor(h, out);
#endif
}

bool ReadFileStream(FILE* f, std::string* out) {
  return ReadFileDescriptor(fileno(f), out);
}

bool ReadFile(const std::string& path, std::string* out) {
  base::ScopedFile fd = base::OpenFile(path, O_RDONLY);
  if (!fd)
    return false;

  return ReadFileDescriptor(*fd, out);
}

ssize_t WriteAll(int fd, const void* buf, size_t count) {
  size_t written = 0;
  while (written < count) {
    // write() on windows takes an unsigned int size.
    uint32_t bytes_left = static_cast<uint32_t>(
        std::min(count - written, static_cast<size_t>(UINT32_MAX)));
    ssize_t wr = PERFETTO_EINTR(
        write(fd, static_cast<const char*>(buf) + written, bytes_left));
    if (wr == 0)
      break;
    if (wr < 0)
      return wr;
    written += static_cast<size_t>(wr);
  }
  return static_cast<ssize_t>(written);
}

ssize_t WriteAllHandle(PlatformHandle h, const void* buf, size_t count) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  DWORD wsize = 0;
  if (::WriteFile(h, buf, static_cast<DWORD>(count), &wsize, nullptr)) {
    return wsize;
  } else {
    return -1;
  }
#else
  return WriteAll(h, buf, count);
#endif
}

bool FlushFile(int fd) {
  PERFETTO_DCHECK(fd != 0);
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  return !PERFETTO_EINTR(fdatasync(fd));
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return !PERFETTO_EINTR(_commit(fd));
#else
  return !PERFETTO_EINTR(fsync(fd));
#endif
}

bool Mkdir(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _mkdir(path.c_str()) == 0;
#else
  return mkdir(path.c_str(), 0755) == 0;
#endif
}

bool Rmdir(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _rmdir(path.c_str()) == 0;
#else
  return rmdir(path.c_str()) == 0;
#endif
}

int CloseFile(int fd) {
  return close(fd);
}

ScopedFile OpenFile(const std::string& path, int flags, FileOpenMode mode) {
  PERFETTO_DCHECK((flags & O_CREAT) == 0 || mode != kFileModeInvalid);
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Always use O_BINARY on Windows, to avoid silly EOL translations.
  ScopedFile fd(_open(path.c_str(), flags | O_BINARY, mode));
#else
  // Always open a ScopedFile with O_CLOEXEC so we can safely fork and exec.
  ScopedFile fd(open(path.c_str(), flags | O_CLOEXEC, mode));
#endif
  return fd;
}

bool FileExists(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _access(path.c_str(), 0) == 0;
#else
  return access(path.c_str(), F_OK) == 0;
#endif
}

// Declared in base/platform_handle.h.
int ClosePlatformHandle(PlatformHandle handle) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Make the return value UNIX-style.
  return CloseHandle(handle) ? 0 : -1;
#else
  return close(handle);
#endif
}

base::Status ListFilesRecursive(const std::string& dir_path,
                                std::vector<std::string>& output) {
  std::string root_dir_path = dir_path;
  if (root_dir_path.back() == '\\') {
    root_dir_path.back() = '/';
  } else if (root_dir_path.back() != '/') {
    root_dir_path.push_back('/');
  }

  // dir_queue contains full paths to the directories. The paths include the
  // root_dir_path at the beginning and the trailing slash at the end.
  std::deque<std::string> dir_queue;
  dir_queue.push_back(root_dir_path);

  while (!dir_queue.empty()) {
    const std::string cur_dir = std::move(dir_queue.front());
    dir_queue.pop_front();
#if PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
    return base::ErrStatus("ListFilesRecursive not supported yet");
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
    std::string glob_path = cur_dir + "*";
    // + 1 because we also have to count the NULL terminator.
    if (glob_path.length() + 1 > MAX_PATH)
      return base::ErrStatus("Directory path %s is too long", dir_path.c_str());
    WIN32_FIND_DATAA ffd;

    base::ScopedResource<HANDLE, FindClose, nullptr, false,
                         base::PlatformHandleChecker>
        hFind(FindFirstFileA(glob_path.c_str(), &ffd));
    if (!hFind) {
      // For empty directories, there should be at least one entry '.'.
      // If FindFirstFileA returns INVALID_HANDLE_VALUE, this means directory
      // couldn't be accessed.
      return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
    }
    do {
      if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0)
        continue;
      if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
        std::string subdir_path = cur_dir + ffd.cFileName + '/';
        dir_queue.push_back(subdir_path);
      } else {
        const std::string full_path = cur_dir + ffd.cFileName;
        PERFETTO_CHECK(full_path.length() > root_dir_path.length());
        output.push_back(full_path.substr(root_dir_path.length()));
      }
    } while (FindNextFileA(*hFind, &ffd));
#else
    ScopedDir dir = ScopedDir(opendir(cur_dir.c_str()));
    if (!dir) {
      return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
    }
    for (auto* dirent = readdir(dir.get()); dirent != nullptr;
         dirent = readdir(dir.get())) {
      if (strcmp(dirent->d_name, ".") == 0 ||
          strcmp(dirent->d_name, "..") == 0) {
        continue;
      }
      if (dirent->d_type == DT_DIR) {
        dir_queue.push_back(cur_dir + dirent->d_name + '/');
      } else if (dirent->d_type == DT_REG) {
        const std::string full_path = cur_dir + dirent->d_name;
        PERFETTO_CHECK(full_path.length() > root_dir_path.length());
        output.push_back(full_path.substr(root_dir_path.length()));
      }
    }
#endif
  }
  return base::OkStatus();
}

std::string GetFileExtension(const std::string& filename) {
  auto ext_idx = filename.rfind('.');
  if (ext_idx == std::string::npos)
    return std::string();
  return filename.substr(ext_idx);
}

base::Optional<size_t> GetFileSize(const std::string& file_path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  HANDLE file =
      CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
                  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  if (file == INVALID_HANDLE_VALUE) {
    return nullopt;
  }
  LARGE_INTEGER file_size;
  file_size.QuadPart = 0;
  BOOL ok = GetFileSizeEx(file, &file_size);
  CloseHandle(file);
  if (!ok) {
    return nullopt;
  }
  return static_cast<size_t>(file_size.QuadPart);
#else
  base::ScopedFile fd(base::OpenFile(file_path, O_RDONLY | O_CLOEXEC));
  if (!fd) {
    return nullopt;
  }
  struct stat buf{};
  if (fstat(*fd, &buf) == -1) {
    return nullopt;
  }
  return static_cast<size_t>(buf.st_size);
#endif
}

}  // namespace base
}  // namespace perfetto
<commit_msg>Speculative fix of Windows build breakage am: 0f3d962283 am: 456a82d668<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "perfetto/ext/base/file_utils.h"

#include <sys/stat.h>
#include <sys/types.h>

#include <algorithm>
#include <deque>
#include <string>
#include <vector>

#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/base/platform_handle.h"
#include "perfetto/base/status.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/utils.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <Windows.h>
#include <direct.h>
#include <io.h>
#else
#include <dirent.h>
#include <unistd.h>
#endif

namespace perfetto {
namespace base {
namespace {
constexpr size_t kBufSize = 2048;
}  // namespace

ssize_t Read(int fd, void* dst, size_t dst_size) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _read(fd, dst, static_cast<unsigned>(dst_size));
#else
  return PERFETTO_EINTR(read(fd, dst, dst_size));
#endif
}

bool ReadFileDescriptor(int fd, std::string* out) {
  // Do not override existing data in string.
  size_t i = out->size();

  struct stat buf {};
  if (fstat(fd, &buf) != -1) {
    if (buf.st_size > 0)
      out->resize(i + static_cast<size_t>(buf.st_size));
  }

  ssize_t bytes_read;
  for (;;) {
    if (out->size() < i + kBufSize)
      out->resize(out->size() + kBufSize);

    bytes_read = Read(fd, &((*out)[i]), kBufSize);
    if (bytes_read > 0) {
      i += static_cast<size_t>(bytes_read);
    } else {
      out->resize(i);
      return bytes_read == 0;
    }
  }
}

bool ReadPlatformHandle(PlatformHandle h, std::string* out) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Do not override existing data in string.
  size_t i = out->size();

  for (;;) {
    if (out->size() < i + kBufSize)
      out->resize(out->size() + kBufSize);
    DWORD bytes_read = 0;
    auto res = ::ReadFile(h, &((*out)[i]), kBufSize, &bytes_read, nullptr);
    if (res && bytes_read > 0) {
      i += static_cast<size_t>(bytes_read);
    } else {
      out->resize(i);
      const bool is_eof = res && bytes_read == 0;
      auto err = res ? 0 : GetLastError();
      // The "Broken pipe" error on Windows is slighly different than Unix:
      // On Unix: a "broken pipe" error can happen only on the writer side. On
      // the reader there is no broken pipe, just a EOF.
      // On windows: the reader also sees a broken pipe error.
      // Here we normalize on the Unix behavior, treating broken pipe as EOF.
      return is_eof || err == ERROR_BROKEN_PIPE;
    }
  }
#else
  return ReadFileDescriptor(h, out);
#endif
}

bool ReadFileStream(FILE* f, std::string* out) {
  return ReadFileDescriptor(fileno(f), out);
}

bool ReadFile(const std::string& path, std::string* out) {
  base::ScopedFile fd = base::OpenFile(path, O_RDONLY);
  if (!fd)
    return false;

  return ReadFileDescriptor(*fd, out);
}

ssize_t WriteAll(int fd, const void* buf, size_t count) {
  size_t written = 0;
  while (written < count) {
    // write() on windows takes an unsigned int size.
    uint32_t bytes_left = static_cast<uint32_t>(
        std::min(count - written, static_cast<size_t>(UINT32_MAX)));
    ssize_t wr = PERFETTO_EINTR(
        write(fd, static_cast<const char*>(buf) + written, bytes_left));
    if (wr == 0)
      break;
    if (wr < 0)
      return wr;
    written += static_cast<size_t>(wr);
  }
  return static_cast<ssize_t>(written);
}

ssize_t WriteAllHandle(PlatformHandle h, const void* buf, size_t count) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  DWORD wsize = 0;
  if (::WriteFile(h, buf, static_cast<DWORD>(count), &wsize, nullptr)) {
    return wsize;
  } else {
    return -1;
  }
#else
  return WriteAll(h, buf, count);
#endif
}

bool FlushFile(int fd) {
  PERFETTO_DCHECK(fd != 0);
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  return !PERFETTO_EINTR(fdatasync(fd));
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return !PERFETTO_EINTR(_commit(fd));
#else
  return !PERFETTO_EINTR(fsync(fd));
#endif
}

bool Mkdir(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _mkdir(path.c_str()) == 0;
#else
  return mkdir(path.c_str(), 0755) == 0;
#endif
}

bool Rmdir(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _rmdir(path.c_str()) == 0;
#else
  return rmdir(path.c_str()) == 0;
#endif
}

int CloseFile(int fd) {
  return close(fd);
}

ScopedFile OpenFile(const std::string& path, int flags, FileOpenMode mode) {
  PERFETTO_DCHECK((flags & O_CREAT) == 0 || mode != kFileModeInvalid);
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Always use O_BINARY on Windows, to avoid silly EOL translations.
  ScopedFile fd(_open(path.c_str(), flags | O_BINARY, mode));
#else
  // Always open a ScopedFile with O_CLOEXEC so we can safely fork and exec.
  ScopedFile fd(open(path.c_str(), flags | O_CLOEXEC, mode));
#endif
  return fd;
}

bool FileExists(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _access(path.c_str(), 0) == 0;
#else
  return access(path.c_str(), F_OK) == 0;
#endif
}

// Declared in base/platform_handle.h.
int ClosePlatformHandle(PlatformHandle handle) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Make the return value UNIX-style.
  return CloseHandle(handle) ? 0 : -1;
#else
  return close(handle);
#endif
}

base::Status ListFilesRecursive(const std::string& dir_path,
                                std::vector<std::string>& output) {
  std::string root_dir_path = dir_path;
  if (root_dir_path.back() == '\\') {
    root_dir_path.back() = '/';
  } else if (root_dir_path.back() != '/') {
    root_dir_path.push_back('/');
  }

  // dir_queue contains full paths to the directories. The paths include the
  // root_dir_path at the beginning and the trailing slash at the end.
  std::deque<std::string> dir_queue;
  dir_queue.push_back(root_dir_path);

  while (!dir_queue.empty()) {
    const std::string cur_dir = std::move(dir_queue.front());
    dir_queue.pop_front();
#if PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
    return base::ErrStatus("ListFilesRecursive not supported yet");
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
    std::string glob_path = cur_dir + "*";
    // + 1 because we also have to count the NULL terminator.
    if (glob_path.length() + 1 > MAX_PATH)
      return base::ErrStatus("Directory path %s is too long", dir_path.c_str());
    WIN32_FIND_DATAA ffd;

    // Wrap FindClose to: (1) make the return unix-style; (2) deal w/ stdcall.
    static auto find_close = [](HANDLE h) { return FindClose(h) ? 0 : -1; };
    base::ScopedResource<HANDLE, find_close, nullptr, false,
                         base::PlatformHandleChecker>
        hFind(FindFirstFileA(glob_path.c_str(), &ffd));
    if (!hFind) {
      // For empty directories, there should be at least one entry '.'.
      // If FindFirstFileA returns INVALID_HANDLE_VALUE, this means directory
      // couldn't be accessed.
      return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
    }
    do {
      if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0)
        continue;
      if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
        std::string subdir_path = cur_dir + ffd.cFileName + '/';
        dir_queue.push_back(subdir_path);
      } else {
        const std::string full_path = cur_dir + ffd.cFileName;
        PERFETTO_CHECK(full_path.length() > root_dir_path.length());
        output.push_back(full_path.substr(root_dir_path.length()));
      }
    } while (FindNextFileA(*hFind, &ffd));
#else
    ScopedDir dir = ScopedDir(opendir(cur_dir.c_str()));
    if (!dir) {
      return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
    }
    for (auto* dirent = readdir(dir.get()); dirent != nullptr;
         dirent = readdir(dir.get())) {
      if (strcmp(dirent->d_name, ".") == 0 ||
          strcmp(dirent->d_name, "..") == 0) {
        continue;
      }
      if (dirent->d_type == DT_DIR) {
        dir_queue.push_back(cur_dir + dirent->d_name + '/');
      } else if (dirent->d_type == DT_REG) {
        const std::string full_path = cur_dir + dirent->d_name;
        PERFETTO_CHECK(full_path.length() > root_dir_path.length());
        output.push_back(full_path.substr(root_dir_path.length()));
      }
    }
#endif
  }
  return base::OkStatus();
}

std::string GetFileExtension(const std::string& filename) {
  auto ext_idx = filename.rfind('.');
  if (ext_idx == std::string::npos)
    return std::string();
  return filename.substr(ext_idx);
}

base::Optional<size_t> GetFileSize(const std::string& file_path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  HANDLE file =
      CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
                  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  if (file == INVALID_HANDLE_VALUE) {
    return nullopt;
  }
  LARGE_INTEGER file_size;
  file_size.QuadPart = 0;
  BOOL ok = GetFileSizeEx(file, &file_size);
  CloseHandle(file);
  if (!ok) {
    return nullopt;
  }
  return static_cast<size_t>(file_size.QuadPart);
#else
  base::ScopedFile fd(base::OpenFile(file_path, O_RDONLY | O_CLOEXEC));
  if (!fd) {
    return nullopt;
  }
  struct stat buf{};
  if (fstat(*fd, &buf) == -1) {
    return nullopt;
  }
  return static_cast<size_t>(buf.st_size);
#endif
}

}  // namespace base
}  // namespace perfetto
<|endoftext|>


<commit_before>#include <time.h>
#include <unistd.h>

#include <iostream>

struct node {
    struct node *pr;
    struct node *lf;
    struct node *rg;
    int value;
} typedef Node;

class BST
{
    public:

        void insert_node(int value);
        void delete_node(int value);
        void print_nodes(void);

        BST();

    private:

        Node *root;

        void insert_node(Node *node, int value);
        void delete_node(Node *node, int value);
        void transplant(Node *x, Node *y);
        void print_nodes(Node *node);
        Node *create_node(Node *pr, int value);
        Node *min_node(Node *node);
};

BST::BST(void)
{
    root = NULL;
}

Node *BST::create_node(Node *pr, int value)
{
    Node *new_node = new Node();
    new_node->value = value;
    new_node->lf = NULL;
    new_node->rg = NULL;
    new_node->pr = pr;

    return new_node;
}

void BST::insert_node(Node *node, int value)
{
    if (node == NULL)
        root = create_node(NULL, value);
    else if (node->value > value) {
        if (node->lf)
            insert_node(node->lf, value);
        else {
            Node *new_node = create_node(node, value);
            node->lf = new_node;
        }
    } else {
        if (node->rg)
            insert_node(node->rg, value);
        else {
            Node *new_node = create_node(node, value);
            node->rg = new_node;
        }
    }
}

void BST::insert_node(int value)
{
    insert_node(root, value);
}

void BST::transplant(Node *x, Node *y)
{
    if (x == root)
        root = y;
    if (x == x->pr->rg)
        x->pr->rg = y;
    else
        x->pr->lf = y;
    if (y)
        y->pr = x->pr;
}

Node *BST::min_node(Node *node)
{
    if (!node->lf)
        return node;
    return min_node(node->lf);
}

void BST::delete_node(Node *node, int value)
{
    if (node == NULL)
        return;
    else if (node->value > value)
        delete_node(node->lf, value);
    else if (node->value < value)
        delete_node(node->rg, value);
    else {
        if (node->rg and !node->lf)
            transplant(node, node->rg);
        else if (node->lf and !node->rg)
            transplant(node, node->lf);
        else {
            Node *s = min_node(node->rg);
            if (s->pr != node) {
                transplant(s, s->rg);
                s->rg = node->rg;
                s->rg->pr = s;
            }

            transplant(node, s);
            s->lf = node->lf;
            s->lf->pr = s;
        }
    }
}

void BST::delete_node(int value)
{
    delete_node(root, value);
}

void BST::print_nodes(Node *node)
{
    if (!node)
        return;

    print_nodes(node->lf);
    std::cout << "Value: " << node->value << std::endl;
    print_nodes(node->rg);
}

void BST::print_nodes(void)
{
    print_nodes(root);
}

int main(int argc, char *argv[])
{
    std::cout << "Binary Search Tree!" << std::endl;

    int number_of_test_values = 10;
    BST tree = BST();

    std::cout << "Inserting <" << number_of_test_values;
    std::cout << "> random values...." << std::endl;

    srand(time(NULL));

    for (int i=0; i < number_of_test_values; i++) {
        int value = rand() % 100;
        std::cout << "Inserting " << value << std::endl;
        tree.insert_node(value);
    }

    tree.print_nodes();

    return 0;
}

<commit_msg>Generic Binary Search Tree!<commit_after>#include <time.h>
#include <unistd.h>

#include <iostream>

template <class T>
class Node
{
    public:
        Node<T> *pr;
        Node<T> *lf;
        Node<T> *rg;
        T value;

        Node(T value) {
            pr = NULL;
            lf = NULL;
            rg = NULL;
            this->value = value;
        }
};

template <class T>
class BST
{
    public:

        void insert_node(T value);
        void delete_node(T value);
        void print_nodes(void);

        BST();

    private:

        Node<T> *root;

        void insert_node(Node<T> *node, T value);
        void delete_node(Node<T> *node, T value);
        void transplant(Node<T> *x, Node<T> *y);
        void print_nodes(Node<T> *node);
        Node<T> *create_node(Node<T> *pr, T value);
        Node<T> *min_node(Node<T> *node);
};

template <class T>
BST<T>::BST(void)
{
    root = NULL;
}

template <class T>
void BST<T>::insert_node(Node<T> *node, T value)
{
    if (node == NULL)
        root = new Node<T>(value);
    else if (node->value > value) {
        if (node->lf)
            insert_node(node->lf, value);
        else {
            Node<T> *new_node = new Node<T>(value);
            node->lf = new_node;
            new_node->pr = node;
        }
    } else {
        if (node->rg)
            insert_node(node->rg, value);
        else {
            Node<T> *new_node = new Node<T>(value);
            node->rg = new_node;
            new_node->pr = node;
        }
    }
}

template <class T>
void BST<T>::insert_node(T value)
{
    insert_node(root, value);
}

template <class T>
void BST<T>::transplant(Node<T> *x, Node<T> *y)
{
    if (x == root)
        root = y;
    if (x == x->pr->rg)
        x->pr->rg = y;
    else
        x->pr->lf = y;
    if (y)
        y->pr = x->pr;
}

template <class T>
Node<T> *BST<T>::min_node(Node<T> *node)
{
    if (!node->lf)
        return node;
    return min_node(node->lf);
}

template <class T>
void BST<T>::delete_node(Node<T> *node, T value)
{
    if (node == NULL)
        return;
    else if (node->value > value)
        delete_node(node->lf, value);
    else if (node->value < value)
        delete_node(node->rg, value);
    else {
        if (!node->lf)
            transplant(node, node->rg);
        else if (!node->rg)
            transplant(node, node->lf);
        else {
            Node<T> *s = min_node(node->rg);
            if (s->pr != node) {
                transplant(s, s->rg);
                s->rg = node->rg;
                s->rg->pr = s;
            }

            transplant(node, s);
            s->lf = node->lf;
            s->lf->pr = s;
        }
    }
}

template <class T>
void BST<T>::delete_node(T value)
{
    delete_node(root, value);
}

template <class T>
void BST<T>::print_nodes(Node<T> *node)
{
    if (!node)
        return;

    print_nodes(node->lf);
    std::cout << "Value: " << node->value << std::endl;
    print_nodes(node->rg);
}

template <class T>
void BST<T>::print_nodes(void)
{
    print_nodes(root);
}

int main(int argc, char *argv[])
{
    std::cout << "Binary Search Tree!" << std::endl;

    int number_of_test_values = 10;
    BST<int> tree = BST<int>();

    std::cout << "Inserting <" << number_of_test_values;
    std::cout << "> random values...." << std::endl;

    srand(time(NULL));

    int del_value;
    for (int i=0; i < number_of_test_values; i++) {
        int value = rand() % 100;
        if (i == 5)
            del_value = value;
        std::cout << "Inserting " << value << std::endl;
        tree.insert_node(value);
    }

    tree.print_nodes();
    std::cout << "Deleting " << del_value << std::endl;
    tree.delete_node(del_value);
    tree.print_nodes();

    return 0;
}

<|endoftext|>