<commit_before>#include "builtin/io.hpp"
#include "builtin/string.hpp"

#include <cstdio>
#include <sys/stat.h>
#include <cxxtest/TestSuite.h>

using namespace rubinius;

class TestIO : public CxxTest::TestSuite {
  public:

  VM *state;
  IO* io;
  char *fname;
  int fd;

  void setUp() {
    state = new VM();
    fd = make_io();
    io = IO::create(state, fd);

    /** @todo   Fix this. --rue */
    fname = NULL;
  }

  void tearDown() {
    remove_io(fd);
    delete state;
  }

  void test_io_fields() {
    TS_ASSERT_EQUALS(5U, IO::fields);
  }

  void test_iobuffer_fields() {
    TS_ASSERT_EQUALS(6U, IOBuffer::fields);
  }

  int make_io() {
    char* templ = strdup("/tmp/rubinius_TestIO.XXXXXX");
    int fd = mkstemp(templ);

    if(fd == -1) {
      throw std::runtime_error(strerror(errno));
    }

    free(templ);
    return fd;
  }

  void remove_io(int fd) {
    close(fd);
    unlink(fname);
  }

  void test_create() {
    TS_ASSERT_EQUALS(fd, io->descriptor()->to_native());
    TS_ASSERT_EQUALS(Fixnum::from(0), io->lineno());
    TS_ASSERT(io->eof()->false_p());
    int acc_mode = fcntl(io->to_fd(), F_GETFL);
    TS_ASSERT(acc_mode >= 0);
    TS_ASSERT_EQUALS(Fixnum::from(acc_mode), io->mode());
    TS_ASSERT(kind_of<IOBuffer>(io->ibuffer()));
  }

  void test_allocate() {
    io = IO::allocate(state, G(io));
    TS_ASSERT(io->descriptor()->nil_p());
    TS_ASSERT_EQUALS(Fixnum::from(0), io->lineno());
    TS_ASSERT(io->eof()->false_p());
    TS_ASSERT(io->mode()->nil_p());
    TS_ASSERT(kind_of<IOBuffer>(io->ibuffer()));
  }

  void test_ensure_open() {
    TS_ASSERT(io->ensure_open(state)->nil_p());
    io->descriptor(state, (Fixnum*)Qnil);
    TS_ASSERT_THROWS_ASSERT(io->ensure_open(state), const RubyException &e,
        TS_ASSERT(Exception::io_error_p(state, e.exception)));
    io->descriptor(state, Fixnum::from(-1));
    TS_ASSERT_THROWS_ASSERT(io->ensure_open(state), const RubyException &e,
        TS_ASSERT(Exception::io_error_p(state, e.exception)));
  }

  void test_set_mode() {
    io->mode(state, (Fixnum*)Qnil);
    TS_ASSERT(io->mode()->nil_p());
    io->set_mode(state);
    int acc_mode = fcntl(io->to_fd(), F_GETFL);
    TS_ASSERT(acc_mode >= 0);
    TS_ASSERT_EQUALS(Fixnum::from(acc_mode), io->mode());
  }

  void test_force_read_only() {
    io->force_read_only(state);
    TS_ASSERT((io->mode()->to_native() & O_ACCMODE) == O_RDONLY);
  }

  void test_force_write_only() {
    io->force_write_only(state);
    TS_ASSERT((io->mode()->to_native() & O_ACCMODE) == O_WRONLY);
  }

  void test_connect_pipe() {
    IO* lhs = IO::allocate(state, G(io));
    IO* rhs = IO::allocate(state, G(io));

    TS_ASSERT(IO::connect_pipe(state, lhs, rhs)->true_p());
    TS_ASSERT_EQUALS(Fixnum::from(0), lhs->lineno());
    TS_ASSERT_EQUALS(Fixnum::from(0), rhs->lineno());
    TS_ASSERT(kind_of<IOBuffer>(lhs->ibuffer()));
    TS_ASSERT(kind_of<IOBuffer>(rhs->ibuffer()));
    int acc_mode = fcntl(lhs->to_fd(), F_GETFL);
    TS_ASSERT(acc_mode >= 0);
    TS_ASSERT_EQUALS(Fixnum::from(acc_mode), lhs->mode());
    acc_mode = fcntl(rhs->to_fd(), F_GETFL);
    TS_ASSERT(acc_mode >= 0);
    TS_ASSERT_EQUALS(Fixnum::from(acc_mode), rhs->mode());

    lhs->close(state);
    rhs->close(state);
  }

  void test_write() {
    char buf[4];

    String* s = String::create(state, "abdc");
    io->write(state, s);

    lseek(fd, 0, SEEK_SET);
    TS_ASSERT_EQUALS(::read(fd, buf, 4U), 4);
    TS_ASSERT_SAME_DATA(buf, "abdc", 4);
  }

  void test_query() {
    TS_ASSERT_EQUALS(Qnil, io->query(state, state->symbol("unknown")));

    io->descriptor(state, Fixnum::from(-1));
    TS_ASSERT_THROWS_ASSERT(io->query(state, state->symbol("tty?")),
        const RubyException &e,
        TS_ASSERT(Exception::io_error_p(state, e.exception)));
  }

  void test_query_tty() {
    Symbol* tty_p = state->symbol("tty?");
    TS_ASSERT_EQUALS(Qfalse, io->query(state, tty_p));
  }

  void test_query_ttyname() {
    IO* rb_stdout = ((IO*)G(object)->get_const(state, "STDOUT"));
    String* tty = try_as<String>(rb_stdout->query(state, state->symbol("ttyname")));

    // TODO: /dev/ttyxxx won't be portable to e.g. windoze
    TS_ASSERT(tty);
  }

  void test_create_buffer() {
    IOBuffer* buf = IOBuffer::create(state, 10);
    Fixnum* zero = Fixnum::from(0);

    TS_ASSERT_EQUALS(zero, buf->start());
    TS_ASSERT_EQUALS(zero, buf->used());
    TS_ASSERT_EQUALS(Fixnum::from(10), buf->total());
    TS_ASSERT_EQUALS(10U, buf->left());
    TS_ASSERT(kind_of<Channel>(buf->channel()));
    TS_ASSERT_EQUALS(Qfalse, buf->eof());
  }
};
<commit_msg>Fix test failure<commit_after>#include "builtin/io.hpp"
#include "builtin/string.hpp"

#include <cstdio>
#include <sys/stat.h>
#include <cxxtest/TestSuite.h>

using namespace rubinius;

class TestIO : public CxxTest::TestSuite {
  public:

  VM *state;
  IO* io;
  char *fname;
  int fd;

  void setUp() {
    state = new VM();
    fd = make_io();
    io = IO::create(state, fd);

    /** @todo   Fix this. --rue */
    fname = NULL;
  }

  void tearDown() {
    remove_io(fd);
    delete state;
  }

  void test_io_fields() {
    TS_ASSERT_EQUALS(6U, IO::fields);
  }

  void test_iobuffer_fields() {
    TS_ASSERT_EQUALS(6U, IOBuffer::fields);
  }

  int make_io() {
    char* templ = strdup("/tmp/rubinius_TestIO.XXXXXX");
    int fd = mkstemp(templ);

    if(fd == -1) {
      throw std::runtime_error(strerror(errno));
    }

    free(templ);
    return fd;
  }

  void remove_io(int fd) {
    close(fd);
    unlink(fname);
  }

  void test_create() {
    TS_ASSERT_EQUALS(fd, io->descriptor()->to_native());
    TS_ASSERT_EQUALS(Fixnum::from(0), io->lineno());
    TS_ASSERT(io->eof()->false_p());
    int acc_mode = fcntl(io->to_fd(), F_GETFL);
    TS_ASSERT(acc_mode >= 0);
    TS_ASSERT_EQUALS(Fixnum::from(acc_mode), io->mode());
    TS_ASSERT(kind_of<IOBuffer>(io->ibuffer()));
  }

  void test_allocate() {
    io = IO::allocate(state, G(io));
    TS_ASSERT(io->descriptor()->nil_p());
    TS_ASSERT_EQUALS(Fixnum::from(0), io->lineno());
    TS_ASSERT(io->eof()->false_p());
    TS_ASSERT(io->mode()->nil_p());
    TS_ASSERT(kind_of<IOBuffer>(io->ibuffer()));
  }

  void test_ensure_open() {
    TS_ASSERT(io->ensure_open(state)->nil_p());
    io->descriptor(state, (Fixnum*)Qnil);
    TS_ASSERT_THROWS_ASSERT(io->ensure_open(state), const RubyException &e,
        TS_ASSERT(Exception::io_error_p(state, e.exception)));
    io->descriptor(state, Fixnum::from(-1));
    TS_ASSERT_THROWS_ASSERT(io->ensure_open(state), const RubyException &e,
        TS_ASSERT(Exception::io_error_p(state, e.exception)));
  }

  void test_set_mode() {
    io->mode(state, (Fixnum*)Qnil);
    TS_ASSERT(io->mode()->nil_p());
    io->set_mode(state);
    int acc_mode = fcntl(io->to_fd(), F_GETFL);
    TS_ASSERT(acc_mode >= 0);
    TS_ASSERT_EQUALS(Fixnum::from(acc_mode), io->mode());
  }

  void test_force_read_only() {
    io->force_read_only(state);
    TS_ASSERT((io->mode()->to_native() & O_ACCMODE) == O_RDONLY);
  }

  void test_force_write_only() {
    io->force_write_only(state);
    TS_ASSERT((io->mode()->to_native() & O_ACCMODE) == O_WRONLY);
  }

