<commit_before>
// =-=-=-=-=-=-=-
#include "apiHeaderAll.hpp"
#include "msParam.hpp"
#include "reGlobalsExtern.hpp"
#include "irods_ms_plugin.hpp"

// =-=-=-=-=-=-=-
// STL Includes
#include <string>
#include <iostream>

// =-=-=-=-=-=-=-
// cURL Includes
#include <curl/curl.h>
#include <curl/easy.h>

typedef struct writeData_t {
    char path[MAX_NAME_LEN];
    int desc;
    rsComm_t *rsComm;
} writeData_t;

typedef struct readData_t {
  char path[MAX_NAME_LEN];
  FILE *fd;
} readData_t;

class irodsCurl {
private:
    // iRODS serv, char *destPath er handle
    rsComm_t *rsComm;

    // cURL handle
    CURL *curl;

public:
    irodsCurl( rsComm_t *comm ) {
        rsComm = comm;

        curl = curl_easy_init();
        if ( !curl ) {
            rodsLog( LOG_ERROR, "irodsCurl: %s", curl_easy_strerror( CURLE_FAILED_INIT ) );
        }
    }

    ~irodsCurl() {
        if ( curl ) {
            curl_easy_cleanup( curl );
        }
    }

    //Gets file name from a path
    char *getName (const char *path) {

	char tmpPath[strlen(path)]; //FIXME: does tmpPath do anything? why do we have this?

	strcpy(tmpPath, path);

        char* p;

        char* outStr;
        outStr = (char*)malloc(strlen(path));

        p = strrchr (tmpPath, '/');

       	snprintf(outStr, strlen(path), "%s", p +1);

	return outStr;
}

    int get( char *url, char *sourcePath, char *destPath, char *ext) {

	CURL *curl;
	CURLcode res = CURLE_OK;
        writeData_t writeData;	                // the "file descriptor" for our destination object
        openedDataObjInp_t openedTarget;	// for closing iRODS object after writing

        readData_t readData;

        int status;

	struct curl_httppost *formpost=NULL;
	struct curl_httppost *lastptr=NULL;

	curl_global_init(CURL_GLOBAL_ALL);

        /* Fill in the file upload field */
        curl_formadd(&formpost,
                &lastptr,
                CURLFORM_COPYNAME, "output_format",
                CURLFORM_COPYCONTENTS, ext,
                CURLFORM_END);

        /* Fill in the filename field */
        curl_formadd(&formpost,
                &lastptr,
                CURLFORM_COPYNAME, "file",
                CURLFORM_FILENAME, getName(sourcePath),
                CURLFORM_STREAM, &readData,
                CURLFORM_CONTENTSLENGTH, 100,  //This needs to be the size of the upload
                CURLFORM_CONTENTTYPE, "application/octet-stream",
                CURLFORM_END);

        // Zero fill openedDataObjInp
        memset( &openedTarget, 0, sizeof( openedDataObjInp_t ) );

        // Set up writeData
        snprintf(writeData.path, MAX_NAME_LEN, "%s", destPath);
        writeData.desc = 0;	                 // the object is yet to be created
        writeData.rsComm = rsComm;

        // Set up writeDataInp
        snprintf(readData.path, MAX_NAME_LEN, "%s", sourcePath);
        readData.fd = 0;	// the object is yet to be created

        // Set up easy handler
 	curl = curl_easy_init();

	/* what URL that receives this POST */
        curl_easy_setopt(curl, CURLOPT_URL, url);

        curl_easy_setopt(curl, CURLOPT_READFUNCTION, &irodsCurl::my_read_obj);
        curl_easy_setopt(curl, CURLOPT_READDATA, &readData);
        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &irodsCurl::my_write_obj);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &writeData);

        // CURL call
        res = curl_easy_perform( curl );

        // Some error logging
        if ( res != CURLE_OK ) {
            rodsLog( LOG_ERROR, "irodsCurl::get: cURL error: %s", curl_easy_strerror( res ) );
        }

        // close iRODS object
        if (writeData.desc) {
            openedTarget.l1descInx = writeData.desc;
            status = rsDataObjClose(rsComm, &openedTarget);
            if (status < 0) {
                rodsLog(LOG_ERROR, "irodsCurl::get: rsDataObjClose failed for %s, status = %d",
                         writeData.path, status);
            }
        }

        /* then cleanup the formpost chain */
        curl_formfree(formpost);

        return res;
    }

    static size_t my_read_obj(void *buffer, size_t size, size_t nmemb, void* userp) {
        struct readData_t *readData = (struct readData_t *) userp;

        if (!readData) {
            return -11;
        }

        if (!readData->fd) {
            readData->fd = fopen(readData->path, "r");
        }

        return fread(buffer, size, nmemb, readData->fd);
    }

    // Custom callback function for the curl handler, to write to an iRODS object
    static size_t my_write_obj(void *buffer, size_t size, size_t nmemb, writeData_t *writeData) {
        dataObjInp_t file;	// input struct for rsDataObjCreate
        openedDataObjInp_t openedFile;	// input struct for rsDataObjWrite
        bytesBuf_t bytesBuf;	// input buffer for rsDataObjWrite
        size_t written;	// return value

        int desc;

        // Make sure we have something to write to
        if (!writeData) {
            rodsLog( LOG_ERROR, "my_write_obj: writeData is NULL, status = %d", SYS_INTERNAL_NULL_INPUT_ERR );
            return SYS_INTERNAL_NULL_INPUT_ERR;
        }

        // Zero fill input structs
        memset( &file, 0, sizeof( dataObjInp_t ) );
        memset( &openedFile, 0, sizeof( openedDataObjInp_t ) );

        // If this is the first call we need to create our data object before writing to it
        if (!writeData->desc) {
            strncpy(file.objPath, writeData->path, MAX_NAME_LEN);

            // Overwrite existing file (for this tutorial only, in case the example has been run before)
            addKeyVal(&file.condInput, FORCE_FLAG_KW, "");

            writeData->desc = rsDataObjCreate(writeData->rsComm, &file);

            // No create?
            if ( writeData->desc <= 2 ) {
                rodsLog( LOG_ERROR, "my_write_obj: rsDataObjCreate failed for %s, status = %d", file.objPath, writeData->desc);
                return (writeData->desc);
            }
        }

        // Set up input buffer for rsDataObjWrite
        bytesBuf.len = (int)(size * nmemb);
        bytesBuf.buf = buffer;

        // Set up input struct for rsDataObjWrite
	openedFile.l1descInx = writeData->desc;
        openedFile.len = bytesBuf.len;

        // Write to data object
        written = rsDataObjWrite(writeData->rsComm, &openedFile, &bytesBuf);

        return (written);
    }

}; // class irodsCurl

extern "C" {

    int irods_curl_get( msParam_t* url, msParam_t* source_obj, msParam_t* ext_obj,
                                        msParam_t* dest_obj, ruleExecInfo_t* rei ) {
        dataObjInp_t destObjInp, *myDestObjInp;	/* for parsing input object */

        // Sanity checks
        if ( !rei || !rei->rsComm ) {
            rodsLog( LOG_ERROR, "irods_curl_get: Input rei or rsComm is NULL." );
            return ( SYS_INTERNAL_NULL_INPUT_ERR );
        }

	// get destination path from sourcePath and exten.
	char *sourceStr = parseMspForStr(source_obj);
	char *extStr = parseMspForStr(ext_obj);

	char *source = "/tempZone/home/public/new.png";

	char tmpSource[strlen(source) + 10];

	strcpy(tmpSource, source);

    	char *lastdot = strrchr (tmpSource, '.');
	char *lastsep = ('/' == 0) ? NULL : strrchr (tmpSource, '/');

	if (lastdot != NULL)
	{
        // and it's before the extenstion separator.

        	if (lastsep != NULL)
		{
            		if (lastsep < lastdot)
			{
                	// then remove it.

                	*lastdot = '\0';
            		}
        	}
		else
		{
            	// Has extension separator with no path separator.

            	*lastdot = '\0';
        	}
    	}
        char destStr[strlen(source)+10];

	snprintf(destStr, strlen(source) + 10, "%s%s%s", tmpSource, ".", extStr);

	fillStrInMsParam(dest_obj, destStr);

        // Get path of destination object
        rei->status = parseMspForDataObjInp( dest_obj, &destObjInp, &myDestObjInp, 0 );
        if ( rei->status < 0 ) {
            rodsLog( LOG_ERROR, "irods_curl_get: Input object error. status = %d", rei->status );
            return ( rei->status );
        }

        // Create irodsCurl instance
        irodsCurl myCurl( rei->rsComm );

        // Call irodsCurl::get

        rei->status = myCurl.get( parseMspForStr( url ), sourceStr,  destObjInp.objPath, extStr);

        // Done
        return rei->status;

    }

// =-=-=-=-=-=-=-
// 2. Create the plugin factory function which will return a microservice
// table entry
    irods::ms_table_entry* plugin_factory() {
        // =-=-=-=-=-=-=-
        // 3. allocate a microservice plugin which takes the number of function
        // params as a parameter to the constructor
        irods::ms_table_entry* msvc = new irods::ms_table_entry( 4 );

        // =-=-=-=-=-=-=-
        // 4. add the microservice function as an operation to the plugin
        // the first param is the name / key of the operation, the second
        // is the name of the function which will be the microservice
        msvc->add_operation( "irods_curl_get", "irods_curl_get" );

        // =-=-=-=-=-=-=-
        // 5. return the newly created microservice plugin
        return msvc;
    }
}	// extern "C"
<commit_msg>Added FIXME message<commit_after>
// =-=-=-=-=-=-=-
#include "apiHeaderAll.hpp"
#include "msParam.hpp"
#include "reGlobalsExtern.hpp"
#include "irods_ms_plugin.hpp"

