<commit_before>#include <iostream>
#include "gpi/gpi.h"
#include "phitron/phitron.h"
#include "window.h"
#include "draw.h"
#include <chrono>
#include <thread>

#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

//Amount of particles in test simulation
#define OBJECTS 128

#define FPS 20

using namespace std;
using namespace chrono;

uint16_t toHalfFloat(float x) {
    uint32_t &f = reinterpret_cast<uint32_t&>(x);
    return ((f >> 16) & 0x8000) | ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) | ((f >> 13) & 0x03ff);
}

int main() {
    Window window("testing", WINDOW_WIDTH, WINDOW_HEIGHT);
    Renderer renderer(window);

    GroupRenderer gr(WINDOW_WIDTH, WINDOW_HEIGHT);

    steady_clock::time_point lastTime = steady_clock::now();

    phi::P3 particles[OBJECTS];
    phi::V3 colors[OBJECTS];

    std::mt19937 rand(3);

    for (unsigned i = 0; i != OBJECTS; i++) {
        particles[i].position = phi::V3(rand()/double(rand.max())*2-1, rand()/double(rand.max())*2-1, rand()/double(rand.max())/8);
        particles[i].velocity = phi::V3(rand()/double(rand.max())*2-1, rand()/double(rand.max())*2-1, rand()/double(rand.max())*2-1);
        particles[i].velocity *= 0.0005;
        particles[i].inertia = 100.0;

        colors[i] = phi::V3(rand()/double(rand.max()), rand()/double(rand.max()), rand()/double(rand.max()));
        colors[i] *= 1;
    }

    uint16_t *posbuffer = (uint16_t*)gr.buffer.buffer.map(GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);

    while (true) {
        SDL_Event event;
        while (window.pollEvent(event)) {
            switch (event.type) {
            case SDL_QUIT:
                return 0;
            }
        }

        #pragma omp parallel for
        for (int i = 0; i != OBJECTS; i++)
            particles[i].gravitate(0.1, phi::V3(0, 0, 0), 0.1);
            /*for (int j = 0; j != OBJECTS; j++)
                if (i != j)
                    particles[i].gravitate(0.0001, particles[j].position, 0.1);*/

        for (unsigned i = 0; i != OBJECTS; i++) {
            particles[i].advance();
            posbuffer[i*7 + 0] = toHalfFloat(particles[i].position.x);
            posbuffer[i*7 + 1] = toHalfFloat(particles[i].position.y);
            posbuffer[i*7 + 2] = toHalfFloat(particles[i].position.z);

            posbuffer[i*7 + 3] = toHalfFloat(colors[i].x);
            posbuffer[i*7 + 4] = toHalfFloat(colors[i].y);
            posbuffer[i*7 + 5] = toHalfFloat(colors[i].z);

            posbuffer[i*7 + 6] = toHalfFloat(0.1);
        }

        gr.buffer.buffer.sync();

        gr.render(OBJECTS, WINDOW_WIDTH, WINDOW_HEIGHT);

        this_thread::sleep_until(lastTime + duration<double>(1.0/FPS));
        steady_clock::time_point thisTime = steady_clock::now();
        double timeDelta = duration_cast<duration<double>>(thisTime - lastTime).count();
        cout << "FPS: " << (1.0/timeDelta) << endl;
        lastTime = thisTime;

        window.flip();
    }
    return 0;
}

<commit_msg>fixed omp loop and changed sleeping code<commit_after>#include <iostream>
#include "gpi/gpi.h"
#include "phitron/phitron.h"
#include "window.h"
#include "draw.h"
#include <chrono>
#include <thread>

#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

//Amount of particles in test simulation
#define OBJECTS 128

#define FPS 20

using namespace std;
using namespace chrono;

uint16_t toHalfFloat(float x) {
    uint32_t &f = reinterpret_cast<uint32_t&>(x);
    return ((f >> 16) & 0x8000) | ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) | ((f >> 13) & 0x03ff);
}

