<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkXYZMolReader.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

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

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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 AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/

#include "vtkXYZMolReader.h"

#include "vtkObjectFactory.h"
#include "vtkPoints.h"
#include "vtkIdTypeArray.h"
#include "vtkPolyData.h"

#include <sys/stat.h>

//----------------------------------------------------------------------------
vtkCxxRevisionMacro(vtkXYZMolReader, "1.3");
vtkStandardNewMacro(vtkXYZMolReader);

//----------------------------------------------------------------------------
vtkXYZMolReader::vtkXYZMolReader()
{
  this->TimeStep  = 0;
  this->MaxTimeStep  = 0;
}

//----------------------------------------------------------------------------
vtkXYZMolReader::~vtkXYZMolReader()
{
}

//----------------------------------------------------------------------------
char* vtkXYZMolReader::GetNextLine(FILE* fp, char* line, int maxlen)
{
  int cc;
  int len;
  int comment = 0;
  char* ptr = 0;
  do
    {
    comment = 0;
    if ( !fgets(line, maxlen, fp) )
      {
      //cout << "Problem when reading. EOF?" << endl;
      return 0;
      }
    len = strlen(line);
    for ( cc = 0; cc < len; cc ++ )
      {
      int ch = line[cc];
      if ( ch == '#' )
        {
        comment = 1;
        break;
        }
      else if ( ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' )
        {
        break;
        }
      }
    if ( cc == len )
      {
      comment = 1;
      }
    }
  while ( comment );
  //cout << "Have line that is not a comment: [" << line << "]" << endl;
  len = strlen(line);
  int ft = 0;
  ptr = line;
  for ( cc = 0; cc < len; cc ++ )
    {
    int ch = line[cc];
    if ( !ft && ( ch == ' ' || ch == '\t' ) )
      {
      ptr++;
      }
    else if ( ch == '#' || ch == '\n' || ch == '\r' )
      {
      line[cc] = 0;
      break;
      }
    else
      {
      ft = 1;
      }
    }
  if ( strlen(ptr) == 0 )
    {
    return 0;
    }
  return ptr;
}

//----------------------------------------------------------------------------
int vtkXYZMolReader::GetLine1(const char* line, int *cnt)
{
  char dummy[1024] = "";
  if ( !line || sscanf(line, "%d%s", cnt, dummy) < 1)
    {
    return 0;
    }
  int cc;
  for ( cc = 0; cc < static_cast<int>(strlen(dummy)); ++cc )
    {
    if ( dummy[cc] != ' ' && dummy[cc] != '\t' && dummy[cc] != '\n' &&
        dummy[cc] != '\r' )
      {
      return 0;
      }
    }
  return 1;
}

//----------------------------------------------------------------------------
int vtkXYZMolReader::GetLine2(const char* line, char *name)
{
  char dummy[1024] = "";
  if ( !line || sscanf(line, "%s%s", name, dummy) < 1)
    {
    return 0;
    }
  int cc;
  for ( cc = 0; cc < static_cast<int>(strlen(dummy)); ++cc )
    {
    if ( dummy[cc] != ' ' && dummy[cc] != '\t' && dummy[cc] != '\n' &&
        dummy[cc] != '\r' )
      {
      return 0;
      }
    }
  return 1;
}

//----------------------------------------------------------------------------
int vtkXYZMolReader::GetAtom(const char* line, char* atom, float *x)
{
  char dummy[1024] = "";
  if ( !line || sscanf(line, "%s %f %f %f%s", atom, x, x+1, x+2, dummy) < 4)
    {
    return 0;
    }
  int cc;
  for ( cc = 0; cc < static_cast<int>(strlen(dummy)); ++cc )
    {
    if ( dummy[cc] != ' ' && dummy[cc] != '\t' && dummy[cc] != '\n' &&
        dummy[cc] != '\r' )
      {
      return 0;
      }
    }
  return 1;
}

//----------------------------------------------------------------------------
void vtkXYZMolReader::InsertAtom(const char* atom, float *pos)
{
  this->Points->InsertNextPoint(pos);
  this->AtomType->InsertNextValue(this->MakeAtomType(atom));
}

//----------------------------------------------------------------------------
int vtkXYZMolReader::CanReadFile(const char* name)
{
  if ( !name )
    {
    return 0;
    }

  // First make sure the file exists.  This prevents an empty file
  // from being created on older compilers.
  struct stat fs;
  if(stat(name, &fs) != 0)
    {
    return 0;
    }

  FILE* fp = fopen(name, "r");
  if ( !fp )
    {
    return 0;
    }

  int valid = 0;

  const int maxlen = 1024;
  char buffer[maxlen];
  char comment[maxlen];
  char atom[maxlen];
  char* lptr = 0;
  int num = 0;
  float pos[3];

  lptr = this->GetNextLine(fp, buffer, maxlen);
  if ( this->GetLine1(lptr, &num) )
    {
    // Have header
    lptr = this->GetNextLine(fp, buffer, maxlen);
    if ( this->GetLine2(lptr, comment) )
      {
      lptr = this->GetNextLine(fp, buffer, maxlen);
      if ( this->GetAtom(lptr, atom, pos) )
        {
        valid = 3;
        }
      }
    else if ( this->GetAtom(lptr, atom, pos) )
      {
      valid = 3;
      }
    }
  else
    {
    // No header
    lptr = this->GetNextLine(fp, buffer, maxlen);
    if ( this->GetAtom(lptr, atom, pos) )
      {
      valid = 3;
      }
    }

  fclose(fp);
  return valid;
}

//----------------------------------------------------------------------------
void vtkXYZMolReader::ReadSpecificMolecule(FILE *fp)
{
  const int maxlen = 1024;
  char buffer[maxlen];
  char comment[maxlen];
  char* lptr = 0;

  int have_header = 0;
  int num = 0;
  int cnt = 0;
  int ccnt = 0;
  int rcnt = 0;
  int timestep = 1;

  int selectstep = this->TimeStep;

  float pos[3];
  char atom[maxlen];

  while ( (lptr = this->GetNextLine(fp, buffer, maxlen)) )
    {
    if ( ( cnt == 0 || ccnt == num ) && this->GetLine1(lptr, &num) )
      {
      have_header = 1;
      vtkDebugMacro("Have header. Number of atoms is: " << num);
      ccnt = 0;
      if ( cnt > 0 )
        {
        timestep ++;
        }
      }
    else if ( have_header )
      {
      if ( ccnt == 0 && this->GetLine2(lptr, comment) )
        {
        vtkDebugMacro("Have comment");
        }
      else if ( this->GetAtom(lptr, atom, pos) )
        {
        if ( ccnt >= num )
          {
          vtkErrorMacro("Expecting " << num << " atoms, found: " << ccnt);
          return;
          }
        else
          {
          if ( selectstep == timestep -1 )
            {
            // Got atom with full signature
            this->InsertAtom(atom, pos);
            rcnt ++;
            }
          ccnt ++;
          }
        }
      else
        {
        vtkErrorMacro("Expecting atom, got: " << lptr);
        return;
        }
      }
    else
      {
      if ( this->GetAtom(lptr, atom, pos) )
        {
        // Got atom with simple signature
        this->InsertAtom(atom, pos);
        rcnt ++;
        }
      else
        {
        vtkErrorMacro("Expecting atom, got: " << lptr);
        return;
        }
      }
    ++ cnt;
    }

  // Just some more checking and cleanups
  if ( num == 0 )
    {
    num = rcnt;
    }

  vtkDebugMacro("Number of atoms: " << num << " (" << rcnt << ")");
  if ( num != rcnt )
    {
    vtkErrorMacro("Expecting " << num << " atoms, got " << rcnt);
    return;
    }

  if ( selectstep >= timestep )
    {
    vtkErrorMacro("Only have " << timestep << " time steps");
    return;
    }

  this->SetMaxTimeStep(timestep);
  this->NumberOfAtoms = num;
}

//----------------------------------------------------------------------------
void vtkXYZMolReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  os << indent << "TimeStep: " << this->TimeStep << endl;
  os << indent << "MaxTimeStep: " << this->MaxTimeStep;
}
<commit_msg>BUG: Fix crashing when timestep is greater than maximum<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkXYZMolReader.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

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

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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 AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/

#include "vtkXYZMolReader.h"

#include "vtkObjectFactory.h"
#include "vtkPoints.h"
#include "vtkIdTypeArray.h"
#include "vtkPolyData.h"

#include <sys/stat.h>

//----------------------------------------------------------------------------
vtkCxxRevisionMacro(vtkXYZMolReader, "1.4");
vtkStandardNewMacro(vtkXYZMolReader);

//----------------------------------------------------------------------------
vtkXYZMolReader::vtkXYZMolReader()
{
  this->TimeStep  = 0;
  this->MaxTimeStep  = 0;
}

//----------------------------------------------------------------------------
vtkXYZMolReader::~vtkXYZMolReader()
{
}

//----------------------------------------------------------------------------
char* vtkXYZMolReader::GetNextLine(FILE* fp, char* line, int maxlen)
{
  int cc;
  int len;
  int comment = 0;
  char* ptr = 0;
  do
    {
    comment = 0;
    if ( !fgets(line, maxlen, fp) )
      {
      //cout << "Problem when reading. EOF?" << endl;
      return 0;
      }
    len = strlen(line);
    for ( cc = 0; cc < len; cc ++ )
      {
      int ch = line[cc];
      if ( ch == '#' )
        {
        comment = 1;
        break;
        }
      else if ( ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' )
        {
        break;
        }
      }
    if ( cc == len )
      {
      comment = 1;
      }
    }
  while ( comment );
  //cout << "Have line that is not a comment: [" << line << "]" << endl;
  len = strlen(line);
  int ft = 0;
  ptr = line;
  for ( cc = 0; cc < len; cc ++ )
    {
    int ch = line[cc];
    if ( !ft && ( ch == ' ' || ch == '\t' ) )
      {
      ptr++;
      }
    else if ( ch == '#' || ch == '\n' || ch == '\r' )
      {
      line[cc] = 0;
      break;
      }
    else
      {
      ft = 1;
      }
    }
  if ( strlen(ptr) == 0 )
    {
    return 0;
    }
  return ptr;
}

//----------------------------------------------------------------------------
int vtkXYZMolReader::GetLine1(const char* line, int *cnt)
{
  char dummy[1024] = "";
  if ( !line || sscanf(line, "%d%s", cnt, dummy) < 1)
    {
    return 0;
    }
  int cc;
  for ( cc = 0; cc < static_cast<int>(strlen(dummy)); ++cc )
    {
    if ( dummy[cc] != ' ' && dummy[cc] != '\t' && dummy[cc] != '\n' &&
        dummy[cc] != '\r' )
      {
      return 0;
      }
    }
  return 1;
}

//----------------------------------------------------------------------------
int vtkXYZMolReader::GetLine2(const char* line, char *name)
{
  char dummy[1024] = "";
  if ( !line || sscanf(line, "%s%s", name, dummy) < 1)
    {
    return 0;
    }
  int cc;
  for ( cc = 0; cc < static_cast<int>(strlen(dummy)); ++cc )
    {
    if ( dummy[cc] != ' ' && dummy[cc] != '\t' && dummy[cc] != '\n' &&
        dummy[cc] != '\r' )
      {
      return 0;
      }
    }
  return 1;
}

//----------------------------------------------------------------------------
int vtkXYZMolReader::GetAtom(const char* line, char* atom, float *x)
{
  char dummy[1024] = "";
  if ( !line || sscanf(line, "%s %f %f %f%s", atom, x, x+1, x+2, dummy) < 4)
    {
    return 0;
    }
  int cc;
  for ( cc = 0; cc < static_cast<int>(strlen(dummy)); ++cc )
    {
    if ( dummy[cc] != ' ' && dummy[cc] != '\t' && dummy[cc] != '\n' &&
        dummy[cc] != '\r' )
      {
      return 0;
      }
    }
  return 1;
}

//----------------------------------------------------------------------------
void vtkXYZMolReader::InsertAtom(const char* atom, float *pos)
{
  this->Points->InsertNextPoint(pos);
  this->AtomType->InsertNextValue(this->MakeAtomType(atom));
}

//----------------------------------------------------------------------------
int vtkXYZMolReader::CanReadFile(const char* name)
{
  if ( !name )
    {
    return 0;
    }

  // First make sure the file exists.  This prevents an empty file
  // from being created on older compilers.
  struct stat fs;
  if(stat(name, &fs) != 0)
    {
    return 0;
    }

  FILE* fp = fopen(name, "r");
  if ( !fp )
    {
    return 0;
    }

  int valid = 0;

  const int maxlen = 1024;
  char buffer[maxlen];
  char comment[maxlen];
  char atom[maxlen];
  char* lptr = 0;
  int num = 0;
  float pos[3];

  lptr = this->GetNextLine(fp, buffer, maxlen);
  if ( this->GetLine1(lptr, &num) )
    {
    // Have header
    lptr = this->GetNextLine(fp, buffer, maxlen);
    if ( this->GetLine2(lptr, comment) )
      {
      lptr = this->GetNextLine(fp, buffer, maxlen);
      if ( this->GetAtom(lptr, atom, pos) )
        {
        valid = 3;
        }
      }
    else if ( this->GetAtom(lptr, atom, pos) )
      {
      valid = 3;
      }
    }
  else
    {
    // No header
    lptr = this->GetNextLine(fp, buffer, maxlen);
    if ( this->GetAtom(lptr, atom, pos) )
      {
      valid = 3;
      }
    }

  fclose(fp);
  return valid;
}

//----------------------------------------------------------------------------
void vtkXYZMolReader::ReadSpecificMolecule(FILE *fp)
{
  const int maxlen = 1024;
  char buffer[maxlen];
  char comment[maxlen];
  char* lptr = 0;

  int have_header = 0;
  int num = 0;
  int cnt = 0;
  int ccnt = 0;
  int rcnt = 0;
  int timestep = 1;

  int selectstep = this->TimeStep;

  float pos[3];
  char atom[maxlen];

  this->AtomType->Allocate(1024);
  this->Points->Allocate(1024);

  while ( (lptr = this->GetNextLine(fp, buffer, maxlen)) )
    {
    if ( ( cnt == 0 || ccnt == num ) && this->GetLine1(lptr, &num) )
      {
      have_header = 1;
      vtkDebugMacro("Have header. Number of atoms is: " << num);
      ccnt = 0;
      if ( cnt > 0 )
        {
        timestep ++;
        }
      }
    else if ( have_header )
      {
      if ( ccnt == 0 && this->GetLine2(lptr, comment) )
        {
        vtkDebugMacro("Have comment");
        }
      else if ( this->GetAtom(lptr, atom, pos) )
        {
        if ( ccnt >= num )
          {
          vtkErrorMacro("Expecting " << num << " atoms, found: " << ccnt);
          return;
          }
        else
          {
          if ( selectstep == timestep -1 )
            {
            // Got atom with full signature
            this->InsertAtom(atom, pos);
            rcnt ++;
            }
          ccnt ++;
          }
        }
      else
        {
        vtkErrorMacro("Expecting atom, got: " << lptr);
        return;
        }
      }
    else
      {
      if ( this->GetAtom(lptr, atom, pos) )
        {
        // Got atom with simple signature
        this->InsertAtom(atom, pos);
        rcnt ++;
        }
      else
        {
        vtkErrorMacro("Expecting atom, got: " << lptr);
        return;
        }
      }
    ++ cnt;
    }

  // Just some more checking and cleanups
  if ( num == 0 )
    {
    num = rcnt;
    }

  this->AtomType->Squeeze();
  this->Points->Squeeze();

  if ( selectstep >= timestep )
    {
    this->NumberOfAtoms = 0;
    vtkErrorMacro("Only have " << timestep << " time step(s)");
    return;
    }

  vtkDebugMacro("Number of atoms: " << num << " (" << rcnt << ")");
  if ( num != rcnt )
    {
    this->NumberOfAtoms = 0;
    vtkErrorMacro("Expecting " << num << " atoms, got " << rcnt);
    return;
    }

  this->SetMaxTimeStep(timestep);
  this->NumberOfAtoms = num;
}

//----------------------------------------------------------------------------
void vtkXYZMolReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  os << indent << "TimeStep: " << this->TimeStep << endl;
  os << indent << "MaxTimeStep: " << this->MaxTimeStep;
}
<|endoftext|>