// =-=-=-=-=-=-=-
// STL Includes
#include <string>
#include <iostream>

// =-=-=-=-=-=-=-
// cURL Includes
#include <curl/curl.h>
#include <curl/easy.h>

typedef struct writeData_t {
    char path[MAX_NAME_LEN];
    int desc;
    rsComm_t *rsComm;
} writeData_t;

typedef struct readData_t {
  char path[MAX_NAME_LEN];
  FILE *fd;
} readData_t;

class irodsCurl {
private:
    // iRODS serv, char *destPath er handle
    rsComm_t *rsComm;

    // cURL handle
    CURL *curl;

public:
    irodsCurl( rsComm_t *comm ) {
        rsComm = comm;

        curl = curl_easy_init();
        if ( !curl ) {
            rodsLog( LOG_ERROR, "irodsCurl: %s", curl_easy_strerror( CURLE_FAILED_INIT ) );
        }
    }

    ~irodsCurl() {
        if ( curl ) {
            curl_easy_cleanup( curl );
        }
    }

    //Gets file name from a path
    char *getName (const char *path) {

	char tmpPath[strlen(path)]; //FIXME: does tmpPath do anything? why do we have this?

	strcpy(tmpPath, path);

        char* p;

        char* outStr;
        outStr = (char*)malloc(strlen(path));  //FIXME: should this malloc one extra byte for the null terminator?

        p = strrchr (tmpPath, '/');

       	snprintf(outStr, strlen(path), "%s", p +1);

	return outStr;
}

    int get( char *url, char *sourcePath, char *destPath, char *ext) {

	CURL *curl;
	CURLcode res = CURLE_OK;
        writeData_t writeData;	                // the "file descriptor" for our destination object
        openedDataObjInp_t openedTarget;	// for closing iRODS object after writing

        readData_t readData;

        int status;

	struct curl_httppost *formpost=NULL;
	struct curl_httppost *lastptr=NULL;

	curl_global_init(CURL_GLOBAL_ALL);

        /* Fill in the file upload field */
        curl_formadd(&formpost,
                &lastptr,
                CURLFORM_COPYNAME, "output_format",
                CURLFORM_COPYCONTENTS, ext,
                CURLFORM_END);

        /* Fill in the filename field */
        curl_formadd(&formpost,
                &lastptr,
                CURLFORM_COPYNAME, "file",
                CURLFORM_FILENAME, getName(sourcePath),
                CURLFORM_STREAM, &readData,
                CURLFORM_CONTENTSLENGTH, 100,  //This needs to be the size of the upload
                CURLFORM_CONTENTTYPE, "application/octet-stream",
                CURLFORM_END);

        // Zero fill openedDataObjInp
        memset( &openedTarget, 0, sizeof( openedDataObjInp_t ) );

        // Set up writeData
        snprintf(writeData.path, MAX_NAME_LEN, "%s", destPath);
        writeData.desc = 0;	                 // the object is yet to be created
        writeData.rsComm = rsComm;

        // Set up writeDataInp
        snprintf(readData.path, MAX_NAME_LEN, "%s", sourcePath);
        readData.fd = 0;	// the object is yet to be created

        // Set up easy handler
 	curl = curl_easy_init();

	/* what URL that receives this POST */
        curl_easy_setopt(curl, CURLOPT_URL, url);

        curl_easy_setopt(curl, CURLOPT_READFUNCTION, &irodsCurl::my_read_obj);
        curl_easy_setopt(curl, CURLOPT_READDATA, &readData);
        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &irodsCurl::my_write_obj);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &writeData);

        // CURL call
        res = curl_easy_perform( curl );

        // Some error logging
        if ( res != CURLE_OK ) {
            rodsLog( LOG_ERROR, "irodsCurl::get: cURL error: %s", curl_easy_strerror( res ) );
        }

        // close iRODS object
        if (writeData.desc) {
            openedTarget.l1descInx = writeData.desc;
            status = rsDataObjClose(rsComm, &openedTarget);
            if (status < 0) {
                rodsLog(LOG_ERROR, "irodsCurl::get: rsDataObjClose failed for %s, status = %d",
                         writeData.path, status);
            }
        }

        /* then cleanup the formpost chain */
        curl_formfree(formpost);

        return res;
    }

    static size_t my_read_obj(void *buffer, size_t size, size_t nmemb, void* userp) {
        struct readData_t *readData = (struct readData_t *) userp;

        if (!readData) {
            return -11;
        }

        if (!readData->fd) {
            readData->fd = fopen(readData->path, "r");
        }

        return fread(buffer, size, nmemb, readData->fd);
    }

    // Custom callback function for the curl handler, to write to an iRODS object
    static size_t my_write_obj(void *buffer, size_t size, size_t nmemb, writeData_t *writeData) {
        dataObjInp_t file;	// input struct for rsDataObjCreate
        openedDataObjInp_t openedFile;	// input struct for rsDataObjWrite
        bytesBuf_t bytesBuf;	// input buffer for rsDataObjWrite
        size_t written;	// return value

        int desc;

        // Make sure we have something to write to
        if (!writeData) {
            rodsLog( LOG_ERROR, "my_write_obj: writeData is NULL, status = %d", SYS_INTERNAL_NULL_INPUT_ERR );
            return SYS_INTERNAL_NULL_INPUT_ERR;
        }

        // Zero fill input structs
        memset( &file, 0, sizeof( dataObjInp_t ) );
        memset( &openedFile, 0, sizeof( openedDataObjInp_t ) );

        // If this is the first call we need to create our data object before writing to it
        if (!writeData->desc) {
            strncpy(file.objPath, writeData->path, MAX_NAME_LEN);

            // Overwrite existing file (for this tutorial only, in case the example has been run before)
            addKeyVal(&file.condInput, FORCE_FLAG_KW, "");

            writeData->desc = rsDataObjCreate(writeData->rsComm, &file);

            // No create?
            if ( writeData->desc <= 2 ) {
                rodsLog( LOG_ERROR, "my_write_obj: rsDataObjCreate failed for %s, status = %d", file.objPath, writeData->desc);
                return (writeData->desc);
            }
        }

        // Set up input buffer for rsDataObjWrite
        bytesBuf.len = (int)(size * nmemb);
        bytesBuf.buf = buffer;

        // Set up input struct for rsDataObjWrite
	openedFile.l1descInx = writeData->desc;
        openedFile.len = bytesBuf.len;

        // Write to data object
        written = rsDataObjWrite(writeData->rsComm, &openedFile, &bytesBuf);

        return (written);
    }

}; // class irodsCurl

extern "C" {

    int irods_curl_get( msParam_t* url, msParam_t* source_obj, msParam_t* ext_obj,
                                        msParam_t* dest_obj, ruleExecInfo_t* rei ) {
        dataObjInp_t destObjInp, *myDestObjInp;	/* for parsing input object */

        // Sanity checks
        if ( !rei || !rei->rsComm ) {
            rodsLog( LOG_ERROR, "irods_curl_get: Input rei or rsComm is NULL." );
            return ( SYS_INTERNAL_NULL_INPUT_ERR );
        }

	// get destination path from sourcePath and exten.
	char *sourceStr = parseMspForStr(source_obj);
	char *extStr = parseMspForStr(ext_obj);

	char *source = "/tempZone/home/public/new.png";

	char tmpSource[strlen(source) + 10];

	strcpy(tmpSource, source);

    	char *lastdot = strrchr (tmpSource, '.');
	char *lastsep = ('/' == 0) ? NULL : strrchr (tmpSource, '/');

	if (lastdot != NULL)
	{
        // and it's before the extenstion separator.

        	if (lastsep != NULL)
		{
            		if (lastsep < lastdot)
			{
                	// then remove it.

                	*lastdot = '\0';
            		}
        	}
		else
		{
            	// Has extension separator with no path separator.

            	*lastdot = '\0';
        	}
    	}
        char destStr[strlen(source)+10];

	snprintf(destStr, strlen(source) + 10, "%s%s%s", tmpSource, ".", extStr);

	fillStrInMsParam(dest_obj, destStr);

        // Get path of destination object
        rei->status = parseMspForDataObjInp( dest_obj, &destObjInp, &myDestObjInp, 0 );
        if ( rei->status < 0 ) {
            rodsLog( LOG_ERROR, "irods_curl_get: Input object error. status = %d", rei->status );
            return ( rei->status );
        }

        // Create irodsCurl instance
        irodsCurl myCurl( rei->rsComm );

        // Call irodsCurl::get

        rei->status = myCurl.get( parseMspForStr( url ), sourceStr,  destObjInp.objPath, extStr);

        // Done
        return rei->status;

    }

// =-=-=-=-=-=-=-
// 2. Create the plugin factory function which will return a microservice
// table entry
    irods::ms_table_entry* plugin_factory() {
        // =-=-=-=-=-=-=-
        // 3. allocate a microservice plugin which takes the number of function
        // params as a parameter to the constructor
        irods::ms_table_entry* msvc = new irods::ms_table_entry( 4 );

        // =-=-=-=-=-=-=-
        // 4. add the microservice function as an operation to the plugin
        // the first param is the name / key of the operation, the second
        // is the name of the function which will be the microservice
        msvc->add_operation( "irods_curl_get", "irods_curl_get" );

        // =-=-=-=-=-=-=-
        // 5. return the newly created microservice plugin
        return msvc;
    }
}	// extern "C"
<|endoftext|>