  void test_connect_pipe() {
    IO* lhs = IO::allocate(state, G(io));
    IO* rhs = IO::allocate(state, G(io));

    TS_ASSERT(IO::connect_pipe(state, lhs, rhs)->true_p());
    TS_ASSERT_EQUALS(Fixnum::from(0), lhs->lineno());
    TS_ASSERT_EQUALS(Fixnum::from(0), rhs->lineno());
    TS_ASSERT(kind_of<IOBuffer>(lhs->ibuffer()));
    TS_ASSERT(kind_of<IOBuffer>(rhs->ibuffer()));
    int acc_mode = fcntl(lhs->to_fd(), F_GETFL);
    TS_ASSERT(acc_mode >= 0);
    TS_ASSERT_EQUALS(Fixnum::from(acc_mode), lhs->mode());
    acc_mode = fcntl(rhs->to_fd(), F_GETFL);
    TS_ASSERT(acc_mode >= 0);
    TS_ASSERT_EQUALS(Fixnum::from(acc_mode), rhs->mode());

    lhs->close(state);
    rhs->close(state);
  }

  void test_write() {
    char buf[4];

    String* s = String::create(state, "abdc");
    io->write(state, s);

    lseek(fd, 0, SEEK_SET);
    TS_ASSERT_EQUALS(::read(fd, buf, 4U), 4);
    TS_ASSERT_SAME_DATA(buf, "abdc", 4);
  }

  void test_query() {
    TS_ASSERT_EQUALS(Qnil, io->query(state, state->symbol("unknown")));

    io->descriptor(state, Fixnum::from(-1));
    TS_ASSERT_THROWS_ASSERT(io->query(state, state->symbol("tty?")),
        const RubyException &e,
        TS_ASSERT(Exception::io_error_p(state, e.exception)));
  }

  void test_query_tty() {
    Symbol* tty_p = state->symbol("tty?");
    TS_ASSERT_EQUALS(Qfalse, io->query(state, tty_p));
  }

  void test_query_ttyname() {
    IO* rb_stdout = ((IO*)G(object)->get_const(state, "STDOUT"));
    String* tty = try_as<String>(rb_stdout->query(state, state->symbol("ttyname")));

    // TODO: /dev/ttyxxx won't be portable to e.g. windoze
    TS_ASSERT(tty);
  }

  void test_create_buffer() {
    IOBuffer* buf = IOBuffer::create(state, 10);
    Fixnum* zero = Fixnum::from(0);

    TS_ASSERT_EQUALS(zero, buf->start());
    TS_ASSERT_EQUALS(zero, buf->used());
    TS_ASSERT_EQUALS(Fixnum::from(10), buf->total());
    TS_ASSERT_EQUALS(10U, buf->left());
    TS_ASSERT(kind_of<Channel>(buf->channel()));
    TS_ASSERT_EQUALS(Qfalse, buf->eof());
  }
};
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkXMLParser.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// Hack access to the fstream implementation if necessary.  This is
// only needed on a few SGI MIPSpro compiler versions.
#if defined(__sgi) && !defined(__GNUC__) && defined(_COMPILER_VERSION)
# if _COMPILER_VERSION == 730
#  include "vtkConfigure.h"
#  if VTK_STREAM_EOF_SEVERITY == 3
#   define protected public
#   define private public
#   include <fstream>
#   undef private
#   undef protected
#  endif
# endif
#endif

#include "vtkXMLParser.h"
#include "vtkObjectFactory.h"

#include "expat.h"
#include <ctype.h>
#include <sys/stat.h>

vtkCxxRevisionMacro(vtkXMLParser, "1.21");
vtkStandardNewMacro(vtkXMLParser);

//----------------------------------------------------------------------------
vtkXMLParser::vtkXMLParser()
{
  this->Stream            = 0;
  this->Parser            = 0;
  this->FileName          = 0;
  this->InputString       = 0;
  this->InputStringLength = 0;
  this->ParseError        = 0;
}

//----------------------------------------------------------------------------
vtkXMLParser::~vtkXMLParser()
{
  this->SetStream(0);
  this->SetFileName(0);
}

//----------------------------------------------------------------------------
void vtkXMLParser::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  if(this->Stream)
    {
    os << indent << "Stream: " << this->Stream << "\n";
    }
  else
    {
    os << indent << "Stream: (none)\n";
    }
  os << indent << "FileName: " << (this->FileName? this->FileName : "(none)")
     << "\n";
}

//----------------------------------------------------------------------------
long vtkXMLParser::TellG()
{
  // Standard tellg returns -1 if fail() is true.
  if(!this->Stream || this->Stream->fail())
    {
    return -1;
    }
#if VTK_STREAM_EOF_SEVERITY == 0
  // No work-around required.  Just return the position.
  return this->Stream->tellg();
#else
  long pos = this->Stream->tellg();
  if(pos == -1)
    {
    // Clear the fail bit from failing tellg.
    this->Stream->clear(this->Stream->rdstate() & ~ios::failbit);

    // Save the eof bit.
    int eof = this->Stream->eof()?1:0;

    // Clear the eof bit.
    if(eof)
      {
      this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit);
      }

# if VTK_STREAM_EOF_SEVERITY == 2
    // Re-seek to the end to escape the buggy stream state.
    this->Stream->seekg(0, ios::end);
# elif VTK_STREAM_EOF_SEVERITY == 3
    // Call an internal filebuf method to escape the buggy stream
    // state.  This is a very ugly hack.
    static_cast<ifstream*>(this->Stream)->rdbuf()->_M_seek_return(0,0);
# endif

    // Call tellg to get the position.
    pos = this->Stream->tellg();

    // Restore the eof bit.
    if(eof)
      {
      this->Stream->clear(this->Stream->rdstate() | ios::eofbit);
      }
    }
  return pos;
#endif
}

//----------------------------------------------------------------------------
void vtkXMLParser::SeekG(long position)
{
  // Standard seekg does nothing if fail() is true.
  if(!this->Stream || this->Stream->fail())
    {
    return;
    }
#if VTK_STREAM_EOF_SEVERITY == 0
  // No work-around required.  Just seek to the position.
  this->Stream->seekg(position);
#else
  // Save the eof bit.
  int eof = this->Stream->eof()?1:0;

  // Clear the eof bit.
  if(eof)
    {
    this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit);
    }

# if VTK_STREAM_EOF_SEVERITY == 3
  // Check if the stream is in the buggy state.
  if(long(this->Stream->tellg()) == -1)
    {
    // Call an internal filebuf method to escape the buggy stream
    // state.  This is a very ugly hack.
    this->Stream->clear(this->Stream->rdstate() & ~ios::failbit);
    this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit);
    static_cast<ifstream*>(this->Stream)->rdbuf()->_M_seek_return(0,0);
    }
# endif

  // Seek to the given position.
  this->Stream->seekg(position);

  // Restore the eof bit.
  if(eof)
    {
    this->Stream->clear(this->Stream->rdstate() | ios::eofbit);
    }
#endif
}

//----------------------------------------------------------------------------
int vtkXMLParser::Parse(const char* inputString)
{
  this->InputString = inputString;
  this->InputStringLength = -1;
  int result = this->vtkXMLParser::Parse();
  this->InputString = 0;
  return result;
}

//----------------------------------------------------------------------------
int vtkXMLParser::Parse(const char* inputString, unsigned int length)
{
  this->InputString = inputString;
  this->InputStringLength = length;
  int result = this->vtkXMLParser::Parse();
  this->InputString = 0;
  this->InputStringLength = -1;
  return result;
}

//----------------------------------------------------------------------------
int vtkXMLParser::Parse()
{
  // Select source of XML
  ifstream ifs;
  if ( !this->InputString && !this->Stream && this->FileName )
    {
    // If it is file, open it and set the appropriate stream
    struct stat fs;
    if (stat(this->FileName, &fs) != 0)
      {
      vtkErrorMacro("Cannot open XML file: " << this->FileName);
      return 0;
      }
#ifdef _WIN32
    ifs.open(this->FileName, ios::binary | ios::in);
#else
    ifs.open(this->FileName, ios::in);
#endif
    if ( !ifs )
      {
      vtkErrorMacro("Cannot open XML file: " << this->FileName);
      return 0;
      }
    this->Stream = &ifs;
    }

  // Create the expat XML parser.
  this->Parser = XML_ParserCreate(0);
  XML_SetElementHandler(static_cast<XML_Parser>(this->Parser),
                        &vtkXMLParserStartElement,
                        &vtkXMLParserEndElement);
  XML_SetCharacterDataHandler(static_cast<XML_Parser>(this->Parser),
                              &vtkXMLParserCharacterDataHandler);
  XML_SetUserData(static_cast<XML_Parser>(this->Parser), this);

  // Parse the input.
  int result = this->ParseXML();

  if(result)
    {
    // Tell the expat XML parser about the end-of-input.
    if(!XML_Parse(static_cast<XML_Parser>(this->Parser), "", 0, 1))
      {
      this->ReportXmlParseError();
      result = 0;
      }
    }

  // Clean up the parser.
  XML_ParserFree(static_cast<XML_Parser>(this->Parser));
  this->Parser = 0;

  // If the source was a file, reset the stream
  if ( this->Stream == &ifs )
    {
    this->Stream = 0;
    }

  return result;
}

