<commit_before>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM 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 dated February 1999.

#include "../general/okina.hpp"

#include <bitset>
#include <cassert>

namespace mfem
{

// *****************************************************************************
// * Tests if ptr is a known address
// *****************************************************************************
static bool Known(const mm::ledger &maps, const void *ptr)
{
   const mm::memory_map::const_iterator found = maps.memories.find(ptr);
   const bool known = found != maps.memories.end();
   if (known) { return true; }
   return false;
}

// *****************************************************************************
bool mm::Known(const void *ptr)
{
   return mfem::Known(maps,ptr);
}

// *****************************************************************************
// * Looks if ptr is an alias of one memory
// *****************************************************************************
static const void* IsAlias(const mm::ledger &maps, const void *ptr)
{
   MFEM_ASSERT(!Known(maps, ptr), "Ptr is an already known address!");
   for (mm::memory_map::const_iterator mem = maps.memories.begin();
        mem != maps.memories.end(); mem++)
   {
      const void *b_ptr = mem->first;
      if (b_ptr > ptr) { continue; }
      const void *end = static_cast<const char*>(b_ptr) + mem->second.bytes;
      if (ptr < end) { return b_ptr; }
   }
   return nullptr;
}

// *****************************************************************************
static const void* InsertAlias(mm::ledger &maps,
                               const void *base,
                               const void *ptr)
{
   mm::memory &mem = maps.memories.at(base);
   const long offset = static_cast<const char*>(ptr) - static_cast<const char*>
                       (base);
   const mm::alias *alias = new mm::alias{&mem, offset};
   maps.aliases.emplace(ptr, alias);
#ifdef MFEM_DEBUG_MM
   {
      mem.aliases.sort();
      for (const mm::alias *a : mem.aliases)
      {
         if (a->mem == &mem )
         {
            assert(a->offset != offset);
         }
      }
   }
#endif // MFEM_DEBUG
   mem.aliases.push_back(alias);
   return ptr;
}

// *****************************************************************************
// * Tests if ptr is an alias address
// *****************************************************************************
static bool Alias(mm::ledger &maps, const void *ptr)
{
   const mm::alias_map::const_iterator found = maps.aliases.find(ptr);
   const bool alias = found != maps.aliases.end();
   if (alias) { return true; }
   const void *base = IsAlias(maps, ptr);
   if (!base) { return false; }
   InsertAlias(maps, base, ptr);
   return true;
}

// *****************************************************************************
bool mm::Alias(const void *ptr)
{
   return mfem::Alias(maps,ptr);
}

// *****************************************************************************
static void DumpMode(void)
{
   static bool env_ini = false;
   static bool env_dbg = false;
   if (!env_ini) { env_dbg = getenv("DBG"); env_ini = true; }
   if (!env_dbg) { return; }
   static std::bitset<8+1> mode;
   std::bitset<8+1> cfg;
   cfg.set(config::UsingMM()?8:0);
   cfg.set(config::DeviceHasBeenEnabled()?7:0);
   cfg.set(config::DeviceEnabled()?6:0);
   cfg.set(config::DeviceDisabled()?5:0);
   cfg.set(config::UsingHost()?4:0);
   cfg.set(config::UsingDevice()?3:0);
   cfg.set(config::UsingCuda()?2:0);
   cfg.set(config::UsingOcca()?1:0);
   cfg>>=1;
   if (cfg==mode) { return; }
   mode=cfg;
   printf("\033[1K\r[0x%lx] %sMM %sHasBeenEnabled %sEnabled %sDisabled "
          "%sHOST %sDEVICE %sCUDA %sOCCA\033[m", mode.to_ulong(),
          config::UsingMM()?"\033[32m":"\033[31m",
          config::DeviceHasBeenEnabled()?"\033[32m":"\033[31m",
          config::DeviceEnabled()?"\033[32m":"\033[31m",
          config::DeviceDisabled()?"\033[32m":"\033[31m",
          config::UsingHost()?"\033[32m":"\033[31m",
          config::UsingDevice()?"\033[32m":"\033[31m",
          config::UsingCuda()?"\033[32m":"\033[31m",
          config::UsingOcca()?"\033[32m":"\033[31m");
}

// *****************************************************************************
static inline bool MmFilter(void)
{
   if (!config::UsingMM()) { return true; }
   return false;
}

// *****************************************************************************
static inline bool MmDeviceIniFilter(void)
{
   if (MmFilter()) { return true; }
   if (config::DeviceDisabled()) { return true; }
   if (!config::DeviceHasBeenEnabled()) { return true; }
   assert(!config::UsingOcca());
   return false;
}

// *****************************************************************************
// * Adds an address
// *****************************************************************************
void* mm::Insert(void *ptr, const size_t bytes)
{
   if (MmFilter()) { return ptr; }
   const bool known = Known(ptr);
   if (known)
   {
      mfem_error("Trying to insert a non-MM pointer!");
   }
   MFEM_ASSERT(!known, "Trying to add an already present address!");
   DumpMode();
   maps.memories.emplace(ptr, memory(ptr, bytes));
   return ptr;
}

// *****************************************************************************
// * Remove the address from the map, as well as all the address' aliases
// *****************************************************************************
void *mm::Erase(void *ptr)
{
   if (MmFilter()) { return ptr; }
   const bool known = Known(ptr);
   if (!known)
   {
      mfem_error("Trying to erase an unknown pointer!");
   }
   MFEM_ASSERT(known, "Trying to erase an unknown pointer!");
   memory &mem = maps.memories.at(ptr);
   for (const alias* const alias : mem.aliases)
   {
      maps.aliases.erase(alias);
   }
   mem.aliases.clear();
   maps.memories.erase(ptr);
   return ptr;
}

// *****************************************************************************
// * Turn a known address to the right host or device one
// * Alloc, Push or Pull it if required
// *****************************************************************************
static void *PtrKnown(mm::ledger &maps, void *ptr)
{
   mm::memory &base = maps.memories.at(ptr);
   const bool host = base.host;
   const bool device = !host;
   const size_t bytes = base.bytes;
   const bool gpu = config::UsingDevice();
   if (host && !gpu) { return ptr; }
   if (!base.d_ptr) { cuMemAlloc(&base.d_ptr, bytes); }
   assert(base.d_ptr);
   if (device &&  gpu) { return base.d_ptr; }
   if (device && !gpu) // Pull
   {
      cuMemcpyDtoH(ptr, base.d_ptr, bytes);
      base.host = true;
      return ptr;
   }
   // Push
   assert(host && gpu);
   cuMemcpyHtoD(base.d_ptr, ptr, bytes);
   base.host = false;
   return base.d_ptr;
}

// *****************************************************************************
// * Turn an alias to the right host or device one
// * Alloc, Push or Pull it if required
// *****************************************************************************
static void *PtrAlias(mm::ledger &maps, void *ptr)
{
   const bool gpu = config::UsingDevice();
   const mm::alias *alias = maps.aliases.at(ptr);
   const mm::memory *base = alias->mem;
   const bool host = base->host;
   const bool device = !base->host;
   const size_t bytes = base->bytes;
   if (host && !gpu) { return ptr; }
   if (!base->d_ptr) { cuMemAlloc(&(alias->mem->d_ptr), bytes); }
   assert(base->d_ptr);
   void *a_ptr = static_cast<char*>(base->d_ptr) + alias->offset;
   if (device && gpu) { return a_ptr; }
   if (device && !gpu) // Pull
   {
      cuMemcpyDtoH(base->h_ptr, base->d_ptr, bytes);
      alias->mem->host = true;
      return ptr;
   }
   // Push
   assert(host && gpu);
   cuMemcpyHtoD(base->d_ptr, base->h_ptr, bytes);
   alias->mem->host = false;
   return a_ptr;
}

// *****************************************************************************
// * Turn an address to the right host or device one
// *****************************************************************************
void *mm::Ptr(void *ptr)
{
   if (MmDeviceIniFilter()) { return ptr; }
   if (Known(ptr)) { return PtrKnown(maps, ptr); }
   if (Alias(ptr)) { return PtrAlias(maps, ptr); }
   if (config::UsingDevice())
   {
      mfem_error("Trying to use unknown pointer on the DEVICE!");
   }
   return ptr;
}

// *****************************************************************************
const void *mm::Ptr(const void *ptr)
{
   return static_cast<const void*>(Ptr(const_cast<void*>(ptr)));
}

// *****************************************************************************
static OccaMemory occaMemory(mm::ledger &maps, const void *ptr)
{
   OccaDevice occaDevice = config::GetOccaDevice();
   if (!config::UsingMM())
   {
      OccaMemory o_ptr = occaWrapMemory(occaDevice, const_cast<void*>(ptr), 0);
      return o_ptr;
   }
   const bool known = mm::known(ptr);
   if (!known) { mfem_error("occaMemory"); }
   MFEM_ASSERT(known, "Unknown address!");
   mm::memory &base = maps.memories.at(ptr);
   const size_t bytes = base.bytes;
   const bool gpu = config::UsingDevice();
   MFEM_ASSERT(config::UsingOcca(), "Using OCCA memory without OCCA mode!");
   if (!base.d_ptr)
   {
      base.host = false; // This address is no more on the host
      if (gpu)
      {
         cuMemAlloc(&base.d_ptr, bytes);
         void *stream = config::Stream();
         cuMemcpyHtoDAsync(base.d_ptr, base.h_ptr, bytes, stream);
      }
      else
      {
         base.o_ptr = occaDeviceMalloc(occaDevice, bytes);
         base.d_ptr = occaMemoryPtr(base.o_ptr);
         occaCopyFrom(base.o_ptr, base.h_ptr);
      }
   }
   if (gpu)
   {
      return occaWrapMemory(occaDevice, base.d_ptr, bytes);
   }
   return base.o_ptr;
}

// *****************************************************************************
OccaMemory mm::Memory(const void *ptr) { return occaMemory(maps, ptr); }

// *****************************************************************************
static void PushKnown(mm::ledger &maps, const void *ptr, const size_t bytes)
{
   mm::memory &base = maps.memories.at(ptr);
   if (!base.d_ptr) { cuMemAlloc(&base.d_ptr, base.bytes); }
   cuMemcpyHtoD(base.d_ptr, ptr, bytes == 0 ? base.bytes : bytes);
}

// *****************************************************************************
static void PushAlias(const mm::ledger &maps, const void *ptr,
                      const size_t bytes)
{
   const mm::alias *alias = maps.aliases.at(ptr);
   cuMemcpyHtoD(static_cast<char*>(alias->mem->d_ptr) + alias->offset, ptr, bytes);
}

// *****************************************************************************
void mm::Push(const void *ptr, const size_t bytes)
{
   if (MmDeviceIniFilter()) { return; }
   if (Known(ptr)) { return PushKnown(maps, ptr, bytes); }
   if (Alias(ptr)) { return PushAlias(maps, ptr, bytes); }
   if (config::UsingDevice())
   {
      mfem_error("Unknown pointer to push to!");
   }
}

// *****************************************************************************
static void PullKnown(const mm::ledger &maps, const void *ptr,
                      const size_t bytes)
{
   const mm::memory &base = maps.memories.at(ptr);
   const bool host = base.host;
   if (host) { return; }
   cuMemcpyDtoH(base.h_ptr, base.d_ptr, bytes == 0 ? base.bytes : bytes);
}

// *****************************************************************************
static void PullAlias(const mm::ledger &maps, const void *ptr,
                      const size_t bytes)
{
   const mm::alias *alias = maps.aliases.at(ptr);
   const bool host = alias->mem->host;
   if (host) { return; }
   cuMemcpyDtoH(const_cast<void*>(ptr),
                static_cast<char*>(alias->mem->d_ptr) + alias->offset, bytes);
}

// *****************************************************************************
void mm::Pull(const void *ptr, const size_t bytes)
{
   if (MmDeviceIniFilter()) { return; }
   if (Known(ptr)) { return PullKnown(maps, ptr, bytes); }
   if (Alias(ptr)) { return PullAlias(maps, ptr, bytes); }
   if (config::UsingDevice())
   {
      mfem_error("Unknown pointer to pull from!");
   }
}

// *****************************************************************************
// * Data will be pushed/pulled before the copy happens on the H or the D
// *****************************************************************************
static void* d2d(void *dst, const void *src, const size_t bytes,
                 const bool async)
{
   const bool host = config::UsingHost();
   if (host) { return std::memcpy(dst, src, bytes); }
   const void *d_src = mm::ptr(src);
   void *d_dst = mm::ptr(dst);
   if (!async) { return cuMemcpyDtoD(d_dst, const_cast<void*>(d_src), bytes); }
   return cuMemcpyDtoDAsync(d_dst, const_cast<void*>(d_src),
                            bytes, config::Stream());
}

// *****************************************************************************
void* mm::memcpy(void *dst, const void *src, const size_t bytes,
                 const bool async)
{
   if (bytes == 0)
   {
      return dst;
   }
   else
   {
      return d2d(dst, src, bytes, async);
   }
}

} // namespace mfem
<commit_msg>memory manger returns null pointer if you give it one<commit_after>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM 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 dated February 1999.