<commit_before><commit_msg>CloseSuperfluousFiles shouldn't close the directory it's reading from<commit_after><|endoftext|>


<commit_before>#include <iostream>

#include "game.hpp"
#include <SDL2/SDL.h>

#include <thread>
#include <chrono>
#include <atomic>

#ifdef _OPENMP
#include <omp.h>
#endif

// TODO: reorder header includes (std first)
// TODO: fix formatting

using namespace std::chrono;

milliseconds last_frame_time;
Scal last_frame_game_time;
milliseconds last_report_time;
std::atomic<Scal> next_game_time_target;

std::unique_ptr<game> G;

GLdouble width, height;   /* window width and height */

std::atomic<bool> flag_display;
std::atomic<bool> quit;
std::atomic<bool> pause;

using std::cout;
using std::endl;

int frame_number;

void init()
{
  width  = 800.0;                 /* initial window width and height, */
  height = 800.0;                  /* within which we draw. */

  last_frame_game_time = 0.;
  pause = false;
}

/* Callback functions for GLUT */

/* Draw the window - this is where all the GL actions are */
void display(void)
{
  if(flag_display) return;
  flag_display=true;

  const Scal fps=30.0;
  milliseconds current_time = duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch());
  milliseconds time_past_from_last_frame = current_time-last_frame_time;

  //if(time_past_from_last_frame<milliseconds(100)) return;

  milliseconds frame_duration(int(1000.0/fps));
  milliseconds time_residual=frame_duration-time_past_from_last_frame;

  //cout<<"sleep for "<<time_residual.count()<<endl;
  //std::this_thread::sleep_for(time_residual);
  //std::this_thread::sleep_for(frame_duration);

  auto new_frame_time = duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch());
  auto new_frame_game_time = G->PS->GetTime();

  const Scal frame_real_duration_s =
      (new_frame_time - last_frame_time).count() / 1000.;

  if ((new_frame_time - last_report_time).count() > 1000.) {
    std::cout
        << "fps: " << 1. / frame_real_duration_s
        << ", game rate="
        << (new_frame_game_time -
            last_frame_game_time) / frame_real_duration_s
        << ", particles="
        << G->PS->GetNumParticles()
        //<< ", max_per_cell="
        //<< G->PS->GetNumPerCell()
        << ", t="
        << G->PS->GetTime()
        << ", steps="
        << G->PS->GetNumSteps()
        << std::endl;
    last_report_time = new_frame_time;
    //G->PS->Blocks.print_status();
  }

  const Scal game_rate_target = 10.;
  //const Scal game_rate_target = 1.;
  if (!pause) {
    next_game_time_target = new_frame_game_time + game_rate_target / fps;
  }

  last_frame_time = new_frame_time;
  last_frame_game_time = new_frame_game_time;
  //cout<<"Frame "<<frame_number++<<endl;

  /* clear the screen to white */
  glClear(GL_COLOR_BUFFER_BIT);

  {
    std::lock_guard<std::mutex> lg(G->PS->m_buffer_);
    G->R->DrawAll();
    G->PS->SetRendererReadyForNext(true);
  }

  glFlush();

  //glutSwapBuffers();

  flag_display=false;
}

void cycle()
{
  //omp_set_dynamic(0);
  //omp_set_nested(0);
  //omp_set_num_threads(std::thread::hardware_concurrency());
#ifdef _OPENMP
  omp_set_num_threads(2);
#endif

  #pragma omp parallel
  {
    #pragma omp master
    std::cout
        << "Computation started, "
        #ifdef _OPENMP
        << "OpenMP with " << omp_get_num_threads() << " threads"
        #else
        << "single-threaded"
        #endif
        << std::endl;
  }

  while (!quit) {
    G->PS->step(next_game_time_target, pause);
    std::this_thread::sleep_for(milliseconds(50));
    if (pause) {
      std::this_thread::sleep_for(milliseconds(100));
    }
  }
  std::cout << "Computation finished" << std::endl;
}

// TODO: detect motionless regions

vect GetDomainMousePosition(int x, int y) {
  vect c;
  vect A(-1.,-1.), B(-1 + 2. * width / 800, -1. + 2. * height / 800);
  c.x = A.x + (B.x - A.x) * (x / width);
  c.y = B.y + (A.y - B.y) * (y / height);
  return c;
}

vect GetDomainMousePosition() {
  int x, y;
  SDL_GetMouseState(&x, &y);
  return GetDomainMousePosition(x, y);
}

int main() {
  if (SDL_Init(SDL_INIT_VIDEO) != 0) {
    SDL_Log("Unable to initialize SDL: %s\n", SDL_GetError());
    return 1;
  }

  init();

  SDL_Window* window = SDL_CreateWindow(
      "ptoy",
      SDL_WINDOWPOS_UNDEFINED,
      SDL_WINDOWPOS_UNDEFINED,
      width,
      height,
      SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
  );

  if (window == NULL) {
    SDL_Log("Unable to create window: %s\n", SDL_GetError());
    return 1;
  }

  SDL_GLContext glcontext = SDL_GL_CreateContext(window);

  auto gray = 0.5;
  glClearColor(gray, gray, gray, 0.0);
  glClear(GL_COLOR_BUFFER_BIT);
  SDL_GL_SwapWindow(window);

  G = std::unique_ptr<game>(new game(width, height));
  std::thread computation_thread(cycle);

  G->PS->SetForce(vect(0., 0.), false);

  //Main loop flag
  quit = false;

  //Event handler
  SDL_Event e;

  enum class MouseState {None, Force, Bonds, Pick, Freeze, Portal};
  MouseState mouse_state = MouseState::Force;

  //While application is running
  while (!quit) {
    while (SDL_PollEvent( &e ) != 0) {
      if (e.type == SDL_QUIT) {
        quit = true;
      } else if (e.type == SDL_KEYDOWN) {
        switch( e.key.keysym.sym ) {
          case 'q':
            quit = true;
            break;
          case 'n':
            mouse_state = MouseState::None;
            std::cout << "Mouse switched to None mode" << std::endl;
            break;
          case 'r':
            mouse_state = MouseState::Force;
            std::cout << "Mouse switched to Repulsive mode" << std::endl;
            G->PS->SetForceAttractive(false);
            break;
          case 'f':
            mouse_state = MouseState::Freeze;
            std::cout << "Mouse switched to Freeze mode" << std::endl;
            break;
          case 'p':
            mouse_state = MouseState::Pick;
            std::cout << "Mouse switched to Pick mode" << std::endl;
            break;
          case 'a':
            mouse_state = MouseState::Force;
            std::cout << "Mouse switched to Attractive mode" << std::endl;
            G->PS->SetForceAttractive(true);
            break;
          case 'b':
            mouse_state = MouseState::Bonds;
            std::cout << "Mouse switched to Bonds mode" << std::endl;
            break;
          case 'o':
            mouse_state = MouseState::Portal;
            std::cout << "Mouse switched to Portal mode" << std::endl;
            break;
          case 'i':
            std::cout << "Remove last portal" << std::endl;
            G->PS->RemoveLastPortal();
            break;
          case 'g':
            G->PS->InvertGravity();
            std::cout
              << (G->PS->GetGravity() ? "Gravity on" : "Gravity off")
              << std::endl;
            break;
          case ' ':
            pause = !pause;
            break;
        }
      } else if (e.type == SDL_MOUSEMOTION) {
        switch (mouse_state) {
          case MouseState::Force:
            G->PS->SetForce(GetDomainMousePosition());
            break;
          case MouseState::Bonds:
            G->PS->BondsMove(GetDomainMousePosition());
            break;
          case MouseState::Pick:
            G->PS->PickMove(GetDomainMousePosition());
            break;
          case MouseState::Freeze:
            G->PS->FreezeMove(GetDomainMousePosition());
            break;
          case MouseState::Portal:
            G->PS->PortalMove(GetDomainMousePosition());
            break;
          case MouseState::None:
            break;
        }
      } else if (e.type == SDL_MOUSEBUTTONDOWN) {
        switch (mouse_state) {
          case MouseState::Force:
            G->PS->SetForce(GetDomainMousePosition(), true);
            break;
          case MouseState::Bonds:
            G->PS->BondsStart(GetDomainMousePosition());
            break;
          case MouseState::Pick:
            G->PS->PickStart(GetDomainMousePosition());
            break;
          case MouseState::Freeze:
            G->PS->FreezeStart(GetDomainMousePosition());
            break;
          case MouseState::Portal:
            G->PS->PortalStart(GetDomainMousePosition());
            break;
          case MouseState::None:
            break;
        }
      } else if (e.type == SDL_MOUSEBUTTONUP) {
        switch (mouse_state) {
          case MouseState::Force:
            G->PS->SetForce(false);
            break;
          case MouseState::Bonds:
            G->PS->BondsStop(GetDomainMousePosition());
            break;
          case MouseState::Pick:
            G->PS->PickStop(GetDomainMousePosition());
            break;
          case MouseState::Freeze:
            G->PS->FreezeStop(GetDomainMousePosition());
            break;
          case MouseState::Portal:
            G->PS->PortalStop(GetDomainMousePosition());
            break;
          case MouseState::None:
            break;
        }
      } else if (e.type == SDL_WINDOWEVENT) {
        switch (e.window.event) {
          case SDL_WINDOWEVENT_RESIZED:
            width = e.window.data1;
            height = e.window.data2;
            glViewport(0, 0, width, height);
            G->SetWindowSize(width, height);
            break;
        }
      }
    }

    display();
    SDL_GL_SwapWindow(window);
    SDL_Delay(30);
  }

  // Finalize
  SDL_GL_DeleteContext(glcontext);
  SDL_DestroyWindow(window);
  SDL_Quit();

  computation_thread.join();

  return 0;
}
<commit_msg>Add quit counter: key q to press 3 times<commit_after>#include <iostream>

