<commit_before>/*
 * Copyright © 2008, 2009 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <getopt.h>

/** @file main.cpp
 *
 * This file is the main() routine and scaffolding for producing
 * builtin_compiler (which doesn't include builtins itself and is used
 * to generate the profile information for builtin_function.cpp), and
 * for glsl_compiler (which does include builtins and can be used to
 * offline compile GLSL code and examine the resulting GLSL IR.
 */

#include "ast.h"
#include "glsl_parser_extras.h"
#include "ir_optimization.h"
#include "program.h"
#include "loop_analysis.h"
#include "standalone_scaffolding.h"

static void
initialize_context(struct gl_context *ctx, gl_api api)
{
   initialize_context_to_defaults(ctx, api);

   /* The standalone compiler needs to claim support for almost
    * everything in order to compile the built-in functions.
    */
   ctx->Const.GLSLVersion = 330;
   ctx->Extensions.ARB_ES3_compatibility = true;

   ctx->Const.MaxClipPlanes = 8;
   ctx->Const.MaxDrawBuffers = 2;

   /* More than the 1.10 minimum to appease parser tests taken from
    * apps that (hopefully) already checked the number of coords.
    */
   ctx->Const.MaxTextureCoordUnits = 4;

   ctx->Driver.NewShader = _mesa_new_shader;
}

/* Returned string will have 'ctx' as its ralloc owner. */
static char *
load_text_file(void *ctx, const char *file_name)
{
	char *text = NULL;
	size_t size;
	size_t total_read = 0;
	FILE *fp = fopen(file_name, "rb");

	if (!fp) {
		return NULL;
	}

	fseek(fp, 0L, SEEK_END);
	size = ftell(fp);
	fseek(fp, 0L, SEEK_SET);

	text = (char *) ralloc_size(ctx, size + 1);
	if (text != NULL) {
		do {
			size_t bytes = fread(text + total_read,
					     1, size - total_read, fp);
			if (bytes < size - total_read) {
				free(text);
				text = NULL;
				break;
			}

			if (bytes == 0) {
				break;
			}

			total_read += bytes;
		} while (total_read < size);

		text[total_read] = '\0';
	}

	fclose(fp);

	return text;
}

int glsl_es = 0;
int dump_ast = 0;
int dump_hir = 0;
int dump_lir = 0;
int do_link = 0;

const struct option compiler_opts[] = {
   { "glsl-es",  no_argument, &glsl_es,  1 },
   { "dump-ast", no_argument, &dump_ast, 1 },
   { "dump-hir", no_argument, &dump_hir, 1 },
   { "dump-lir", no_argument, &dump_lir, 1 },
   { "link",     no_argument, &do_link,  1 },
   { NULL, 0, NULL, 0 }
};

/**
 * \brief Print proper usage and exit with failure.
 */
void
usage_fail(const char *name)
{

   const char *header =
      "usage: %s [options] <file.vert | file.geom | file.frag>\n"
      "\n"
      "Possible options are:\n";
   printf(header, name, name);
   for (const struct option *o = compiler_opts; o->name != 0; ++o) {
      printf("    --%s\n", o->name);
   }
   exit(EXIT_FAILURE);
}

void
compile_shader(struct gl_context *ctx, struct gl_shader *shader)
{
   struct _mesa_glsl_parse_state *state =
      new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);

   _mesa_glsl_compile_shader(ctx, shader, dump_ast, dump_hir);

   /* Print out the resulting IR */
   if (!state->error && dump_lir) {
      _mesa_print_ir(shader->ir, state);
   }

   return;
}

int
main(int argc, char **argv)
{
   int status = EXIT_SUCCESS;
   struct gl_context local_ctx;
   struct gl_context *ctx = &local_ctx;

   int c;
   int idx = 0;
   while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1)
      /* empty */ ;

   if (argc <= optind)
      usage_fail(argv[0]);

   initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL_COMPAT);

   struct gl_shader_program *whole_program;

   whole_program = rzalloc (NULL, struct gl_shader_program);
   assert(whole_program != NULL);
   whole_program->InfoLog = ralloc_strdup(whole_program, "");

   for (/* empty */; argc > optind; optind++) {
      whole_program->Shaders =
	 reralloc(whole_program, whole_program->Shaders,
		  struct gl_shader *, whole_program->NumShaders + 1);
      assert(whole_program->Shaders != NULL);

      struct gl_shader *shader = rzalloc(whole_program, gl_shader);

      whole_program->Shaders[whole_program->NumShaders] = shader;
      whole_program->NumShaders++;

      const unsigned len = strlen(argv[optind]);
      if (len < 6)
	 usage_fail(argv[0]);

      const char *const ext = & argv[optind][len - 5];
      if (strncmp(".vert", ext, 5) == 0 || strncmp(".glsl", ext, 5) == 0)
	 shader->Type = GL_VERTEX_SHADER;
      else if (strncmp(".geom", ext, 5) == 0)
	 shader->Type = GL_GEOMETRY_SHADER;
      else if (strncmp(".frag", ext, 5) == 0)
	 shader->Type = GL_FRAGMENT_SHADER;
      else
	 usage_fail(argv[0]);

      shader->Source = load_text_file(whole_program, argv[optind]);
      if (shader->Source == NULL) {
	 printf("File \"%s\" does not exist.\n", argv[optind]);
	 exit(EXIT_FAILURE);
      }

      compile_shader(ctx, shader);

      if (!shader->CompileStatus) {
	 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
	 status = EXIT_FAILURE;
	 break;
      }
   }

   if ((status == EXIT_SUCCESS) && do_link)  {
      link_shaders(ctx, whole_program);
      status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;

      if (strlen(whole_program->InfoLog) > 0)
	 printf("Info log for linking:\n%s\n", whole_program->InfoLog);
   }

   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
      ralloc_free(whole_program->_LinkedShaders[i]);

   ralloc_free(whole_program);
   _mesa_glsl_release_types();
   _mesa_glsl_release_builtin_functions();

   return status;
}
<commit_msg>glsl_compiler: Set max GLSL version on the command line<commit_after>/*
 * Copyright © 2008, 2009 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <getopt.h>

/** @file main.cpp
 *
 * This file is the main() routine and scaffolding for producing
 * builtin_compiler (which doesn't include builtins itself and is used
 * to generate the profile information for builtin_function.cpp), and
 * for glsl_compiler (which does include builtins and can be used to
 * offline compile GLSL code and examine the resulting GLSL IR.
 */

#include "ast.h"
#include "glsl_parser_extras.h"
#include "ir_optimization.h"
#include "program.h"
#include "loop_analysis.h"
#include "standalone_scaffolding.h"

static int glsl_version = 330;

static void
initialize_context(struct gl_context *ctx, gl_api api)
{
   initialize_context_to_defaults(ctx, api);

   /* The standalone compiler needs to claim support for almost
    * everything in order to compile the built-in functions.
    */
   ctx->Const.GLSLVersion = glsl_version;
   ctx->Extensions.ARB_ES3_compatibility = true;

   switch (ctx->Const.GLSLVersion) {
   case 100:
      ctx->Const.MaxClipPlanes = 0;
      ctx->Const.MaxCombinedTextureImageUnits = 8;
      ctx->Const.MaxDrawBuffers = 2;
      ctx->Const.MinProgramTexelOffset = 0;
      ctx->Const.MaxProgramTexelOffset = 0;
      ctx->Const.MaxLights = 0;
      ctx->Const.MaxTextureCoordUnits = 0;
      ctx->Const.MaxTextureUnits = 8;

      ctx->Const.VertexProgram.MaxAttribs = 8;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 0;
      ctx->Const.VertexProgram.MaxUniformComponents = 128 * 4;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 32;

      ctx->Const.FragmentProgram.MaxTextureImageUnits =
         ctx->Const.MaxCombinedTextureImageUnits;
      ctx->Const.FragmentProgram.MaxUniformComponents = 16 * 4;
      ctx->Const.FragmentProgram.MaxInputComponents =
         ctx->Const.VertexProgram.MaxOutputComponents;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxVarying = ctx->Const.VertexProgram.MaxOutputComponents / 4;
      break;
   case 110:
   case 120:
      ctx->Const.MaxClipPlanes = 6;
      ctx->Const.MaxCombinedTextureImageUnits = 2;
      ctx->Const.MaxDrawBuffers = 1;
      ctx->Const.MinProgramTexelOffset = 0;
      ctx->Const.MaxProgramTexelOffset = 0;
      ctx->Const.MaxLights = 8;
      ctx->Const.MaxTextureCoordUnits = 2;
      ctx->Const.MaxTextureUnits = 2;

      ctx->Const.VertexProgram.MaxAttribs = 16;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 0;
      ctx->Const.VertexProgram.MaxUniformComponents = 512;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 32;

      ctx->Const.FragmentProgram.MaxTextureImageUnits =
         ctx->Const.MaxCombinedTextureImageUnits;
      ctx->Const.FragmentProgram.MaxUniformComponents = 64;
      ctx->Const.FragmentProgram.MaxInputComponents =
         ctx->Const.VertexProgram.MaxOutputComponents;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxVarying = ctx->Const.VertexProgram.MaxOutputComponents / 4;
      break;
   case 130:
   case 140:
      ctx->Const.MaxClipPlanes = 8;
      ctx->Const.MaxCombinedTextureImageUnits = 16;
      ctx->Const.MaxDrawBuffers = 8;
      ctx->Const.MinProgramTexelOffset = -8;
      ctx->Const.MaxProgramTexelOffset = 7;
      ctx->Const.MaxLights = 8;
      ctx->Const.MaxTextureCoordUnits = 8;
      ctx->Const.MaxTextureUnits = 2;

      ctx->Const.VertexProgram.MaxAttribs = 16;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 16;
      ctx->Const.VertexProgram.MaxUniformComponents = 1024;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 64;

      ctx->Const.FragmentProgram.MaxTextureImageUnits = 16;
      ctx->Const.FragmentProgram.MaxUniformComponents = 1024;
      ctx->Const.FragmentProgram.MaxInputComponents =
         ctx->Const.VertexProgram.MaxOutputComponents;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxVarying = ctx->Const.VertexProgram.MaxOutputComponents / 4;
      break;
   case 150:
   case 330:
      ctx->Const.MaxClipPlanes = 8;
      ctx->Const.MaxDrawBuffers = 8;
      ctx->Const.MinProgramTexelOffset = -8;
      ctx->Const.MaxProgramTexelOffset = 7;
      ctx->Const.MaxLights = 8;
      ctx->Const.MaxTextureCoordUnits = 8;
      ctx->Const.MaxTextureUnits = 2;

      ctx->Const.VertexProgram.MaxAttribs = 16;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 16;
      ctx->Const.VertexProgram.MaxUniformComponents = 1024;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 64;

      ctx->Const.GeometryProgram.MaxTextureImageUnits = 16;
      ctx->Const.GeometryProgram.MaxUniformComponents = 1024;
      ctx->Const.GeometryProgram.MaxInputComponents =
         ctx->Const.VertexProgram.MaxOutputComponents;
      ctx->Const.GeometryProgram.MaxOutputComponents = 128;

      ctx->Const.FragmentProgram.MaxTextureImageUnits = 16;
      ctx->Const.FragmentProgram.MaxUniformComponents = 1024;
      ctx->Const.FragmentProgram.MaxInputComponents =
         ctx->Const.GeometryProgram.MaxOutputComponents;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxCombinedTextureImageUnits =
         ctx->Const.VertexProgram.MaxTextureImageUnits
         + ctx->Const.GeometryProgram.MaxTextureImageUnits
         + ctx->Const.FragmentProgram.MaxTextureImageUnits;

      ctx->Const.MaxGeometryOutputVertices = 256;
      ctx->Const.MaxGeometryTotalOutputComponents = 1024;

//      ctx->Const.MaxGeometryVaryingComponents = 64;

      ctx->Const.MaxVarying = 60 / 4;
      break;
   case 300:
      ctx->Const.MaxClipPlanes = 8;
      ctx->Const.MaxCombinedTextureImageUnits = 32;
      ctx->Const.MaxDrawBuffers = 4;
      ctx->Const.MinProgramTexelOffset = -8;
      ctx->Const.MaxProgramTexelOffset = 7;
      ctx->Const.MaxLights = 0;
      ctx->Const.MaxTextureCoordUnits = 0;
      ctx->Const.MaxTextureUnits = 0;

      ctx->Const.VertexProgram.MaxAttribs = 16;
      ctx->Const.VertexProgram.MaxTextureImageUnits = 16;
      ctx->Const.VertexProgram.MaxUniformComponents = 1024;
      ctx->Const.VertexProgram.MaxInputComponents = 0; /* not used */
      ctx->Const.VertexProgram.MaxOutputComponents = 16 * 4;

      ctx->Const.FragmentProgram.MaxTextureImageUnits = 16;
      ctx->Const.FragmentProgram.MaxUniformComponents = 224;
      ctx->Const.FragmentProgram.MaxInputComponents = 15 * 4;
      ctx->Const.FragmentProgram.MaxOutputComponents = 0; /* not used */

      ctx->Const.MaxVarying = ctx->Const.FragmentProgram.MaxInputComponents / 4;
      break;
   }

   ctx->Driver.NewShader = _mesa_new_shader;
}