int main() {
    Window window("testing", WINDOW_WIDTH, WINDOW_HEIGHT);
    Renderer renderer(window);

    GroupRenderer gr(WINDOW_WIDTH, WINDOW_HEIGHT);

    steady_clock::time_point lastTime = steady_clock::now();

    phi::P3 particles[OBJECTS];
    phi::V3 colors[OBJECTS];

    std::mt19937 rand(3);

    for (unsigned i = 0; i != OBJECTS; i++) {
        particles[i].position = phi::V3(rand()/double(rand.max())*2-1, rand()/double(rand.max())*2-1, rand()/double(rand.max())/8);
        particles[i].velocity = phi::V3(rand()/double(rand.max())*2-1, rand()/double(rand.max())*2-1, rand()/double(rand.max())*2-1);
        particles[i].velocity *= 0.0005;
        particles[i].inertia = 100.0;

        colors[i] = phi::V3(rand()/double(rand.max()), rand()/double(rand.max()), rand()/double(rand.max()));
        colors[i] *= 1;
    }

    uint16_t *posbuffer = (uint16_t*)gr.buffer.buffer.map(GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);

    while (true) {
        SDL_Event event;
        while (window.pollEvent(event)) {
            switch (event.type) {
            case SDL_QUIT:
                return 0;
            }
        }

        #pragma omp parallel for
        for (int i = 0; i != OBJECTS; i++) {
            //particles[i].gravitate(0.1, phi::V3(0, 0, 0), 0.1);
            for (int j = 0; j != OBJECTS; j++)
                if (i != j)
                    particles[i].gravitate(0.0001, particles[j].position, 0.1);
        }

        for (unsigned i = 0; i != OBJECTS; i++) {
            particles[i].advance();
            posbuffer[i*7 + 0] = toHalfFloat(particles[i].position.x);
            posbuffer[i*7 + 1] = toHalfFloat(particles[i].position.y);
            posbuffer[i*7 + 2] = toHalfFloat(particles[i].position.z);

            posbuffer[i*7 + 3] = toHalfFloat(colors[i].x);
            posbuffer[i*7 + 4] = toHalfFloat(colors[i].y);
            posbuffer[i*7 + 5] = toHalfFloat(colors[i].z);

            posbuffer[i*7 + 6] = toHalfFloat(0.1);
        }

        gr.buffer.buffer.sync();

        gr.render(OBJECTS, WINDOW_WIDTH, WINDOW_HEIGHT);

        steady_clock::time_point thisTime = steady_clock::now();
        this_thread::sleep_for(lastTime - thisTime + duration<double>(1.0/FPS));
        double timeDelta = duration_cast<duration<double>>(thisTime - lastTime).count();
        cout << "FPS: " << (1.0/timeDelta) << endl;
        lastTime = thisTime;

        window.flip();
    }
    return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2007 Rony Shapiro <ronys@users.sourceforge.net>.
 * All rights reserved. Use of the code is allowed under the
 * Artistic License terms, as specified in the LICENSE file
 * distributed with this code, or available from
 * http://www.opensource.org/licenses/artistic-license.php
 */
// UUIDGen.cpp
// Silly class for generating UUIDs
// Each instance has its own unique value,
// which can be accessed as an array of bytes or as a human-readable
// ASCII string.
//

#include "UUIDGen.h"
#include "util.h" /* for trashMemory() */
#include <stdio.h> /* for _stprintf() */
#include <assert.h>

#ifdef _WIN32
#include <Winsock2.h> /* for htonl, htons */
#else
/* currently here only for Cygwin test harness */
#include <asm/byteorder.h> /* for htonl, htons */
#endif

CUUIDGen::CUUIDGen()
{
  UuidCreate(&uuid);
}

CUUIDGen::CUUIDGen(const uuid_array_t &uuid_array)
{
  unsigned long *p0 = (unsigned long *)uuid_array;
  uuid.Data1 = htonl(*p0);
  unsigned short *p1 = (unsigned short *)&uuid_array[4];
  uuid.Data2 = htons(*p1);
  unsigned short *p2 = (unsigned short *)&uuid_array[6];
  uuid.Data3 = htons(*p2);
  for (int i = 0; i < 8; i++)
    uuid.Data4[i] = uuid_array[i + 8];
}

CUUIDGen::~CUUIDGen()
{
  trashMemory((unsigned char *)&uuid, sizeof(uuid));
}

void CUUIDGen::GetUUID(uuid_array_t &uuid_array) const
{
  unsigned long *p0 = (unsigned long *)uuid_array;
  *p0 = htonl(uuid.Data1);
  unsigned short *p1 = (unsigned short *)&uuid_array[4];
  *p1 = htons(uuid.Data2);
  unsigned short *p2 = (unsigned short *)&uuid_array[6];
  *p2 = htons(uuid.Data3);
  for (int i = 0; i < 8; i++)
    uuid_array[i + 8] = uuid.Data4[i];
}

void CUUIDGen::GetUUIDStr(uuid_str_t &str) const
{
#if _MSC_VER >= 1400
  _stprintf_s((char *)str, 37,
#else
  _stprintf((char *)str,
#endif
	  "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
	  uuid.Data1, uuid.Data2, uuid.Data3,
	  (unsigned char) uuid.Data4[0], (unsigned char) uuid.Data4[1],
	  (unsigned char) uuid.Data4[2], (unsigned char) uuid.Data4[3],
	  (unsigned char) uuid.Data4[4], (unsigned char) uuid.Data4[5],
	  (unsigned char) uuid.Data4[6], (unsigned char) uuid.Data4[7]);
}

#ifdef TEST
#include <stdio.h>
int main()
{
  uuid_str_t str;
  uuid_array_t uuid_array;

  for (int i = 0; i< 10; i++) {
    CUUIDGen uuid;
    uuid.GetUUIDStr(str);
    printf("%s\n",str);
    uuid.GetUUID(uuid_array);
    printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
	   uuid_array[0], uuid_array[1], uuid_array[2], uuid_array[3],
	   uuid_array[4], uuid_array[5], uuid_array[6], uuid_array[7],
	   uuid_array[8], uuid_array[9], uuid_array[10], uuid_array[11],
	   uuid_array[12], uuid_array[13], uuid_array[14], uuid_array[15]);
  }
  return 0;
}
#endif
<commit_msg>Replaced 37 with it's meaning.<commit_after>/*
 * Copyright (c) 2003-2007 Rony Shapiro <ronys@users.sourceforge.net>.
 * All rights reserved. Use of the code is allowed under the
 * Artistic License terms, as specified in the LICENSE file
 * distributed with this code, or available from
 * http://www.opensource.org/licenses/artistic-license.php
 */
// UUIDGen.cpp
// Silly class for generating UUIDs
// Each instance has its own unique value,
// which can be accessed as an array of bytes or as a human-readable
// ASCII string.
//

#include "UUIDGen.h"
#include "util.h" /* for trashMemory() */
#include <stdio.h> /* for _stprintf() */
#include <assert.h>

#ifdef _WIN32
#include <Winsock2.h> /* for htonl, htons */
#else
/* currently here only for Cygwin test harness */
#include <asm/byteorder.h> /* for htonl, htons */
#endif

CUUIDGen::CUUIDGen()
{
  UuidCreate(&uuid);
}

CUUIDGen::CUUIDGen(const uuid_array_t &uuid_array)
{
  unsigned long *p0 = (unsigned long *)uuid_array;
  uuid.Data1 = htonl(*p0);
  unsigned short *p1 = (unsigned short *)&uuid_array[4];
  uuid.Data2 = htons(*p1);
  unsigned short *p2 = (unsigned short *)&uuid_array[6];
  uuid.Data3 = htons(*p2);
  for (int i = 0; i < 8; i++)
    uuid.Data4[i] = uuid_array[i + 8];
}

CUUIDGen::~CUUIDGen()
{
  trashMemory((unsigned char *)&uuid, sizeof(uuid));
}

void CUUIDGen::GetUUID(uuid_array_t &uuid_array) const
{
  unsigned long *p0 = (unsigned long *)uuid_array;
  *p0 = htonl(uuid.Data1);
  unsigned short *p1 = (unsigned short *)&uuid_array[4];
  *p1 = htons(uuid.Data2);
  unsigned short *p2 = (unsigned short *)&uuid_array[6];
  *p2 = htons(uuid.Data3);
  for (int i = 0; i < 8; i++)
    uuid_array[i + 8] = uuid.Data4[i];
}

void CUUIDGen::GetUUIDStr(uuid_str_t &str) const
{
#if _MSC_VER >= 1400
    _stprintf_s((char *)str, sizeof(str)/sizeof(str[0]),
#else
    _stprintf((char *)str,
#endif
	  "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
	  uuid.Data1, uuid.Data2, uuid.Data3,
	  (unsigned char) uuid.Data4[0], (unsigned char) uuid.Data4[1],
	  (unsigned char) uuid.Data4[2], (unsigned char) uuid.Data4[3],
	  (unsigned char) uuid.Data4[4], (unsigned char) uuid.Data4[5],
	  (unsigned char) uuid.Data4[6], (unsigned char) uuid.Data4[7]);
}

#ifdef TEST
#include <stdio.h>
int main()
{
  uuid_str_t str;
  uuid_array_t uuid_array;

  for (int i = 0; i< 10; i++) {
    CUUIDGen uuid;
    uuid.GetUUIDStr(str);
    printf("%s\n",str);
    uuid.GetUUID(uuid_array);
    printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
	   uuid_array[0], uuid_array[1], uuid_array[2], uuid_array[3],
	   uuid_array[4], uuid_array[5], uuid_array[6], uuid_array[7],
	   uuid_array[8], uuid_array[9], uuid_array[10], uuid_array[11],
	   uuid_array[12], uuid_array[13], uuid_array[14], uuid_array[15]);
  }
  return 0;
}
#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library 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.
 *
 * This library 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 this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$
#include <mapnik/global.hpp>
#include <mapnik/octree.hpp>
#include <mapnik/global.hpp>

extern "C"
{
#include <png.h>
}

namespace mapnik {

   template <typename T>
   void write_data (png_structp png_ptr, png_bytep data, png_size_t length)
   {
      T * out = static_cast<T*>(png_get_io_ptr(png_ptr));
      out->write(reinterpret_cast<char*>(data), length);
   }

   template <typename T>
   void flush_data (png_structp png_ptr)
   {
      T * out = static_cast<T*>(png_get_io_ptr(png_ptr));
      out->flush();
   }

   template <typename T1, typename T2>
   void save_as_png(T1 & file , T2 const& image)
   {
      png_voidp error_ptr=0;
      png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                                  error_ptr,0, 0);

      if (!png_ptr) return;

      // switch on optimization only if supported
#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED)
      png_uint_32 mask, flags;
      flags = png_get_asm_flags(png_ptr);
      mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
      png_set_asm_flags(png_ptr, flags | mask);
#endif
      png_set_filter (png_ptr, 0, PNG_FILTER_NONE);
      png_infop info_ptr = png_create_info_struct(png_ptr);
      if (!info_ptr)
      {
         png_destroy_write_struct(&png_ptr,(png_infopp)0);
         return;
      }
      if (setjmp(png_jmpbuf(png_ptr)))
      {
         png_destroy_write_struct(&png_ptr, &info_ptr);
         return;
      }
      png_set_write_fn (png_ptr, &file, &write_data<T1>, &flush_data<T1>);

      //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
      //png_set_compression_strategy(png_ptr, Z_FILTERED);
      png_set_IHDR(png_ptr, info_ptr,image.width(),image.height(),8,
                   PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE,
                   PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
      png_write_info(png_ptr, info_ptr);
      for (unsigned i=0;i<image.height();i++)
      {
         png_write_row(png_ptr,(png_bytep)image.getRow(i));
      }

      png_write_end(png_ptr, info_ptr);
      png_destroy_write_struct(&png_ptr, &info_ptr);
   }

   template <typename T>
   void reduce_8  (T const& in, image_data_8 & out, octree<rgb> & tree)
   {
      unsigned width = in.width();
      unsigned height = in.height();
      for (unsigned y = 0; y < height; ++y)
      {
         mapnik::image_data_32::pixel_type const * row = in.getRow(y);
         mapnik::image_data_8::pixel_type  * row_out = out.getRow(y);
         for (unsigned x = 0; x < width; ++x)
         {
            unsigned val = row[x];
#ifdef MAPNIK_BIG_ENDIAN
            mapnik::rgb c((val>>24)&0xff, (val>>16)&0xff, (val>>8) & 0xff);
            byte index = tree.quantize(c);
            if (!(val&0x80)) index = 0;//alfa
#else
            mapnik::rgb c((val)&0xff, (val>>8)&0xff, (val>>16) & 0xff);
            byte index = tree.quantize(c);
            if (!((val>>24)&0x80)) index = 0;//alfa
#endif
            row_out[x] = index;
         }
      }
   }

   template <typename T>
   void reduce_4 (T const& in, image_data_8 & out, octree<rgb> & tree)
   {
      unsigned width = in.width();
      unsigned height = in.height();

      for (unsigned y = 0; y < height; ++y)
      {
         mapnik::image_data_32::pixel_type const * row = in.getRow(y);
         mapnik::image_data_8::pixel_type  * row_out = out.getRow(y);

         for (unsigned x = 0; x < width; ++x)
         {
            unsigned val = row[x];
#ifdef MAPNIK_BIG_ENDIAN
            mapnik::rgb c((val>>24)&0xff, (val>>16)&0xff, (val>>8) & 0xff);
            byte index = tree.quantize(c);
            if (x%2 >  0) index = index<<4;
            if (!(val&0x80)) index = 0;//alfa
#else
            mapnik::rgb c((val)&0xff, (val>>8)&0xff, (val>>16) & 0xff);
            byte index = tree.quantize(c);
            if (x%2 >  0) index = index<<4;
            if (!((val>>24)&0x80)) index = 0;//alfa
#endif
            row_out[x>>1] |= index;
         }
      }
   }

   // 1-bit but only one color.
   template <typename T>
   void reduce_1(T const&, image_data_8 & out, octree<rgb> &)
   {
      out.set(0); // only one color!!!
   }

   template <typename T>
   void save_as_png(T & file, std::vector<mapnik::rgb> & palette,
                    mapnik::image_data_8 const& image,
                    unsigned width,
                    unsigned height,
                    unsigned color_depth,
                    bool hasAlfa)
   {
      png_voidp error_ptr=0;
      png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                                  error_ptr,0, 0);

      if (!png_ptr) return;

      // switch on optimization only if supported
#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED)
      png_uint_32 mask, flags;
      flags = png_get_asm_flags(png_ptr);
      mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
      png_set_asm_flags(png_ptr, flags | mask);
#endif
      png_set_filter (png_ptr, 0, PNG_FILTER_NONE);
      png_infop info_ptr = png_create_info_struct(png_ptr);
      if (!info_ptr)
      {
         png_destroy_write_struct(&png_ptr,(png_infopp)0);
         return;
      }
      if (setjmp(png_jmpbuf(png_ptr)))
      {
         png_destroy_write_struct(&png_ptr, &info_ptr);
         return;
      }
      png_set_write_fn (png_ptr, &file, &write_data<T>, &flush_data<T>);

      png_set_IHDR(png_ptr, info_ptr,width,height,color_depth,
                   PNG_COLOR_TYPE_PALETTE,PNG_INTERLACE_NONE,
                   PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);

      png_set_PLTE(png_ptr,info_ptr,reinterpret_cast<png_color*>(&palette[0]),palette.size());

      // make transparent lowest indexes, so tRNS is small
      if (hasAlfa)
      {
         byte trans[] = {0,0,0,0};
         //png_color_16p unused;
         png_set_tRNS(png_ptr, info_ptr, (png_bytep)trans, 1, NULL);
      }

      png_write_info(png_ptr, info_ptr);
      for (unsigned i=0;i<height;i++)
      {
         png_write_row(png_ptr,(png_bytep)image.getRow(i));
      }

      png_write_end(png_ptr, info_ptr);
      png_destroy_write_struct(&png_ptr, &info_ptr);
   }

   template <typename T1,typename T2>
   void save_as_png256(T1 & file, T2 const& image)
   {
      octree<rgb> tree(256);
      unsigned width = image.width();
      unsigned height = image.height();
      for (unsigned y = 0; y < height; ++y)
      {
         typename T2::pixel_type const * row = image.getRow(y);
         for (unsigned x = 0; x < width; ++x)
         {
            unsigned val = row[x];
#ifdef MAPNIK_BIG_ENDIAN
            if (val&0x80)
            {
               tree.insert(mapnik::rgb((val>>24)&0xff, (val>>16)&0xff, (val>>8) & 0xff));
            }
#else
            if ((val>>24)&0x80)
            {
               tree.insert(mapnik::rgb((val)&0xff, (val>>8)&0xff, (val>>16) & 0xff));
            }
#endif
            else
            {
               tree.hasAlfa(true);
            }
         }
      }

      std::vector<rgb> palette;
      tree.create_palette(palette);
      assert(palette.size() <= 256);

      if (palette.size() > 16 )
      {
         // >16 && <=256 colors -> write 8-bit color depth
         image_data_8 reduced_image(width,height);
         reduce_8(image,reduced_image,tree);
         save_as_png(file,palette,reduced_image,width,height,8,tree.hasAlfa());
      }
      else if (palette.size() == 1)
      {
         // 1 color image ->  write 1-bit color depth PNG
         unsigned image_width  = (int(0.125*width) + 7)&~7;
         unsigned image_height = height;
         image_data_8 reduced_image(image_width,image_height);
         reduce_1(image,reduced_image,tree);
         save_as_png(file,palette,reduced_image,width,height,1,tree.hasAlfa());
      }
      else
      {
         // <=16 colors -> write 4-bit color depth PNG
         unsigned image_width  = (int(0.5*width) + 3)&~3;
         unsigned image_height = height;
         image_data_8 reduced_image(image_width,image_height);
         reduce_4(image,reduced_image,tree);
         save_as_png(file,palette,reduced_image,width,height,4,tree.hasAlfa());
      }
   }
}
<commit_msg>apply patch from marcin to fix problem with occaisionaly garbled/striped png256 output along shape edges - closes #416,#445,#447, improves upon #202<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library 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.
 *
 * This library 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 this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$