<commit_before>#ifndef ORIGEN_HPP_INCLUDED
#define ORIGEN_HPP_INCLUDED

#define ORIGEN_VERSION "0.8.1"

#ifndef debugger
#define debugger __asm__("int $3");
#endif

#include "origen/utils.hpp"
#include "origen/helpers.hpp"
#include "origen/site.hpp"

namespace Origen {

extern vector<Site> Sites;
Utils::Version version();
Site& site();
Site& site(int site);

}
#endif
<commit_msg>Wrote new version in C++ code<commit_after>#ifndef ORIGEN_HPP_INCLUDED
#define ORIGEN_HPP_INCLUDED

#define ORIGEN_VERSION "0.8.2"

#ifndef debugger
#define debugger __asm__("int $3");
#endif

#include "origen/utils.hpp"
#include "origen/helpers.hpp"
#include "origen/site.hpp"

namespace Origen {

extern vector<Site> Sites;
Utils::Version version();
Site& site();
Site& site(int site);

}
#endif
<|endoftext|>


<commit_before>// demo.cpp
#include "demo.h"

#include <iostream>

#include "demo/render/grapi.h"

namespace demo
{

bool Demo::startup()
{
    return rndr::GrApi::init();
}

void Demo::run()
{
    _window.open();
    _window.activate();
    printf( "OpenGL version is (%s)\n", glGetString( GL_VERSION ) );

    // run while the window is open
    while ( _window.isOpen() )
    {
        glfwPollEvents();

        _window.update();
    }
}

void Demo::shutdown()
{
    rndr::GrApi::terminate();
}

} // End nspc demo<commit_msg>Remove unnecessary includes.<commit_after>// demo.cpp
#include "demo.h"

namespace demo
{

bool Demo::startup()
{
    return rndr::GrApi::init();
}

void Demo::run()
{
    _window.open();
    _window.activate();
    printf( "OpenGL version is (%s)\n", glGetString( GL_VERSION ) );

    // run while the window is open
    while ( _window.isOpen() )
    {
        glfwPollEvents();

        _window.update();
    }
}

void Demo::shutdown()
{
    rndr::GrApi::terminate();
}

} // End nspc demo<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

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

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/
/// @todo Documentation Core/Logging/Log.cc

#include <Core/Logging/Log.h>

#include <log4cpp/Category.hh>
#include <log4cpp/CategoryStream.hh>
#include <log4cpp/Appender.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/Layout.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/Priority.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/BasicLayout.hh>

#include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp>
#include <Core/Utils/Exception.h>

// Includes for platform specific functions to get directory to store temp files and user data
#ifdef _WIN32
#include <shlobj.h>
#include <tlhelp32.h>
#include <windows.h>
#include <LMCons.h>
#include <psapi.h>
#else
#include <stdlib.h>
#include <sys/types.h>
#ifndef __APPLE__
#include <unistd.h>
#include <sys/sysinfo.h>
#else
#include <unistd.h>
#include <sys/utsname.h>
#include <sys/sysctl.h>
#include <sys/param.h>
#include <sys/mount.h>
#endif
#endif

using namespace SCIRun::Core::Logging;

namespace SCIRun
{
  namespace Core
  {
    namespace Logging
    {
      class LogStreamImpl
      {
      public:
        LogStreamImpl(const log4cpp::CategoryStream& s) : stream_(s) {}
        log4cpp::CategoryStream stream_;
      };

      class LogImpl
      {
      public:
        LogImpl() : name_("root"), cppLogger_(log4cpp::Category::getRoot()), latestStream_(new LogStreamImpl(cppLogger_.infoStream()))
        {
          setAppenders();
        }

        explicit LogImpl(const std::string& name) : name_(name), cppLogger_(log4cpp::Category::getInstance(name)), latestStream_(new LogStreamImpl(cppLogger_.infoStream()))
        {
          /// @todo
          setAppenders();
          cppLogger_.setAdditivity(false);
          cppLogger_.setPriority(log4cpp::Priority::INFO);  //?
        }

        void log(LogLevel level, const std::string& msg)
        {
          cppLogger_ << translate(level) << msg;
        }

        Log::Stream& stream(LogLevel level)
        {
          latestStream_ = Log::Stream(new LogStreamImpl(cppLogger_ << translate(level)));
          return latestStream_;
        }

        bool verbose() const
        {
          return cppLogger_.getPriority() == log4cpp::Priority::DEBUG;
        }

        void setVerbose(bool v)
        {
          cppLogger_.setPriority(v ? log4cpp::Priority::DEBUG : log4cpp::Priority::INFO);
        }

        void flush()
        {
          latestStream_.flush();
        }

        log4cpp::Priority::PriorityLevel translate(LogLevel level)
        {
          // Translate pix logging level to cpp logging level
          log4cpp::Priority::PriorityLevel cpp_level = log4cpp::Priority::NOTSET;
          switch (level)
          {
          case NOTSET: // allow fall through
          case EMERG:  cpp_level = log4cpp::Priority::EMERG;  break;
          case ALERT:  cpp_level = log4cpp::Priority::ALERT;  break;
          case CRIT:   cpp_level = log4cpp::Priority::CRIT;   break;
          case ERROR_LOG:  cpp_level = log4cpp::Priority::ERROR;  break;
          case WARN:   cpp_level = log4cpp::Priority::WARN;   break;
          case NOTICE: cpp_level = log4cpp::Priority::NOTICE; break;
          case INFO:   cpp_level = log4cpp::Priority::INFO;   break;
          case DEBUG_LOG:  cpp_level = log4cpp::Priority::DEBUG;  break;
          default:
            THROW_INVALID_ARGUMENT("Unknown log level: " + boost::lexical_cast<std::string>((int)level));
          };
          if (cpp_level == log4cpp::Priority::NOTSET)
          {
            THROW_INVALID_ARGUMENT("Could not set log level.");
          }
          return cpp_level;
        }

        boost::filesystem::path file_;
      private:
        std::string name_;
        log4cpp::Category& cppLogger_;
        Log::Stream latestStream_;

        void setAppenders()
        {
          std::string pattern("%d{%Y-%m-%d %H:%M:%S.%l} %c [%p] %m%n");

          log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout);
          auto layout1 = new log4cpp::PatternLayout();
          std::string backupPattern1 = layout1->getConversionPattern();
          try
          {
            layout1->setConversionPattern(pattern);
          }
          catch (log4cpp::ConfigureFailure& exception)
          {
            /// @todo: log?
            std::cerr << "Caught ConfigureFailure exception: " << exception.what() << std::endl
              << "Restoring original pattern: (" << backupPattern1 << ")" << std::endl;
            layout1->setConversionPattern(backupPattern1);
          }
          appender1->setLayout(layout1);

          file_ = Log::logDirectory() / ("scirun5_" + name_ + ".log");
          log4cpp::Appender *appender2 = new log4cpp::FileAppender("default", file_.string());
          auto layout2 = new log4cpp::PatternLayout();
          std::string backupPattern2 = layout1->getConversionPattern();
          try
          {
            layout2->setConversionPattern(pattern);
          }
          catch (log4cpp::ConfigureFailure& exception)
          {
            /// @todo: log?
            std::cerr << "Caught ConfigureFailure exception: " << exception.what() << std::endl
              << "Restoring original pattern: (" << backupPattern2 << ")" << std::endl;
            layout2->setConversionPattern(backupPattern2);
          }
          appender2->setLayout(layout2);

          cppLogger_.addAppender(appender1);
          cppLogger_.addAppender(appender2);
        }
      };
    }
  }
}

Log::Log() : impl_(new LogImpl)
{
  init();
}

Log::Log(const std::string& name) : impl_(new LogImpl(name))
{
  init();
}

void Log::init()
{
  *this << DEBUG_LOG << "Logging to file: " << impl_->file_.string() << std::endl;
}

boost::filesystem::path Log::directory_(ApplicationHelper().configDirectory());

boost::filesystem::path Log::logDirectory() { return directory_; }
void Log::setLogDirectory(const boost::filesystem::path& dir)
{
  directory_ = dir;
  //std::cout << "Log dir set to " << dir << std::endl;
}

Log& Log::get()
{
  static Log logger;
  return logger;
}

Log& Log::get(const std::string& name)
{
  /// @todo: make thread safe
  static std::map<std::string, boost::shared_ptr<Log>> logs;
  auto i = logs.find(name);
  if (i == logs.end())
  {
    logs[name] = boost::shared_ptr<Log>(new Log(name));
    return *logs[name];
  }
  return *i->second;
}

void Log::flush()
{
  impl_->flush();
}

void Log::log(LogLevel level, const std::string& msg)
{
  impl_->log(level, msg);
}

Log::Stream& SCIRun::Core::Logging::operator<<(Log& log, LogLevel level)
{
  return log.impl_->stream(level);
}

void Log::Stream::stream(const std::string& msg)
{
  impl_->stream_ << msg;
}

void Log::Stream::stream(double x)
{
  impl_->stream_ << x;
}

void Log::Stream::flush()
{
  impl_->stream_.flush();
}

Log::Stream::Stream(LogStreamImpl* impl) : impl_(impl) {}

Log::Stream& SCIRun::Core::Logging::operator<<(Log::Stream& log, const std::string& msg)
{
  log.stream(msg);
  return log;
}