#include "../general/okina.hpp"

#include <bitset>
#include <cassert>

namespace mfem
{

// *****************************************************************************
// * Tests if ptr is a known address
// *****************************************************************************
static bool Known(const mm::ledger &maps, const void *ptr)
{
   const mm::memory_map::const_iterator found = maps.memories.find(ptr);
   const bool known = found != maps.memories.end();
   if (known) { return true; }
   return false;
}

// *****************************************************************************
bool mm::Known(const void *ptr)
{
   return mfem::Known(maps,ptr);
}

// *****************************************************************************
// * Looks if ptr is an alias of one memory
// *****************************************************************************
static const void* IsAlias(const mm::ledger &maps, const void *ptr)
{
   MFEM_ASSERT(!Known(maps, ptr), "Ptr is an already known address!");
   for (mm::memory_map::const_iterator mem = maps.memories.begin();
        mem != maps.memories.end(); mem++)
   {
      const void *b_ptr = mem->first;
      if (b_ptr > ptr) { continue; }
      const void *end = static_cast<const char*>(b_ptr) + mem->second.bytes;
      if (ptr < end) { return b_ptr; }
   }
   return nullptr;
}

// *****************************************************************************
static const void* InsertAlias(mm::ledger &maps,
                               const void *base,
                               const void *ptr)
{
   mm::memory &mem = maps.memories.at(base);
   const long offset = static_cast<const char*>(ptr) - static_cast<const char*>
                       (base);
   const mm::alias *alias = new mm::alias{&mem, offset};
   maps.aliases.emplace(ptr, alias);
#ifdef MFEM_DEBUG_MM
   {
      mem.aliases.sort();
      for (const mm::alias *a : mem.aliases)
      {
         if (a->mem == &mem )
         {
            assert(a->offset != offset);
         }
      }
   }
#endif // MFEM_DEBUG
   mem.aliases.push_back(alias);
   return ptr;
}

// *****************************************************************************
// * Tests if ptr is an alias address
// *****************************************************************************
static bool Alias(mm::ledger &maps, const void *ptr)
{
   const mm::alias_map::const_iterator found = maps.aliases.find(ptr);
   const bool alias = found != maps.aliases.end();
   if (alias) { return true; }
   const void *base = IsAlias(maps, ptr);
   if (!base) { return false; }
   InsertAlias(maps, base, ptr);
   return true;
}

// *****************************************************************************
bool mm::Alias(const void *ptr)
{
   return mfem::Alias(maps,ptr);
}

// *****************************************************************************
static void DumpMode(void)
{
   static bool env_ini = false;
   static bool env_dbg = false;
   if (!env_ini) { env_dbg = getenv("DBG"); env_ini = true; }
   if (!env_dbg) { return; }
   static std::bitset<8+1> mode;
   std::bitset<8+1> cfg;
   cfg.set(config::UsingMM()?8:0);
   cfg.set(config::DeviceHasBeenEnabled()?7:0);
   cfg.set(config::DeviceEnabled()?6:0);
   cfg.set(config::DeviceDisabled()?5:0);
   cfg.set(config::UsingHost()?4:0);
   cfg.set(config::UsingDevice()?3:0);
   cfg.set(config::UsingCuda()?2:0);
   cfg.set(config::UsingOcca()?1:0);
   cfg>>=1;
   if (cfg==mode) { return; }
   mode=cfg;
   printf("\033[1K\r[0x%lx] %sMM %sHasBeenEnabled %sEnabled %sDisabled "
          "%sHOST %sDEVICE %sCUDA %sOCCA\033[m", mode.to_ulong(),
          config::UsingMM()?"\033[32m":"\033[31m",
          config::DeviceHasBeenEnabled()?"\033[32m":"\033[31m",
          config::DeviceEnabled()?"\033[32m":"\033[31m",
          config::DeviceDisabled()?"\033[32m":"\033[31m",
          config::UsingHost()?"\033[32m":"\033[31m",
          config::UsingDevice()?"\033[32m":"\033[31m",
          config::UsingCuda()?"\033[32m":"\033[31m",
          config::UsingOcca()?"\033[32m":"\033[31m");
}

// *****************************************************************************
static inline bool MmFilter(void)
{
   if (!config::UsingMM()) { return true; }
   return false;
}

// *****************************************************************************
static inline bool MmDeviceIniFilter(void)
{
   if (MmFilter()) { return true; }
   if (config::DeviceDisabled()) { return true; }
   if (!config::DeviceHasBeenEnabled()) { return true; }
   assert(!config::UsingOcca());
   return false;
}

// *****************************************************************************
// * Adds an address
// *****************************************************************************
void* mm::Insert(void *ptr, const size_t bytes)
{
   if (MmFilter()) { return ptr; }
   const bool known = Known(ptr);
   if (known)
   {
      mfem_error("Trying to insert a non-MM pointer!");
   }
   MFEM_ASSERT(!known, "Trying to add an already present address!");
   DumpMode();
   maps.memories.emplace(ptr, memory(ptr, bytes));
   return ptr;
}

// *****************************************************************************
// * Remove the address from the map, as well as all the address' aliases
// *****************************************************************************
void *mm::Erase(void *ptr)
{
   if (MmFilter()) { return ptr; }
   const bool known = Known(ptr);
   if (!known)
   {
      mfem_error("Trying to erase an unknown pointer!");
   }
   MFEM_ASSERT(known, "Trying to erase an unknown pointer!");
   memory &mem = maps.memories.at(ptr);
   for (const alias* const alias : mem.aliases)
   {
      maps.aliases.erase(alias);
   }
   mem.aliases.clear();
   maps.memories.erase(ptr);
   return ptr;
}

// *****************************************************************************
// * Turn a known address to the right host or device one
// * Alloc, Push or Pull it if required
// *****************************************************************************
static void *PtrKnown(mm::ledger &maps, void *ptr)
{
   mm::memory &base = maps.memories.at(ptr);
   const bool host = base.host;
   const bool device = !host;
   const size_t bytes = base.bytes;
   const bool gpu = config::UsingDevice();
   if (host && !gpu) { return ptr; }
   if (!base.d_ptr) { cuMemAlloc(&base.d_ptr, bytes); }
   assert(base.d_ptr);
   if (device &&  gpu) { return base.d_ptr; }
   if (device && !gpu) // Pull
   {
      cuMemcpyDtoH(ptr, base.d_ptr, bytes);
      base.host = true;
      return ptr;
   }
   // Push
   assert(host && gpu);
   cuMemcpyHtoD(base.d_ptr, ptr, bytes);
   base.host = false;
   return base.d_ptr;
}

// *****************************************************************************
// * Turn an alias to the right host or device one
// * Alloc, Push or Pull it if required
// *****************************************************************************
static void *PtrAlias(mm::ledger &maps, void *ptr)
{
   const bool gpu = config::UsingDevice();
   const mm::alias *alias = maps.aliases.at(ptr);
   const mm::memory *base = alias->mem;
   const bool host = base->host;
   const bool device = !base->host;
   const size_t bytes = base->bytes;
   if (host && !gpu) { return ptr; }
   if (!base->d_ptr) { cuMemAlloc(&(alias->mem->d_ptr), bytes); }
   assert(base->d_ptr);
   void *a_ptr = static_cast<char*>(base->d_ptr) + alias->offset;
   if (device && gpu) { return a_ptr; }
   if (device && !gpu) // Pull
   {
      cuMemcpyDtoH(base->h_ptr, base->d_ptr, bytes);
      alias->mem->host = true;
      return ptr;
   }
   // Push
   assert(host && gpu);
   cuMemcpyHtoD(base->d_ptr, base->h_ptr, bytes);
   alias->mem->host = false;
   return a_ptr;
}

// *****************************************************************************
// * Turn an address to the right host or device one
// *****************************************************************************
void *mm::Ptr(void *ptr)
{
   if (MmDeviceIniFilter()) { return ptr; }
   if (Known(ptr)) { return PtrKnown(maps, ptr); }
   if (Alias(ptr)) { return PtrAlias(maps, ptr); }
   if (config::UsingDevice() && ptr==NULL)
   {
     return NULL;
   }
   else
   {
     mfem_error("Trying to use unknown pointer on the DEVICE!");
   }
   return ptr;
}

// *****************************************************************************
const void *mm::Ptr(const void *ptr)
{
   return static_cast<const void*>(Ptr(const_cast<void*>(ptr)));
}

// *****************************************************************************
static OccaMemory occaMemory(mm::ledger &maps, const void *ptr)
{
   OccaDevice occaDevice = config::GetOccaDevice();
   if (!config::UsingMM())
   {
      OccaMemory o_ptr = occaWrapMemory(occaDevice, const_cast<void*>(ptr), 0);
      return o_ptr;
   }
   const bool known = mm::known(ptr);
   if (!known) { mfem_error("occaMemory"); }
   MFEM_ASSERT(known, "Unknown address!");
   mm::memory &base = maps.memories.at(ptr);
   const size_t bytes = base.bytes;
   const bool gpu = config::UsingDevice();
   MFEM_ASSERT(config::UsingOcca(), "Using OCCA memory without OCCA mode!");
   if (!base.d_ptr)
   {
      base.host = false; // This address is no more on the host
      if (gpu)
      {
         cuMemAlloc(&base.d_ptr, bytes);
         void *stream = config::Stream();
         cuMemcpyHtoDAsync(base.d_ptr, base.h_ptr, bytes, stream);
      }
      else
      {
         base.o_ptr = occaDeviceMalloc(occaDevice, bytes);
         base.d_ptr = occaMemoryPtr(base.o_ptr);
         occaCopyFrom(base.o_ptr, base.h_ptr);
      }
   }
   if (gpu)
   {
      return occaWrapMemory(occaDevice, base.d_ptr, bytes);
   }
   return base.o_ptr;
}

// *****************************************************************************
OccaMemory mm::Memory(const void *ptr) { return occaMemory(maps, ptr); }

// *****************************************************************************
static void PushKnown(mm::ledger &maps, const void *ptr, const size_t bytes)
{
   mm::memory &base = maps.memories.at(ptr);
   if (!base.d_ptr) { cuMemAlloc(&base.d_ptr, base.bytes); }
   cuMemcpyHtoD(base.d_ptr, ptr, bytes == 0 ? base.bytes : bytes);
}

// *****************************************************************************
static void PushAlias(const mm::ledger &maps, const void *ptr,
                      const size_t bytes)
{
   const mm::alias *alias = maps.aliases.at(ptr);
   cuMemcpyHtoD(static_cast<char*>(alias->mem->d_ptr) + alias->offset, ptr, bytes);
}

// *****************************************************************************
void mm::Push(const void *ptr, const size_t bytes)
{
   if (MmDeviceIniFilter()) { return; }
   if (Known(ptr)) { return PushKnown(maps, ptr, bytes); }
   if (Alias(ptr)) { return PushAlias(maps, ptr, bytes); }
   if (config::UsingDevice())
   {
      mfem_error("Unknown pointer to push to!");
   }
}

// *****************************************************************************
static void PullKnown(const mm::ledger &maps, const void *ptr,
                      const size_t bytes)
{
   const mm::memory &base = maps.memories.at(ptr);
   const bool host = base.host;
   if (host) { return; }
   cuMemcpyDtoH(base.h_ptr, base.d_ptr, bytes == 0 ? base.bytes : bytes);
}

// *****************************************************************************
static void PullAlias(const mm::ledger &maps, const void *ptr,
                      const size_t bytes)
{
   const mm::alias *alias = maps.aliases.at(ptr);
   const bool host = alias->mem->host;
   if (host) { return; }
   cuMemcpyDtoH(const_cast<void*>(ptr),
                static_cast<char*>(alias->mem->d_ptr) + alias->offset, bytes);
}

// *****************************************************************************
void mm::Pull(const void *ptr, const size_t bytes)
{
   if (MmDeviceIniFilter()) { return; }
   if (Known(ptr)) { return PullKnown(maps, ptr, bytes); }
   if (Alias(ptr)) { return PullAlias(maps, ptr, bytes); }
   if (config::UsingDevice())
   {
      mfem_error("Unknown pointer to pull from!");
   }
}

// *****************************************************************************
// * Data will be pushed/pulled before the copy happens on the H or the D
// *****************************************************************************
static void* d2d(void *dst, const void *src, const size_t bytes,
                 const bool async)
{
   const bool host = config::UsingHost();
   if (host) { return std::memcpy(dst, src, bytes); }
   const void *d_src = mm::ptr(src);
   void *d_dst = mm::ptr(dst);
   if (!async) { return cuMemcpyDtoD(d_dst, const_cast<void*>(d_src), bytes); }
   return cuMemcpyDtoDAsync(d_dst, const_cast<void*>(d_src),
                            bytes, config::Stream());
}

// *****************************************************************************
void* mm::memcpy(void *dst, const void *src, const size_t bytes,
                 const bool async)
{
   if (bytes == 0)
   {
      return dst;
   }
   else
   {
      return d2d(dst, src, bytes, async);
   }
}

} // namespace mfem
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//-------------------------------------------------------------------------
//     Event handler for ESD input
//     Author: Andreas Morsch, CERN
//-------------------------------------------------------------------------