//----------------------------------------------------------------------------
int vtkXMLParser::InitializeParser()
{
  if ( this->Parser )
    {
    vtkErrorMacro("Parser already initialized");
    this->ParseError = 1;
    return 0;
    }
  // Create the expat XML parser.
  this->Parser = XML_ParserCreate(0);
  XML_SetElementHandler(static_cast<XML_Parser>(this->Parser),
                        &vtkXMLParserStartElement,
                        &vtkXMLParserEndElement);
  XML_SetCharacterDataHandler(static_cast<XML_Parser>(this->Parser),
                              &vtkXMLParserCharacterDataHandler);
  XML_SetUserData(static_cast<XML_Parser>(this->Parser), this);
  this->ParseError = 0;
  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLParser::ParseChunk(const char* inputString, unsigned int length)
{
  if ( !this->Parser )
    {
    vtkErrorMacro("Parser not initialized");
    this->ParseError = 1;
    return 0;
    }
  int res;
  res = this->ParseBuffer(inputString, length);
  if ( res == 0 )
    {
    this->ParseError = 1;
    }
  return res;
}

//----------------------------------------------------------------------------
int vtkXMLParser::CleanupParser()
{
  if ( !this->Parser )
    {
    vtkErrorMacro("Parser not initialized");
    this->ParseError = 1;
    return 0;
    }
  int result = !this->ParseError;
  if(result)
    {
    // Tell the expat XML parser about the end-of-input.
    if(!XML_Parse(static_cast<XML_Parser>(this->Parser), "", 0, 1))
      {
      this->ReportXmlParseError();
      result = 0;
      }
    }

  // Clean up the parser.
  XML_ParserFree(static_cast<XML_Parser>(this->Parser));
  this->Parser = 0;

  return result;
}

//----------------------------------------------------------------------------
int vtkXMLParser::ParseXML()
{
  // Parsing of message
  if ( this->InputString )
    {
    if ( this->InputStringLength >= 0 )
      {
      return this->ParseBuffer(this->InputString, this->InputStringLength);
      }
    else
      {
      return this->ParseBuffer(this->InputString);
      }
    }

  // Make sure we have input.
  if(!this->Stream)
    {
    vtkErrorMacro("Parse() called with no Stream set.");
    return 0;
    }

  // Default stream parser just reads a block at a time.
  istream& in = *(this->Stream);
  const int bufferSize = 4096;
  char buffer[bufferSize];

  // Read in the stream and send its contents to the XML parser.  This
  // read loop is very sensitive on certain platforms with slightly
  // broken stream libraries (like HPUX).  Normally, it is incorrect
  // to not check the error condition on the fin.read() before using
  // the data, but the fin.gcount() will be zero if an error occurred.
  // Therefore, the loop should be safe everywhere.
  while(!this->ParseError && !this->ParsingComplete() && in)
    {
    in.read(buffer, bufferSize);
    if(in.gcount())
      {
      if(!this->ParseBuffer(buffer, in.gcount()))
        {
        return 0;
        }
      }
    }

  // Clear the fail and eof bits on the input stream so we can later
  // seek back to read data.
  this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit);
  this->Stream->clear(this->Stream->rdstate() & ~ios::failbit);

  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLParser::ParsingComplete()
{
  // Default behavior is to parse to end of stream.
  return 0;
}

//----------------------------------------------------------------------------
void vtkXMLParser::StartElement(const char *name,
                                const char ** vtkNotUsed(atts))
{
  this->ReportUnknownElement(name);
}

//----------------------------------------------------------------------------
void vtkXMLParser::EndElement(const char * vtkNotUsed(name))
{
}

//----------------------------------------------------------------------------
void vtkXMLParser::CharacterDataHandler(const char* vtkNotUsed(inData),
                                        int vtkNotUsed(inLength))
{
}

//----------------------------------------------------------------------------
void vtkXMLParser::ReportStrayAttribute(const char* element, const char* attr,
                                        const char* value)
{
  vtkWarningMacro("Stray attribute in XML stream: Element " << element
                  << " has " << attr << "=\"" << value << "\"");
}

//----------------------------------------------------------------------------
void vtkXMLParser::ReportMissingAttribute(const char* element,
                                          const char* attr)
{
  vtkErrorMacro("Missing attribute in XML stream: Element " << element
                << " is missing " << attr);
}

//----------------------------------------------------------------------------
void vtkXMLParser::ReportBadAttribute(const char* element, const char* attr,
                                      const char* value)
{
  vtkErrorMacro("Bad attribute value in XML stream: Element " << element
                << " has " << attr << "=\"" << value << "\"");
}

//----------------------------------------------------------------------------
void vtkXMLParser::ReportUnknownElement(const char* element)
{
  vtkErrorMacro("Unknown element in XML stream: " << element);
}

//----------------------------------------------------------------------------
void vtkXMLParser::ReportXmlParseError()
{
  vtkErrorMacro("Error parsing XML in stream at line "
                << XML_GetCurrentLineNumber(static_cast<XML_Parser>(this->Parser))
                << ": " << XML_ErrorString(XML_GetErrorCode(static_cast<XML_Parser>(this->Parser))));
}

//----------------------------------------------------------------------------
unsigned long vtkXMLParser::GetXMLByteIndex()
{
  return XML_GetCurrentByteIndex(static_cast<XML_Parser>(this->Parser));
}

//----------------------------------------------------------------------------
int vtkXMLParser::ParseBuffer(const char* buffer, unsigned int count)
{
  // Pass the buffer to the expat XML parser.
  if(!XML_Parse(static_cast<XML_Parser>(this->Parser), buffer, count, 0))
    {
    this->ReportXmlParseError();
    return 0;
    }
  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLParser::ParseBuffer(const char* buffer)
{
  return this->ParseBuffer(buffer, static_cast<int>(strlen(buffer)));
}

//----------------------------------------------------------------------------
int vtkXMLParser::IsSpace(char c)
{
  return isspace(c);
}

//----------------------------------------------------------------------------
void vtkXMLParserStartElement(void* parser, const char *name,
                              const char **atts)
{
  // Begin element handler that is registered with the XML_Parser.
  // This just casts the user data to a vtkXMLParser and calls
  // StartElement.
  static_cast<vtkXMLParser*>(parser)->StartElement(name, atts);
}

//----------------------------------------------------------------------------
void vtkXMLParserEndElement(void* parser, const char *name)
{
  // End element handler that is registered with the XML_Parser.  This
  // just casts the user data to a vtkXMLParser and calls EndElement.
  static_cast<vtkXMLParser*>(parser)->EndElement(name);
}

//----------------------------------------------------------------------------
void vtkXMLParserCharacterDataHandler(void* parser, const char* data,
                                      int length)
{
  // Character data handler that is registered with the XML_Parser.
  // This just casts the user data to a vtkXMLParser and calls
  // CharacterDataHandler.
  static_cast<vtkXMLParser*>(parser)->CharacterDataHandler(data, length);
}
<commit_msg>BUG: The HP compiler sets the badbit too often and prevents the SeekG/TellG wrappers from working correctly.  This is a work-around.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkXMLParser.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// Hack access to the fstream implementation if necessary.  This is
// only needed on a few SGI MIPSpro compiler versions.
#if defined(__sgi) && !defined(__GNUC__) && defined(_COMPILER_VERSION)
# if _COMPILER_VERSION == 730
#  include "vtkConfigure.h"
#  if VTK_STREAM_EOF_SEVERITY == 3
#   define protected public
#   define private public
#   include <fstream>
#   undef private
#   undef protected
#  endif
# endif
#endif

#include "vtkXMLParser.h"
#include "vtkObjectFactory.h"

#include "expat.h"
#include <ctype.h>
#include <sys/stat.h>

vtkCxxRevisionMacro(vtkXMLParser, "1.22");
vtkStandardNewMacro(vtkXMLParser);

//----------------------------------------------------------------------------
vtkXMLParser::vtkXMLParser()
{
  this->Stream            = 0;
  this->Parser            = 0;
  this->FileName          = 0;
  this->InputString       = 0;
  this->InputStringLength = 0;
  this->ParseError        = 0;
}

//----------------------------------------------------------------------------
vtkXMLParser::~vtkXMLParser()
{
  this->SetStream(0);
  this->SetFileName(0);
}

//----------------------------------------------------------------------------
void vtkXMLParser::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  if(this->Stream)
    {
    os << indent << "Stream: " << this->Stream << "\n";
    }
  else
    {
    os << indent << "Stream: (none)\n";
    }
  os << indent << "FileName: " << (this->FileName? this->FileName : "(none)")
     << "\n";
}

//----------------------------------------------------------------------------
static int vtkXMLParserFail(istream* stream)
{
  // The fail() method returns true if either the failbit or badbit is set.
#if defined(__HP_aCC)
  // The HP compiler sets the badbit too often, so we ignore it.
  return (stream->rdstate() & ios::failbit)? 1:0;
#else
  return stream->fail()? 1:0;
#endif
}

//----------------------------------------------------------------------------
long vtkXMLParser::TellG()
{
  // Standard tellg returns -1 if fail() is true.
  if(!this->Stream || vtkXMLParserFail(this->Stream))
    {
    return -1;
    }
#if VTK_STREAM_EOF_SEVERITY == 0
  // No work-around required.  Just return the position.
  return this->Stream->tellg();
#else
  long pos = this->Stream->tellg();
  if(pos == -1)
    {
    // Clear the fail bit from failing tellg.
    this->Stream->clear(this->Stream->rdstate() & ~ios::failbit);

    // Save the eof bit.
    int eof = this->Stream->eof()?1:0;

    // Clear the eof bit.
    if(eof)
      {
      this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit);
      }

# if VTK_STREAM_EOF_SEVERITY == 2
    // Re-seek to the end to escape the buggy stream state.
    this->Stream->seekg(0, ios::end);
# elif VTK_STREAM_EOF_SEVERITY == 3
    // Call an internal filebuf method to escape the buggy stream
    // state.  This is a very ugly hack.
    static_cast<ifstream*>(this->Stream)->rdbuf()->_M_seek_return(0,0);
# endif

    // Call tellg to get the position.
    pos = this->Stream->tellg();

    // Restore the eof bit.
    if(eof)
      {
      this->Stream->clear(this->Stream->rdstate() | ios::eofbit);
      }
    }
  return pos;
#endif
}

//----------------------------------------------------------------------------
void vtkXMLParser::SeekG(long position)
{
  // Standard seekg does nothing if fail() is true.
  if(!this->Stream || vtkXMLParserFail(this->Stream))
    {
    return;
    }
#if VTK_STREAM_EOF_SEVERITY == 0
  // No work-around required.  Just seek to the position.
  this->Stream->seekg(position);
#else
  // Save the eof bit.
  int eof = this->Stream->eof()?1:0;

  // Clear the eof bit.
  if(eof)
    {
    this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit);
    }