#include "game.hpp"
#include <SDL2/SDL.h>

#include <thread>
#include <chrono>
#include <atomic>

#ifdef _OPENMP
#include <omp.h>
#endif

// TODO: reorder header includes (std first)
// TODO: fix formatting

using namespace std::chrono;

milliseconds last_frame_time;
Scal last_frame_game_time;
milliseconds last_report_time;
std::atomic<Scal> next_game_time_target;

std::unique_ptr<game> G;

GLdouble width, height;   /* window width and height */

std::atomic<bool> flag_display;
std::atomic<bool> quit;
std::atomic<bool> pause;

using std::cout;
using std::endl;

int frame_number;

void init()
{
  width  = 800.0;                 /* initial window width and height, */
  height = 800.0;                  /* within which we draw. */

  last_frame_game_time = 0.;
  pause = false;
}

/* Callback functions for GLUT */

/* Draw the window - this is where all the GL actions are */
void display(void)
{
  if(flag_display) return;
  flag_display=true;

  const Scal fps=30.0;
  milliseconds current_time = duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch());
  milliseconds time_past_from_last_frame = current_time-last_frame_time;

  //if(time_past_from_last_frame<milliseconds(100)) return;

  milliseconds frame_duration(int(1000.0/fps));
  milliseconds time_residual=frame_duration-time_past_from_last_frame;

  //cout<<"sleep for "<<time_residual.count()<<endl;
  //std::this_thread::sleep_for(time_residual);
  //std::this_thread::sleep_for(frame_duration);

  auto new_frame_time = duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch());
  auto new_frame_game_time = G->PS->GetTime();

  const Scal frame_real_duration_s =
      (new_frame_time - last_frame_time).count() / 1000.;

  if ((new_frame_time - last_report_time).count() > 1000.) {
    std::cout
        << "fps: " << 1. / frame_real_duration_s
        << ", game rate="
        << (new_frame_game_time -
            last_frame_game_time) / frame_real_duration_s
        << ", particles="
        << G->PS->GetNumParticles()
        //<< ", max_per_cell="
        //<< G->PS->GetNumPerCell()
        << ", t="
        << G->PS->GetTime()
        << ", steps="
        << G->PS->GetNumSteps()
        << std::endl;
    last_report_time = new_frame_time;
    //G->PS->Blocks.print_status();
  }

  const Scal game_rate_target = 10.;
  //const Scal game_rate_target = 1.;
  if (!pause) {
    next_game_time_target = new_frame_game_time + game_rate_target / fps;
  }

  last_frame_time = new_frame_time;
  last_frame_game_time = new_frame_game_time;
  //cout<<"Frame "<<frame_number++<<endl;

  /* clear the screen to white */
  glClear(GL_COLOR_BUFFER_BIT);

  {
    std::lock_guard<std::mutex> lg(G->PS->m_buffer_);
    G->R->DrawAll();
    G->PS->SetRendererReadyForNext(true);
  }

  glFlush();

  //glutSwapBuffers();

  flag_display=false;
}

void cycle()
{
  //omp_set_dynamic(0);
  //omp_set_nested(0);
  //omp_set_num_threads(std::thread::hardware_concurrency());
#ifdef _OPENMP
  omp_set_num_threads(2);
#endif

  #pragma omp parallel
  {
    #pragma omp master
    std::cout
        << "Computation started, "
        #ifdef _OPENMP
        << "OpenMP with " << omp_get_num_threads() << " threads"
        #else
        << "single-threaded"
        #endif
        << std::endl;
  }

  while (!quit) {
    G->PS->step(next_game_time_target, pause);
    std::this_thread::sleep_for(milliseconds(50));
    if (pause) {
      std::this_thread::sleep_for(milliseconds(100));
    }
  }
  std::cout << "Computation finished" << std::endl;
}

// TODO: detect motionless regions

vect GetDomainMousePosition(int x, int y) {
  vect c;
  vect A(-1.,-1.), B(-1 + 2. * width / 800, -1. + 2. * height / 800);
  c.x = A.x + (B.x - A.x) * (x / width);
  c.y = B.y + (A.y - B.y) * (y / height);
  return c;
}

vect GetDomainMousePosition() {
  int x, y;
  SDL_GetMouseState(&x, &y);
  return GetDomainMousePosition(x, y);
}

int main() {
  if (SDL_Init(SDL_INIT_VIDEO) != 0) {
    SDL_Log("Unable to initialize SDL: %s\n", SDL_GetError());
    return 1;
  }

  init();

  SDL_Window* window = SDL_CreateWindow(
      "ptoy",
      SDL_WINDOWPOS_UNDEFINED,
      SDL_WINDOWPOS_UNDEFINED,
      width,
      height,
      SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
  );

  if (window == NULL) {
    SDL_Log("Unable to create window: %s\n", SDL_GetError());
    return 1;
  }

  SDL_GLContext glcontext = SDL_GL_CreateContext(window);

  auto gray = 0.5;
  glClearColor(gray, gray, gray, 0.0);
  glClear(GL_COLOR_BUFFER_BIT);
  SDL_GL_SwapWindow(window);

  G = std::unique_ptr<game>(new game(width, height));
  std::thread computation_thread(cycle);

  G->PS->SetForce(vect(0., 0.), false);

  //Main loop flag
  quit = false;

  //Event handler
  SDL_Event e;

  enum class MouseState {None, Force, Bonds, Pick, Freeze, Portal};
  MouseState mouse_state = MouseState::Force;

  size_t quit_count = 0;

  //While application is running
  while (!quit) {
    while (SDL_PollEvent( &e ) != 0) {
      if (e.type == SDL_QUIT) {
        quit = true;
      } else if (e.type == SDL_KEYDOWN) {
        if (e.key.keysym.sym != 'q') {
          quit_count = 0;
        }
        switch( e.key.keysym.sym ) {
          case 'q':
            if (++quit_count >= 3) {
              quit = true;
            } else {
              std::cout << "Quit counter: "
                << quit_count << "/3" << std::endl;
            }
            break;
          case 'n':
            mouse_state = MouseState::None;
            std::cout << "Mouse switched to None mode" << std::endl;
            break;
          case 'r':
            mouse_state = MouseState::Force;
            std::cout << "Mouse switched to Repulsive mode" << std::endl;
            G->PS->SetForceAttractive(false);
            break;
          case 'f':
            mouse_state = MouseState::Freeze;
            std::cout << "Mouse switched to Freeze mode" << std::endl;
            break;
          case 'p':
            mouse_state = MouseState::Pick;
            std::cout << "Mouse switched to Pick mode" << std::endl;
            break;
          case 'a':
            mouse_state = MouseState::Force;
            std::cout << "Mouse switched to Attractive mode" << std::endl;
            G->PS->SetForceAttractive(true);
            break;
          case 'b':
            mouse_state = MouseState::Bonds;
            std::cout << "Mouse switched to Bonds mode" << std::endl;
            break;
          case 'o':
            mouse_state = MouseState::Portal;
            std::cout << "Mouse switched to Portal mode" << std::endl;
            break;
          case 'i':
            std::cout << "Remove last portal" << std::endl;
            G->PS->RemoveLastPortal();
            break;
          case 'g':
            G->PS->InvertGravity();
            std::cout
              << (G->PS->GetGravity() ? "Gravity on" : "Gravity off")
              << std::endl;
            break;
          case ' ':
            pause = !pause;
            break;
        }
      } else if (e.type == SDL_MOUSEMOTION) {
        switch (mouse_state) {
          case MouseState::Force:
            G->PS->SetForce(GetDomainMousePosition());
            break;
          case MouseState::Bonds:
            G->PS->BondsMove(GetDomainMousePosition());
            break;
          case MouseState::Pick:
            G->PS->PickMove(GetDomainMousePosition());
            break;
          case MouseState::Freeze:
            G->PS->FreezeMove(GetDomainMousePosition());
            break;
          case MouseState::Portal:
            G->PS->PortalMove(GetDomainMousePosition());
            break;
          case MouseState::None:
            break;
        }
      } else if (e.type == SDL_MOUSEBUTTONDOWN) {
        switch (mouse_state) {
          case MouseState::Force:
            G->PS->SetForce(GetDomainMousePosition(), true);
            break;
          case MouseState::Bonds:
            G->PS->BondsStart(GetDomainMousePosition());
            break;
          case MouseState::Pick:
            G->PS->PickStart(GetDomainMousePosition());
            break;
          case MouseState::Freeze:
            G->PS->FreezeStart(GetDomainMousePosition());
            break;
          case MouseState::Portal:
            G->PS->PortalStart(GetDomainMousePosition());
            break;
          case MouseState::None:
            break;
        }
      } else if (e.type == SDL_MOUSEBUTTONUP) {
        switch (mouse_state) {
          case MouseState::Force:
            G->PS->SetForce(false);
            break;
          case MouseState::Bonds:
            G->PS->BondsStop(GetDomainMousePosition());
            break;
          case MouseState::Pick:
            G->PS->PickStop(GetDomainMousePosition());
            break;
          case MouseState::Freeze:
            G->PS->FreezeStop(GetDomainMousePosition());
            break;
          case MouseState::Portal:
            G->PS->PortalStop(GetDomainMousePosition());
            break;
          case MouseState::None:
            break;
        }
      } else if (e.type == SDL_WINDOWEVENT) {
        switch (e.window.event) {
          case SDL_WINDOWEVENT_RESIZED:
            width = e.window.data1;
            height = e.window.data2;
            glViewport(0, 0, width, height);
            G->SetWindowSize(width, height);
            break;
        }
      }
    }

    display();
    SDL_GL_SwapWindow(window);
    SDL_Delay(30);
  }

  // Finalize
  SDL_GL_DeleteContext(glcontext);
  SDL_DestroyWindow(window);
  SDL_Quit();

  computation_thread.join();

  return 0;
}
<|endoftext|>