/* Returned string will have 'ctx' as its ralloc owner. */
static char *
load_text_file(void *ctx, const char *file_name)
{
	char *text = NULL;
	size_t size;
	size_t total_read = 0;
	FILE *fp = fopen(file_name, "rb");

	if (!fp) {
		return NULL;
	}

	fseek(fp, 0L, SEEK_END);
	size = ftell(fp);
	fseek(fp, 0L, SEEK_SET);

	text = (char *) ralloc_size(ctx, size + 1);
	if (text != NULL) {
		do {
			size_t bytes = fread(text + total_read,
					     1, size - total_read, fp);
			if (bytes < size - total_read) {
				free(text);
				text = NULL;
				break;
			}

			if (bytes == 0) {
				break;
			}

			total_read += bytes;
		} while (total_read < size);

		text[total_read] = '\0';
	}

	fclose(fp);

	return text;
}

int dump_ast = 0;
int dump_hir = 0;
int dump_lir = 0;
int do_link = 0;

const struct option compiler_opts[] = {
   { "dump-ast", no_argument, &dump_ast, 1 },
   { "dump-hir", no_argument, &dump_hir, 1 },
   { "dump-lir", no_argument, &dump_lir, 1 },
   { "link",     no_argument, &do_link,  1 },
   { "version",  required_argument, NULL, 'v' },
   { NULL, 0, NULL, 0 }
};

/**
 * \brief Print proper usage and exit with failure.
 */
void
usage_fail(const char *name)
{

   const char *header =
      "usage: %s [options] <file.vert | file.geom | file.frag>\n"
      "\n"
      "Possible options are:\n";
   printf(header, name, name);
   for (const struct option *o = compiler_opts; o->name != 0; ++o) {
      printf("    --%s\n", o->name);
   }
   exit(EXIT_FAILURE);
}

void
compile_shader(struct gl_context *ctx, struct gl_shader *shader)
{
   struct _mesa_glsl_parse_state *state =
      new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);

   _mesa_glsl_compile_shader(ctx, shader, dump_ast, dump_hir);

   /* Print out the resulting IR */
   if (!state->error && dump_lir) {
      _mesa_print_ir(shader->ir, state);
   }

   return;
}

int
main(int argc, char **argv)
{
   int status = EXIT_SUCCESS;
   struct gl_context local_ctx;
   struct gl_context *ctx = &local_ctx;
   bool glsl_es = false;

   int c;
   int idx = 0;
   while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1) {
      switch (c) {
      case 'v':
         glsl_version = strtol(optarg, NULL, 10);
         switch (glsl_version) {
         case 100:
         case 300:
            glsl_es = true;
            break;
         case 110:
         case 120:
         case 130:
         case 140:
         case 150:
         case 330:
            glsl_es = false;
            break;
         default:
            fprintf(stderr, "Unrecognized GLSL version `%s'\n", optarg);
            usage_fail(argv[0]);
            break;
         }
         break;
      default:
         break;
      }
   }

   if (argc <= optind)
      usage_fail(argv[0]);

   initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL_COMPAT);

   struct gl_shader_program *whole_program;

   whole_program = rzalloc (NULL, struct gl_shader_program);
   assert(whole_program != NULL);
   whole_program->InfoLog = ralloc_strdup(whole_program, "");

   for (/* empty */; argc > optind; optind++) {
      whole_program->Shaders =
	 reralloc(whole_program, whole_program->Shaders,
		  struct gl_shader *, whole_program->NumShaders + 1);
      assert(whole_program->Shaders != NULL);

      struct gl_shader *shader = rzalloc(whole_program, gl_shader);

      whole_program->Shaders[whole_program->NumShaders] = shader;
      whole_program->NumShaders++;

      const unsigned len = strlen(argv[optind]);
      if (len < 6)
	 usage_fail(argv[0]);

      const char *const ext = & argv[optind][len - 5];
      if (strncmp(".vert", ext, 5) == 0 || strncmp(".glsl", ext, 5) == 0)
	 shader->Type = GL_VERTEX_SHADER;
      else if (strncmp(".geom", ext, 5) == 0)
	 shader->Type = GL_GEOMETRY_SHADER;
      else if (strncmp(".frag", ext, 5) == 0)
	 shader->Type = GL_FRAGMENT_SHADER;
      else
	 usage_fail(argv[0]);

      shader->Source = load_text_file(whole_program, argv[optind]);
      if (shader->Source == NULL) {
	 printf("File \"%s\" does not exist.\n", argv[optind]);
	 exit(EXIT_FAILURE);
      }

      compile_shader(ctx, shader);

      if (!shader->CompileStatus) {
	 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
	 status = EXIT_FAILURE;
	 break;
      }
   }

   if ((status == EXIT_SUCCESS) && do_link)  {
      link_shaders(ctx, whole_program);
      status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;

      if (strlen(whole_program->InfoLog) > 0)
	 printf("Info log for linking:\n%s\n", whole_program->InfoLog);
   }

   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
      ralloc_free(whole_program->_LinkedShaders[i]);

   ralloc_free(whole_program);
   _mesa_glsl_release_types();
   _mesa_glsl_release_builtin_functions();

   return status;
}
<|endoftext|>


<commit_before>/* $Id: ex2.C,v 1.18 2005-06-06 17:50:35 jwpeterson Exp $ */

/* The Next Great Finite Element Library. */
/* Copyright (C) 2003  Benjamin S. Kirk */

/* 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

 //
Example 2 - Defining a Simple System

 //
 // This is the second example program.  It demonstrates how to
 // create an equation system for a simple scalar system.  This
 // example will also introduce some of the issues involved with using Petsc
 // in your application.
 //
 // This is the first example program that indirectly
 // uses the Petsc library.  By default equation data is stored
 // in Petsc vectors, which may span multiple processors.  Before
 // Petsc is used it must be initialized via libMesh::init().  Note that
 // by passing argc and argv to Petsc you may specify
 // command line arguments to Petsc.  For example, you might
 // try running this example as:
 //
 // ./ex2 -log_info
 //
 // to see what Petsc is doing behind the scenes or
 //
 // ./ex2 -log_summary
 //
 // to get a summary of what Petsc did.
 // Among other things, libMesh::init() initializes the MPI
 // communications library on your system if you haven't already
 // done so.

// C++ include files that we need
#include <iostream>
//Basic include file needed for the mesh functionality.
#include "libmesh.h"
#include "mesh.h"
// Include file that defines various mesh generation utilities
#include "mesh_generation.h"
// Include file that defines (possibly multiple) systems of equations.
#include "equation_systems.h"
// Include file that defines a simple steady system
#include "transient_system.h"

int main (int argc, char** argv)
{
  libMesh::init (argc, argv);
  // This set of braces are used to force object scope.  This
  // way we can guarantee all our objects are destroyed before calling
  // libMesh::close() at the end of the program.
  {
    // A brief message to the user to inform her of the
    // exact name of the program being run, and its command line.
    std::cout << "Running " << argv[0];
    for (int i=1; i<argc; i++)
      std::cout << " " << argv[i];
    std::cout << std::endl << std::endl;

    // Create a 2D mesh.
    Mesh mesh (2);

    // Use the MeshTools::Generation mesh generator to create a uniform
    // grid on the unit square.  By default a mesh of QUAD4
    // elements will be created.  We instruct the mesh generator
    // to build a mesh of 5x5 elements.
    MeshTools::Generation::build_cube (mesh, 5, 5);

    // Print information about the mesh to the screen.
    mesh.print_info();

    // Create an equation systems object. This object can
    // contain multiple systems of different
    // flavors for solving loosely coupled physics.  Each system can
    // contain multiple variables of different approximation orders.
    // Here we will simply create a single system with one variable.
    // Later on, other flavors of systems will be introduced.  For the
    // moment, we use the general system.
    // The EquationSystems object needs a reference to the mesh
    // object, so the order of construction here is important.
    EquationSystems equation_systems (mesh);

    // Add a flag "test" that is visible for all systems.  This
    // helps in inter-system communication.
    equation_systems.parameters.set<bool> ("test") = true;

    // Set a simulation-specific parameter visible for all systems.
    // This helps in inter-system-communication.
    equation_systems.parameters.set<Real> ("dummy") = 42.;

    // Set another simulation-specific parameter
    equation_systems.parameters.set<Real> ("nobody") = 0.;

    // Now we declare the system and its variables.
    // We begin by adding a "SteadyStytem" to the
    // EquationSystems object, and we give it the name
    // "Simple System".
    equation_systems.add_system<TransientLinearImplicitSystem> ("Simple System");

    // Adds the variable "u" to "Simple System".  "u"
    // will be approximated using first-order approximation.
    equation_systems.get_system("Simple System").add_variable("u", FIRST);

    // Initialize the data structures for the equation system.
    equation_systems.init();

    // Prints information about the system to the screen.
    equation_systems.print_info();

    // Write the equation system if the user specified an
    // output file name.  Note that there are two possible
    // formats to write to.  Specifying libMeshEnums::WRITE will
    // create a formatted ASCII file.  Optionally, you can specify
    // libMeshEnums::ENCODE and get an XDR-encoded binary file.
    //
    // We will write the data, clear the object, and read the file
    // we just wrote.  This is simply to demonstrate capability.
    // Note that you might use this in an application to periodically
    // dump the state of your simulation.  You can then restart from
    // this data later.
    if (argc == 2)
      if (argv[1][0] != '-')
	{
	  std::cout << "<<< Writing system to file " << argv[1]
		    << std::endl;

	  // Write the system.
	  equation_systems.write (argv[1], libMeshEnums::WRITE);

	  // Clear the equation systems data structure.
	  equation_systems.clear ();

	  std::cout << ">>> Reading system from file " << argv[1]
		    << std::endl << std::endl;

	  // Read the file we just wrote.  This better
	  // work!
	  equation_systems.read (argv[1], libMeshEnums::READ);

	  // Print the information again.
	  equation_systems.print_info();
	}

    // All our objects will be destroyed at this closing brace.
    // That way we can safely call PetscFinalize() and be sure we
    // don't have any Petsc-dependent objects lurking around!
  }

  // Call libMesh::close(), which in turn finalizes PETSc and/or
  // MPI.
  return libMesh::close();
}
<commit_msg>Add include for linear_implicit_system.h that no longer gets brought in by transient_system.h<commit_after>/* $Id: ex2.C,v 1.19 2006-03-29 21:00:56 roystgnr Exp $ */