Log::Stream& SCIRun::Core::Logging::operator<<(Log::Stream& log, double x)
{
  log.stream(x);
  return log;
}

//super hacky and dumb. need to figure out proper way
Log::Stream& SCIRun::Core::Logging::operator<<(Log::Stream& log, std::ostream&(*func)(std::ostream&))
{
  log.flush();
  return log;
}

void Log::setVerbose(bool v)
{
  impl_->setVerbose(v);
}

bool Log::verbose() const
{
  return impl_->verbose();
}

//TODO: move

// following ugly code copied from Seg3D.

bool ApplicationHelper::get_user_directory( boost::filesystem::path& user_dir, bool config_path)
{
#ifdef _WIN32
  TCHAR dir[MAX_PATH];

  // Try to create the local application directory
  // If it already exists return the name of the directory.

  if( config_path )
  {
    if ( SUCCEEDED( SHGetFolderPath( 0, CSIDL_LOCAL_APPDATA, 0, 0, dir ) ) )
    {
      user_dir = boost::filesystem::path( dir );
      return true;
    }
    else
    {
      std::cerr << "Could not get user directory.";
      return false;
    }
  }
  else
  {
    if ( SUCCEEDED( SHGetFolderPath( 0, CSIDL_MYDOCUMENTS, 0, 0, dir ) ) )
    {
      user_dir = boost::filesystem::path( dir );
      return true;
    }
    else
    {
      std::cerr << "Could not get user directory.";
      return false;
    }
  }
#else

  if ( getenv( "HOME" ) )
  {
    user_dir = boost::filesystem::path( getenv( "HOME" ) );

    if (! boost::filesystem::exists( user_dir ) )
    {
      std::cerr << "Could not get user directory.";
      return false;
    }

    return true;
  }
  else
  {
    std::cerr << "Could not get user directory.";
    return false;
  }
#endif
}

bool ApplicationHelper::get_user_desktop_directory( boost::filesystem::path& user_desktop_dir )
{
#ifdef _WIN32
  TCHAR dir[MAX_PATH];

  // Try to create the local application directory
  // If it already exists return the name of the directory.

  if ( SUCCEEDED( SHGetFolderPath( 0, CSIDL_DESKTOPDIRECTORY, 0, 0, dir ) ) )
  {
    user_desktop_dir = boost::filesystem::path( dir );
    return true;
  }
  else
  {
    std::cerr << "Could not get user desktop directory.";
    return false;
  }

#else

  if ( getenv( "HOME" ) )
  {
    user_desktop_dir = boost::filesystem::path( getenv( "HOME" ) ) / "Desktop" / "";

    if (! boost::filesystem::exists( user_desktop_dir ) )
    {
      std::cerr << "Could not get user desktop directory.";
      return false;
    }

    return true;
  }
  else
  {
    std::cerr << "Could not get user desktop directory.";
    return false;
  }
#endif
}

bool ApplicationHelper::get_config_directory( boost::filesystem::path& config_dir )
{
  boost::filesystem::path user_dir;
  if ( !( get_user_directory( user_dir, true ) ) ) return false;

#ifdef _WIN32
  config_dir = user_dir / applicationName();
#else
  std::string dot_app_name = std::string( "." ) + applicationName();
  config_dir = user_dir / dot_app_name;
#endif

  if ( !( boost::filesystem::exists( config_dir ) ) )
  {
    if ( !( boost::filesystem::create_directory( config_dir ) ) )
    {
      std::cerr << "Could not create directory: " << config_dir.string() << std::endl;
      return false;
    }

    std::cerr << "Created directory: " << config_dir.string() << std::endl;
  }

  return true;
}

bool ApplicationHelper::get_user_name( std::string& user_name )
{
#ifdef _WIN32
  TCHAR name[UNLEN+1];
  DWORD length = UNLEN;

  if ( GetUserName( name, &length ) )
  {
    user_name = std::string( name );
    return true;
  }
  else
  {
    std::cerr << "Could not resolve user name.";
    return false;
  }
#else
  if ( getenv( "USER" ) )
  {
    user_name = std::string( getenv( "USER" ) );
    return true;
  }
  else
  {
    std::cerr << "Could not resolve user name.";
    return false;
  }
#endif

}

boost::filesystem::path ApplicationHelper::configDirectory()
{
  boost::filesystem::path config;
  if (!get_config_directory(config))
    return boost::filesystem::current_path();
  return config;
}

std::string ApplicationHelper::applicationName()
{
  return "SCIRun";
}

ApplicationHelper::ApplicationHelper()
{
  //boost::filesystem::path::imbue( std::locale( "" ) );
  boost::filesystem::path dummy("boost bug workaround");
  if (dummy.string().empty())
    std::cout << dummy.string() << std::endl;
}
<commit_msg>Fix Mac build<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

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

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/
/// @todo Documentation Core/Logging/Log.cc

#include <Core/Logging/Log.h>

#include <log4cpp/Category.hh>
#include <log4cpp/CategoryStream.hh>
#include <log4cpp/Appender.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/Layout.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/Priority.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/BasicLayout.hh>

#include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp>
#include <Core/Utils/Exception.h>

// Includes for platform specific functions to get directory to store temp files and user data
#ifdef _WIN32
#include <shlobj.h>
#include <tlhelp32.h>
#include <windows.h>
#include <LMCons.h>
#include <psapi.h>
#else
#include <stdlib.h>
#include <sys/types.h>
#ifndef __APPLE__
#include <unistd.h>
#include <sys/sysinfo.h>
#else
#include <unistd.h>
#include <sys/utsname.h>
#include <sys/sysctl.h>
#include <sys/param.h>
#include <sys/mount.h>
#endif
#endif

using namespace SCIRun::Core::Logging;

namespace SCIRun
{
  namespace Core
  {
    namespace Logging
    {
      class LogStreamImpl
      {
      public:
        LogStreamImpl(const log4cpp::CategoryStream& s) : stream_(s) {}
        log4cpp::CategoryStream stream_;
      };

      class LogImpl
      {
      public:
        LogImpl() : name_("root"), cppLogger_(log4cpp::Category::getRoot()), latestStream_(new LogStreamImpl(cppLogger_.infoStream()))
        {
          setAppenders();
        }

        explicit LogImpl(const std::string& name) : name_(name), cppLogger_(log4cpp::Category::getInstance(name)), latestStream_(new LogStreamImpl(cppLogger_.infoStream()))
        {
          /// @todo
          setAppenders();
          cppLogger_.setAdditivity(false);
          cppLogger_.setPriority(log4cpp::Priority::INFO);  //?
        }

        void log(LogLevel level, const std::string& msg)
        {
          cppLogger_ << translate(level) << msg;
        }

        Log::Stream& stream(LogLevel level)
        {
          latestStream_ = Log::Stream(new LogStreamImpl(cppLogger_ << translate(level)));
          return latestStream_;
        }

        bool verbose() const
        {
          return cppLogger_.getPriority() == log4cpp::Priority::DEBUG;
        }

        void setVerbose(bool v)
        {
          cppLogger_.setPriority(v ? log4cpp::Priority::DEBUG : log4cpp::Priority::INFO);
        }

        void flush()
        {
          latestStream_.flush();
        }

        log4cpp::Priority::PriorityLevel translate(LogLevel level)
        {
          // Translate pix logging level to cpp logging level
          log4cpp::Priority::PriorityLevel cpp_level = log4cpp::Priority::NOTSET;
          switch (level)
          {
          case NOTSET: // allow fall through
          case EMERG:  cpp_level = log4cpp::Priority::EMERG;  break;
          case ALERT:  cpp_level = log4cpp::Priority::ALERT;  break;
          case CRIT:   cpp_level = log4cpp::Priority::CRIT;   break;
          case ERROR_LOG:  cpp_level = log4cpp::Priority::ERROR;  break;
          case WARN:   cpp_level = log4cpp::Priority::WARN;   break;
          case NOTICE: cpp_level = log4cpp::Priority::NOTICE; break;
          case INFO:   cpp_level = log4cpp::Priority::INFO;   break;
          case DEBUG_LOG:  cpp_level = log4cpp::Priority::DEBUG;  break;
          default:
            THROW_INVALID_ARGUMENT("Unknown log level: " + boost::lexical_cast<std::string>((int)level));
          };
          if (cpp_level == log4cpp::Priority::NOTSET)
          {
            THROW_INVALID_ARGUMENT("Could not set log level.");
          }
          return cpp_level;
        }

        boost::filesystem::path file_;
      private:
        std::string name_;
        log4cpp::Category& cppLogger_;
        Log::Stream latestStream_;

        void setAppenders()
        {
          std::string pattern("%d{%Y-%m-%d %H:%M:%S.%l} %c [%p] %m%n");

          log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout);
          auto layout1 = new log4cpp::PatternLayout();
          std::string backupPattern1 = layout1->getConversionPattern();
          try
          {
            layout1->setConversionPattern(pattern);
          }
          catch (log4cpp::ConfigureFailure& exception)
          {
            /// @todo: log?
            std::cerr << "Caught ConfigureFailure exception: " << exception.what() << std::endl
              << "Restoring original pattern: (" << backupPattern1 << ")" << std::endl;
            layout1->setConversionPattern(backupPattern1);
          }
          appender1->setLayout(layout1);

          file_ = Log::logDirectory() / ("scirun5_" + name_ + ".log");
          log4cpp::Appender *appender2 = new log4cpp::FileAppender("default", file_.string());
          auto layout2 = new log4cpp::PatternLayout();
          std::string backupPattern2 = layout1->getConversionPattern();
          try
          {
            layout2->setConversionPattern(pattern);
          }
          catch (log4cpp::ConfigureFailure& exception)
          {
            /// @todo: log?
            std::cerr << "Caught ConfigureFailure exception: " << exception.what() << std::endl
              << "Restoring original pattern: (" << backupPattern2 << ")" << std::endl;
            layout2->setConversionPattern(backupPattern2);
          }
          appender2->setLayout(layout2);

          cppLogger_.addAppender(appender1);
          cppLogger_.addAppender(appender2);
        }
      };
    }
  }
}

Log::Log() : impl_(new LogImpl)
{
  init();
}

Log::Log(const std::string& name) : impl_(new LogImpl(name))
{
  init();
}

void Log::init()
{
  *this << DEBUG_LOG << "Logging to file: " << impl_->file_.string() << std::endl;
}

boost::filesystem::path Log::directory_(ApplicationHelper().configDirectory());

boost::filesystem::path Log::logDirectory() { return directory_; }
void Log::setLogDirectory(const boost::filesystem::path& dir)
{
  directory_ = dir;
  //std::cout << "Log dir set to " << dir << std::endl;
}

Log& Log::get()
{
  static Log logger;
  return logger;
}

Log& Log::get(const std::string& name)
{
  /// @todo: make thread safe
  static std::map<std::string, boost::shared_ptr<Log>> logs;
  auto i = logs.find(name);
  if (i == logs.end())
  {
    logs[name] = boost::shared_ptr<Log>(new Log(name));
    return *logs[name];
  }
  return *i->second;
}

void Log::flush()
{
  impl_->flush();
}

void Log::log(LogLevel level, const std::string& msg)
{
  impl_->log(level, msg);
}

Log::Stream& SCIRun::Core::Logging::operator<<(Log& log, LogLevel level)
{
  return log.impl_->stream(level);
}

void Log::Stream::stream(const std::string& msg)
{
  impl_->stream_ << msg;
}

void Log::Stream::stream(double x)
{
  impl_->stream_ << x;
}

void Log::Stream::flush()
{
  impl_->stream_.flush();
}

Log::Stream::Stream(LogStreamImpl* impl) : impl_(impl) {}

Log::Stream& SCIRun::Core::Logging::operator<<(Log::Stream& log, const std::string& msg)
{
  log.stream(msg);
  return log;
}

Log::Stream& SCIRun::Core::Logging::operator<<(Log::Stream& log, double x)
{
  log.stream(x);
  return log;
}

//super hacky and dumb. need to figure out proper way
Log::Stream& SCIRun::Core::Logging::operator<<(Log::Stream& log, std::ostream&(*func)(std::ostream&))
{
  log.flush();
  return log;
}

void Log::setVerbose(bool v)
{
  impl_->setVerbose(v);
}

bool Log::verbose() const
{
  return impl_->verbose();
}

//TODO: move

// following ugly code copied from Seg3D.