#include <mapnik/global.hpp>
#include <mapnik/octree.hpp>
#include <mapnik/global.hpp>

extern "C"
{
#include <png.h>
}

namespace mapnik {

   template <typename T>
   void write_data (png_structp png_ptr, png_bytep data, png_size_t length)
   {
      T * out = static_cast<T*>(png_get_io_ptr(png_ptr));
      out->write(reinterpret_cast<char*>(data), length);
   }

   template <typename T>
   void flush_data (png_structp png_ptr)
   {
      T * out = static_cast<T*>(png_get_io_ptr(png_ptr));
      out->flush();
   }

   template <typename T1, typename T2>
   void save_as_png(T1 & file , T2 const& image)
   {
      png_voidp error_ptr=0;
      png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                                  error_ptr,0, 0);

      if (!png_ptr) return;

      // switch on optimization only if supported
#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED)
      png_uint_32 mask, flags;
      flags = png_get_asm_flags(png_ptr);
      mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
      png_set_asm_flags(png_ptr, flags | mask);
#endif
      png_set_filter (png_ptr, 0, PNG_FILTER_NONE);
      png_infop info_ptr = png_create_info_struct(png_ptr);
      if (!info_ptr)
      {
         png_destroy_write_struct(&png_ptr,(png_infopp)0);
         return;
      }
      if (setjmp(png_jmpbuf(png_ptr)))
      {
         png_destroy_write_struct(&png_ptr, &info_ptr);
         return;
      }
      png_set_write_fn (png_ptr, &file, &write_data<T1>, &flush_data<T1>);

      //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
      //png_set_compression_strategy(png_ptr, Z_FILTERED);
      png_set_IHDR(png_ptr, info_ptr,image.width(),image.height(),8,
                   PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE,
                   PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
      png_write_info(png_ptr, info_ptr);
      for (unsigned i=0;i<image.height();i++)
      {
         png_write_row(png_ptr,(png_bytep)image.getRow(i));
      }

      png_write_end(png_ptr, info_ptr);
      png_destroy_write_struct(&png_ptr, &info_ptr);
   }

   template <typename T>
   void reduce_8  (T const& in, image_data_8 & out, octree<rgb> & tree)
   {
      unsigned width = in.width();
      unsigned height = in.height();
      for (unsigned y = 0; y < height; ++y)
      {
         mapnik::image_data_32::pixel_type const * row = in.getRow(y);
         mapnik::image_data_8::pixel_type  * row_out = out.getRow(y);
         for (unsigned x = 0; x < width; ++x)
         {
            unsigned val = row[x];
#ifdef MAPNIK_BIG_ENDIAN
            mapnik::rgb c((val>>24)&0xff, (val>>16)&0xff, (val>>8) & 0xff);
            byte index = tree.quantize(c);
            if (!(val&0x80)) index = 0;//alfa
#else
            mapnik::rgb c((val)&0xff, (val>>8)&0xff, (val>>16) & 0xff);
            byte index = tree.quantize(c);
            if (!((val>>24)&0x80)) index = 0;//alfa
#endif
            row_out[x] = index;
         }
      }
   }

   template <typename T>
   void reduce_4 (T const& in, image_data_8 & out, octree<rgb> & tree)
   {
      unsigned width = in.width();
      unsigned height = in.height();

      for (unsigned y = 0; y < height; ++y)
      {
         mapnik::image_data_32::pixel_type const * row = in.getRow(y);
         mapnik::image_data_8::pixel_type  * row_out = out.getRow(y);

         for (unsigned x = 0; x < width; ++x)
         {
            unsigned val = row[x];
#ifdef MAPNIK_BIG_ENDIAN
            mapnik::rgb c((val>>24)&0xff, (val>>16)&0xff, (val>>8) & 0xff);
            byte index = tree.quantize(c);
            if (x%2 == 0) index = index<<4;
            if (!(val&0x80)) index = 0;//alfa
#else
            mapnik::rgb c((val)&0xff, (val>>8)&0xff, (val>>16) & 0xff);
            byte index = tree.quantize(c);
            if (x%2 == 0) index = index<<4;
            if (!((val>>24)&0x80)) index = 0;//alfa
#endif
            row_out[x>>1] |= index;
         }
      }
   }

   // 1-bit but only one color.
   template <typename T>
   void reduce_1(T const&, image_data_8 & out, octree<rgb> &)
   {
      out.set(0); // only one color!!!
   }

   template <typename T>
   void save_as_png(T & file, std::vector<mapnik::rgb> & palette,
                    mapnik::image_data_8 const& image,
                    unsigned width,
                    unsigned height,
                    unsigned color_depth,
                    bool hasAlfa)
   {
      png_voidp error_ptr=0;
      png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                                  error_ptr,0, 0);

      if (!png_ptr) return;

      // switch on optimization only if supported
#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED)
      png_uint_32 mask, flags;
      flags = png_get_asm_flags(png_ptr);
      mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
      png_set_asm_flags(png_ptr, flags | mask);
#endif
      png_set_filter (png_ptr, 0, PNG_FILTER_NONE);
      png_infop info_ptr = png_create_info_struct(png_ptr);
      if (!info_ptr)
      {
         png_destroy_write_struct(&png_ptr,(png_infopp)0);
         return;
      }
      if (setjmp(png_jmpbuf(png_ptr)))
      {
         png_destroy_write_struct(&png_ptr, &info_ptr);
         return;
      }
      png_set_write_fn (png_ptr, &file, &write_data<T>, &flush_data<T>);

      png_set_IHDR(png_ptr, info_ptr,width,height,color_depth,
                   PNG_COLOR_TYPE_PALETTE,PNG_INTERLACE_NONE,
                   PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);

      png_set_PLTE(png_ptr,info_ptr,reinterpret_cast<png_color*>(&palette[0]),palette.size());

      // make transparent lowest indexes, so tRNS is small
      if (hasAlfa)
      {
         byte trans[] = {0,0,0,0};
         //png_color_16p unused;
         png_set_tRNS(png_ptr, info_ptr, (png_bytep)trans, 1, NULL);
      }

      png_write_info(png_ptr, info_ptr);
      for (unsigned i=0;i<height;i++)
      {
         png_write_row(png_ptr,(png_bytep)image.getRow(i));
      }

      png_write_end(png_ptr, info_ptr);
      png_destroy_write_struct(&png_ptr, &info_ptr);
   }

   template <typename T1,typename T2>
   void save_as_png256(T1 & file, T2 const& image)
   {
      octree<rgb> tree(256);
      unsigned width = image.width();
      unsigned height = image.height();
      for (unsigned y = 0; y < height; ++y)
      {
         typename T2::pixel_type const * row = image.getRow(y);
         for (unsigned x = 0; x < width; ++x)
         {
            unsigned val = row[x];
#ifdef MAPNIK_BIG_ENDIAN
            if (val&0x80)
            {
               tree.insert(mapnik::rgb((val>>24)&0xff, (val>>16)&0xff, (val>>8) & 0xff));
            }
#else
            if ((val>>24)&0x80)
            {
               tree.insert(mapnik::rgb((val)&0xff, (val>>8)&0xff, (val>>16) & 0xff));
            }
#endif
            else
            {
               tree.hasAlfa(true);
            }
         }
      }

      std::vector<rgb> palette;
      tree.create_palette(palette);
      assert(palette.size() <= 256);

      if (palette.size() > 16 )
      {
         // >16 && <=256 colors -> write 8-bit color depth
         image_data_8 reduced_image(width,height);
         reduce_8(image,reduced_image,tree);
         save_as_png(file,palette,reduced_image,width,height,8,tree.hasAlfa());
      }
      else if (palette.size() == 1)
      {
         // 1 color image ->  write 1-bit color depth PNG
         unsigned image_width  = (int(0.125*width) + 7)&~7;
         unsigned image_height = height;
         image_data_8 reduced_image(image_width,image_height);
         reduce_1(image,reduced_image,tree);
         save_as_png(file,palette,reduced_image,width,height,1,tree.hasAlfa());
      }
      else
      {
         // <=16 colors -> write 4-bit color depth PNG
         unsigned image_width  = (int(0.5*width) + 3)&~3;
         unsigned image_height = height;
         image_data_8 reduced_image(image_width,image_height);
         reduce_4(image,reduced_image,tree);
         save_as_png(file,palette,reduced_image,width,height,4,tree.hasAlfa());
      }
   }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

/**
 * @file pandora/Block.hpp
 * @brief Definition of the class Block.
 */

#ifndef PAN_BOCK_H_INCLUDE
#define PAN_BOCK_H_INCLUDE

#include <vector>
#include <string>

#include <pandora/EntityWithMetadata.hpp>

namespace pandora {

class Section;
class Source;
class DataArray;
class SimpleTag;
class DataTag;

/**
 * Class that represents a pandora Block entity.
 */
class Block : public EntityWithMetadata {

private:

  Group source_group, data_array_group, simple_tag_group, data_tag_group;

public:

  /**
   * Copy constructor.
   *
   * @param block     The block to create the new copy from.
   */
  Block(const Block &block);

  /**
   * Standard constructor for a Block.
   *
   * @param file      The file which contains this block.
   * @param group     The group that represents the block inside the file.
   * @param id        The id of this block.
   */
  Block(File file, Group group, std::string id);

  /**
   * Standard constructor for a Block.
   *
   * @param file      The file which contains this block.
   * @param group     The group that represents the block inside the file.
   * @param id        The id of this block.
   */
  Block(File file, Group group, std::string id, time_t time);

  //--------------------------------------------------
  // Methods concerning sources
  // TODO implement source methods
  //--------------------------------------------------

  /**
   * Checks if this block has a specific root source.
   *
   * @param id        The id of the source.
   *
   * @return True if a source with the given id exists at the root, false
   *         otherwise.
   */
  bool hasSource(std::string id) const;

  /**
   * Retrieves a specific root source.
   *
   * @param id        The id of the source.
   *
   * @return The source with the given id. If it doesn't exist an exception
   *         will be thrown.
   */
  Source getSource(std::string id) const;

  /**
   * Retrieves a specific root source by index.
   *
   * @param index     The index of the source.
   *
   * @return The source at the specified index.
   */
  Source getSource(size_t index) const;

  /**
   * Checks if a source with a specific id exists either as a root source or
   * somewhere in the subtree of all root sources.
   *
   * @param id        The id of the source.
   *
   * @return True if a source with the given id exists, false otherwise.
   */
  bool existsSource(std::string id) const;

  /**
   * Retrieves a specific source by searching all sources and their
   * child sources.
   *
   * @param id        The id of the source.
   *
   * @return The source with the given id. If it doesn't exist an exception
   *         will be thrown.
   */
  Source findSource(std::string id) const;

  /**
   * Returns the number of root sources in this block.
   *
   * @return The number of root sources.
   */
  size_t sourceCount() const;