# if VTK_STREAM_EOF_SEVERITY == 3
  // Check if the stream is in the buggy state.
  if(long(this->Stream->tellg()) == -1)
    {
    // Call an internal filebuf method to escape the buggy stream
    // state.  This is a very ugly hack.
    this->Stream->clear(this->Stream->rdstate() & ~ios::failbit);
    this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit);
    static_cast<ifstream*>(this->Stream)->rdbuf()->_M_seek_return(0,0);
    }
# endif

  // Seek to the given position.
  this->Stream->seekg(position);

  // Restore the eof bit.
  if(eof)
    {
    this->Stream->clear(this->Stream->rdstate() | ios::eofbit);
    }
#endif
}

//----------------------------------------------------------------------------
int vtkXMLParser::Parse(const char* inputString)
{
  this->InputString = inputString;
  this->InputStringLength = -1;
  int result = this->vtkXMLParser::Parse();
  this->InputString = 0;
  return result;
}

//----------------------------------------------------------------------------
int vtkXMLParser::Parse(const char* inputString, unsigned int length)
{
  this->InputString = inputString;
  this->InputStringLength = length;
  int result = this->vtkXMLParser::Parse();
  this->InputString = 0;
  this->InputStringLength = -1;
  return result;
}

//----------------------------------------------------------------------------
int vtkXMLParser::Parse()
{
  // Select source of XML
  ifstream ifs;
  if ( !this->InputString && !this->Stream && this->FileName )
    {
    // If it is file, open it and set the appropriate stream
    struct stat fs;
    if (stat(this->FileName, &fs) != 0)
      {
      vtkErrorMacro("Cannot open XML file: " << this->FileName);
      return 0;
      }
#ifdef _WIN32
    ifs.open(this->FileName, ios::binary | ios::in);
#else
    ifs.open(this->FileName, ios::in);
#endif
    if ( !ifs )
      {
      vtkErrorMacro("Cannot open XML file: " << this->FileName);
      return 0;
      }
    this->Stream = &ifs;
    }

  // Create the expat XML parser.
  this->Parser = XML_ParserCreate(0);
  XML_SetElementHandler(static_cast<XML_Parser>(this->Parser),
                        &vtkXMLParserStartElement,
                        &vtkXMLParserEndElement);
  XML_SetCharacterDataHandler(static_cast<XML_Parser>(this->Parser),
                              &vtkXMLParserCharacterDataHandler);
  XML_SetUserData(static_cast<XML_Parser>(this->Parser), this);

  // Parse the input.
  int result = this->ParseXML();

  if(result)
    {
    // Tell the expat XML parser about the end-of-input.
    if(!XML_Parse(static_cast<XML_Parser>(this->Parser), "", 0, 1))
      {
      this->ReportXmlParseError();
      result = 0;
      }
    }

  // Clean up the parser.
  XML_ParserFree(static_cast<XML_Parser>(this->Parser));
  this->Parser = 0;

  // If the source was a file, reset the stream
  if ( this->Stream == &ifs )
    {
    this->Stream = 0;
    }

  return result;
}