bool ApplicationHelper::get_user_directory( boost::filesystem::path& user_dir, bool config_path)
{
#ifdef _WIN32
  TCHAR dir[MAX_PATH];

  // Try to create the local application directory
  // If it already exists return the name of the directory.

  if( config_path )
  {
    if ( SUCCEEDED( SHGetFolderPath( 0, CSIDL_LOCAL_APPDATA, 0, 0, dir ) ) )
    {
      user_dir = boost::filesystem::path( dir );
      return true;
    }
    else
    {
      std::cerr << "Could not get user directory.";
      return false;
    }
  }
  else
  {
    if ( SUCCEEDED( SHGetFolderPath( 0, CSIDL_MYDOCUMENTS, 0, 0, dir ) ) )
    {
      user_dir = boost::filesystem::path( dir );
      return true;
    }
    else
    {
      std::cerr << "Could not get user directory.";
      return false;
    }
  }
#else

  if ( getenv( "HOME" ) )
  {
    user_dir = boost::filesystem::path( getenv( "HOME" ) );

    if (! boost::filesystem::exists( user_dir ) )
    {
      std::cerr << "Could not get user directory.";
      return false;
    }

    return true;
  }
  else
  {
    std::cerr << "Could not get user directory.";
    return false;
  }
#endif
}

bool ApplicationHelper::get_user_desktop_directory( boost::filesystem::path& user_desktop_dir )
{
#ifdef _WIN32
  TCHAR dir[MAX_PATH];

  // Try to create the local application directory
  // If it already exists return the name of the directory.

  if ( SUCCEEDED( SHGetFolderPath( 0, CSIDL_DESKTOPDIRECTORY, 0, 0, dir ) ) )
  {
    user_desktop_dir = boost::filesystem::path( dir );
    return true;
  }
  else
  {
    std::cerr << "Could not get user desktop directory.";
    return false;
  }

#else

  if ( getenv( "HOME" ) )
  {
    user_desktop_dir = boost::filesystem::path( getenv( "HOME" ) ) / "Desktop" / "";

    if (! boost::filesystem::exists( user_desktop_dir ) )
    {
      std::cerr << "Could not get user desktop directory.";
      return false;
    }

    return true;
  }
  else
  {
    std::cerr << "Could not get user desktop directory.";
    return false;
  }
#endif
}

bool ApplicationHelper::get_config_directory( boost::filesystem::path& config_dir )
{
  boost::filesystem::path user_dir;
  if ( !( get_user_directory( user_dir, true ) ) ) return false;

#ifdef _WIN32
  config_dir = user_dir / applicationName();
#else
  std::string dot_app_name = std::string( "." ) + applicationName();
  config_dir = user_dir / dot_app_name;
#endif

  if ( !( boost::filesystem::exists( config_dir ) ) )
  {
    if ( !( boost::filesystem::create_directory( config_dir ) ) )
    {
      std::cerr << "Could not create directory: " << config_dir.string() << std::endl;
      return false;
    }

    std::cerr << "Created directory: " << config_dir.string() << std::endl;
  }

  return true;
}

bool ApplicationHelper::get_user_name( std::string& user_name )
{
#ifdef _WIN32
  TCHAR name[UNLEN+1];
  DWORD length = UNLEN;

  if ( GetUserName( name, &length ) )
  {
    user_name = std::string( name );
    return true;
  }
  else
  {
    std::cerr << "Could not resolve user name.";
    return false;
  }
#else
  if ( getenv( "USER" ) )
  {
    user_name = std::string( getenv( "USER" ) );
    return true;
  }
  else
  {
    std::cerr << "Could not resolve user name.";
    return false;
  }
#endif

}

boost::filesystem::path ApplicationHelper::configDirectory()
{
  boost::filesystem::path config;
  if (!get_config_directory(config))
    return boost::filesystem::current_path();
  return config;
}

std::string ApplicationHelper::applicationName()
{
  return "SCIRun";
}

ApplicationHelper::ApplicationHelper()
{
#if WIN32
  boost::filesystem::path::imbue( std::locale( "" ) );
#endif
  boost::filesystem::path dummy("boost bug workaround");
  if (dummy.string().empty())
    std::cout << dummy.string() << std::endl;
}
<|endoftext|>


<commit_before>/*
 * bacteria-core, core for cellular automaton
 * Copyright (C) 2016 Pavel Dolgov
 *
 * See the LICENSE file for terms of use.
 */

#ifndef CORE_CONSTANTS_HPP_
#define CORE_CONSTANTS_HPP_

/** Mass increase per one 'eat' command */
const int EAT_MASS = 1;

const int MAX_COMMANDS_PER_INSTRUCTION = 100;

const int MIN_COMMANDS_PER_INSTRUCTION = 1;

/** Maximum randomly generated number of actions (per instruction) */
const int RANDOM_MAX_ACTIONS = 5;

/** Maximum number of actions per move */
const int MAX_ACTIONS = 1;

/** Maximum number of pseudo actions per move */
const int MAX_PSEUDO_ACTIONS = 30;

/** Default mass of bacteria */
const int DEFAULT_MASS = 5;

/** Minimum width of board */
const int MIN_WIDTH = 5;

/** Maximum width of board */
const int MAX_WIDTH = 500;

/** Minimum height of board */
const int MIN_HEIGHT = 5;

/** Maximum height of board */
const int MAX_HEIGHT = 500;

#endif
<commit_msg>Add new constant GO_MASS<commit_after>/*
 * bacteria-core, core for cellular automaton
 * Copyright (C) 2016 Pavel Dolgov
 *
 * See the LICENSE file for terms of use.
 */

#ifndef CORE_CONSTANTS_HPP_
#define CORE_CONSTANTS_HPP_

/** Mass increase per one 'eat' command */
const int EAT_MASS = 1;

/** Mass increase per one 'go' command */
const int GO_MASS = -1;

const int MAX_COMMANDS_PER_INSTRUCTION = 100;

const int MIN_COMMANDS_PER_INSTRUCTION = 1;

/** Maximum randomly generated number of actions (per instruction) */
const int RANDOM_MAX_ACTIONS = 5;

/** Maximum number of actions per move */
const int MAX_ACTIONS = 1;

/** Maximum number of pseudo actions per move */
const int MAX_PSEUDO_ACTIONS = 30;

/** Default mass of bacteria */
const int DEFAULT_MASS = 5;

/** Minimum width of board */
const int MIN_WIDTH = 5;

/** Maximum width of board */
const int MAX_WIDTH = 500;

/** Minimum height of board */
const int MIN_HEIGHT = 5;

/** Maximum height of board */
const int MAX_HEIGHT = 500;

#endif
<|endoftext|>


<commit_before><commit_msg>fdo#74702 DrawTransformedBitmapEx simplified<commit_after><|endoftext|>


<commit_before>// 26 june 2017
#define UNICODE
#define _UNICODE
#define STRICT
#define STRICT_TYPED_ITEMIDS
#define WINVER			0x0600
#define _WIN32_WINNT		0x0600
#define _WIN32_WINDOWS	0x0600
#define _WIN32_IE			0x0700
#define NTDDI_VERSION		0x06000000
#include <windows.h>
#include <usp10.h>
#include <d2d1.h>
#include <dwrite.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>

// build:
// msvc: cl winunicodeshapetest.cpp -EHsc -W4 -Zi -link -debug user32.lib kernel32.lib usp10.lib gdi32.lib ole32.lib dwrite.lib shell32.lib
// mingw: TODO

void die(const char *msg, HRESULT hr)
{
	fprintf(stderr, "%s: 0x%08I32X\n", msg, hr);
	exit(1);
}

void dieLE(const char *msg)
{
	DWORD le;
	HRESULT hr;

	le = GetLastError();
	hr = HRESULT_FROM_WIN32(le);
	if (le == 0)
		hr = E_FAIL;
	die(msg, hr);
}

struct scriptItemizeParams {
	WCHAR *pwcInChars;
	int cInChars;
	int cMaxItems;
	const SCRIPT_CONTROL *psControl;
	const SCRIPT_STATE *psState;
	SCRIPT_ITEM *pItems;
	OPENTYPE_TAG *pScriptTags;
	int *pcItems;
};

BOOL doScriptItemize(struct scriptItemizeParams *p)
{
	HRESULT hr;

	hr = ScriptItemize(p->pwcInChars, p->cInChars,
		p->cMaxItems, p->psControl, p->psState,
		p->pItems, p->pcItems);
	if (hr == S_OK)
		return TRUE;
	if (hr != E_OUTOFMEMORY)
		die("error calling ScriptItemize()", hr);
	return FALSE;
}

BOOL doScriptItemizeOpenType(struct scriptItemizeParams *p)
{
	HRESULT hr;

	hr = ScriptItemizeOpenType(p->pwcInChars, p->cInChars,
		p->cMaxItems, p->psControl, p->psState,
		p->pItems, p->pScriptTags, p->pcItems);
	if (hr == S_OK)
		return TRUE;
	if (hr != E_OUTOFMEMORY)
		die("error calling ScriptItemizeOpenType()", hr);
	return FALSE;
}

struct scriptShapeParams {
	HDC hdc;
	SCRIPT_CACHE *psc;
	const WCHAR *pwcChars;
	int cChars;
	int cMaxGlyphs;
	SCRIPT_ANALYSIS *psa;
	WORD *pwOutGlyphs;
	WORD *pwLogClust;
	SCRIPT_VISATTR *psva;
	int *pcGlyphs;

	OPENTYPE_TAG tagScript;
	OPENTYPE_TAG tagLangSys;
	int *rcRangeChars;
	TEXTRANGE_PROPERTIES **rpRangeProperties;
	int cRanges;
	SCRIPT_CHARPROP *pCharProps;
	SCRIPT_GLYPHPROP *pOutGlyphProps;
};

BOOL doScriptShape(struct scriptShapeParams *p)
{
	HRESULT hr;

	hr = ScriptShape(p->hdc, p->psc, p->pwcChars, p->cChars,
		p->cMaxGlyphs, p->psa,
		p->pwOutGlyphs, p->pwLogClust, p->psva,
		p->pcGlyphs);
	if (hr == S_OK)
		return TRUE;
	if (hr != E_OUTOFMEMORY)
		die("error calling ScriptShape()", hr);
	return FALSE;
}

BOOL doScriptShapeOpenType(struct scriptShapeParams *p)
{
	HRESULT hr;

	hr = ScriptShapeOpenType(p->hdc, p->psc, p->psa,
		p->tagScript, p->tagLangSys,
		p->rcRangeChars, p->rpRangeProperties, p->cRanges,
		p->pwcChars, p->cChars, p->cMaxGlyphs,
		p->pwLogClust, p->pCharProps, p->pwOutGlyphs,
		p->pOutGlyphProps, p->pcGlyphs);
	if (hr == S_OK)
		return TRUE;
	if (hr != E_OUTOFMEMORY)
		die("error calling ScriptShapeOpenType()", hr);
	return FALSE;
}

void uniscribeOnly(HDC dc, WCHAR *string, int len, BOOL (*itemize)(struct scriptItemizeParams *p), BOOL (*shape)(struct scriptShapeParams *p), const char *label)
{
	SCRIPT_CONTROL scriptControl;
	SCRIPT_STATE scriptState;
	SCRIPT_ITEM *items;
	OPENTYPE_TAG *ottags;
	int nItems, nActualItems;
	SCRIPT_CACHE cache;
	int i;
	std::vector<WORD> glyphs;
	size_t gi;

	nItems = len + 2;
	for (;;) {
		struct scriptItemizeParams p;

		items = new SCRIPT_ITEM[nItems + 1];
		ottags = new OPENTYPE_TAG[nItems];
		ZeroMemory(items, (nItems + 1) * sizeof (SCRIPT_ITEM));
		ZeroMemory(&scriptControl, sizeof (SCRIPT_CONTROL));
		ZeroMemory(&scriptState, sizeof (SCRIPT_STATE));
		ZeroMemory(ottags, nItems * sizeof (OPENTYPE_TAG));
		p.pwcInChars = string;
		p.cInChars = len;
		p.cMaxItems = nItems;
		p.psControl = &scriptControl;
		p.psState = &scriptState;
		p.pItems = items;
		p.pScriptTags = ottags;
		p.pcItems = &nActualItems;
		if ((*itemize)(&p))
			break;
		delete[] ottags;
		delete[] items;
		nItems *= 2;
	}
	// TODO call ScriptLayout() here?
	// TODO reset cache every time ScriptShape() is called so as to have no cache whatsoever?
	cache = NULL;
	for (i = 0; i < nActualItems; i++) {
		int nChars;
		WORD *logclusts;
		WORD *glyphbuf;
		SCRIPT_VISATTR *sva;
		SCRIPT_CHARPROP *charProps;
		SCRIPT_GLYPHPROP *glyphProps;
		int nGlyphs, nActualGlyphs;
		int j;

		nChars = items[i + 1].iCharPos - items[i].iCharPos;
		logclusts = new WORD[nChars];
		charProps = new SCRIPT_CHARPROP[nChars];
		nGlyphs = 1.5 * nChars + 16;
		for (;;) {
			scriptShapeParams p;

			glyphbuf = new WORD[nGlyphs];
			sva = new SCRIPT_VISATTR[nGlyphs];
			glyphProps = new SCRIPT_GLYPHPROP[nGlyphs];
			ZeroMemory(logclusts, nChars * sizeof (WORD));
			ZeroMemory(glyphbuf, nGlyphs * sizeof (WORD));
			ZeroMemory(sva, nGlyphs * sizeof (SCRIPT_VISATTR));
			ZeroMemory(charProps, nChars * sizeof (SCRIPT_CHARPROP));
			ZeroMemory(glyphProps, nGlyphs * sizeof (SCRIPT_GLYPHPROP));
			p.hdc = dc;
			p.psc = &cache;
			p.pwcChars = string + items[i].iCharPos;
			p.cChars = nChars;
			p.cMaxGlyphs = nGlyphs;
			p.psa = &(items[i].a);
			p.pwOutGlyphs = glyphbuf;
			p.pwLogClust = logclusts;
			p.psva = sva;
			p.pcGlyphs = &nActualGlyphs;
			p.tagScript = ottags[i];
			// 'dflt' in little-endian; see https://github.com/emacs-mirror/emacs/blob/master/src/w32uniscribe.c
			p.tagLangSys = 0x746C6664;
			p.rcRangeChars = NULL;			// TODO
			p.rpRangeProperties = NULL;		// TODO
			p.cRanges = 0;					// TODO
			p.pCharProps = charProps;
			p.pOutGlyphProps = glyphProps;
			if ((*shape)(&p))
				break;
			delete[] glyphProps;
			delete[] sva;
			delete[] glyphbuf;
			nGlyphs *= 2;
		}
		for (j = 0; j < nActualGlyphs; j++)
			glyphs.push_back(glyphbuf[j]);
		delete[] glyphProps;
		delete[] charProps;
		delete[] sva;
		delete[] glyphbuf;
		delete[] logclusts;
	}
	// TODO do we call ScriptLayout() *here* instead?
	delete[] ottags;
	delete[] items;

	printf("%s:", label);
	for (gi = 0; gi < glyphs.size(); gi++)
		printf(" %hu", glyphs[gi]);
	printf("\n");
}

