<commit_before>/**
 * This file is part of the CernVM File System.
 */

#include <fcntl.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include <vector>

#include "logging.h"

#include "file_watcher_kqueue.h"

namespace file_watcher {

FileWatcherKqueue::FileWatcherKqueue() {}

FileWatcherKqueue::~FileWatcherKqueue() {}

bool FileWatcherKqueue::RunEventLoop(const FileWatcher::HandlerMap& handlers,
                                     int control_pipe) {
  kq_ = kqueue();
  if (kq_ == -1) {
    LogCvmfs(kLogCvmfs, kLogDebug, "Cannot create kqueue.");
    return false;
  }

  // Control pipe sending the stop event.
  struct kevent watch_event;
  EV_SET(&watch_event, control_pipe, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR,
         0, 0, 0);
  if (kevent(kq_, &watch_event, 1, NULL, 0, NULL) == -1) {
    LogCvmfs(kLogCvmfs, kLogDebug, "Could not register event with kqueue.");
    return false;
  }

  for (FileWatcher::HandlerMap::const_iterator it = handlers.begin();
       it != handlers.end(); ++it) {
    RegisterFilter(it->first, it->second);
  }

  bool stop = false;
  while (!stop) {
    std::vector<struct kevent> triggered_events(handlers.size() + 1);
    int nev = kevent(kq_, NULL, 0, &triggered_events[0], triggered_events.size(), NULL);
    if (nev == -1) {
      LogCvmfs(kLogCvmfs, kLogDebug, "Could not poll events.");
      return false;
    }
    if (nev == 0) {
      continue;
    }
    for (int i = 0; i < nev; ++i) {
      struct kevent& current_ev = triggered_events[i];
      if (current_ev.ident == static_cast<uint64_t>(control_pipe)) {
        char buffer[1];
        read(control_pipe, &buffer, 1);
        LogCvmfs(kLogCvmfs, kLogDebug, "Stopping.\n");
        stop = true;
        continue;
      } else {
        std::map<int, WatchRecord>::const_iterator
            it = watch_records_.find(current_ev.ident);
        if (it != watch_records_.end()) {
          int current_fd = current_ev.ident;
          WatchRecord current_record = it->second;
          file_watcher::Event event = file_watcher::kInvalid;
          if (current_ev.fflags & NOTE_DELETE) {
            event = file_watcher::kDeleted;
          } else if (current_ev.fflags & NOTE_LINK) {
            // Hardlinked
            event = file_watcher::kHardlinked;
          } else if (current_ev.fflags & NOTE_WRITE) {
            // Modified
            event = file_watcher::kModified;
          } else if (current_ev.fflags & NOTE_RENAME) {
            // Renamed
            event = file_watcher::kRenamed;
          } else if (current_ev.fflags & NOTE_ATTRIB) {
            // Attributes
            event = file_watcher::kAttributes;
          }
          if (event != file_watcher::kInvalid) {
            current_record.handler_->Handle(current_record.file_path_, event);
          } else {
            LogCvmfs(kLogCvmfs, kLogDebug, "Unknown event 0x%x\n", current_ev.fflags);
          }

          // Perform post-handling actions (i.e. remove, reset filter)
          if (event == file_watcher::kDeleted) {
            RemoveFilter(current_fd);
            const std::string file_path = watch_records_[current_fd].file_path_;
            EventHandler* handler = watch_records_[current_fd].handler_;
            RegisterFilter(file_path, handler);
          }
        } else {
          LogCvmfs(kLogCvmfs, kLogDebug, "Unknown kevent ident: %ld", current_ev.ident);
        }
      }
    }
  }
  return true;
}

void FileWatcherKqueue::RemoveFilter(int fd) {
  struct kevent remove_event;
  EV_SET(&remove_event, fd, EVFILT_VNODE, EV_DELETE,
         NULL, 0, 0);
  if (kevent(kq_, &remove_event, 1, NULL, 0, NULL) == -1) {
    LogCvmfs(kLogCvmfs, kLogDebug, "Could not remove event filter from kqueue.");
  }
  close(fd);
  watch_records_.erase(fd);
}

void FileWatcherKqueue::RegisterFilter(const std::string& file_path,
                                       EventHandler* handler) {
  int fd = open(file_path.c_str(), O_RDONLY);
  if (fd == -1) {
    LogCvmfs(kLogCvmfs, kLogDebug, "Cannot open `%s'", file_path.c_str());
    return;
  }
  struct kevent watch_event;
  EV_SET(&watch_event, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
         NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK|NOTE_RENAME|NOTE_REVOKE,
         0, 0);

  if (kevent(kq_, &watch_event, 1, NULL, 0, NULL) == -1) {
    LogCvmfs(kLogCvmfs, kLogDebug, "Could not register event with kqueue.");
    return;
  }

  watch_records_[fd] = WatchRecord(file_path, handler);
}

}  // namespace file_watcher
<commit_msg>FileWatcherKqueue - Implement retry loop when file is deleted<commit_after>/**
 * This file is part of the CernVM File System.
 */

#include <fcntl.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include <vector>

#include "backoff.h"
#include "file_watcher_kqueue.h"
#include "logging.h"
#include "util/posix.h"

namespace file_watcher {

FileWatcherKqueue::FileWatcherKqueue() {}

FileWatcherKqueue::~FileWatcherKqueue() {}

bool FileWatcherKqueue::RunEventLoop(const FileWatcher::HandlerMap& handlers,
                                     int control_pipe) {
  kq_ = kqueue();
  if (kq_ == -1) {
    LogCvmfs(kLogCvmfs, kLogDebug, "FileWatcherKqueue - Cannot create kqueue.");
    return false;
  }

  // Control pipe sending the stop event.
  struct kevent watch_event;
  EV_SET(&watch_event, control_pipe, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR,
         0, 0, 0);
  if (kevent(kq_, &watch_event, 1, NULL, 0, NULL) == -1) {
    LogCvmfs(kLogCvmfs, kLogDebug, "FileWatcherKqueue - Could not register event with kqueue.");
    return false;
  }

  for (FileWatcher::HandlerMap::const_iterator it = handlers.begin();
       it != handlers.end(); ++it) {
    RegisterFilter(it->first, it->second);
  }

  bool stop = false;
  while (!stop) {
    std::vector<struct kevent> triggered_events(handlers.size() + 1);
    int nev = kevent(kq_, NULL, 0, &triggered_events[0], triggered_events.size(), NULL);
    if (nev == -1) {
      LogCvmfs(kLogCvmfs, kLogDebug, "FileWatcherKqueue - Could not poll events.");
      return false;
    }
    if (nev == 0) {
      continue;
    }
    for (int i = 0; i < nev; ++i) {
      struct kevent& current_ev = triggered_events[i];
      if (current_ev.ident == static_cast<uint64_t>(control_pipe)) {
        char buffer[1];
        read(control_pipe, &buffer, 1);
        LogCvmfs(kLogCvmfs, kLogDebug, "FileWatcherKqueue - Stopping.\n");
        stop = true;
        continue;
      } else {
        std::map<int, WatchRecord>::const_iterator
            it = watch_records_.find(current_ev.ident);
        if (it != watch_records_.end()) {
          int current_fd = current_ev.ident;
          WatchRecord current_record = it->second;
          file_watcher::Event event = file_watcher::kInvalid;
          if (current_ev.fflags & NOTE_DELETE) {
            event = file_watcher::kDeleted;
          } else if (current_ev.fflags & NOTE_LINK) {
            // Hardlinked
            event = file_watcher::kHardlinked;
          } else if (current_ev.fflags & NOTE_WRITE) {
            // Modified
            event = file_watcher::kModified;
          } else if (current_ev.fflags & NOTE_RENAME) {
            // Renamed
            event = file_watcher::kRenamed;
          } else if (current_ev.fflags & NOTE_ATTRIB) {
            // Attributes
            event = file_watcher::kAttributes;
          }
          if (event != file_watcher::kInvalid) {
            current_record.handler_->Handle(current_record.file_path_, event);
          } else {
            LogCvmfs(kLogCvmfs, kLogDebug, "FileWatcherKqueue - Unknown event 0x%x\n", current_ev.fflags);
          }

          // Perform post-handling actions (i.e. remove, reset filter)
          if (event == file_watcher::kDeleted) {
            const std::string file_path = watch_records_[current_fd].file_path_;
            EventHandler* handler = watch_records_[current_fd].handler_;
            RemoveFilter(current_fd);
            RegisterFilter(file_path, handler);
          }
        } else {
          LogCvmfs(kLogCvmfs, kLogDebug, "FileWatcherKqueue - Unknown kevent ident: %ld", current_ev.ident);
        }
      }
    }
  }
  return true;
}

void FileWatcherKqueue::RemoveFilter(int fd) {
  struct kevent remove_event;
  EV_SET(&remove_event, fd, EVFILT_VNODE, EV_DELETE,
         NULL, 0, 0);
  if (kevent(kq_, &remove_event, 1, NULL, 0, NULL) == -1) {
    LogCvmfs(kLogCvmfs, kLogDebug, "FileWatcherKqueue - Could not remove event filter from kqueue.");
  }
  close(fd);
  watch_records_.erase(fd);
}

void FileWatcherKqueue::RegisterFilter(const std::string& file_path,
                                       EventHandler* handler) {
  bool done = false;
  BackoffThrottle throttle(1000, 10000, 50000);
  while ((!done)) {
    int fd = open(file_path.c_str(), O_RDONLY);
    if (fd == -1) {
      LogCvmfs(kLogCvmfs, kLogDebug,
               "FileWatcherKqueue - Cannot open file %s. Retrying.",
               file_path.c_str());
      throttle.Throttle();
      continue;
    }
    struct kevent watch_event;
    EV_SET(&watch_event, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
           NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK|NOTE_RENAME|NOTE_REVOKE,
           0, 0);

    if (kevent(kq_, &watch_event, 1, NULL, 0, NULL) == -1) {
      LogCvmfs(kLogCvmfs, kLogDebug, "FileWatcherKqueue - Could not register event with kqueue.");
      return;
    }

    watch_records_[fd] = WatchRecord(file_path, handler);

    done = true;
  }
  throttle.Reset();
}

}  // namespace file_watcher
<|endoftext|>