/* The Next Great Finite Element Library. */
/* Copyright (C) 2003  Benjamin S. Kirk */

/* 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

 //
Example 2 - Defining a Simple System

 //
 // This is the second example program.  It demonstrates how to
 // create an equation system for a simple scalar system.  This
 // example will also introduce some of the issues involved with using Petsc
 // in your application.
 //
 // This is the first example program that indirectly
 // uses the Petsc library.  By default equation data is stored
 // in Petsc vectors, which may span multiple processors.  Before
 // Petsc is used it must be initialized via libMesh::init().  Note that
 // by passing argc and argv to Petsc you may specify
 // command line arguments to Petsc.  For example, you might
 // try running this example as:
 //
 // ./ex2 -log_info
 //
 // to see what Petsc is doing behind the scenes or
 //
 // ./ex2 -log_summary
 //
 // to get a summary of what Petsc did.
 // Among other things, libMesh::init() initializes the MPI
 // communications library on your system if you haven't already
 // done so.

// C++ include files that we need
#include <iostream>
//Basic include file needed for the mesh functionality.
#include "libmesh.h"
#include "mesh.h"
// Include file that defines various mesh generation utilities
#include "mesh_generation.h"
// Include file that defines (possibly multiple) systems of equations.
#include "equation_systems.h"
// Include files that define a simple steady system
#include "linear_implicit_system.h"
#include "transient_system.h"

int main (int argc, char** argv)
{
  libMesh::init (argc, argv);
  // This set of braces are used to force object scope.  This
  // way we can guarantee all our objects are destroyed before calling
  // libMesh::close() at the end of the program.
  {
    // A brief message to the user to inform her of the
    // exact name of the program being run, and its command line.
    std::cout << "Running " << argv[0];
    for (int i=1; i<argc; i++)
      std::cout << " " << argv[i];
    std::cout << std::endl << std::endl;

    // Create a 2D mesh.
    Mesh mesh (2);

    // Use the MeshTools::Generation mesh generator to create a uniform
    // grid on the unit square.  By default a mesh of QUAD4
    // elements will be created.  We instruct the mesh generator
    // to build a mesh of 5x5 elements.
    MeshTools::Generation::build_cube (mesh, 5, 5);

    // Print information about the mesh to the screen.
    mesh.print_info();

    // Create an equation systems object. This object can
    // contain multiple systems of different
    // flavors for solving loosely coupled physics.  Each system can
    // contain multiple variables of different approximation orders.
    // Here we will simply create a single system with one variable.
    // Later on, other flavors of systems will be introduced.  For the
    // moment, we use the general system.
    // The EquationSystems object needs a reference to the mesh
    // object, so the order of construction here is important.
    EquationSystems equation_systems (mesh);

    // Add a flag "test" that is visible for all systems.  This
    // helps in inter-system communication.
    equation_systems.parameters.set<bool> ("test") = true;

    // Set a simulation-specific parameter visible for all systems.
    // This helps in inter-system-communication.
    equation_systems.parameters.set<Real> ("dummy") = 42.;

    // Set another simulation-specific parameter
    equation_systems.parameters.set<Real> ("nobody") = 0.;

    // Now we declare the system and its variables.
    // We begin by adding a "SteadyStytem" to the
    // EquationSystems object, and we give it the name
    // "Simple System".
    equation_systems.add_system<TransientLinearImplicitSystem> ("Simple System");

    // Adds the variable "u" to "Simple System".  "u"
    // will be approximated using first-order approximation.
    equation_systems.get_system("Simple System").add_variable("u", FIRST);

    // Initialize the data structures for the equation system.
    equation_systems.init();

    // Prints information about the system to the screen.
    equation_systems.print_info();

    // Write the equation system if the user specified an
    // output file name.  Note that there are two possible
    // formats to write to.  Specifying libMeshEnums::WRITE will
    // create a formatted ASCII file.  Optionally, you can specify
    // libMeshEnums::ENCODE and get an XDR-encoded binary file.
    //
    // We will write the data, clear the object, and read the file
    // we just wrote.  This is simply to demonstrate capability.
    // Note that you might use this in an application to periodically
    // dump the state of your simulation.  You can then restart from
    // this data later.
    if (argc == 2)
      if (argv[1][0] != '-')
	{
	  std::cout << "<<< Writing system to file " << argv[1]
		    << std::endl;

	  // Write the system.
	  equation_systems.write (argv[1], libMeshEnums::WRITE);

	  // Clear the equation systems data structure.
	  equation_systems.clear ();

	  std::cout << ">>> Reading system from file " << argv[1]
		    << std::endl << std::endl;

	  // Read the file we just wrote.  This better
	  // work!
	  equation_systems.read (argv[1], libMeshEnums::READ);

	  // Print the information again.
	  equation_systems.print_info();
	}

    // All our objects will be destroyed at this closing brace.
    // That way we can safely call PetscFinalize() and be sure we
    // don't have any Petsc-dependent objects lurking around!
  }

  // Call libMesh::close(), which in turn finalizes PETSc and/or
  // MPI.
  return libMesh::close();
}
<|endoftext|>


<commit_before>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/
#include"ork/ork.hpp"
#define ORK_STL_INC_FILE <fstream>
#include"ork/core/stl_include.inl"
#define ORK_STL_INC_FILE <iostream>
#include"ork/core/stl_include.inl"
#define ORK_STL_INC_FILE <mutex>
#include"ork/core/stl_include.inl"
#define ORK_STL_INC_FILE <sstream>
#include"ork/core/stl_include.inl"

#include"ork/memory.hpp"

namespace ork {

const ork::string debug_trace(ORK("debug_trace"));
const ork::string output_data(ORK("output_data"));

const ork::string&to_string(const log_channel val) {
	switch(val) {
	case log_channel::debug_trace:
		return debug_trace;
	case log_channel::output_data:
		return output_data;
	};
	ORK_UNREACHABLE
}
log_channel string2log_channel(const ork::string&str) {
	if(str == output_data) {
		return log_channel::output_data;
	}
	if(str == output_data) {
		return log_channel::output_data;
	}
	ORK_THROW(ORK("Invalid log_channel: ") << str);
}

const ork::string trace(ORK("trace"));
const ork::string debug(ORK("debug"));
const ork::string info(ORK("info"));
const ork::string warning(ORK("warning"));
const ork::string error(ORK("error"));
const ork::string fatal(ORK("fatal"));

const ork::string&to_string(const severity_level val) {
	switch(val) {
	case severity_level::trace:
		return trace;
	case severity_level::debug:
		return debug;
	case severity_level::info:
		return info;
	case severity_level::warning:
		return warning;
	case severity_level::error:
		return error;
	case severity_level::fatal:
		return fatal;
	};
	ORK_UNREACHABLE
}
severity_level string2severity_level(const ork::string&str) {
	if(str == trace) {
		return severity_level::trace;
	}
	if(str == debug) {
		return severity_level::debug;
	}
	if(str == info) {
		return severity_level::info;
	}
	if(str == warning) {
		return severity_level::warning;
	}
	if(str == error) {
		return severity_level::error;
	}
	if(str == fatal) {
		return severity_level::fatal;
	}
	ORK_THROW(ORK("Invalid severity_level: ") << str);
}

//This is little more than a synchronous wrapper around an o_stream
class log_stream {
public:
	using stream_ptr = std::shared_ptr<o_stream>;
private:
	stream_ptr _stream;
	std::mutex _mutex;
public:
	explicit log_stream(stream_ptr stream_) : _stream{stream_}, _mutex{} {}
	ORK_NON_COPYABLE(log_stream)
public:
	void log(const string&message) {
		std::lock_guard<std::mutex>lock(_mutex);
		*_stream << message;
	}
	void flush() {
		_stream->flush();
	}
};

class log_sink {
public:
	using stream_ptr = std::shared_ptr<log_stream>;
private:
	std::vector<stream_ptr>_streams = {};
	bool _auto_flush = false;
public:
	log_sink() {}
	log_sink(const bool auto_flush) : _auto_flush{auto_flush} {}
public:
	void insert(const stream_ptr&ptr) {
		_streams.push_back(ptr);
	}
	void log(const string&message) {
		for(auto&stream : _streams) {
			stream->log(message);
			if(_auto_flush) {
				stream->flush();
			}
		}
	}
	void set_auto_flush(const bool auto_flush) {
		_auto_flush = auto_flush;
	}
	void flush() {
		for(auto&stream : _streams) {
			stream->flush();
		}
	}
};

std::shared_ptr<log_stream>open_file_log_stream(const file::path&file_name) {
	if(!file::ensure_directory(file_name)) {
		ORK_THROW(ORK("Could not create directory : ") << file_name.ORK_GEN_STR())
	}
	of_stream* p_stream = new of_stream();
	p_stream->open(file_name);//std::ios::app | std::ios::ate
	if(p_stream->fail()) {
		ORK_THROW(ORK("Error opening log : ") << file_name)
	}
	//p_stream->rdbuf()->pubsetbuf(0, 0);//Less performance, more likely to catch error messages
	return std::shared_ptr<log_stream>(new log_stream(log_stream::stream_ptr(p_stream)));
}

//This is where our logging system falls short of a generic filter system; try to hide it somewhat in one place
class log_multiplexer {
private:
	std::array<log_sink, severity_levels.size()>_severity_sinks = {};
	log_sink _data_sink = {};
public:
	log_multiplexer(const file::path&root_directory){
		auto lout = log_sink::stream_ptr{new log_stream{log_stream::stream_ptr{&ORK_CLOG, singleton_deleter<o_stream>()}}};
		auto lerr = log_sink::stream_ptr{new log_stream{log_stream::stream_ptr{&ORK_CERR, singleton_deleter<o_stream>()}}};
		auto flog = open_file_log_stream(root_directory / ORK("trace.log"));
		auto fdata = open_file_log_stream(root_directory / ORK("output.log"));

		for(const auto sv : severity_levels) {
			auto sink = _severity_sinks[static_cast<size_t>(sv)];
			if(sv < severity_level::error) {
				sink.insert(lout);
				sink.set_auto_flush(true);
			}
			else {
				sink.insert(lerr);
			}
			sink.insert(flog);
		}
		_data_sink.insert(lout);
		_data_sink.insert(fdata);
	}
public:
	void log(const log_channel channel, const severity_level severity, const o_string_stream&stream) {
		const string message = stream.str();
		switch(channel) {
		case log_channel::debug_trace:
			log_severity(severity, message);
			break;
		case log_channel::output_data:
			_data_sink.log(stream.str());
			break;
		default:
			ORK_UNREACHABLE
		};
	}
	void flush_all() {
		for(auto&sink : _severity_sinks) {
			sink.flush();
		}
		_data_sink.flush();
	}
private:
	void log_severity(const severity_level severity, const string&message) {
		const bool do_it = ORK_DEBUG || severity > severity_level::debug;
		if(do_it) {//To avoid constant conditional expression
			_severity_sinks[static_cast<size_t>(severity)].log(message);
		}
	}
};

struct log_scope::impl {
public:
	std::shared_ptr<log_multiplexer>multiplexer;
	log_channel channel;
	severity_level severity;
	o_string_stream stream;
public:
	impl(std::shared_ptr<log_multiplexer>&mp, const log_channel lc, const severity_level sv)
		: multiplexer{mp}
		, channel{lc}
		, severity{sv}
		, stream{}
	{}
	~impl() {
		multiplexer->log(channel, severity, stream);
	}
	ORK_MOVE_ONLY(impl)
};

log_scope::log_scope(std::unique_ptr<impl>&&ptr) : _pimpl{ std::move(ptr) } {}
log_scope::~log_scope() {}

#define LOG_STREAM_OPERATOR(TYPE) \
log_scope& log_scope::operator<< (const TYPE val) {\
	_pimpl->stream << val;\
	return *this;\
}
LOG_STREAM_OPERATOR(bool)
LOG_STREAM_OPERATOR(short)
LOG_STREAM_OPERATOR(unsigned short)
LOG_STREAM_OPERATOR(int)
LOG_STREAM_OPERATOR(unsigned)
LOG_STREAM_OPERATOR(long)
LOG_STREAM_OPERATOR(unsigned long)
LOG_STREAM_OPERATOR(long long)
LOG_STREAM_OPERATOR(unsigned long long)
LOG_STREAM_OPERATOR(float)
LOG_STREAM_OPERATOR(double)
LOG_STREAM_OPERATOR(long double)

#undef LOG_STREAM_OPERATOR
#define LOG_STREAM_OPERATOR(TYPE) \
log_scope& log_scope::operator<< (const TYPE val) {\
	_pimpl->stream << ORK_BYTE_2_STR(val);\
	return *this;\
}

LOG_STREAM_OPERATOR(char)
LOG_STREAM_OPERATOR(char*)
LOG_STREAM_OPERATOR(bstring&)

#undef LOG_STREAM_OPERATOR
#define LOG_STREAM_OPERATOR(TYPE) \
log_scope& log_scope::operator<< (const TYPE val) {\
	_pimpl->stream << ORK_WIDE_2_STR(val);\
	return *this;\
}

LOG_STREAM_OPERATOR(wchar_t)
LOG_STREAM_OPERATOR(wchar_t*)
LOG_STREAM_OPERATOR(wstring&)

log_scope& log_scope::operator<< (const void* val) {
	_pimpl->stream << val;
	return *this;
}
log_scope& log_scope::operator<< (const std::streambuf* sb) {
	_pimpl->stream << sb;
	return *this;
}
log_scope& log_scope::operator<< (std::ostream& (*pf)(std::ostream&)) {
	_pimpl->stream << pf;
	return *this;
}
log_scope& log_scope::operator<< (std::ios& (*pf)(std::ios&)) {
	_pimpl->stream << pf;
	return *this;
}
log_scope& log_scope::operator<< (std::ios_base& (*pf)(std::ios_base&)) {
	_pimpl->stream << pf;
	return *this;
}

const string&to_formatted_string(const severity_level sv) {
	static const std::array<const string, severity_levels.size()>strings = {{
		  ORK("TRACE")
		, ORK("DEBUG")
		, ORK("INFO ")
		, ORK("WARN ")
		, ORK("ERROR")
		, ORK("FATAL")
	}};
	return strings[static_cast<size_t>(sv)];
}

struct logger::impl {
public:
	file::path root_directory;
	std::shared_ptr<log_multiplexer>multiplexer;
public:
	impl(const file::path&directory)
		: root_directory(directory)
		, multiplexer{new log_multiplexer(directory)}
	{}
	void flush_all() {
		multiplexer->flush_all();
	}
};

logger::logger(const file::path&log_directory) : _pimpl(new impl(log_directory)) {}
logger::~logger() {}

const file::path& logger::root_directory() {
	return _pimpl->root_directory;
}

log_scope logger::get_log_scope(
	  const string&file_
	, const string&line_
	, const string&function_
	, const log_channel channel
	, const severity_level severity)
{
	const file::path fullpath(file_);
	string file(fullpath.filename().ORK_GEN_STR());
	file.resize(28, ORK(' '));

	string line(line_);
	line.resize(4, ORK(' '));

	string function(function_);
	function.resize(40, ORK(' '));

	std::unique_ptr<log_scope::impl> ls_impl(new log_scope::impl(_pimpl->multiplexer, channel, severity));
	log_scope scope(std::move(ls_impl));
	//Output formatted context first
	scope << ORK("[") << to_formatted_string(severity) << ORK("]:") << file << ORK("(") << line << ORK("):") << function << ORK("-- ");

	//Finally, return the stream to the client
	return std::move(scope);
}

void logger::flush_all() {
	_pimpl->flush_all();
}

logger*_g_log = nullptr;
int make_global_log(const string&directory) {
	static logger log(directory);
	_g_log = &log;
	return 0;
}
logger& get_global_log() {
	return *_g_log;
}

}//namespace ork
<commit_msg>Log now auto flushes<commit_after>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/
#include"ork/ork.hpp"
#define ORK_STL_INC_FILE <fstream>
#include"ork/core/stl_include.inl"
#define ORK_STL_INC_FILE <iostream>
#include"ork/core/stl_include.inl"
#define ORK_STL_INC_FILE <mutex>
#include"ork/core/stl_include.inl"
#define ORK_STL_INC_FILE <sstream>
#include"ork/core/stl_include.inl"

#include"ork/memory.hpp"

namespace ork {

const ork::string debug_trace(ORK("debug_trace"));
const ork::string output_data(ORK("output_data"));

const ork::string&to_string(const log_channel val) {
	switch(val) {
	case log_channel::debug_trace:
		return debug_trace;
	case log_channel::output_data:
		return output_data;
	};
	ORK_UNREACHABLE
}
log_channel string2log_channel(const ork::string&str) {
	if(str == output_data) {
		return log_channel::output_data;
	}
	if(str == output_data) {
		return log_channel::output_data;
	}
	ORK_THROW(ORK("Invalid log_channel: ") << str);
}

const ork::string trace(ORK("trace"));
const ork::string debug(ORK("debug"));
const ork::string info(ORK("info"));
const ork::string warning(ORK("warning"));
const ork::string error(ORK("error"));
const ork::string fatal(ORK("fatal"));

const ork::string&to_string(const severity_level val) {
	switch(val) {
	case severity_level::trace:
		return trace;
	case severity_level::debug:
		return debug;
	case severity_level::info:
		return info;
	case severity_level::warning:
		return warning;
	case severity_level::error:
		return error;
	case severity_level::fatal:
		return fatal;
	};
	ORK_UNREACHABLE
}
severity_level string2severity_level(const ork::string&str) {
	if(str == trace) {
		return severity_level::trace;
	}
	if(str == debug) {
		return severity_level::debug;
	}
	if(str == info) {
		return severity_level::info;
	}
	if(str == warning) {
		return severity_level::warning;
	}
	if(str == error) {
		return severity_level::error;
	}
	if(str == fatal) {
		return severity_level::fatal;
	}
	ORK_THROW(ORK("Invalid severity_level: ") << str);
}

//This is little more than a synchronous wrapper around an o_stream
class log_stream {
public:
	using stream_ptr = std::shared_ptr<o_stream>;
private:
	stream_ptr _stream;
	std::mutex _mutex;
public:
	explicit log_stream(stream_ptr stream_) : _stream{stream_}, _mutex{} {}
	ORK_NON_COPYABLE(log_stream)
public:
	void log(const string&message) {
		std::lock_guard<std::mutex>lock(_mutex);
		*_stream << message;
	}
	void flush() {
		_stream->flush();
	}
};

class log_sink {
public:
	using stream_ptr = std::shared_ptr<log_stream>;
private:
	std::vector<stream_ptr>_streams = {};
	bool _auto_flush = true;
public:
	log_sink() {}
	log_sink(const bool auto_flush) : _auto_flush{auto_flush} {}
public:
	void insert(const stream_ptr&ptr) {
		_streams.push_back(ptr);
	}
	void log(const string&message) {
		for(auto&stream : _streams) {
			stream->log(message);
			if(_auto_flush) {
				stream->flush();
			}
		}
	}
	void set_auto_flush(const bool auto_flush) {
		_auto_flush = auto_flush;
	}
	void flush() {
		for(auto&stream : _streams) {
			stream->flush();
		}
	}
};

std::shared_ptr<log_stream>open_file_log_stream(const file::path&file_name) {
	if(!file::ensure_directory(file_name)) {
		ORK_THROW(ORK("Could not create directory : ") << file_name.ORK_GEN_STR())
	}
	of_stream* p_stream = new of_stream();
	p_stream->open(file_name);//std::ios::app | std::ios::ate
	if(p_stream->fail()) {
		ORK_THROW(ORK("Error opening log : ") << file_name)
	}
	//p_stream->rdbuf()->pubsetbuf(0, 0);//Less performance, more likely to catch error messages
	return std::shared_ptr<log_stream>(new log_stream(log_stream::stream_ptr(p_stream)));
}

//This is where our logging system falls short of a generic filter system; try to hide it somewhat in one place
class log_multiplexer {
private:
	std::array<log_sink, severity_levels.size()>_severity_sinks = {};
	log_sink _data_sink = {};
public:
	log_multiplexer(const file::path&root_directory){
		auto lout = log_sink::stream_ptr{new log_stream{log_stream::stream_ptr{&ORK_CLOG, singleton_deleter<o_stream>()}}};
		auto lerr = log_sink::stream_ptr{new log_stream{log_stream::stream_ptr{&ORK_CERR, singleton_deleter<o_stream>()}}};
		auto flog = open_file_log_stream(root_directory / ORK("trace.log"));
		auto fdata = open_file_log_stream(root_directory / ORK("output.log"));

		for(const auto sv : severity_levels) {
			auto sink = _severity_sinks[static_cast<size_t>(sv)];
			if(sv < severity_level::error) {
				sink.insert(lout);
				sink.set_auto_flush(true);
			}
			else {
				sink.insert(lerr);
			}
			sink.insert(flog);
		}
		_data_sink.insert(lout);
		_data_sink.insert(fdata);
	}
public:
	void log(const log_channel channel, const severity_level severity, const o_string_stream&stream) {
		const string message = stream.str();
		switch(channel) {
		case log_channel::debug_trace:
			log_severity(severity, message);
			break;
		case log_channel::output_data:
			_data_sink.log(stream.str());
			break;
		default:
			ORK_UNREACHABLE
		};
	}
	void flush_all() {
		for(auto&sink : _severity_sinks) {
			sink.flush();
		}
		_data_sink.flush();
	}
private:
	void log_severity(const severity_level severity, const string&message) {
		const bool do_it = ORK_DEBUG || severity > severity_level::debug;
		if(do_it) {//To avoid constant conditional expression
			_severity_sinks[static_cast<size_t>(severity)].log(message);
		}
	}
};

struct log_scope::impl {
public:
	std::shared_ptr<log_multiplexer>multiplexer;
	log_channel channel;
	severity_level severity;
	o_string_stream stream;
public:
	impl(std::shared_ptr<log_multiplexer>&mp, const log_channel lc, const severity_level sv)
		: multiplexer{mp}
		, channel{lc}
		, severity{sv}
		, stream{}
	{}
	~impl() {
		multiplexer->log(channel, severity, stream);
	}
	ORK_MOVE_ONLY(impl)
};

log_scope::log_scope(std::unique_ptr<impl>&&ptr) : _pimpl{ std::move(ptr) } {}
log_scope::~log_scope() {}

#define LOG_STREAM_OPERATOR(TYPE) \
log_scope& log_scope::operator<< (const TYPE val) {\
	_pimpl->stream << val;\
	return *this;\
}
LOG_STREAM_OPERATOR(bool)
LOG_STREAM_OPERATOR(short)
LOG_STREAM_OPERATOR(unsigned short)
LOG_STREAM_OPERATOR(int)
LOG_STREAM_OPERATOR(unsigned)
LOG_STREAM_OPERATOR(long)
LOG_STREAM_OPERATOR(unsigned long)
LOG_STREAM_OPERATOR(long long)
LOG_STREAM_OPERATOR(unsigned long long)
LOG_STREAM_OPERATOR(float)
LOG_STREAM_OPERATOR(double)
LOG_STREAM_OPERATOR(long double)

#undef LOG_STREAM_OPERATOR
#define LOG_STREAM_OPERATOR(TYPE) \
log_scope& log_scope::operator<< (const TYPE val) {\
	_pimpl->stream << ORK_BYTE_2_STR(val);\
	return *this;\
}

LOG_STREAM_OPERATOR(char)
LOG_STREAM_OPERATOR(char*)
LOG_STREAM_OPERATOR(bstring&)

#undef LOG_STREAM_OPERATOR
#define LOG_STREAM_OPERATOR(TYPE) \
log_scope& log_scope::operator<< (const TYPE val) {\
	_pimpl->stream << ORK_WIDE_2_STR(val);\
	return *this;\
}

LOG_STREAM_OPERATOR(wchar_t)
LOG_STREAM_OPERATOR(wchar_t*)
LOG_STREAM_OPERATOR(wstring&)

log_scope& log_scope::operator<< (const void* val) {
	_pimpl->stream << val;
	return *this;
}
log_scope& log_scope::operator<< (const std::streambuf* sb) {
	_pimpl->stream << sb;
	return *this;
}
log_scope& log_scope::operator<< (std::ostream& (*pf)(std::ostream&)) {
	_pimpl->stream << pf;
	return *this;
}
log_scope& log_scope::operator<< (std::ios& (*pf)(std::ios&)) {
	_pimpl->stream << pf;
	return *this;
}
log_scope& log_scope::operator<< (std::ios_base& (*pf)(std::ios_base&)) {
	_pimpl->stream << pf;
	return *this;
}

const string&to_formatted_string(const severity_level sv) {
	static const std::array<const string, severity_levels.size()>strings = {{
		  ORK("TRACE")
		, ORK("DEBUG")
		, ORK("INFO ")
		, ORK("WARN ")
		, ORK("ERROR")
		, ORK("FATAL")
	}};
	return strings[static_cast<size_t>(sv)];
}

struct logger::impl {
public:
	file::path root_directory;
	std::shared_ptr<log_multiplexer>multiplexer;
public:
	impl(const file::path&directory)
		: root_directory(directory)
		, multiplexer{new log_multiplexer(directory)}
	{}
	void flush_all() {
		multiplexer->flush_all();
	}
};

logger::logger(const file::path&log_directory) : _pimpl(new impl(log_directory)) {}
logger::~logger() {}

const file::path& logger::root_directory() {
	return _pimpl->root_directory;
}

log_scope logger::get_log_scope(
	  const string&file_
	, const string&line_
	, const string&function_
	, const log_channel channel
	, const severity_level severity)
{
	const file::path fullpath(file_);
	string file(fullpath.filename().ORK_GEN_STR());
	file.resize(28, ORK(' '));

	string line(line_);
	line.resize(4, ORK(' '));

	string function(function_);
	function.resize(40, ORK(' '));

	std::unique_ptr<log_scope::impl> ls_impl(new log_scope::impl(_pimpl->multiplexer, channel, severity));
	log_scope scope(std::move(ls_impl));
	//Output formatted context first
	scope << ORK("[") << to_formatted_string(severity) << ORK("]:") << file << ORK("(") << line << ORK("):") << function << ORK("-- ");

	//Finally, return the stream to the client
	return std::move(scope);
}

void logger::flush_all() {
	_pimpl->flush_all();
}

logger*_g_log = nullptr;
int make_global_log(const string&directory) {
	static logger log(directory);
	_g_log = &log;
	return 0;
}
logger& get_global_log() {
	return *_g_log;
}

}//namespace ork
<|endoftext|>


<commit_before>
#include "demoloop.h"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include "graphics/shader.h"
using namespace std;
using namespace demoloop;

float t = 0;
const float CYCLE_LENGTH = 10;

const static std::string shaderCode = R"===(
uniform mediump float cycle_ratio;

#define DEMOLOOP_M_PI 3.1459

#ifdef VERTEX
vec4 position(mat4 transform_proj, mat4 model, vec4 vertpos) {
  return transform_proj * model * vertpos;
}
#endif

#ifdef PIXEL
const int iter = 100;

const int numColors = 5;
const vec3 colors[numColors] = vec3[](
  // vec3(26.0 / 256.0, 41.0 / 256.0, 128.0 / 256.0),
  // vec3(38.0 / 256.0, 208.0 / 256.0, 206.0 / 256.0),
  // vec3(1.0, 1.0, 1.0),
  // vec3(0.0, 0.0, 0.0)

  vec3(0.8, 0.60, 0.1),
  vec3(234.0 / 256.0, 119.0 / 256.0, 2.0 / 256.0),
  vec3(1.0, 0.0, 0.0),
  vec3(1.0, 0.70, 0.0),
  vec3(0.0, 0.0, 0.0)
);
// float arrayTest[5] = float[5](3.4, 4.2, 5.0, 5.2, 1.1);

vec4 effect(vec4 color, Image texture, vec2 tc, vec2 screen_coords) {
  float t = cycle_ratio;
  float x = tc.x;
  float y = tc.y;

  vec2 c = vec2(
    (1.0 - pow(sin(cycle_ratio * DEMOLOOP_M_PI), 5.0)) / 28.5 + 0.35,
    0.3 + sin(cycle_ratio * DEMOLOOP_M_PI * 2.0) / 30.0
  );

  vec2 z;
  z.x = 3.0 * (x - 0.5);
  z.y = 2.0 * (y - 0.5);

  z /= 2.0;
  z.y -= 0.4;

  const float B = 256.0;

  int iterations = 0;
  for(int i=0; i<iter; i++) {
    z = vec2( z.x*z.x - z.y*z.y, 2.0*z.x*z.y ) + c;

    if(dot(z,z)>(B*B)) break;
    iterations = i;
  }

  // float q = (iterations == iter ? 0.0 : float(iterations)) / iter;
  float q = (iterations - log2(log2(dot(z,z))) + 4.0) / iter;
  float stepIncrement = 1.0 / (numColors + 1.0);
  float step = 0.0;

  vec3 mixed = vec3(0.0, 0.0, 0.0);
  for (int i = 0; i < numColors; ++i) {
    mixed = mix(mixed, colors[i], smoothstep(step, step + stepIncrement, q)); step += stepIncrement;
  }
  return vec4(mixed, 1.0);
}
#endif
)===";
class Loop050 : public Demoloop {
public:
  Loop050() : Demoloop(150, 150, 150), shader({shaderCode, shaderCode}) {
  }

  void Update(float dt) {
    t += dt;

    const float cycle = fmod(t, CYCLE_LENGTH);
    const float cycle_ratio = cycle / CYCLE_LENGTH;

    shader.attach();
    shader.sendFloat("cycle_ratio", 1, &cycle_ratio, 1);

    renderTexture(gl.getDefaultTexture(), 0, 0, width, height);

    shader.detach();
  }

private:
  Shader shader;
};

int main(int, char**){
  Loop050 test;
  test.Run();

  return 0;
}
<commit_msg>fix loop 051 for mobile<commit_after>
#include "demoloop.h"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include "graphics/shader.h"
using namespace std;
using namespace demoloop;

float t = 0;
const float CYCLE_LENGTH = 10;

const static std::string shaderCode = R"===(
uniform mediump float cycle_ratio;

#define DEMOLOOP_M_PI 3.1459

#ifdef VERTEX
vec4 position(mat4 transform_proj, mat4 model, vec4 vertpos) {
  return transform_proj * model * vertpos;
}
#endif

#ifdef PIXEL
const int iter = 100;

#define NUM_COLORS 5
uniform vec3 gradientColors[NUM_COLORS];

vec4 effect(vec4 color, Image texture, vec2 tc, vec2 screen_coords) {
  float t = cycle_ratio;
  float x = tc.x;
  float y = tc.y;

  vec2 c = vec2(
    (1.0 - pow(sin(cycle_ratio * DEMOLOOP_M_PI), 5.0)) / 28.5 + 0.35,
    0.3 + sin(cycle_ratio * DEMOLOOP_M_PI * 2.0) / 30.0
  );

  highp vec2 z;
  z.x = 3.0 * (x - 0.5);
  z.y = 2.0 * (y - 0.5);

  z /= 2.0;
  z.y -= 0.4;

  const float B = 256.0;

  int iterations = 0;
  for(int i=0; i<iter; i++) {
    z = vec2( z.x*z.x - z.y*z.y, 2.0*z.x*z.y ) + c;

    if(dot(z,z)>(B*B)) break;
    iterations = i;
  }

  float fIterations = float(iterations);
  float logLogDot = log2(log2(dot(z,z)));
  float q = (fIterations - logLogDot + 4.0) / float(iter);
  float stepIncrement = 1.0 / (float(NUM_COLORS) + 1.0);
  float step = 0.0;

  vec3 mixed = vec3(0.0, 0.0, 0.0);
  for (int i = 0; i < NUM_COLORS; ++i) {
    mixed = mix(mixed, gradientColors[i], smoothstep(step, step + stepIncrement, q)); step += stepIncrement;
  }
  return vec4(mixed, 1.0);
}
#endif
)===";
class Loop050 : public Demoloop {
public:
  Loop050() : Demoloop(150, 150, 150), shader({shaderCode, shaderCode}) {
    glm::vec3 colors[5] = {
      glm::vec3(0.8, 0.6, 0.1),
      glm::vec3(0.917, 0.467, 0.008),
      glm::vec3(1.0, 0.0, 0.0),
      glm::vec3(1.0, 0.7, 0.0),
      glm::vec3(0.0, 0.0, 0.0),
    };
    shader.sendFloat("gradientColors", 3, &colors[0].x, 5);
  }

  void Update(float dt) {
    t += dt;

    const float cycle = fmod(t, CYCLE_LENGTH);
    const float cycle_ratio = cycle / CYCLE_LENGTH;

    shader.attach();
    shader.sendFloat("cycle_ratio", 1, &cycle_ratio, 1);

    renderTexture(gl.getDefaultTexture(), 0, 0, width, height);

    shader.detach();
  }

private:
  Shader shader;
};

int main(int, char**){
  Loop050 test;
  test.Run();

  return 0;
}
<|endoftext|>


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

#include "ltsh.h"

#include "maxp.h"

// LTSH - Linear Threshold
// http://www.microsoft.com/typography/otspec/ltsh.htm

namespace ots {

bool OpenTypeLTSH::Parse(const uint8_t *data, size_t length) {
  Buffer table(data, length);

  OpenTypeMAXP *maxp = dynamic_cast<OpenTypeMAXP*>(
      GetFont()->GetTable(OTS_TAG_MAXP));
  if (!maxp) {
    return Error("Missing maxp table from font needed by ltsh");
  }

  uint16_t num_glyphs = 0;
  if (!table.ReadU16(&this->version) ||
      !table.ReadU16(&num_glyphs)) {
    return Error("Failed to read ltsh header");
  }

  if (this->version != 0) {
    return Drop("bad version: %u", this->version);
  }

  if (num_glyphs != maxp->num_glyphs) {
    return Drop("bad num_glyphs: %u", num_glyphs);
  }

  this->ypels.reserve(num_glyphs);
  for (unsigned i = 0; i < num_glyphs; ++i) {
    uint8_t pel = 0;
    if (!table.ReadU8(&pel)) {
      return Error("Failed to read pixels for glyph %d", i);
    }
    this->ypels.push_back(pel);
  }

  return true;
}

bool OpenTypeLTSH::Serialize(OTSStream *out) {
  const uint16_t num_ypels = static_cast<uint16_t>(this->ypels.size());
  if (num_ypels != this->ypels.size() ||
      !out->WriteU16(this->version) ||
      !out->WriteU16(num_ypels)) {
    return Error("Failed to write pels size");
  }
  for (uint16_t i = 0; i < num_ypels; ++i) {
    if (!out->Write(&(this->ypels[i]), 1)) {
      return Error("Failed to write pixel size for glyph %d", i);
    }
  }

  return true;
}

bool OpenTypeLTSH::ShouldSerialize() {
  return Table::ShouldSerialize() &&
         // this table is not for CFF fonts.
         GetFont()->GetTable(OTS_TAG_GLYF) != NULL;
}

}  // namespace ots
<commit_msg>[ltsh] Improve error messages<commit_after>// Copyright (c) 2009-2017 The OTS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ltsh.h"

#include "maxp.h"

// LTSH - Linear Threshold
// http://www.microsoft.com/typography/otspec/ltsh.htm

namespace ots {

bool OpenTypeLTSH::Parse(const uint8_t *data, size_t length) {
  Buffer table(data, length);

  OpenTypeMAXP *maxp = dynamic_cast<OpenTypeMAXP*>(
      GetFont()->GetTable(OTS_TAG_MAXP));
  if (!maxp) {
    return Error("Required maxp table is missing");
  }

  uint16_t num_glyphs = 0;
  if (!table.ReadU16(&this->version) ||
      !table.ReadU16(&num_glyphs)) {
    return Error("Failed to read table header");
  }

  if (this->version != 0) {
    return Drop("Unsupported version: %u", this->version);
  }

  if (num_glyphs != maxp->num_glyphs) {
    return Drop("Bad numGlyphs: %u", num_glyphs);
  }

  this->ypels.reserve(num_glyphs);
  for (unsigned i = 0; i < num_glyphs; ++i) {
    uint8_t pel = 0;
    if (!table.ReadU8(&pel)) {
      return Error("Failed to read pixels for glyph %d", i);
    }
    this->ypels.push_back(pel);
  }

  return true;
}

bool OpenTypeLTSH::Serialize(OTSStream *out) {
  const uint16_t num_ypels = static_cast<uint16_t>(this->ypels.size());
  if (num_ypels != this->ypels.size() ||
      !out->WriteU16(this->version) ||
      !out->WriteU16(num_ypels)) {
    return Error("Failed to write table header");
  }
  for (uint16_t i = 0; i < num_ypels; ++i) {
    if (!out->Write(&(this->ypels[i]), 1)) {
      return Error("Failed to write pixel size for glyph %d", i);
    }
  }

  return true;
}

bool OpenTypeLTSH::ShouldSerialize() {
  return Table::ShouldSerialize() &&
         // this table is not for CFF fonts.
         GetFont()->GetTable(OTS_TAG_GLYF) != NULL;
}

}  // namespace ots
<|endoftext|>


<commit_before>#define GLEW_STATIC
#define RUN_GRAPHICS_DISPLAY 0x00;
#define GLM_FORCE_RADIANS

#include <GL/glew.h>
#include <GL/gl.h>
#include <SDL2/SDL.h>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include <iostream>
#include <memory>
#include <boost/program_options.hpp>

#include "common.h"
#include "GameWorld.h"

// Lousy global variables
const Uint8* keyboard_input;

SDL_Window * _window;

int window_width, window_height;
bool fullscreen = false;

/*
 * SDL timers run in separate threads.  In the timer thread
 * push an event onto the event queue.  This event signifies
 * to call display() from the thread in which the OpenGL
 * context was created.
 */