  /**
   * Returns all root sources in this block as a vector.
   *
   * @return All root sources.
   */
  std::vector<Source> sources() const;

  /**
   * Create a new root source.
   *
   * @param name      The name of the source to create.
   * @param type      The type of the source.
   *
   * @return The created source object.
   */
  Source createSource(std::string name, std::string type);

  /**
   * Remove a root source and all its child sources from
   * the block.
   *
   * @param id        The id of the source to remove.
   *
   * @return True if the source was removed, false otherwise.
   */
  bool removeSource(std::string id);

  //--------------------------------------------------
  // Methods concerning data arrays
  // TODO implement data array methods
  //--------------------------------------------------

  /**
   * Checks if a specific data array exists in this block.
   *
   * @param id        The id of a data array.
   *
   * @return True if the data array exists, false otherwise.
   */
  bool hasDataArray(std::string id) const;

  /**
   * Retrieves a specific data array from the block.
   *
   * @param id        The id of an existing data array.
   *
   * @return The data array with the specified id. If this
   *         doesn't exist, an exception will be thrown.
   */
  DataArray getDataArray(std::string id) const;

  /**
   * Retrieves a data array by index.
   *
   * @param index     The index of the data array.
   *
   * @return The data array at the specified index.
   */
  DataArray getDataArray(size_t index) const;

  /**
   * Returns all data arrays of this block as a vector.
   *
   * @return All data arrays.
   */
  std::vector<DataArray> dataArrays() const;

  /**
   * Returns the number of all data arrays of the block.
   *
   * @return The number of data arrays of the block.
   */
  size_t dataArrayCount() const;

  /**
   * Create a new data array associated with this block.
   *
   * @param name      The name of the data array to create.
   *
   * @return The newly created data array.
   */
  DataArray createDataArray(std::string name, std::string type);

  /**
   * Remove/delete a data array from this block.
   *
   * @param id        The id of the data array to remove.
   *
   * @return True if the data array was removed, false otherwise.
   */
  bool removeDataArray(std::string id);

  //--------------------------------------------------
  // Methods concerning simple tags.
  // TODO implement simple tag methods.
  //--------------------------------------------------

  /**
   * Checks if a specific simple tag exists in the block.
   *
   * @param id        The id of a simple tag.
   *
   * @return True if the simple tag exists, false otherwise.
   */
  bool hasSimpleTag(std::string id) const;

  /**
   * Retrieves a specific simple tag from the block.
   *
   * @param id        The id of the simple tag.
   *
   * @return The tag with the specified id. If this tag doesn't exist
   *         an exception will be thrown.
   */
  SimpleTag getSimpleTag(std::string id) const;

  /**
   * Retrieves a specific simple tag by index.
   *
   * @param index     The index of the tag.
   *
   * @return The simple tag at the specified index.
   */
  SimpleTag getSimpleTag(size_t index) const;

  /**
   * Get all simple tags associated with this block.
   *
   * @return All simple tags as a vector.
   */
  std::vector<SimpleTag> simpleTags() const;

  /**
   * Returns the number of simple tag associated with
   * this block.
   *
   * @return The number of simple tags.
   */
  size_t simpleTagCount() const;

  /**
   * Create a new simple tag associated with this block.
   *
   * @param name      The name of the simple tag to create.
   * @param type      The type of the tag.
   *
   * @return The newly created tag.
   */
  SimpleTag createSimpleTag(std::string name, std::string type);

  /**
   * Remove a simple tag from the block.
   *
   * @param id        The id of the tag to remove.
   *
   * @return True if the tag was removed, false otherwise.
   */
  bool removeSimpleTag(std::string id);

  //--------------------------------------------------
  // Methods concerning data tags.
  // TODO implement data tag methods.
  //--------------------------------------------------

  /**
   * Checks if a specific data tag exists in the block.
   *
   * @param id        The id of a data tag.
   *
   * @return True if the data tag exists, false otherwise.
   */
  bool hasDataTag(std::string id) const;

  /**
   * Retrieves a specific data tag from the block.
   *
   * @param id        The id of the data tag.
   *
   * @return The tag with the specified id. If this tag doesn't exist
   *         an exception will be thrown.
   */
  DataTag getDataTag(std::string id) const;

  /**
   * Retrieves a specific data tag by index.
   *
   * @param index     The index of the tag.
   *
   * @return The data tag at the specified index.
   */
  DataTag getDataTag(size_t index) const;

  /**
   * Get all simple data associated with this block.
   *
   * @return All simple tags as a vector.
   */
  std::vector<DataTag> dataTags() const;

  /**
   * Returns the number of data tag associated with
   * this block.
   *
   * @return The number of data tags.
   */
  size_t dataTagCount() const;

  /**
   * Create a new data tag associated with this block.
   *
   * @param name      The name of the data tag to create.
   * @param type      The type of the tag.
   *
   * @return The newly created tag.
   */
  DataTag createDataTag(std::string name, std::string type);

  /**
   * Remove a data tag from the block.
   *
   * @param id        The id of the tag to remove.
   *
   * @return True if the tag was removed, false otherwise.
   */
  void removeDataTag(std::string id);

  //--------------------------------------------------
  // Other methods and functions
  //--------------------------------------------------

  Block& operator=(const Block &other) {
    if (*this != other) {
        this->file = other.file;
        this->group = other.group;
        this->entity_id = other.entity_id;
        this->source_group = other.source_group;
        this->data_array_group = other.data_array_group;
        this->simple_tag_group = other.simple_tag_group;
        this->data_tag_group = other.data_tag_group;
      }
      return *this;
  }

  /**
   * Output operator
   */
  friend std::ostream& operator<<(std::ostream &out, const Block &ent);

  virtual ~Block();

};

}

#endif // HDX_BOCK_H_INCLUDE
<commit_msg>Block: assignment operator added<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

/**
 * @file pandora/Block.hpp
 * @brief Definition of the class Block.
 */

#ifndef PAN_BOCK_H_INCLUDE
#define PAN_BOCK_H_INCLUDE

#include <vector>
#include <string>

#include <pandora/EntityWithMetadata.hpp>

namespace pandora {

class Section;
class Source;
class DataArray;
class SimpleTag;
class DataTag;

/**
 * Class that represents a pandora Block entity.
 */
class Block : public EntityWithMetadata {

private:

  Group source_group, data_array_group, simple_tag_group, data_tag_group;

public:

  /**
   * Copy constructor.
   *
   * @param block     The block to create the new copy from.
   */
  Block(const Block &block);

  /**
   * Standard constructor for a Block.
   *
   * @param file      The file which contains this block.
   * @param group     The group that represents the block inside the file.
   * @param id        The id of this block.
   */
  Block(File file, Group group, std::string id);

  /**
   * Standard constructor for a Block.
   *
   * @param file      The file which contains this block.
   * @param group     The group that represents the block inside the file.
   * @param id        The id of this block.
   */
  Block(File file, Group group, std::string id, time_t time);

  //--------------------------------------------------
  // Methods concerning sources
  // TODO implement source methods
  //--------------------------------------------------

  /**
   * Checks if this block has a specific root source.
   *
   * @param id        The id of the source.
   *
   * @return True if a source with the given id exists at the root, false
   *         otherwise.
   */
  bool hasSource(std::string id) const;

  /**
   * Retrieves a specific root source.
   *
   * @param id        The id of the source.
   *
   * @return The source with the given id. If it doesn't exist an exception
   *         will be thrown.
   */
  Source getSource(std::string id) const;

  /**
   * Retrieves a specific root source by index.
   *
   * @param index     The index of the source.
   *
   * @return The source at the specified index.
   */
  Source getSource(size_t index) const;

  /**
   * Checks if a source with a specific id exists either as a root source or
   * somewhere in the subtree of all root sources.
   *
   * @param id        The id of the source.
   *
   * @return True if a source with the given id exists, false otherwise.
   */
  bool existsSource(std::string id) const;

  /**
   * Retrieves a specific source by searching all sources and their
   * child sources.
   *
   * @param id        The id of the source.
   *
   * @return The source with the given id. If it doesn't exist an exception
   *         will be thrown.
   */
  Source findSource(std::string id) const;

  /**
   * Returns the number of root sources in this block.
   *
   * @return The number of root sources.
   */
  size_t sourceCount() const;

  /**
   * Returns all root sources in this block as a vector.
   *
   * @return All root sources.
   */
  std::vector<Source> sources() const;

  /**
   * Create a new root source.
   *
   * @param name      The name of the source to create.
   * @param type      The type of the source.
   *
   * @return The created source object.
   */
  Source createSource(std::string name, std::string type);

  /**
   * Remove a root source and all its child sources from
   * the block.
   *
   * @param id        The id of the source to remove.
   *
   * @return True if the source was removed, false otherwise.
   */
  bool removeSource(std::string id);

  //--------------------------------------------------
  // Methods concerning data arrays
  // TODO implement data array methods
  //--------------------------------------------------

  /**
   * Checks if a specific data array exists in this block.
   *
   * @param id        The id of a data array.
   *
   * @return True if the data array exists, false otherwise.
   */
  bool hasDataArray(std::string id) const;

  /**
   * Retrieves a specific data array from the block.
   *
   * @param id        The id of an existing data array.
   *
   * @return The data array with the specified id. If this
   *         doesn't exist, an exception will be thrown.
   */
  DataArray getDataArray(std::string id) const;

  /**
   * Retrieves a data array by index.
   *
   * @param index     The index of the data array.
   *
   * @return The data array at the specified index.
   */
  DataArray getDataArray(size_t index) const;

  /**
   * Returns all data arrays of this block as a vector.
   *
   * @return All data arrays.
   */
  std::vector<DataArray> dataArrays() const;

  /**
   * Returns the number of all data arrays of the block.
   *
   * @return The number of data arrays of the block.
   */
  size_t dataArrayCount() const;

  /**
   * Create a new data array associated with this block.
   *
   * @param name      The name of the data array to create.
   *
   * @return The newly created data array.
   */
  DataArray createDataArray(std::string name, std::string type);

  /**
   * Remove/delete a data array from this block.
   *
   * @param id        The id of the data array to remove.
   *
   * @return True if the data array was removed, false otherwise.
   */
  bool removeDataArray(std::string id);

  //--------------------------------------------------
  // Methods concerning simple tags.
  // TODO implement simple tag methods.
  //--------------------------------------------------

  /**
   * Checks if a specific simple tag exists in the block.
   *
   * @param id        The id of a simple tag.
   *
   * @return True if the simple tag exists, false otherwise.
   */
  bool hasSimpleTag(std::string id) const;

  /**
   * Retrieves a specific simple tag from the block.
   *
   * @param id        The id of the simple tag.
   *
   * @return The tag with the specified id. If this tag doesn't exist
   *         an exception will be thrown.
   */
  SimpleTag getSimpleTag(std::string id) const;

  /**
   * Retrieves a specific simple tag by index.
   *
   * @param index     The index of the tag.
   *
   * @return The simple tag at the specified index.
   */
  SimpleTag getSimpleTag(size_t index) const;