<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Ash Berlin, Aristid Breitkreuz

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

#include "flusspferd/object.hpp"
#include "flusspferd/string.hpp"
#include "flusspferd/evaluate.hpp"
#include "flusspferd/security.hpp"
#include "flusspferd/exception.hpp"
#include "flusspferd/io/io.hpp"
#include "test_environment.hpp"
#include <iostream>
#include <string>

#ifdef FLUSSPFERD_HAVE_IO

BOOST_FIXTURE_TEST_SUITE( io, context_fixture )

BOOST_AUTO_TEST_CASE( test_have_IO ) {
  flusspferd::io::load_io();
  flusspferd::root_value v;
  BOOST_CHECK_NO_THROW( v = flusspferd::evaluate("IO", __FILE__, __LINE__) );
  BOOST_CHECK(v.is_object());
  BOOST_CHECK(!v.is_null());

  flusspferd::gc();
}

BOOST_AUTO_TEST_CASE( IO_no_security ) {
  flusspferd::io::load_io();

  const char* js = "f = new IO.File('test/fixtures/file1'); f.readWhole()";
  flusspferd::root_value v;
  BOOST_CHECK_THROW(
    v = flusspferd::evaluate(js, __FILE__, __LINE__),
    flusspferd::exception);
}

BOOST_AUTO_TEST_CASE( test_file_read ) {
  flusspferd::io::load_io();
  flusspferd::security::create(flusspferd::global());

  const char* js = "f = new IO.File('test/fixtures/file1'); f.readWhole()";
  flusspferd::root_value v;
  BOOST_CHECK_NO_THROW( v = flusspferd::evaluate(js, __FILE__, __LINE__) );
  BOOST_CHECK_EQUAL(v.to_string().c_str(), "foobar\nbaz\n");

  js = "f = new IO.File('test/fixtures/file1'); f.readWhole()";
  BOOST_CHECK_NO_THROW( v = flusspferd::evaluate(js, __FILE__, __LINE__) );
  BOOST_CHECK_EQUAL(v.to_string().c_str(), "foobar\nbaz\n");

  flusspferd::gc();
}

BOOST_AUTO_TEST_SUITE_END()

#endif
<commit_msg>tests: fix failing testcases<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Ash Berlin, Aristid Breitkreuz

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

#include "flusspferd/object.hpp"
#include "flusspferd/string.hpp"
#include "flusspferd/evaluate.hpp"
#include "flusspferd/security.hpp"
#include "flusspferd/exception.hpp"
#include "flusspferd/io/io.hpp"
#include "test_environment.hpp"
#include <iostream>
#include <string>

#ifdef FLUSSPFERD_HAVE_IO

BOOST_FIXTURE_TEST_SUITE( io, context_fixture )

BOOST_AUTO_TEST_CASE( IO_no_security ) {
  flusspferd::object IO = flusspferd::create_object();
  flusspferd::global().set_property("IO", IO);
  flusspferd::io::load_io(IO);

  const char* js = "f = new IO.File('test/fixtures/file1'); f.readWhole()";
  flusspferd::root_value v;
  BOOST_CHECK_THROW(
    v = flusspferd::evaluate(js, __FILE__, __LINE__),
    flusspferd::exception);
}

BOOST_AUTO_TEST_CASE( test_file_read ) {
  flusspferd::object IO = flusspferd::create_object();
  flusspferd::global().set_property("IO", IO);
  flusspferd::io::load_io(IO);

  flusspferd::security::create(flusspferd::global());

  const char* js = "f = new IO.File('test/fixtures/file1'); f.readWhole()";
  flusspferd::root_value v;
  BOOST_CHECK_NO_THROW( v = flusspferd::evaluate(js, __FILE__, __LINE__) );
  BOOST_CHECK_EQUAL(v.to_string().c_str(), "foobar\nbaz\n");

  js = "f = new IO.File('test/fixtures/file1'); f.readWhole()";
  BOOST_CHECK_NO_THROW( v = flusspferd::evaluate(js, __FILE__, __LINE__) );
  BOOST_CHECK_EQUAL(v.to_string().c_str(), "foobar\nbaz\n");

  flusspferd::gc();
}

BOOST_AUTO_TEST_SUITE_END()

#endif
<|endoftext|>


<commit_before>#define START 0
#define ENTRY 0

#include "timings.h"

#include <libcpu.h>
#include "arch/mips/libcpu_mips.h"
#include "arch/arm/libcpu_arm.h"
#include "arch/m88k/libcpu_m88k.h"
#include "arch/m88k/m88k_isa.h"
#include "arch/x86/libcpu_x86.h"

#define RET_MAGIC 0x4D495354

static void
debug_function(cpu_t *cpu)
{
	fprintf(stderr, "%s:%u\n", __FILE__, __LINE__);
}

//////////////////////////////////////////////////////////////////////
#define SINGLESTEP_NONE	0
#define SINGLESTEP_STEP	1
#define SINGLESTEP_BB	2
//////////////////////////////////////////////////////////////////////

int
main(int argc, char **argv)
{
	char *executable;
	cpu_arch_t arch;
	cpu_t *cpu;
	uint8_t *RAM;
	FILE *f;
	int ramsize;

	int singlestep = SINGLESTEP_NONE;
	int log = 1;
	int print_ir = 1;

	/* parameter parsing */
	if (argc < 2) {
		printf("Usage: %s [binary]\n", argv[0]);
		return 0;
	}
	executable = argv[1];
	arch = CPU_ARCH_8086;

	ramsize = 1*1024*1024;
	RAM = (uint8_t*)malloc(ramsize);

	cpu = cpu_new(arch, 0, 0);

	cpu_set_flags_optimize(cpu, CPU_OPTIMIZE_ALL);
	cpu_set_flags_debug(cpu, 0
		| (print_ir? CPU_DEBUG_PRINT_IR : 0)
		| (print_ir? CPU_DEBUG_PRINT_IR_OPTIMIZED : 0)
		| (log? CPU_DEBUG_LOG :0)
		| (singlestep == SINGLESTEP_STEP? CPU_DEBUG_SINGLESTEP    : 0)
		| (singlestep == SINGLESTEP_BB?   CPU_DEBUG_SINGLESTEP_BB : 0)
		);

	cpu_set_ram(cpu, RAM);

	/* load code */
	if (!(f = fopen(executable, "rb"))) {
		printf("Could not open %s!\n", executable);
		return 2;
	}
	cpu->code_start = START;
	cpu->code_end = cpu->code_start + fread(&RAM[cpu->code_start], 1, ramsize-cpu->code_start, f);
	fclose(f);
	cpu->code_entry = cpu->code_start + ENTRY;

	cpu_tag(cpu, cpu->code_entry);

	cpu_translate(cpu); /* force translation now */

	printf("\n*** Executing...\n");

	printf("GUEST run..."); fflush(stdout);

	cpu_run(cpu, debug_function);

	printf("done!\n");

	cpu_free(cpu);

	return 0;
}
<commit_msg>x86: Disable IR printing by default<commit_after>#define START 0
#define ENTRY 0

#include "timings.h"

#include <libcpu.h>
#include "arch/mips/libcpu_mips.h"
#include "arch/arm/libcpu_arm.h"
#include "arch/m88k/libcpu_m88k.h"
#include "arch/m88k/m88k_isa.h"
#include "arch/x86/libcpu_x86.h"

#define RET_MAGIC 0x4D495354

static void
debug_function(cpu_t *cpu)
{
	fprintf(stderr, "%s:%u\n", __FILE__, __LINE__);
}

//////////////////////////////////////////////////////////////////////
#define SINGLESTEP_NONE	0
#define SINGLESTEP_STEP	1
#define SINGLESTEP_BB	2
//////////////////////////////////////////////////////////////////////

int
main(int argc, char **argv)
{
	char *executable;
	cpu_arch_t arch;
	cpu_t *cpu;
	uint8_t *RAM;
	FILE *f;
	int ramsize;

	int singlestep = SINGLESTEP_NONE;
	int log = 1;
	int print_ir = 0;

	/* parameter parsing */
	if (argc < 2) {
		printf("Usage: %s [--print-ir] <binary>\n", argv[0]);
		return 0;
	}
	if (!strcmp(argv[1], "--print-ir")) {
		print_ir = 1;
		argv++;
	}
	executable = argv[1];
	arch = CPU_ARCH_8086;

	ramsize = 1*1024*1024;
	RAM = (uint8_t*)malloc(ramsize);

	cpu = cpu_new(arch, 0, 0);

	cpu_set_flags_optimize(cpu, CPU_OPTIMIZE_ALL);
	cpu_set_flags_debug(cpu, 0
		| (print_ir? CPU_DEBUG_PRINT_IR : 0)
		| (print_ir? CPU_DEBUG_PRINT_IR_OPTIMIZED : 0)
		| (log? CPU_DEBUG_LOG :0)
		| (singlestep == SINGLESTEP_STEP? CPU_DEBUG_SINGLESTEP    : 0)
		| (singlestep == SINGLESTEP_BB?   CPU_DEBUG_SINGLESTEP_BB : 0)
		);

	cpu_set_ram(cpu, RAM);

	/* load code */
	if (!(f = fopen(executable, "rb"))) {
		printf("Could not open %s!\n", executable);
		return 2;
	}
	cpu->code_start = START;
	cpu->code_end = cpu->code_start + fread(&RAM[cpu->code_start], 1, ramsize-cpu->code_start, f);
	fclose(f);
	cpu->code_entry = cpu->code_start + ENTRY;

	cpu_tag(cpu, cpu->code_entry);

	cpu_translate(cpu); /* force translation now */

	printf("\n*** Executing...\n");

	printf("GUEST run..."); fflush(stdout);

	cpu_run(cpu, debug_function);

	printf("done!\n");

	cpu_free(cpu);

	return 0;
}
<|endoftext|>