Uint32 tick(Uint32 interval, void *param)
{
	SDL_Event event;
	event.type = SDL_USEREVENT;
	event.user.code = RUN_GRAPHICS_DISPLAY;
	event.user.data1 = 0;
	event.user.data2 = 0;
	SDL_PushEvent(&event);
	return interval;
	std::cout << "tick" << std::endl;
}

struct SDLWindowDeleter
{
	inline void operator()(SDL_Window* window)
	{
		SDL_DestroyWindow(window);
	}
};

/*
 * Handles input
 */
void HandleInput(const std::shared_ptr<GameWorld> game_world)
{
	// Camera controller
	int x, y;
	SDL_PumpEvents();
	SDL_GetMouseState(&x, &y);
	SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
	SDL_WarpMouseInWindow(_window, window_width/2, window_height/2);
	SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
	SDL_PumpEvents();
	game_world->MoveCamera(glm::vec2(x,y), glm::vec2(window_width, window_height));

	// Update game_world camera
	if(keyboard_input[SDL_SCANCODE_W])
		game_world->CameraController(1); // forward
	if(keyboard_input[SDL_SCANCODE_A])
		game_world->CameraController(2); // left
	if(keyboard_input[SDL_SCANCODE_S])
		game_world->CameraController(3); // back
	if(keyboard_input[SDL_SCANCODE_D])
		game_world->CameraController(4); // right
	if(keyboard_input[SDL_SCANCODE_SPACE])
		game_world->CameraController(9); // player: +y ("fly" up)
	if(keyboard_input[SDL_SCANCODE_LCTRL])
		game_world->CameraController(10); // player: -y ("fly" down)

	if(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT))
		game_world->DoAction(1);
	if(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_RIGHT))
		game_world->DoAction(2);
	if(keyboard_input[SDL_SCANCODE_G])
		game_world->DoAction(3);
	if(keyboard_input[SDL_SCANCODE_H])
		game_world->DoAction(4);

	if(keyboard_input[SDL_SCANCODE_E])
		game_world->ChangeBlockDist(1);
	if(keyboard_input[SDL_SCANCODE_Q])
		game_world->ChangeBlockDist(-1);

	if(keyboard_input[SDL_SCANCODE_ESCAPE])
		SDL_Quit();
}