int main(void)
{
	int argc;
	LPWSTR *argv;
	WCHAR *fontname, *string;
	int len;
	HDC dc;
	HFONT font, prevfont;
	HRESULT hr;

	// TODO would using wmain() be adequate?
	argv = CommandLineToArgvW(GetCommandLineW(), &argc);
	if (argv == NULL)
		dieLE("error getting command-line arguments");
	if (argc != 3) {
		fprintf(stderr, "usage: %ws font string\n", argv[0]);
		return 1;
	}
	fontname = argv[1];
	string = argv[2];
	len = wcslen(string);

	// DirectWrite requires COM
	hr = CoInitialize(NULL);
	if (hr != S_OK)
		die("error initializing COM", hr);
	// Uniscribe requires a device context with the font to use
	dc = GetDC(NULL);
	if (dc == NULL)
		dieLE("error getting screen HDC for Uniscribe");
	// TODO DEFAULT_CHARSET might affect the results we get
	font = CreateFontW(0, 0, 0, 0, 0, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fontname);
	if (font == NULL)
		dieLE("error creating font for Uniscribe");
	prevfont = (HFONT) SelectObject(dc, font);
	if (prevfont == NULL)
		dieLE("error selecting font into HDC for Uniscribe");

	uniscribeOnly(dc, string, len,
		doScriptItemize, doScriptShape, "Uniscribe");
	uniscribeOnly(dc, string, len,
		doScriptItemizeOpenType, doScriptShapeOpenType, "Uniscribe OpenType");

	SelectObject(dc, prevfont);
	DeleteObject(font);
	ReleaseDC(NULL, dc);
	CoUninitialize();
	return 0;
}
<commit_msg>Added features to the Windows Unicode shaper test.<commit_after>// 26 june 2017
#define UNICODE
#define _UNICODE
#define STRICT
#define STRICT_TYPED_ITEMIDS
#define WINVER			0x0600
#define _WIN32_WINNT		0x0600
#define _WIN32_WINDOWS	0x0600
#define _WIN32_IE			0x0700
#define NTDDI_VERSION		0x06000000
#include <windows.h>
#include <usp10.h>
#include <d2d1.h>
#include <dwrite.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>

// build:
// msvc: cl winunicodeshapetest.cpp -EHsc -W4 -Zi -link -debug user32.lib kernel32.lib usp10.lib gdi32.lib ole32.lib dwrite.lib shell32.lib
// mingw: TODO

void die(const char *msg, HRESULT hr)
{
	fprintf(stderr, "%s: 0x%08I32X\n", msg, hr);
	exit(1);
}

void dieLE(const char *msg)
{
	DWORD le;
	HRESULT hr;

	le = GetLastError();
	hr = HRESULT_FROM_WIN32(le);
	if (le == 0)
		hr = E_FAIL;
	die(msg, hr);
}

class featurePreparer {
	std::vector<OPENTYPE_TAG> tags;
	std::vector<LONG> values;
	bool prepared;
	OPENTYPE_FEATURE_RECORD *otfr;
	TEXTRANGE_PROPERTIES *tr;
public:
	TEXTRANGE_PROPERTIES **usRangeProperties;
	int *usRangeChars;
	int usRanges;

	featurePreparer()
	{
		this->prepared = false;
		this->otfr = NULL;
		this->tr = NULL;
		this->usRangeProperties = NULL;
		this->usRangeChars = NULL;
		this->usRanges = 0;
	}

	~featurePreparer()
	{
		if (this->prepared) {
			delete[] this->usRangeChars;
			delete[] this->usRangeProperties;
			delete this->tr;
			delete[] this->otfr;
		}
	}

	void add(char a, char b, char c, char d, LONG value)
	{
		this->tags.push_back((OPENTYPE_TAG) DWRITE_MAKE_OPENTYPE_TAG(a, b, c, d));
		this->values.push_back(value);
	}

	void prepare(size_t len)
	{
		size_t i, n;

		this->prepared = true;
		n = this->tags.size();
		this->otfr = new OPENTYPE_FEATURE_RECORD[n];
		for (i = 0; i < n; i++) {
			this->otfr[i].tagFeature = this->tags[i];
			this->otfr[i].lParameter = this->values[i];
		}
		this->tr = new TEXTRANGE_PROPERTIES;
		this->tr->potfRecords = this->otfr;
		this->tr->cotfRecords = n;
		this->usRangeProperties = new TEXTRANGE_PROPERTIES *[1];
		this->usRangeProperties[0] = this->tr;
		this->usRangeChars = new int[1];
		this->usRangeChars[0] = len;
		this->usRanges = 1;
	}
};

struct scriptItemizeParams {
	WCHAR *pwcInChars;
	int cInChars;
	int cMaxItems;
	const SCRIPT_CONTROL *psControl;
	const SCRIPT_STATE *psState;
	SCRIPT_ITEM *pItems;
	OPENTYPE_TAG *pScriptTags;
	int *pcItems;
};

BOOL doScriptItemize(struct scriptItemizeParams *p)
{
	HRESULT hr;

	hr = ScriptItemize(p->pwcInChars, p->cInChars,
		p->cMaxItems, p->psControl, p->psState,
		p->pItems, p->pcItems);
	if (hr == S_OK)
		return TRUE;
	if (hr != E_OUTOFMEMORY)
		die("error calling ScriptItemize()", hr);
	return FALSE;
}

BOOL doScriptItemizeOpenType(struct scriptItemizeParams *p)
{
	HRESULT hr;

	hr = ScriptItemizeOpenType(p->pwcInChars, p->cInChars,
		p->cMaxItems, p->psControl, p->psState,
		p->pItems, p->pScriptTags, p->pcItems);
	if (hr == S_OK)
		return TRUE;
	if (hr != E_OUTOFMEMORY)
		die("error calling ScriptItemizeOpenType()", hr);
	return FALSE;
}

struct scriptShapeParams {
	HDC hdc;
	SCRIPT_CACHE *psc;
	const WCHAR *pwcChars;
	int cChars;
	int cMaxGlyphs;
	SCRIPT_ANALYSIS *psa;
	WORD *pwOutGlyphs;
	WORD *pwLogClust;
	SCRIPT_VISATTR *psva;
	int *pcGlyphs;

	OPENTYPE_TAG tagScript;
	OPENTYPE_TAG tagLangSys;
	int *rcRangeChars;
	TEXTRANGE_PROPERTIES **rpRangeProperties;
	int cRanges;
	SCRIPT_CHARPROP *pCharProps;
	SCRIPT_GLYPHPROP *pOutGlyphProps;
};

BOOL doScriptShape(struct scriptShapeParams *p)
{
	HRESULT hr;

	hr = ScriptShape(p->hdc, p->psc, p->pwcChars, p->cChars,
		p->cMaxGlyphs, p->psa,
		p->pwOutGlyphs, p->pwLogClust, p->psva,
		p->pcGlyphs);
	if (hr == S_OK)
		return TRUE;
	if (hr != E_OUTOFMEMORY)
		die("error calling ScriptShape()", hr);
	return FALSE;
}

BOOL doScriptShapeOpenType(struct scriptShapeParams *p)
{
	HRESULT hr;

	hr = ScriptShapeOpenType(p->hdc, p->psc, p->psa,
		p->tagScript, p->tagLangSys,
		p->rcRangeChars, p->rpRangeProperties, p->cRanges,
		p->pwcChars, p->cChars, p->cMaxGlyphs,
		p->pwLogClust, p->pCharProps, p->pwOutGlyphs,
		p->pOutGlyphProps, p->pcGlyphs);
	if (hr == S_OK)
		return TRUE;
	if (hr != E_OUTOFMEMORY)
		die("error calling ScriptShapeOpenType()", hr);
	return FALSE;
}

void uniscribeOnly(HDC dc, WCHAR *string, int len, featurePreparer *features, BOOL (*itemize)(struct scriptItemizeParams *p), BOOL (*shape)(struct scriptShapeParams *p), const char *label)
{
	SCRIPT_CONTROL scriptControl;
	SCRIPT_STATE scriptState;
	SCRIPT_ITEM *items;
	OPENTYPE_TAG *ottags;
	int nItems, nActualItems;
	SCRIPT_CACHE cache;
	int i;
	std::vector<WORD> glyphs;
	size_t gi;

	nItems = len + 2;
	for (;;) {
		struct scriptItemizeParams p;

		items = new SCRIPT_ITEM[nItems + 1];
		ottags = new OPENTYPE_TAG[nItems];
		ZeroMemory(items, (nItems + 1) * sizeof (SCRIPT_ITEM));
		ZeroMemory(&scriptControl, sizeof (SCRIPT_CONTROL));
		ZeroMemory(&scriptState, sizeof (SCRIPT_STATE));
		ZeroMemory(ottags, nItems * sizeof (OPENTYPE_TAG));
		p.pwcInChars = string;
		p.cInChars = len;
		p.cMaxItems = nItems;
		p.psControl = &scriptControl;
		p.psState = &scriptState;
		p.pItems = items;
		p.pScriptTags = ottags;
		p.pcItems = &nActualItems;
		if ((*itemize)(&p))
			break;
		delete[] ottags;
		delete[] items;
		nItems *= 2;
	}
	// TODO call ScriptLayout() here?
	// TODO reset cache every time ScriptShape() is called so as to have no cache whatsoever?
	cache = NULL;
	for (i = 0; i < nActualItems; i++) {
		int nChars;
		WORD *logclusts;
		WORD *glyphbuf;
		SCRIPT_VISATTR *sva;
		SCRIPT_CHARPROP *charProps;
		SCRIPT_GLYPHPROP *glyphProps;
		int nGlyphs, nActualGlyphs;
		int j;

		nChars = items[i + 1].iCharPos - items[i].iCharPos;
		logclusts = new WORD[nChars];
		charProps = new SCRIPT_CHARPROP[nChars];
		nGlyphs = 1.5 * nChars + 16;
		for (;;) {
			scriptShapeParams p;

			glyphbuf = new WORD[nGlyphs];
			sva = new SCRIPT_VISATTR[nGlyphs];
			glyphProps = new SCRIPT_GLYPHPROP[nGlyphs];
			ZeroMemory(logclusts, nChars * sizeof (WORD));
			ZeroMemory(glyphbuf, nGlyphs * sizeof (WORD));
			ZeroMemory(sva, nGlyphs * sizeof (SCRIPT_VISATTR));
			ZeroMemory(charProps, nChars * sizeof (SCRIPT_CHARPROP));
			ZeroMemory(glyphProps, nGlyphs * sizeof (SCRIPT_GLYPHPROP));
			p.hdc = dc;
			p.psc = &cache;
			p.pwcChars = string + items[i].iCharPos;
			p.cChars = nChars;
			p.cMaxGlyphs = nGlyphs;
			p.psa = &(items[i].a);
			p.pwOutGlyphs = glyphbuf;
			p.pwLogClust = logclusts;
			p.psva = sva;
			p.pcGlyphs = &nActualGlyphs;
			p.tagScript = ottags[i];
			// 'dflt' in little-endian; see https://github.com/emacs-mirror/emacs/blob/master/src/w32uniscribe.c
			p.tagLangSys = 0x746C6664;
			p.rcRangeChars = NULL;
			p.rpRangeProperties = NULL;
			p.cRanges = 0;
			if (features != NULL) {
				p.rcRangeChars = features->usRangeChars;
				p.rpRangeProperties = features->usRangeProperties;
				p.cRanges = features->usRanges;
			}
			p.pCharProps = charProps;
			p.pOutGlyphProps = glyphProps;
			if ((*shape)(&p))
				break;
			delete[] glyphProps;
			delete[] sva;
			delete[] glyphbuf;
			nGlyphs *= 2;
		}
		for (j = 0; j < nActualGlyphs; j++)
			glyphs.push_back(glyphbuf[j]);
		delete[] glyphProps;
		delete[] charProps;
		delete[] sva;
		delete[] glyphbuf;
		delete[] logclusts;
	}
	// TODO do we call ScriptLayout() *here* instead?
	delete[] ottags;
	delete[] items;

	printf("%s:", label);
	for (gi = 0; gi < glyphs.size(); gi++)
		printf(" %hu", glyphs[gi]);
	printf("\n");
}