#include <TTree.h>

#include "AliESDInputHandler.h"
#include "AliESDEvent.h"
#include "AliESD.h"

ClassImp(AliESDInputHandler)

//______________________________________________________________________________
AliESDInputHandler::AliESDInputHandler() :
  AliInputEventHandler(),
  fEvent(0x0)
{
  // default constructor
}

//______________________________________________________________________________
AliESDInputHandler::~AliESDInputHandler()
{
  // destructor
  //  delete fEvent;
}

//______________________________________________________________________________
AliESDInputHandler::AliESDInputHandler(const char* name, const char* title):
  AliInputEventHandler(name, title), fEvent(0x0)
{
}

Bool_t AliESDInputHandler::InitIO(Option_t* /*opt*/)
{
    if (!fTree) return kFALSE;
    // Get pointer to ESD event
    if(!fEvent){
      fEvent = new AliESDEvent();
      fEvent->ReadFromTree(fTree);
    }
    return kTRUE;
}

Bool_t AliESDInputHandler::BeginEvent(Long64_t /*entry*/)
{
    // Copy from old to new format if necessary
    AliESD* old = ((AliESDEvent*) fEvent)->GetAliESDOld();
    if (old) {
	((AliESDEvent*)fEvent)->CopyFromOldESD();
	old->Reset();
    }
    return kTRUE;
}

Bool_t  AliESDInputHandler::FinishEvent(){
  //  if(fEvent)fEvent->Reset();
  return kTRUE;
}

<commit_msg>bug fix that caused processing of the same event all the time in proof<commit_after>/**************************************************************************
 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//-------------------------------------------------------------------------
//     Event handler for ESD input
//     Author: Andreas Morsch, CERN
//-------------------------------------------------------------------------

#include <TTree.h>

#include "AliESDInputHandler.h"
#include "AliESDEvent.h"
#include "AliESD.h"

ClassImp(AliESDInputHandler)

//______________________________________________________________________________
AliESDInputHandler::AliESDInputHandler() :
  AliInputEventHandler(),
  fEvent(0x0)
{
  // default constructor
}

//______________________________________________________________________________
AliESDInputHandler::~AliESDInputHandler()
{
  // destructor
  //  delete fEvent;
}

//______________________________________________________________________________
AliESDInputHandler::AliESDInputHandler(const char* name, const char* title):
  AliInputEventHandler(name, title), fEvent(0x0)
{
}

Bool_t AliESDInputHandler::InitIO(Option_t* /*opt*/)
{
    if (!fTree) return kFALSE;
    // Get pointer to ESD event
    if (fEvent) {
      delete fEvent;
      fEvent = 0;
    }
    fEvent = new AliESDEvent();

    fEvent->ReadFromTree(fTree);
    return kTRUE;
}

Bool_t AliESDInputHandler::BeginEvent(Long64_t /*entry*/)
{
    // Copy from old to new format if necessary
    AliESD* old = ((AliESDEvent*) fEvent)->GetAliESDOld();
    if (old) {
	((AliESDEvent*)fEvent)->CopyFromOldESD();
	old->Reset();
    }
    return kTRUE;
}

Bool_t  AliESDInputHandler::FinishEvent(){
  //  if(fEvent)fEvent->Reset();
  return kTRUE;
}

<|endoftext|>


<commit_before>/* XWinOutd.cc *************************************************-*-c++-*-
**                                                                      **
**                             G A M M A                                **
**                                                                      **
**      XWinOutd                                  Implementation	**
**                                                                      **
**      Copyright (c) 1999                                              **
**      Scott Smith                                                     **
**      National High Magnetic Field Laboratory                         **
**      1800 E. Paul Dirac Drive                                        **
**      Box 4005                                                        **
**      Tallahassee, FL 32306                                           **
**                                                                      **
**      $Header: $
**                                                                      **
*************************************************************************/