/*
 * Draws the game world and handles buffer switching.
 */
void Draw(const std::shared_ptr<SDL_Window> window, const std::shared_ptr<GameWorld> game_world)
{
	// Background colour for the window
	glClearColor(0.0f, 0.2f, 0.2f, 0.3f);
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	// Draw the gameworld
	game_world->Draw();

	// Swap buffers
	SDL_GL_SwapWindow(window.get());
}

/*
 * Handles the initialisation of the game world.
 * Configures the SDL window and initialises GLEW
 */
std::shared_ptr<SDL_Window> InitWorld()
{
	// Window properties
	std::shared_ptr<SDL_Window> window;

	// Glew will later ensure that OpenGL 3 *is* supported
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

	// Do double buffering in GL
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

	// Initialise SDL - when using C/C++ it's common to have to
	// initialise libraries by calling a function within them.
	if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_TIMER) < 0)
	{
		std::cout << "Failed to initialise SDL: " << SDL_GetError() << std::endl;
		return nullptr;
	}
	SDL_GetError();

	// When we close a window quit the SDL application
	atexit(SDL_Quit);

	SDL_ShowCursor(0);

	if(fullscreen)
	{
		SDL_DisplayMode display;
		SDL_GetCurrentDisplayMode(0, &display);
		window_width = display.w;
		window_height = display.h;
	}
	else
	{
		window_width = 1024;
		window_height = 768;
	}

	// Create a new window with an OpenGL surface
	_window = SDL_CreateWindow("BlockWorld"
							 , SDL_WINDOWPOS_CENTERED
							 , SDL_WINDOWPOS_CENTERED
							 , window_width
							 , window_height
							 , SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);

	if(fullscreen)
	{
		SDL_SetWindowFullscreen(_window, SDL_WINDOW_FULLSCREEN);
	}

	if(!_window)
	{
		std::cout << "Failed to create SDL window: " << SDL_GetError() << std::endl;
		return nullptr;
	}

	SDL_GLContext glContext = SDL_GL_CreateContext(_window);
	if (!glContext)
	{
		std::cout << "Failed to create OpenGL context: " << SDL_GetError() << std::endl;
		return nullptr;
	}

	// Initialise GLEW - an easy way to ensure OpenGl 3.0+
	// The *must* be done after we have set the video mode - otherwise we have no
	// OpenGL context to test.
	glewInit();
	if(!glewIsSupported("GL_VERSION_3_0"))
	{
		std::cerr << "OpenGL 3.0 not available" << std::endl;
		return nullptr;
	}

	// OpenGL settings
	glDisable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);

	window.reset(_window, SDL_DestroyWindow);
	return window;
}