int main(void)
{
	int argc;
	LPWSTR *argv;
	WCHAR *fontname, *string;
	int len;
	HDC dc;
	HFONT font, prevfont;
	featurePreparer *features;
	HRESULT hr;

	// TODO would using wmain() be adequate?
	argv = CommandLineToArgvW(GetCommandLineW(), &argc);
	if (argv == NULL)
		dieLE("error getting command-line arguments");
	if (argc != 3) {
		fprintf(stderr, "usage: %ws font string\n", argv[0]);
		return 1;
	}
	fontname = argv[1];
	string = argv[2];
	len = wcslen(string);

	// DirectWrite requires COM
	hr = CoInitialize(NULL);
	if (hr != S_OK)
		die("error initializing COM", hr);
	// Uniscribe requires a device context with the font to use
	dc = GetDC(NULL);
	if (dc == NULL)
		dieLE("error getting screen HDC for Uniscribe");
	// TODO DEFAULT_CHARSET might affect the results we get
	font = CreateFontW(0, 0, 0, 0, 0, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fontname);
	if (font == NULL)
		dieLE("error creating font for Uniscribe");
	prevfont = (HFONT) SelectObject(dc, font);
	if (prevfont == NULL)
		dieLE("error selecting font into HDC for Uniscribe");

	// first, uniscribe only; no features are used
	uniscribeOnly(dc, string, len, NULL,
		doScriptItemize, doScriptShape, "Uniscribe");

	// next, unprepared features (NULL values)
	features = new featurePreparer;
	uniscribeOnly(dc, string, len, features,
		doScriptItemizeOpenType, doScriptShapeOpenType, "Uniscribe OpenType");
	delete features;

	SelectObject(dc, prevfont);
	DeleteObject(font);
	ReleaseDC(NULL, dc);
	CoUninitialize();
	return 0;
}
<|endoftext|>


<commit_before>#include <FWApplication.h>

#include <Dialog.h>
#include <GridView.h>
#include <TableLayout.h>
#include <PlatformThread.h>
#include <SysEvent.h>
#include <LinearLayout.h>
#include <TextLabel.h>
#include <TextField.h>
#include <Button.h>

using namespace std;

class AppMessageDialog : public Dialog {
 public:
  AppMessageDialog(const std::string & title, const std::string & message) : Dialog(title) {
    style("height", "wrap-content");
    auto mainLayout = make_shared<LinearLayout>(1);
    mainLayout->style("width", "match-parent");
    mainLayout->style("height", "wrap-content");
    addChild(mainLayout);

    auto dialogMessage = make_shared<TextLabel>(message);
    mainLayout->addChild(dialogMessage);

    auto okButton = std::make_shared<Button>("OK");
    mainLayout->addChild(okButton);
  }

  bool isA(const std::string & className) const override {
    if (className == "AppMessageDialog") return true;
    return Dialog::isA(className);
  }

  void onCommandEvent(CommandEvent & ev) override {
    endModal();
  }
};

class AppInputDialog : public Dialog {
 public:
  AppInputDialog(const std::string & title, const std::string & message) : Dialog(title) {
    style("height", "wrap-content");
    auto mainLayout = make_shared<LinearLayout>(1);
    mainLayout->style("width", "match-parent");
    mainLayout->style("height", "wrap-content");
    mainLayout->style("background-color", "#ffffff");
    addChild(mainLayout);

    auto dialogTitle = std::make_shared<TextLabel>(title);
    dialogTitle->style("background-color", "#ffffff");
    dialogTitle->style("width", "match-parent");
    dialogTitle->style("gravity", "center-horizontal");
    dialogTitle->style("height", "wrap-content");
    dialogTitle->style("font-size", "24");
    dialogTitle->style("padding-top", "12");
    dialogTitle->style("padding-bottom", "16");
    dialogTitle->style("font-weight", "bold");
    dialogTitle->style("padding-left", "4");
    dialogTitle->style("color", "#c1272d");
    mainLayout->addChild(dialogTitle);

    auto dialogMessage = make_shared<TextLabel>(message);
    mainLayout->addChild(dialogMessage);

    textField = make_shared<TextField>();
    textField->style("width", "match-parent");
    textField->style("minimun-width", "100");
    textField->style("padding-bottom", "10");
    textField->style("padding-top", "10");
    textField->style("hint", "Enter code here");
    textField->style("padding-left", "4");
    mainLayout->addChild(textField);

    auto buttonLayout = make_shared<LinearLayout>(2);
    auto okButton = std::make_shared<Button>("OK", 1);
    okButton->style("width", "match-parent");
    okButton->style("height", "match-parent");
    okButton->style("color", "#c1272d");
    okButton->style("border", "#c1272d");
    okButton->style("border-radius", "4");
    okButton->style("weight", "1");
    okButton->style("margin-left", "16");
    okButton->style("margin-right", "2");
    okButton->style("margin-bottom", "2");
    buttonLayout->addChild(okButton);
    auto cancelButton = std::make_shared<Button>("Cancel", 0);
    cancelButton->style("width", "match-parent");
    cancelButton->style("height", "match-parent");
    cancelButton->style("color", "#c1272d");
    cancelButton->style("border", "#c1272d");
    cancelButton->style("border-radius", "4");
    cancelButton->style("weight", "1");
    cancelButton->style("margin-left", "16");
    cancelButton->style("margin-right", "2");
    cancelButton->style("margin-bottom", "2");
    buttonLayout->addChild(cancelButton);

    mainLayout->addChild(buttonLayout);
  }

  bool isA(const std::string & className) const override {
    if (className == "AppInputDialog") return true;
    return Dialog::isA(className);
  }

  void onCommandEvent(CommandEvent & ev) override {
    if (ev.getElementId() == 1) {
      endModal(1);
    } else {
      endModal(0);
    }
  }

  const std::string & getValue() { return textField->getValue(); }

 private:
  std::shared_ptr<TextField> textField;
};

class DebugDialog : public Dialog {
public:
  DebugDialog() : Dialog("Debug") {
    auto mainLayout = make_shared<LinearLayout>(FW_VERTICAL);
    addChild(mainLayout);

    mainLayout->addChild(make_shared<TextLabel>("Debug screen")).style("font-size", "14")
      .style("white-space", "nowrap")
      .style("margin", 5);

    mainLayout->addChild(make_shared<TextLabel>("Stuff")).style("font-size", "12").style("margin", 5);

    auto table = make_shared<TableLayout>(2);
    table->style("margin", 5);
    mainLayout->addChild(table);

    mainLayout->addChild(make_shared<TextLabel>("Threads")).style("font-size", "12").style("margin", 5);

    auto grid = make_shared<GridView>();
    grid->style("margin", 5);
    grid->addColumn("Runnable");
    grid->addColumn("State");
    mainLayout->addChild(grid);
  }

  void load() {
    auto & grid = find("GridView").front();
    populateThreads(dynamic_cast<GridView&>(grid), getThread());
  }

protected:
  void populateThreads(GridView & grid, PlatformThread & thread) {
    string runnable_name, runnable_status;
    auto runnable = thread.getRunnablePtr();
    if (runnable) {
      runnable_name = runnable->getName();
      runnable_status = runnable->getStatusText();
    }
    grid.setValue(numThreadRows, 0, runnable_name);
    grid.setValue(numThreadRows, 1, runnable_status);
    numThreadRows++;
    for (auto & td : thread.getSubThreads()) {
      populateThreads(grid, *td.second);
    }
  }

private:
  int numThreadRows = 0;
};

void
FWApplication::onSysEvent(SysEvent & ev) {
  if (ev.getType() == SysEvent::BACK) {
    int poppedView = popViewBackHistory();
    if (poppedView != 0) {
      Command c(Command::SET_INT_VALUE, poppedView);
      c.setValue(3);
      sendCommand(c);
    } else {
      Command c(Command::QUIT_APP, poppedView);
      sendCommand(c);
    }
  } else if (ev.getType() == SysEvent::DEBUG) {
    auto dialog = make_shared<DebugDialog>();
    dialog->showModal(this);
  }
}

void
FWApplication::showMessageDialog(const std::string & title, const std::string & message) {
  auto dialog = make_shared<AppMessageDialog>(title, message);
  dialog->showModal(this);
}

std::string
FWApplication::showInputDialog(const std::string & title, const std::string & message) {
  auto dialog = make_shared<AppInputDialog>(title, message);
  if (dialog->showModal(this)) {
    return dialog->getValue();
  } else {
    return "";
  }
}
<commit_msg>modify appearance<commit_after>#include <FWApplication.h>

#include <Dialog.h>
#include <GridView.h>
#include <TableLayout.h>
#include <PlatformThread.h>
#include <SysEvent.h>
#include <LinearLayout.h>
#include <TextLabel.h>
#include <TextField.h>
#include <Button.h>

using namespace std;

class AppMessageDialog : public Dialog {
 public:
  AppMessageDialog(const std::string & title, const std::string & message) : Dialog(title) {
    style("height", "wrap-content");
    auto mainLayout = make_shared<LinearLayout>(1);
    mainLayout->style("width", "match-parent");
    mainLayout->style("height", "wrap-content");
    addChild(mainLayout);

    auto dialogMessage = make_shared<TextLabel>(message);
    mainLayout->addChild(dialogMessage);

    auto okButton = std::make_shared<Button>("OK");
    okButton->style("width", "match-parent");
    okButton->style("height", "match-parent");
    okButton->style("color", "#ffffff");
    okButton->style("background", "#c1272d");
    okButton->style("border-radius", "4");
    okButton->style("weight", "1");
    okButton->style("margin-left", "2");
    okButton->style("margin-right", "2");
    okButton->style("margin-bottom", "2");
    mainLayout->addChild(okButton);
  }

  bool isA(const std::string & className) const override {
    if (className == "AppMessageDialog") return true;
    return Dialog::isA(className);
  }

  void onCommandEvent(CommandEvent & ev) override {
    endModal();
  }
};

class AppInputDialog : public Dialog {
 public:
  AppInputDialog(const std::string & title, const std::string & message) : Dialog(title) {
    style("height", "wrap-content");
    auto mainLayout = make_shared<LinearLayout>(1);
    mainLayout->style("width", "match-parent");
    mainLayout->style("height", "wrap-content");
    mainLayout->style("background-color", "#ffffff");
    addChild(mainLayout);

    auto dialogTitle = std::make_shared<TextLabel>(title);
    dialogTitle->style("background-color", "#ffffff");
    dialogTitle->style("width", "match-parent");
    dialogTitle->style("gravity", "center-horizontal");
    dialogTitle->style("height", "wrap-content");
    dialogTitle->style("font-size", "24");
    dialogTitle->style("padding-top", "12");
    dialogTitle->style("padding-bottom", "16");
    dialogTitle->style("font-weight", "bold");
    dialogTitle->style("padding-left", "4");
    dialogTitle->style("color", "#c1272d");
    mainLayout->addChild(dialogTitle);

    auto dialogMessage = make_shared<TextLabel>(message);
    mainLayout->addChild(dialogMessage);

    textField = make_shared<TextField>();
    textField->style("width", "match-parent");
    textField->style("min-width", "100");
    textField->style("padding-bottom", "10");
    textField->style("padding-top", "10");
    textField->style("hint", "Enter code here");
    textField->style("padding-left", "4");
    mainLayout->addChild(textField);

    auto buttonLayout = make_shared<LinearLayout>(2);
    auto okButton = std::make_shared<Button>("OK", 1);
    okButton->style("width", "match-parent");
    okButton->style("height", "match-parent");
    okButton->style("color", "#ffffff");
    okButton->style("background", "#c1272d");
    okButton->style("border-radius", "4");
    okButton->style("weight", "1");
    okButton->style("margin-left", "4");
    okButton->style("margin-right", "2");
    okButton->style("margin-bottom", "4");
    buttonLayout->addChild(okButton);
    auto cancelButton = std::make_shared<Button>("Cancel", 0);
    cancelButton->style("width", "match-parent");
    cancelButton->style("height", "match-parent");
    cancelButton->style("color", "#ffffff");
    cancelButton->style("background", "#c1272d");
    cancelButton->style("border-radius", "4");
    cancelButton->style("weight", "1");
    cancelButton->style("margin-left", "4");
    cancelButton->style("margin-right", "2");
    cancelButton->style("margin-bottom", "4");
    buttonLayout->addChild(cancelButton);

    mainLayout->addChild(buttonLayout);
  }