/*************************************************************************
**                                                                      **
**      Description                                                     **
**                                                                      **
** The XWin* files provide an interface to Bruker XWinNMR (uxnmr) data  **
** sets. This class embodies a Bruker parameter file, outd, which seems	**
** to control output of NMR spectra within XWinNMR. Yet another ASCII	**
** paramter file, this has nothing to do with GAMMA and we will try	**
** and have minimal dealings with it - especially since it appears	**
** associated with processed data. A typical filename will be something	**
** such as dir/1/pdata/1/outd where dir	is the directory base that	**
** contains XWinNMR data.  Note that without the existence of an outd	**
** file one cannot display status parameters under the "Output" menu	**
** in XWinNMR. I don't recall if its absence disallows proper reading	**
** of a 1D data set within XWinNMR..... below if their 1D data set	**
** directory hierarchy:							**
**                          __ acqu  (changable parameter file)		**
**			   / 						**
**                        /___ acqus (static parameter file)		**
**			 /						**
**  expname -- expnum --< ---- fid (binary data)			**
**			 \						**
**			  \___ pdata -- 1 -- proc, procs, meta, outd	**
**									**
*************************************************************************/

#ifndef   XWinOutd_CC_			// Is file already included?
#  define XWinOutd_CC_ 1		// If no, then remember it
#  if defined(GAMPRAGMA)		// Using the GNU compiler?
#    pragma implementation		// This is the implementation
#  endif

#include <GamIO/XWinOutd.h>		// Include the interface
#include <GamIO/XWinPSet.h>             // Include Bruker parameter sets
#include <Basics/Gutils.h>		// Include GAMMA errors
#include <stdlib.h>
#include <string>			// Include libstdc++ strings
#include <time.h>			// Include time and data access
#ifndef _MSC_VER                        // If not using MSVC++ then we
 #include <sys/time.h>			// Include time and date access
 #include <unistd.h>			// Include POSIX getcwd function
#else                                   // and if using MSVC++ then I guess
 #include <time.h>			// Include time and date access
#endif

using std::string;			// Using libstdc++ strings
using std::ofstream;			// Using libstdc++ output file streams
using std::ostream;			// Using libstdc++ output streams

// ----------------------------------------------------------------------------
// ----------------------------- PRIVATE FUNCTIONS ----------------------------
// ----------------------------------------------------------------------------

// ____________________________________________________________________________
// i                      XWinNMR Outd File Error Handling
// ____________________________________________________________________________

/* These functions take care of any errors encountered when reading, writing,
   and setting parameters in Bruker acquisition parameter files.

        Input		eidx    : Error index
        		pname   : Additional error message
        		noret	: Flag for linefeed (0=linefeed)
        Output		void    : An error message is output                 */

void XWinOutd::XWinOutderror(int eidx, int noret) const
  {
  string hdr("XWinNMR Outd Parameter File");
  string msg;
  switch (eidx)
    {
    case 25: GAMMAerror(hdr,"Cannot Write Parameters To File",noret);break; // (25)
    default: GAMMAerror(hdr, eidx, noret); break;// Usually Unknown Error  (-1)
    }
  }

void XWinOutd::XWinOutderror(int eidx, const string& pname, int noret) const
  {
  string hdr("XWinNMR Outd Parameter File");
  string msg;
  switch(eidx)
    {
    case 21:msg = string("Cannot Write To ") + pname;
             GAMMAerror(hdr,msg+pname,noret);  break;                  // (21)
    default: GAMMAerror(hdr, eidx, pname, noret); break;// Unknown Error  (-1)
    }
  }

volatile void XWinOutd::XWinOutdfatality(int eidx) const
  {
  XWinOutderror(eidx, 1);			// Normal non-fatal error
  if(eidx) XWinOutderror(0);			// Program aborting error
  GAMMAfatal();					// Clean exit from program
  }

volatile void XWinOutd::XWinOutdfatality(int eidx, const string& pname) const
  {
  XWinOutderror(eidx, pname, 1);		// Normal non-fatal error
  if(eidx) XWinOutderror(0);			// Program aborting error
  GAMMAfatal();					// Clean exit from program
  }

// ____________________________________________________________________________
// ii                 XWinNMR Outd File Default Parmameters
// ____________________________________________________________________________

void XWinOutd::SetDefaults()
  {
  oname     = "outd";
  _TITLE    = "Parameter File,  Version XWIN-NMR  GAMMA";
  _JCAMPDX  = "5.0";
  _DATATYPE = "Parameter Values";
  time_t longtime;              // Need a time structure
  longtime = NULL;        //

#ifdef _MSC_VER
	struct tm newtime;
  localtime_s(&newtime,&longtime);
	char date[31];
	asctime_s(date, 30, &newtime);
  _DATE = date;
#else
  struct tm *ptr;               // For setting current date
  ptr = localtime(&longtime);
  _DATE = asctime(ptr);
#endif

  _CURPLOT = string("hpdj550");	// Default plotter
  _CURPRIN = string("$hpdj550c");// The default printer
  _DFORMAT = "normdp";		// The default format
  _LFORMAT = "normlp";		// The default format
  _PFORMAT = "normpl"; 		// The default format
  _SURQMSG = 1;			//
  }

// ----------------------------------------------------------------------------
// ---------------------------- PUBLIC FUNCTIONS ------------------------------
// ----------------------------------------------------------------------------

// ____________________________________________________________________________
// A             XWinOutd Parameter File Constructors, Destructor
// ____________________________________________________________________________

/* These are the constructors of the class handling Bruker XWinNMR output
   parameter files.  This doesn't do anything in particular, it is the write
   functions that perform the work.                                          */

XWinOutd::XWinOutd()  { SetDefaults(); }
XWinOutd::XWinOutd(const string& name) { SetDefaults(); oname = name; }
XWinOutd::~XWinOutd() { }

// ____________________________________________________________________________
// B                  XWinOutd Parameter Access Functions
// ____________________________________________________________________________

/* These functions allow users to set any more important parameters that
   these files contain.                                                      */

void XWinOutd::Printer(string pname) { _CURPRIN = pname; }
void XWinOutd::Plotter(string pname) { _CURPLOT = pname; }

// ____________________________________________________________________________
// C                       XWinOutd Input Functions
// ____________________________________________________________________________

/* These functions will read in the 1D plot/print parameters from an XWinNMR
   parameter file, typically named outd.  By design, the Bruker parameter
   file is initially read into a GAMMA parameter set so that ALL parameters in
   the file are stored (class XWinPSet).  Subsequently, the parameters in the
   parameter set are parsed (herein) to obtain values of consequence to GAMMA
   and these are explicitly maintained variables in this class.

     Function                               Purpose
   ____________________________________________________________________________

     read               Read in parameter set for class object.  This is done
	    	        special since Bruker format is NOT in GAMMA parameter
		        format so it must be parsed appropriately.
   parsePSet            Converts parameters in internal pset to specific values
    getPar              Returns parameter found in the parameter set herein
		        This function is inherited from base class XWinPSet. */

bool XWinOutd::read(const string& filein, int warn)
  {
  oname = filein;				// Set internal filename
  bool TF = read(warn);                          // Read in all parameters
  if(!TF && warn)                               // Output errors if trouble
    {
    XWinOutderror(1, filein, 1);               // Problems with filein
    if(warn > 1) XWinOutderror(3);             // Can't construct from pset
    else         XWinOutderror(3,1);
    }
  return TF;
  }

bool XWinOutd::read(int warn)
  {
  XWinPSet::readPSet(oname, warn);		// Use base class to read
  return parsePSet(warn);			// Parse our essential params
  }

bool XWinOutd::parsePSet(int warn)
  {
  string pvalue;					// String value for # points
  if(getPar("TITLE",   pvalue,0,0))    _TITLE = pvalue;	// Try & get the title
  if(getPar("JCAMPDX", _JCAMPDX,0,0)) 			// Try & get JCAMP version
//    _JCAMPDX = atof(pvalue.c_str());
  if(getPar("DATATYPE",pvalue,0,0)) _DATATYPE = pvalue;	// Try & get DATATYPE
  if(getPar("DATE",    pvalue,0,0))    _DATE  = pvalue;	// Try & get the date
  if(getPar("CURPLOT", pvalue,0,0)) _CURPLOT  = pvalue;
  if(getPar("CURPRIN", pvalue,0,0)) _CURPRIN  = pvalue;
  if(getPar("DFORMAT", pvalue,0,0)) _DFORMAT  = pvalue;
  if(getPar("LFORMAT", pvalue,0,0)) _LFORMAT  = pvalue;
  if(getPar("PFORMAT", pvalue,0,0)) _PFORMAT  = pvalue;
  if(getPar("SURQMSG", pvalue,0,0))
    _SURQMSG  = atoi(pvalue.c_str());
  return true;
  }

//int XWinOutd::getPar(const string& n,string& v,int i, int w) const;

// ____________________________________________________________________________
// D                         XWinOutd Output Functions
// ____________________________________________________________________________

/* These function allow for output of NMR parameters directly into a Bruker
   XWinNMR ASCII parameter file (outd).                                      */

int XWinOutd::write(const string& dname, int warn)
  { oname = dname; return write(warn); }