<commit_before>/*
PStreams - POSIX Process I/O for C++
Copyright (C) 2002 Jonathan Wakely

This file is part of PStreams.

PStreams is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.

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

You should have received a copy of the GNU Lesser General Public License
along with PStreams; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#define REDI_PSTREAMS_POPEN_USES_BIDIRECTIONAL_PIPE 1

//#include "pstream_compat.h"

// TODO test rpstream - this does nothing for the moment
#define TEST_RPSTREAM 1

// test eviscerated pstreams
#define REDI_EVISCERATE_PSTREAMS 1

#include "pstream.h"

#if TEST_RPSTREAM
#include "rpstream.h"
#endif

// include these after pstream.h to ensure it #includes everything it needs
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <fstream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
//#include <fcntl.h>
#include <errno.h>

using namespace std;
using namespace redi;

namespace  // anon
{
    // helper functions for printing test results

    string
    test_type(const istream& s)
    { return "r"; }

    string
    test_type(const ostream& s)
    { return "w"; }

    string
    test_type(const iostream& s)
    { return "b"; }

    template <typename T>
    string
    test_id(const T& s)
    {
        static int count = 0;
        ostringstream buf;
        buf << test_type(s) << ++count;
        return buf.str();
    }

    template <typename T>
    void
    print_result(const T& s, bool result)
    {
        clog << "Test " << setw(4) << test_id(s) << ": "
            << (result ? "Pass" : "Fail!")
            << endl;
    }

    template <typename T>
    bool
    check_pass(const T& s, bool expected = true)
    {
        bool res = s.good() == expected;
        print_result(s, res);
        return res;
    }

    template <typename T>
    bool
    check_fail(const T& s) { return check_pass(s, false); }
}

int main()
{
    ios_base::sync_with_stdio();

    string str;

    clog << "# Testing basic I/O\n";

    {
        // test formatted output
        //
        // This should read the strings on stdin and print them on stdout
        // prefixed by "STDOUT: "

        opstream os("/bin/sed 's/^./STDIN: &/' - /etc/issue");
        os << ".fnord.\n";
        str = "..fnord..\n";
        os << str;
        check_pass(os);
    }

    {
        // test execve() style construction
        //
        // This should read the strings on stdin and print them on stdout
        // prefixed by "STDIN: "

        vector<string> argv;
        argv.push_back("sed");
        argv.push_back("s/^./STDIN: &/");
        opstream os("sed", argv);

        check_pass(os << "Magic Monkey\n");
    }

    {
        // test unformatted output
        //
        // This should read the strings on stdin and print them on stdout
        // prefixed by "STDIN: "

        opstream sed("/bin/sed 's/^./STDIN: &/'");
        str = "Monkey Magic\n";
        for (string::const_iterator i = str.begin(); i!=str.end(); ++i)
            sed.put(*i);
        check_pass(sed);
    }

    {
        // test formatted input
        // should print hostname on stdout, prefixed by "STDOUT: "
        ipstream host("hostname");
        if (getline(host, str))  // extracts up to newline, eats newline
            cout << "STDOUT: " << str << endl;
        check_pass(host);
        // check we hit EOF at next read
        char c;
        print_result(host, !host.get(c));
        print_result(host, host.eof());
        check_fail(host);
    }

    {
        // test unformatted input
        // should print hostname on stdout, prefixed by "STDOUT: "
        ipstream host("date");
        str.clear();
        char c;
        while (host.get(c))  // extracts up to EOF (including newline)
            str += c;
        cout << "STDOUT:  " << str << flush;
        print_result(host, host.eof());
    }

    {
        // open after construction, then write
        opstream os;
        os.open("/bin/sed 's/^./STDIN: &/'");
        os << "Hello, world!\n";
        check_pass(os);
    }

    {
        // open after construction, then read
        ipstream is;
        is.open("hostname");
        string s;
        is >> s;
        cout << "STDOUT: " << s << endl;
        check_pass(is);
    }

    {
        // open after construction, then write
        ipstream host;
        host.open("hostname");
        if (host >> str)
            cout << "STDOUT: " << str << endl;
        check_pass(host);
        // chomp newline and try to read past end
        char c;
        host.get(c);
        host.get(c);
        check_fail(host);
    }

    clog << "# Testing bidirectional PStreams\n";

    pstreambuf::pmode all3streams =
        pstreambuf::pstdin|pstreambuf::pstdout|pstreambuf::pstderr;

    {
        // test output on bidirectional pstream
        string cmd = "grep ^127 -- /etc/hosts /no/such/file";
        pstream ps(cmd, all3streams);

        print_result(ps, ps.is_open());
        print_result(ps, ps.out());
        print_result(ps, ps.err());

        string buf;
        while (getline(ps.out(), buf))
            cout << "STDOUT: " << buf << endl;
        check_fail(ps);
        while (getline(ps.err(), buf))
            cout << "STDERR: " << buf << endl;
        check_fail(ps);
    }

    {
        // test input on bidirectional pstream and test peof manip
        string cmd = "grep fnord -- -";
        pstream ps(cmd, all3streams);

        print_result(ps, ps.is_open());
        print_result(ps, ps);

        ps << "12345\nfnord\n0000" << peof;
        // manip calls ps.rdbuf()->peof();

        string buf;
        getline(ps.out(), buf);

        do
        {
            print_result(ps, buf == "fnord");
            cout << "STDOUT: " << buf << endl;
        } while (getline(ps.out(), buf));

        print_result(ps, !(ps << "pipe closed, no fnord now"));
        check_fail(ps);
    }
    // TODO - test child moves onto next file after peof on stdin

    {
        // test signals
        string cmd = "grep 127 -- -";
        pstream ps(cmd, all3streams);

        pstreambuf* pbuf = ps.rdbuf();

        int e1 = pbuf->error();
        print_result(ps, e1 == 0);
        pbuf->kill(SIGTERM);
        int e2 = pbuf->error();
        print_result(ps, e1 == e2);

        pbuf->close();
        int e3 = pbuf->error();
        print_result(ps, !(ps << "127 fail 127\n"));
        print_result(ps, e1 == e3);
    }

    clog << "# Testing behaviour with bad commands" << endl;

    //string badcmd = "hgfhdgf";
    string badcmd = "hgfhdgf 2>/dev/null";

    {
        // check eof() works
        ipstream is(badcmd);
        print_result(is, is.get()==EOF);
        print_result(is, is.eof() );
    }

    {
        // test writing to bad command
        opstream ofail(badcmd);
        sleep(1);  // give shell time to try command and exit
        // this would cause SIGPIPE: ofail<<"blahblah";
        // does not show failure: print_result(ofail, !ofail.is_open());
        pstreambuf* buf = ofail.rdbuf();
        print_result(ofail, buf->exited());
        int status = buf->status();
        print_result(ofail, WIFEXITED(status) && WEXITSTATUS(status)==127);
    }

    {
        // reading from bad cmd
        vector<string> argv;
        argv.push_back("hdhdhd");
        argv.push_back("arg1");
        argv.push_back("arg2");
        ipstream ifail("hdhdhd", argv);
        check_fail(ifail>>str);
    }

    clog << "# Testing behaviour with uninit'ed streams" << endl;

    {
        // check eof() works
        ipstream is;
        print_result(is, is.get()==EOF);
        print_result(is, is.eof() );
    }

    {
        // test writing to no command
        opstream ofail;
        check_fail(ofail<<"blahblah");
    }

    clog << "# Testing other member functions\n";

    {
        string cmd("grep re");
        opstream s(cmd);
        print_result(s, cmd == s.command());
    }

    {
        string cmd("grep re");
        opstream s;
        s.open(cmd);
        print_result(s, cmd == s.command());
    }

    {
        string cmd("/bin/ls");
        ipstream s(cmd);
        print_result(s, cmd == s.command());
    }

    {
        string cmd("/bin/ls");
        ipstream s;
        s.open(cmd);
        print_result(s, cmd == s.command());
    }

    // TODO more testing of other members

    clog << "# Testing writing to closed stream\n";

    {
        opstream os("sed 's/foo/FOO/'");
        os << "foo\n";
        os.close();
        if (os << "bar\n")
            cout << "Wrote to closed stream" << endl;
        print_result(os, !(os << "bar\n"));
    }

#if REDI_EVISCERATE_PSTREAMS
    clog << "# Testing eviscerated pstream\n";

    {
        opstream os("sed 's/.*/FNORD/'");
        FILE *in, *out, *err;
        size_t res = os.fopen(in, out, err);
        print_result(os, res & pstreambuf::pstdin);
        print_result(os, in!=NULL);
        int i = fputs("flax\n", in);
        fflush(in);
        print_result(os, i>=0 && i!=EOF);
    }

    {
        string cmd = "ls /etc/motd /no/such/file";
        ipstream is(cmd, pstreambuf::pstdout|pstreambuf::pstderr);
        FILE *in, *out, *err;
        size_t res = is.fopen(in, out, err);
        print_result(is, res & pstreambuf::pstdout);
        print_result(is, res & pstreambuf::pstderr);
        print_result(is, out!=NULL);
        print_result(is, err!=NULL);

        size_t len = 256;
        char buf[len];
        char* p = fgets(buf, len, out);
        cout << "STDOUT: " << buf;
        print_result(is, p!=NULL);

        p = fgets(buf, len, err);
        cout << "STDERR: " << buf;
        print_result(is, p!=NULL);
    }

    {
        string cmd = "grep 127 -- - /etc/hosts /no/such/file";
        pstream ps(cmd, all3streams);
        FILE *in, *out, *err;
        size_t res = ps.fopen(in, out, err);
        print_result(ps, res & pstreambuf::pstdin);
        print_result(ps, res & pstreambuf::pstdout);
        print_result(ps, res & pstreambuf::pstderr);
        print_result(ps, in!=NULL);
        print_result(ps, out!=NULL);
        print_result(ps, err!=NULL);

        // ps << "12345\n1112777\n0000" << EOF;
#if 0
        size_t len = 256;
        char buf[len];
        char* p = fgets(buf, len, out);
        cout << "STDOUT: " << buf;
        print_result(ps, p!=NULL);

        p = fgets(buf, len, err);
        cout << "STDERR: " << buf;
        print_result(ps, p!=NULL);
#endif
    }