  bool isA(const std::string & className) const override {
    if (className == "AppInputDialog") return true;
    return Dialog::isA(className);
  }

  void onCommandEvent(CommandEvent & ev) override {
    if (ev.getElementId() == 1) {
      endModal(1);
    } else {
      endModal(0);
    }
  }

  const std::string & getValue() { return textField->getValue(); }

 private:
  std::shared_ptr<TextField> textField;
};

class DebugDialog : public Dialog {
public:
  DebugDialog() : Dialog("Debug") {
    auto mainLayout = make_shared<LinearLayout>(FW_VERTICAL);
    addChild(mainLayout);

    mainLayout->addChild(make_shared<TextLabel>("Debug screen")).style("font-size", "14")
      .style("white-space", "nowrap")
      .style("margin", 5);

    mainLayout->addChild(make_shared<TextLabel>("Stuff")).style("font-size", "12").style("margin", 5);

    auto table = make_shared<TableLayout>(2);
    table->style("margin", 5);
    mainLayout->addChild(table);

    mainLayout->addChild(make_shared<TextLabel>("Threads")).style("font-size", "12").style("margin", 5);

    auto grid = make_shared<GridView>();
    grid->style("margin", 5);
    grid->addColumn("Runnable");
    grid->addColumn("State");
    mainLayout->addChild(grid);
  }

  void load() {
    auto & grid = find("GridView").front();
    populateThreads(dynamic_cast<GridView&>(grid), getThread());
  }

protected:
  void populateThreads(GridView & grid, PlatformThread & thread) {
    string runnable_name, runnable_status;
    auto runnable = thread.getRunnablePtr();
    if (runnable) {
      runnable_name = runnable->getName();
      runnable_status = runnable->getStatusText();
    }
    grid.setValue(numThreadRows, 0, runnable_name);
    grid.setValue(numThreadRows, 1, runnable_status);
    numThreadRows++;
    for (auto & td : thread.getSubThreads()) {
      populateThreads(grid, *td.second);
    }
  }

private:
  int numThreadRows = 0;
};

void
FWApplication::onSysEvent(SysEvent & ev) {
  if (ev.getType() == SysEvent::BACK) {
    int poppedView = popViewBackHistory();
    if (poppedView != 0) {
      Command c(Command::SET_INT_VALUE, poppedView);
      c.setValue(3);
      sendCommand(c);
    } else {
      Command c(Command::QUIT_APP, poppedView);
      sendCommand(c);
    }
  } else if (ev.getType() == SysEvent::DEBUG) {
    auto dialog = make_shared<DebugDialog>();
    dialog->showModal(this);
  }
}

void
FWApplication::showMessageDialog(const std::string & title, const std::string & message) {
  auto dialog = make_shared<AppMessageDialog>(title, message);
  dialog->showModal(this);
}

std::string
FWApplication::showInputDialog(const std::string & title, const std::string & message) {
  auto dialog = make_shared<AppInputDialog>(title, message);
  if (dialog->showModal(this)) {
    return dialog->getValue();
  } else {
    return "";
  }
}
<|endoftext|>


<commit_before><commit_msg>coverity#1093230 Dereference before null check<commit_after><|endoftext|>


<commit_before>// -*- C++ -*-

/**
 * @file   gnuwrapper.cpp
 * @brief  Replaces malloc family on GNU/Linux with custom versions.
 * @author Emery Berger <http://www.cs.umass.edu/~emery>
 * @note   Copyright (C) 2010 by Emery Berger, University of Massachusetts Amherst.
 */

#ifndef __GNUC__
#error "This file requires the GNU compiler."
#endif

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <new>
#include <pthread.h>

#include "heaplayers.h"

/*
  To use this library,
  you only need to define the following allocation functions:

  - xxmalloc
  - xxfree
  - xxmalloc_usable_size
  - xxmalloc_lock
  - xxmalloc_unlock

  See the extern "C" block below for function prototypes and more
  details. YOU SHOULD NOT NEED TO MODIFY ANY OF THE CODE HERE TO
  SUPPORT ANY ALLOCATOR.

  LIMITATIONS:

  - This wrapper assumes that the underlying allocator will do "the
    right thing" when xxfree() is called with a pointer internal to an
    allocated object. Header-based allocators, for example, need not
    apply.

*/

static bool initialized = false;

extern "C" {

  void * xxmalloc (size_t);
  void   xxfree (void *);
  size_t xxmalloc_usable_size (void *);
  void   xxmalloc_lock (void);
  void   xxmalloc_unlock (void);

  static void my_init_hook (void);

  // New hooks for allocation functions.
  static void * my_malloc_hook (size_t, const void *);
  static void   my_free_hook (void *, const void *);
  static void * my_realloc_hook (void *, size_t, const void *);
  static void * my_memalign_hook (size_t, size_t, const void *);

  // Store the old hooks just in case.
  static void * (*old_malloc_hook) (size_t, const void *);
  static void   (*old_free_hook) (void *, const void *);
  static void * (*old_realloc_hook)(void *ptr, size_t size, const void *caller);
  static void * (*old_memalign_hook)(size_t alignment, size_t size, const void *caller);

// From GNU libc 2.14 this macro is defined, to declare
// hook variables as volatile. Define it as empty for
// older glibc versions
#ifndef __MALLOC_HOOK_VOLATILE
 #define __MALLOC_HOOK_VOLATILE
#endif

  void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) = my_init_hook;

  static void my_init_hook (void) {
    if (!initialized) {
      // Store the old hooks.
      old_malloc_hook = __malloc_hook;
      old_free_hook = __free_hook;
      old_realloc_hook = __realloc_hook;
      old_memalign_hook = __memalign_hook;

      // Point the hooks to the replacement functions.
      __malloc_hook = my_malloc_hook;
      __free_hook = my_free_hook;
      __realloc_hook = my_realloc_hook;
      __memalign_hook = my_memalign_hook;

      // Set up everything so that fork behaves properly.
      pthread_atfork(xxmalloc_lock, xxmalloc_unlock, xxmalloc_unlock);

      initialized = true;

    }

  }

  static void * my_malloc_hook (size_t size, const void *) {
    return xxmalloc(size);
  }

  static void my_free_hook (void * ptr, const void *) {
    xxfree(ptr);
  }

  static void * my_realloc_hook (void * ptr, size_t sz, const void *) {
    // NULL ptr = malloc.
    if (ptr == NULL) {
      return xxmalloc(sz);
    }

    if (sz == 0) {
      xxfree (ptr);
#if defined(__APPLE__)
      // 0 size = free. We return a small object.  This behavior is
      // apparently required under Mac OS X and optional under POSIX.
      return xxmalloc(1);
#else
      // For POSIX, don't return anything.
      return NULL;
#endif
    }

    size_t objSize = xxmalloc_usable_size(ptr);

#if 0
    // Custom logic here to ensure we only do a logarithmic number of
    // reallocations (with a constant space overhead).

    // Don't change size if the object is shrinking by less than half.
    if ((objSize / 2 < sz) && (sz <= objSize)) {
      // Do nothing.
      return ptr;
    }
    // If the object is growing by less than 2X, double it.
    if ((objSize < sz) && (sz < objSize * 2)) {
      sz = objSize * 2;
    }
#endif

    void * buf = xxmalloc(sz);

    if (buf != NULL) {
      // Successful malloc.
      // Copy the contents of the original object
      // up to the size of the new block.
      size_t minSize = (objSize < sz) ? objSize : sz;
      memcpy (buf, ptr, minSize);
      xxfree (ptr);
    }

    // Return a pointer to the new one.
    return buf;
  }

  static void * my_memalign_hook (size_t size, size_t alignment, const void *) {
    // Check for non power-of-two alignment, or mistake in size.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return NULL;
      }

    // Try to just allocate an object of the requested size.
    // If it happens to be aligned properly, just return it.
    void * ptr = xxmalloc (size);
    if (((size_t) ptr & (alignment - 1)) == (size_t) ptr) {
      // It is already aligned just fine; return it.
      return ptr;
    }

    // It was not aligned as requested: free the object.
    xxfree (ptr);

    // Now get a big chunk of memory and align the object within it.
    // NOTE: this REQUIRES that the underlying allocator be able
    // to free the aligned object, or ignore the free request.
    void * buf = xxmalloc (2 * alignment + size);
    void * alignedPtr = (void *) (((size_t) buf + alignment - 1) & ~(alignment - 1));

    return alignedPtr;
  }

  ////// END OF HOOK FUNCTIONS

  // This is here because, for some reason, the GNU hooks don't
  // necessarily replace all memory operations as they should.

  int posix_memalign (void **memptr, size_t alignment, size_t size) throw()
  {
    if (!initialized) {
      my_init_hook();
    }
    // Check for non power-of-two alignment.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return EINVAL;
      }
    void * ptr = my_memalign_hook (size, alignment, NULL);
    if (!ptr) {
      return ENOMEM;
    } else {
      *memptr = ptr;
      return 0;
    }
  }

  //// DIRECT REPLACEMENTS FOR MALLOC FAMILY.

  size_t malloc_usable_size (void * ptr) throw() {
    return xxmalloc_usable_size (ptr);
  }

  int mallopt (int param, int value) throw() {
    // NOP.
    param = param;
    value = value;
    return 1; // success.
  }

  int malloc_trim (size_t pad) throw() {
    // NOP.
    pad = pad;
    return 0; // no memory returned to OS.
  }

  void malloc_stats (void) throw() {
    // NOP.
  }

  void * malloc_get_state (void) throw() {
    return NULL; // always returns "error".
  }

  int malloc_set_state (void * ptr) throw() {
    ptr = ptr;
    return 0; // success.
  }

  struct mallinfo mallinfo(void) throw() {
    // For now, we return useless stats.
    struct mallinfo m;
    m.arena = 0;
    m.ordblks = 0;
    m.smblks = 0;
    m.hblks = 0;
    m.hblkhd = 0;
    m.usmblks = 0;
    m.fsmblks = 0;
    m.uordblks = 0;
    m.fordblks = 0;
    m.keepcost = 0;
    return m;
  }

  void * malloc (size_t sz) throw () {
    return xxmalloc (sz);
  }

  void free (void * ptr) throw() {
    xxfree (ptr);
  }

  void * realloc (void * ptr, size_t sz) throw () {
    return my_realloc_hook (ptr, sz, NULL);
  }

  void * memalign (size_t sz, size_t alignment) throw() {
    return my_memalign_hook (sz, alignment, NULL);
  }

  void cfree (void * ptr) throw () {
    xxfree (ptr);
  }

  size_t malloc_size (void * p) {
    return xxmalloc_usable_size (p);
  }

  void * valloc (size_t sz) throw() {
    return my_memalign_hook (sz, HL::CPUInfo::PageSize, NULL);
  }

  void * pvalloc (size_t sz) throw() {
    return valloc ((sz + HL::CPUInfo::PageSize - 1) & ~(HL::CPUInfo::PageSize - 1));
  }

}

void * operator new (size_t sz) throw (std::bad_alloc)
{
  void * ptr = xxmalloc (sz);
  if (ptr == NULL) {
    throw std::bad_alloc();
  } else {
    return ptr;
  }
}

void operator delete (void * ptr)
  throw ()
{
  xxfree (ptr);
}

void * operator new (size_t sz, const std::nothrow_t&) throw() {
  return xxmalloc(sz);
}

void * operator new[] (size_t size)
  throw (std::bad_alloc)
{
  void * ptr = xxmalloc(size);
  if (ptr == NULL) {
    throw std::bad_alloc();
  } else {
    return ptr;
  }
}

void * operator new[] (size_t sz, const std::nothrow_t&)
  throw()
 {
  return xxmalloc(sz);
}

void operator delete[] (void * ptr)
  throw ()
{
  xxfree (ptr);
}