int XWinOutd::write(int warn) const
  {
  ofstream ofstr(oname.c_str());		// Open ASCII file for output
  if(!ofstr.good())				// If file bad then exit
     {
     if(warn)
       {
       XWinOutderror(2, 1);			// Output filestream problems
       XWinOutderror(25,1);			// Can't write parameters out
       if(warn==1) XWinOutderror(21,oname,1);	// Can't write parameters out
       else        XWinOutdfatality(21,oname);	// with out without die
       }
     return 0;
     }
  string nn("##");			// Bruker ## parameter line start
  string nns("##$");			// Bruker ##$ parameter line start
  string ss("$$");			// Bruker $$ parameter line start
  ofstr << nn << "TITLE= "    << _TITLE << "\n";
  ofstr << nn << "JCAMPDX= "  << _JCAMPDX << "\n";
  ofstr << nn << "DATATYPE= " << _DATATYPE << "\n";
  time_t longtime;				// Need a time structure
  longtime = NULL;

#ifdef _MSC_VER
	struct tm newtime;
  localtime_s(&newtime,&longtime);
	char timebuf[31];
	asctime_s(timebuf, 30, &newtime);
  ofstr << ss << " " << timebuf;
#else
  struct tm *ptr;
  ptr = localtime(&longtime);
  ofstr << ss << " " << asctime(ptr);
#endif

	ofstr << nns << "CURPLOT= <" << _CURPLOT << ">\n";
  ofstr << nns << "CURPRIN= <" << _CURPRIN << ">\n";
  ofstr << nns << "DFORMAT= <" << _DFORMAT << ">\n";
  ofstr << nns << "LFORMAT= <" << _LFORMAT << ">\n";
  ofstr << nns << "PFORMAT= <" << _PFORMAT << ">\n";
  ofstr << nns << "SURQMSG= <" << _SURQMSG << "\n";
  ofstr << nn << "END= ";
  ofstr << "\n\n";
  return 1;
  }

// ____________________________________________________________________________
// E                    XWinOutd Standard Output Functions
// ____________________________________________________________________________

/* These functions allow for a quick output of the parameter file contents.
   They don't have anything to do with output while running XWinNMR, rather
   users can just glance at procs parameters or store then in a small file.  */

// ostream& XWinOutd::printPset(ostream& O) const		INHERITED

ostream& XWinOutd::print(ostream& ostr, int full, int hdr) const
  {
  string marg(16, ' ');
  string ls = string("\n") + marg;
  if(hdr)
    ostr << ls << "Outd Parameter File:       " << oname;
  XWinPSet::print(ostr, 0, 0);
  if(!full)
    {
    ostr << ls << "Plotter:                      " << _CURPLOT;
    ostr << ls << "Printer:                      " << _CURPRIN;
    ostr << ls << "Display Format:               " << _DFORMAT;
    ostr << ls << "Print Format:                 " << _LFORMAT;
    ostr << ls << "Parameter Plot Format:        " << _PFORMAT;
    ostr << ls << "SURQMSG:   			 " << _SURQMSG;
    }
  else
    {
    ostr << ls << "Title:                        " << _TITLE;
    ostr << ls << "JCAMP Version:                " << _JCAMPDX;
    ostr << ls << "Data Type:                    " << _DATATYPE;
    ostr << ls << "File Date:                    " << _DATE;
    ostr << ls << "Plotter:                      " << _CURPLOT;
    ostr << ls << "Printer:                      " << _CURPRIN;
    ostr << ls << "Display Format:               " << _DFORMAT;
    ostr << ls << "Print Format:                 " << _LFORMAT;
    ostr << ls << "Parameter Plot Format:        " << _PFORMAT;
    ostr << ls << "SURQMSG:   			 " << _SURQMSG;
    }
  return ostr;
  }

ostream& operator<< (ostream& O, const XWinOutd& P) { P.print(O); return O; }

#endif							// XWinOutd.cc
<commit_msg>Corrected mistake when assigning initial value to time_t longtime. Should be a long and not a pointer.<commit_after>/* XWinOutd.cc *************************************************-*-c++-*-
**                                                                      **
**                             G A M M A                                **
**                                                                      **
**      XWinOutd                                  Implementation	**
**                                                                      **
**      Copyright (c) 1999                                              **
**      Scott Smith                                                     **
**      National High Magnetic Field Laboratory                         **
**      1800 E. Paul Dirac Drive                                        **
**      Box 4005                                                        **
**      Tallahassee, FL 32306                                           **
**                                                                      **
**      $Header: $
**                                                                      **
*************************************************************************/

/*************************************************************************
**                                                                      **
**      Description                                                     **
**                                                                      **
** The XWin* files provide an interface to Bruker XWinNMR (uxnmr) data  **
** sets. This class embodies a Bruker parameter file, outd, which seems	**
** to control output of NMR spectra within XWinNMR. Yet another ASCII	**
** paramter file, this has nothing to do with GAMMA and we will try	**
** and have minimal dealings with it - especially since it appears	**
** associated with processed data. A typical filename will be something	**
** such as dir/1/pdata/1/outd where dir	is the directory base that	**
** contains XWinNMR data.  Note that without the existence of an outd	**
** file one cannot display status parameters under the "Output" menu	**
** in XWinNMR. I don't recall if its absence disallows proper reading	**
** of a 1D data set within XWinNMR..... below if their 1D data set	**
** directory hierarchy:							**
**                          __ acqu  (changable parameter file)		**
**			   / 						**
**                        /___ acqus (static parameter file)		**
**			 /						**
**  expname -- expnum --< ---- fid (binary data)			**
**			 \						**
**			  \___ pdata -- 1 -- proc, procs, meta, outd	**
**									**
*************************************************************************/

#ifndef   XWinOutd_CC_			// Is file already included?
#  define XWinOutd_CC_ 1		// If no, then remember it
#  if defined(GAMPRAGMA)		// Using the GNU compiler?
#    pragma implementation		// This is the implementation
#  endif

#include <GamIO/XWinOutd.h>		// Include the interface
#include <GamIO/XWinPSet.h>             // Include Bruker parameter sets
#include <Basics/Gutils.h>		// Include GAMMA errors
#include <stdlib.h>
#include <string>			// Include libstdc++ strings
#include <time.h>			// Include time and data access
#ifndef _MSC_VER                        // If not using MSVC++ then we
 #include <sys/time.h>			// Include time and date access
 #include <unistd.h>			// Include POSIX getcwd function
#else                                   // and if using MSVC++ then I guess
 #include <time.h>			// Include time and date access
#endif

using std::string;			// Using libstdc++ strings
using std::ofstream;			// Using libstdc++ output file streams
using std::ostream;			// Using libstdc++ output streams

// ----------------------------------------------------------------------------
// ----------------------------- PRIVATE FUNCTIONS ----------------------------
// ----------------------------------------------------------------------------

// ____________________________________________________________________________
// i                      XWinNMR Outd File Error Handling
// ____________________________________________________________________________

/* These functions take care of any errors encountered when reading, writing,
   and setting parameters in Bruker acquisition parameter files.

        Input		eidx    : Error index
        		pname   : Additional error message
        		noret	: Flag for linefeed (0=linefeed)
        Output		void    : An error message is output                 */

void XWinOutd::XWinOutderror(int eidx, int noret) const
  {
  string hdr("XWinNMR Outd Parameter File");
  string msg;
  switch (eidx)
    {
    case 25: GAMMAerror(hdr,"Cannot Write Parameters To File",noret);break; // (25)
    default: GAMMAerror(hdr, eidx, noret); break;// Usually Unknown Error  (-1)
    }
  }

void XWinOutd::XWinOutderror(int eidx, const string& pname, int noret) const
  {
  string hdr("XWinNMR Outd Parameter File");
  string msg;
  switch(eidx)
    {
    case 21:msg = string("Cannot Write To ") + pname;
             GAMMAerror(hdr,msg+pname,noret);  break;                  // (21)
    default: GAMMAerror(hdr, eidx, pname, noret); break;// Unknown Error  (-1)
    }
  }

volatile void XWinOutd::XWinOutdfatality(int eidx) const
  {
  XWinOutderror(eidx, 1);			// Normal non-fatal error
  if(eidx) XWinOutderror(0);			// Program aborting error
  GAMMAfatal();					// Clean exit from program
  }

volatile void XWinOutd::XWinOutdfatality(int eidx, const string& pname) const
  {
  XWinOutderror(eidx, pname, 1);		// Normal non-fatal error
  if(eidx) XWinOutderror(0);			// Program aborting error
  GAMMAfatal();					// Clean exit from program
  }

// ____________________________________________________________________________
// ii                 XWinNMR Outd File Default Parmameters
// ____________________________________________________________________________

void XWinOutd::SetDefaults()
  {
  oname     = "outd";
  _TITLE    = "Parameter File,  Version XWIN-NMR  GAMMA";
  _JCAMPDX  = "5.0";
  _DATATYPE = "Parameter Values";
  time_t longtime;              // Need a time structure
  longtime = 0;        //

#ifdef _MSC_VER
	struct tm newtime;
  localtime_s(&newtime,&longtime);
	char date[31];
	asctime_s(date, 30, &newtime);
  _DATE = date;
#else
  struct tm *ptr;               // For setting current date
  ptr = localtime(&longtime);
  _DATE = asctime(ptr);
#endif

  _CURPLOT = string("hpdj550");	// Default plotter
  _CURPRIN = string("$hpdj550c");// The default printer
  _DFORMAT = "normdp";		// The default format
  _LFORMAT = "normlp";		// The default format
  _PFORMAT = "normpl"; 		// The default format
  _SURQMSG = 1;			//
  }

// ----------------------------------------------------------------------------
// ---------------------------- PUBLIC FUNCTIONS ------------------------------
// ----------------------------------------------------------------------------

// ____________________________________________________________________________
// A             XWinOutd Parameter File Constructors, Destructor
// ____________________________________________________________________________

/* These are the constructors of the class handling Bruker XWinNMR output
   parameter files.  This doesn't do anything in particular, it is the write
   functions that perform the work.                                          */

XWinOutd::XWinOutd()  { SetDefaults(); }
XWinOutd::XWinOutd(const string& name) { SetDefaults(); oname = name; }
XWinOutd::~XWinOutd() { }

// ____________________________________________________________________________
// B                  XWinOutd Parameter Access Functions
// ____________________________________________________________________________

/* These functions allow users to set any more important parameters that
   these files contain.                                                      */

void XWinOutd::Printer(string pname) { _CURPRIN = pname; }
void XWinOutd::Plotter(string pname) { _CURPLOT = pname; }

// ____________________________________________________________________________
// C                       XWinOutd Input Functions
// ____________________________________________________________________________