  /**
   * Get all simple tags associated with this block.
   *
   * @return All simple tags as a vector.
   */
  std::vector<SimpleTag> simpleTags() const;

  /**
   * Returns the number of simple tag associated with
   * this block.
   *
   * @return The number of simple tags.
   */
  size_t simpleTagCount() const;

  /**
   * Create a new simple tag associated with this block.
   *
   * @param name      The name of the simple tag to create.
   * @param type      The type of the tag.
   *
   * @return The newly created tag.
   */
  SimpleTag createSimpleTag(std::string name, std::string type);

  /**
   * Remove a simple tag from the block.
   *
   * @param id        The id of the tag to remove.
   *
   * @return True if the tag was removed, false otherwise.
   */
  bool removeSimpleTag(std::string id);

  //--------------------------------------------------
  // Methods concerning data tags.
  // TODO implement data tag methods.
  //--------------------------------------------------

  /**
   * Checks if a specific data tag exists in the block.
   *
   * @param id        The id of a data tag.
   *
   * @return True if the data tag exists, false otherwise.
   */
  bool hasDataTag(std::string id) const;

  /**
   * Retrieves a specific data tag from the block.
   *
   * @param id        The id of the data tag.
   *
   * @return The tag with the specified id. If this tag doesn't exist
   *         an exception will be thrown.
   */
  DataTag getDataTag(std::string id) const;

  /**
   * Retrieves a specific data tag by index.
   *
   * @param index     The index of the tag.
   *
   * @return The data tag at the specified index.
   */
  DataTag getDataTag(size_t index) const;

  /**
   * Get all simple data associated with this block.
   *
   * @return All simple tags as a vector.
   */
  std::vector<DataTag> dataTags() const;

  /**
   * Returns the number of data tag associated with
   * this block.
   *
   * @return The number of data tags.
   */
  size_t dataTagCount() const;

  /**
   * Create a new data tag associated with this block.
   *
   * @param name      The name of the data tag to create.
   * @param type      The type of the tag.
   *
   * @return The newly created tag.
   */
  DataTag createDataTag(std::string name, std::string type);

  /**
   * Remove a data tag from the block.
   *
   * @param id        The id of the tag to remove.
   *
   * @return True if the tag was removed, false otherwise.
   */
  void removeDataTag(std::string id);

  //--------------------------------------------------
  // Other methods and functions
  //--------------------------------------------------

  /**
   * Assignment operator
   */
  Block& operator=(const Block &other);

  /**
   * Output operator
   */
  friend std::ostream& operator<<(std::ostream &out, const Block &ent);

  virtual ~Block();

};

}

#endif // HDX_BOCK_H_INCLUDE
<|endoftext|>


<commit_before>/**
 * @file pfasst/config.hpp
 * @since v0.3.0
 */
#ifndef _PFASST__CONFIG_HPP_
#define _PFASST__CONFIG_HPP_

#include <fstream>
#include <iostream>
#include <string>
#include <map>
using namespace std;

#include <boost/program_options.hpp>
namespace po = boost::program_options;

#ifdef WITH_MPI
  #include <mpi.h>
#endif

namespace pfasst
{
  /**
   * @since v0.3.0
   */
  namespace config
  {
    /**
     * Get MPI rank during initialization.
     *
     * When running without MPI (ie, without using mpirun/mpiexec), returns 0.  When running with
     * MPI, returns the MPI rank.
     *
     * If the user is running with MPI and MPI_Init hasn't been called yet, this will return 0.  I
     * hope this is rare.
     */
    int get_rank()
    {
#ifdef WITH_MPI
      int initialized = 0, rank = 0;
      // if we're not running under "mpirun/mpiexec", just assume rank 0.
      MPI_Initialized(&initialized);
      if (initialized) {
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
      }
      return rank;
#else
      return 0;
#endif
    }

    /**
     * Runtime config options provider.
     *
     * This singleton provides easy access to command line parameters at runtime.
     *
     * @note This uses the Singleton Pattern, and hence pfasst::options::get_instance() is
     *    thread-safe with C++11.
     * @since v0.3.0
     * @ingroup Internals
     */
    class options
    {
      public:
        /// line width of help and usage information
        static const size_t LINE_WIDTH = 100;

      private:
        po::options_description all_options;
        map<string, po::options_description> option_groups;
        po::variables_map variables_map;
        vector<string> unrecognized_args;
        bool initialized = false;

        //! @{
        options();
        options(const options&) = delete;
        void operator=(const options&) = delete;
        //! @}

      public:
        //! @{
        /**
         * Accessor to the singleton instance.
         *
         * @returns singleton config::options instance
         */
        static options& get_instance();
        po::variables_map& get_variables_map();
        po::options_description& get_all_options();
        vector<string>& get_unrecognized_args();
        //! @}

        //! @{
        /**
         * Adds a new boolean flag.
         *
         * @param[in] group string identifying the parameter group
         * @param[in] option Name of the command line parameter.
         *   It is possible to specify a long and optional short option name by comma-separation.
         *   Short option names are identified by being only a single character.
         *   They are automatically parsed as '`-[SHORT]`' by `boost::program_options` in contrast
         *   to '`--[LONG]`'.
         * @param[in] help help text to be displayed in the help and usage information
         */
        static void add_option(const string& group, const string& option, const string& help);

        /**
         * Adds a new parameter with an expected value of type @p T.
         *
         * @tparam T type of the specified parameter
         * @param[in] group string identifying the parameter group
         * @param[in] option Name of the command line parameter.
         *   It is possible to specify a long and optional short option name by comma-separation.
         *   Short option names are identified by being only a single character.
         *   They are automatically parsed as '`-[SHORT]`' by `boost::program_options` in contrast
         *   to '`--[LONG]`'.
         * @param[in] help help text to be displayed in the help and usage information
         *
         * @overload
         */
        template<typename T>
        static void add_option(const string& group, const string& option, const string& help);
        //! @}

        /**
         * Initialize program options.
         *
         * This initializes `boost::program_options` with all previously added options and groups.
         */
        void init();
    };

    /**
     * get value of specific type @p T
     *
     * @tparam T type of the retreived value
     * @param[in] name Name of the (long) option as defined with @p option in options::add_option()
     * @returns Value of type @p T of desired option.
     * @throws boost::bad_any_cast if option is not given.
     *
     * @see
     *   [boost::any::bad_any_cast]
     *   (http://www.boost.org/doc/libs/1_57_0/doc/html/boost/bad_any_cast.html)
     */
    template<typename T>
    inline T get_value(const string& name)
    {
      return options::get_instance().get_variables_map()[name].as<T>();
    }

    /**
     * Get value of specific type @p T with default value.
     *
     * @tparam T type of the retreived value
     *
     * @overload
     */
    template<typename T>
    inline T get_value(const string& name, const T& default_val)
    {
      return options::get_instance().get_variables_map().count(name)
              ? options::get_instance().get_variables_map()[name].as<T>() : default_val;
    }

    /**
     * Compile basic help and usage information.
     *
     * Depending on @p if_no_params and presence of given command line parameters the help and
     * usage information is compiled.
     * In case @p if_no_params is `true` and there are no parameters given on the command line or
     * @p if_no_params is `false` no matter whether parameters are given, the help message is
     * generated.
     *
     * @param[in] if_no_params flag governing compilation of help and usage information
     * @returns string containing basic help and usage information; string may be empty
     */
    static string print_help(bool if_no_params = false)
    {
      bool no_params_given = options::get_instance().get_variables_map().empty();

      if (!if_no_params || (if_no_params && no_params_given)) {
        stringstream s;
        s << options::get_instance().get_all_options() << endl;
        s << "Logging options:" << endl
          << "  -v [ --verbose ]       activates maximum verbosity" << endl
          << "  --v=arg                activates verbosity upto verbose level `arg`" << endl
          << "                         (valid range: 0-9)" << endl
          << "  -vmodule=arg           actives verbose logging for specific module" << endl
          << "                         (see [1] for details)" << endl << endl
          << "[1]: https://github.com/easylogging/easyloggingpp#vmodule" << endl;
        return s.str();
      } else {
        return string();
      }
    }

    /**
     * Read and parse command line parameters.
     *
     * @param[in] argc Number of command line arguments as provided by `%main(int, char**)`.
     * @param[in] argv List of command line arguments as provided by `%main(int, char**)`.
     * @param[in] exit_on_help Whether to exit the program after displaying help and usage
     *   information.
     *
     * @note Will call `std::exit` in case the `help` parameter has been provided and
     *   @p exit_on_help is `true`.
     */
    static inline void read_commandline(int argc, char* argv[], bool exit_on_help = true)
    {
      po::parsed_options parsed = po::command_line_parser(argc, argv)
                                    .options(options::get_instance().get_all_options())
                                    .allow_unregistered().run();
      options::get_instance().get_unrecognized_args() = po::collect_unrecognized(parsed.options,
                                                                                po::exclude_positional);
      po::store(parsed, options::get_instance().get_variables_map());
      po::notify(options::get_instance().get_variables_map());

      if (options::get_instance().get_variables_map().count("help")) {
        if (get_rank() == 0) {
          cout << print_help() << endl;
        }

        if (exit_on_help) {
#ifdef WITH_MPI
          MPI_Finalize();
#endif
          exit(0);
        }
      }
    }

    /**
     * Read config parameters from file.
     *
     * @param[in] file_name name of the INI-like file containing config parameters;
     *   path/name may be relative
     * @throws invalid_argument if the given file could not be opened
     *
     * @see
     *   [Boost Program Options Documentation on supported INI-like file format]
     *   (http://www.boost.org/doc/libs/1_57_0/doc/html/program_options/overview.html#idp343292240)
     */
    static inline void read_config_file(const string& file_name)
    {
      ifstream ifs(file_name.c_str(), ios_base::in);
      if (!ifs) {
        throw invalid_argument("Config file '" + file_name + "' not found.");
      } else {
        po::store(po::parse_config_file(ifs, options::get_instance().get_all_options()),
                  options::get_instance().get_variables_map());
        po::notify(options::get_instance().get_variables_map());
      }
    }

    /**
     * Initialize options detection and parsing.
     *
     * Prepopulates following groups and parameters:
     *
     * Group      | Parameter     | Type
     * -----------|---------------|---------
     * Global     | `h`, `help`   | `bool`
     * Duration   | `dt`          | `double`
     * Duration   | `tend`        | `double`
     * Duration   | `num_iters`   | `size_t`
     * Tolerances | `abs_res_tol` | `double`
     * Tolerances | `rel_res_tol` | `double`
     */
    static inline void init()
    {
      options::add_option("Global", "help,h", "display this help message");
      options::add_option("Global", "quiet,q", "don't log to stdout");

      options::add_option<double>("Duration", "dt", "time step size");
      options::add_option<double>("Duration", "tend", "final time of simulation");
      options::add_option<size_t>("Duration", "num_steps", "number time steps");
      options::add_option<size_t>("Duration", "num_iter", "number of iterations");

      options::add_option<size_t>("Quadrature", "num_nodes", "number of quadrature nodes");

      options::add_option<double>("Tolerances", "abs_res_tol", "absolute residual tolerance");
      options::add_option<double>("Tolerances", "rel_res_tol", "relative residual tolerance");

      options::get_instance().init();
    }
  }  // ::pfasst::config
}  // ::pfasst