#endif

#if TEST_RPSTREAM
#endif

#if 0

#ifdef _STREAM_COMPAT

    // check fstreambase doesn't try to close() an attached fd
    FILE* f = fopen("/tmp/poo", "a");
    fprintf(f, "text\n");
    fflush(f);
    {
        fstream fs;
        fs.attach(fileno(f));
        fs << "more text" << endl;
    }
    fprintf(f, "even more text\n");
    fflush(f);
    cout << "retval of fclose(): " << fclose(f) << endl;

    // same check again, using only filedescs (no FILE*s)
    int fd = open("/tmp/oops", O_CREAT|O_WRONLY, 0777);
    clog << errno << ' ' << strerror(errno) << endl;
    errno=0;
    clog << write(fd, "TEXT\n", 5) << endl;
    clog << errno << ' ' << strerror(errno) << endl;
    errno=0;
    fsync(fd);
    {
        ofstream fs(fd);
        fs << "MORE TEXT" << endl;
        clog << strerror(errno) << endl;
        errno=0;
    }
    clog << write(fd, "EVEN MORE TEXT\n", 15) << endl;
    clog << strerror(errno) << endl;
    errno=0;
    fsync(fd);
    close(fd);
#endif  // _STREAM_COMPAT

#endif

    return 0;
}