/* These functions will read in the 1D plot/print parameters from an XWinNMR
   parameter file, typically named outd.  By design, the Bruker parameter
   file is initially read into a GAMMA parameter set so that ALL parameters in
   the file are stored (class XWinPSet).  Subsequently, the parameters in the
   parameter set are parsed (herein) to obtain values of consequence to GAMMA
   and these are explicitly maintained variables in this class.

     Function                               Purpose
   ____________________________________________________________________________

     read               Read in parameter set for class object.  This is done
	    	        special since Bruker format is NOT in GAMMA parameter
		        format so it must be parsed appropriately.
   parsePSet            Converts parameters in internal pset to specific values
    getPar              Returns parameter found in the parameter set herein
		        This function is inherited from base class XWinPSet. */

bool XWinOutd::read(const string& filein, int warn)
  {
  oname = filein;				// Set internal filename
  bool TF = read(warn);                          // Read in all parameters
  if(!TF && warn)                               // Output errors if trouble
    {
    XWinOutderror(1, filein, 1);               // Problems with filein
    if(warn > 1) XWinOutderror(3);             // Can't construct from pset
    else         XWinOutderror(3,1);
    }
  return TF;
  }

bool XWinOutd::read(int warn)
  {
  XWinPSet::readPSet(oname, warn);		// Use base class to read
  return parsePSet(warn);			// Parse our essential params
  }

bool XWinOutd::parsePSet(int warn)
  {
  string pvalue;					// String value for # points
  if(getPar("TITLE",   pvalue,0,0))    _TITLE = pvalue;	// Try & get the title
  if(getPar("JCAMPDX", _JCAMPDX,0,0)) 			// Try & get JCAMP version
//    _JCAMPDX = atof(pvalue.c_str());
  if(getPar("DATATYPE",pvalue,0,0)) _DATATYPE = pvalue;	// Try & get DATATYPE
  if(getPar("DATE",    pvalue,0,0))    _DATE  = pvalue;	// Try & get the date
  if(getPar("CURPLOT", pvalue,0,0)) _CURPLOT  = pvalue;
  if(getPar("CURPRIN", pvalue,0,0)) _CURPRIN  = pvalue;
  if(getPar("DFORMAT", pvalue,0,0)) _DFORMAT  = pvalue;
  if(getPar("LFORMAT", pvalue,0,0)) _LFORMAT  = pvalue;
  if(getPar("PFORMAT", pvalue,0,0)) _PFORMAT  = pvalue;
  if(getPar("SURQMSG", pvalue,0,0))
    _SURQMSG  = atoi(pvalue.c_str());
  return true;
  }

//int XWinOutd::getPar(const string& n,string& v,int i, int w) const;

// ____________________________________________________________________________
// D                         XWinOutd Output Functions
// ____________________________________________________________________________

/* These function allow for output of NMR parameters directly into a Bruker
   XWinNMR ASCII parameter file (outd).                                      */

int XWinOutd::write(const string& dname, int warn)
  { oname = dname; return write(warn); }

int XWinOutd::write(int warn) const
  {
  ofstream ofstr(oname.c_str());		// Open ASCII file for output
  if(!ofstr.good())				// If file bad then exit
     {
     if(warn)
       {
       XWinOutderror(2, 1);			// Output filestream problems
       XWinOutderror(25,1);			// Can't write parameters out
       if(warn==1) XWinOutderror(21,oname,1);	// Can't write parameters out
       else        XWinOutdfatality(21,oname);	// with out without die
       }
     return 0;
     }
  string nn("##");			// Bruker ## parameter line start
  string nns("##$");			// Bruker ##$ parameter line start
  string ss("$$");			// Bruker $$ parameter line start
  ofstr << nn << "TITLE= "    << _TITLE << "\n";
  ofstr << nn << "JCAMPDX= "  << _JCAMPDX << "\n";
  ofstr << nn << "DATATYPE= " << _DATATYPE << "\n";
  time_t longtime;				// Need a time structure
  longtime = 0;

#ifdef _MSC_VER
	struct tm newtime;
  localtime_s(&newtime,&longtime);
	char timebuf[31];
	asctime_s(timebuf, 30, &newtime);
  ofstr << ss << " " << timebuf;
#else
  struct tm *ptr;
  ptr = localtime(&longtime);
  ofstr << ss << " " << asctime(ptr);
#endif

	ofstr << nns << "CURPLOT= <" << _CURPLOT << ">\n";
  ofstr << nns << "CURPRIN= <" << _CURPRIN << ">\n";
  ofstr << nns << "DFORMAT= <" << _DFORMAT << ">\n";
  ofstr << nns << "LFORMAT= <" << _LFORMAT << ">\n";
  ofstr << nns << "PFORMAT= <" << _PFORMAT << ">\n";
  ofstr << nns << "SURQMSG= <" << _SURQMSG << "\n";
  ofstr << nn << "END= ";
  ofstr << "\n\n";
  return 1;
  }

// ____________________________________________________________________________
// E                    XWinOutd Standard Output Functions
// ____________________________________________________________________________

/* These functions allow for a quick output of the parameter file contents.
   They don't have anything to do with output while running XWinNMR, rather
   users can just glance at procs parameters or store then in a small file.  */

// ostream& XWinOutd::printPset(ostream& O) const		INHERITED

ostream& XWinOutd::print(ostream& ostr, int full, int hdr) const
  {
  string marg(16, ' ');
  string ls = string("\n") + marg;
  if(hdr)
    ostr << ls << "Outd Parameter File:       " << oname;
  XWinPSet::print(ostr, 0, 0);
  if(!full)
    {
    ostr << ls << "Plotter:                      " << _CURPLOT;
    ostr << ls << "Printer:                      " << _CURPRIN;
    ostr << ls << "Display Format:               " << _DFORMAT;
    ostr << ls << "Print Format:                 " << _LFORMAT;
    ostr << ls << "Parameter Plot Format:        " << _PFORMAT;
    ostr << ls << "SURQMSG:   			 " << _SURQMSG;
    }
  else
    {
    ostr << ls << "Title:                        " << _TITLE;
    ostr << ls << "JCAMP Version:                " << _JCAMPDX;
    ostr << ls << "Data Type:                    " << _DATATYPE;
    ostr << ls << "File Date:                    " << _DATE;
    ostr << ls << "Plotter:                      " << _CURPLOT;
    ostr << ls << "Printer:                      " << _CURPRIN;
    ostr << ls << "Display Format:               " << _DFORMAT;
    ostr << ls << "Print Format:                 " << _LFORMAT;
    ostr << ls << "Parameter Plot Format:        " << _PFORMAT;
    ostr << ls << "SURQMSG:   			 " << _SURQMSG;
    }
  return ostr;
  }

ostream& operator<< (ostream& O, const XWinOutd& P) { P.print(O); return O; }

#endif							// XWinOutd.cc
<|endoftext|>


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

#include "sync/notifier/invalidator_registrar.h"

#include <cstddef>
#include <utility>

#include "base/logging.h"
#include "sync/notifier/object_id_invalidation_map.h"

namespace syncer {

InvalidatorRegistrar::InvalidatorRegistrar()
    : state_(DEFAULT_INVALIDATION_ERROR) {}

InvalidatorRegistrar::~InvalidatorRegistrar() {
  DCHECK(thread_checker_.CalledOnValidThread());
  CHECK(!handlers_.might_have_observers());
  CHECK(handler_to_ids_map_.empty());
}

void InvalidatorRegistrar::RegisterHandler(InvalidationHandler* handler) {
  DCHECK(thread_checker_.CalledOnValidThread());
  CHECK(handler);
  CHECK(!handlers_.HasObserver(handler));
  handlers_.AddObserver(handler);
}

void InvalidatorRegistrar::UpdateRegisteredIds(
    InvalidationHandler* handler,
    const ObjectIdSet& ids) {
  DCHECK(thread_checker_.CalledOnValidThread());
  CHECK(handler);
  CHECK(handlers_.HasObserver(handler));

  for (HandlerIdsMap::const_iterator it = handler_to_ids_map_.begin();
       it != handler_to_ids_map_.end(); ++it) {
    if (it->first == handler) {
      continue;
    }

    std::vector<invalidation::ObjectId> intersection;
    std::set_intersection(
        it->second.begin(), it->second.end(),
        ids.begin(), ids.end(),
        intersection.begin(), ObjectIdLessThan());
    CHECK(intersection.empty())
        << "Duplicate registration: trying to register "
        << ObjectIdToString(*intersection.begin()) << " for "
        << handler << " when it's already registered for "
        << it->first;
  }

  if (ids.empty()) {
    handler_to_ids_map_.erase(handler);
  } else {
    handler_to_ids_map_[handler] = ids;
  }
}

void InvalidatorRegistrar::UnregisterHandler(InvalidationHandler* handler) {
  DCHECK(thread_checker_.CalledOnValidThread());
  CHECK(handler);
  CHECK(handlers_.HasObserver(handler));
  handlers_.RemoveObserver(handler);
  handler_to_ids_map_.erase(handler);
}

ObjectIdSet InvalidatorRegistrar::GetRegisteredIds(
    InvalidationHandler* handler) const {
  DCHECK(thread_checker_.CalledOnValidThread());
  HandlerIdsMap::const_iterator lookup = handler_to_ids_map_.find(handler);
  if (lookup != handler_to_ids_map_.end()) {
    return lookup->second;
  } else {
    return ObjectIdSet();
  }
}

ObjectIdSet InvalidatorRegistrar::GetAllRegisteredIds() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  ObjectIdSet registered_ids;
  for (HandlerIdsMap::const_iterator it = handler_to_ids_map_.begin();
       it != handler_to_ids_map_.end(); ++it) {
    registered_ids.insert(it->second.begin(), it->second.end());
  }
  return registered_ids;
}

void InvalidatorRegistrar::DispatchInvalidationsToHandlers(
    const ObjectIdInvalidationMap& invalidation_map) {
  DCHECK(thread_checker_.CalledOnValidThread());
  // If we have no handlers, there's nothing to do.
  if (!handlers_.might_have_observers()) {
    return;
  }

  for (HandlerIdsMap::iterator it = handler_to_ids_map_.begin();
       it != handler_to_ids_map_.end(); ++it) {
    ObjectIdInvalidationMap to_emit =
        invalidation_map.GetSubsetWithObjectIds(it->second);
    if (!to_emit.Empty()) {
      it->first->OnIncomingInvalidation(to_emit);
    }
  }
}