#include "pfasst/config_impl.hpp"

#endif  // _PFASST__CONFIG_HPP_
<commit_msg>config: finally enable config-file parsing<commit_after>/**
 * @file pfasst/config.hpp
 * @since v0.3.0
 */
#ifndef _PFASST__CONFIG_HPP_
#define _PFASST__CONFIG_HPP_

#include <fstream>
#include <iostream>
#include <string>
#include <map>
using namespace std;

#include <boost/program_options.hpp>
namespace po = boost::program_options;

#ifdef WITH_MPI
  #include <mpi.h>
#endif

namespace pfasst
{
  /**
   * @since v0.3.0
   */
  namespace config
  {
    /**
     * Get MPI rank during initialization.
     *
     * When running without MPI (ie, without using mpirun/mpiexec), returns 0.  When running with
     * MPI, returns the MPI rank.
     *
     * If the user is running with MPI and MPI_Init hasn't been called yet, this will return 0.  I
     * hope this is rare.
     */
    int get_rank()
    {
#ifdef WITH_MPI
      int initialized = 0, rank = 0;
      // if we're not running under "mpirun/mpiexec", just assume rank 0.
      MPI_Initialized(&initialized);
      if (initialized) {
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
      }
      return rank;
#else
      return 0;
#endif
    }

    /**
     * Runtime config options provider.
     *
     * This singleton provides easy access to command line parameters at runtime.
     *
     * @note This uses the Singleton Pattern, and hence pfasst::options::get_instance() is
     *    thread-safe with C++11.
     * @since v0.3.0
     * @ingroup Internals
     */
    class options
    {
      public:
        /// line width of help and usage information
        static const size_t LINE_WIDTH = 100;

      private:
        po::options_description all_options;
        map<string, po::options_description> option_groups;
        po::variables_map variables_map;
        vector<string> unrecognized_args;
        bool initialized = false;

        //! @{
        options();
        options(const options&) = delete;
        void operator=(const options&) = delete;
        //! @}

      public:
        //! @{
        /**
         * Accessor to the singleton instance.
         *
         * @returns singleton config::options instance
         */
        static options& get_instance();
        po::variables_map& get_variables_map();
        po::options_description& get_all_options();
        vector<string>& get_unrecognized_args();
        //! @}

        //! @{
        /**
         * Adds a new boolean flag.
         *
         * @param[in] group string identifying the parameter group
         * @param[in] option Name of the command line parameter.
         *   It is possible to specify a long and optional short option name by comma-separation.
         *   Short option names are identified by being only a single character.
         *   They are automatically parsed as '`-[SHORT]`' by `boost::program_options` in contrast
         *   to '`--[LONG]`'.
         * @param[in] help help text to be displayed in the help and usage information
         */
        static void add_option(const string& group, const string& option, const string& help);

        /**
         * Adds a new parameter with an expected value of type @p T.
         *
         * @tparam T type of the specified parameter
         * @param[in] group string identifying the parameter group
         * @param[in] option Name of the command line parameter.
         *   It is possible to specify a long and optional short option name by comma-separation.
         *   Short option names are identified by being only a single character.
         *   They are automatically parsed as '`-[SHORT]`' by `boost::program_options` in contrast
         *   to '`--[LONG]`'.
         * @param[in] help help text to be displayed in the help and usage information
         *
         * @overload
         */
        template<typename T>
        static void add_option(const string& group, const string& option, const string& help);
        //! @}

        /**
         * Initialize program options.
         *
         * This initializes `boost::program_options` with all previously added options and groups.
         */
        void init();
    };

    /**
     * get value of specific type @p T
     *
     * @tparam T type of the retreived value
     * @param[in] name Name of the (long) option as defined with @p option in options::add_option()
     * @returns Value of type @p T of desired option.
     * @throws boost::bad_any_cast if option is not given.
     *
     * @see
     *   [boost::any::bad_any_cast]
     *   (http://www.boost.org/doc/libs/1_57_0/doc/html/boost/bad_any_cast.html)
     */
    template<typename T>
    inline T get_value(const string& name)
    {
      return options::get_instance().get_variables_map()[name].as<T>();
    }

    /**
     * Get value of specific type @p T with default value.
     *
     * @tparam T type of the retreived value
     *
     * @overload
     */
    template<typename T>
    inline T get_value(const string& name, const T& default_val)
    {
      return options::get_instance().get_variables_map().count(name)
              ? options::get_instance().get_variables_map()[name].as<T>() : default_val;
    }

    /**
     * Compile basic help and usage information.
     *
     * Depending on @p if_no_params and presence of given command line parameters the help and
     * usage information is compiled.
     * In case @p if_no_params is `true` and there are no parameters given on the command line or
     * @p if_no_params is `false` no matter whether parameters are given, the help message is
     * generated.
     *
     * @param[in] if_no_params flag governing compilation of help and usage information
     * @returns string containing basic help and usage information; string may be empty
     */
    static string print_help(bool if_no_params = false)
    {
      bool no_params_given = options::get_instance().get_variables_map().empty();

      if (!if_no_params || (if_no_params && no_params_given)) {
        stringstream s;
        s << options::get_instance().get_all_options() << endl;
        s << "Logging options:" << endl
          << "  -v [ --verbose ]       activates maximum verbosity" << endl
          << "  --v=arg                activates verbosity upto verbose level `arg`" << endl
          << "                         (valid range: 0-9)" << endl
          << "  -vmodule=arg           actives verbose logging for specific module" << endl
          << "                         (see [1] for details)" << endl << endl
          << "[1]: https://github.com/easylogging/easyloggingpp#vmodule" << endl;
        return s.str();
      } else {
        return string();
      }
    }

    /**
     * Read config parameters from file.
     *
     * A potential INI file might look like the following:
     *
     * @code
     * # Global
     * quiet=yes
     *
     * # Duration
     * dt=0.015625
     * num_steps=2
     * num_iter=10
     *
     * # Tolerances
     * rel_res_tol=1e-10
     *
     * # PFASST
     * num_blocks=1
     * @endcode
     *
     * @param[in] file_name name of the INI-like file containing config parameters;
     *   path/name may be relative
     * @throws invalid_argument if the given file could not be opened
     *
     * @see
     *   [Boost Program Options Documentation on supported INI-like file format]
     *   (http://www.boost.org/doc/libs/1_57_0/doc/html/program_options/overview.html#idp343292240)
     */
    static inline void read_config_file(const string& file_name)
    {
      ifstream ifs(file_name.c_str(), ios_base::in);
      if (!ifs) {
        throw invalid_argument("Config file '" + file_name + "' not found.");
      } else {
        po::store(po::parse_config_file(ifs, options::get_instance().get_all_options()),
                  options::get_instance().get_variables_map());
        po::notify(options::get_instance().get_variables_map());
      }
    }

    /**
     * Read and parse command line parameters.
     *
     * @param[in] argc Number of command line arguments as provided by `%main(int, char**)`.
     * @param[in] argv List of command line arguments as provided by `%main(int, char**)`.
     * @param[in] exit_on_help Whether to exit the program after displaying help and usage
     *   information.
     *
     * @note Will call `std::exit` in case the `help` parameter has been provided and
     *   @p exit_on_help is `true`.
     */
    static inline void read_commandline(int argc, char* argv[], bool exit_on_help = true)
    {
      po::parsed_options parsed = po::command_line_parser(argc, argv)
                                    .options(options::get_instance().get_all_options())
                                    .allow_unregistered().run();
      options::get_instance().get_unrecognized_args() = po::collect_unrecognized(parsed.options,
                                                                                po::exclude_positional);
      po::store(parsed, options::get_instance().get_variables_map());
      po::notify(options::get_instance().get_variables_map());

      if (options::get_instance().get_variables_map().count("input")) {
        string input_file = config::get_value<string>("input");
        read_config_file(input_file);
      }

      if (options::get_instance().get_variables_map().count("help")) {
        if (get_rank() == 0) {
          cout << print_help() << endl;
        }

        if (exit_on_help) {
#ifdef WITH_MPI
          MPI_Finalize();
#endif
          exit(0);
        }
      }
    }

    /**
     * Initialize options detection and parsing.
     *
     * Prepopulates following groups and parameters:
     *
     * Group      | Parameter     | Type
     * -----------|---------------|---------
     * Global     | `h`, `help`   | `bool`
     * Global     | `q`, `quiet`  | `bool`
     * Global     | `input`       | `string`
     * Duration   | `dt`          | `double`
     * Duration   | `tend`        | `double`
     * Duration   | `num_iters`   | `size_t`
     * Tolerances | `abs_res_tol` | `double`
     * Tolerances | `rel_res_tol` | `double`
     */
    static inline void init()
    {
      options::add_option("Global", "help,h", "display this help message");
      options::add_option("Global", "quiet,q", "don't log to stdout");
      options::add_option<string>("Global", "input", "INI file with configuration options");

      options::add_option<double>("Duration", "dt", "time step size");
      options::add_option<double>("Duration", "tend", "final time of simulation");
      options::add_option<size_t>("Duration", "num_steps", "number time steps");
      options::add_option<size_t>("Duration", "num_iter", "number of iterations");

      options::add_option<size_t>("Quadrature", "num_nodes", "number of quadrature nodes");

      options::add_option<double>("Tolerances", "abs_res_tol", "absolute residual tolerance");
      options::add_option<double>("Tolerances", "rel_res_tol", "relative residual tolerance");

      options::get_instance().init();
    }
  }  // ::pfasst::config
}  // ::pfasst

#include "pfasst/config_impl.hpp"

#endif  // _PFASST__CONFIG_HPP_
<|endoftext|>


<commit_before>e5b3b8cf-ad5a-11e7-bdd0-ac87a332f658<commit_msg>Did ANOTHER thing<commit_after>e6710a66-ad5a-11e7-9d49-ac87a332f658<|endoftext|>


<commit_before>#include "inform.hpp"
#include "windows.hpp"
#include <boost/exception/diagnostic_information.hpp>
#include <iostream>
#include <set>

void select_phenotype_of_interest(categories_type const& categories, std::string& phenotype)
{
	std::set<std::string> phenotypes;
	for(auto const& category: categories)
	{
		for(auto const& sample: category.second)
		{
			for(auto const& phenotype: sample.second.phenotypes)
			{
				phenotypes.insert(phenotype.first);
			}
		}
	}

	while(true)
	{
		std::cout << "Please select your phenotype of interest: " << std::endl;
		for(auto const& phenotype: phenotypes)
		{
			std::cout << phenotype << std::endl;
		}
		std::cout << "> ";
		std::getline(std::cin, phenotype);
		if(phenotypes.count(phenotype))
		{
			std::cout << std::endl;
			return;
		}
	}
}