<commit_before>#include <GarrysMod/Lua/Interface.h>
#include <lua.hpp>

extern "C" int luaopen_ssl_core( lua_State *state );
extern "C" int luaopen_ssl_context( lua_State *state );
extern "C" int luaopen_ssl_x509( lua_State *state );

GMOD_MODULE_OPEN( )
{
	if( luaopen_ssl_core( LUA->state ) == 1 )
	{
		lua_replace( LUA->state, 1 );
		lua_settop( LUA->state, 1 );
		LUA->Push( -1 );
		LUA->SetField( GarrysMod::Lua::INDEX_GLOBAL, "ssl" );
	}

	if( luaopen_ssl_context( LUA->state ) == 1 )
	{
		lua_replace( LUA->state, 2 );
		lua_settop( LUA->state, 2 );
		LUA->SetField( -2, "context" );
	}

	if( luaopen_ssl_x509( LUA->state ) == 1 )
	{
		lua_replace( LUA->state, 2 );
		lua_settop( LUA->state, 2 );
		LUA->SetField( -2, "x509" );
	}

	return 1;
}

GMOD_MODULE_CLOSE( )
{
	LUA->PushNil( );
	LUA->SetField( GarrysMod::Lua::INDEX_GLOBAL, "ssl" );
	return 0;
}
<commit_msg>use const LUA->GetState() instead of private member state<commit_after>#include <GarrysMod/Lua/Interface.h>
#include <lua.hpp>

extern "C" int luaopen_ssl_core( lua_State *state );
extern "C" int luaopen_ssl_context( lua_State *state );
extern "C" int luaopen_ssl_x509( lua_State *state );

GMOD_MODULE_OPEN( )
{
	if( luaopen_ssl_core( LUA->GetState( ) ) == 1 )
	{
		lua_replace( LUA->GetState( ), 1 );
		lua_settop( LUA->GetState( ), 1 );
		LUA->Push( -1 );
		LUA->SetField( GarrysMod::Lua::INDEX_GLOBAL, "ssl" );
	}

	if( luaopen_ssl_context( LUA->GetState( ) ) == 1 )
	{
		lua_replace( LUA->GetState( ), 2 );
		lua_settop( LUA->GetState( ), 2 );
		LUA->SetField( -2, "context" );
	}

	if( luaopen_ssl_x509( LUA->GetState( ) ) == 1 )
	{
		lua_replace( LUA->GetState( ), 2 );
		lua_settop( LUA->GetState( ), 2 );
		LUA->SetField( -2, "x509" );
	}

	return 1;
}

GMOD_MODULE_CLOSE( )
{
	LUA->PushNil( );
	LUA->SetField( GarrysMod::Lua::INDEX_GLOBAL, "ssl" );
	return 0;
}
<|endoftext|>


<commit_before>#include <3ds.h>
#include <stdio.h>

void shutdown3DS()
{
	Handle ptmSysmHandle = 0;
	Result result = srvGetServiceHandle(&ptmSysmHandle, "ns:s");
	if (result != 0)
		return;

	// http://3dbrew.org/wiki/NSS:ShutdownAsync

	u32 *commandBuffer = getThreadCommandBuffer();
	commandBuffer[0] = 0x000E0000;

	svcSendSyncRequest(ptmSysmHandle);
	svcCloseHandle(ptmSysmHandle);
}

int main(int argc, char **argv) {
	hidScanInput();

#ifndef ALWAYS_SHUTDOWN
	// If any key is pressed, cancel the shutdown.
	if (hidKeysDown() != 0)
		goto done;
#endif
	shutdown3DS();

done:
	// Hack: the 3ds crashes ("An error has occcurred.") for some reason
	// without one iteration of the main loop.
	aptMainLoop();
	return 0;
}
<commit_msg>Rename a variable due to using a different service.<commit_after>#include <3ds.h>
#include <stdio.h>

void shutdown3DS()
{
	Handle nssHandle = 0;
	Result result = srvGetServiceHandle(&nssHandle, "ns:s");
	if (result != 0)
		return;

	// http://3dbrew.org/wiki/NSS:ShutdownAsync

	u32 *commandBuffer = getThreadCommandBuffer();
	commandBuffer[0] = 0x000E0000;

	svcSendSyncRequest(nssHandle);
	svcCloseHandle(nssHandle);
}

int main(int argc, char **argv) {
	hidScanInput();

#ifndef ALWAYS_SHUTDOWN
	// If any key is pressed, cancel the shutdown.
	if (hidKeysDown() != 0)
		goto done;
#endif
	shutdown3DS();

done:
	// Hack: the 3ds crashes ("An error has occcurred.") for some reason
	// without one iteration of the main loop.
	aptMainLoop();
	return 0;
}
<|endoftext|>


<commit_before>#include <ctrcommon/app.hpp>
#include <ctrcommon/gpu.hpp>
#include <ctrcommon/input.hpp>
#include <ctrcommon/nor.hpp>
#include <ctrcommon/platform.hpp>
#include <ctrcommon/ui.hpp>

#include "rop.h"

#include <sys/errno.h>
#include <stdio.h>
#include <string.h>

#include <sstream>
#include <iomanip>

typedef enum {
    INSTALL_CIA,
    DELETE_CIA,
    DELETE_TITLE,
    LAUNCH_TITLE
} Mode;