void InvalidatorRegistrar::UpdateInvalidatorState(InvalidatorState state) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DVLOG(1) << "New invalidator state: " << InvalidatorStateToString(state_)
      << " -> " << InvalidatorStateToString(state);
  state_ = state;
  FOR_EACH_OBSERVER(InvalidationHandler, handlers_,
                    OnInvalidatorStateChange(state));
}

InvalidatorState InvalidatorRegistrar::GetInvalidatorState() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return state_;
}

bool InvalidatorRegistrar::IsHandlerRegisteredForTest(
    InvalidationHandler* handler) const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return handlers_.HasObserver(handler);
}

void InvalidatorRegistrar::DetachFromThreadForTest() {
  DCHECK(thread_checker_.CalledOnValidThread());
  thread_checker_.DetachFromThread();
}

}  // namespace syncer
<commit_msg>Fix misuse of STL in InvalidatorRegistrar<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sync/notifier/invalidator_registrar.h"

#include <cstddef>
#include <iterator>
#include <utility>

#include "base/logging.h"
#include "sync/notifier/object_id_invalidation_map.h"

namespace syncer {

InvalidatorRegistrar::InvalidatorRegistrar()
    : state_(DEFAULT_INVALIDATION_ERROR) {}

InvalidatorRegistrar::~InvalidatorRegistrar() {
  DCHECK(thread_checker_.CalledOnValidThread());
  CHECK(!handlers_.might_have_observers());
  CHECK(handler_to_ids_map_.empty());
}

void InvalidatorRegistrar::RegisterHandler(InvalidationHandler* handler) {
  DCHECK(thread_checker_.CalledOnValidThread());
  CHECK(handler);
  CHECK(!handlers_.HasObserver(handler));
  handlers_.AddObserver(handler);
}

void InvalidatorRegistrar::UpdateRegisteredIds(
    InvalidationHandler* handler,
    const ObjectIdSet& ids) {
  DCHECK(thread_checker_.CalledOnValidThread());
  CHECK(handler);
  CHECK(handlers_.HasObserver(handler));

  for (HandlerIdsMap::const_iterator it = handler_to_ids_map_.begin();
       it != handler_to_ids_map_.end(); ++it) {
    if (it->first == handler) {
      continue;
    }

    std::vector<invalidation::ObjectId> intersection;
    std::set_intersection(
        it->second.begin(), it->second.end(),
        ids.begin(), ids.end(),
        std::inserter(intersection, intersection.end()),
        ObjectIdLessThan());
    CHECK(intersection.empty())
        << "Duplicate registration: trying to register "
        << ObjectIdToString(*intersection.begin()) << " for "
        << handler << " when it's already registered for "
        << it->first;
  }

  if (ids.empty()) {
    handler_to_ids_map_.erase(handler);
  } else {
    handler_to_ids_map_[handler] = ids;
  }
}

void InvalidatorRegistrar::UnregisterHandler(InvalidationHandler* handler) {
  DCHECK(thread_checker_.CalledOnValidThread());
  CHECK(handler);
  CHECK(handlers_.HasObserver(handler));
  handlers_.RemoveObserver(handler);
  handler_to_ids_map_.erase(handler);
}

ObjectIdSet InvalidatorRegistrar::GetRegisteredIds(
    InvalidationHandler* handler) const {
  DCHECK(thread_checker_.CalledOnValidThread());
  HandlerIdsMap::const_iterator lookup = handler_to_ids_map_.find(handler);
  if (lookup != handler_to_ids_map_.end()) {
    return lookup->second;
  } else {
    return ObjectIdSet();
  }
}

ObjectIdSet InvalidatorRegistrar::GetAllRegisteredIds() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  ObjectIdSet registered_ids;
  for (HandlerIdsMap::const_iterator it = handler_to_ids_map_.begin();
       it != handler_to_ids_map_.end(); ++it) {
    registered_ids.insert(it->second.begin(), it->second.end());
  }
  return registered_ids;
}

void InvalidatorRegistrar::DispatchInvalidationsToHandlers(
    const ObjectIdInvalidationMap& invalidation_map) {
  DCHECK(thread_checker_.CalledOnValidThread());
  // If we have no handlers, there's nothing to do.
  if (!handlers_.might_have_observers()) {
    return;
  }

  for (HandlerIdsMap::iterator it = handler_to_ids_map_.begin();
       it != handler_to_ids_map_.end(); ++it) {
    ObjectIdInvalidationMap to_emit =
        invalidation_map.GetSubsetWithObjectIds(it->second);
    if (!to_emit.Empty()) {
      it->first->OnIncomingInvalidation(to_emit);
    }
  }
}

void InvalidatorRegistrar::UpdateInvalidatorState(InvalidatorState state) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DVLOG(1) << "New invalidator state: " << InvalidatorStateToString(state_)
      << " -> " << InvalidatorStateToString(state);
  state_ = state;
  FOR_EACH_OBSERVER(InvalidationHandler, handlers_,
                    OnInvalidatorStateChange(state));
}

InvalidatorState InvalidatorRegistrar::GetInvalidatorState() const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return state_;
}

bool InvalidatorRegistrar::IsHandlerRegisteredForTest(
    InvalidationHandler* handler) const {
  DCHECK(thread_checker_.CalledOnValidThread());
  return handlers_.HasObserver(handler);
}

void InvalidatorRegistrar::DetachFromThreadForTest() {
  DCHECK(thread_checker_.CalledOnValidThread());
  thread_checker_.DetachFromThread();
}

}  // namespace syncer
<|endoftext|>


<commit_before>#include <iostream>
#include <ctime>

#include "zobrist.hpp"
#include "uai.hpp"

int main()
{
    zobrist_init();

    std::string mode;
    std::cin >> mode;
    if(mode == "manual")
    {
        manual();
    }
    else if(mode == "uai")
    {
        uai();
    }
    else if(mode == "about")
    {
        std::cout << "An Ataxx engine written in C++" << std::endl;
        std::cout << "https://github.com/kz04px/ataxx-engine" << std::endl;
        std::cout << "Compiled: " <<   __TIME__ << " " << __DATE__ <<std::endl;
#ifdef NDEBUG
        std::cout << "NDEBUG enabled" << std::endl;
#endif
#ifdef NULLMOVE
        std::cout << "NULLMOVE enabled" << std::endl;
#endif
#ifdef KILLER_MOVES
        std::cout << "KILLER_MOVES enabled" << std::endl;
#endif
#ifdef LMR
        std::cout << "LMR enabled" << std::endl;
#endif
#ifdef ASPIRATION_WINDOWS
        std::cout << "ASPIRATION_WINDOWS enabled" << std::endl;
#endif
    }
    else
    {
        std::cout << "ERROR: Unknown protocol " << mode << std::endl;
    }

    return 0;
}
<commit_msg>Added some about information<commit_after>#include <iostream>
#include <ctime>

#include "zobrist.hpp"
#include "uai.hpp"
#include "move.hpp"
#include "hashtable.hpp"