void try_directory(boost::filesystem::path const& directory)
{
	if(boost::filesystem::is_directory(directory))
	{
		categories_type categories;
		load_inform_samples(directory, categories);
		if(categories.empty())
		{
			boost::filesystem::directory_iterator end;
			for(boost::filesystem::directory_iterator iter(directory); iter != end; ++ iter)
			{
				try_directory(iter->path());
			}
		}
		else
		{
			std::string interest;
			select_phenotype_of_interest(categories, interest);
			for(auto const& category: categories)
			{
				boost::filesystem::create_directories(directory / category.first);
				save_inform_sample_nearest(directory, category, interest);
				save_inform_sample_nearest_composites(directory, category, interest);
				save_inform_sample_neighbor_composites(directory, category, interest);
				save_inform_phenotype_nearest(directory, category, interest);
			}
			save_inform_phenotype_summary(directory, categories, interest);
		}
	}
	else
	{
		std::cout << "Not a directory: " << directory << std::endl;
	}
}

int main(int argc, char* argv[])
{
	try
	{
		if(argc > 1)
		{
			for(int i(1); i < argc; ++ i)
			{
				try_directory(argv[i]);
			}
		}
		else
		{
			std::cout << "This program processes a collection of inForm samples located in a directory. Example:" << std::endl;
			std::cout << "samples" << std::endl << "\tset 1" << std::endl << "\tset 2" << std::endl << "\tset 3" << std::endl << "\t..." << std::endl << std::endl;
			std::cout << "You can pass the directories you wish to process on the command line. If you provide a directory" << std::endl;
			std::cout << "containing sub-directories (i.e. \"samples\" above), the sub-directories will be processed as well." << std::endl << std::endl;
			std::cout << "For now you can manually select a directory to process..." << std::endl;
			try_directory(windows::select_directory());
		}
		return 0;
	}

	catch(...)
	{
		std::cout << boost::current_exception_diagnostic_information() << std::endl;
		return 1;
	}
}<commit_msg>Re-use phenotype of interest across samples<commit_after>#include "inform.hpp"
#include "windows.hpp"
#include <boost/exception/diagnostic_information.hpp>
#include <iostream>
#include <set>

void select_phenotype_of_interest(categories_type const& categories, std::string& interest)
{
	std::set<std::string> phenotypes;
	for(auto const& category: categories)
	{
		for(auto const& sample: category.second)
		{
			for(auto const& phenotype: sample.second.phenotypes)
			{
				phenotypes.insert(phenotype.first);
			}
		}
	}

	while(phenotypes.count(interest) == 0)
	{
		std::cout << "Please select your phenotype of interest: " << std::endl;
		for(auto const& phenotype: phenotypes)
		{
			std::cout << phenotype << std::endl;
		}
		std::cout << "> ";
		std::getline(std::cin, interest);
	}

	std::cout << std::endl;
	return;
}

void try_directory(boost::filesystem::path const& directory, std::string& interest)
{
	if(boost::filesystem::is_directory(directory))
	{
		categories_type categories;
		load_inform_samples(directory, categories);
		if(categories.empty())
		{
			boost::filesystem::directory_iterator end;
			for(boost::filesystem::directory_iterator iter(directory); iter != end; ++ iter)
			{
				try_directory(iter->path(), interest);
			}
		}
		else
		{
			select_phenotype_of_interest(categories, interest);
			for(auto const& category: categories)
			{
				boost::filesystem::create_directories(directory / category.first);
				save_inform_sample_nearest(directory, category, interest);
				save_inform_sample_nearest_composites(directory, category, interest);
				save_inform_sample_neighbor_composites(directory, category, interest);
				save_inform_phenotype_nearest(directory, category, interest);
			}
			save_inform_phenotype_summary(directory, categories, interest);
		}
	}
	else
	{
		std::cout << "Not a directory: " << directory << std::endl;
	}
}

int main(int argc, char* argv[])
{
	try
	{
		std::string interest;	// Phenotype of interest
		if(argc > 1)
		{
			for(int i(1); i < argc; ++ i)
			{
				try_directory(argv[i], interest);
			}
		}
		else
		{
			std::cout << "This program processes a collection of inForm samples located in a directory. Example:" << std::endl;
			std::cout << "samples" << std::endl << "\tset 1" << std::endl << "\tset 2" << std::endl << "\tset 3" << std::endl << "\t..." << std::endl << std::endl;
			std::cout << "You can pass the directories you wish to process on the command line. If you provide a directory" << std::endl;
			std::cout << "containing sub-directories (i.e. \"samples\" above), the sub-directories will be processed as well." << std::endl << std::endl;
			std::cout << "For now you can manually select a directory to process..." << std::endl;
			try_directory(windows::select_directory(), interest);
		}
		return 0;
	}

	catch(...)
	{
		std::cout << boost::current_exception_diagnostic_information() << std::endl;
		return 1;
	}
}<|endoftext|>


<commit_before>#include "playlist.hpp"
#include "chromecast.hpp"
#include "webserver.hpp"
#include "cast_channel.pb.h"
#include <syslog.h>
#include <getopt.h>
#include <fstream>

void usage();
extern char* __progname;

const char* ffmpegpath()
{
	if (access("./ffmpeg", F_OK) == 0)
		return "./ffmpeg";
	return "ffmpeg";
}

int main(int argc, char* argv[])
{
	GOOGLE_PROTOBUF_VERIFY_VERSION;
	OpenSSL_add_ssl_algorithms();
 	SSL_load_error_strings();
	signal(SIGPIPE, SIG_IGN);
	openlog(NULL, LOG_PID | LOG_PERROR, LOG_DAEMON);

	std::string ip;
	unsigned short port = 8080;
	bool subtitles = false, play = false;
	Playlist playlist;

	static struct option longopts[] = {
		{ "help", no_argument, NULL, 'h' },
		{ "chromecast", required_argument, NULL, 'c' },
		{ "port", required_argument, NULL, 'p' },
		{ "playlist", required_argument, NULL, 'P' },
		{ "play", no_argument, NULL, 'y' },
		{ "subtitles", no_argument, NULL, 'S' },
		{ "shuffle", no_argument, NULL, 's' },
		{ "repeat", no_argument, NULL, 'r' },
		{ "repeat-all", no_argument, NULL, 'R' },
		{ "track", required_argument, NULL, 't' },
		{ NULL, 0, NULL, 0 }
	};

	int ch;
	while ((ch = getopt_long(argc, argv, "hc:p:P:sSrRyt:", longopts, NULL)) != -1) {
		switch (ch) {
			case 'c':
				ip = optarg;
				break;
			case 'p':
				port = strtoul(optarg, NULL, 10);
				break;
			case 'P':
				{
					std::ifstream input(optarg);
					for (std::string line; getline(input, line);)
						playlist.insert(line);
				}
				break;
			case 's':
				playlist.setShuffle(true);
				break;
			case 'S':
				subtitles = true;
				break;
			case 'r':
				playlist.setRepeat(true);
				break;
			case 'R':
				playlist.setRepeatAll(true);
				break;
			case 'y':
				play = true;
				break;
			case 't':
				playlist.insert(std::string(optarg));
				break;
			default:
			case 'h':
				usage();
		}
	}

	if (ip.empty())
		usage();

	ChromeCast chromecast(ip);
	chromecast.init();
	chromecast.setSubtitleSettings(subtitles);
	chromecast.setMediaStatusCallback([&chromecast, &playlist, port](const std::string& playerState,
			const std::string& idleReason, const std::string& uuid) -> void {
		syslog(LOG_DEBUG, "mediastatus: %s %s %s", playerState.c_str(), idleReason.c_str(), uuid.c_str());
		if (playerState == "IDLE") {
			if (idleReason == "FINISHED") {
				try {
					std::lock_guard<std::mutex> lock(playlist.getMutex());
					PlaylistItem track = playlist.getNextTrack(uuid);
					std::thread foo([&chromecast, port, track]() {
						chromecast.load("http://" + chromecast.getSocketName() + ":" + std::to_string(port) + "/stream/" + track.getUUID(),
							track.getName(), track.getUUID());
					});
					foo.detach();
				} catch (...) {
					// ...
				}
			}
		}
	});
	Webserver http(port, chromecast, playlist);
	if (play) {
		try {
			const PlaylistItem& track = playlist.getNextTrack("");
			chromecast.load(
				"http://" + chromecast.getSocketName() + ":" + std::to_string(port) + "/stream/" + track.getUUID(),
				track.getName(), track.getUUID());
		} catch (const std::runtime_error& e) {
			syslog(LOG_DEBUG, "--play failed: %s", e.what());
		}
	}
	while (1) sleep(3600);
	return 0;
}

void usage()
{
	printf("%s --chromecast <ip> [ --port <number> ] [ --playlist <path> ]\n"
			"\t[ --shuffle ] [ --repeat ] [ --repeat-all ]\n"
			"\t[ --subtitles ] [ --play ]\n", __progname);
	exit(1);
}
<commit_msg>document track<commit_after>#include "playlist.hpp"
#include "chromecast.hpp"
#include "webserver.hpp"
#include "cast_channel.pb.h"
#include <syslog.h>
#include <getopt.h>
#include <fstream>

void usage();
extern char* __progname;

const char* ffmpegpath()
{
	if (access("./ffmpeg", F_OK) == 0)
		return "./ffmpeg";
	return "ffmpeg";
}

int main(int argc, char* argv[])
{
	GOOGLE_PROTOBUF_VERIFY_VERSION;
	OpenSSL_add_ssl_algorithms();
 	SSL_load_error_strings();
	signal(SIGPIPE, SIG_IGN);
	openlog(NULL, LOG_PID | LOG_PERROR, LOG_DAEMON);

	std::string ip;
	unsigned short port = 8080;
	bool subtitles = false, play = false;
	Playlist playlist;

	static struct option longopts[] = {
		{ "help", no_argument, NULL, 'h' },
		{ "chromecast", required_argument, NULL, 'c' },
		{ "port", required_argument, NULL, 'p' },
		{ "playlist", required_argument, NULL, 'P' },
		{ "play", no_argument, NULL, 'y' },
		{ "subtitles", no_argument, NULL, 'S' },
		{ "shuffle", no_argument, NULL, 's' },
		{ "repeat", no_argument, NULL, 'r' },
		{ "repeat-all", no_argument, NULL, 'R' },
		{ "track", required_argument, NULL, 't' },
		{ NULL, 0, NULL, 0 }
	};

	int ch;
	while ((ch = getopt_long(argc, argv, "hc:p:P:sSrRyt:", longopts, NULL)) != -1) {
		switch (ch) {
			case 'c':
				ip = optarg;
				break;
			case 'p':
				port = strtoul(optarg, NULL, 10);
				break;
			case 'P':
				{
					std::ifstream input(optarg);
					for (std::string line; getline(input, line);)
						playlist.insert(line);
				}
				break;
			case 's':
				playlist.setShuffle(true);
				break;
			case 'S':
				subtitles = true;
				break;
			case 'r':
				playlist.setRepeat(true);
				break;
			case 'R':
				playlist.setRepeatAll(true);
				break;
			case 'y':
				play = true;
				break;
			case 't':
				playlist.insert(std::string(optarg));
				break;
			default:
			case 'h':
				usage();
		}
	}

	if (ip.empty())
		usage();

	ChromeCast chromecast(ip);
	chromecast.init();
	chromecast.setSubtitleSettings(subtitles);
	chromecast.setMediaStatusCallback([&chromecast, &playlist, port](const std::string& playerState,
			const std::string& idleReason, const std::string& uuid) -> void {
		syslog(LOG_DEBUG, "mediastatus: %s %s %s", playerState.c_str(), idleReason.c_str(), uuid.c_str());
		if (playerState == "IDLE") {
			if (idleReason == "FINISHED") {
				try {
					std::lock_guard<std::mutex> lock(playlist.getMutex());
					PlaylistItem track = playlist.getNextTrack(uuid);
					std::thread foo([&chromecast, port, track]() {
						chromecast.load("http://" + chromecast.getSocketName() + ":" + std::to_string(port) + "/stream/" + track.getUUID(),
							track.getName(), track.getUUID());
					});
					foo.detach();
				} catch (...) {
					// ...
				}
			}
		}
	});
	Webserver http(port, chromecast, playlist);
	if (play) {
		try {
			const PlaylistItem& track = playlist.getNextTrack("");
			chromecast.load(
				"http://" + chromecast.getSocketName() + ":" + std::to_string(port) + "/stream/" + track.getUUID(),
				track.getName(), track.getUUID());
		} catch (const std::runtime_error& e) {
			syslog(LOG_DEBUG, "--play failed: %s", e.what());
		}
	}
	while (1) sleep(3600);
	return 0;
}