<commit_msg>Fixed incorrect order for memalign.<commit_after>// -*- C++ -*-

/**
 * @file   gnuwrapper.cpp
 * @brief  Replaces malloc family on GNU/Linux with custom versions.
 * @author Emery Berger <http://www.cs.umass.edu/~emery>
 * @note   Copyright (C) 2010 by Emery Berger, University of Massachusetts Amherst.
 */

#ifndef __GNUC__
#error "This file requires the GNU compiler."
#endif

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <new>
#include <pthread.h>

#include "heaplayers.h"

/*
  To use this library,
  you only need to define the following allocation functions:

  - xxmalloc
  - xxfree
  - xxmalloc_usable_size
  - xxmalloc_lock
  - xxmalloc_unlock

  See the extern "C" block below for function prototypes and more
  details. YOU SHOULD NOT NEED TO MODIFY ANY OF THE CODE HERE TO
  SUPPORT ANY ALLOCATOR.

  LIMITATIONS:

  - This wrapper assumes that the underlying allocator will do "the
    right thing" when xxfree() is called with a pointer internal to an
    allocated object. Header-based allocators, for example, need not
    apply.

*/

static bool initialized = false;

extern "C" {

  void * xxmalloc (size_t);
  void   xxfree (void *);
  size_t xxmalloc_usable_size (void *);
  void   xxmalloc_lock (void);
  void   xxmalloc_unlock (void);

  static void my_init_hook (void);

  // New hooks for allocation functions.
  static void * my_malloc_hook (size_t, const void *);
  static void   my_free_hook (void *, const void *);
  static void * my_realloc_hook (void *, size_t, const void *);
  static void * my_memalign_hook (size_t, size_t, const void *);

  // Store the old hooks just in case.
  static void * (*old_malloc_hook) (size_t, const void *);
  static void   (*old_free_hook) (void *, const void *);
  static void * (*old_realloc_hook)(void *ptr, size_t size, const void *caller);
  static void * (*old_memalign_hook)(size_t alignment, size_t size, const void *caller);

// From GNU libc 2.14 this macro is defined, to declare
// hook variables as volatile. Define it as empty for
// older glibc versions
#ifndef __MALLOC_HOOK_VOLATILE
 #define __MALLOC_HOOK_VOLATILE
#endif

  void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) = my_init_hook;

  static void my_init_hook (void) {
    if (!initialized) {
      // Store the old hooks.
      old_malloc_hook = __malloc_hook;
      old_free_hook = __free_hook;
      old_realloc_hook = __realloc_hook;
      old_memalign_hook = __memalign_hook;

      // Point the hooks to the replacement functions.
      __malloc_hook = my_malloc_hook;
      __free_hook = my_free_hook;
      __realloc_hook = my_realloc_hook;
      __memalign_hook = my_memalign_hook;

      // Set up everything so that fork behaves properly.
      pthread_atfork(xxmalloc_lock, xxmalloc_unlock, xxmalloc_unlock);

      initialized = true;

    }

  }

  static void * my_malloc_hook (size_t size, const void *) {
    return xxmalloc(size);
  }

  static void my_free_hook (void * ptr, const void *) {
    xxfree(ptr);
  }

  static void * my_realloc_hook (void * ptr, size_t sz, const void *) {
    // NULL ptr = malloc.
    if (ptr == NULL) {
      return xxmalloc(sz);
    }

    if (sz == 0) {
      xxfree (ptr);
#if defined(__APPLE__)
      // 0 size = free. We return a small object.  This behavior is
      // apparently required under Mac OS X and optional under POSIX.
      return xxmalloc(1);
#else
      // For POSIX, don't return anything.
      return NULL;
#endif
    }

    size_t objSize = xxmalloc_usable_size(ptr);

#if 0
    // Custom logic here to ensure we only do a logarithmic number of
    // reallocations (with a constant space overhead).

    // Don't change size if the object is shrinking by less than half.
    if ((objSize / 2 < sz) && (sz <= objSize)) {
      // Do nothing.
      return ptr;
    }
    // If the object is growing by less than 2X, double it.
    if ((objSize < sz) && (sz < objSize * 2)) {
      sz = objSize * 2;
    }
#endif

    void * buf = xxmalloc(sz);

    if (buf != NULL) {
      // Successful malloc.
      // Copy the contents of the original object
      // up to the size of the new block.
      size_t minSize = (objSize < sz) ? objSize : sz;
      memcpy (buf, ptr, minSize);
      xxfree (ptr);
    }

    // Return a pointer to the new one.
    return buf;
  }

  static void * my_memalign_hook (size_t size, size_t alignment, const void *) {
    // Check for non power-of-two alignment, or mistake in size.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return NULL;
      }

    // Try to just allocate an object of the requested size.
    // If it happens to be aligned properly, just return it.
    void * ptr = xxmalloc (size);
    if (((size_t) ptr & (alignment - 1)) == (size_t) ptr) {
      // It is already aligned just fine; return it.
      return ptr;
    }

    // It was not aligned as requested: free the object.
    xxfree (ptr);

    // Now get a big chunk of memory and align the object within it.
    // NOTE: this REQUIRES that the underlying allocator be able
    // to free the aligned object, or ignore the free request.
    void * buf = xxmalloc (2 * alignment + size);
    void * alignedPtr = (void *) (((size_t) buf + alignment - 1) & ~(alignment - 1));

    return alignedPtr;
  }

  ////// END OF HOOK FUNCTIONS

  // This is here because, for some reason, the GNU hooks don't
  // necessarily replace all memory operations as they should.

  int posix_memalign (void **memptr, size_t alignment, size_t size) throw()
  {
    if (!initialized) {
      my_init_hook();
    }
    // Check for non power-of-two alignment.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return EINVAL;
      }
    void * ptr = my_memalign_hook (size, alignment, NULL);
    if (!ptr) {
      return ENOMEM;
    } else {
      *memptr = ptr;
      return 0;
    }
  }

  //// DIRECT REPLACEMENTS FOR MALLOC FAMILY.

  size_t malloc_usable_size (void * ptr) throw() {
    return xxmalloc_usable_size (ptr);
  }

  int mallopt (int param, int value) throw() {
    // NOP.
    param = param;
    value = value;
    return 1; // success.
  }

  int malloc_trim (size_t pad) throw() {
    // NOP.
    pad = pad;
    return 0; // no memory returned to OS.
  }

  void malloc_stats (void) throw() {
    // NOP.
  }

  void * malloc_get_state (void) throw() {
    return NULL; // always returns "error".
  }

  int malloc_set_state (void * ptr) throw() {
    ptr = ptr;
    return 0; // success.
  }

  struct mallinfo mallinfo(void) throw() {
    // For now, we return useless stats.
    struct mallinfo m;
    m.arena = 0;
    m.ordblks = 0;
    m.smblks = 0;
    m.hblks = 0;
    m.hblkhd = 0;
    m.usmblks = 0;
    m.fsmblks = 0;
    m.uordblks = 0;
    m.fordblks = 0;
    m.keepcost = 0;
    return m;
  }

  void * malloc (size_t sz) throw () {
    return xxmalloc (sz);
  }

  void free (void * ptr) throw() {
    xxfree (ptr);
  }

  void * realloc (void * ptr, size_t sz) throw () {
    return my_realloc_hook (ptr, sz, NULL);
  }

  void * memalign (size_t alignment, size_t sz) throw() {
    return my_memalign_hook (sz, alignment, NULL);
  }

  void cfree (void * ptr) throw () {
    xxfree (ptr);
  }

  size_t malloc_size (void * p) {
    return xxmalloc_usable_size (p);
  }

  void * valloc (size_t sz) throw() {
    return my_memalign_hook (sz, HL::CPUInfo::PageSize, NULL);
  }

  void * pvalloc (size_t sz) throw() {
    return valloc ((sz + HL::CPUInfo::PageSize - 1) & ~(HL::CPUInfo::PageSize - 1));
  }

}

void * operator new (size_t sz) throw (std::bad_alloc)
{
  void * ptr = xxmalloc (sz);
  if (ptr == NULL) {
    throw std::bad_alloc();
  } else {
    return ptr;
  }
}

void operator delete (void * ptr)
  throw ()
{
  xxfree (ptr);
}

void * operator new (size_t sz, const std::nothrow_t&) throw() {
  return xxmalloc(sz);
}

void * operator new[] (size_t size)
  throw (std::bad_alloc)
{
  void * ptr = xxmalloc(size);
  if (ptr == NULL) {
    throw std::bad_alloc();
  } else {
    return ptr;
  }
}

void * operator new[] (size_t sz, const std::nothrow_t&)
  throw()
 {
  return xxmalloc(sz);
}

void operator delete[] (void * ptr)
  throw ()
{
  xxfree (ptr);
}

<|endoftext|>


<commit_before>//
// Copyright 2016 Google Inc.
//
// 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 "FirebaseArduino.h"

void FirebaseArduino::begin(const char* host, const char* auth) {
  http_.reset(FirebaseHttpClient::create());
  http_->setReuseConnection(true);
  host_ = host;
  auth_ = auth;
}

String FirebaseArduino::FirebaseArduino::push(const String& path, const JsonVariant& value) {
  String buf;
  value.printTo(buf);
  auto push = FirebasePush(host_, auth_, path, buf, http_.get());
  error_ = push.error();
  return push.name();
}

void FirebaseArduino::set(const String& path, const JsonVariant& value) {
  String buf;
  value.printTo(buf);
  auto set = FirebaseSet(host_, auth_, path, buf, http_.get());
  error_ = set.error();
}

FirebaseObject FirebaseArduino::get(const char* path) {
  auto get = FirebaseGet(host_, auth_, path, http_.get());
  error_ = get.error();
  if (!error_) {
    return FirebaseObject{""};
  }
  return FirebaseObject(get.response());
}

void FirebaseArduino::remove(const char* path) {
  auto remove = FirebaseRemove(host_, auth_, path, http_.get());
  error_ = remove.error();
}

void FirebaseArduino::stream(const char* path) {
  auto stream = FirebaseStream(host_, auth_, path, http_.get());
  error_ = stream.error();
}

bool FirebaseArduino::available() {
  return http_->getStreamPtr()->available();
}

FirebaseObject FirebaseArduino::readEvent() {
  auto client = http_->getStreamPtr();
  String type = client->readStringUntil('\n').substring(7);;
  String event = client->readStringUntil('\n').substring(6);
  client->readStringUntil('\n'); // consume separator
  FirebaseObject obj = FirebaseObject(event);
  obj["type"] = type;
  return obj;
}

bool FirebaseArduino::success() {
  return error_;
}

bool FirebaseArduino::failed() {
  return !error_;
}

const String& FirebaseArduino::error() {
  return error_.message();
}

FirebaseArduino Firebase;
<commit_msg>FirebaseArduino: fix error check<commit_after>//
// Copyright 2016 Google Inc.
//
// 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 "FirebaseArduino.h"

void FirebaseArduino::begin(const char* host, const char* auth) {
  http_.reset(FirebaseHttpClient::create());
  http_->setReuseConnection(true);
  host_ = host;
  auth_ = auth;
}

String FirebaseArduino::FirebaseArduino::push(const String& path, const JsonVariant& value) {
  String buf;
  value.printTo(buf);
  auto push = FirebasePush(host_, auth_, path, buf, http_.get());
  error_ = push.error();
  return push.name();
}

void FirebaseArduino::set(const String& path, const JsonVariant& value) {
  String buf;
  value.printTo(buf);
  auto set = FirebaseSet(host_, auth_, path, buf, http_.get());
  error_ = set.error();
}

FirebaseObject FirebaseArduino::get(const char* path) {
  auto get = FirebaseGet(host_, auth_, path, http_.get());
  error_ = get.error();
  if (!error_) {
    return FirebaseObject{""};
  }
  return FirebaseObject(get.response());
}

void FirebaseArduino::remove(const char* path) {
  auto remove = FirebaseRemove(host_, auth_, path, http_.get());
  error_ = remove.error();
}

void FirebaseArduino::stream(const char* path) {
  auto stream = FirebaseStream(host_, auth_, path, http_.get());
  error_ = stream.error();
}

bool FirebaseArduino::available() {
  return http_->getStreamPtr()->available();
}

FirebaseObject FirebaseArduino::readEvent() {
  auto client = http_->getStreamPtr();
  String type = client->readStringUntil('\n').substring(7);;
  String event = client->readStringUntil('\n').substring(6);
  client->readStringUntil('\n'); // consume separator
  FirebaseObject obj = FirebaseObject(event);
  obj["type"] = type;
  return obj;
}

bool FirebaseArduino::success() {
  return error_.code() == 0;
}

bool FirebaseArduino::failed() {
  return error_.code() != 0;
}

const String& FirebaseArduino::error() {
  return error_.message();
}

FirebaseArduino Firebase;
<|endoftext|>