ApplicationMode ParseOptions (int argc, char ** argv)
{
	namespace po = boost::program_options;

	po::options_description desc("Allowed options");
	desc.add_options()
		("help", "print this help message")
		("fullscreen", "Runs the game in fullscreen")
		("translate", "Show translation example (default)")
		("rotate", "Show rotation example")
		("scale", "Show scale example");

	po::variables_map vm;
	po::store(po::parse_command_line(argc, argv, desc), vm);
	po::notify(vm);

	if(vm.count("help"))
	{
		std::cout << desc << std::endl;
		exit(0);
	}

	if(vm.count("fullscreen"))
	{
		fullscreen = true;
	}

	if(vm.count("rotate"))
	{
		return ROTATE;
	}

	if(vm.count("scale"))
	{
		return SCALE;
	}

	// The default
	return TRANSFORM;
}

int main(int argc, char ** argv) {
	Uint32 delay = 1000/60; // in milliseconds

	auto mode = ParseOptions(argc, argv);
	auto window = InitWorld();
	auto game_world = std::make_shared<GameWorld>(mode);

	if(!window)
	{
		SDL_Quit();
	}

	keyboard_input = SDL_GetKeyboardState(NULL);

	// Call the function "tick" every delay milliseconds
	SDL_AddTimer(delay, tick, NULL);

	// Add the main event loop
	SDL_Event event;
	while (SDL_WaitEvent(&event))
	{
		switch (event.type)
		{
			case SDL_QUIT:
				SDL_Quit();
				break;
			case SDL_USEREVENT:
				Draw(window, game_world);
				HandleInput(game_world);
				break;
			default:
			  break;
		}
	}
}
<commit_msg>Remove tick output<commit_after>#define GLEW_STATIC
#define RUN_GRAPHICS_DISPLAY 0x00;
#define GLM_FORCE_RADIANS

#include <GL/glew.h>
#include <GL/gl.h>
#include <SDL2/SDL.h>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include <iostream>
#include <memory>
#include <boost/program_options.hpp>

#include "common.h"
#include "GameWorld.h"

// Lousy global variables
const Uint8* keyboard_input;

SDL_Window * _window;

int window_width, window_height;
bool fullscreen = false;

/*
 * SDL timers run in separate threads.  In the timer thread
 * push an event onto the event queue.  This event signifies
 * to call display() from the thread in which the OpenGL
 * context was created.
 */
Uint32 tick(Uint32 interval, void *param)
{
	SDL_Event event;
	event.type = SDL_USEREVENT;
	event.user.code = RUN_GRAPHICS_DISPLAY;
	event.user.data1 = 0;
	event.user.data2 = 0;
	SDL_PushEvent(&event);
	return interval;
}

struct SDLWindowDeleter
{
	inline void operator()(SDL_Window* window)
	{
		SDL_DestroyWindow(window);
	}
};

/*
 * Handles input
 */
void HandleInput(const std::shared_ptr<GameWorld> game_world)
{
	// Camera controller
	int x, y;
	SDL_PumpEvents();
	SDL_GetMouseState(&x, &y);
	SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
	SDL_WarpMouseInWindow(_window, window_width/2, window_height/2);
	SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
	SDL_PumpEvents();
	game_world->MoveCamera(glm::vec2(x,y), glm::vec2(window_width, window_height));

	// Update game_world camera
	if(keyboard_input[SDL_SCANCODE_W])
		game_world->CameraController(1); // forward
	if(keyboard_input[SDL_SCANCODE_A])
		game_world->CameraController(2); // left
	if(keyboard_input[SDL_SCANCODE_S])
		game_world->CameraController(3); // back
	if(keyboard_input[SDL_SCANCODE_D])
		game_world->CameraController(4); // right
	if(keyboard_input[SDL_SCANCODE_SPACE])
		game_world->CameraController(9); // player: +y ("fly" up)
	if(keyboard_input[SDL_SCANCODE_LCTRL])
		game_world->CameraController(10); // player: -y ("fly" down)

	if(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT))
		game_world->DoAction(1);
	if(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_RIGHT))
		game_world->DoAction(2);
	if(keyboard_input[SDL_SCANCODE_G])
		game_world->DoAction(3);
	if(keyboard_input[SDL_SCANCODE_H])
		game_world->DoAction(4);

	if(keyboard_input[SDL_SCANCODE_E])
		game_world->ChangeBlockDist(1);
	if(keyboard_input[SDL_SCANCODE_Q])
		game_world->ChangeBlockDist(-1);

	if(keyboard_input[SDL_SCANCODE_ESCAPE])
		SDL_Quit();
}