<commit_msg>Tidy up calls totest functions, use check_pass/check_fail where possible. Remove block of old, unused code.<commit_after>/*
PStreams - POSIX Process I/O for C++
Copyright (C) 2002 Jonathan Wakely

This file is part of PStreams.

PStreams is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.

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

You should have received a copy of the GNU Lesser General Public License
along with PStreams; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#define REDI_PSTREAMS_POPEN_USES_BIDIRECTIONAL_PIPE 1

//#include "pstream_compat.h"

// TODO test rpstream - this does nothing for the moment
#define TEST_RPSTREAM 1

// test eviscerated pstreams
#define REDI_EVISCERATE_PSTREAMS 1

#include "pstream.h"

#if TEST_RPSTREAM
#include "rpstream.h"
#endif

// include these after pstream.h to ensure it #includes everything it needs
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <fstream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
//#include <fcntl.h>
#include <errno.h>

using namespace std;
using namespace redi;

namespace  // anon
{
    // helper functions for printing test results

    string
    test_type(const istream& s)
    { return "r"; }

    string
    test_type(const ostream& s)
    { return "w"; }

    string
    test_type(const iostream& s)
    { return "b"; }

    template <typename T>
    string
    test_id(const T& s)
    {
        static int count = 0;
        ostringstream buf;
        buf << test_type(s) << ++count;
        return buf.str();
    }

    template <typename T>
    void
    print_result(const T& s, bool result)
    {
        clog << "Test " << setw(4) << test_id(s) << ": "
            << (result ? "Pass" : "Fail!")
            << endl;
    }

    template <typename T>
    bool
    check_pass(const T& s, bool expected = true)
    {
        bool res = s.good() == expected;
        print_result(s, res);
        return res;
    }

    template <typename T>
    bool
    check_fail(const T& s) { return check_pass(s, false); }
}

int main()
{
    ios_base::sync_with_stdio();

    string str;

    clog << "# Testing basic I/O\n";

    {
        // test formatted output
        //
        // This should read the strings on stdin and print them on stdout
        // prefixed by "STDOUT: "

        opstream os("/bin/sed 's/^./STDIN: &/' - /etc/issue");
        os << ".fnord.\n";
        str = "..fnord..\n";
        os << str;
        check_pass(os);
    }

    {
        // test execve() style construction
        //
        // This should read the strings on stdin and print them on stdout
        // prefixed by "STDIN: "

        vector<string> argv;
        argv.push_back("sed");
        argv.push_back("s/^./STDIN: &/");
        opstream os("sed", argv);

        check_pass(os << "Magic Monkey\n");
    }

    {
        // test unformatted output
        //
        // This should read the strings on stdin and print them on stdout
        // prefixed by "STDIN: "

        opstream sed("/bin/sed 's/^./STDIN: &/'");
        str = "Monkey Magic\n";
        for (string::const_iterator i = str.begin(); i!=str.end(); ++i)
            sed.put(*i);
        check_pass(sed);
    }

    {
        // test formatted input
        // should print hostname on stdout, prefixed by "STDOUT: "
        ipstream host("hostname");
        if (getline(host, str))  // extracts up to newline, eats newline
            cout << "STDOUT: " << str << endl;
        check_pass(host);
        // check we hit EOF at next read
        char c;
        print_result(host, !host.get(c));
        print_result(host, host.eof());
        check_fail(host);
    }

    {
        // test unformatted input
        // should print hostname on stdout, prefixed by "STDOUT: "
        ipstream host("date");
        str.clear();
        char c;
        while (host.get(c))  // extracts up to EOF (including newline)
            str += c;
        cout << "STDOUT:  " << str << flush;
        print_result(host, host.eof());
    }

    {
        // open after construction, then write
        opstream os;
        os.open("/bin/sed 's/^./STDIN: &/'");
        os << "Hello, world!\n";
        check_pass(os);
    }

    {
        // open after construction, then read
        ipstream is;
        is.open("hostname");
        string s;
        is >> s;
        cout << "STDOUT: " << s << endl;
        check_pass(is);
    }

    {
        // open after construction, then write
        ipstream host;
        host.open("hostname");
        if (host >> str)
            cout << "STDOUT: " << str << endl;
        check_pass(host);
        // chomp newline and try to read past end
        char c;
        host.get(c);
        host.get(c);
        check_fail(host);
    }

    clog << "# Testing bidirectional PStreams\n";

    pstreambuf::pmode all3streams =
        pstreambuf::pstdin|pstreambuf::pstdout|pstreambuf::pstderr;

    {
        // test output on bidirectional pstream
        string cmd = "grep ^127 -- /etc/hosts /no/such/file";
        pstream ps(cmd, all3streams);

        print_result(ps, ps.is_open());
        check_pass(ps.out());
        check_pass(ps.err());

        string buf;
        while (getline(ps.out(), buf))
            cout << "STDOUT: " << buf << endl;
        check_fail(ps);
        while (getline(ps.err(), buf))
            cout << "STDERR: " << buf << endl;
        check_fail(ps);
    }

    {
        // test input on bidirectional pstream and test peof manip
        string cmd = "grep fnord -- -";
        pstream ps(cmd, all3streams);

        print_result(ps, ps.is_open());
        check_pass(ps);

        ps << "12345\nfnord\n0000" << peof;
        // manip calls ps.rdbuf()->peof();

        string buf;
        getline(ps.out(), buf);

        do
        {
            print_result(ps, buf == "fnord");
            cout << "STDOUT: " << buf << endl;
        } while (getline(ps.out(), buf));

        check_fail(ps << "pipe closed, no fnord now");
    }
    // TODO - test child moves onto next file after peof on stdin

    {
        // test signals
        string cmd = "grep 127 -- -";
        pstream ps(cmd, all3streams);

        pstreambuf* pbuf = ps.rdbuf();

        int e1 = pbuf->error();
        print_result(ps, e1 == 0);
        pbuf->kill(SIGTERM);
        int e2 = pbuf->error();
        print_result(ps, e1 == e2);

        pbuf->close();
        int e3 = pbuf->error();
        check_fail(ps << "127 fail 127\n");
        print_result(ps, e1 == e3);
    }

    clog << "# Testing behaviour with bad commands" << endl;

    //string badcmd = "hgfhdgf";
    string badcmd = "hgfhdgf 2>/dev/null";

    {
        // check eof() works
        ipstream is(badcmd);
        print_result(is, is.get()==EOF);
        print_result(is, is.eof() );
    }

    {
        // test writing to bad command
        opstream ofail(badcmd);
        sleep(1);  // give shell time to try command and exit
        // this would cause SIGPIPE: ofail<<"blahblah";
        // does not show failure: print_result(ofail, !ofail.is_open());
        pstreambuf* buf = ofail.rdbuf();
        print_result(ofail, buf->exited());
        int status = buf->status();
        print_result(ofail, WIFEXITED(status) && WEXITSTATUS(status)==127);
    }

    {
        // reading from bad cmd
        vector<string> argv;
        argv.push_back("hdhdhd");
        argv.push_back("arg1");
        argv.push_back("arg2");
        ipstream ifail("hdhdhd", argv);
        check_fail(ifail>>str);
    }

    clog << "# Testing behaviour with uninit'ed streams" << endl;

    {
        // check eof() works
        ipstream is;
        print_result(is, is.get()==EOF);
        print_result(is, is.eof() );
    }

    {
        // test writing to no command
        opstream ofail;
        check_fail(ofail<<"blahblah");
    }

    clog << "# Testing other member functions\n";

    {
        string cmd("grep re");
        opstream s(cmd);
        print_result(s, cmd == s.command());
    }

    {
        string cmd("grep re");
        opstream s;
        s.open(cmd);
        print_result(s, cmd == s.command());
    }

    {
        string cmd("/bin/ls");
        ipstream s(cmd);
        print_result(s, cmd == s.command());
    }

    {
        string cmd("/bin/ls");
        ipstream s;
        s.open(cmd);
        print_result(s, cmd == s.command());
    }

    // TODO more testing of other members

    clog << "# Testing writing to closed stream\n";

    {
        opstream os("tr a-z A-Z | sed 's/^/STDIN: /'");
        os << "foo\n";
        os.close();
        if (os << "bar\n")
            cout << "Wrote to closed stream" << endl;
        check_fail(os << "bar\n");
    }

#if REDI_EVISCERATE_PSTREAMS
    clog << "# Testing eviscerated pstream\n";

    {
        opstream os("tr a-z A-Z | sed 's/^/STDIN: /'");
        FILE *in, *out, *err;
        size_t res = os.fopen(in, out, err);
        print_result(os, res & pstreambuf::pstdin);
        print_result(os, in!=NULL);
        int i = fputs("flax\n", in);
        fflush(in);
        print_result(os, i>=0 && i!=EOF);
    }

    {
        string cmd = "ls /etc/motd /no/such/file";
        ipstream is(cmd, pstreambuf::pstdout|pstreambuf::pstderr);
        FILE *in, *out, *err;
        size_t res = is.fopen(in, out, err);
        print_result(is, res & pstreambuf::pstdout);
        print_result(is, res & pstreambuf::pstderr);
        print_result(is, out!=NULL);
        print_result(is, err!=NULL);

        size_t len = 256;
        char buf[len];
        char* p = fgets(buf, len, out);
        cout << "STDOUT: " << buf;
        print_result(is, p!=NULL);

        p = fgets(buf, len, err);
        cout << "STDERR: " << buf;
        print_result(is, p!=NULL);
    }

    {
        string cmd = "grep 127 -- - /etc/hosts /no/such/file";
        pstream ps(cmd, all3streams);
        FILE *in, *out, *err;
        size_t res = ps.fopen(in, out, err);
        print_result(ps, res & pstreambuf::pstdin);
        print_result(ps, res & pstreambuf::pstdout);
        print_result(ps, res & pstreambuf::pstderr);
        print_result(ps, in!=NULL);
        print_result(ps, out!=NULL);
        print_result(ps, err!=NULL);

        // ps << "12345\n1112777\n0000" << EOF;
#if 0
        size_t len = 256;
        char buf[len];
        char* p = fgets(buf, len, out);
        cout << "STDOUT: " << buf;
        print_result(ps, p!=NULL);

        p = fgets(buf, len, err);
        cout << "STDERR: " << buf;
        print_result(ps, p!=NULL);
#endif
    }

#endif

#if TEST_RPSTREAM
#endif

    return 0;
}

<|endoftext|>


<commit_before>
#include <iostream>
#include <sf2/sf2.hpp>

enum class Color {
	RED, GREEN, BLUE
};
sf2_enumDef(Color,
	sf2_value(RED),
	sf2_value(GREEN),
	sf2_value(BLUE)
);

struct Position {
	float x, y, z;
};
sf2_structDef(Position,
	sf2_member(x),
	sf2_member(y),
	sf2_member(z)
);

struct Player {
	Position position;
	Color color;
	std::string name;
};
sf2_structDef(Player,
	sf2_member(position),
	sf2_member(color),
	sf2_member(name)
);

int main() {
	std::cout<<"Test01:"<<std::endl;

	Player player1 {Position{5,2,1}, Color::GREEN, "The first \nplayer \""};

	auto player1AsString = sf2::writeString(player1);

	std::cout<<"player1:  "<<player1AsString<<std::endl;

	Player parsedPlayer = sf2::parseString<Player>(player1AsString);

	std::cout<<"parsedPlayer:  "<<sf2::writeString(parsedPlayer)<<std::endl;
}
<commit_msg>UTF-8 test<commit_after>
#include <iostream>
#include <sf2/sf2.hpp>

enum class Color {
	RED, GREEN, BLUE
};
sf2_enumDef(Color,
	sf2_value(RED),
	sf2_value(GREEN),
	sf2_value(BLUE)
);

struct Position {
	float x, y, z;
};
sf2_structDef(Position,
	sf2_member(x),
	sf2_member(y),
	sf2_member(z)
);

struct Player {
	Position position;
	Color color;
	std::string name;
};
sf2_structDef(Player,
	sf2_member(position),
	sf2_member(color),
	sf2_member(name)
);

int main() {
	std::cout<<"Test01:"<<std::endl;

	Player player1 {Position{5,2,1}, Color::GREEN, "The first player is \"ÄÖÜ ß öäü ẑ\"⸮"};

	auto player1AsString = sf2::writeString(player1);

	std::cout<<"player1:  "<<player1AsString<<std::endl;

	Player parsedPlayer = sf2::parseString<Player>(player1AsString);

	std::cout<<"parsedPlayer:  "<<sf2::writeString(parsedPlayer)<<std::endl;
}
<|endoftext|>


<commit_before>// trance typeinfo.hpp - Local Function Library
//
// Copyright (c) 2011 - 2011 Kohei Takahashi (Flast)
//
// 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.

#ifndef IG_TRANCE_TYPEINFO_HPP_ONCE_
#define IG_TRANCE_TYPEINFO_HPP_ONCE_

#include <typeinfo>

#include <trance/config.hpp>

#if defined( BOOST_GNU_STDLIB ) && BOOST_GNU_STDLIB
#   include <cstdlib>
#   include <cxxabi.h>
#endif // BOOST_GNU_STDLIB

namespace trance
{

namespace typeinfo_detail
{

class _type_info_impl
  : public ::std::type_info
{
    template < typename >
    friend _type_info_impl &
    _type_id_by_type( void );

    typedef ::std::type_info _base_t;

#if defined( BOOST_GNU_STDLIB ) && BOOST_GNU_STDLIB
    static inline char *
    _demangle( const char *_name )
    { return __cxxabiv1::__cxa_demangle( _name, 0, 0, 0 ); }

    char *_M_demangled_name;

    explicit
    _type_info_impl( const char *_n )
      : _base_t( _n ),
        _M_demangled_name( _demangle( _n ) ) {}
#endif // BOOST_GNU_STDLIB

public:
    ~_type_info_impl( void ) TRANCE_NOEXCEPT
    {
#if defined( BOOST_GNU_STDLIB ) && BOOST_GNU_STDLIB
        ::std::free( _M_demangled_name );
#endif // BOOST_GNU_STDLIB
    }

    const char *
    demangled_name( void ) const
    { return _M_demangled_name; }
};

template < typename T >
inline _type_info_impl &
_type_id_by_type( void )
{
    static _type_info_impl _impl_instance( typeid( T ).name() );
    return _impl_instance;
}

#if defined( BOOST_NO_RVALUE_REFERENCES )

template < typename T >
inline _type_info_impl &
_type_id_by_expr( T & )
{ return _type_id_by_type< T >(); }

template < typename T >
inline _type_info_impl &
_type_id_by_expr( const T & )
{ return _type_id_by_type< const T >(); }

#else // BOOST_NO_RVALUE_REFERENCES

template < typename T >
inline _type_info_impl &
_type_id_by_expr( T && )
{ return _type_id_by_type< T >(); }

#endif // BOOST_NO_RVALUE_REFERENCES

} // namespace typeinfo_detail

#define TRANCE_TYPEID_BY_TYPE( _T ) \
  ::trance::typeinfo_detail::_type_id_by_type< _T >()

#define TRANCE_TYPEID_BY_EXPR( _Expr ) \
  ::trance::typeinfo_detail::_type_id_by_expr( _Expr )

} // namespace trance

#endif // IG_TRANCE_TYPEINFO_HPP_ONCE_

<commit_msg>add intermediate interface<commit_after>// trance typeinfo.hpp - Local Function Library
//
// Copyright (c) 2011 - 2011 Kohei Takahashi (Flast)
//
// 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.

#ifndef IG_TRANCE_TYPEINFO_HPP_ONCE_
#define IG_TRANCE_TYPEINFO_HPP_ONCE_

#include <typeinfo>

#include <trance/config.hpp>

#if defined( BOOST_GNU_STDLIB ) && BOOST_GNU_STDLIB
#   include <cstdlib>
#   include <cxxabi.h>
#endif // BOOST_GNU_STDLIB

namespace trance
{

class type_info
  : public ::std::type_info
{
    typedef ::std::type_info _base_t;

protected:
    explicit
    type_info( const char *_n )
      : _base_t( _n ) {}

public:
    virtual ~type_info( void ) {}

    virtual const char *
    demangled_name( void ) const = 0;
};

namespace typeinfo_detail
{

class _type_info_impl
  : public type_info
{
    template < typename >
    friend type_info &
    _type_id_by_type( void );

#if defined( BOOST_GNU_STDLIB ) && BOOST_GNU_STDLIB
    static inline char *
    _demangle( const char *_name )
    { return __cxxabiv1::__cxa_demangle( _name, 0, 0, 0 ); }

    char *_M_demangled_name;

    explicit
    _type_info_impl( const char *_n )
      : type_info( _n ),
        _M_demangled_name( _demangle( _n ) ) {}
#endif // BOOST_GNU_STDLIB

public:
    ~_type_info_impl( void ) TRANCE_NOEXCEPT
    {
#if defined( BOOST_GNU_STDLIB ) && BOOST_GNU_STDLIB
        ::std::free( _M_demangled_name );
#endif // BOOST_GNU_STDLIB
    }

    const char *
    demangled_name( void ) const
    { return _M_demangled_name; }
};

template < typename T >
inline type_info &
_type_id_by_type( void )
{
    static _type_info_impl _impl_instance( typeid( T ).name() );
    return _impl_instance;
}

#if defined( BOOST_NO_RVALUE_REFERENCES )

template < typename T >
inline type_info &
_type_id_by_expr( T & )
{ return _type_id_by_type< T >(); }

template < typename T >
inline type_info &
_type_id_by_expr( const T & )
{ return _type_id_by_type< const T >(); }

#else // BOOST_NO_RVALUE_REFERENCES

template < typename T >
inline type_info &
_type_id_by_expr( T && )
{ return _type_id_by_type< T >(); }

#endif // BOOST_NO_RVALUE_REFERENCES

} // namespace typeinfo_detail

#define TRANCE_TYPEID_BY_TYPE( _T ) \
  ::trance::typeinfo_detail::_type_id_by_type< _T >()

#define TRANCE_TYPEID_BY_EXPR( _Expr ) \
  ::trance::typeinfo_detail::_type_id_by_expr( _Expr )

} // namespace trance

#endif // IG_TRANCE_TYPEINFO_HPP_ONCE_

<|endoftext|>


<commit_before>#include <TFile.h>
#include <TNtuple.h>
#include <TH2.h>
#include <TProfile.h>
#include <TCanvas.h>
#include <TFrame.h>
#include <TROOT.h>
#include <TSystem.h>
#include <TRandom.h>
#include <TBenchmark.h>
#include <TInterpreter.h>

TFile *hsimple(Int_t get=0)
{
//  This program creates :
//    - a one dimensional histogram
//    - a two dimensional histogram
//    - a profile histogram
//    - a memory-resident ntuple
//
//  These objects are filled with some random numbers and saved on a file.
//  If get=1 the macro returns a pointer to the TFile of "hsimple.root"
//          if this file exists, otherwise it is created.
//  The file "hsimple.root" is created in $ROOTSYS/tutorials if the caller has
//  write access to this directory, otherwise the file is created in $PWD

   TString filename = "hsimple.root";
   TString dir = gSystem->UnixPathName(gInterpreter->GetCurrentMacroName());
   dir.ReplaceAll("hsimple.C","");
   dir.ReplaceAll("/./","/");
   TFile *hfile = 0;
   if (get) {
      // if the argument get =1 return the file "hsimple.root"
      // if the file does not exist, it is created
      TString fullPath = dir+"hsimple.root";
      if (!gSystem->AccessPathName(fullPath,kFileExists)) {
	 hfile = TFile::Open(fullPath); //in $ROOTSYS/tutorials
         if (hfile) return hfile;
      }
      //otherwise try $PWD/hsimple.root
      if (!gSystem->AccessPathName("hsimple.root",kFileExists)) {
         hfile = TFile::Open("hsimple.root"); //in current dir
         if (hfile) return hfile;
      }
   }
   //no hsimple.root file found. Must generate it !
   //generate hsimple.root in $ROOTSYS/tutorials if we have write access
   if (!gSystem->AccessPathName(dir,kWritePermission)) {
      filename = dir+"hsimple.root";
   } else if (!gSystem->AccessPathName(".",kWritePermission)) {
      //otherwise generate hsimple.root in the current directory
   } else {
      printf("you must run the script in a directory with write access\n");
      return 0;
   }
   hfile = (TFile*)gROOT->FindObject(filename); if (hfile) hfile->Close();
   hfile = new TFile(filename,"RECREATE","Demo ROOT file with histograms");

   // Create some histograms, a profile histogram and an ntuple
   TH1F *hpx = new TH1F("hpx","This is the px distribution",100,-4,4);
   hpx->SetFillColor(48);
   TH2F *hpxpy = new TH2F("hpxpy","py vs px",40,-4,4,40,-4,4);
   TProfile *hprof = new TProfile("hprof","Profile of pz versus px",100,-4,4,0,20);
   TNtuple *ntuple = new TNtuple("ntuple","Demo ntuple","px:py:pz:random:i");

   gBenchmark->Start("hsimple");

   // Create a new canvas.
   TCanvas *c1 = new TCanvas("c1","Dynamic Filling Example",200,10,700,500);
   c1->SetFillColor(42);
   c1->GetFrame()->SetFillColor(21);
   c1->GetFrame()->SetBorderSize(6);
   c1->GetFrame()->SetBorderMode(-1);

   // Fill histograms randomly
   gRandom->SetSeed(42);
   Float_t px, py, pz;
   const Int_t kUPDATE = 1000;
   for (Int_t i = 0; i < 25000; i++) {
      gRandom->Rannor(px,py);
      pz = px*px + py*py;
      Float_t random = gRandom->Rndm(1);
      hpx->Fill(px);
      hpxpy->Fill(px,py);
      hprof->Fill(px,pz);
      ntuple->Fill(px,py,pz,random,i);
      if (i && (i%kUPDATE) == 0) {
         if (i == kUPDATE) hpx->Draw();
         c1->Modified();
         c1->Update();
         if (gSystem->ProcessEvents())
            break;
      }
   }
   gBenchmark->Show("hsimple");

   // Save all objects in this file
   hpx->SetFillColor(0);
   hfile->Write();
   hpx->SetFillColor(48);
   c1->Modified();
   return hfile;

// Note that the file is automatically close when application terminates
// or when the file destructor is called.
}
<commit_msg>Modify the tutorial such that the results are always identical. Instead of using the current global random number generator pointed by gRandom, a local TRandom3 object is instantiated (hence destroyed) at each run.<commit_after>#include <TFile.h>
#include <TNtuple.h>
#include <TH2.h>
#include <TProfile.h>
#include <TCanvas.h>
#include <TFrame.h>
#include <TROOT.h>
#include <TSystem.h>
#include <TRandom3.h>
#include <TBenchmark.h>
#include <TInterpreter.h>

TFile *hsimple(Int_t get=0)
{
//  This program creates :
//    - a one dimensional histogram
//    - a two dimensional histogram
//    - a profile histogram
//    - a memory-resident ntuple
//
//  These objects are filled with some random numbers and saved on a file.
//  If get=1 the macro returns a pointer to the TFile of "hsimple.root"
//          if this file exists, otherwise it is created.
//  The file "hsimple.root" is created in $ROOTSYS/tutorials if the caller has
//  write access to this directory, otherwise the file is created in $PWD

   TString filename = "hsimple.root";
   TString dir = gSystem->UnixPathName(gInterpreter->GetCurrentMacroName());
   dir.ReplaceAll("hsimple.C","");
   dir.ReplaceAll("/./","/");
   TFile *hfile = 0;
   if (get) {
      // if the argument get =1 return the file "hsimple.root"
      // if the file does not exist, it is created
      TString fullPath = dir+"hsimple.root";
      if (!gSystem->AccessPathName(fullPath,kFileExists)) {
	 hfile = TFile::Open(fullPath); //in $ROOTSYS/tutorials
         if (hfile) return hfile;
      }
      //otherwise try $PWD/hsimple.root
      if (!gSystem->AccessPathName("hsimple.root",kFileExists)) {
         hfile = TFile::Open("hsimple.root"); //in current dir
         if (hfile) return hfile;
      }
   }
   //no hsimple.root file found. Must generate it !
   //generate hsimple.root in $ROOTSYS/tutorials if we have write access
   if (!gSystem->AccessPathName(dir,kWritePermission)) {
      filename = dir+"hsimple.root";
   } else if (!gSystem->AccessPathName(".",kWritePermission)) {
      //otherwise generate hsimple.root in the current directory
   } else {
      printf("you must run the script in a directory with write access\n");
      return 0;
   }
   hfile = (TFile*)gROOT->FindObject(filename); if (hfile) hfile->Close();
   hfile = new TFile(filename,"RECREATE","Demo ROOT file with histograms");

   // Create some histograms, a profile histogram and an ntuple
   TH1F *hpx = new TH1F("hpx","This is the px distribution",100,-4,4);
   hpx->SetFillColor(48);
   TH2F *hpxpy = new TH2F("hpxpy","py vs px",40,-4,4,40,-4,4);
   TProfile *hprof = new TProfile("hprof","Profile of pz versus px",100,-4,4,0,20);
   TNtuple *ntuple = new TNtuple("ntuple","Demo ntuple","px:py:pz:random:i");

   gBenchmark->Start("hsimple");

   // Create a new canvas.
   TCanvas *c1 = new TCanvas("c1","Dynamic Filling Example",200,10,700,500);
   c1->SetFillColor(42);
   c1->GetFrame()->SetFillColor(21);
   c1->GetFrame()->SetBorderSize(6);
   c1->GetFrame()->SetBorderMode(-1);

   // Fill histograms randomly
   TRandom3 random;
   Float_t px, py, pz;
   const Int_t kUPDATE = 1000;
   for (Int_t i = 0; i < 25000; i++) {
      random.Rannor(px,py);
      pz = px*px + py*py;
      Float_t rnd = random.Rndm(1);
      hpx->Fill(px);
      hpxpy->Fill(px,py);
      hprof->Fill(px,pz);
      ntuple->Fill(px,py,pz,rnd,i);
      if (i && (i%kUPDATE) == 0) {
         if (i == kUPDATE) hpx->Draw();
         c1->Modified();
         c1->Update();
         if (gSystem->ProcessEvents())
            break;
      }
   }
   gBenchmark->Show("hsimple");

   // Save all objects in this file
   hpx->SetFillColor(0);
   hfile->Write();
   hpx->SetFillColor(48);
   c1->Modified();
   return hfile;

// Note that the file is automatically close when application terminates
// or when the file destructor is called.
}
<|endoftext|>


<commit_before>//     Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_LITERAL_HPP
#define TOML11_LITERAL_HPP
#include "parser.hpp"

namespace toml
{
inline namespace literals
{
inline namespace toml_literals
{

inline ::toml::value operator""_toml(const char* str, std::size_t len)
{
    ::toml::detail::location<std::vector<char>>
        loc(/* filename = */ std::string("TOML literal encoded in a C++ code"),
            /* contents = */ std::vector<char>(str, str + len));

    // if there are some comments or empty lines, skip them.
    using skip_line = ::toml::detail::repeat<toml::detail::sequence<
            ::toml::detail::maybe<::toml::detail::lex_ws>,
            ::toml::detail::maybe<::toml::detail::lex_comment>,
            ::toml::detail::lex_newline
        >, ::toml::detail::at_least<1>>;
    skip_line::invoke(loc);

    // if there are some whitespaces before a value, skip them.
    using skip_ws = ::toml::detail::repeat<
        ::toml::detail::lex_ws, ::toml::detail::at_least<1>>;
    skip_ws::invoke(loc);

    // to distinguish arrays and tables, first check it is a table or not.
    //
    // "[1,2,3]"_toml;   // this is an array
    // "[table]"_toml;   // a table that has an empty table named "table" inside.
    // "[[1,2,3]]"_toml; // this is an array of arrays
    // "[[table]]"_toml; // this is a table that has an array of tables inside.
    //
    // "[[1]]"_toml;     // this can be both... (currently it becomes a table)
    // "1 = [{}]"_toml;  // this is a table that has an array of table named 1.
    // "[[1,]]"_toml;    // this is an array of arrays.
    // "[[1],]"_toml;    // this also.

    const auto the_front = loc.iter();

    const bool is_table_key = ::toml::detail::lex_std_table::invoke(loc);
    loc.reset(the_front);

    const bool is_aots_key  = ::toml::detail::lex_array_table::invoke(loc);
    loc.reset(the_front);

    // If it is neither a table-key or a array-of-table-key, it may be a value.
    if(!is_table_key && !is_aots_key)
    {
        if(auto data = ::toml::detail::parse_value(loc))
        {
            return data.unwrap();
        }
    }

    // Note that still it can be a table, because the literal might be something
    // like the following.
    // ```cpp
    // R"( // c++11 raw string literals
    //   key = "value"
    //   int = 42
    // )"_toml;
    // ```
    // It is a valid toml file.
    // It should be parsed as if we parse a file with this content.

    if(auto data = ::toml::detail::parse_toml_file(loc))
    {
        loc.reset(loc.begin()); // rollback to the top of the literal
        return ::toml::value(std::move(data.unwrap()),
                ::toml::detail::region<std::vector<char>>(std::move(loc)));
    }
    else // none of them.
    {
        throw ::toml::syntax_error(data.unwrap_err());
    }
}

} // toml_literals
} // literals
} // toml
#endif//TOML11_LITERAL_HPP
<commit_msg>fix: skip first ws/newlines in toml literal<commit_after>//     Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_LITERAL_HPP
#define TOML11_LITERAL_HPP
#include "parser.hpp"