int main(int argc, char **argv) {
    if(!platformInit()) {
        return 0;
    }

    bool ninjhax = platformIsNinjhax();

    std::vector<std::string> extensions;
    extensions.push_back("cia");

    MediaType destination = SD;
    Mode mode = INSTALL_CIA;
    bool exit = false;
    bool netInstall = false;
    u64 freeSpace = fsGetFreeSpace(destination);
    auto onLoop = [&]() {
        if(ninjhax && inputIsPressed(BUTTON_START)) {
            exit = true;
            return true;
        }

        bool breakLoop = false;

        if(inputIsPressed(BUTTON_L)) {
            if(destination == SD) {
                destination = NAND;
            } else {
                destination = SD;
            }

            freeSpace = fsGetFreeSpace(destination);
            if(mode == DELETE_TITLE || mode == LAUNCH_TITLE) {
                breakLoop = true;
            }
        }

        if(inputIsPressed(BUTTON_R)) {
            if(mode == INSTALL_CIA) {
                mode = DELETE_CIA;
            } else if(mode == DELETE_CIA) {
                mode = DELETE_TITLE;
                breakLoop = true;
            } else if(mode == DELETE_TITLE) {
                mode = LAUNCH_TITLE;
            } else if(mode == LAUNCH_TITLE) {
                mode = INSTALL_CIA;
                breakLoop = true;
            }
        }

        if(mode == INSTALL_CIA && inputIsPressed(BUTTON_Y)) {
            netInstall = true;
            breakLoop = true;
        }

        if(inputIsPressed(BUTTON_SELECT)) {
            u32 selected = 0;
            bool dirty = true;
            while(platformIsRunning()) {
                inputPoll();
                if(inputIsPressed(BUTTON_B)) {
                    break;
                }

                if(inputIsPressed(BUTTON_A)) {
                    std::stringstream stream;
                    stream << "Install the selected ROP?" << "\n";
                    stream << ropNames[selected];

                    if(uiPrompt(TOP_SCREEN, stream.str(), true)) {
                        u16 userSettingsOffset = 0;
                        bool result = norRead(0x20, &userSettingsOffset, 2) && norWrite(userSettingsOffset << 3, rops[selected], ROP_SIZE);

                        std::stringstream resultMsg;
                        resultMsg << "ROP installation ";
                        if(result) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << platformGetErrorString(platformGetError());
                        }

                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                        break;
                    }
                }

                if(inputIsPressed(BUTTON_LEFT)) {
                    if(selected == 0) {
                        selected = ROP_COUNT - 1;
                    } else {
                        selected--;
                    }

                    dirty = true;
                }

                if(inputIsPressed(BUTTON_RIGHT)) {
                    if(selected >= ROP_COUNT - 1) {
                        selected = 0;
                    } else {
                        selected++;
                    }

                    dirty = true;
                }

                if(dirty) {
                    std::stringstream stream;
                    stream << "Select a ROP to install." << "\n";
                    stream << "< " << ropNames[selected] << " >" << "\n";
                    stream << "Press A to install, B to cancel.";
                    uiDisplayMessage(TOP_SCREEN, stream.str());
                }
            }
		}

        std::stringstream stream;
        stream << "Battery: ";
        if(platformIsBatteryCharging()) {
            stream << "Charging";
        } else {
            for(u32 i = 0; i < platformGetBatteryLevel(); i++) {
                stream << "|";
            }
        }

        stream << ", WiFi: ";
        if(!platformIsWifiConnected()) {
            stream << "Disconnected";
        } else {
            for(u32 i = 0; i < platformGetWifiLevel(); i++) {
                stream << "|";
            }
        }

        stream << "\n";

        stream << "Free Space: " << freeSpace << " bytes (" << std::fixed << std::setprecision(2) << freeSpace / 1024.0f / 1024.0f << "MB)" << "\n";
        stream << "Destination: " << (destination == NAND ? "NAND" : "SD") << ", Mode: " << (mode == INSTALL_CIA ? "Install CIA" : mode == DELETE_CIA ? "Delete CIA" : mode == DELETE_TITLE ? "Delete Title" : "Launch Title") << "\n";
        stream << "L - Switch Destination, R - Switch Mode" << "\n";
        if(mode == INSTALL_CIA) {
            stream << "X - Install all CIAs in the current directory" << "\n";
            stream << "Y - Receive an app over the network" << "\n";
        } else if(mode == DELETE_CIA) {
            stream << "X - Delete all CIAs in the current directory" << "\n";
        }

        stream << "SELECT - Install MSET ROP";

        if(ninjhax) {
            stream << "\n" << "START - Exit to launcher";
        }

        std::string str = stream.str();
        const std::string title = "FBI v1.4";
        gputDrawString(title, (gpuGetViewportWidth() - gputGetStringWidth(title, 16)) / 2, (gpuGetViewportHeight() - gputGetStringHeight(title, 16) + gputGetStringHeight(str, 8)) / 2, 16, 16);
        gputDrawString(str, (gpuGetViewportWidth() - gputGetStringWidth(str, 8)) / 2, 4, 8, 8);

        return breakLoop;
    };

    std::string batchInfo = "";

    int prevProgress = -1;
    auto onProgress = [&](u64 pos, u64 totalSize) {
        u32 progress = (u32) ((pos * 100) / totalSize);
        if(prevProgress != (int) progress) {
            prevProgress = (int) progress;

            std::stringstream details;
            details << batchInfo;
            details << "Press B to cancel.";

            uiDisplayProgress(TOP_SCREEN, "Installing", details.str(), true, progress);
        }

        inputPoll();
        return !inputIsPressed(BUTTON_B);
    };

    bool showNetworkPrompts = true;

    while(platformIsRunning()) {
        std::string fileTarget;
        App appTarget;
        if(mode == INSTALL_CIA || mode == DELETE_CIA) {
            if(netInstall && !exit) {
                gpuClearScreens();

                RemoteFile file = uiAcceptRemoteFile(TOP_SCREEN, [&](std::stringstream& infoStream) {
                    if(inputIsPressed(BUTTON_A)) {
                        showNetworkPrompts = !showNetworkPrompts;
                    }

                    infoStream << "\n";
                    infoStream << "Prompts: " << (showNetworkPrompts ? "Enabled" : "Disabled") << "\n";
                    infoStream << "Press A to toggle prompts.";
                });

                if(file.fd == NULL) {
                    netInstall = false;
                    continue;
                }

                std::stringstream confirmStream;
                confirmStream << "Install the received application?" << "\n";
                confirmStream << "Size: " << file.fileSize << " bytes (" << std::fixed << std::setprecision(2) << file.fileSize / 1024.0f / 1024.0f << "MB)";
                if(!showNetworkPrompts || uiPrompt(TOP_SCREEN, confirmStream.str(), true)) {
                    AppResult ret = appInstall(destination, file.fd, file.fileSize, onProgress);
                    prevProgress = -1;
                    if(showNetworkPrompts || ret != APP_SUCCESS) {
                        std::stringstream resultMsg;
                        resultMsg << "Install ";
                        if(ret == APP_SUCCESS) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                        }

                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                    }
                }

                fclose(file.fd);
                continue;
            }

            uiSelectFile(&fileTarget, "/", extensions, [&](const std::string currDirectory, bool inRoot, bool &updateList) {
                if(inputIsPressed(BUTTON_X)) {
                    std::stringstream confirmMsg;
                    if(mode == INSTALL_CIA) {
                        confirmMsg << "Install ";
                    } else {
                        confirmMsg << "Delete ";
                    }

                    confirmMsg << "all CIAs in the current directory?";
                    if(uiPrompt(TOP_SCREEN, confirmMsg.str(), true)) {
                        bool failed = false;
                        std::vector<FileInfo> contents = fsGetDirectoryContents(currDirectory);
                        u32 currItem = 0;
                        for(std::vector<FileInfo>::iterator it = contents.begin(); it != contents.end(); it++) {
                            std::string path = (*it).path;
                            if(!fsIsDirectory(path) && fsHasExtensions(path, extensions)) {
                                std::string displayFileName = (*it).name;
                                if(displayFileName.length() > 40) {
                                    displayFileName.resize(40);
                                    displayFileName += "...";
                                }

                                if(mode == INSTALL_CIA) {
                                    std::stringstream batchInstallStream;
                                    batchInstallStream << displayFileName << " (" << currItem << ")" << "\n";

                                    batchInfo = batchInstallStream.str();
                                    AppResult ret = appInstallFile(destination, path, onProgress);
                                    prevProgress = -1;
                                    batchInfo = "";
                                    if(ret != APP_SUCCESS) {
                                        Error error = platformGetError();
                                        platformSetError(error);

                                        std::stringstream resultMsg;
                                        resultMsg << "Install failed!" << "\n";
                                        resultMsg << displayFileName << "\n";
                                        resultMsg << appGetResultString(ret);
                                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                                        if(error.module != MODULE_NN_AM || error.description != DESCRIPTION_ALREADY_EXISTS) {
                                            failed = true;
                                            break;
                                        }
                                    }
                                } else {
                                    std::stringstream deleteStream;
                                    deleteStream << "Deleting CIA..." << "\n";
                                    deleteStream << displayFileName << " (" << currItem << ")";

                                    uiDisplayMessage(TOP_SCREEN, deleteStream.str());
                                    if(remove(path.c_str()) != 0) {
                                        std::stringstream resultMsg;
                                        resultMsg << "Delete failed!" << "\n";
                                        resultMsg << displayFileName << "\n";
                                        resultMsg << strerror(errno);
                                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                                        failed = true;
                                        break;
                                    } else {
                                        updateList = true;
                                    }
                                }
                            }

                            currItem++;
                        }

                        if(!failed) {
                            uiPrompt(TOP_SCREEN, "Install succeeded!\n", false);
                        }

                        freeSpace = fsGetFreeSpace(destination);
                    }
                }

                return onLoop();
            }, [&](const std::string path, bool &updateList) {
                std::stringstream confirmMsg;
                if(mode == INSTALL_CIA) {
                    confirmMsg << "Install ";
                } else {
                    confirmMsg << "Delete ";
                }

                confirmMsg << "the selected CIA?";
                if(uiPrompt(TOP_SCREEN, confirmMsg.str(), true)) {
                    std::stringstream resultMsg;
                    if(mode == INSTALL_CIA) {
                        resultMsg << "Install ";
                    } else {
                        resultMsg << "Delete ";
                    }

                    if(mode == INSTALL_CIA) {
                        AppResult ret = appInstallFile(destination, path, onProgress);
                        prevProgress = -1;
                        if(ret == APP_SUCCESS) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                        }
                    } else {
                        uiDisplayMessage(TOP_SCREEN, "Deleting CIA...");
                        if(remove(path.c_str()) != 0) {
                            updateList = true;
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << strerror(errno);
                        }
                    }

                    uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                    freeSpace = fsGetFreeSpace(destination);
                }

                return false;
            });
        } else if(mode == DELETE_TITLE || mode == LAUNCH_TITLE) {
            uiDisplayMessage(BOTTOM_SCREEN, "Loading title list...");
            uiSelectApp(&appTarget, destination, [&](bool &updateList) {
                return onLoop();
            }, [&](App app, bool &updateList) {
                if(mode == DELETE_TITLE) {
                    if(uiPrompt(TOP_SCREEN, "Delete the selected title?", true) && (destination != NAND || uiPrompt(TOP_SCREEN, "You are about to delete a title from the NAND.\nTHIS HAS THE POTENTIAL TO BRICK YOUR 3DS!\nAre you sure you wish to continue?", true))) {
                        updateList = true;
                        uiDisplayMessage(TOP_SCREEN, "Deleting title...");
                        AppResult ret = appDelete(app);

                        std::stringstream resultMsg;
                        resultMsg << "Delete ";
                        if(ret == APP_SUCCESS) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                        }

                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                        freeSpace = fsGetFreeSpace(destination);
                    }
                } else if(mode == LAUNCH_TITLE) {
                    if(uiPrompt(TOP_SCREEN, "Launch the selected title?", true)) {
                        updateList = true;
                        uiDisplayMessage(TOP_SCREEN, "Launching title...");
                        AppResult ret = appLaunch(app);

                        if(ret != APP_SUCCESS) {
                            std::stringstream resultMsg;
                            resultMsg << "Launch failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                            uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                        } else {
                            while(true) {
                            }
                        }
                    }
                }

                return false;
            });
        }

        if(exit) {
            break;
        }
    }

    platformCleanup();
    return 0;
}
<commit_msg>Add file list loading screen, move network installation code into loop to avoid reloading lists.<commit_after>#include <ctrcommon/app.hpp>
#include <ctrcommon/gpu.hpp>
#include <ctrcommon/input.hpp>
#include <ctrcommon/nor.hpp>
#include <ctrcommon/platform.hpp>
#include <ctrcommon/ui.hpp>