/*
 * Draws the game world and handles buffer switching.
 */
void Draw(const std::shared_ptr<SDL_Window> window, const std::shared_ptr<GameWorld> game_world)
{
	// Background colour for the window
	glClearColor(0.0f, 0.2f, 0.2f, 0.3f);
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	// Draw the gameworld
	game_world->Draw();

	// Swap buffers
	SDL_GL_SwapWindow(window.get());
}

/*
 * Handles the initialisation of the game world.
 * Configures the SDL window and initialises GLEW
 */
std::shared_ptr<SDL_Window> InitWorld()
{
	// Window properties
	std::shared_ptr<SDL_Window> window;

	// Glew will later ensure that OpenGL 3 *is* supported
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

	// Do double buffering in GL
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

	// Initialise SDL - when using C/C++ it's common to have to
	// initialise libraries by calling a function within them.
	if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_TIMER) < 0)
	{
		std::cout << "Failed to initialise SDL: " << SDL_GetError() << std::endl;
		return nullptr;
	}
	SDL_GetError();

	// When we close a window quit the SDL application
	atexit(SDL_Quit);

	SDL_ShowCursor(0);

	if(fullscreen)
	{
		SDL_DisplayMode display;
		SDL_GetCurrentDisplayMode(0, &display);
		window_width = display.w;
		window_height = display.h;
	}
	else
	{
		window_width = 1024;
		window_height = 768;
	}

	// Create a new window with an OpenGL surface
	_window = SDL_CreateWindow("BlockWorld"
							 , SDL_WINDOWPOS_CENTERED
							 , SDL_WINDOWPOS_CENTERED
							 , window_width
							 , window_height
							 , SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);

	if(fullscreen)
	{
		SDL_SetWindowFullscreen(_window, SDL_WINDOW_FULLSCREEN);
	}

	if(!_window)
	{
		std::cout << "Failed to create SDL window: " << SDL_GetError() << std::endl;
		return nullptr;
	}

	SDL_GLContext glContext = SDL_GL_CreateContext(_window);
	if (!glContext)
	{
		std::cout << "Failed to create OpenGL context: " << SDL_GetError() << std::endl;
		return nullptr;
	}

	// Initialise GLEW - an easy way to ensure OpenGl 3.0+
	// The *must* be done after we have set the video mode - otherwise we have no
	// OpenGL context to test.
	glewInit();
	if(!glewIsSupported("GL_VERSION_3_0"))
	{
		std::cerr << "OpenGL 3.0 not available" << std::endl;
		return nullptr;
	}

	// OpenGL settings
	glDisable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);

	window.reset(_window, SDL_DestroyWindow);
	return window;
}

ApplicationMode ParseOptions (int argc, char ** argv)
{
	namespace po = boost::program_options;

	po::options_description desc("Allowed options");
	desc.add_options()
		("help", "print this help message")
		("fullscreen", "Runs the game in fullscreen")
		("translate", "Show translation example (default)")
		("rotate", "Show rotation example")
		("scale", "Show scale example");

	po::variables_map vm;
	po::store(po::parse_command_line(argc, argv, desc), vm);
	po::notify(vm);

	if(vm.count("help"))
	{
		std::cout << desc << std::endl;
		exit(0);
	}

	if(vm.count("fullscreen"))
	{
		fullscreen = true;
	}

	if(vm.count("rotate"))
	{
		return ROTATE;
	}

	if(vm.count("scale"))
	{
		return SCALE;
	}

	// The default
	return TRANSFORM;
}

int main(int argc, char ** argv) {
	Uint32 delay = 1000/60; // in milliseconds

	auto mode = ParseOptions(argc, argv);
	auto window = InitWorld();
	auto game_world = std::make_shared<GameWorld>(mode);

	if(!window)
	{
		SDL_Quit();
	}

	keyboard_input = SDL_GetKeyboardState(NULL);

	// Call the function "tick" every delay milliseconds
	SDL_AddTimer(delay, tick, NULL);

	// Add the main event loop
	SDL_Event event;
	while (SDL_WaitEvent(&event))
	{
		switch (event.type)
		{
			case SDL_QUIT:
				SDL_Quit();
				break;
			case SDL_USEREVENT:
				Draw(window, game_world);
				HandleInput(game_world);
				break;
			default:
			  break;
		}
	}
}
<|endoftext|>


<commit_before>/*
 * main.cc
 */
#include <unistd.h>
#include <fstream>
#include <string>

#include "qv/dynkin.h"
#include "qv/quiver_matrix.h"

#include "class_size_slave.h"
#include "fast_mmi_slave.h"
#include "fast_mmi_master.h"
#include "mpi_tags.h"
#include "slow_check_master.h"

void usage() {
	std::cout << "qvmmi [-sf] [-d diagram | -m matrix | -i input ]" << std::endl;
}

bool valid_dynkin(std::string matrix) {
	return cluster::dynkin::MAP.count(matrix) != 0;
}

QuiverMatrix get_matrix(bool dynkin, std::string matrix) {
	if(dynkin) {
		return cluster::dynkin::MAP.at(matrix);
	}
	return QuiverMatrix(matrix);
}
int main(int argc, char* argv[]) {

	MPI::Init(argc, argv);
	int rank = MPI::COMM_WORLD.Get_rank();

	int opt;
	bool slow = false;
	bool fast = false;
	bool dynkin = false;
	std::string matrix;
	std::string input;
	while ((opt = getopt (argc, argv, "fsd:m:i:")) != -1){
		switch (opt) {
			case 'f':
				fast = true;
				break;
			case 's':
				slow = true;
				break;
			case 'd':
				matrix = optarg;
				dynkin = true;
				break;
			case 'm':
				matrix = optarg;
				break;
			case 'i':
				input = optarg;
				break;
			case '?':
				return 1;
			default:
				return 2;
		}
	}

	if(slow) {
		if(rank == MASTER) {
			if(input.empty()){
				qvmmi::SlowCheckMaster master;
				master.run();
			} else {
				std::ifstream file;
				file.open(input);
				if(!file.is_open()) {
					std::cout << "Error opening file "<< input << std::endl;
					MPI::Finalize();
					return 1;
				}
				qvmmi::SlowCheckMaster master(file);
				master.run();
				file.close();
			}
		} else {
			qvmmi::ClassSizeSlave slave;
			slave.run();
		}

	} else if(fast) {
		if(rank == MASTER) {
			if(dynkin && !valid_dynkin(matrix)){
				std::cout << "Invalid matrix" << std::endl;
				MPI::Finalize();
				return 1;
			}
			QuiverMatrix mat = get_matrix(dynkin, matrix);
			qvmmi::FastMMIMaster m(mat);
			m.run();
		} else {
			if(dynkin && !valid_dynkin(matrix)){
				MPI::Finalize();
				return 1;
			}
			qvmmi::FastMMISlave s;
			s.run();

		}
	} else {
		usage();
		std::cout << "Specify an option" << std::endl;
	}

	MPI::Finalize();
	return 0;
}

<commit_msg>Reorders includes for intelmpi.<commit_after>/*
 * main.cc
 */
#include "class_size_slave.h"
#include "fast_mmi_slave.h"
#include "slow_check_master.h"
#include "fast_mmi_master.h"

#include <unistd.h>
#include <fstream>
#include <string>

#include "qv/dynkin.h"
#include "qv/quiver_matrix.h"

#include "mpi_tags.h"

void usage() {
	std::cout << "qvmmi [-sf] [-d diagram | -m matrix | -i input ]" << std::endl;
}

bool valid_dynkin(std::string matrix) {
	return cluster::dynkin::MAP.count(matrix) != 0;
}

QuiverMatrix get_matrix(bool dynkin, std::string matrix) {
	if(dynkin) {
		return cluster::dynkin::MAP.at(matrix);
	}
	return QuiverMatrix(matrix);
}
int main(int argc, char* argv[]) {

	MPI::Init(argc, argv);
	int rank = MPI::COMM_WORLD.Get_rank();

	int opt;
	bool slow = false;
	bool fast = false;
	bool dynkin = false;
	std::string matrix;
	std::string input;
	while ((opt = getopt (argc, argv, "fsd:m:i:")) != -1){
		switch (opt) {
			case 'f':
				fast = true;
				break;
			case 's':
				slow = true;
				break;
			case 'd':
				matrix = optarg;
				dynkin = true;
				break;
			case 'm':
				matrix = optarg;
				break;
			case 'i':
				input = optarg;
				break;
			case '?':
				return 1;
			default:
				return 2;
		}
	}

	if(slow) {
		if(rank == MASTER) {
			if(input.empty()){
				qvmmi::SlowCheckMaster master;
				master.run();
			} else {
				std::ifstream file;
				file.open(input);
				if(!file.is_open()) {
					std::cout << "Error opening file "<< input << std::endl;
					MPI::Finalize();
					return 1;
				}
				qvmmi::SlowCheckMaster master(file);
				master.run();
				file.close();
			}
		} else {
			qvmmi::ClassSizeSlave slave;
			slave.run();
		}

	} else if(fast) {
		if(rank == MASTER) {
			if(dynkin && !valid_dynkin(matrix)){
				std::cout << "Invalid matrix" << std::endl;
				MPI::Finalize();
				return 1;
			}
			QuiverMatrix mat = get_matrix(dynkin, matrix);
			qvmmi::FastMMIMaster m(mat);
			m.run();
		} else {
			if(dynkin && !valid_dynkin(matrix)){
				MPI::Finalize();
				return 1;
			}
			qvmmi::FastMMISlave s;
			s.run();

		}
	} else {
		usage();
		std::cout << "Specify an option" << std::endl;
	}

	MPI::Finalize();
	return 0;
}

<|endoftext|>


<commit_before>#include "NTClient.h"
#include "colors.h"
#include "json.hpp"

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

void initBot(string username, string password, int wpm, double acc) {
	NTClient nclient = NTClient(wpm, acc);
	nclient.login(username, password);
	nclient.connect();
}
void initlog(string msg) {
	cout << CLR_GRN << STYLE_BOLD << "[INIT] " << CLR_RESET << CLR_WHT << msg << CLR_RESET;
}
void errlog(string msg) {
	cout << CLR_RED << STYLE_BOLD << "[ERR!] " << CLR_RESET << CLR_WHT << msg << CLR_RESET;
}
int main(int argc, char** argv) {
	bool useCustomConfig = false;
	string customConfig;
	for (int i = 0; i < argc; ++i) {
		string arg = string(argv[i]);
		if (i != 0) {
			if (arg == "--help" || arg == "-h") {
				cout << "UltraType++ - An open-source command line NitroType bot." << endl
				<< "GitHub URL: https://github.com/ultratype/UltraTypePP" << endl
				<< "Version: 1.0" << endl
				<< "Arguments:" << endl
				<< "	--help or -h: Display this help message." << endl
				<< "	--config <filename> or -c <filename>: Load the config from the specified file." << endl;
				return 0;
			}
		}
	}
	srand(static_cast<unsigned int>(time(0)));
	ifstream configf;
	configf.exceptions(std::ios::failbit | std::ios::badbit);
	try {
		configf.open("config.json");
	} catch(const exception& e) {
		errlog("Failed to open the JSON config. For help, read the UltraType++ repository README.\n");
		return 1;
	}
	return 0;
}<commit_msg>Add custom config flags<commit_after>#include "NTClient.h"
#include "colors.h"
#include "json.hpp"

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