namespace toml
{
inline namespace literals
{
inline namespace toml_literals
{

inline ::toml::value operator""_toml(const char* str, std::size_t len)
{
    ::toml::detail::location<std::vector<char>>
        loc(/* filename = */ std::string("TOML literal encoded in a C++ code"),
            /* contents = */ std::vector<char>(str, str + len));

    // if there are some comments or empty lines, skip them.
    using skip_line = ::toml::detail::repeat<toml::detail::sequence<
            ::toml::detail::maybe<::toml::detail::lex_ws>,
            ::toml::detail::maybe<::toml::detail::lex_comment>,
            ::toml::detail::lex_newline
        >, ::toml::detail::at_least<1>>;
    skip_line::invoke(loc);

    // if there are some whitespaces before a value, skip them.
    using skip_ws = ::toml::detail::repeat<
        ::toml::detail::lex_ws, ::toml::detail::at_least<1>>;
    skip_ws::invoke(loc);

    // to distinguish arrays and tables, first check it is a table or not.
    //
    // "[1,2,3]"_toml;   // this is an array
    // "[table]"_toml;   // a table that has an empty table named "table" inside.
    // "[[1,2,3]]"_toml; // this is an array of arrays
    // "[[table]]"_toml; // this is a table that has an array of tables inside.
    //
    // "[[1]]"_toml;     // this can be both... (currently it becomes a table)
    // "1 = [{}]"_toml;  // this is a table that has an array of table named 1.
    // "[[1,]]"_toml;    // this is an array of arrays.
    // "[[1],]"_toml;    // this also.

    const auto the_front = loc.iter();

    const bool is_table_key = ::toml::detail::lex_std_table::invoke(loc);
    loc.reset(the_front);

    const bool is_aots_key  = ::toml::detail::lex_array_table::invoke(loc);
    loc.reset(the_front);

    // If it is neither a table-key or a array-of-table-key, it may be a value.
    if(!is_table_key && !is_aots_key)
    {
        if(auto data = ::toml::detail::parse_value(loc))
        {
            return data.unwrap();
        }
    }

    // Note that still it can be a table, because the literal might be something
    // like the following.
    // ```cpp
    // R"( // c++11 raw string literals
    //   key = "value"
    //   int = 42
    // )"_toml;
    // ```
    // It is a valid toml file.
    // It should be parsed as if we parse a file with this content.

    if(auto data = ::toml::detail::parse_toml_file(loc))
    {
        loc.reset(loc.begin()); // rollback to the top of the literal
        // skip needless characters for error message
        skip_line::invoke(loc); // skip the first several needless lines
        skip_ws::invoke(loc);   // skip the first several needless whitespaces
        return ::toml::value(std::move(data.unwrap()),
                ::toml::detail::region<std::vector<char>>(std::move(loc)));
    }
    else // none of them.
    {
        throw ::toml::syntax_error(data.unwrap_err());
    }
}

} // toml_literals
} // literals
} // toml
#endif//TOML11_LITERAL_HPP
<|endoftext|>