#include "rop.h"

#include <sys/errno.h>
#include <stdio.h>
#include <string.h>

#include <sstream>
#include <iomanip>

typedef enum {
    INSTALL_CIA,
    DELETE_CIA,
    DELETE_TITLE,
    LAUNCH_TITLE
} Mode;

int main(int argc, char **argv) {
    if(!platformInit()) {
        return 0;
    }

    bool ninjhax = platformIsNinjhax();

    std::vector<std::string> extensions;
    extensions.push_back("cia");

    MediaType destination = SD;
    Mode mode = INSTALL_CIA;
    bool exit = false;
    bool showNetworkPrompts = true;
    u64 freeSpace = fsGetFreeSpace(destination);

    std::string batchInfo = "";
    int prevProgress = -1;
    auto onProgress = [&](u64 pos, u64 totalSize) {
        u32 progress = (u32) ((pos * 100) / totalSize);
        if(prevProgress != (int) progress) {
            prevProgress = (int) progress;

            std::stringstream details;
            details << batchInfo;
            details << "Press B to cancel.";

            uiDisplayProgress(TOP_SCREEN, "Installing", details.str(), true, progress);
        }

        inputPoll();
        return !inputIsPressed(BUTTON_B);
    };

    auto onLoop = [&]() {
        if(ninjhax && inputIsPressed(BUTTON_START)) {
            exit = true;
            return true;
        }

        bool breakLoop = false;

        if(inputIsPressed(BUTTON_L)) {
            if(destination == SD) {
                destination = NAND;
            } else {
                destination = SD;
            }

            freeSpace = fsGetFreeSpace(destination);
            if(mode == DELETE_TITLE || mode == LAUNCH_TITLE) {
                breakLoop = true;
            }
        }

        if(inputIsPressed(BUTTON_R)) {
            if(mode == INSTALL_CIA) {
                mode = DELETE_CIA;
            } else if(mode == DELETE_CIA) {
                mode = DELETE_TITLE;
                breakLoop = true;
            } else if(mode == DELETE_TITLE) {
                mode = LAUNCH_TITLE;
            } else if(mode == LAUNCH_TITLE) {
                mode = INSTALL_CIA;
                breakLoop = true;
            }
        }

        if(mode == INSTALL_CIA && inputIsPressed(BUTTON_Y)) {
            while(platformIsRunning()) {
                gpuClearScreens();

                RemoteFile file = uiAcceptRemoteFile(TOP_SCREEN, [&](std::stringstream& infoStream) {
                    if(inputIsPressed(BUTTON_A)) {
                        showNetworkPrompts = !showNetworkPrompts;
                    }

                    infoStream << "\n";
                    infoStream << "Prompts: " << (showNetworkPrompts ? "Enabled" : "Disabled") << "\n";
                    infoStream << "Press A to toggle prompts.";
                });

                if(file.fd == NULL) {
                    break;
                }

                std::stringstream confirmStream;
                confirmStream << "Install the received application?" << "\n";
                confirmStream << "Size: " << file.fileSize << " bytes (" << std::fixed << std::setprecision(2) << file.fileSize / 1024.0f / 1024.0f << "MB)";
                if(!showNetworkPrompts || uiPrompt(TOP_SCREEN, confirmStream.str(), true)) {
                    AppResult ret = appInstall(destination, file.fd, file.fileSize, onProgress);
                    prevProgress = -1;
                    if(showNetworkPrompts || ret != APP_SUCCESS) {
                        std::stringstream resultMsg;
                        resultMsg << "Install ";
                        if(ret == APP_SUCCESS) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                        }

                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                    }
                }

                fclose(file.fd);
            }
        }

        if(inputIsPressed(BUTTON_SELECT)) {
            u32 selected = 0;
            bool dirty = true;
            while(platformIsRunning()) {
                inputPoll();
                if(inputIsPressed(BUTTON_B)) {
                    break;
                }

                if(inputIsPressed(BUTTON_A)) {
                    std::stringstream stream;
                    stream << "Install the selected ROP?" << "\n";
                    stream << ropNames[selected];

                    if(uiPrompt(TOP_SCREEN, stream.str(), true)) {
                        u16 userSettingsOffset = 0;
                        bool result = norRead(0x20, &userSettingsOffset, 2) && norWrite(userSettingsOffset << 3, rops[selected], ROP_SIZE);

                        std::stringstream resultMsg;
                        resultMsg << "ROP installation ";
                        if(result) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << platformGetErrorString(platformGetError());
                        }

                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                    }

                    dirty = true;
                }

                if(inputIsPressed(BUTTON_LEFT)) {
                    if(selected == 0) {
                        selected = ROP_COUNT - 1;
                    } else {
                        selected--;
                    }

                    dirty = true;
                }

                if(inputIsPressed(BUTTON_RIGHT)) {
                    if(selected >= ROP_COUNT - 1) {
                        selected = 0;
                    } else {
                        selected++;
                    }

                    dirty = true;
                }

                if(dirty) {
                    std::stringstream stream;
                    stream << "Select a ROP to install." << "\n";
                    stream << "< " << ropNames[selected] << " >" << "\n";
                    stream << "Press A to install, B to cancel.";
                    uiDisplayMessage(TOP_SCREEN, stream.str());
                }
            }
		}

        std::stringstream stream;
        stream << "Battery: ";
        if(platformIsBatteryCharging()) {
            stream << "Charging";
        } else {
            for(u32 i = 0; i < platformGetBatteryLevel(); i++) {
                stream << "|";
            }
        }

        stream << ", WiFi: ";
        if(!platformIsWifiConnected()) {
            stream << "Disconnected";
        } else {
            for(u32 i = 0; i < platformGetWifiLevel(); i++) {
                stream << "|";
            }
        }

        stream << "\n";

        stream << "Free Space: " << freeSpace << " bytes (" << std::fixed << std::setprecision(2) << freeSpace / 1024.0f / 1024.0f << "MB)" << "\n";
        stream << "Destination: " << (destination == NAND ? "NAND" : "SD") << ", Mode: " << (mode == INSTALL_CIA ? "Install CIA" : mode == DELETE_CIA ? "Delete CIA" : mode == DELETE_TITLE ? "Delete Title" : "Launch Title") << "\n";
        stream << "L - Switch Destination, R - Switch Mode" << "\n";
        if(mode == INSTALL_CIA) {
            stream << "X - Install all CIAs in the current directory" << "\n";
            stream << "Y - Receive an app over the network" << "\n";
        } else if(mode == DELETE_CIA) {
            stream << "X - Delete all CIAs in the current directory" << "\n";
        }

        stream << "SELECT - Install MSET ROP";

        if(ninjhax) {
            stream << "\n" << "START - Exit to launcher";
        }

        std::string str = stream.str();
        const std::string title = "FBI v1.4.1";
        gputDrawString(title, (gpuGetViewportWidth() - gputGetStringWidth(title, 16)) / 2, (gpuGetViewportHeight() - gputGetStringHeight(title, 16) + gputGetStringHeight(str, 8)) / 2, 16, 16);
        gputDrawString(str, (gpuGetViewportWidth() - gputGetStringWidth(str, 8)) / 2, 4, 8, 8);

        return breakLoop;
    };

    while(platformIsRunning()) {
        if(mode == INSTALL_CIA || mode == DELETE_CIA) {
            uiDisplayMessage(BOTTOM_SCREEN, "Loading file list...");

            std::string fileTarget;
            uiSelectFile(&fileTarget, "/", extensions, [&](const std::string currDirectory, bool inRoot, bool &updateList) {
                if(inputIsPressed(BUTTON_X)) {
                    std::stringstream confirmMsg;
                    if(mode == INSTALL_CIA) {
                        confirmMsg << "Install ";
                    } else {
                        confirmMsg << "Delete ";
                    }

                    confirmMsg << "all CIAs in the current directory?";
                    if(uiPrompt(TOP_SCREEN, confirmMsg.str(), true)) {
                        bool failed = false;
                        std::vector<FileInfo> contents = fsGetDirectoryContents(currDirectory);
                        u32 currItem = 0;
                        for(std::vector<FileInfo>::iterator it = contents.begin(); it != contents.end(); it++) {
                            std::string path = (*it).path;
                            if(!fsIsDirectory(path) && fsHasExtensions(path, extensions)) {
                                std::string displayFileName = (*it).name;
                                if(displayFileName.length() > 40) {
                                    displayFileName.resize(40);
                                    displayFileName += "...";
                                }

                                if(mode == INSTALL_CIA) {
                                    std::stringstream batchInstallStream;
                                    batchInstallStream << displayFileName << " (" << currItem << ")" << "\n";

                                    batchInfo = batchInstallStream.str();
                                    AppResult ret = appInstallFile(destination, path, onProgress);
                                    prevProgress = -1;
                                    batchInfo = "";
                                    if(ret != APP_SUCCESS) {
                                        Error error = platformGetError();
                                        platformSetError(error);

                                        std::stringstream resultMsg;
                                        resultMsg << "Install failed!" << "\n";
                                        resultMsg << displayFileName << "\n";
                                        resultMsg << appGetResultString(ret);
                                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                                        if(error.module != MODULE_NN_AM || error.description != DESCRIPTION_ALREADY_EXISTS) {
                                            failed = true;
                                            break;
                                        }
                                    }
                                } else {
                                    std::stringstream deleteStream;
                                    deleteStream << "Deleting CIA..." << "\n";
                                    deleteStream << displayFileName << " (" << currItem << ")";

                                    uiDisplayMessage(TOP_SCREEN, deleteStream.str());
                                    if(remove(path.c_str()) != 0) {
                                        std::stringstream resultMsg;
                                        resultMsg << "Delete failed!" << "\n";
                                        resultMsg << displayFileName << "\n";
                                        resultMsg << strerror(errno);
                                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                                        failed = true;
                                        break;
                                    } else {
                                        updateList = true;
                                    }
                                }
                            }

                            currItem++;
                        }

                        if(!failed) {
                            uiPrompt(TOP_SCREEN, "Install succeeded!\n", false);
                        }

                        freeSpace = fsGetFreeSpace(destination);
                    }
                }

                return onLoop();
            }, [&](const std::string path, bool &updateList) {
                std::stringstream confirmMsg;
                if(mode == INSTALL_CIA) {
                    confirmMsg << "Install ";
                } else {
                    confirmMsg << "Delete ";
                }

                confirmMsg << "the selected CIA?";
                if(uiPrompt(TOP_SCREEN, confirmMsg.str(), true)) {
                    std::stringstream resultMsg;
                    if(mode == INSTALL_CIA) {
                        resultMsg << "Install ";
                    } else {
                        resultMsg << "Delete ";
                    }

                    if(mode == INSTALL_CIA) {
                        AppResult ret = appInstallFile(destination, path, onProgress);
                        prevProgress = -1;
                        if(ret == APP_SUCCESS) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                        }
                    } else {
                        uiDisplayMessage(TOP_SCREEN, "Deleting CIA...");
                        if(remove(path.c_str()) != 0) {
                            updateList = true;
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << strerror(errno);
                        }
                    }

                    uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                    freeSpace = fsGetFreeSpace(destination);
                }

                return false;
            });
        } else if(mode == DELETE_TITLE || mode == LAUNCH_TITLE) {
            uiDisplayMessage(BOTTOM_SCREEN, "Loading title list...");

            App appTarget;
            uiSelectApp(&appTarget, destination, [&](bool &updateList) {
                return onLoop();
            }, [&](App app, bool &updateList) {
                if(mode == DELETE_TITLE) {
                    if(uiPrompt(TOP_SCREEN, "Delete the selected title?", true) && (destination != NAND || uiPrompt(TOP_SCREEN, "You are about to delete a title from the NAND.\nTHIS HAS THE POTENTIAL TO BRICK YOUR 3DS!\nAre you sure you wish to continue?", true))) {
                        updateList = true;
                        uiDisplayMessage(TOP_SCREEN, "Deleting title...");
                        AppResult ret = appDelete(app);

                        std::stringstream resultMsg;
                        resultMsg << "Delete ";
                        if(ret == APP_SUCCESS) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                        }

                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                        freeSpace = fsGetFreeSpace(destination);
                    }
                } else if(mode == LAUNCH_TITLE) {
                    if(uiPrompt(TOP_SCREEN, "Launch the selected title?", true)) {
                        updateList = true;
                        uiDisplayMessage(TOP_SCREEN, "Launching title...");
                        AppResult ret = appLaunch(app);

                        if(ret != APP_SUCCESS) {
                            std::stringstream resultMsg;
                            resultMsg << "Launch failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                            uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                        } else {
                            while(true) {
                            }
                        }
                    }
                }

                return false;
            });
        }

        if(exit) {
            break;
        }
    }

    platformCleanup();
    return 0;
}
<|endoftext|>