void usage()
{
	printf("%s --chromecast <ip> [ --port <number> ] [ --playlist <path> ]\n"
			"\t[ --shuffle ] [ --repeat ] [ --repeat-all ]\n"
			"\t[ --subtitles ] [ --play ] [ --track <file> ]\n", __progname);
	exit(1);
}
<|endoftext|>


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

  Library:   CTK

  Copyright (c) Kitware Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://commontk.org/LICENSE

  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.

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

// Qt includes
#include <QDebug>
#include <QDir>
#include <QTextStream>
#include <QTime>

// CTK includes
#include "ctkUtils.h"

// STD includes
#include <cstdlib>
#include <iostream>

namespace
{
//-----------------------------------------------------------------------------
bool createFile(int line, const QDir& dir, const QString& relativePath, const QString& fileName)
{
  QDir newDir(dir);
  newDir.mkpath(relativePath);
  newDir.cd(relativePath);
  QString filePath = QFileInfo(newDir, fileName).filePath();
  QFile file(filePath);
  file.open(QIODevice::Text | QIODevice::WriteOnly);
  QTextStream out(&file);
  out << "Generated by ctkUtilsCopyDirRecursivelyTest1" << endl;
  file.close();

  if (!QFile::exists(filePath))
    {
    std::cerr << "Line " << line << " - Failed to create file" << qPrintable(filePath) << std::endl;
    return false;
    }

  return true;
}

} // end of anonymous namespace

//-----------------------------------------------------------------------------
int ctkUtilsCopyDirRecursivelyTest1(int argc, char * argv [] )
{
  Q_UNUSED(argc);
  Q_UNUSED(argv);

  // --------------------------------------------------------------------------
  // Test copyDirRecursively(const QString &srcPath, const QString &dstPath);
  // --------------------------------------------------------------------------

  QDir tmp = QDir::temp();
  QString temporaryDirName =
      QString("ctkUtilsCopyDirRecursivelyTest1.%1").arg(QTime::currentTime().toString("hhmmsszzz"));

  {
  // Attempt to copy nonexistent relative directory
  QString nonexistentRelativeDirPath = temporaryDirName;
  if (ctk::copyDirRecursively(nonexistentRelativeDirPath, tmp.absolutePath()))
    {
    std::cerr << "Line " << __LINE__ << " - Problem with ctk::copyDirRecursively() !"
              << " - It should fail to copy nonexistent directory: " <<
              qPrintable(nonexistentRelativeDirPath)<< std::endl;
    return EXIT_FAILURE;
    }
  }

  {
  // Attempt to copy nonexistent absolute directory
  QString nonexistentAbsoluteDirPath = tmp.absolutePath() + "/" + temporaryDirName;
  if (ctk::copyDirRecursively(nonexistentAbsoluteDirPath, tmp.absolutePath()))
    {
    std::cerr << "Line " << __LINE__ << " - Problem with ctk::copyDirRecursively() !"
              << " - It should fail to delete nonexistent directory: " <<
              qPrintable(nonexistentAbsoluteDirPath)<< std::endl;
    return EXIT_FAILURE;
    }
  }

  // Create a directory structure
  tmp.mkdir(temporaryDirName);
  tmp.cd(temporaryDirName);
  if (!createFile(__LINE__, tmp, "foo", "a.txt"))
    {
    return EXIT_FAILURE;
    }
  if (!createFile(__LINE__, tmp, "foo/bar", "b.txt"))
    {
    return EXIT_FAILURE;
    }
  if (!createFile(__LINE__, tmp, "foo/zoo", "c.txt"))
    {
    return EXIT_FAILURE;
    }

  {
  QString srcPath(tmp.path() + "/foo");
  QString destPath(tmp.path() + "/dest");
  if (!ctk::copyDirRecursively(srcPath, destPath))
    {
    std::cerr << "Line " << __LINE__ << " - Problem with ctk::copyDirRecursively()"
              << " - Failed to copy directory: " << qPrintable(srcPath)
              << "into" << qPrintable(destPath) << std::endl;
    return EXIT_FAILURE;
    }
  }

  {
  // Atempt to copy a directory into itself
  QString srcPath(tmp.path());
  QString destPath(tmp.path() + "/dest");
  if (ctk::copyDirRecursively(srcPath, destPath))
    {
    std::cerr << "Line " << __LINE__ << " - Problem with ctk::copyDirRecursively()"
              << " - Copy of directory: " << qPrintable(srcPath)
              << "into itself " << qPrintable(destPath)
              << " should fail !" << std::endl;
    return EXIT_FAILURE;
    }
  }

  return EXIT_SUCCESS;
}
<commit_msg>ENH: Improve ctkUtilsCopyDirRecursivelyTest1 to check file existence<commit_after>/*=========================================================================

  Library:   CTK

  Copyright (c) Kitware Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://commontk.org/LICENSE

  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.

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

// Qt includes
#include <QDebug>
#include <QDir>
#include <QTextStream>
#include <QTime>

// CTK includes
#include "ctkCoreTestingMacros.h"
#include "ctkUtils.h"

// STD includes
#include <cstdlib>
#include <iostream>

namespace
{
//-----------------------------------------------------------------------------
bool createFile(int line, const QDir& dir, const QString& relativePath, const QString& fileName)
{
  QDir newDir(dir);
  newDir.mkpath(relativePath);
  newDir.cd(relativePath);
  QString filePath = QFileInfo(newDir, fileName).filePath();
  QFile file(filePath);
  file.open(QIODevice::Text | QIODevice::WriteOnly);
  QTextStream out(&file);
  out << "Generated by ctkUtilsCopyDirRecursivelyTest1" << endl;
  file.close();

  if (!QFile::exists(filePath))
    {
    std::cerr << "Line " << line << " - Failed to create file" << qPrintable(filePath) << std::endl;
    return false;
    }

  return true;
}

} // end of anonymous namespace

//-----------------------------------------------------------------------------
int ctkUtilsCopyDirRecursivelyTest1(int argc, char * argv [] )
{
  Q_UNUSED(argc);
  Q_UNUSED(argv);

  // --------------------------------------------------------------------------
  // Test copyDirRecursively(const QString &srcPath, const QString &dstPath);
  // --------------------------------------------------------------------------

  QDir tmp = QDir::temp();
  QString temporaryDirName =
      QString("ctkUtilsCopyDirRecursivelyTest1.%1").arg(QTime::currentTime().toString("hhmmsszzz"));

  {
  // Attempt to copy nonexistent relative directory
  QString nonexistentRelativeDirPath = temporaryDirName;
  if (ctk::copyDirRecursively(nonexistentRelativeDirPath, tmp.absolutePath()))
    {
    std::cerr << "Line " << __LINE__ << " - Problem with ctk::copyDirRecursively() !"
              << " - It should fail to copy nonexistent directory: " <<
              qPrintable(nonexistentRelativeDirPath)<< std::endl;
    return EXIT_FAILURE;
    }
  }

  {
  // Attempt to copy nonexistent absolute directory
  QString nonexistentAbsoluteDirPath = tmp.absolutePath() + "/" + temporaryDirName;
  if (ctk::copyDirRecursively(nonexistentAbsoluteDirPath, tmp.absolutePath()))
    {
    std::cerr << "Line " << __LINE__ << " - Problem with ctk::copyDirRecursively() !"
              << " - It should fail to delete nonexistent directory: " <<
              qPrintable(nonexistentAbsoluteDirPath)<< std::endl;
    return EXIT_FAILURE;
    }
  }

  // Create a directory structure
  tmp.mkdir(temporaryDirName);
  tmp.cd(temporaryDirName);
  if (!createFile(__LINE__, tmp, "foo", "a.txt"))
    {
    return EXIT_FAILURE;
    }
  if (!createFile(__LINE__, tmp, "foo/bar", "b.txt"))
    {
    return EXIT_FAILURE;
    }
  if (!createFile(__LINE__, tmp, "foo/zoo", "c.txt"))
    {
    return EXIT_FAILURE;
    }

  {
  QString srcPath(tmp.path() + "/foo");
  QString destPath(tmp.path() + "/dest");
  if (!ctk::copyDirRecursively(srcPath, destPath))
    {
    std::cerr << "Line " << __LINE__ << " - Problem with ctk::copyDirRecursively()"
              << " - Failed to copy directory: " << qPrintable(srcPath)
              << "into" << qPrintable(destPath) << std::endl;
    return EXIT_FAILURE;
    }

  // Check content of destination directory
  CHECK_BOOL(QDir(destPath).exists("a.txt"), true);
  CHECK_BOOL(QDir(destPath).exists("bar/b.txt"), true);
  CHECK_BOOL(QDir(destPath).exists("zoo/c.txt"), true);
  }

  {
  // Atempt to copy a directory into itself
  QString srcPath(tmp.path());
  QString destPath(tmp.path() + "/dest");
  if (ctk::copyDirRecursively(srcPath, destPath))
    {
    std::cerr << "Line " << __LINE__ << " - Problem with ctk::copyDirRecursively()"
              << " - Copy of directory: " << qPrintable(srcPath)
              << "into itself " << qPrintable(destPath)
              << " should fail !" << std::endl;
    return EXIT_FAILURE;
    }
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>c9685c54-4b02-11e5-8886-28cfe9171a43<commit_msg>I'm done<commit_after>c974cfca-4b02-11e5-a17c-28cfe9171a43<|endoftext|>