<commit_before>/**
 *
 *  File reader
 *
 *  https://github.com/kdzlvaids/algorithm_and_practice-pknu-2016
 *
 */

#ifndef ALGORITHM_FILEREADER_HPP_
#define ALGORITHM_FILEREADER_HPP_ 1

/** Includes */
#include <string>
#include <fstream>      /** File stream */
#include <sstream>      /** String stream */
#include <functional>
#include <regex>        /** Regular expressions */
#include <array>        /** Containers */
#include <vector>       /** Containers */

namespace algorithm
{

/** File reader */
template<
    std::streamsize StreamSize  = 1000,                             /**< Stream unit size (word, line, etc.)*/
    class   StringType          = std::string,                      /**< Char array type */
    class   StringArrayType     = std::vector<StringType>,          /**< Array of Char array type */
    class   DelimsType          = StringType                        /**< List of delimiters type (Char array type, should be iterable) */
>
class FileReader
{
public:
    typedef size_t              SizeType;
    typedef char                CharType;   /**< Char type */

    typedef std::istream        InputStreamType;        /**< Common input stream type */
    typedef std::ifstream       FileInputStreamType;    /**< File input stream type */
    typedef std::stringstream   StringInputStreamType;  /**< String input stream type */
    typedef std::regex          RegexType;              /**< Regular expression pattern type */

private:
    FileInputStreamType         stream_;    /**< File stream */

    /** Test whether the character matches with one of delims

        \note   If the number of delimiters is N, then the time complexity is O(N).

        \return     Return true if ch is a delimiter; otherwise return false
        \param[in]  ch      Character to compare
        \param[in]  delims  List of delimiters
    */
    inline
    bool
    IsDelimiter(const CharType & ch, const DelimsType & delims)
    {
        for(const CharType & delim : delims)
        {
            if(ch == delim)
                return true;
        }

        return false;
    }

public:
    /** Constructor */
    FileReader(void)
    { }

    FileReader(const StringType & filename)
    { Open(filename); }

    /** Destructor */
    ~FileReader(void)
    { Close(); }

    /** Open a file and associates it with the stream

        \param[in]  filename    Path of the file
    */
    void
    Open(const StringType & filename)
    { stream_.open(filename); }

    /** Close the associated file */
    void
    Close(void)
    { stream_.close(); }

    /** Close and re-open the associated file

        \param[in]  filename    Path of the file
    */
    void
    Reopen(const StringType & filename)
    {
        Close();
        Open(filename);
    }

    /** Test whether the stream has an associated file

        \return     Return true if the stream has an associated file;
                    otherwise return false
    */
    inline
    bool
    IsOpen(void)
    { return stream_.is_open(); }

    /** Test whether the stream reached to End-of-file

        \return     Return true if the stream reached to EOF; otherwise return false
    */
    inline
    bool
    IsEOF(void)
    { return stream_.eof(); }

    /** Read a file until specific delimiter

        \note   If the length of each line in input stream is M
                and the number of delimiters is N,
                then the time complexity is O(M*N).

        \return     Length of output string
        \param[out] out_string  String to store
        \param[in]  stream      File stream
        \param[in]  delims      List of delimiters
    */
    SizeType
    Read(StringType & out_string, InputStreamType & stream, const DelimsType & delims)
    {
        out_string.clear();

        CharType ch;
        while(IsEOF() != true && IsDelimiter(ch = stream.get(), delims) != true)
            out_string += ch;

        return out_string.length();
    }

    /** Read a line

        \return     Length of output string
        \param[out] out_string  String to store a line
    */
    SizeType
    ReadLine(StringType & out_string)
    { return Read(out_string, stream_, "\n"); }

    /** Tokenising the stream by delimiter

        \return     Number of tokens
        \param[out] out_tokens  Array to store tokens;
                    Requires member functions: clear(), push_back(), size()
        \param[in]  stream      File stream
        \param[in]  delims      List of delimiters
    */
    SizeType
    DivideByDelimiter(StringArrayType & out_tokens, InputStreamType & stream, const DelimsType & delims)
    {
        out_tokens.clear();

        StringType string;
        while(Read(string, stream, delims) > 0)
            out_tokens.push_back(string);

        return out_tokens.size();
    }

    /** Tokenising the string by delimiter

        \return     Number of tokens
        \param[out] out_tokens  Array to store tokens;
                    Requires member functions: clear(), push_back(), size()
        \param[in]  string      String
        \param[in]  delims      List of delimiters
    */
    SizeType
    DivideByDelimiter(StringArrayType & out_tokens, const StringType & string, const DelimsType & delims)
    {
        StringInputStreamType stream(string);
        return DivideByDelimiter(out_tokens, stream, delims);
    }

    /** Parser

        Loop the logic (line reading) until term_condition comes true.
        Callback is called with each line.

        There is two functions which works as callback function:
            *   void callback(StringType &)
            *   bool term_condition(InputStreamType &)

        First, function named `callback' is called in every line.
        As argument, string of each line is passed.

        Second, function named `term_condition' is called in every line, too.
        As argument, input stream is passed, which is potentially unsafe.

        `term_condition' is works as contitional expression in `while' loop,
        which continues the line reading, should return true to escape out the loop.
        `term_condition' is OPTIONAL, and the default value is:
        `
            bool
            term_condition(InputStreamType & stream)
            { return IsEOF(); }
        '.

        \note   Experimental

        \param[in]  callback        Callback function
        \param[in]  term_condition  Function which have a termination condition;
                                    if the loop reached to terminate condition,
                                    term_condition should return true to escape out
                                    (Optional, default value is: `return IsEOF;')
    */
    void
    Parse(std::function<void(StringType &)> & callback,
          std::function<bool(InputStreamType &)> & term_condition =
          [] (InputStreamType & stream)
          -> bool
          { return IsEOF(); }
    )
    {
        while(term_condition(stream_) != true)
        {
            StringType string;
            ReadLine(string);
            callback(string);
        }
    }

#if 0
    /** Regular expression match operation

        \note   Experimental

        \return     Return true if match exists; otherwise return false
        http://en.cppreference.com/w/cpp/regex/regex_match
    */
    bool
    RegexMatch(StringType & out_result, const StringType & string, const StringType & regex_pattern)
    {
        RegexType pattern(regex_pattern);
        bool r = regex_match(string, pattern);

        return (r.ready() == true && r.empty() == true && r.size() == 0) != true;
    }
#endif
};

} /** ns: algorithm */