<commit_before>#include "CLIParser.h"

namespace ros2_components
{
CLIParser::CLIParser(char *argv[], int argc, std::string _programDescription)
{

    for(int i=0; i < argc;i++)
    {
        this->arguments.push_back(std::string(argv[i]));

    }
    //0 arg is the program name
    this->baseVerb = std::make_shared<CLIVerb>(arguments[0], _programDescription,nullptr);
    this->baseVerb->addArgument(std::make_shared<CLIArgument>("help", "Print this help", &helpFound ));
}

void CLIParser::parse()
{
    arguments.erase(arguments.begin());
    this->baseVerb->parse(arguments);

    if(helpFound)
    {
        printHelp(this->helpString);
    }
}

void CLIParser::addVerb(CLIVerb::SharedPtr verb)
{
    this->baseVerb->addVerb(verb);
}

void CLIParser::addArgument(CLIArgument::SharedPtr arg)
{
    this->baseVerb->addArgument(arg);
}

void CLIParser::printHelp(std::string additionalInformation)
{
    int depth = 0;
    std::cout <<  additionalInformation << std::endl;
    std::function<void(CLIVerb::SharedPtr)> func = [&](CLIVerb::SharedPtr verb)
    {
        if(!verb)
            return;
        for(int i = 0; i < depth; i++)
            std::cout << " ";

        std::cout << printInColor(verb->getName(),ConsoleColor::FG_BLUE) << std::endl;

        for(int i = 0; i < depth+4; i++)
            std::cout << " ";

        std::cout << verb->getDescription() << std::endl << std::endl;
        if(verb->getAllCliParameter().size() > 0)
        {
            for(int i = 0; i < depth+2; i++)
                std::cout << " ";
            std::cout << "Needed parameters: " << std::endl;
        }

        for(auto cliParam : verb->getAllCliParameter())
        {
            for(int i = 0; i < depth+4; i++)
                std::cout << " ";
            std::string output =  cliParam->getName() + "                     ";
            output.insert(20, cliParam->getDescription());
            std::cout << output << std::endl;
        }

        for(auto cliArg : verb->getAllCliArguments())
        {
            for(int i = 0; i < depth+4; i++)
                std::cout << " ";
            std::string output = " --" + cliArg->getName() + "                     ";
            output.insert(20, cliArg->getDescription());
            std::cout << output << std::endl;
        }

        depth = depth+2;
        for(auto subVerbEntry : verb->getChildVerbs())
        {
            CLIVerb::SharedPtr subVerb = subVerbEntry.second;

            func(subVerb);
        }
        depth = depth-2;

    };
    func(this->baseVerb);
}

bool CLIParser::getHelpFound() const
{
    return helpFound;
}

CLIVerb::SharedPtr CLIParser::getBaseVerb() const
{
    return baseVerb;
}
}
<commit_msg>fixed bug<commit_after>#include "CLIParser.h"

namespace ros2_components
{
CLIParser::CLIParser(char *argv[], int argc, std::string _programDescription)
{

    for(int i=0; i < argc;i++)
    {
        this->arguments.push_back(std::string(argv[i]));

    }
    //0 arg is the program name
    this->baseVerb = std::make_shared<CLIVerb>(arguments[0], _programDescription,nullptr);
    this->baseVerb->addArgument(std::make_shared<CLIArgument>("help", "Print this help", &helpFound ));
}

void CLIParser::parse()
{
    if(arguments.size() <= 0)
        return;
    arguments.erase(arguments.begin());
    this->baseVerb->parse(arguments);

    if(helpFound)
    {
        printHelp(this->helpString);
    }
}

void CLIParser::addVerb(CLIVerb::SharedPtr verb)
{
    this->baseVerb->addVerb(verb);
}

void CLIParser::addArgument(CLIArgument::SharedPtr arg)
{
    this->baseVerb->addArgument(arg);
}

void CLIParser::printHelp(std::string additionalInformation)
{
    int depth = 0;
    std::cout <<  additionalInformation << std::endl;
    std::function<void(CLIVerb::SharedPtr)> func = [&](CLIVerb::SharedPtr verb)
    {
        if(!verb)
            return;
        for(int i = 0; i < depth; i++)
            std::cout << " ";

        std::cout << printInColor(verb->getName(),ConsoleColor::FG_BLUE) << std::endl;

        for(int i = 0; i < depth+4; i++)
            std::cout << " ";

        std::cout << verb->getDescription() << std::endl << std::endl;
        if(verb->getAllCliParameter().size() > 0)
        {
            for(int i = 0; i < depth+2; i++)
                std::cout << " ";
            std::cout << "Needed parameters: " << std::endl;
        }

        for(auto cliParam : verb->getAllCliParameter())
        {
            for(int i = 0; i < depth+4; i++)
                std::cout << " ";
            std::string output =  cliParam->getName() + "                     ";
            output.insert(20, cliParam->getDescription());
            std::cout << output << std::endl;
        }

        for(auto cliArg : verb->getAllCliArguments())
        {
            for(int i = 0; i < depth+4; i++)
                std::cout << " ";
            std::string output = " --" + cliArg->getName() + "                     ";
            output.insert(20, cliArg->getDescription());
            std::cout << output << std::endl;
        }

        depth = depth+2;
        for(auto subVerbEntry : verb->getChildVerbs())
        {
            CLIVerb::SharedPtr subVerb = subVerbEntry.second;

            func(subVerb);
        }
        depth = depth-2;

    };
    func(this->baseVerb);
}

bool CLIParser::getHelpFound() const
{
    return helpFound;
}

CLIVerb::SharedPtr CLIParser::getBaseVerb() const
{
    return baseVerb;
}
}
<|endoftext|>