//----------------------------------------------------------------------------
int vtkXMLParser::InitializeParser()
{
  if ( this->Parser )
    {
    vtkErrorMacro("Parser already initialized");
    this->ParseError = 1;
    return 0;
    }
  // Create the expat XML parser.
  this->Parser = XML_ParserCreate(0);
  XML_SetElementHandler(static_cast<XML_Parser>(this->Parser),
                        &vtkXMLParserStartElement,
                        &vtkXMLParserEndElement);
  XML_SetCharacterDataHandler(static_cast<XML_Parser>(this->Parser),
                              &vtkXMLParserCharacterDataHandler);
  XML_SetUserData(static_cast<XML_Parser>(this->Parser), this);
  this->ParseError = 0;
  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLParser::ParseChunk(const char* inputString, unsigned int length)
{
  if ( !this->Parser )
    {
    vtkErrorMacro("Parser not initialized");
    this->ParseError = 1;
    return 0;
    }
  int res;
  res = this->ParseBuffer(inputString, length);
  if ( res == 0 )
    {
    this->ParseError = 1;
    }
  return res;
}

//----------------------------------------------------------------------------
int vtkXMLParser::CleanupParser()
{
  if ( !this->Parser )
    {
    vtkErrorMacro("Parser not initialized");
    this->ParseError = 1;
    return 0;
    }
  int result = !this->ParseError;
  if(result)
    {
    // Tell the expat XML parser about the end-of-input.
    if(!XML_Parse(static_cast<XML_Parser>(this->Parser), "", 0, 1))
      {
      this->ReportXmlParseError();
      result = 0;
      }
    }

  // Clean up the parser.
  XML_ParserFree(static_cast<XML_Parser>(this->Parser));
  this->Parser = 0;

  return result;
}

//----------------------------------------------------------------------------
int vtkXMLParser::ParseXML()
{
  // Parsing of message
  if ( this->InputString )
    {
    if ( this->InputStringLength >= 0 )
      {
      return this->ParseBuffer(this->InputString, this->InputStringLength);
      }
    else
      {
      return this->ParseBuffer(this->InputString);
      }
    }

  // Make sure we have input.
  if(!this->Stream)
    {
    vtkErrorMacro("Parse() called with no Stream set.");
    return 0;
    }

  // Default stream parser just reads a block at a time.
  istream& in = *(this->Stream);
  const int bufferSize = 4096;
  char buffer[bufferSize];

  // Read in the stream and send its contents to the XML parser.  This
  // read loop is very sensitive on certain platforms with slightly
  // broken stream libraries (like HPUX).  Normally, it is incorrect
  // to not check the error condition on the fin.read() before using
  // the data, but the fin.gcount() will be zero if an error occurred.
  // Therefore, the loop should be safe everywhere.
  while(!this->ParseError && !this->ParsingComplete() && in)
    {
    in.read(buffer, bufferSize);
    if(in.gcount())
      {
      if(!this->ParseBuffer(buffer, in.gcount()))
        {
        return 0;
        }
      }
    }

  // Clear the fail and eof bits on the input stream so we can later
  // seek back to read data.
  this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit);
  this->Stream->clear(this->Stream->rdstate() & ~ios::failbit);

  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLParser::ParsingComplete()
{
  // Default behavior is to parse to end of stream.
  return 0;
}

//----------------------------------------------------------------------------
void vtkXMLParser::StartElement(const char *name,
                                const char ** vtkNotUsed(atts))
{
  this->ReportUnknownElement(name);
}

//----------------------------------------------------------------------------
void vtkXMLParser::EndElement(const char * vtkNotUsed(name))
{
}

//----------------------------------------------------------------------------
void vtkXMLParser::CharacterDataHandler(const char* vtkNotUsed(inData),
                                        int vtkNotUsed(inLength))
{
}

//----------------------------------------------------------------------------
void vtkXMLParser::ReportStrayAttribute(const char* element, const char* attr,
                                        const char* value)
{
  vtkWarningMacro("Stray attribute in XML stream: Element " << element
                  << " has " << attr << "=\"" << value << "\"");
}

//----------------------------------------------------------------------------
void vtkXMLParser::ReportMissingAttribute(const char* element,
                                          const char* attr)
{
  vtkErrorMacro("Missing attribute in XML stream: Element " << element
                << " is missing " << attr);
}

//----------------------------------------------------------------------------
void vtkXMLParser::ReportBadAttribute(const char* element, const char* attr,
                                      const char* value)
{
  vtkErrorMacro("Bad attribute value in XML stream: Element " << element
                << " has " << attr << "=\"" << value << "\"");
}

//----------------------------------------------------------------------------
void vtkXMLParser::ReportUnknownElement(const char* element)
{
  vtkErrorMacro("Unknown element in XML stream: " << element);
}

//----------------------------------------------------------------------------
void vtkXMLParser::ReportXmlParseError()
{
  vtkErrorMacro("Error parsing XML in stream at line "
                << XML_GetCurrentLineNumber(static_cast<XML_Parser>(this->Parser))
                << ": " << XML_ErrorString(XML_GetErrorCode(static_cast<XML_Parser>(this->Parser))));
}

//----------------------------------------------------------------------------
unsigned long vtkXMLParser::GetXMLByteIndex()
{
  return XML_GetCurrentByteIndex(static_cast<XML_Parser>(this->Parser));
}

//----------------------------------------------------------------------------
int vtkXMLParser::ParseBuffer(const char* buffer, unsigned int count)
{
  // Pass the buffer to the expat XML parser.
  if(!XML_Parse(static_cast<XML_Parser>(this->Parser), buffer, count, 0))
    {
    this->ReportXmlParseError();
    return 0;
    }
  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLParser::ParseBuffer(const char* buffer)
{
  return this->ParseBuffer(buffer, static_cast<int>(strlen(buffer)));
}

//----------------------------------------------------------------------------
int vtkXMLParser::IsSpace(char c)
{
  return isspace(c);
}

//----------------------------------------------------------------------------
void vtkXMLParserStartElement(void* parser, const char *name,
                              const char **atts)
{
  // Begin element handler that is registered with the XML_Parser.
  // This just casts the user data to a vtkXMLParser and calls
  // StartElement.
  static_cast<vtkXMLParser*>(parser)->StartElement(name, atts);
}

//----------------------------------------------------------------------------
void vtkXMLParserEndElement(void* parser, const char *name)
{
  // End element handler that is registered with the XML_Parser.  This
  // just casts the user data to a vtkXMLParser and calls EndElement.
  static_cast<vtkXMLParser*>(parser)->EndElement(name);
}

//----------------------------------------------------------------------------
void vtkXMLParserCharacterDataHandler(void* parser, const char* data,
                                      int length)
{
  // Character data handler that is registered with the XML_Parser.
  // This just casts the user data to a vtkXMLParser and calls
  // CharacterDataHandler.
  static_cast<vtkXMLParser*>(parser)->CharacterDataHandler(data, length);
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/ClangInternalState.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceManager.h"

#include "llvm/ADT/SmallString.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"

#include <cstdio>
#include <string>
#include <time.h>

using namespace clang;

namespace cling {
  ClangInternalState::ClangInternalState(ASTContext& C, llvm::Module& M,
                                         const std::string& name)
    : m_ASTContext(C), m_Module(M), m_DiffCommand("diff -u "), m_Name(name) {
    store();
  }

  ClangInternalState::~ClangInternalState() {
    // cleanup the temporary files:
    remove(m_LookupTablesFile.c_str());
    remove(m_IncludedFilesFile.c_str());
    remove(m_ASTFile.c_str());
    remove(m_LLVMModuleFile.c_str());
  }

  void ClangInternalState::store() {
    m_LookupTablesOS.reset(createOutputFile("lookup", &m_LookupTablesFile));
    m_IncludedFilesOS.reset(createOutputFile("included", &m_IncludedFilesFile));
    m_ASTOS.reset(createOutputFile("ast", &m_ASTFile));
    m_LLVMModuleOS.reset(createOutputFile("module", &m_LLVMModuleFile));

    printLookupTables(*m_LookupTablesOS.get(), m_ASTContext);
    printIncludedFiles(*m_IncludedFilesOS.get(),
                       m_ASTContext.getSourceManager());
    printAST(*m_ASTOS.get(), m_ASTContext);
    printLLVMModule(*m_LLVMModuleOS.get(), m_Module);
  }
  namespace {
    std::string getCurrentTimeAsString() {
      time_t rawtime;
      struct tm * timeinfo;
      char buffer [80];

      time (&rawtime);
      timeinfo = localtime (&rawtime);

      strftime (buffer, 80, "%I_%M_%S", timeinfo);
      return buffer;
    }
  }

  // Copied with modifications from CompilerInstance.cpp
  llvm::raw_fd_ostream*
  ClangInternalState::createOutputFile(llvm::StringRef OutFile,
                                       std::string *TempPathName/*=0*/,
                                       bool RemoveFileOnSignal/*=true*/) {
    llvm::OwningPtr<llvm::raw_fd_ostream> OS;
    std::string OSFile;
    llvm::SmallString<256> OutputPath;
    llvm::sys::path::system_temp_directory(/*erasedOnReboot*/false, OutputPath);

    // Only create the temporary if the parent directory exists (or create
    // missing directories is true) and we can actually write to OutPath,
    // otherwise we want to fail early.
    llvm::SmallString<256> TempPath(OutputPath);
    llvm::sys::fs::make_absolute(TempPath);
    assert(llvm::sys::fs::is_directory(TempPath.str()) && "Must be a folder.");
    // Create a temporary file.
    llvm::sys::path::append(TempPath, OutFile);
    TempPath += "-" + getCurrentTimeAsString();
    TempPath += "-%%%%%%%%";
    int fd;
    if (llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath)
        == llvm::errc::success) {
      OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
      OSFile = TempPath.str();
    }

    // Make sure the out stream file gets removed if we crash.
    if (RemoveFileOnSignal)
      llvm::sys::RemoveFileOnSignal(OSFile);

    if (TempPathName)
      *TempPathName = OSFile;

    return OS.take();
  }

  void ClangInternalState::compare(ClangInternalState& other) {
    std::string differences = "";
    if (differentContent(m_LookupTablesFile, other.m_LookupTablesFile,
                         differences)) {
      llvm::errs() << "Differences in the lookup tables\n";
      llvm::errs() << differences << "\n";
      differences = "";
    }

    if (differentContent(m_IncludedFilesFile, other.m_IncludedFilesFile,
                         differences)) {
      llvm::errs() << "Differences in the included files\n";
      llvm::errs() << differences << "\n";
      differences = "";
    }

    if (differentContent(m_ASTFile, other.m_ASTFile, differences)) {
      llvm::errs() << "Differences in the AST \n";
      llvm::errs() << differences << "\n";
      differences = "";
    }

    if (differentContent(m_LLVMModuleFile, other.m_LLVMModuleFile, differences)){
      llvm::errs() << "Differences in the llvm Module \n";
      llvm::errs() << differences << "\n";
      differences = "";
    }
  }

  bool ClangInternalState::differentContent(const std::string& file1,
                                            const std::string& file2,
                                            std::string& differences) const {
    FILE* pipe = popen((m_DiffCommand + file1 + " " + file2).c_str() , "r");
    assert(pipe && "Error creating the pipe");
    assert(differences.empty() && "Must be empty");

    char buffer[128];
    while(!feof(pipe)) {
      if(fgets(buffer, 128, pipe) != NULL)
        differences += buffer;
    }
    pclose(pipe);
    return !differences.empty();
  }

  class DumpLookupTables : public RecursiveASTVisitor<DumpLookupTables> {
  private:
    //llvm::raw_ostream& m_OS;
  public:
    //DumpLookupTables(llvm::raw_ostream& OS) : m_OS(OS) { }
    DumpLookupTables(llvm::raw_ostream&) { }
    bool VisitDeclContext(DeclContext* DC) {
      //DC->dumpLookups(m_OS);
      return true;
    }
  };

  void ClangInternalState::printLookupTables(llvm::raw_ostream& Out,
                                             ASTContext& C) {
    DumpLookupTables dumper(Out);
    dumper.TraverseDecl(C.getTranslationUnitDecl());
  }

  void ClangInternalState::printIncludedFiles(llvm::raw_ostream& Out,
                                              SourceManager& SM) {
    for (clang::SourceManager::fileinfo_iterator I = SM.fileinfo_begin(),
           E = SM.fileinfo_end(); I != E; ++I) {
      const clang::SrcMgr::ContentCache &C = *I->second;
      const clang::FileEntry *FE = C.OrigEntry;
      // Our error recovery purges the cache of the FileEntry, but keeps
      // the FileEntry's pointer so that if it was used by smb (like the
      // SourceManager) it wouldn't be dangling. In that case we shouldn't
      // print the FileName, because semantically it is not there.
      if (!FE->getSize() && !FE->getModificationTime())
        continue;
      std::string fileName(FE->getName());
      if (!(fileName.compare(0, 5, "/usr/") == 0 &&
            fileName.find("/bits/") != std::string::npos)) {
        Out << fileName << '\n';
      }
    }
  }

  void ClangInternalState::printAST(llvm::raw_ostream& Out, ASTContext& C) {
    TranslationUnitDecl* TU = C.getTranslationUnitDecl();
    unsigned Indentation = 0;
    bool PrintInstantiation = false;
    std::string ErrMsg;
    clang::PrintingPolicy policy = C.getPrintingPolicy();
    TU->print(Out, policy, Indentation, PrintInstantiation);
    // TODO: For future when we relpace the bump allocation with slab.
    //
    //Out << "Allocated memory: " << C.getAllocatedMemory();
    //Out << "Side table allocated memory: " << C.getSideTableAllocatedMemory();
    Out.flush();
  }

  void ClangInternalState::printLLVMModule(llvm::raw_ostream& Out,
                                           llvm::Module& M) {
    M.print(Out, /*AssemblyAnnotationWriter*/ 0);
  }
} // end namespace cling
<commit_msg>Dump the lookup tables, too.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/ClangInternalState.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceManager.h"

#include "llvm/ADT/SmallString.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"

#include <cstdio>
#include <string>
#include <time.h>

using namespace clang;

namespace cling {
  ClangInternalState::ClangInternalState(ASTContext& C, llvm::Module& M,
                                         const std::string& name)
    : m_ASTContext(C), m_Module(M), m_DiffCommand("diff -u "), m_Name(name) {
    store();
  }

  ClangInternalState::~ClangInternalState() {
    // cleanup the temporary files:
    remove(m_LookupTablesFile.c_str());
    remove(m_IncludedFilesFile.c_str());
    remove(m_ASTFile.c_str());
    remove(m_LLVMModuleFile.c_str());
  }

  void ClangInternalState::store() {
    m_LookupTablesOS.reset(createOutputFile("lookup", &m_LookupTablesFile));
    m_IncludedFilesOS.reset(createOutputFile("included", &m_IncludedFilesFile));
    m_ASTOS.reset(createOutputFile("ast", &m_ASTFile));
    m_LLVMModuleOS.reset(createOutputFile("module", &m_LLVMModuleFile));

    printLookupTables(*m_LookupTablesOS.get(), m_ASTContext);
    printIncludedFiles(*m_IncludedFilesOS.get(),
                       m_ASTContext.getSourceManager());
    printAST(*m_ASTOS.get(), m_ASTContext);
    printLLVMModule(*m_LLVMModuleOS.get(), m_Module);
  }
  namespace {
    std::string getCurrentTimeAsString() {
      time_t rawtime;
      struct tm * timeinfo;
      char buffer [80];

      time (&rawtime);
      timeinfo = localtime (&rawtime);

      strftime (buffer, 80, "%I_%M_%S", timeinfo);
      return buffer;
    }
  }

  // Copied with modifications from CompilerInstance.cpp
  llvm::raw_fd_ostream*
  ClangInternalState::createOutputFile(llvm::StringRef OutFile,
                                       std::string *TempPathName/*=0*/,
                                       bool RemoveFileOnSignal/*=true*/) {
    llvm::OwningPtr<llvm::raw_fd_ostream> OS;
    std::string OSFile;
    llvm::SmallString<256> OutputPath;
    llvm::sys::path::system_temp_directory(/*erasedOnReboot*/false, OutputPath);

    // Only create the temporary if the parent directory exists (or create
    // missing directories is true) and we can actually write to OutPath,
    // otherwise we want to fail early.
    llvm::SmallString<256> TempPath(OutputPath);
    llvm::sys::fs::make_absolute(TempPath);
    assert(llvm::sys::fs::is_directory(TempPath.str()) && "Must be a folder.");
    // Create a temporary file.
    llvm::sys::path::append(TempPath, OutFile);
    TempPath += "-" + getCurrentTimeAsString();
    TempPath += "-%%%%%%%%";
    int fd;
    if (llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath)
        == llvm::errc::success) {
      OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
      OSFile = TempPath.str();
    }

    // Make sure the out stream file gets removed if we crash.
    if (RemoveFileOnSignal)
      llvm::sys::RemoveFileOnSignal(OSFile);

    if (TempPathName)
      *TempPathName = OSFile;

    return OS.take();
  }

  void ClangInternalState::compare(ClangInternalState& other) {
    std::string differences = "";
    if (differentContent(m_LookupTablesFile, other.m_LookupTablesFile,
                         differences)) {
      llvm::errs() << "Differences in the lookup tables\n";
      llvm::errs() << differences << "\n";
      differences = "";
    }

    if (differentContent(m_IncludedFilesFile, other.m_IncludedFilesFile,
                         differences)) {
      llvm::errs() << "Differences in the included files\n";
      llvm::errs() << differences << "\n";
      differences = "";
    }

    if (differentContent(m_ASTFile, other.m_ASTFile, differences)) {
      llvm::errs() << "Differences in the AST \n";
      llvm::errs() << differences << "\n";
      differences = "";
    }

    if (differentContent(m_LLVMModuleFile, other.m_LLVMModuleFile, differences)){
      llvm::errs() << "Differences in the llvm Module \n";
      llvm::errs() << differences << "\n";
      differences = "";
    }
  }

  bool ClangInternalState::differentContent(const std::string& file1,
                                            const std::string& file2,
                                            std::string& differences) const {
    FILE* pipe = popen((m_DiffCommand + file1 + " " + file2).c_str() , "r");
    assert(pipe && "Error creating the pipe");
    assert(differences.empty() && "Must be empty");

    char buffer[128];
    while(!feof(pipe)) {
      if(fgets(buffer, 128, pipe) != NULL)
        differences += buffer;
    }
    pclose(pipe);
    return !differences.empty();
  }

  class DumpLookupTables : public RecursiveASTVisitor<DumpLookupTables> {
  private:
    llvm::raw_ostream& m_OS;
  public:
    DumpLookupTables(llvm::raw_ostream& OS) : m_OS(OS) { }
    bool VisitDecl(Decl* D) {
      if (DeclContext* DC = dyn_cast<DeclContext>(D))
        VisitDeclContext(DC);
      return true;
    }

    bool VisitDeclContext(DeclContext* DC) {
      DC->dumpLookups(m_OS);
      return true;
    }
  };

  void ClangInternalState::printLookupTables(llvm::raw_ostream& Out,
                                             ASTContext& C) {
    DumpLookupTables dumper(Out);
    dumper.TraverseDecl(C.getTranslationUnitDecl());
  }

  void ClangInternalState::printIncludedFiles(llvm::raw_ostream& Out,
                                              SourceManager& SM) {
    for (clang::SourceManager::fileinfo_iterator I = SM.fileinfo_begin(),
           E = SM.fileinfo_end(); I != E; ++I) {
      const clang::SrcMgr::ContentCache &C = *I->second;
      const clang::FileEntry *FE = C.OrigEntry;
      // Our error recovery purges the cache of the FileEntry, but keeps
      // the FileEntry's pointer so that if it was used by smb (like the
      // SourceManager) it wouldn't be dangling. In that case we shouldn't
      // print the FileName, because semantically it is not there.
      if (!FE->getSize() && !FE->getModificationTime())
        continue;
      std::string fileName(FE->getName());
      if (!(fileName.compare(0, 5, "/usr/") == 0 &&
            fileName.find("/bits/") != std::string::npos)) {
        Out << fileName << '\n';
      }
    }
  }

  void ClangInternalState::printAST(llvm::raw_ostream& Out, ASTContext& C) {
    TranslationUnitDecl* TU = C.getTranslationUnitDecl();
    unsigned Indentation = 0;
    bool PrintInstantiation = false;
    std::string ErrMsg;
    clang::PrintingPolicy policy = C.getPrintingPolicy();
    TU->print(Out, policy, Indentation, PrintInstantiation);
    // TODO: For future when we relpace the bump allocation with slab.
    //
    //Out << "Allocated memory: " << C.getAllocatedMemory();
    //Out << "Side table allocated memory: " << C.getSideTableAllocatedMemory();
    Out.flush();
  }

  void ClangInternalState::printLLVMModule(llvm::raw_ostream& Out,
                                           llvm::Module& M) {
    M.print(Out, /*AssemblyAnnotationWriter*/ 0);
  }
} // end namespace cling
<|endoftext|>


<commit_before>/*
Copyright (c) 2017 ayevuhn

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.
*/

/**
* @file ServerDemo.cpp
*
* Short demonstration that shows how
* to use the TcpEndpoint class as a
* server.
*/

#include <iostream>
#include "TcpEndpoint.h"

/**
* At first this program will wait for a connection on port
* 52200. As soon as a client has connected it will try to receive
* messages which have 10 bytes or less. When a message arrives
* It will be displayed and a response message containing the
* word "Acknowledged" will be sent to the client. This program
* ends when the client closes the connection.
*/
int main ()
{
  spw::TcpEndpoint server(52200); //Listen on port 52200
  server.setTimeout(3000); //3 seconds timeout
  server.useTimeout(true); //Use non blocking mode

  std::cout << "Waiting for connection." << std::endl;

  // In this part the server is waiting for a peer to connect.

  for(;;)
  {
    try
    {
      server.waitForConnection();
      std::cout << "Connected to " << server.getPeerIpAddress()
                << ":" << server.getPeerPort() << std::endl;
      break;
    }
    catch(spw::Timeout &ex)
    {
      std::cout << "No connection yet." << std::endl;
    }
    catch(spw::OtherError &ex)
    {
      std::cerr << ex.what() << std::endl;
      exit(1);
    }
    catch(...)
    {
      std::cerr << "Error occurred. Cause unknown. Terminating." << std::endl;
      exit(2);
    }
  }

  // Connection is established. Communication takes places in this part.

  std::string received;

  for(;;)
  {
    try
    {
      std::cout << "Receiving..." << std::endl;
      server.receiveString(received, 10);
      std::cout << "Received: " << received << std::endl;
      std::cout << "Sending: Acknowledged" << std::endl;
      server.sendString("Acknowledged");
    }
    catch(spw::Timeout &ex)
    {
      std::cout << "Nothing received yet" << std::endl;
    }
    catch(spw::Disconnect &ex)
    {
      std::cerr << ex.what() << std::endl;
      break;
    }
    catch(spw::OtherError &ex)
    {
      std::cerr << ex.what() << std::endl;
      exit(4);
    }
    catch(...)
    {
      std::cerr << "Error occured. Cause unknown. Terminating." << std::endl;
    }
  }

  std::cout << "Done" << std::endl;

  return 0;
}

<commit_msg>Added exit() statement in ServerDemo.cpp<commit_after>/*
Copyright (c) 2017 ayevuhn

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.
*/

/**
* @file ServerDemo.cpp
*
* Short demonstration that shows how
* to use the TcpEndpoint class as a
* server.
*/

#include <iostream>
#include "TcpEndpoint.h"

/**
* At first this program will wait for a connection on port
* 52200. As soon as a client has connected it will try to receive
* messages which have 10 bytes or less. When a message arrives
* It will be displayed and a response message containing the
* word "Acknowledged" will be sent to the client. This program
* ends when the client closes the connection.
*/
int main ()
{
  spw::TcpEndpoint server(52200); //Listen on port 52200
  server.setTimeout(3000); //3 seconds timeout
  server.useTimeout(true); //Use non blocking mode

  std::cout << "Waiting for connection." << std::endl;

  // In this part the server is waiting for a peer to connect.

  for(;;)
  {
    try
    {
      server.waitForConnection();
      std::cout << "Connected to " << server.getPeerIpAddress()
                << ":" << server.getPeerPort() << std::endl;
      break;
    }
    catch(spw::Timeout &ex)
    {
      std::cout << "No connection yet." << std::endl;
    }
    catch(spw::OtherError &ex)
    {
      std::cerr << ex.what() << std::endl;
      exit(1);
    }
    catch(...)
    {
      std::cerr << "Error occurred. Cause unknown. Terminating." << std::endl;
      exit(2);
    }
  }

  // Connection is established. Communication takes places in this part.

  std::string received;

  for(;;)
  {
    try
    {
      std::cout << "Receiving..." << std::endl;
      server.receiveString(received, 10);
      std::cout << "Received: " << received << std::endl;
      std::cout << "Sending: Acknowledged" << std::endl;
      server.sendString("Acknowledged");
    }
    catch(spw::Timeout &ex)
    {
      std::cout << "Nothing received yet" << std::endl;
    }
    catch(spw::Disconnect &ex)
    {
      std::cerr << ex.what() << std::endl;
      break;
    }
    catch(spw::OtherError &ex)
    {
      std::cerr << ex.what() << std::endl;
      exit(3);
    }
    catch(...)
    {
      std::cerr << "Error occured. Cause unknown. Terminating." << std::endl;
      exit(4);
    }
  }

  std::cout << "Done" << std::endl;

  return 0;
}

<|endoftext|>


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

   The MIT License

   Copyright (c) 2010 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.
*/

/**
  \file    InveonConverter.cpp
  \author  Tom Fogal
           SCI Institute
           University of Utah
*/
#include "../StdTuvokDefines.h"
#include <cctype>
#include <fstream>
#ifdef _MSC_VER
# include <functional>
# include <unordered_map>
#else
# include <tr1/functional>
# include <tr1/unordered_map>
#endif
#include <sstream>
#include <string>
#include "InveonConverter.h"
#include <Basics/EndianConvert.h>

InveonConverter::InveonConverter()
{
  m_vConverterDesc = "Inveon";
  m_vSupportedExt.push_back("HDR");
}

typedef std::tr1::unordered_map<std::string, std::string> LineMap;
// The 'hdr' files we are given consist of a series of lines which begin with a
// keyword, and then a series of space-separated parameters.  This searches for
// lines which begin with the strings in the keys of the map, and fills the
// values with the rest of the lines.
// Ex: a stream consists of:
//    abc 42
//    def 19
//    qwerty 12.5512 123
//    foo bar
// then if the input map contains:
//    "abc":""
//    "qwerty":""
//    "foo":""
// then the output map will contain:
//    "abc":"42"
//    "qwerty":"12.5512 123"
//    "foo":"bar"
static void
findlines(std::ifstream& ifs, LineMap& values)
{
  ifs.seekg(0);
  std::string line;

  while(ifs) {
    if(getline(ifs, line)) {
      // iterate through all our keys and see if the line begins with
      // any of them.
      for(LineMap::iterator l = values.begin(); l != values.end(); ++l) {
        if(line.find(l->first) == 0) {
          l->second = line.substr(l->first.length()+1); // +1: skip space.
        }
      }
    }
  }
}

namespace {
  template <typename T> T convert(const std::string& s) {
    T t;
    std::istringstream conv(s);
    conv >> t;
    return t;
  }
}

bool InveonConverter::ConvertToRAW(const std::string& strSourceFilename,
                                    const std::string&,
                                    bool /* bNoUserInteraction */,
                                    UINT64& iHeaderSkip,
                                    UINT64& iComponentSize,
                                    UINT64& iComponentCount,
                                    bool& bConvertEndianess, bool& bSigned,
                                    bool& bIsFloat, UINT64VECTOR3& vVolumeSize,
                                    FLOATVECTOR3& vVolumeAspect,
                                    std::string& strTitle,
                                    UVFTables::ElementSemanticTable& eType,
                                    std::string& strIntermediateFile,
                                    bool& bDeleteIntermediateFile)
{
  std::ifstream infn(strSourceFilename.c_str(), std::ios::in);
  if(!infn.is_open()) {
    T_ERROR("Could not open %s", strSourceFilename.c_str());
    return false;
  }

  iHeaderSkip = 0;
  iComponentCount = 1;
  eType = UVFTables::ES_UNDEFINED;
  bDeleteIntermediateFile = false;
  bSigned = true; // format does not distinguish
  strTitle = "Inveon";

  // The filename is actually stored in the header, but it includes
  // a full pathname and is thus garbage in many instances; e.g. the
  // files I have say:  "F:/somefolder/xyz/blah/whatever/file.ct.img",
  // and I'm on a Unix system, so "F:" doesn't even make sense.
  // Therefore we just ignore the filename in the header and use the
  // "hdr" filename sans the "hdr" extension, which seems to be the
  // convention.
  strIntermediateFile = SysTools::RemoveExt(strSourceFilename);

  LineMap lines;
  lines.insert(LineMap::value_type("version",""));
  lines.insert(LineMap::value_type("number_of_dimensions",""));
  lines.insert(LineMap::value_type("x_dimension",""));
  lines.insert(LineMap::value_type("y_dimension",""));
  lines.insert(LineMap::value_type("z_dimension",""));
  lines.insert(LineMap::value_type("pixel_size_x",""));
  lines.insert(LineMap::value_type("pixel_size_y",""));
  lines.insert(LineMap::value_type("pixel_size_z",""));
  lines.insert(LineMap::value_type("data_type",""));

  findlines(infn, lines);

  for(LineMap::const_iterator l = lines.begin(); l != lines.end(); ++l) {
    MESSAGE("read %s -> '%s'", l->first.c_str(), l->second.c_str());
    if(l->first == "version" && l->second != "001.910") {
      WARNING("Unknown version.  Attempting to continue, but I might "
              "be interpreting this file incorrectly.");
    } else if(l->first == "number_of_dimensions" && l->second != "3") {
      WARNING("%s dimensions instead of 3; continuing anyway...",
              l->second.c_str());
    } else if(l->first == "x_dimension") {
      vVolumeSize[0] = convert<UINT64>(l->second);
    } else if(l->first == "y_dimension") {
      vVolumeSize[1] = convert<UINT64>(l->second);
    } else if(l->first == "z_dimension") {
      vVolumeSize[2] = convert<UINT64>(l->second);
    } else if(l->first == "pixel_size_x") {
      vVolumeAspect[0] = convert<float>(l->second);
    } else if(l->first == "pixel_size_y") {
      vVolumeAspect[1] = convert<float>(l->second);
    } else if(l->first == "pixel_size_z") {
      vVolumeAspect[2] = convert<float>(l->second);
    } else if(l->first == "data_type") {
      size_t type = convert<size_t>(l->second);
      switch(type) {
        case 1: // byte
          iComponentSize = 8;
          bConvertEndianess = false;
          bIsFloat = false;
          break;
        case 2: // 2-byte integer, intel style
          iComponentSize = 16;
          bConvertEndianess = EndianConvert::IsBigEndian();
          bIsFloat = false;
          break;
        case 3: // 4-byte integer, intel style
          iComponentSize = 32;
          bConvertEndianess = EndianConvert::IsBigEndian();
          bIsFloat = false;
          break;
        case 4: // 4-byte float, intel style
          iComponentSize = 32;
          bConvertEndianess = EndianConvert::IsBigEndian();
          bIsFloat = true;
          break;
        case 5: // 4-byte float, sun style
          iComponentSize = 32;
          bConvertEndianess = !EndianConvert::IsBigEndian();
          bIsFloat = true;
          break;
        case 6: // 2-byte integer, sun style
          iComponentSize = 16;
          bConvertEndianess = !EndianConvert::IsBigEndian();
          bIsFloat = false;
          break;
        case 7: // 4-byte integer, sun style
          iComponentSize = 32;
          bConvertEndianess = !EndianConvert::IsBigEndian();
          bIsFloat = false;
          break;
        default:
          T_ERROR("Unknown data type %u", static_cast<unsigned>(type));
          return false;
          break;
      }
    }
  }

  return true;
}

bool InveonConverter::ConvertToNative(
  const std::string& strRawFilename,
  const std::string& strTargetFilename,
  UINT64 iHeaderSkip,
  UINT64 iComponentSize, UINT64 iComponentCount,
  bool bSigned, bool bIsFloat,
  UINT64VECTOR3 vVolumeSize, FLOATVECTOR3 vVolumeAspect,
  bool bNoUserInteraction,
  const bool bQuantizeTo8Bit)
{
  std::ofstream hdr(strTargetFilename.c_str(), std::ios::out);
  if(!hdr.is_open()) {
    T_ERROR("Unable to open target file %s", strTargetFilename.c_str());
    return false;
  }

  hdr << "version 001.910\n"
      << "number_of_dimensions 3\n"
      << "x_dimension " << vVolumeSize[0] << "\n"
      << "y_dimension " << vVolumeSize[1] << "\n"
      << "z_dimension " << vVolumeSize[2] << "\n"
      << "pixel_size_x " << vVolumeAspect[0] << "\n"
      << "pixel_size_y " << vVolumeAspect[1] << "\n"
      << "pixel_size_z " << vVolumeAspect[2] << "\n"
      << "data_type ";
  if(iComponentSize == 8) {
    hdr << "1\n";
  } else if(iComponentSize == 16 && EndianConvert::IsBigEndian()) {
    hdr << "2\n";
  } else if(iComponentSize == 32 && EndianConvert::IsBigEndian() && !bIsFloat) {
    hdr << "3\n";
  } else if(iComponentSize == 32 && EndianConvert::IsBigEndian() && bIsFloat) {
    hdr << "4\n";
  } else if(iComponentSize == 32 && !EndianConvert::IsBigEndian() && bIsFloat) {
    hdr << "5\n";
  } else if(iComponentSize == 16 && !EndianConvert::IsBigEndian() && !bIsFloat) {
    hdr << "6\n";
  } else if(iComponentSize == 32 && !EndianConvert::IsBigEndian() && !bIsFloat) {
    hdr << "7\n";
  } else {
    T_ERROR("Unknown data type!\n");
    hdr << "0\n";
  }

  std::string data_file = SysTools::RemoveExt(strTargetFilename.c_str());
  if(!RAWConverter::ConvertToNative(
      strRawFilename, data_file, iHeaderSkip,  iComponentSize, iComponentCount,
      bSigned, bIsFloat, vVolumeSize, vVolumeAspect, bNoUserInteraction,
      bQuantizeTo8Bit)) {
    T_ERROR("Error creating raw file '%s'", data_file.c_str());
    remove(data_file.c_str());
    return false;
  }

  return true;
}

// checks for comment lines, ascii.
bool InveonConverter::CanRead(const std::string&,
                              const std::vector<int8_t>& start) const
{
  using namespace std::tr1::placeholders;

  // Are there any non-ascii characters?
  std::vector<int8_t>::const_iterator notascii = std::find_if(
    start.begin(), start.end(),
    std::tr1::bind(
      std::not_equal_to<int>(),
        std::tr1::bind(isascii, _1),
        1
      )
  );

  // first char is nothing/comment, and we couldn't find a character
  // which wasn't ascii.
  return (std::isspace(start[0]) || start[0] == '#') && notascii == start.end();
}
<commit_msg>Write out "#" comment character.<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2010 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.
*/

/**
  \file    InveonConverter.cpp
  \author  Tom Fogal
           SCI Institute
           University of Utah
*/
#include "../StdTuvokDefines.h"
#include <cctype>
#include <fstream>
#ifdef _MSC_VER
# include <functional>
# include <unordered_map>
#else
# include <tr1/functional>
# include <tr1/unordered_map>
#endif
#include <sstream>
#include <string>
#include "InveonConverter.h"
#include <Basics/EndianConvert.h>

InveonConverter::InveonConverter()
{
  m_vConverterDesc = "Inveon";
  m_vSupportedExt.push_back("HDR");
}

typedef std::tr1::unordered_map<std::string, std::string> LineMap;
// The 'hdr' files we are given consist of a series of lines which begin with a
// keyword, and then a series of space-separated parameters.  This searches for
// lines which begin with the strings in the keys of the map, and fills the
// values with the rest of the lines.
// Ex: a stream consists of:
//    abc 42
//    def 19
//    qwerty 12.5512 123
//    foo bar
// then if the input map contains:
//    "abc":""
//    "qwerty":""
//    "foo":""
// then the output map will contain:
//    "abc":"42"
//    "qwerty":"12.5512 123"
//    "foo":"bar"
static void
findlines(std::ifstream& ifs, LineMap& values)
{
  ifs.seekg(0);
  std::string line;

  while(ifs) {
    if(getline(ifs, line)) {
      // iterate through all our keys and see if the line begins with
      // any of them.
      for(LineMap::iterator l = values.begin(); l != values.end(); ++l) {
        if(line.find(l->first) == 0) {
          l->second = line.substr(l->first.length()+1); // +1: skip space.
        }
      }
    }
  }
}

namespace {
  template <typename T> T convert(const std::string& s) {
    T t;
    std::istringstream conv(s);
    conv >> t;
    return t;
  }
}

bool InveonConverter::ConvertToRAW(const std::string& strSourceFilename,
                                    const std::string&,
                                    bool /* bNoUserInteraction */,
                                    UINT64& iHeaderSkip,
                                    UINT64& iComponentSize,
                                    UINT64& iComponentCount,
                                    bool& bConvertEndianess, bool& bSigned,
                                    bool& bIsFloat, UINT64VECTOR3& vVolumeSize,
                                    FLOATVECTOR3& vVolumeAspect,
                                    std::string& strTitle,
                                    UVFTables::ElementSemanticTable& eType,
                                    std::string& strIntermediateFile,
                                    bool& bDeleteIntermediateFile)
{
  std::ifstream infn(strSourceFilename.c_str(), std::ios::in);
  if(!infn.is_open()) {
    T_ERROR("Could not open %s", strSourceFilename.c_str());
    return false;
  }

  iHeaderSkip = 0;
  iComponentCount = 1;
  eType = UVFTables::ES_UNDEFINED;
  bDeleteIntermediateFile = false;
  bSigned = true; // format does not distinguish
  strTitle = "Inveon";

  // The filename is actually stored in the header, but it includes
  // a full pathname and is thus garbage in many instances; e.g. the
  // files I have say:  "F:/somefolder/xyz/blah/whatever/file.ct.img",
  // and I'm on a Unix system, so "F:" doesn't even make sense.
  // Therefore we just ignore the filename in the header and use the
  // "hdr" filename sans the "hdr" extension, which seems to be the
  // convention.
  strIntermediateFile = SysTools::RemoveExt(strSourceFilename);

  LineMap lines;
  lines.insert(LineMap::value_type("version",""));
  lines.insert(LineMap::value_type("number_of_dimensions",""));
  lines.insert(LineMap::value_type("x_dimension",""));
  lines.insert(LineMap::value_type("y_dimension",""));
  lines.insert(LineMap::value_type("z_dimension",""));
  lines.insert(LineMap::value_type("pixel_size_x",""));
  lines.insert(LineMap::value_type("pixel_size_y",""));
  lines.insert(LineMap::value_type("pixel_size_z",""));
  lines.insert(LineMap::value_type("data_type",""));

  findlines(infn, lines);

  for(LineMap::const_iterator l = lines.begin(); l != lines.end(); ++l) {
    MESSAGE("read %s -> '%s'", l->first.c_str(), l->second.c_str());
    if(l->first == "version" && l->second != "001.910") {
      WARNING("Unknown version.  Attempting to continue, but I might "
              "be interpreting this file incorrectly.");
    } else if(l->first == "number_of_dimensions" && l->second != "3") {
      WARNING("%s dimensions instead of 3; continuing anyway...",
              l->second.c_str());
    } else if(l->first == "x_dimension") {
      vVolumeSize[0] = convert<UINT64>(l->second);
    } else if(l->first == "y_dimension") {
      vVolumeSize[1] = convert<UINT64>(l->second);
    } else if(l->first == "z_dimension") {
      vVolumeSize[2] = convert<UINT64>(l->second);
    } else if(l->first == "pixel_size_x") {
      vVolumeAspect[0] = convert<float>(l->second);
    } else if(l->first == "pixel_size_y") {
      vVolumeAspect[1] = convert<float>(l->second);
    } else if(l->first == "pixel_size_z") {
      vVolumeAspect[2] = convert<float>(l->second);
    } else if(l->first == "data_type") {
      size_t type = convert<size_t>(l->second);
      switch(type) {
        case 1: // byte
          iComponentSize = 8;
          bConvertEndianess = false;
          bIsFloat = false;
          break;
        case 2: // 2-byte integer, intel style
          iComponentSize = 16;
          bConvertEndianess = EndianConvert::IsBigEndian();
          bIsFloat = false;
          break;
        case 3: // 4-byte integer, intel style
          iComponentSize = 32;
          bConvertEndianess = EndianConvert::IsBigEndian();
          bIsFloat = false;
          break;
        case 4: // 4-byte float, intel style
          iComponentSize = 32;
          bConvertEndianess = EndianConvert::IsBigEndian();
          bIsFloat = true;
          break;
        case 5: // 4-byte float, sun style
          iComponentSize = 32;
          bConvertEndianess = !EndianConvert::IsBigEndian();
          bIsFloat = true;
          break;
        case 6: // 2-byte integer, sun style
          iComponentSize = 16;
          bConvertEndianess = !EndianConvert::IsBigEndian();
          bIsFloat = false;
          break;
        case 7: // 4-byte integer, sun style
          iComponentSize = 32;
          bConvertEndianess = !EndianConvert::IsBigEndian();
          bIsFloat = false;
          break;
        default:
          T_ERROR("Unknown data type %u", static_cast<unsigned>(type));
          return false;
          break;
      }
    }
  }

  return true;
}

bool InveonConverter::ConvertToNative(
  const std::string& strRawFilename,
  const std::string& strTargetFilename,
  UINT64 iHeaderSkip,
  UINT64 iComponentSize, UINT64 iComponentCount,
  bool bSigned, bool bIsFloat,
  UINT64VECTOR3 vVolumeSize, FLOATVECTOR3 vVolumeAspect,
  bool bNoUserInteraction,
  const bool bQuantizeTo8Bit)
{
  std::ofstream hdr(strTargetFilename.c_str(), std::ios::out);
  if(!hdr.is_open()) {
    T_ERROR("Unable to open target file %s", strTargetFilename.c_str());
    return false;
  }

  hdr << "#\n" // we use this to check if it's an Inveon file
      << "version 001.910\n"
      << "number_of_dimensions 3\n"
      << "x_dimension " << vVolumeSize[0] << "\n"
      << "y_dimension " << vVolumeSize[1] << "\n"
      << "z_dimension " << vVolumeSize[2] << "\n"
      << "pixel_size_x " << vVolumeAspect[0] << "\n"
      << "pixel_size_y " << vVolumeAspect[1] << "\n"
      << "pixel_size_z " << vVolumeAspect[2] << "\n"
      << "data_type ";
  if(iComponentSize == 8) {
    hdr << "1\n";
  } else if(iComponentSize == 16 && EndianConvert::IsBigEndian()) {
    hdr << "2\n";
  } else if(iComponentSize == 32 && EndianConvert::IsBigEndian() && !bIsFloat) {
    hdr << "3\n";
  } else if(iComponentSize == 32 && EndianConvert::IsBigEndian() && bIsFloat) {
    hdr << "4\n";
  } else if(iComponentSize == 32 && !EndianConvert::IsBigEndian() && bIsFloat) {
    hdr << "5\n";
  } else if(iComponentSize == 16 && !EndianConvert::IsBigEndian() && !bIsFloat) {
    hdr << "6\n";
  } else if(iComponentSize == 32 && !EndianConvert::IsBigEndian() && !bIsFloat) {
    hdr << "7\n";
  } else {
    T_ERROR("Unknown data type!\n");
    hdr << "0\n";
  }

  std::string data_file = SysTools::RemoveExt(strTargetFilename.c_str());
  if(!RAWConverter::ConvertToNative(
      strRawFilename, data_file, iHeaderSkip,  iComponentSize, iComponentCount,
      bSigned, bIsFloat, vVolumeSize, vVolumeAspect, bNoUserInteraction,
      bQuantizeTo8Bit)) {
    T_ERROR("Error creating raw file '%s'", data_file.c_str());
    remove(data_file.c_str());
    return false;
  }

  return true;
}

// checks for comment lines, ascii.
bool InveonConverter::CanRead(const std::string&,
                              const std::vector<int8_t>& start) const
{
  using namespace std::tr1::placeholders;

  // Are there any non-ascii characters?
  std::vector<int8_t>::const_iterator notascii = std::find_if(
    start.begin(), start.end(),
    std::tr1::bind(
      std::not_equal_to<int>(),
        std::tr1::bind(isascii, _1),
        1
      )
  );

  // first char is nothing/comment, and we couldn't find a character
  // which wasn't ascii.
  return (std::isspace(start[0]) || start[0] == '#') && notascii == start.end();
}
<|endoftext|>