#endif /** ! ALGORITHM_FILEREADER_HPP_ */
<commit_msg>Fix cond-exp in loop uses stream_ even not a stream_<commit_after>/**
 *
 *  File reader
 *
 *  https://github.com/kdzlvaids/algorithm_and_practice-pknu-2016
 *
 */

#ifndef ALGORITHM_FILEREADER_HPP_
#define ALGORITHM_FILEREADER_HPP_ 1

/** Includes */
#include <string>
#include <fstream>      /** File stream */
#include <sstream>      /** String stream */
#include <functional>
#include <regex>        /** Regular expressions */
#include <array>        /** Containers */
#include <vector>       /** Containers */

namespace algorithm
{

/** File reader */
template<
    std::streamsize StreamSize  = 1000,                             /**< Stream unit size (word, line, etc.)*/
    class   StringType          = std::string,                      /**< Char array type */
    class   StringArrayType     = std::vector<StringType>,          /**< Array of Char array type */
    class   DelimsType          = StringType                        /**< List of delimiters type (Char array type, should be iterable) */
>
class FileReader
{
public:
    typedef size_t              SizeType;
    typedef char                CharType;   /**< Char type */

    typedef std::istream        InputStreamType;        /**< Common input stream type */
    typedef std::ifstream       FileInputStreamType;    /**< File input stream type */
    typedef std::stringstream   StringInputStreamType;  /**< String input stream type */
    typedef std::regex          RegexType;              /**< Regular expression pattern type */

private:
    FileInputStreamType         stream_;    /**< File stream */

    /** Test whether the character matches with one of delims

        \note   If the number of delimiters is N, then the time complexity is O(N).

        \return     Return true if ch is a delimiter; otherwise return false
        \param[in]  ch      Character to compare
        \param[in]  delims  List of delimiters
    */
    inline
    bool
    IsDelimiter(const CharType & ch, const DelimsType & delims)
    {
        for(const CharType & delim : delims)
        {
            if(ch == delim)
                return true;
        }

        return false;
    }

public:
    /** Constructor */
    FileReader(void)
    { }

    FileReader(const StringType & filename)
    { Open(filename); }

    /** Destructor */
    ~FileReader(void)
    { Close(); }

    /** Open a file and associates it with the stream

        \param[in]  filename    Path of the file
    */
    void
    Open(const StringType & filename)
    { stream_.open(filename); }

    /** Close the associated file */
    void
    Close(void)
    { stream_.close(); }

    /** Close and re-open the associated file

        \param[in]  filename    Path of the file
    */
    void
    Reopen(const StringType & filename)
    {
        Close();
        Open(filename);
    }

    /** Test whether the stream has an associated file

        \return     Return true if the stream has an associated file;
                    otherwise return false
    */
    inline
    bool
    IsOpen(void)
    { return stream_.is_open(); }

    /** Test whether the stream reached to End-of-file

        \return     Return true if the stream reached to EOF; otherwise return false
    */
    inline
    bool
    IsEOF(void)
    { return stream_.eof(); }

    /** Read a file until specific delimiter

        \note   If the length of each line in input stream is M
                and the number of delimiters is N,
                then the time complexity is O(M*N).

        \return     Length of output string
        \param[out] out_string  String to store
        \param[in]  stream      File stream
        \param[in]  delims      List of delimiters
    */
    SizeType
    Read(StringType & out_string, InputStreamType & stream, const DelimsType & delims)
    {
        out_string.clear();

        CharType ch;
        while(stream.eof() != true && IsDelimiter(ch = stream.get(), delims) != true)
            out_string += ch;

        return out_string.length();
    }

    /** Read a line

        \return     Length of output string
        \param[out] out_string  String to store a line
    */
    SizeType
    ReadLine(StringType & out_string)
    { return Read(out_string, stream_, "\n"); }

    /** Tokenising the stream by delimiter

        \return     Number of tokens
        \param[out] out_tokens  Array to store tokens;
                    Requires member functions: clear(), push_back(), size()
        \param[in]  stream      File stream
        \param[in]  delims      List of delimiters
    */
    SizeType
    DivideByDelimiter(StringArrayType & out_tokens, InputStreamType & stream, const DelimsType & delims)
    {
        out_tokens.clear();

        StringType string;
        while(Read(string, stream, delims) > 0)
            out_tokens.push_back(string);

        return out_tokens.size();
    }

    /** Tokenising the string by delimiter

        \return     Number of tokens
        \param[out] out_tokens  Array to store tokens;
                    Requires member functions: clear(), push_back(), size()
        \param[in]  string      String
        \param[in]  delims      List of delimiters
    */
    SizeType
    DivideByDelimiter(StringArrayType & out_tokens, const StringType & string, const DelimsType & delims)
    {
        StringInputStreamType stream(string);
        return DivideByDelimiter(out_tokens, stream, delims);
    }

    /** Parser

        Loop the logic (line reading) until term_condition comes true.
        Callback is called with each line.

        There is two functions which works as callback function:
            *   void callback(StringType &)
            *   bool term_condition(InputStreamType &)

        First, function named `callback' is called in every line.
        As argument, string of each line is passed.

        Second, function named `term_condition' is called in every line, too.
        As argument, input stream is passed, which is potentially unsafe.

        `term_condition' is works as contitional expression in `while' loop,
        which continues the line reading, should return true to escape out the loop.
        `term_condition' is OPTIONAL, and the default value is:
        `
            bool
            term_condition(InputStreamType & stream)
            { return IsEOF(); }
        '.

        \note   Experimental

        \param[in]  callback        Callback function
        \param[in]  term_condition  Function which have a termination condition;
                                    if the loop reached to terminate condition,
                                    term_condition should return true to escape out
                                    (Optional, default value is: `return IsEOF;')
    */
    void
    Parse(std::function<void(StringType &)> & callback,
          std::function<bool(InputStreamType &)> & term_condition =
          [] (InputStreamType & stream)
          -> bool
          { return IsEOF(); }
    )
    {
        while(term_condition(stream_) != true)
        {
            StringType string;
            ReadLine(string);
            callback(string);
        }
    }

#if 0
    /** Regular expression match operation

        \note   Experimental

        \return     Return true if match exists; otherwise return false
        http://en.cppreference.com/w/cpp/regex/regex_match
    */
    bool
    RegexMatch(StringType & out_result, const StringType & string, const StringType & regex_pattern)
    {
        RegexType pattern(regex_pattern);
        bool r = regex_match(string, pattern);

        return (r.ready() == true && r.empty() == true && r.size() == 0) != true;
    }
#endif
};

} /** ns: algorithm */

#endif /** ! ALGORITHM_FILEREADER_HPP_ */
<|endoftext|>


<commit_before>// Copyright 2019 DeepMind Technologies Ltd. All rights reserved.
//
// 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 <memory>
#include <string>

#include "open_spiel/algorithms/value_iteration.h"
#include "open_spiel/games/tic_tac_toe.h"
#include "open_spiel/spiel.h"
#include "open_spiel/spiel_utils.h"

// Example code for using value iteration algorithm to solve tic-tac-toe.
int main(int argc, char** argv) {
  std::shared_ptr<const open_spiel::Game> game =
      open_spiel::LoadGame("tic_tac_toe");

  auto solution = open_spiel::algorithms::ValueIteration(*game, -1, 0.01);
  for (const auto& kv : solution) {
    std::cerr << "State: " << std::endl
              << kv.first << std::endl
              << "Value: " << kv.second << std::endl;
  }

  std::string initial_state = "...\n...\n...";
  std::string cross_win_state = "...\n...\n.ox";
  std::string naught_win_state = "x..\noo.\nxx.";
  SPIEL_CHECK_EQ(solution[initial_state], 0);
  SPIEL_CHECK_EQ(solution[cross_win_state], 1);
  SPIEL_CHECK_EQ(solution[naught_win_state], -1);
}
<commit_msg>Command line arguments for value iteration example<commit_after>// Copyright 2019 DeepMind Technologies Ltd. All rights reserved.
//
// 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 <memory>
#include <string>

#include "open_spiel/abseil-cpp/absl/flags/flag.h"
#include "open_spiel/abseil-cpp/absl/flags/parse.h"
#include "open_spiel/abseil-cpp/absl/strings/str_format.h"
#include "open_spiel/algorithms/value_iteration.h"
#include "open_spiel/spiel.h"
#include "open_spiel/spiel_utils.h"

ABSL_FLAG(std::string, game, "tic_tac_toe", "The name of the game to play.");
ABSL_FLAG(int, depth_limit, -1, "Depth limit until which to compute value iteration.");
ABSL_FLAG(double, threshold, 0.01, "Threshold accuracy at which to stop value iteration.");

// Example code for using value iteration algorithm to solve tic-tac-toe.
int main(int argc, char** argv) {
  absl::ParseCommandLine(argc, argv);

  std::shared_ptr<const open_spiel::Game> game =
      open_spiel::LoadGame(absl::GetFlag(FLAGS_game));

  auto solution = open_spiel::algorithms::ValueIteration(*game, absl::GetFlag(FLAGS_depth_limit), absl::GetFlag(FLAGS_threshold));
  for (const auto& kv : solution) {
    std::cerr << "State: " << std::endl
              << kv.first << std::endl
              << "Value: " << kv.second << std::endl;
  }
/* tic tac toe example usage
  std::string initial_state = "...\n...\n...";
  std::string cross_win_state = "...\n...\n.ox";
  std::string naught_win_state = "x..\noo.\nxx.";
  SPIEL_CHECK_EQ(solution[initial_state], 0);
  SPIEL_CHECK_EQ(solution[cross_win_state], 1);
  SPIEL_CHECK_EQ(solution[naught_win_state], -1);
*/
}
<|endoftext|>