void initBot(string username, string password, int wpm, double acc) {
	NTClient nclient = NTClient(wpm, acc);
	nclient.login(username, password);
	nclient.connect();
}
void initlog(string msg) {
	cout << CLR_GRN << STYLE_BOLD << "[INIT] " << CLR_RESET << CLR_WHT << msg << CLR_RESET;
}
void errlog(string msg) {
	cout << CLR_RED << STYLE_BOLD << "[ERR!] " << CLR_RESET << CLR_WHT << msg << CLR_RESET;
}
int main(int argc, char** argv) {
	srand(static_cast<unsigned int>(time(0)));
	bool useCustomConfig = false;
	string customConfig;
	for (int i = 0; i < argc; ++i) {
		string arg = string(argv[i]);
		if (i != 0) {
			if (arg == "--help" || arg == "-h") {
				cout << "UltraType++ - An open-source command line NitroType bot." << endl
				<< "GitHub URL: https://github.com/ultratype/UltraTypePP" << endl
				<< "Version: 1.0" << endl
				<< "Arguments:" << endl
				<< "	--help or -h: Display this help message." << endl
				<< "	--config <filename> or -c <filename>: Load the config from the specified file." << endl;
				return 0;
			} else if (arg == "--config" || arg == "-c") {
				customConfig = string(argv[i + 1]);
				useCustomConfig = true;
			}
		}
	}
	ifstream configf;
	configf.exceptions(std::ios::failbit | std::ios::badbit);
	initlog("Attempting to read config file...\n");
	try {
		if (useCustomConfig) {
			configf.open(customConfig.c_str());
		} else {
			configf.open("config.json");
		}
	} catch(const exception& e) {
		errlog("Failed to open the JSON config. For help, read the UltraType++ repository README, or use --help.\n");
		return 1;
	}
	return 0;
}<|endoftext|>


<commit_before><commit_msg>Trying to delete an index that does not exists would attempt to add status code 404 on a NULL object<commit_after><|endoftext|>


<commit_before>#include <cstdio>

#include "gameboy.h"
#include "cartridge.h"
#include "video/screen.h"
#include "util/log.h"

#include "video/screens/null_screen.h"
#include "video/screens/sfml_screen.h"

int main(int argc, char* argv[]) {
    if (argc != 2) {
        log_error("Please provide a ROM file to run")
        return 0;
    }

    log_set_level(LogLevel::Trace);

    std::string rom_name = argv[1];
    log_info("Loading rom from file: %s", rom_name.c_str());

    Cartridge cartridge(rom_name);
    SFMLScreen screen;
    Gameboy gameboy(screen, cartridge);

    gameboy.run();
}
<commit_msg>Reorganise main.cc<commit_after>#include "gameboy.h"
#include "cartridge.h"
#include "video/screen.h"
#include "util/log.h"

#include "video/screens/null_screen.h"
#include "video/screens/sfml_screen.h"

int main(int argc, char* argv[]) {
    log_set_level(LogLevel::Trace);

    if (argc != 2) {
        log_error("Please provide a ROM file to run")
        return 1;
    }

    std::string rom_name = argv[1];
    Cartridge cartridge(rom_name);

    SFMLScreen screen;

    Gameboy gameboy(screen, cartridge);
    gameboy.run();
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <time.h>
#include <cassert>
#include <functional>
#include <iostream>
#include <string>
#include <variant>
#include <vector>

#include <mpd/connection.h>

#include "args.h"
#include "ashuffle.h"
#include "getpass.h"
#include "load.h"
#include "mpd_client.h"
#include "shuffle.h"

using namespace ashuffle;

namespace {

std::unique_ptr<Loader> BuildLoader(mpd::MPD* mpd, const Options& opts) {
    if (opts.file_in != nullptr && opts.check_uris) {
        return std::make_unique<FileMPDLoader>(mpd, opts.ruleset, opts.group_by,
                                               opts.file_in);
    } else if (opts.file_in != nullptr) {
        return std::make_unique<FileLoader>(opts.file_in);
    }

    return std::make_unique<MPDLoader>(mpd, opts.ruleset, opts.group_by);
}

}  // namespace

int main(int argc, const char* argv[]) {
    std::variant<Options, ParseError> parse =
        Options::ParseFromC(*mpd::client::Parser(), argv, argc);
    if (ParseError* err = std::get_if<ParseError>(&parse); err != nullptr) {
        switch (err->type) {
            case ParseError::Type::kUnknown:
                std::cerr << "unknown option parsing error. Please file a bug "
                          << "at https://github.com/joshkunz/ashuffle"
                          << std::endl;
                break;
            case ParseError::Type::kHelp:
                // We always print the help, so just break here.
                break;
            case ParseError::Type::kGeneric:
                std::cerr << "error: " << err->msg << std::endl;
                break;
            default:
                assert(false && "unreachable");
        }
        std::cerr << DisplayHelp;
        exit(EXIT_FAILURE);
    }

    Options options = std::move(std::get<Options>(parse));

    if (!options.check_uris && !options.group_by.empty()) {
        std::cerr << "-g/--group-by not supported with no-check" << std::endl;
        exit(EXIT_FAILURE);
    }

    std::function<std::string()> pass_f = [] {
        return GetPass(stdin, stdout, "mpd password: ");
    };
    /* attempt to connect to MPD */
    std::unique_ptr<mpd::MPD> mpd =
        Connect(*mpd::client::Dialer(), options, pass_f);

    ShuffleChain songs((size_t)options.tweak.window_size);

    {
        // We construct the loader in a new scope, since loaders can
        // consume a lot of memory.
        std::unique_ptr<Loader> loader = BuildLoader(mpd.get(), options);
        loader->Load(&songs);
    }

    // For integration testing, we sometimes just want to have ashuffle
    // dump the list of songs in its shuffle chain.
    if (options.test.print_all_songs_and_exit) {
        bool first = true;
        for (auto&& group : songs.Items()) {
            if (!first) {
                std::cout << "---" << std::endl;
            }
            first = false;
            for (auto&& song : group) {
                std::cout << song << std::endl;
            }
        }
        exit(EXIT_SUCCESS);
    }

    if (songs.Len() == 0) {
        std::cerr << "Song pool is empty." << std::endl;
        exit(EXIT_FAILURE);
    }

    if (!options.group_by.empty()) {
        std::cout << absl::StrFormat("Picking from %u groups (%u songs).",
                                     songs.Len(), songs.LenURIs())
                  << std::endl;
    } else {
        std::cout << "Picking random songs out of a pool of " << songs.Len()
                  << "." << std::endl;
    }

    /* do the main action */
    if (options.queue_only) {
        size_t number_of_songs;
        for (unsigned i = 0; i < options.queue_only; i++) {
            auto& picked_songs = songs.Pick();
            number_of_songs += picked_songs.size();
            mpd->Add(picked_songs);
        }

        /* print number of songs or groups (and songs) added */
        std::cout << absl::StrFormat(
            "Added %u %s%s", options.queue_only,
            options.group_by.empty() ? "song" : "group",
            options.queue_only > 1 ? "s" : "");
        if (!options.group_by.empty()) {
            std::cout << absl::StrFormat(" (%u songs)", number_of_songs);
        }
        std::cout << "." << std::endl;
    } else {
        Loop(mpd.get(), &songs, options);
    }

    return 0;
}
<commit_msg>cleanup: Fix uninitialized use of `number_of_songs`.<commit_after>#include <stdlib.h>
#include <time.h>
#include <cassert>
#include <functional>
#include <iostream>
#include <string>
#include <variant>
#include <vector>

#include <mpd/connection.h>

#include "args.h"
#include "ashuffle.h"
#include "getpass.h"
#include "load.h"
#include "mpd_client.h"
#include "shuffle.h"

using namespace ashuffle;

namespace {

std::unique_ptr<Loader> BuildLoader(mpd::MPD* mpd, const Options& opts) {
    if (opts.file_in != nullptr && opts.check_uris) {
        return std::make_unique<FileMPDLoader>(mpd, opts.ruleset, opts.group_by,
                                               opts.file_in);
    } else if (opts.file_in != nullptr) {
        return std::make_unique<FileLoader>(opts.file_in);
    }

    return std::make_unique<MPDLoader>(mpd, opts.ruleset, opts.group_by);
}

}  // namespace

int main(int argc, const char* argv[]) {
    std::variant<Options, ParseError> parse =
        Options::ParseFromC(*mpd::client::Parser(), argv, argc);
    if (ParseError* err = std::get_if<ParseError>(&parse); err != nullptr) {
        switch (err->type) {
            case ParseError::Type::kUnknown:
                std::cerr << "unknown option parsing error. Please file a bug "
                          << "at https://github.com/joshkunz/ashuffle"
                          << std::endl;
                break;
            case ParseError::Type::kHelp:
                // We always print the help, so just break here.
                break;
            case ParseError::Type::kGeneric:
                std::cerr << "error: " << err->msg << std::endl;
                break;
            default:
                assert(false && "unreachable");
        }
        std::cerr << DisplayHelp;
        exit(EXIT_FAILURE);
    }

    Options options = std::move(std::get<Options>(parse));

    if (!options.check_uris && !options.group_by.empty()) {
        std::cerr << "-g/--group-by not supported with no-check" << std::endl;
        exit(EXIT_FAILURE);
    }

    std::function<std::string()> pass_f = [] {
        return GetPass(stdin, stdout, "mpd password: ");
    };
    /* attempt to connect to MPD */
    std::unique_ptr<mpd::MPD> mpd =
        Connect(*mpd::client::Dialer(), options, pass_f);

    ShuffleChain songs((size_t)options.tweak.window_size);

    {
        // We construct the loader in a new scope, since loaders can
        // consume a lot of memory.
        std::unique_ptr<Loader> loader = BuildLoader(mpd.get(), options);
        loader->Load(&songs);
    }

    // For integration testing, we sometimes just want to have ashuffle
    // dump the list of songs in its shuffle chain.
    if (options.test.print_all_songs_and_exit) {
        bool first = true;
        for (auto&& group : songs.Items()) {
            if (!first) {
                std::cout << "---" << std::endl;
            }
            first = false;
            for (auto&& song : group) {
                std::cout << song << std::endl;
            }
        }
        exit(EXIT_SUCCESS);
    }

    if (songs.Len() == 0) {
        std::cerr << "Song pool is empty." << std::endl;
        exit(EXIT_FAILURE);
    }

    if (!options.group_by.empty()) {
        std::cout << absl::StrFormat("Picking from %u groups (%u songs).",
                                     songs.Len(), songs.LenURIs())
                  << std::endl;
    } else {
        std::cout << "Picking random songs out of a pool of " << songs.Len()
                  << "." << std::endl;
    }

    if (options.queue_only) {
        size_t number_of_songs = 0;
        for (unsigned i = 0; i < options.queue_only; i++) {
            auto& picked_songs = songs.Pick();
            number_of_songs += picked_songs.size();
            mpd->Add(picked_songs);
        }

        /* print number of songs or groups (and songs) added */
        std::cout << absl::StrFormat(
            "Added %u %s%s", options.queue_only,
            options.group_by.empty() ? "song" : "group",
            options.queue_only > 1 ? "s" : "");
        if (!options.group_by.empty()) {
            std::cout << absl::StrFormat(" (%u songs)", number_of_songs);
        }
        std::cout << "." << std::endl;
    } else {
        Loop(mpd.get(), &songs, options);
    }

    return 0;
}
<|endoftext|>