int main()
{
    zobrist_init();

    std::string mode;
    std::cin >> mode;
    if(mode == "manual")
    {
        manual();
    }
    else if(mode == "uai")
    {
        uai();
    }
    else if(mode == "about")
    {
        std::cout << "An Ataxx engine written in C++" << std::endl;
        std::cout << "https://github.com/kz04px/ataxx-engine" << std::endl;
        std::cout << "Compiled: " <<   __TIME__ << " " << __DATE__ << std::endl;
        std::cout << std::endl;

        std::cout << "Search:" << std::endl;
#ifdef NDEBUG
        std::cout << "NDEBUG enabled" << std::endl;
#endif
#ifdef NULLMOVE
        std::cout << "NULLMOVE enabled" << std::endl;
#endif
#ifdef KILLER_MOVES
        std::cout << "KILLER_MOVES enabled" << std::endl;
#endif
#ifdef LMR
        std::cout << "LMR enabled" << std::endl;
#endif
#ifdef ASPIRATION_WINDOWS
        std::cout << "ASPIRATION_WINDOWS enabled" << std::endl;
#endif
        std::cout << std::endl;

        std::cout << "Other:" << std::endl;
        std::cout << "sizeof(Move): " << sizeof(Move) << " bytes" << std::endl;
        std::cout << "sizeof(Entry): " << sizeof(Entry) << " bytes" << std::endl;
        std::cout << "entries/MB: " << 1048576/sizeof(Entry) << std::endl;
        std::cout << std::endl;
    }
    else
    {
        std::cout << "ERROR: Unknown protocol " << mode << std::endl;
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * 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.
 *
 * 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
 * FOUNDATION 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.
 */

#ifndef BENG_PROXY_GROWING_BUFFER_HXX
#define BENG_PROXY_GROWING_BUFFER_HXX

#include "DefaultChunkAllocator.hxx"
#include "util/Compiler.h"
#include "util/ConstBuffer.hxx"

#include <utility>

#include <stddef.h>
#include <stdint.h>

template<typename T> struct ConstBuffer;
template<typename T> struct WritableBuffer;
class IstreamBucketList;

/**
 * An auto-growing buffer you can write to.
 */
class GrowingBuffer {
    friend class GrowingBufferReader;

    struct Buffer;

    struct BufferPtr {
        Buffer *buffer = nullptr;
        DefaultChunkAllocator allocator;

        BufferPtr() = default;

        BufferPtr(BufferPtr &&src) noexcept
            :buffer(src.buffer), allocator(std::move(src.allocator)) {
            src.buffer = nullptr;
        }

        ~BufferPtr() noexcept {
            if (buffer != nullptr)
                Free();
        }

        BufferPtr &operator=(BufferPtr &&src) noexcept {
            using std::swap;
            swap(buffer, src.buffer);
            swap(allocator, src.allocator);
            return *this;
        }

        operator bool() const noexcept {
            return buffer != nullptr;
        }

        Buffer &Allocate() noexcept;
        void Free() noexcept;

        void Pop() noexcept;

        const Buffer *get() const noexcept {
            return buffer;
        }

        Buffer *get() noexcept {
            return buffer;
        }

        const Buffer &operator*() const noexcept {
            return *buffer;
        }

        Buffer &operator*() noexcept {
            return *buffer;
        }

        const Buffer *operator->() const noexcept {
            return buffer;
        }

        Buffer *operator->() noexcept {
            return buffer;
        }

        template<typename F>
        void ForEachBuffer(size_t skip, F &&f) const;
    };

    struct Buffer {
        BufferPtr next;

        const size_t size;
        size_t fill = 0;
        uint8_t data[sizeof(size_t)];

        explicit Buffer(size_t _size) noexcept
            :size(_size) {}

        bool IsFull() const noexcept {
            return fill == size;
        }

        WritableBuffer<void> Write() noexcept;
        size_t WriteSome(ConstBuffer<void> src) noexcept;
    };

    BufferPtr head;
    Buffer *tail = nullptr;

    size_t position = 0;

public:
    GrowingBuffer() = default;

    GrowingBuffer(GrowingBuffer &&src) noexcept
        :head(std::move(src.head)), tail(src.tail) {
        src.tail = nullptr;
    }

    bool IsEmpty() const noexcept {
        return tail == nullptr;
    }

    void Clear() noexcept {
        Release();
    }

    /**
     * Release the buffer list, which may now be owned by somebody
     * else.
     */
    void Release() noexcept {
        if (head)
            head.Free();
        tail = nullptr;
        position = 0;
    }

    void *Write(size_t length) noexcept;

    size_t WriteSome(const void *p, size_t length) noexcept;
    void Write(const void *p, size_t length) noexcept;

    void Write(const char *p) noexcept;

    void AppendMoveFrom(GrowingBuffer &&src) noexcept;

    /**
     * Returns the total size of the buffer.
     */
    gcc_pure
    size_t GetSize() const noexcept;

    /**
     * Duplicates the whole buffer (including all chunks) to one
     * contiguous buffer.
     */
    WritableBuffer<void> Dup(struct pool &pool) const noexcept;

    gcc_pure
    ConstBuffer<void> Read() const noexcept;

    /**
     * Skip an arbitrary number of data bytes, which may span over
     * multiple internal buffers.
     */
    void Skip(size_t length) noexcept;

    /**
     * Consume data returned by Read().
     */
    void Consume(size_t length) noexcept;

    void FillBucketList(IstreamBucketList &list) const noexcept;
    size_t ConsumeBucketList(size_t nbytes) noexcept;

private:
    Buffer &AppendBuffer() noexcept;

    void CopyTo(void *dest) const noexcept;

    template<typename F>
    void ForEachBuffer(F &&f) const {
        head.ForEachBuffer(position, std::forward<F>(f));
    }
};

template<typename F>
void
GrowingBuffer::BufferPtr::ForEachBuffer(size_t skip, F &&f) const
{
    for (const auto *i = get(); i != nullptr; i = i->next.get()) {
        ConstBuffer<uint8_t> b(i->data, i->fill);
        if (skip > 0) {
            if (skip >= b.size) {
                skip -= b.size;
                continue;
            } else {
                b.skip_front(skip);
                skip = 0;
            }
        }

        f(b.ToVoid());
    }
}

class GrowingBufferReader {
    GrowingBuffer::BufferPtr buffer;
    size_t position = 0;

public:
    explicit GrowingBufferReader(GrowingBuffer &&gb) noexcept;

    gcc_pure
    bool IsEOF() const noexcept;

    gcc_pure
    size_t Available() const noexcept;

    gcc_pure
    ConstBuffer<void> Read() const noexcept;

    /**
     * Consume data returned by Read().
     */
    void Consume(size_t length) noexcept;

    /**
     * Skip an arbitrary number of data bytes, which may span over
     * multiple internal buffers.
     */
    void Skip(size_t length) noexcept;

    void FillBucketList(IstreamBucketList &list) const noexcept;
    size_t ConsumeBucketList(size_t nbytes) noexcept;

private:
    template<typename F>
    void ForEachBuffer(F &&f) const {
        buffer.ForEachBuffer(position, std::forward<F>(f));
    }
};

#endif
<commit_msg>GrowingBuffer: add move operator<commit_after>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * 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.
 *
 * 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
 * FOUNDATION 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.
 */

#ifndef BENG_PROXY_GROWING_BUFFER_HXX
#define BENG_PROXY_GROWING_BUFFER_HXX

#include "DefaultChunkAllocator.hxx"
#include "util/Compiler.h"
#include "util/ConstBuffer.hxx"

#include <utility>

#include <stddef.h>
#include <stdint.h>

template<typename T> struct ConstBuffer;
template<typename T> struct WritableBuffer;
class IstreamBucketList;

/**
 * An auto-growing buffer you can write to.
 */
class GrowingBuffer {
    friend class GrowingBufferReader;

    struct Buffer;

    struct BufferPtr {
        Buffer *buffer = nullptr;
        DefaultChunkAllocator allocator;

        BufferPtr() = default;

        BufferPtr(BufferPtr &&src) noexcept
            :buffer(src.buffer), allocator(std::move(src.allocator)) {
            src.buffer = nullptr;
        }

        ~BufferPtr() noexcept {
            if (buffer != nullptr)
                Free();
        }

        BufferPtr &operator=(BufferPtr &&src) noexcept {
            using std::swap;
            swap(buffer, src.buffer);
            swap(allocator, src.allocator);
            return *this;
        }

        operator bool() const noexcept {
            return buffer != nullptr;
        }

        Buffer &Allocate() noexcept;
        void Free() noexcept;

        void Pop() noexcept;

        const Buffer *get() const noexcept {
            return buffer;
        }

        Buffer *get() noexcept {
            return buffer;
        }

        const Buffer &operator*() const noexcept {
            return *buffer;
        }

        Buffer &operator*() noexcept {
            return *buffer;
        }

        const Buffer *operator->() const noexcept {
            return buffer;
        }

        Buffer *operator->() noexcept {
            return buffer;
        }

        template<typename F>
        void ForEachBuffer(size_t skip, F &&f) const;
    };

    struct Buffer {
        BufferPtr next;

        const size_t size;
        size_t fill = 0;
        uint8_t data[sizeof(size_t)];

        explicit Buffer(size_t _size) noexcept
            :size(_size) {}

        bool IsFull() const noexcept {
            return fill == size;
        }

        WritableBuffer<void> Write() noexcept;
        size_t WriteSome(ConstBuffer<void> src) noexcept;
    };

    BufferPtr head;
    Buffer *tail = nullptr;

    size_t position = 0;

public:
    GrowingBuffer() = default;

    GrowingBuffer(GrowingBuffer &&src) noexcept
        :head(std::move(src.head)), tail(src.tail) {
        src.tail = nullptr;
    }

    GrowingBuffer &operator=(GrowingBuffer &&src) noexcept {
        using std::swap;
        swap(head, src.head);
        swap(tail, src.tail);
        swap(position, src.position);
        return *this;
    }

    bool IsEmpty() const noexcept {
        return tail == nullptr;
    }

    void Clear() noexcept {
        Release();
    }

    /**
     * Release the buffer list, which may now be owned by somebody
     * else.
     */
    void Release() noexcept {
        if (head)
            head.Free();
        tail = nullptr;
        position = 0;
    }

    void *Write(size_t length) noexcept;

    size_t WriteSome(const void *p, size_t length) noexcept;
    void Write(const void *p, size_t length) noexcept;

    void Write(const char *p) noexcept;

    void AppendMoveFrom(GrowingBuffer &&src) noexcept;

    /**
     * Returns the total size of the buffer.
     */
    gcc_pure
    size_t GetSize() const noexcept;

    /**
     * Duplicates the whole buffer (including all chunks) to one
     * contiguous buffer.
     */
    WritableBuffer<void> Dup(struct pool &pool) const noexcept;

    gcc_pure
    ConstBuffer<void> Read() const noexcept;

    /**
     * Skip an arbitrary number of data bytes, which may span over
     * multiple internal buffers.
     */
    void Skip(size_t length) noexcept;

    /**
     * Consume data returned by Read().
     */
    void Consume(size_t length) noexcept;

    void FillBucketList(IstreamBucketList &list) const noexcept;
    size_t ConsumeBucketList(size_t nbytes) noexcept;

private:
    Buffer &AppendBuffer() noexcept;

    void CopyTo(void *dest) const noexcept;

    template<typename F>
    void ForEachBuffer(F &&f) const {
        head.ForEachBuffer(position, std::forward<F>(f));
    }
};

template<typename F>
void
GrowingBuffer::BufferPtr::ForEachBuffer(size_t skip, F &&f) const
{
    for (const auto *i = get(); i != nullptr; i = i->next.get()) {
        ConstBuffer<uint8_t> b(i->data, i->fill);
        if (skip > 0) {
            if (skip >= b.size) {
                skip -= b.size;
                continue;
            } else {
                b.skip_front(skip);
                skip = 0;
            }
        }

        f(b.ToVoid());
    }
}

class GrowingBufferReader {
    GrowingBuffer::BufferPtr buffer;
    size_t position = 0;

public:
    explicit GrowingBufferReader(GrowingBuffer &&gb) noexcept;

    gcc_pure
    bool IsEOF() const noexcept;

    gcc_pure
    size_t Available() const noexcept;

    gcc_pure
    ConstBuffer<void> Read() const noexcept;

    /**
     * Consume data returned by Read().
     */
    void Consume(size_t length) noexcept;

    /**
     * Skip an arbitrary number of data bytes, which may span over
     * multiple internal buffers.
     */
    void Skip(size_t length) noexcept;

    void FillBucketList(IstreamBucketList &list) const noexcept;
    size_t ConsumeBucketList(size_t nbytes) noexcept;

private:
    template<typename F>
    void ForEachBuffer(F &&f) const {
        buffer.ForEachBuffer(position, std::forward<F>(f));
    }
};

#endif
<|endoftext|>