<commit_before>#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <map>
#include <utility>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <vector>
#include <string>
#include <iostream>

#include "functions.h"

int main(int argc, char** argv) {
  std::string prompt;
  getPrompt(prompt);

  bool quit = false;

  // print welcome message and prompt
  printf("Welcome to rshell!\n");

  while (!quit) {
    // holds a single command and its arguments
    Command_t cmd;
    // holds multiple commands
    std::vector<Command_t> cmds;
    // hold a raw line of input
    std::string line;

    // print prompt and get a line of text (done in condition)
    printf("%s", prompt.c_str());
    preProcessLine(line);

    int mode = GETWORD;
    unsigned begin = 0;

    // prepare cmd
    cmd.connector = NONE;

    // syntax error flag
    bool se = false;

    // starts with a connector? I don't think so
    if (line.size() > 0 && isConn(line[0]) && line[0] != ';') {
      se = true;
    } else if (line.size() > 0 && (isRedir(line[0]) || isdigit(line[0]))) {
      mode = GETREDIR;
    }

    // handle the input
    for(unsigned i = 0; i < line.size() && !se; ++i) {
      bool con   = isConn(line[i]);
      // bool dig   = isdigit(line[i]);
      bool redir = isRedir(line[i]);
      bool space = isspace(line[i]);

      // if we're getting a word and there's a whitespace or connector here
      if (mode == GETWORD && (space || con || redir)) {
        // only happens for blank lines:
        if (i == 0 && con) break;
        if (redir) {
          mode = GETREDIR;
          continue;
        }
        // chunk the last term and throw it into the vector
        addArg(cmd, line, begin, i);

        if (space) {
          mode = TRIMSPACE;
        } else if (con) {
          handleCon(cmds, cmd, line, mode, begin, i, se);
        }
      } else if (mode == TRIMSPACE && !space) {
        if (con && cmd.args.empty() && line[i] != ';') {
          se = true;
        } else if (con) {
          handleCon(cmds, cmd, line, mode, begin, i, se);
        } else if (redir) {
          begin = i;
          mode = GETREDIR;
        } else {
          begin = i;
          mode = GETWORD;
        }
      } else if (mode == HANDLESEMI && line[i] != ';') {
        if (isConn(line[i])) {
          se = true;
        } else if (isspace(line[i])) {
          mode = TRIMSPACE;
        } else { // it's a word
          begin = i;
          mode = GETWORD;
        }
      } else if (mode == GETREDIR && line[i] == '"') {
        mode = GETSTRING;
      } else if (mode == GETREDIR && space) {
        handleRedir(cmds, cmd, line, mode, begin, i, se);
        mode = TRIMSPACE;
      } else if (mode == GETSTRING && line[i] == '"') {
        mode = ENDQUOTE;
      } else if (mode == ENDQUOTE) {
        if (space) {
          handleRedir(cmds, cmd, line, mode, begin, i, se);
          mode = TRIMSPACE;
        } else {
          se = true;
          continue;
        }
      }
    }

    // if the last command has a continuation connector, syntax error
    if (cmds.size() > 0 && (cmds[cmds.size()-1].connector == AND
                        ||  cmds[cmds.size()-1].connector == OR
                        ||  cmds[cmds.size()-1].connector == PIPE)) {
      se = true;
    }

    if (mode == GETSTRING) se = true;

    // if there was a syntax error
    if (se) {
      printf("Syntax error\n");
      continue;
    }

    /*
    for(unsigned i = 0; i < cmds.size(); ++i) {
      for(unsigned j = 0; j < cmds[i].args.size(); ++j) {
        printf("cmd %d arg %d: \"%s\"\n", i, j, cmds[i].args[j]);
      }
      if (cmds[i].connector == NONE) printf("connector: NONE\n");
      else if (cmds[i].connector == AND) printf("connector: AND\n");
      else if (cmds[i].connector == OR) printf("connector: OR\n");
      else if (cmds[i].connector == SEMI) printf("connector: SEMI\n");
      else if (cmds[i].connector == PIPE) printf("connector: PIPE\n");
      printf("file descriptor modifications:\n");
      for(unsigned j = 0; j < cmds[i].fdChanges.size(); ++j) {
        if (cmds[i].fdChanges[j].type == INPUT) {
          printf("change fd %d to ",
          (cmds[i].fdChanges[j].orig == DEFAULT) ? 0 :
           cmds[i].fdChanges[j].orig);

          if (cmds[i].fdChanges[j].moveTo == UNDEFINED)
            printf("UNDEFINED\n");
          else if (cmds[i].fdChanges[j].moveTo == FROMSTR)
            printf("FROMSTR (\"%s\")\n", cmds[i].fdChanges[j].s.c_str());
          else
            printf("Some other fd (%d)\n", cmds[i].fdChanges[j].moveTo);
        }

        if (cmds[i].fdChanges[j].type == OUTPUT) {
          printf("change fd %d to ",
          (cmds[i].fdChanges[j].orig == DEFAULT) ? 1 :
           cmds[i].fdChanges[j].orig);

          if (cmds[i].fdChanges[j].moveTo == UNDEFINED)
            printf("UNDEFINED\n");
          else
            printf("Some other fd (%d)\n", cmds[i].fdChanges[j].moveTo);
        }
      }
    }
    // *///

    // now to execute all the commands
    int pa[2];
    for(unsigned i = 0; i < cmds.size(); ++i) {
      size_t argsSize = cmds[i].args.size();
      int exitStatus = 0;

      char* arg = cmds[i].args[0];
      if (strcmp(arg, "exit") == 0) {
        quit = true;
        break;
      }
      char** argv = new char*[argsSize+1];
      for(unsigned j = 0; j < argsSize; ++j) {
        argv[j] = cmds[i].args[j];
      }
      argv[argsSize] = 0;

      if (cmds[i].connector == PIPE) {
        // 1. make pipe
        if (-1 == pipe(pa)) {
          perror("pipe");
          exit(1);
        }
        // 2. this program gets output and next program gets input
        // this program:
        fdChange_t outfdC(1, pa[1], OUTPUT);
        fdChange_t infdC(0, pa[0], INPUT);

        cmds[i].fdChanges.push_back(outfdC);
        cmds[i].closefd.push_back(pa[1]);
        // next program:
        cmds[i+1].fdChanges.push_back(infdC);
        cmds[i+1].closefd.push_back(pa[0]);

      }

      std::map<int, fdData_t> fds;
      for(unsigned j = 0; j < cmds[i].fdChanges.size(); ++j) {
        int o           = cmds[i].fdChanges[j].orig;
        int mt          = cmds[i].fdChanges[j].moveTo;
        int t           = cmds[i].fdChanges[j].type;
        std::string str = cmds[i].fdChanges[j].s;

        if (t == INPUT) {
          if (mt == FILEIN) {
            fds.insert(std::pair<int, fdData_t>(o, fdData_t(-1, DT_FIN, str)));
            // printf("Adding %d pointing to the file %s in input mode\n", o, str.c_str());
          } else if (mt == FROMSTR) {
            fds.insert(std::pair<int, fdData_t>(o, fdData_t(-1, DT_STR, str)));
            // printf("Adding %d pointing to the string %s in input mode\n", o, str.c_str());
          } else {
            fds.insert(std::pair<int, fdData_t>(o, fdData_t(mt, DT_FDIN, str)));
            // printf("Adding %d pointing to the fd %d in input mode\n", mt, o);
          }
        } else if (t == OUTPUT) {
          if (mt == FILEOUT) {
            fds.insert(std::pair<int, fdData_t>(-1, fdData_t(o, DT_FOW, str)));
            // printf("Adding %d pointing to the file %s in output write mode\n", o, str.c_str());
          } else if (mt == FILEAPP) {
            // if (fds
            fds.insert(std::pair<int, fdData_t>(-1, fdData_t(o, DT_FOA, str)));
            // printf("Adding %d pointing to the file %s in output append mode\n", o, str.c_str());
          } else {
            fds.insert(std::pair<int, fdData_t>(mt, fdData_t(o, DT_FDO, str)));
            // printf("Adding %d pointing to the fd %d in output mode\n", o, mt);
          }
        }
      }
      debugMap(fds);

      // arg and argv are now prepared
      pid_t pid = fork();
      if (-1 == pid) {
        perror("fork");
        exit(1); // fatal error
      } else if (0 == pid) { // child process
        deltaFD(fds);
        if (-1 == execvp(arg, argv)) {
          // if there's a return value (-1), there was a problem
          perror(arg);
          delete[] argv;
          exit(1);
        }
      } else { // parent process
        // close current fd's
        /*
        for(unsigned j = 0; j < cmds[i].closefd.size(); ++j) {
          if (-1 == close(cmds[i].closefd[j])) {
            perror("closing in parent");
            exit(1);
          }
        } */
        // only wait for non-pipes
        if (cmds[i].connector != PIPE && -1 == waitpid(pid, &exitStatus, 0)) {
          perror("waitpid");
          exit(1);
        }
      }
      if (!exitStatus) { // all is good (0)
        while (i < cmds.size() && cmds[i].connector == OR) {
          ++i;
        }
      } else { // last command failed
        while (i < cmds.size() && cmds[i].connector == AND) {
          ++i;
        }
      }
    }

    // deallocate allocated memory
    for(unsigned i = 0; i < cmds.size(); ++i) {
      for(unsigned j = 0; j < cmds[i].args.size(); ++j) {
        delete[] cmds[i].args[j];
      }
    }
  }
  printf("Goodbye!\n");
  return 0;
}

<commit_msg>removed execvp and added ability to manually search for paths<commit_after>#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <map>
#include <utility>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <vector>
#include <string>
#include <iostream>

#include "functions.h"

int main(int argc, char** argv) {
  std::string prompt;
  getPrompt(prompt);

  bool quit = false;

  // print welcome message and prompt
  printf("Welcome to rshell!\n");

  while (!quit) {
    // holds a single command and its arguments
    Command_t cmd;
    // holds multiple commands
    std::vector<Command_t> cmds;
    // hold a raw line of input
    std::string line;

    // print prompt and get a line of text (done in condition)
    printf("%s", prompt.c_str());
    preProcessLine(line);

    int mode = GETWORD;
    unsigned begin = 0;

    // prepare cmd
    cmd.connector = NONE;

    // syntax error flag
    bool se = false;

    // starts with a connector? I don't think so
    if (line.size() > 0 && isConn(line[0]) && line[0] != ';') {
      se = true;
    } else if (line.size() > 0 && (isRedir(line[0]) || isdigit(line[0]))) {
      mode = GETREDIR;
    }

    // handle the input
    for(unsigned i = 0; i < line.size() && !se; ++i) {
      bool con   = isConn(line[i]);
      // bool dig   = isdigit(line[i]);
      bool redir = isRedir(line[i]);
      bool space = isspace(line[i]);

      // if we're getting a word and there's a whitespace or connector here
      if (mode == GETWORD && (space || con || redir)) {
        // only happens for blank lines:
        if (i == 0 && con) break;
        if (redir) {
          mode = GETREDIR;
          continue;
        }
        // chunk the last term and throw it into the vector
        addArg(cmd, line, begin, i);

        if (space) {
          mode = TRIMSPACE;
        } else if (con) {
          handleCon(cmds, cmd, line, mode, begin, i, se);
        }
      } else if (mode == TRIMSPACE && !space) {
        if (con && cmd.args.empty() && line[i] != ';') {
          se = true;
        } else if (con) {
          handleCon(cmds, cmd, line, mode, begin, i, se);
        } else if (redir) {
          begin = i;
          mode = GETREDIR;
        } else {
          begin = i;
          mode = GETWORD;
        }
      } else if (mode == HANDLESEMI && line[i] != ';') {
        if (isConn(line[i])) {
          se = true;
        } else if (isspace(line[i])) {
          mode = TRIMSPACE;
        } else { // it's a word
          begin = i;
          mode = GETWORD;
        }
      } else if (mode == GETREDIR && line[i] == '"') {
        mode = GETSTRING;
      } else if (mode == GETREDIR && space) {
        handleRedir(cmds, cmd, line, mode, begin, i, se);
        mode = TRIMSPACE;
      } else if (mode == GETSTRING && line[i] == '"') {
        mode = ENDQUOTE;
      } else if (mode == ENDQUOTE) {
        if (space) {
          handleRedir(cmds, cmd, line, mode, begin, i, se);
          mode = TRIMSPACE;
        } else {
          se = true;
          continue;
        }
      }
    }

    // if the last command has a continuation connector, syntax error
    if (cmds.size() > 0 && (cmds[cmds.size()-1].connector == AND
                        ||  cmds[cmds.size()-1].connector == OR
                        ||  cmds[cmds.size()-1].connector == PIPE)) {
      se = true;
    }

    if (mode == GETSTRING) se = true;

    // if there was a syntax error
    if (se) {
      printf("Syntax error\n");
      continue;
    }

    /* code for debugging
    for(unsigned i = 0; i < cmds.size(); ++i) {
      for(unsigned j = 0; j < cmds[i].args.size(); ++j) {
        printf("cmd %d arg %d: \"%s\"\n", i, j, cmds[i].args[j]);
      }
      if (cmds[i].connector == NONE) printf("connector: NONE\n");
      else if (cmds[i].connector == AND) printf("connector: AND\n");
      else if (cmds[i].connector == OR) printf("connector: OR\n");
      else if (cmds[i].connector == SEMI) printf("connector: SEMI\n");
      else if (cmds[i].connector == PIPE) printf("connector: PIPE\n");
      printf("file descriptor modifications:\n");
      for(unsigned j = 0; j < cmds[i].fdChanges.size(); ++j) {
        if (cmds[i].fdChanges[j].type == INPUT) {
          printf("change fd %d to ",
          (cmds[i].fdChanges[j].orig == DEFAULT) ? 0 :
           cmds[i].fdChanges[j].orig);

          if (cmds[i].fdChanges[j].moveTo == UNDEFINED)
            printf("UNDEFINED\n");
          else if (cmds[i].fdChanges[j].moveTo == FROMSTR)
            printf("FROMSTR (\"%s\")\n", cmds[i].fdChanges[j].s.c_str());
          else
            printf("Some other fd (%d)\n", cmds[i].fdChanges[j].moveTo);
        }

        if (cmds[i].fdChanges[j].type == OUTPUT) {
          printf("change fd %d to ",
          (cmds[i].fdChanges[j].orig == DEFAULT) ? 1 :
           cmds[i].fdChanges[j].orig);

          if (cmds[i].fdChanges[j].moveTo == UNDEFINED)
            printf("UNDEFINED\n");
          else
            printf("Some other fd (%d)\n", cmds[i].fdChanges[j].moveTo);
        }
      }
    }
    // */

    // now to execute all the commands
    // pipe
    int pa[2];
    std::vector<char*> paths;
    // getPaths
    fillPaths(paths);
    for(unsigned cmdi = 0; cmdi < cmds.size(); ++cmdi) {
      size_t argsSize = cmds[cmdi].args.size();
      int exitStatus = 0;

      char* arg = cmds[cmdi].args[0];
      if (strcmp(arg, "exit") == 0) {
        quit = true;
        break;
      }
      char** argv = new char*[argsSize+1];
      for(unsigned j = 0; j < argsSize; ++j) {
        argv[j] = cmds[cmdi].args[j];
      }
      argv[argsSize] = 0;

      if (cmds[cmdi].connector == PIPE) {
        // 1. make pipe
        if (-1 == pipe(pa)) {
          perror("pipe");
          exit(1);
        }
        // 2. this program gets output and next program gets input
        // this program:
        fdChange_t outfdC(1, pa[1], OUTPUT);
        fdChange_t infdC(0, pa[0], INPUT);

        cmds[cmdi].fdChanges.push_back(outfdC);
        cmds[cmdi].closefd.push_back(pa[1]);
        // next program:
        cmds[cmdi+1].fdChanges.push_back(infdC);
        cmds[cmdi+1].closefd.push_back(pa[0]);

      }

      std::map<int, fdData_t> fds;
      for(unsigned j = 0; j < cmds[cmdi].fdChanges.size(); ++j) {
        int o           = cmds[cmdi].fdChanges[j].orig;
        int mt          = cmds[cmdi].fdChanges[j].moveTo;
        int t           = cmds[cmdi].fdChanges[j].type;
        std::string str = cmds[cmdi].fdChanges[j].s;

        if (t == INPUT) {
          if (mt == FILEIN) {
            fds.insert(std::pair<int, fdData_t>(o, fdData_t(-1, DT_FIN, str)));
            // printf("Adding %d pointing to the file %s in input mode\n", o, str.c_str());
          } else if (mt == FROMSTR) {
            fds.insert(std::pair<int, fdData_t>(o, fdData_t(-1, DT_STR, str)));
            // printf("Adding %d pointing to the string %s in input mode\n", o, str.c_str());
          } else {
            fds.insert(std::pair<int, fdData_t>(o, fdData_t(mt, DT_FDIN, str)));
            // printf("Adding %d pointing to the fd %d in input mode\n", mt, o);
          }
        } else if (t == OUTPUT) {
          if (mt == FILEOUT) {
            fds.insert(std::pair<int, fdData_t>(-1, fdData_t(o, DT_FOW, str)));
            // printf("Adding %d pointing to the file %s in output write mode\n", o, str.c_str());
          } else if (mt == FILEAPP) {
            // if (fds
            fds.insert(std::pair<int, fdData_t>(-1, fdData_t(o, DT_FOA, str)));
            // printf("Adding %d pointing to the file %s in output append mode\n", o, str.c_str());
          } else {
            fds.insert(std::pair<int, fdData_t>(mt, fdData_t(o, DT_FDO, str)));
            // printf("Adding %d pointing to the fd %d in output mode\n", o, mt);
          }
        }
      }
      debugMap(fds);

      // arg and argv are now prepared
      pid_t pid = fork();
      if (-1 == pid) {
        perror("fork");
        exit(1); // fatal error
      } else if (0 == pid) { // child process
        deltaFD(fds);
        for(unsigned i = 0; i < paths.size(); ++i) {
          char* executable = new char[strlen(paths[i]) + strlen(arg) + 2];
          strcpy(executable, paths[i]);
          strcat(executable, "/");
          strcat(executable, arg);
          struct stat statRes;
          if (-1 != stat(executable, &statRes)) {
            if (-1 == execv(executable, argv)) {
              // if there's a return value (-1), there was a problem
              debug("executing");
              perror(executable);
              delete[] argv;
              delete[] executable;
              exit(1);
            }
          }
          errno = 0;
          delete[] executable;
        }
        fprintf(stderr, "%s: command not found\n", arg);
        exit(1);
      } else { // parent process
        // close current fd's
        /*
        for(unsigned j = 0; j < cmds[cmdi].closefd.size(); ++j) {
          if (-1 == close(cmds[cmdi].closefd[j])) {
            perror("closing in parent");
            exit(1);
          }
        } */
        // only wait for non-pipes
        if (cmds[cmdi].connector != PIPE && -1 == waitpid(pid, &exitStatus, 0)) {
          perror("waitpid");
          exit(1);
        }
      }
      if (!exitStatus) { // all is good (0)
        while (cmdi < cmds.size() && cmds[cmdi].connector == OR) {
          ++cmdi;
        }
      } else { // last command failed
        while (cmdi < cmds.size() && cmds[cmdi].connector == AND) {
          ++cmdi;
        }
      }
    }

    // deallocate allocated memory
    for(unsigned i = 0; i < cmds.size(); ++i) {
      for(unsigned j = 0; j < cmds[i].args.size(); ++j) {
        delete[] cmds[i].args[j];
      }
    }
    for(unsigned i = 0; i < paths.size(); ++i) {
      delete[] paths[i];
    }
  }
  printf("Goodbye!\n");
  return 0;
}

<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <getopt.h>

#include <string>
#include <vector>

#include "sequence.hpp"
#include "polisher.hpp"
#ifdef CUDA_ENABLED
#include "cuda/cudapolisher.hpp"
#endif

#ifndef RACON_VERSION
#error "Undefined version for Racon. Please pass version using -DRACON_VERSION macro."
#endif

static const char* version = RACON_VERSION;
static const int32_t CUDAALIGNER_INPUT_CODE = 10000;
static const int32_t CUDAALIGNER_BAND_WIDTH_INPUT_CODE = 10001;

static struct option options[] = {
    {"include-unpolished", no_argument, 0, 'u'},
    {"fragment-correction", no_argument, 0, 'f'},
    {"window-length", required_argument, 0, 'w'},
    {"quality-threshold", required_argument, 0, 'q'},
    {"error-threshold", required_argument, 0, 'e'},
    {"no-trimming", no_argument, 0, 'T'},
    {"match", required_argument, 0, 'm'},
    {"mismatch", required_argument, 0, 'x'},
    {"gap", required_argument, 0, 'g'},
    {"threads", required_argument, 0, 't'},
    {"version", no_argument, 0, 'v'},
    {"help", no_argument, 0, 'h'},
#ifdef CUDA_ENABLED
    {"cudapoa-batches", optional_argument, 0, 'c'},
    {"cuda-banded-alignment", no_argument, 0, 'b'},
    {"cudaaligner-batches", required_argument, 0, CUDAALIGNER_INPUT_CODE},
    {"cudaaligner-band-width", required_argument, 0, CUDAALIGNER_BAND_WIDTH_INPUT_CODE},
#endif
    {0, 0, 0, 0}
};

void help();

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

    std::vector<std::string> input_paths;

    uint32_t window_length = 500;
    double quality_threshold = 10.0;
    double error_threshold = 0.3;
    bool trim = true;

    int8_t match = 3;
    int8_t mismatch = -5;
    int8_t gap = -4;
    uint32_t type = 0;

    bool drop_unpolished_sequences = true;
    uint32_t num_threads = 1;

    uint32_t cudapoa_batches = 0;
    uint32_t cudaaligner_batches = 0;
    uint32_t cudaaligner_band_width = 1024;
    bool cuda_banded_alignment = false;

    std::string optstring = "ufw:q:e:m:x:g:t:h";
#ifdef CUDA_ENABLED
    optstring += "bc::";
#endif

    int32_t argument;
    while ((argument = getopt_long(argc, argv, optstring.c_str(), options, nullptr)) != -1) {
        switch (argument) {
            case 'u':
                drop_unpolished_sequences = false;
                break;
            case 'f':
                type = 1;
                break;
            case 'w':
                window_length = atoi(optarg);
                break;
            case 'q':
                quality_threshold = atof(optarg);
                break;
            case 'e':
                error_threshold = atof(optarg);
                break;
            case 'T':
                trim = false;
                break;
            case 'm':
                match = atoi(optarg);
                break;
            case 'x':
                mismatch = atoi(optarg);
                break;
            case 'g':
                gap = atoi(optarg);
                break;
            case 't':
                num_threads = atoi(optarg);
                break;
            case 'v':
                printf("%s\n", version);
                exit(0);
            case 'h':
                help();
                exit(0);
#ifdef CUDA_ENABLED
            case 'c':
                //if option c encountered, cudapoa_batches initialized with a default value of 1.
                cudapoa_batches = 1;
                // next text entry is not an option, assuming it's the arg for option 'c'
                if (optarg == NULL && argv[optind] != NULL
                    && argv[optind][0] != '-') {
                    cudapoa_batches = atoi(argv[optind++]);
                }
                // optional argument provided in the ususal way
                if (optarg != NULL) {
                    cudapoa_batches = atoi(optarg);
                }
                break;
            case 'b':
                cuda_banded_alignment = true;
                break;
            case CUDAALIGNER_INPUT_CODE: // cudaaligner-batches
                cudaaligner_batches = atoi(optarg);
                break;
            case CUDAALIGNER_BAND_WIDTH_INPUT_CODE: // cudaaligner-band-width
                cudaaligner_band_width = atoi(optarg);
                break;
#endif
            default:
                exit(1);
        }
    }

    for (int32_t i = optind; i < argc; ++i) {
        input_paths.emplace_back(argv[i]);
    }

    if (input_paths.size() < 3) {
        fprintf(stderr, "[racon::] error: missing input file(s)!\n");
        help();
        exit(1);
    }

    auto polisher = racon::createPolisher(input_paths[0], input_paths[1],
        input_paths[2], type == 0 ? racon::PolisherType::kC :
        racon::PolisherType::kF, window_length, quality_threshold,
        error_threshold, trim, match, mismatch, gap, num_threads,
        cudapoa_batches, cuda_banded_alignment, cudaaligner_batches,
        cudaaligner_band_width);

    polisher->initialize();

    std::vector<std::unique_ptr<racon::Sequence>> polished_sequences;
    polisher->polish(polished_sequences, drop_unpolished_sequences);

    for (const auto& it: polished_sequences) {
        fprintf(stdout, ">%s\n%s\n", it->name().c_str(), it->data().c_str());
    }

    return 0;
}

void help() {
    printf(
        "usage: racon [options ...] <sequences> <overlaps> <target sequences>\n"
        "\n"
        "    #default output is stdout\n"
        "    <sequences>\n"
        "        input file in FASTA/FASTQ format (can be compressed with gzip)\n"
        "        containing sequences used for correction\n"
        "    <overlaps>\n"
        "        input file in MHAP/PAF/SAM format (can be compressed with gzip)\n"
        "        containing overlaps between sequences and target sequences\n"
        "    <target sequences>\n"
        "        input file in FASTA/FASTQ format (can be compressed with gzip)\n"
        "        containing sequences which will be corrected\n"
        "\n"
        "    options:\n"
        "        -u, --include-unpolished\n"
        "            output unpolished target sequences\n"
        "        -f, --fragment-correction\n"
        "            perform fragment correction instead of contig polishing\n"
        "            (overlaps file should contain dual/self overlaps!)\n"
        "        -w, --window-length <int>\n"
        "            default: 500\n"
        "            size of window on which POA is performed\n"
        "        -q, --quality-threshold <float>\n"
        "            default: 10.0\n"
        "            threshold for average base quality of windows used in POA\n"
        "        -e, --error-threshold <float>\n"
        "            default: 0.3\n"
        "            maximum allowed error rate used for filtering overlaps\n"
        "        --no-trimming\n"
        "            disables consensus trimming at window ends\n"
        "        -m, --match <int>\n"
        "            default: 3\n"
        "            score for matching bases\n"
        "        -x, --mismatch <int>\n"
        "            default: -5\n"
        "            score for mismatching bases\n"
        "        -g, --gap <int>\n"
        "            default: -4\n"
        "            gap penalty (must be negative)\n"
        "        -t, --threads <int>\n"
        "            default: 1\n"
        "            number of threads\n"
        "        --version\n"
        "            prints the version number\n"
        "        -h, --help\n"
        "            prints the usage\n"
#ifdef CUDA_ENABLED
        "        -c, --cudapoa-batches <int>\n"
        "            default: 0\n"
        "            number of batches for CUDA accelerated polishing per GPU\n"
        "        -b, --cuda-banded-alignment\n"
        "            use banding approximation for alignment on GPU\n"
        "        --cudaaligner-batches <int>\n"
        "            default: 0\n"
        "            number of batches for CUDA accelerated alignment per GPU\n"
        "        --cudaaligner-band-width <int>\n"
        "            default: 0\n"
        "            Band width for cuda alignment. Must be >= 0. Non-zero allows user defined \n"
        "            band width, whereas 0 implies auto band width determination.\n"
#endif
    );
}
<commit_msg>[main] update cudaaligner default band to 0<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <getopt.h>

#include <string>
#include <vector>

#include "sequence.hpp"
#include "polisher.hpp"
#ifdef CUDA_ENABLED
#include "cuda/cudapolisher.hpp"
#endif

#ifndef RACON_VERSION
#error "Undefined version for Racon. Please pass version using -DRACON_VERSION macro."
#endif

static const char* version = RACON_VERSION;
static const int32_t CUDAALIGNER_INPUT_CODE = 10000;
static const int32_t CUDAALIGNER_BAND_WIDTH_INPUT_CODE = 10001;

static struct option options[] = {
    {"include-unpolished", no_argument, 0, 'u'},
    {"fragment-correction", no_argument, 0, 'f'},
    {"window-length", required_argument, 0, 'w'},
    {"quality-threshold", required_argument, 0, 'q'},
    {"error-threshold", required_argument, 0, 'e'},
    {"no-trimming", no_argument, 0, 'T'},
    {"match", required_argument, 0, 'm'},
    {"mismatch", required_argument, 0, 'x'},
    {"gap", required_argument, 0, 'g'},
    {"threads", required_argument, 0, 't'},
    {"version", no_argument, 0, 'v'},
    {"help", no_argument, 0, 'h'},
#ifdef CUDA_ENABLED
    {"cudapoa-batches", optional_argument, 0, 'c'},
    {"cuda-banded-alignment", no_argument, 0, 'b'},
    {"cudaaligner-batches", required_argument, 0, CUDAALIGNER_INPUT_CODE},
    {"cudaaligner-band-width", required_argument, 0, CUDAALIGNER_BAND_WIDTH_INPUT_CODE},
#endif
    {0, 0, 0, 0}
};

void help();

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

    std::vector<std::string> input_paths;

    uint32_t window_length = 500;
    double quality_threshold = 10.0;
    double error_threshold = 0.3;
    bool trim = true;

    int8_t match = 3;
    int8_t mismatch = -5;
    int8_t gap = -4;
    uint32_t type = 0;

    bool drop_unpolished_sequences = true;
    uint32_t num_threads = 1;

    uint32_t cudapoa_batches = 0;
    uint32_t cudaaligner_batches = 0;
    uint32_t cudaaligner_band_width = 0;
    bool cuda_banded_alignment = false;

    std::string optstring = "ufw:q:e:m:x:g:t:h";
#ifdef CUDA_ENABLED
    optstring += "bc::";
#endif

    int32_t argument;
    while ((argument = getopt_long(argc, argv, optstring.c_str(), options, nullptr)) != -1) {
        switch (argument) {
            case 'u':
                drop_unpolished_sequences = false;
                break;
            case 'f':
                type = 1;
                break;
            case 'w':
                window_length = atoi(optarg);
                break;
            case 'q':
                quality_threshold = atof(optarg);
                break;
            case 'e':
                error_threshold = atof(optarg);
                break;
            case 'T':
                trim = false;
                break;
            case 'm':
                match = atoi(optarg);
                break;
            case 'x':
                mismatch = atoi(optarg);
                break;
            case 'g':
                gap = atoi(optarg);
                break;
            case 't':
                num_threads = atoi(optarg);
                break;
            case 'v':
                printf("%s\n", version);
                exit(0);
            case 'h':
                help();
                exit(0);
#ifdef CUDA_ENABLED
            case 'c':
                //if option c encountered, cudapoa_batches initialized with a default value of 1.
                cudapoa_batches = 1;
                // next text entry is not an option, assuming it's the arg for option 'c'
                if (optarg == NULL && argv[optind] != NULL
                    && argv[optind][0] != '-') {
                    cudapoa_batches = atoi(argv[optind++]);
                }
                // optional argument provided in the ususal way
                if (optarg != NULL) {
                    cudapoa_batches = atoi(optarg);
                }
                break;
            case 'b':
                cuda_banded_alignment = true;
                break;
            case CUDAALIGNER_INPUT_CODE: // cudaaligner-batches
                cudaaligner_batches = atoi(optarg);
                break;
            case CUDAALIGNER_BAND_WIDTH_INPUT_CODE: // cudaaligner-band-width
                cudaaligner_band_width = atoi(optarg);
                break;
#endif
            default:
                exit(1);
        }
    }

    for (int32_t i = optind; i < argc; ++i) {
        input_paths.emplace_back(argv[i]);
    }

    if (input_paths.size() < 3) {
        fprintf(stderr, "[racon::] error: missing input file(s)!\n");
        help();
        exit(1);
    }

    auto polisher = racon::createPolisher(input_paths[0], input_paths[1],
        input_paths[2], type == 0 ? racon::PolisherType::kC :
        racon::PolisherType::kF, window_length, quality_threshold,
        error_threshold, trim, match, mismatch, gap, num_threads,
        cudapoa_batches, cuda_banded_alignment, cudaaligner_batches,
        cudaaligner_band_width);

    polisher->initialize();

    std::vector<std::unique_ptr<racon::Sequence>> polished_sequences;
    polisher->polish(polished_sequences, drop_unpolished_sequences);

    for (const auto& it: polished_sequences) {
        fprintf(stdout, ">%s\n%s\n", it->name().c_str(), it->data().c_str());
    }

    return 0;
}

void help() {
    printf(
        "usage: racon [options ...] <sequences> <overlaps> <target sequences>\n"
        "\n"
        "    #default output is stdout\n"
        "    <sequences>\n"
        "        input file in FASTA/FASTQ format (can be compressed with gzip)\n"
        "        containing sequences used for correction\n"
        "    <overlaps>\n"
        "        input file in MHAP/PAF/SAM format (can be compressed with gzip)\n"
        "        containing overlaps between sequences and target sequences\n"
        "    <target sequences>\n"
        "        input file in FASTA/FASTQ format (can be compressed with gzip)\n"
        "        containing sequences which will be corrected\n"
        "\n"
        "    options:\n"
        "        -u, --include-unpolished\n"
        "            output unpolished target sequences\n"
        "        -f, --fragment-correction\n"
        "            perform fragment correction instead of contig polishing\n"
        "            (overlaps file should contain dual/self overlaps!)\n"
        "        -w, --window-length <int>\n"
        "            default: 500\n"
        "            size of window on which POA is performed\n"
        "        -q, --quality-threshold <float>\n"
        "            default: 10.0\n"
        "            threshold for average base quality of windows used in POA\n"
        "        -e, --error-threshold <float>\n"
        "            default: 0.3\n"
        "            maximum allowed error rate used for filtering overlaps\n"
        "        --no-trimming\n"
        "            disables consensus trimming at window ends\n"
        "        -m, --match <int>\n"
        "            default: 3\n"
        "            score for matching bases\n"
        "        -x, --mismatch <int>\n"
        "            default: -5\n"
        "            score for mismatching bases\n"
        "        -g, --gap <int>\n"
        "            default: -4\n"
        "            gap penalty (must be negative)\n"
        "        -t, --threads <int>\n"
        "            default: 1\n"
        "            number of threads\n"
        "        --version\n"
        "            prints the version number\n"
        "        -h, --help\n"
        "            prints the usage\n"
#ifdef CUDA_ENABLED
        "        -c, --cudapoa-batches <int>\n"
        "            default: 0\n"
        "            number of batches for CUDA accelerated polishing per GPU\n"
        "        -b, --cuda-banded-alignment\n"
        "            use banding approximation for alignment on GPU\n"
        "        --cudaaligner-batches <int>\n"
        "            default: 0\n"
        "            number of batches for CUDA accelerated alignment per GPU\n"
        "        --cudaaligner-band-width <int>\n"
        "            default: 0\n"
        "            Band width for cuda alignment. Must be >= 0. Non-zero allows user defined \n"
        "            band width, whereas 0 implies auto band width determination.\n"
#endif
    );
}
<|endoftext|>


<commit_before>#include <iostream>

#include "systems/OpenGLSystem.h"
#include "systems/SimplePhysics.h"
#include "systems/FactorySystem.h"
#include "controllers/GLSixDOFViewController.h"
#include "components/ViewMover.h"
#include "SCParser.h"

#if defined OS_Win32
#include "os/win32/win32.h"
#elif defined OS_SDL
#include "os/sdl/SDLSys.h"
#endif

int main(int argCount, char **argValues) {
	OpenGLSystem glsys;
	SimplePhysics physys;
	FactorySystem::getInstance().register_Factory(&glsys);
	FactorySystem::getInstance().register_Factory(&physys);
	IOpSys* os = nullptr;
#if defined OS_Win32
	os = new win32();
#elif defined OS_SDL
	os = new SDLSys();
#endif

	if(os->CreateGraphicsWindow(1024,768) == 0) {
		std::cout << "Error creating window!" << std::endl;
	}

	const int* version = glsys.Start();
	glsys.SetViewportSize(os->GetWindowWidth(), os->GetWindowHeight());

	if (version[0] == -1) {
		std::cout << "Error starting OpenGL!" << std::endl;
	} else {
		std::cout << "OpenGL version: " << version[0] << "." << version[1] << std::endl;
	}

	Sigma::parser::SCParser parser;

	if (!parser.Parse("test.sc")) {
		assert(0 && "Failed to load entities from file.");
	}

	for (unsigned int i = 0; i < parser.EntityCount(); ++i) {
		const Sigma::parser::Entity* e = parser.GetEntity(i);
		for (auto itr = e->components.begin(); itr != e->components.end(); ++itr) {
            FactorySystem::getInstance().create(
                        itr->type,e->id,
                        const_cast<std::vector<Property>&>(itr->properties));
		}
	}

	std::vector<Property> props;
	physys.createViewMover("ViewMover", 9, props);
	ViewMover* mover = reinterpret_cast<ViewMover*>(physys.getComponent(9,ViewMover::getStaticComponentID()));
	Sigma::event::handler::GLSixDOFViewController cameraController(glsys.View(), mover);
	IOpSys::KeyboardEventSystem.Register(&cameraController);

	os->SetupTimer();

	double delta;
	bool isWireframe=false;

	while (os->MessageLoop()) {
		delta = os->GetDeltaTime();
		double deltaSec = (double)delta/100.0f;

		if (os->KeyReleased('P', true)) { // Wireframe mode
			if (!isWireframe) {
				glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
				isWireframe = true;
			} else {
				glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
				isWireframe = false;
			}
		}

		if (os->KeyReleased('M', true)) {
			os->ToggleFullscreen();
			glsys.SetViewportSize(os->GetWindowWidth(), os->GetWindowHeight());
		}

		// Pass in delta time in seconds
		physys.Update(deltaSec);

		if (glsys.Update(delta)) {
			os->Present();
		}
	}

	delete os;

	return 0;
}
<commit_msg>Removed some unnecessary getInstance calls<commit_after>#include <iostream>

#include "systems/OpenGLSystem.h"
#include "systems/SimplePhysics.h"
#include "systems/FactorySystem.h"
#include "controllers/GLSixDOFViewController.h"
#include "components/ViewMover.h"
#include "SCParser.h"

#if defined OS_Win32
#include "os/win32/win32.h"
#elif defined OS_SDL
#include "os/sdl/SDLSys.h"
#endif

int main(int argCount, char **argValues) {
	OpenGLSystem glsys;
	SimplePhysics physys;
	FactorySystem& factory = FactorySystem::getInstance();
	factory.register_Factory(&glsys);
	factory.register_Factory(&physys);
	IOpSys* os = nullptr;
#if defined OS_Win32
	os = new win32();
#elif defined OS_SDL
	os = new SDLSys();
#endif

	if(os->CreateGraphicsWindow(1024,768) == 0) {
		std::cout << "Error creating window!" << std::endl;
	}

	const int* version = glsys.Start();
	glsys.SetViewportSize(os->GetWindowWidth(), os->GetWindowHeight());

	if (version[0] == -1) {
		std::cout << "Error starting OpenGL!" << std::endl;
	} else {
		std::cout << "OpenGL version: " << version[0] << "." << version[1] << std::endl;
	}

	Sigma::parser::SCParser parser;

	if (!parser.Parse("test.sc")) {
		assert(0 && "Failed to load entities from file.");
	}

	for (unsigned int i = 0; i < parser.EntityCount(); ++i) {
		const Sigma::parser::Entity* e = parser.GetEntity(i);
		for (auto itr = e->components.begin(); itr != e->components.end(); ++itr) {
            factory.create(
                        itr->type,e->id,
                        const_cast<std::vector<Property>&>(itr->properties));
		}
	}

	std::vector<Property> props;
	physys.createViewMover("ViewMover", 9, props);
	ViewMover* mover = reinterpret_cast<ViewMover*>(physys.getComponent(9,ViewMover::getStaticComponentID()));
	Sigma::event::handler::GLSixDOFViewController cameraController(glsys.View(), mover);
	IOpSys::KeyboardEventSystem.Register(&cameraController);

	os->SetupTimer();

	double delta;
	bool isWireframe=false;

	while (os->MessageLoop()) {
		delta = os->GetDeltaTime();
		double deltaSec = (double)delta/100.0f;

		if (os->KeyReleased('P', true)) { // Wireframe mode
			if (!isWireframe) {
				glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
				isWireframe = true;
			} else {
				glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
				isWireframe = false;
			}
		}

		if (os->KeyReleased('M', true)) {
			os->ToggleFullscreen();
			glsys.SetViewportSize(os->GetWindowWidth(), os->GetWindowHeight());
		}

		// Pass in delta time in seconds
		physys.Update(deltaSec);

		if (glsys.Update(delta)) {
			os->Present();
		}
	}

	delete os;

	return 0;
}
<|endoftext|>


<commit_before>/**
 * @file main.cpp
 *
 * User interface to the face recognition system.
 */
#include <cstdlib>
#include <exception>
#include <getopt.h>
#include <iomanip>
#include <iostream>
#include <map>
#include <mlearn.h>
#include <unistd.h>

using namespace ML;

enum class InputDataType {
	None,
	Genome,
	Image
};

enum class FeatureType {
	Identity,
	PCA,
	LDA,
	ICA
};

enum class ClassifierType {
	None,
	KNN,
	Bayes
};

typedef enum {
	OPTION_GPU,
	OPTION_LOGLEVEL,
	OPTION_TRAIN,
	OPTION_TEST,
	OPTION_STREAM,
	OPTION_DATA,
	OPTION_PCA,
	OPTION_LDA,
	OPTION_ICA,
	OPTION_KNN,
	OPTION_BAYES,
	OPTION_PCA_N1,
	OPTION_LDA_N1,
	OPTION_LDA_N2,
	OPTION_ICA_N1,
	OPTION_ICA_N2,
	OPTION_ICA_NONL,
	OPTION_ICA_MAX_ITER,
	OPTION_ICA_EPS,
	OPTION_KNN_K,
	OPTION_KNN_DIST,
	OPTION_UNKNOWN = '?'
} option_t;

typedef struct {
	bool train;
	bool test;
	bool stream;
	const char *path_train;
	const char *path_test;
	const char *path_model;
	InputDataType data_type;
	FeatureType feature_type;
	ClassifierType classifier_type;
	int pca_n1;
	int lda_n1;
	int lda_n2;
	int ica_n1;
	int ica_n2;
	ICANonl ica_nonl;
	int ica_max_iter;
	precision_t ica_eps;
	int knn_k;
	dist_func_t knn_dist;
} optarg_t;

const std::map<std::string, InputDataType> data_types = {
	{ "genome", InputDataType::Genome },
	{ "image", InputDataType::Image }
};

const std::map<std::string, dist_func_t> dist_funcs = {
	{ "COS", m_dist_COS },
	{ "L1", m_dist_L1 },
	{ "L2", m_dist_L2 }
};

const std::map<std::string, ICANonl> nonl_funcs = {
	{ "pow3", ICANonl::pow3 },
	{ "tanh", ICANonl::tanh },
	{ "gauss", ICANonl::gauss }
};

/**
 * Print command-line usage and help text.
 */
void print_usage()
{
	std::cerr <<
		"Usage: ./face-rec [options]\n"
		"\n"
		"Options:\n"
		"  --gpu              enable GPU acceleration\n"
		"  --loglevel LEVEL   set the log level ([1]=info, 2=verbose, 3=debug)\n"
		"  --train DIRECTORY  train a model with a training set\n"
		"  --test DIRECTORY   perform recognition on a test set\n"
		"  --stream           perform recognition on an input stream\n"
		"  --data             data type (genome, [image])\n"
		"  --pca              use PCA for feature extraction\n"
		"  --lda              use LDA for feature extraction\n"
		"  --ica              use ICA for feature extraction\n"
		"  --knn              use the kNN classifier (default)\n"
		"  --bayes            use the Bayes classifier\n"
		"\n"
		"Hyperparameters:\n"
		"PCA:\n"
		"  --pca_n1 N         number of principal components to compute\n"
		"\n"
		"LDA:\n"
		"  --lda_n1 N         number of principal components to compute\n"
		"  --lda_n2 N         number of Fisherfaces to compute\n"
		"\n"
		"ICA:\n"
		"  --ica_n1 N         number of principal components to compute\n"
		"  --ica_n2 N         number of independent components to estimate\n"
		"  --ica_nonl [nonl]  nonlinearity function to use ([pow3], tanh, gauss)\n"
		"  --ica_max_iter N   maximum iterations\n"
		"  --ica_eps X        convergence threshold for w\n"
		"\n"
		"kNN:\n"
		"  --knn_k N          number of nearest neighbors to use\n"
		"  --knn_dist [dist]  distance function to use (L1, [L2], COS)\n";
}

/**
 * Parse command-line arguments.
 *
 * @param argc
 * @param argv
 */
optarg_t parse_args(int argc, char **argv)
{
	optarg_t args = {
		false,
		false,
		false,
		nullptr,
		nullptr,
		"./model.dat",
		InputDataType::Image,
		FeatureType::Identity,
		ClassifierType::KNN,
		-1,
		-1, -1,
		-1, -1, ICANonl::pow3, 1000, 0.0001f,
		1, m_dist_L2
	};

	struct option long_options[] = {
		{ "gpu", no_argument, 0, OPTION_GPU },
		{ "loglevel", required_argument, 0, OPTION_LOGLEVEL },
		{ "train", required_argument, 0, OPTION_TRAIN },
		{ "test", required_argument, 0, OPTION_TEST },
		{ "stream", no_argument, 0, OPTION_STREAM },
		{ "data", required_argument, 0, OPTION_DATA },
		{ "pca", no_argument, 0, OPTION_PCA },
		{ "lda", no_argument, 0, OPTION_LDA },
		{ "ica", no_argument, 0, OPTION_ICA },
		{ "knn", no_argument, 0, OPTION_KNN },
		{ "bayes", no_argument, 0, OPTION_BAYES },
		{ "pca_n1", required_argument, 0, OPTION_PCA_N1 },
		{ "lda_n1", required_argument, 0, OPTION_LDA_N1 },
		{ "lda_n2", required_argument, 0, OPTION_LDA_N2 },
		{ "ica_n1", required_argument, 0, OPTION_ICA_N1 },
		{ "ica_n2", required_argument, 0, OPTION_ICA_N2 },
		{ "ica_nonl", required_argument, 0, OPTION_ICA_NONL },
		{ "ica_max_iter", required_argument, 0, OPTION_ICA_MAX_ITER },
		{ "ica_eps", required_argument, 0, OPTION_ICA_EPS },
		{ "knn_k", required_argument, 0, OPTION_KNN_K },
		{ "knn_dist", required_argument, 0, OPTION_KNN_DIST },
		{ 0, 0, 0, 0 }
	};

	int opt;
	while ( (opt = getopt_long_only(argc, argv, "", long_options, nullptr)) != -1 ) {
		switch ( opt ) {
		case OPTION_GPU:
			GPU = true;
			break;
		case OPTION_LOGLEVEL:
			LOGLEVEL = (logger_level_t) atoi(optarg);
			break;
		case OPTION_TRAIN:
			args.train = true;
			args.path_train = optarg;
			break;
		case OPTION_TEST:
			args.test = true;
			args.path_test = optarg;
			break;
		case OPTION_STREAM:
			args.stream = true;
			break;
		case OPTION_DATA:
			try {
				args.data_type = data_types.at(optarg);
			}
			catch ( std::exception& e ) {
				args.data_type = InputDataType::None;
			}
			break;
		case OPTION_PCA:
			args.feature_type = FeatureType::PCA;
			break;
		case OPTION_LDA:
			args.feature_type = FeatureType::LDA;
			break;
		case OPTION_ICA:
			args.feature_type = FeatureType::ICA;
			break;
		case OPTION_KNN:
			args.classifier_type = ClassifierType::KNN;
			break;
		case OPTION_BAYES:
			args.classifier_type = ClassifierType::Bayes;
			break;
		case OPTION_PCA_N1:
			args.pca_n1 = atoi(optarg);
			break;
		case OPTION_LDA_N1:
			args.lda_n1 = atoi(optarg);
			break;
		case OPTION_LDA_N2:
			args.lda_n2 = atoi(optarg);
			break;
		case OPTION_ICA_N1:
			args.ica_n1 = atoi(optarg);
			break;
		case OPTION_ICA_N2:
			args.ica_n2 = atoi(optarg);
			break;
		case OPTION_ICA_NONL:
			try {
				args.ica_nonl = nonl_funcs.at(optarg);
			}
			catch ( std::exception& e ) {
				args.ica_nonl = ICANonl::none;
			}
			break;
		case OPTION_ICA_MAX_ITER:
			args.ica_max_iter = atoi(optarg);
			break;
		case OPTION_ICA_EPS:
			args.ica_eps = atof(optarg);
			break;
		case OPTION_KNN_K:
			args.knn_k = atoi(optarg);
			break;
		case OPTION_KNN_DIST:
			try {
				args.knn_dist = dist_funcs.at(optarg);
			}
			catch ( std::exception& e ) {
				args.knn_dist = nullptr;
			}
			break;
		case OPTION_UNKNOWN:
			print_usage();
			exit(1);
		}
	}

	return args;
}

/**
 * Validate command-line arguments.
 *
 * @param args
 */
void validate_args(const optarg_t& args)
{
	std::vector<std::pair<bool, std::string>> validators = {
		{ args.train || args.test, "--train and/or --test are required" },
		{ args.data_type != InputDataType::None, "--data must be genome | image" },
		{ args.knn_dist != nullptr, "--knn_dist must be L1 | L2 | COS" },
		{ args.ica_nonl != ICANonl::none, "--ica_nonl must be pow3 | tanh | gauss" }
	};
	bool valid = true;

	for ( auto v : validators ) {
		if ( !v.first ) {
			std::cerr << "error: " << v.second << "\n";
			valid = false;
		}
	}

	if ( !valid ) {
		print_usage();
		exit(1);
	}
}

int main(int argc, char **argv)
{
	// parse command-line arguments
	optarg_t args = parse_args(argc, argv);

	// validate arguments
	validate_args(args);

	// initialize GPU if enabled
	gpu_init();

	// initialize data type
	DataType *data_type;

	if ( args.data_type == InputDataType::Genome ) {
		data_type = new Genome();
	}
	else if ( args.data_type == InputDataType::Image ) {
		data_type = new Image();
	}

	// initialize feature layer
	FeatureLayer *feature;

	if ( args.feature_type == FeatureType::Identity ) {
		feature = new IdentityLayer();
	}
	else if ( args.feature_type == FeatureType::PCA ) {
		feature = new PCALayer(args.pca_n1);
	}
	else if ( args.feature_type == FeatureType::LDA ) {
		feature = new LDALayer(args.lda_n1, args.lda_n2);
	}
	else if ( args.feature_type == FeatureType::ICA ) {
		feature = new ICALayer(
			args.ica_n1,
			args.ica_n2,
			args.ica_nonl,
			args.ica_max_iter,
			args.ica_eps
		);
	}

	// initialize classifier layer
	ClassifierLayer *classifier;

	if ( args.classifier_type == ClassifierType::KNN ) {
		classifier = new KNNLayer(args.knn_k, args.knn_dist);
	}
	else if ( args.classifier_type == ClassifierType::Bayes ) {
		classifier = new BayesLayer();
	}

	// initialize model
	ClassificationModel model(feature, classifier);

	// run the face recognition system
	if ( args.train ) {
		Dataset train_set(data_type, args.path_train);

		model.train(train_set);
	}
	else {
		model.load(args.path_model);
	}

	if ( args.test && args.stream ) {
		char END = '0';
		char READ = '1';

		while ( 1 ) {
			char c = std::cin.get();

			if ( c == END ) {
				break;
			}
			else if ( c == READ ) {
				Dataset test_set(data_type, args.path_test, false);

				std::vector<DataLabel> Y_pred = model.predict(test_set);

				// print results
				for ( size_t i = 0; i < test_set.entries().size(); i++ ) {
					const DataLabel& y_pred = Y_pred[i];
					const DataEntry& entry = test_set.entries()[i];

					std::cout << std::left << std::setw(12) << entry.name << "  " << y_pred << "\n";
				}
			}
		}
	}
	else if ( args.test ) {
		Dataset test_set(data_type, args.path_test);

		std::vector<DataLabel> Y_pred = model.predict(test_set);
		model.validate(test_set, Y_pred);
	}
	else {
		model.save(args.path_model);
	}

	timer_print();

	model.print_stats();

	gpu_finalize();

	return 0;
}
<commit_msg>Added separate path arg for --stream<commit_after>/**
 * @file main.cpp
 *
 * User interface to the face recognition system.
 */
#include <cstdlib>
#include <exception>
#include <getopt.h>
#include <iomanip>
#include <iostream>
#include <map>
#include <mlearn.h>
#include <unistd.h>

using namespace ML;

enum class InputDataType {
	None,
	Genome,
	Image
};

enum class FeatureType {
	Identity,
	PCA,
	LDA,
	ICA
};

enum class ClassifierType {
	None,
	KNN,
	Bayes
};

typedef enum {
	OPTION_GPU,
	OPTION_LOGLEVEL,
	OPTION_TRAIN,
	OPTION_TEST,
	OPTION_STREAM,
	OPTION_DATA,
	OPTION_PCA,
	OPTION_LDA,
	OPTION_ICA,
	OPTION_KNN,
	OPTION_BAYES,
	OPTION_PCA_N1,
	OPTION_LDA_N1,
	OPTION_LDA_N2,
	OPTION_ICA_N1,
	OPTION_ICA_N2,
	OPTION_ICA_NONL,
	OPTION_ICA_MAX_ITER,
	OPTION_ICA_EPS,
	OPTION_KNN_K,
	OPTION_KNN_DIST,
	OPTION_UNKNOWN = '?'
} option_t;

typedef struct {
	bool train;
	bool test;
	bool stream;
	const char *path_train;
	const char *path_test;
	const char *path_stream;
	const char *path_model;
	InputDataType data_type;
	FeatureType feature_type;
	ClassifierType classifier_type;
	int pca_n1;
	int lda_n1;
	int lda_n2;
	int ica_n1;
	int ica_n2;
	ICANonl ica_nonl;
	int ica_max_iter;
	precision_t ica_eps;
	int knn_k;
	dist_func_t knn_dist;
} optarg_t;

const std::map<std::string, InputDataType> data_types = {
	{ "genome", InputDataType::Genome },
	{ "image", InputDataType::Image }
};

const std::map<std::string, dist_func_t> dist_funcs = {
	{ "COS", m_dist_COS },
	{ "L1", m_dist_L1 },
	{ "L2", m_dist_L2 }
};

const std::map<std::string, ICANonl> nonl_funcs = {
	{ "pow3", ICANonl::pow3 },
	{ "tanh", ICANonl::tanh },
	{ "gauss", ICANonl::gauss }
};

/**
 * Print command-line usage and help text.
 */
void print_usage()
{
	std::cerr <<
		"Usage: ./face-rec [options]\n"
		"\n"
		"Options:\n"
		"  --gpu              enable GPU acceleration\n"
		"  --loglevel LEVEL   set the log level ([1]=info, 2=verbose, 3=debug)\n"
		"  --train DIRECTORY  train a model with a training set\n"
		"  --test DIRECTORY   perform recognition on a test set\n"
		"  --stream           perform recognition on an input stream\n"
		"  --data             data type (genome, [image])\n"
		"  --pca              use PCA for feature extraction\n"
		"  --lda              use LDA for feature extraction\n"
		"  --ica              use ICA for feature extraction\n"
		"  --knn              use the kNN classifier (default)\n"
		"  --bayes            use the Bayes classifier\n"
		"\n"
		"Hyperparameters:\n"
		"PCA:\n"
		"  --pca_n1 N         number of principal components to compute\n"
		"\n"
		"LDA:\n"
		"  --lda_n1 N         number of principal components to compute\n"
		"  --lda_n2 N         number of Fisherfaces to compute\n"
		"\n"
		"ICA:\n"
		"  --ica_n1 N         number of principal components to compute\n"
		"  --ica_n2 N         number of independent components to estimate\n"
		"  --ica_nonl [nonl]  nonlinearity function to use ([pow3], tanh, gauss)\n"
		"  --ica_max_iter N   maximum iterations\n"
		"  --ica_eps X        convergence threshold for w\n"
		"\n"
		"kNN:\n"
		"  --knn_k N          number of nearest neighbors to use\n"
		"  --knn_dist [dist]  distance function to use (L1, [L2], COS)\n";
}

/**
 * Parse command-line arguments.
 *
 * @param argc
 * @param argv
 */
optarg_t parse_args(int argc, char **argv)
{
	optarg_t args = {
		false,
		false,
		false,
		nullptr,
		nullptr,
		nullptr,
		"./model.dat",
		InputDataType::Image,
		FeatureType::Identity,
		ClassifierType::KNN,
		-1,
		-1, -1,
		-1, -1, ICANonl::pow3, 1000, 0.0001f,
		1, m_dist_L2
	};

	struct option long_options[] = {
		{ "gpu", no_argument, 0, OPTION_GPU },
		{ "loglevel", required_argument, 0, OPTION_LOGLEVEL },
		{ "train", required_argument, 0, OPTION_TRAIN },
		{ "test", required_argument, 0, OPTION_TEST },
		{ "stream", required_argument, 0, OPTION_STREAM },
		{ "data", required_argument, 0, OPTION_DATA },
		{ "pca", no_argument, 0, OPTION_PCA },
		{ "lda", no_argument, 0, OPTION_LDA },
		{ "ica", no_argument, 0, OPTION_ICA },
		{ "knn", no_argument, 0, OPTION_KNN },
		{ "bayes", no_argument, 0, OPTION_BAYES },
		{ "pca_n1", required_argument, 0, OPTION_PCA_N1 },
		{ "lda_n1", required_argument, 0, OPTION_LDA_N1 },
		{ "lda_n2", required_argument, 0, OPTION_LDA_N2 },
		{ "ica_n1", required_argument, 0, OPTION_ICA_N1 },
		{ "ica_n2", required_argument, 0, OPTION_ICA_N2 },
		{ "ica_nonl", required_argument, 0, OPTION_ICA_NONL },
		{ "ica_max_iter", required_argument, 0, OPTION_ICA_MAX_ITER },
		{ "ica_eps", required_argument, 0, OPTION_ICA_EPS },
		{ "knn_k", required_argument, 0, OPTION_KNN_K },
		{ "knn_dist", required_argument, 0, OPTION_KNN_DIST },
		{ 0, 0, 0, 0 }
	};

	int opt;
	while ( (opt = getopt_long_only(argc, argv, "", long_options, nullptr)) != -1 ) {
		switch ( opt ) {
		case OPTION_GPU:
			GPU = true;
			break;
		case OPTION_LOGLEVEL:
			LOGLEVEL = (logger_level_t) atoi(optarg);
			break;
		case OPTION_TRAIN:
			args.train = true;
			args.path_train = optarg;
			break;
		case OPTION_TEST:
			args.test = true;
			args.path_test = optarg;
			break;
		case OPTION_STREAM:
			args.stream = true;
			args.path_stream = optarg;
			break;
		case OPTION_DATA:
			try {
				args.data_type = data_types.at(optarg);
			}
			catch ( std::exception& e ) {
				args.data_type = InputDataType::None;
			}
			break;
		case OPTION_PCA:
			args.feature_type = FeatureType::PCA;
			break;
		case OPTION_LDA:
			args.feature_type = FeatureType::LDA;
			break;
		case OPTION_ICA:
			args.feature_type = FeatureType::ICA;
			break;
		case OPTION_KNN:
			args.classifier_type = ClassifierType::KNN;
			break;
		case OPTION_BAYES:
			args.classifier_type = ClassifierType::Bayes;
			break;
		case OPTION_PCA_N1:
			args.pca_n1 = atoi(optarg);
			break;
		case OPTION_LDA_N1:
			args.lda_n1 = atoi(optarg);
			break;
		case OPTION_LDA_N2:
			args.lda_n2 = atoi(optarg);
			break;
		case OPTION_ICA_N1:
			args.ica_n1 = atoi(optarg);
			break;
		case OPTION_ICA_N2:
			args.ica_n2 = atoi(optarg);
			break;
		case OPTION_ICA_NONL:
			try {
				args.ica_nonl = nonl_funcs.at(optarg);
			}
			catch ( std::exception& e ) {
				args.ica_nonl = ICANonl::none;
			}
			break;
		case OPTION_ICA_MAX_ITER:
			args.ica_max_iter = atoi(optarg);
			break;
		case OPTION_ICA_EPS:
			args.ica_eps = atof(optarg);
			break;
		case OPTION_KNN_K:
			args.knn_k = atoi(optarg);
			break;
		case OPTION_KNN_DIST:
			try {
				args.knn_dist = dist_funcs.at(optarg);
			}
			catch ( std::exception& e ) {
				args.knn_dist = nullptr;
			}
			break;
		case OPTION_UNKNOWN:
			print_usage();
			exit(1);
		}
	}

	return args;
}

/**
 * Validate command-line arguments.
 *
 * @param args
 */
void validate_args(const optarg_t& args)
{
	std::vector<std::pair<bool, std::string>> validators = {
		{ args.train || args.test || args.stream, "--train / --test / --stream are required" },
		{ args.data_type != InputDataType::None, "--data must be genome | image" },
		{ args.knn_dist != nullptr, "--knn_dist must be L1 | L2 | COS" },
		{ args.ica_nonl != ICANonl::none, "--ica_nonl must be pow3 | tanh | gauss" }
	};
	bool valid = true;

	for ( auto v : validators ) {
		if ( !v.first ) {
			std::cerr << "error: " << v.second << "\n";
			valid = false;
		}
	}

	if ( !valid ) {
		print_usage();
		exit(1);
	}
}

int main(int argc, char **argv)
{
	// parse command-line arguments
	optarg_t args = parse_args(argc, argv);

	// validate arguments
	validate_args(args);

	// initialize GPU if enabled
	gpu_init();

	// initialize data type
	DataType *data_type;

	if ( args.data_type == InputDataType::Genome ) {
		data_type = new Genome();
	}
	else if ( args.data_type == InputDataType::Image ) {
		data_type = new Image();
	}

	// initialize feature layer
	FeatureLayer *feature;

	if ( args.feature_type == FeatureType::Identity ) {
		feature = new IdentityLayer();
	}
	else if ( args.feature_type == FeatureType::PCA ) {
		feature = new PCALayer(args.pca_n1);
	}
	else if ( args.feature_type == FeatureType::LDA ) {
		feature = new LDALayer(args.lda_n1, args.lda_n2);
	}
	else if ( args.feature_type == FeatureType::ICA ) {
		feature = new ICALayer(
			args.ica_n1,
			args.ica_n2,
			args.ica_nonl,
			args.ica_max_iter,
			args.ica_eps
		);
	}

	// initialize classifier layer
	ClassifierLayer *classifier;

	if ( args.classifier_type == ClassifierType::KNN ) {
		classifier = new KNNLayer(args.knn_k, args.knn_dist);
	}
	else if ( args.classifier_type == ClassifierType::Bayes ) {
		classifier = new BayesLayer();
	}

	// initialize model
	ClassificationModel model(feature, classifier);

	// run the face recognition system
	if ( args.train ) {
		Dataset train_set(data_type, args.path_train);

		model.train(train_set);
	}
	else {
		model.load(args.path_model);
	}

	if ( args.test ) {
		Dataset test_set(data_type, args.path_test);

		std::vector<DataLabel> Y_pred = model.predict(test_set);
		model.validate(test_set, Y_pred);
	}
	else if ( args.stream ) {
		const char END = '0';
		const char READ = '1';

		while ( true ) {
			char c = std::cin.get();

			if ( c == END ) {
				break;
			}
			else if ( c == READ ) {
				Dataset test_set(data_type, args.path_stream, false);

				std::vector<DataLabel> Y_pred = model.predict(test_set);

				// print results
				for ( size_t i = 0; i < test_set.entries().size(); i++ ) {
					const DataLabel& y_pred = Y_pred[i];
					const DataEntry& entry = test_set.entries()[i];

					std::cout << std::left << std::setw(12) << entry.name << "  " << y_pred << "\n";
				}
			}
		}
	}
	else {
		model.save(args.path_model);
	}

	timer_print();

	model.print_stats();

	gpu_finalize();

	return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium 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 "base/message_pump_x.h"

#include <X11/extensions/XInput2.h>

#include "base/basictypes.h"
#include "base/message_loop.h"

namespace {

gboolean XSourcePrepare(GSource* source, gint* timeout_ms) {
  if (XPending(base::MessagePumpX::GetDefaultXDisplay()))
    *timeout_ms = 0;
  else
    *timeout_ms = -1;
  return FALSE;
}

gboolean XSourceCheck(GSource* source) {
  return XPending(base::MessagePumpX::GetDefaultXDisplay());
}

gboolean XSourceDispatch(GSource* source,
                         GSourceFunc unused_func,
                         gpointer data) {
  base::MessagePumpX* pump = static_cast<base::MessagePumpX*>(data);
  return pump->DispatchXEvents();
}

GSourceFuncs XSourceFuncs = {
  XSourcePrepare,
  XSourceCheck,
  XSourceDispatch,
  NULL
};

// The opcode used for checking events.
int xiopcode = -1;

// The message-pump opens a connection to the display and owns it.
Display* g_xdisplay = NULL;

// The default dispatcher to process native events when no dispatcher
// is specified.
base::MessagePumpDispatcher* g_default_dispatcher = NULL;

void InitializeXInput2(void) {
  Display* display = base::MessagePumpX::GetDefaultXDisplay();
  if (!display)
    return;

  int event, err;

  if (!XQueryExtension(display, "XInputExtension", &xiopcode, &event, &err)) {
    DVLOG(1) << "X Input extension not available.";
    xiopcode = -1;
    return;
  }

#if defined(USE_XI2_MT)
  // USE_XI2_MT also defines the required XI2 minor minimum version.
  int major = 2, minor = USE_XI2_MT;
#else
  int major = 2, minor = 0;
#endif
  if (XIQueryVersion(display, &major, &minor) == BadRequest) {
    DVLOG(1) << "XInput2 not supported in the server.";
    xiopcode = -1;
    return;
  }
#if defined(USE_XI2_MT)
  if (major < 2 || (major == 2 && minor < USE_XI2_MT)) {
    DVLOG(1) << "XI version on server is " << major << "." << minor << ". "
            << "But 2." << USE_XI2_MT << " is required.";
    xiopcode = -1;
    return;
  }
#endif
}

}  // namespace

namespace base {

MessagePumpX::MessagePumpX() : MessagePumpGlib(),
    x_source_(NULL) {
  InitializeXInput2();
  InitXSource();
}

MessagePumpX::~MessagePumpX() {
  g_source_destroy(x_source_);
  g_source_unref(x_source_);
  XCloseDisplay(g_xdisplay);
  g_xdisplay = NULL;
}

// static
Display* MessagePumpX::GetDefaultXDisplay() {
  if (!g_xdisplay)
    g_xdisplay = XOpenDisplay(NULL);
  return g_xdisplay;
}

// static
bool MessagePumpX::HasXInput2() {
  return xiopcode != -1;
}

// static
void MessagePumpX::SetDefaultDispatcher(MessagePumpDispatcher* dispatcher) {
  DCHECK(!g_default_dispatcher || !dispatcher);
  g_default_dispatcher = dispatcher;
}

void MessagePumpX::InitXSource() {
  DCHECK(!x_source_);
  x_poll_.reset(new GPollFD());
  Display* display = GetDefaultXDisplay();
  DCHECK(display) << "Unable to get connection to X server";
  x_poll_->fd = ConnectionNumber(display);
  x_poll_->events = G_IO_IN;

  x_source_ = g_source_new(&XSourceFuncs, sizeof(GSource));
  g_source_add_poll(x_source_, x_poll_.get());
  g_source_set_can_recurse(x_source_, TRUE);
  g_source_set_callback(x_source_, NULL, this, NULL);
  g_source_attach(x_source_, g_main_context_default());
}

bool MessagePumpX::ProcessXEvent(MessagePumpDispatcher* dispatcher,
                                 XEvent* xev) {
  bool should_quit = false;

  bool have_cookie = false;
  if (xev->type == GenericEvent &&
      XGetEventData(xev->xgeneric.display, &xev->xcookie)) {
    have_cookie = true;
  }

  if (!WillProcessXEvent(xev)) {
    MessagePumpDispatcher::DispatchStatus status =
        dispatcher->Dispatch(xev);

    if (status == MessagePumpDispatcher::EVENT_QUIT) {
      should_quit = true;
      Quit();
    } else if (status == MessagePumpDispatcher::EVENT_IGNORED) {
      DVLOG(1) << "Event (" << xev->type << ") not handled.";
    }
    DidProcessXEvent(xev);
  }

  if (have_cookie) {
    XFreeEventData(xev->xgeneric.display, &xev->xcookie);
  }

  return should_quit;
}

gboolean MessagePumpX::DispatchXEvents() {
  Display* display = GetDefaultXDisplay();
  DCHECK(display);
  MessagePumpDispatcher* dispatcher =
      GetDispatcher() ? GetDispatcher() : g_default_dispatcher;

  // In the general case, we want to handle all pending events before running
  // the tasks. This is what happens in the message_pump_glib case.
  while (XPending(display)) {
    XEvent xev;
    XNextEvent(display, &xev);
    if (dispatcher && ProcessXEvent(dispatcher, &xev))
      return TRUE;
  }
  return TRUE;
}

bool MessagePumpX::WillProcessXEvent(XEvent* xevent) {
  if (!observers().might_have_observers())
    return false;
  ObserverListBase<MessagePumpObserver>::Iterator it(observers());
  MessagePumpObserver* obs;
  while ((obs = it.GetNext()) != NULL) {
    if (obs->WillProcessEvent(xevent))
      return true;
  }
  return false;
}

void MessagePumpX::DidProcessXEvent(XEvent* xevent) {
  FOR_EACH_OBSERVER(MessagePumpObserver, observers(), DidProcessEvent(xevent));
}

}  // namespace base
<commit_msg>CrOS: Add a CHECK to help debug a crash in the wild.<commit_after>// Copyright (c) 2012 The Chromium 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 "base/message_pump_x.h"

#include <X11/extensions/XInput2.h>

#include "base/basictypes.h"
#include "base/message_loop.h"

namespace {

gboolean XSourcePrepare(GSource* source, gint* timeout_ms) {
  if (XPending(base::MessagePumpX::GetDefaultXDisplay()))
    *timeout_ms = 0;
  else
    *timeout_ms = -1;
  return FALSE;
}

gboolean XSourceCheck(GSource* source) {
  return XPending(base::MessagePumpX::GetDefaultXDisplay());
}

gboolean XSourceDispatch(GSource* source,
                         GSourceFunc unused_func,
                         gpointer data) {
  base::MessagePumpX* pump = static_cast<base::MessagePumpX*>(data);
  return pump->DispatchXEvents();
}

GSourceFuncs XSourceFuncs = {
  XSourcePrepare,
  XSourceCheck,
  XSourceDispatch,
  NULL
};

// The opcode used for checking events.
int xiopcode = -1;

// The message-pump opens a connection to the display and owns it.
Display* g_xdisplay = NULL;

// The default dispatcher to process native events when no dispatcher
// is specified.
base::MessagePumpDispatcher* g_default_dispatcher = NULL;

void InitializeXInput2(void) {
  Display* display = base::MessagePumpX::GetDefaultXDisplay();
  if (!display)
    return;

  int event, err;

  if (!XQueryExtension(display, "XInputExtension", &xiopcode, &event, &err)) {
    DVLOG(1) << "X Input extension not available.";
    xiopcode = -1;
    return;
  }

#if defined(USE_XI2_MT)
  // USE_XI2_MT also defines the required XI2 minor minimum version.
  int major = 2, minor = USE_XI2_MT;
#else
  int major = 2, minor = 0;
#endif
  if (XIQueryVersion(display, &major, &minor) == BadRequest) {
    DVLOG(1) << "XInput2 not supported in the server.";
    xiopcode = -1;
    return;
  }
#if defined(USE_XI2_MT)
  if (major < 2 || (major == 2 && minor < USE_XI2_MT)) {
    DVLOG(1) << "XI version on server is " << major << "." << minor << ". "
            << "But 2." << USE_XI2_MT << " is required.";
    xiopcode = -1;
    return;
  }
#endif
}

}  // namespace

namespace base {

MessagePumpX::MessagePumpX() : MessagePumpGlib(),
    x_source_(NULL) {
  InitializeXInput2();
  InitXSource();
}

MessagePumpX::~MessagePumpX() {
  g_source_destroy(x_source_);
  g_source_unref(x_source_);
  XCloseDisplay(g_xdisplay);
  g_xdisplay = NULL;
}

// static
Display* MessagePumpX::GetDefaultXDisplay() {
  if (!g_xdisplay)
    g_xdisplay = XOpenDisplay(NULL);
  return g_xdisplay;
}

// static
bool MessagePumpX::HasXInput2() {
  return xiopcode != -1;
}

// static
void MessagePumpX::SetDefaultDispatcher(MessagePumpDispatcher* dispatcher) {
  DCHECK(!g_default_dispatcher || !dispatcher);
  g_default_dispatcher = dispatcher;
}

void MessagePumpX::InitXSource() {
  // CHECKs are to help track down crbug.com/113106.
  CHECK(!x_source_);
  Display* display = GetDefaultXDisplay();
  CHECK(display) << "Unable to get connection to X server";
  x_poll_.reset(new GPollFD());
  CHECK(x_poll_.get());
  x_poll_->fd = ConnectionNumber(display);
  x_poll_->events = G_IO_IN;

  x_source_ = g_source_new(&XSourceFuncs, sizeof(GSource));
  g_source_add_poll(x_source_, x_poll_.get());
  g_source_set_can_recurse(x_source_, TRUE);
  g_source_set_callback(x_source_, NULL, this, NULL);
  g_source_attach(x_source_, g_main_context_default());
}

bool MessagePumpX::ProcessXEvent(MessagePumpDispatcher* dispatcher,
                                 XEvent* xev) {
  bool should_quit = false;

  bool have_cookie = false;
  if (xev->type == GenericEvent &&
      XGetEventData(xev->xgeneric.display, &xev->xcookie)) {
    have_cookie = true;
  }

  if (!WillProcessXEvent(xev)) {
    MessagePumpDispatcher::DispatchStatus status =
        dispatcher->Dispatch(xev);

    if (status == MessagePumpDispatcher::EVENT_QUIT) {
      should_quit = true;
      Quit();
    } else if (status == MessagePumpDispatcher::EVENT_IGNORED) {
      DVLOG(1) << "Event (" << xev->type << ") not handled.";
    }
    DidProcessXEvent(xev);
  }

  if (have_cookie) {
    XFreeEventData(xev->xgeneric.display, &xev->xcookie);
  }

  return should_quit;
}

gboolean MessagePumpX::DispatchXEvents() {
  Display* display = GetDefaultXDisplay();
  DCHECK(display);
  MessagePumpDispatcher* dispatcher =
      GetDispatcher() ? GetDispatcher() : g_default_dispatcher;

  // In the general case, we want to handle all pending events before running
  // the tasks. This is what happens in the message_pump_glib case.
  while (XPending(display)) {
    XEvent xev;
    XNextEvent(display, &xev);
    if (dispatcher && ProcessXEvent(dispatcher, &xev))
      return TRUE;
  }
  return TRUE;
}

bool MessagePumpX::WillProcessXEvent(XEvent* xevent) {
  if (!observers().might_have_observers())
    return false;
  ObserverListBase<MessagePumpObserver>::Iterator it(observers());
  MessagePumpObserver* obs;
  while ((obs = it.GetNext()) != NULL) {
    if (obs->WillProcessEvent(xevent))
      return true;
  }
  return false;
}

void MessagePumpX::DidProcessXEvent(XEvent* xevent) {
  FOR_EACH_OBSERVER(MessagePumpObserver, observers(), DidProcessEvent(xevent));
}

}  // namespace base
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: dbexchange.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: fs $ $Date: 2001-04-11 12:58:38 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the License); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef DBAUI_DBEXCHANGE_HXX
#include "dbexchange.hxx"
#endif
#ifndef _SOT_FORMATS_HXX
#include <sot/formats.hxx>
#endif
#ifndef _SOT_STORAGE_HXX
#include <sot/storage.hxx>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#ifndef _COM_SUN_STAR_SDB_COMMANDTYPE_HPP_
#include <com/sun/star/sdb/CommandType.hpp>
#endif
#ifndef DBAUI_TOKENWRITER_HXX
#include "TokenWriter.hxx"
#endif
#ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
#include "dbustrings.hrc"
#endif
#ifndef _COMPHELPER_EXTRACT_HXX_
#include <comphelper/extract.hxx>
#endif
#ifndef _SVX_DATACCESSDESCRIPTOR_HXX_
#include <svx/dataaccessdescriptor.hxx>
#endif

namespace dbaui
{
    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::beans;
    using namespace ::com::sun::star::sdb;
    using namespace ::com::sun::star::beans;
    using namespace ::com::sun::star::lang;
    using namespace ::com::sun::star::util;
    using namespace ::com::sun::star::sdbc;
    using namespace ::com::sun::star::datatransfer;
    using namespace ::svx;

    // -----------------------------------------------------------------------------
    ODataClipboard::ODataClipboard(
                    const ::rtl::OUString&  _rDatasource,
                    const sal_Int32         _nCommandType,
                    const ::rtl::OUString&  _rCommand,
                    const Reference< XConnection >& _rxConnection,
                    const Reference< XNumberFormatter >& _rxFormatter,
                    const Reference< XMultiServiceFactory >& _rxORB,
                    const sal_Int32 _nFormats)
        :m_pHtml(NULL)
        ,m_pRtf(NULL)
        ,m_nObjectType(CommandType::TABLE)
        ,m_nFormats(_nFormats)
    {
        // build the descriptor (the property sequence)
        ODataAccessDescriptor aDescriptor;
        aDescriptor[daDataSource]   <<= _rDatasource;
        aDescriptor[daConnection]   <<= _rxConnection;
        aDescriptor[daCommand]      <<= _rCommand;
        aDescriptor[daCommandType]  <<= _nCommandType;
        m_aSeq = aDescriptor.createPropertyValueSequence();

        // calculate some stuff which helps us providing the different formats
        if (m_nFormats && DCF_OBJECT_DESCRIPTOR)
        {
            // extract the single values from the sequence
            ::rtl::OUString sDatasourceName;
            ::rtl::OUString sObjectName;
            sal_Bool bEscapeProcessing = sal_True;
            sDatasourceName = _rDatasource;
            m_nObjectType = _nCommandType;
            sObjectName = _rCommand;

            // for compatibility: create a string which can be used for the SOT_FORMATSTR_ID_SBA_DATAEXCHANGE format

            sal_Bool bTreatAsStatement = (CommandType::COMMAND == m_nObjectType);
                // statements are - in this old and ugly format - described as queries

            const sal_Unicode       cSeparator = sal_Unicode(11);
            const ::rtl::OUString   sSeparator(&cSeparator, 1);

            const sal_Unicode       cTableMark = '1';
            const sal_Unicode       cQueryMark = '0';

            // build the descriptor string
            m_sCompatibleObjectDescription += sDatasourceName;
            m_sCompatibleObjectDescription += sSeparator;
            m_sCompatibleObjectDescription += bTreatAsStatement ? ::rtl::OUString() : sObjectName;
            m_sCompatibleObjectDescription += sSeparator;
            switch (m_nObjectType)
            {
                case CommandType::TABLE:
                    m_sCompatibleObjectDescription += ::rtl::OUString(&cTableMark, 1);
                    break;
                case CommandType::QUERY:
                    m_sCompatibleObjectDescription += ::rtl::OUString(&cQueryMark, 1);
                    break;
                case CommandType::COMMAND:
                    m_sCompatibleObjectDescription += ::rtl::OUString(&cQueryMark, 1);
                    // think of it as a query
                    break;
            }
            m_sCompatibleObjectDescription += sSeparator;
            m_sCompatibleObjectDescription += bTreatAsStatement ? sObjectName : ::rtl::OUString();
            m_sCompatibleObjectDescription += sSeparator;
        }

        if (m_nFormats && DCF_HTML_TABLE)
        {
            m_pHtml = new OHTMLImportExport(m_aSeq, _rxORB, _rxFormatter);
            m_xHtml = m_pHtml;
            m_pHtml->initialize();
        }

        if (m_nFormats && DCF_RTF_TABLE)
        {
            m_pRtf = new ORTFImportExport(m_aSeq, _rxORB, _rxFormatter);
            m_xRtf = m_pRtf;
            m_pRtf->initialize();
        }
    }

    // -----------------------------------------------------------------------------
    ODataClipboard::ODataClipboard(const Reference< XPropertySet >& _rxLivingForm, const Reference< XSQLQueryComposer >& _rxComposer)
        :m_pHtml(NULL)
        ,m_pRtf(NULL)
        ,m_nObjectType(CommandType::TABLE)
        ,m_nFormats(DCF_OBJECT_DESCRIPTOR)
    {
        // collect some properties of the form
        ::rtl::OUString sDatasourceName;
        sal_Int32       nObjectType = CommandType::COMMAND;
        ::rtl::OUString sObjectName;
        try
        {
            _rxLivingForm->getPropertyValue(PROPERTY_COMMANDTYPE) >>= nObjectType;
            _rxLivingForm->getPropertyValue(PROPERTY_COMMAND) >>= sObjectName;
            _rxLivingForm->getPropertyValue(PROPERTY_DATASOURCENAME) >>= sDatasourceName;
        }
        catch(Exception&)
        {
            OSL_ENSURE(sal_False, "ODataClipboard::ODataClipboard: could not collect essential form attributes !");
            m_nFormats = 0;
            return;
        }

        sal_Bool bIsStatement = CommandType::COMMAND == nObjectType;
        String sObjectKind = (CommandType::TABLE == nObjectType) ? String('1') : String('0');

        // check if the SQL-statement is modified
        sal_Bool bHasFilterOrSort(sal_False);
        ::rtl::OUString sCompleteStatement;
        try
        {
            ::rtl::OUString sFilter;
            if (::cppu::any2bool(_rxLivingForm->getPropertyValue(PROPERTY_APPLYFILTER)))
                _rxLivingForm->getPropertyValue(PROPERTY_FILTER) >>= sFilter;
            ::rtl::OUString sSort;
            _rxLivingForm->getPropertyValue(PROPERTY_ORDER) >>= sSort;
            bHasFilterOrSort = (sFilter.len()>0) || (sSort.len()>0);

            _rxLivingForm->getPropertyValue(PROPERTY_ACTIVECOMMAND) >>= sCompleteStatement;
            if (_rxComposer.is())
            {
                _rxComposer->setQuery(sCompleteStatement);
                _rxComposer->setFilter(sFilter);
                _rxComposer->setOrder(sSort);
                sCompleteStatement = _rxComposer->getComposedQuery();
            }
        }
        catch(Exception&)
        {
            OSL_ENSURE(sal_False, "ODataClipboard::ODataClipboard: could not collect essential form attributes (part two) !");
            m_nFormats = 0;
            return;
        }

        // build the object description (as string)
        const sal_Unicode       cSeparator(11);
        const ::rtl::OUString   sSeparator(&cSeparator, 1);

        m_sCompatibleObjectDescription = sDatasourceName;
        m_sCompatibleObjectDescription  += sSeparator;
        m_sCompatibleObjectDescription  += bIsStatement ? ::rtl::OUString() : sDatasourceName;
        m_sCompatibleObjectDescription  += sSeparator;
        m_sCompatibleObjectDescription  += sObjectKind;
        m_sCompatibleObjectDescription  += sSeparator;
        m_sCompatibleObjectDescription  +=
                (CommandType::QUERY == nObjectType) && !bHasFilterOrSort
                ? ::rtl::OUString()
            : sCompleteStatement;
            // compatibility says : always add the statement, but don't if it is a "pure" query
        m_sCompatibleObjectDescription  += sSeparator;
    }

    // -----------------------------------------------------------------------------
    void ODataClipboard::addRow(sal_Int32 _nRow)
    {
        OSL_ENSURE(m_nFormats && DCF_OBJECT_DESCRIPTOR, "ODataClipboard::addRow: don't have this (object descriptor) format!");

        const sal_Unicode       cSeparator(11);
        const ::rtl::OUString   sSeparator(&cSeparator, 1);

        m_sCompatibleObjectDescription += ::rtl::OUString::valueOf((sal_Int32)_nRow);
        m_sCompatibleObjectDescription += sSeparator;
    }

    // -----------------------------------------------------------------------------
    sal_Bool ODataClipboard::WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, const ::com::sun::star::datatransfer::DataFlavor& rFlavor )
    {
        if (nUserObjectId == SOT_FORMAT_RTF || nUserObjectId == SOT_FORMATSTR_ID_HTML)
        {
            ODatabaseImportExport* pExport = reinterpret_cast<ODatabaseImportExport*>(pUserObject);
            if(pExport)
            {
                pExport->setStream(&rxOStm);
                return pExport->Write();
            }
        }
        return sal_False;
    }

    // -----------------------------------------------------------------------------
    void ODataClipboard::AddSupportedFormats()
    {
        // RTF?
        if (m_nFormats && DCF_RTF_TABLE)
            AddFormat(SOT_FORMAT_RTF);

        // HTML?
        if (m_nFormats && DCF_HTML_TABLE)
            AddFormat(SOT_FORMATSTR_ID_HTML);

        // object descriptor?
        if (m_nFormats && DCF_OBJECT_DESCRIPTOR)
        {
            switch (m_nObjectType)
            {
                case CommandType::TABLE:
                    AddFormat(SOT_FORMATSTR_ID_DBACCESS_TABLE);
                    break;
                case CommandType::QUERY:
                    AddFormat(SOT_FORMATSTR_ID_DBACCESS_QUERY);
                    break;
                case CommandType::COMMAND:
                    AddFormat(SOT_FORMATSTR_ID_DBACCESS_COMMAND);
                    break;
            }

            sal_Int32 nDescriptorLen = m_sCompatibleObjectDescription.getLength();
            if (nDescriptorLen)
            {
                if (m_sCompatibleObjectDescription.getStr()[nDescriptorLen] == 11)
                    m_sCompatibleObjectDescription = m_sCompatibleObjectDescription.copy(0, nDescriptorLen - 1);

                if (nDescriptorLen)
                    AddFormat(SOT_FORMATSTR_ID_SBA_DATAEXCHANGE);
            }
        }
    }

    // -----------------------------------------------------------------------------
    sal_Bool ODataClipboard::GetData( const DataFlavor& rFlavor )
    {
        ULONG nFormat = SotExchange::GetFormat(rFlavor);
        switch (nFormat)
        {
            case SOT_FORMAT_RTF:
                return SetObject(m_pRtf,SOT_FORMAT_RTF,rFlavor);

            case SOT_FORMATSTR_ID_HTML:
                return SetObject(m_pHtml,SOT_FORMATSTR_ID_HTML,rFlavor);

            case SOT_FORMATSTR_ID_DBACCESS_TABLE:
            case SOT_FORMATSTR_ID_DBACCESS_QUERY:
            case SOT_FORMATSTR_ID_DBACCESS_COMMAND:
                return SetAny(makeAny(m_aSeq), rFlavor);

            case SOT_FORMATSTR_ID_SBA_DATAEXCHANGE:
                return SetString(m_sCompatibleObjectDescription, rFlavor);
        }
        return sal_False;
    }

    // -----------------------------------------------------------------------------
    void ODataClipboard::ObjectReleased()
    {
        m_xHtml = m_xRtf = NULL;
        m_pHtml = NULL;
        m_pRtf = NULL;
        m_aSeq.realloc(0);
    }

    // -----------------------------------------------------------------------------
}

<commit_msg>#86569# corrected building the compatible object description<commit_after>/*************************************************************************
 *
 *  $RCSfile: dbexchange.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: fs $ $Date: 2001-05-03 09:24:23 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the License); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef DBAUI_DBEXCHANGE_HXX
#include "dbexchange.hxx"
#endif
#ifndef _SOT_FORMATS_HXX
#include <sot/formats.hxx>
#endif
#ifndef _SOT_STORAGE_HXX
#include <sot/storage.hxx>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#ifndef _COM_SUN_STAR_SDB_COMMANDTYPE_HPP_
#include <com/sun/star/sdb/CommandType.hpp>
#endif
#ifndef DBAUI_TOKENWRITER_HXX
#include "TokenWriter.hxx"
#endif
#ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
#include "dbustrings.hrc"
#endif
#ifndef _COMPHELPER_EXTRACT_HXX_
#include <comphelper/extract.hxx>
#endif
#ifndef _SVX_DATACCESSDESCRIPTOR_HXX_
#include <svx/dataaccessdescriptor.hxx>
#endif

namespace dbaui
{
    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::beans;
    using namespace ::com::sun::star::sdb;
    using namespace ::com::sun::star::beans;
    using namespace ::com::sun::star::lang;
    using namespace ::com::sun::star::util;
    using namespace ::com::sun::star::sdbc;
    using namespace ::com::sun::star::datatransfer;
    using namespace ::svx;

    // -----------------------------------------------------------------------------
    ODataClipboard::ODataClipboard(
                    const ::rtl::OUString&  _rDatasource,
                    const sal_Int32         _nCommandType,
                    const ::rtl::OUString&  _rCommand,
                    const Reference< XConnection >& _rxConnection,
                    const Reference< XNumberFormatter >& _rxFormatter,
                    const Reference< XMultiServiceFactory >& _rxORB,
                    const sal_Int32 _nFormats)
        :m_pHtml(NULL)
        ,m_pRtf(NULL)
        ,m_nObjectType(CommandType::TABLE)
        ,m_nFormats(_nFormats)
    {
        // build the descriptor (the property sequence)
        ODataAccessDescriptor aDescriptor;
        aDescriptor[daDataSource]   <<= _rDatasource;
        aDescriptor[daConnection]   <<= _rxConnection;
        aDescriptor[daCommand]      <<= _rCommand;
        aDescriptor[daCommandType]  <<= _nCommandType;
        m_aSeq = aDescriptor.createPropertyValueSequence();

        // calculate some stuff which helps us providing the different formats
        if (m_nFormats && DCF_OBJECT_DESCRIPTOR)
        {
            // extract the single values from the sequence
            ::rtl::OUString sDatasourceName;
            ::rtl::OUString sObjectName;
            sal_Bool bEscapeProcessing = sal_True;
            sDatasourceName = _rDatasource;
            m_nObjectType = _nCommandType;
            sObjectName = _rCommand;

            // for compatibility: create a string which can be used for the SOT_FORMATSTR_ID_SBA_DATAEXCHANGE format

            sal_Bool bTreatAsStatement = (CommandType::COMMAND == m_nObjectType);
                // statements are - in this old and ugly format - described as queries

            const sal_Unicode       cSeparator = sal_Unicode(11);
            const ::rtl::OUString   sSeparator(&cSeparator, 1);

            const sal_Unicode       cTableMark = '1';
            const sal_Unicode       cQueryMark = '0';

            // build the descriptor string
            m_sCompatibleObjectDescription += sDatasourceName;
            m_sCompatibleObjectDescription += sSeparator;
            m_sCompatibleObjectDescription += bTreatAsStatement ? ::rtl::OUString() : sObjectName;
            m_sCompatibleObjectDescription += sSeparator;
            switch (m_nObjectType)
            {
                case CommandType::TABLE:
                    m_sCompatibleObjectDescription += ::rtl::OUString(&cTableMark, 1);
                    break;
                case CommandType::QUERY:
                    m_sCompatibleObjectDescription += ::rtl::OUString(&cQueryMark, 1);
                    break;
                case CommandType::COMMAND:
                    m_sCompatibleObjectDescription += ::rtl::OUString(&cQueryMark, 1);
                    // think of it as a query
                    break;
            }
            m_sCompatibleObjectDescription += sSeparator;
            m_sCompatibleObjectDescription += bTreatAsStatement ? sObjectName : ::rtl::OUString();
            m_sCompatibleObjectDescription += sSeparator;
        }

        if (m_nFormats && DCF_HTML_TABLE)
        {
            m_pHtml = new OHTMLImportExport(m_aSeq, _rxORB, _rxFormatter);
            m_xHtml = m_pHtml;
            m_pHtml->initialize();
        }

        if (m_nFormats && DCF_RTF_TABLE)
        {
            m_pRtf = new ORTFImportExport(m_aSeq, _rxORB, _rxFormatter);
            m_xRtf = m_pRtf;
            m_pRtf->initialize();
        }
    }

    // -----------------------------------------------------------------------------
    ODataClipboard::ODataClipboard(const Reference< XPropertySet >& _rxLivingForm, const Reference< XSQLQueryComposer >& _rxComposer)
        :m_pHtml(NULL)
        ,m_pRtf(NULL)
        ,m_nObjectType(CommandType::TABLE)
        ,m_nFormats(DCF_OBJECT_DESCRIPTOR)
    {
        // collect some properties of the form
        ::rtl::OUString sDatasourceName;
        sal_Int32       nObjectType = CommandType::COMMAND;
        ::rtl::OUString sObjectName;
        try
        {
            _rxLivingForm->getPropertyValue(PROPERTY_COMMANDTYPE) >>= nObjectType;
            _rxLivingForm->getPropertyValue(PROPERTY_COMMAND) >>= sObjectName;
            _rxLivingForm->getPropertyValue(PROPERTY_DATASOURCENAME) >>= sDatasourceName;
        }
        catch(Exception&)
        {
            OSL_ENSURE(sal_False, "ODataClipboard::ODataClipboard: could not collect essential form attributes !");
            m_nFormats = 0;
            return;
        }

        sal_Bool bIsStatement = CommandType::COMMAND == nObjectType;
        String sObjectKind = (CommandType::TABLE == nObjectType) ? String('1') : String('0');

        // check if the SQL-statement is modified
        sal_Bool bHasFilterOrSort(sal_False);
        ::rtl::OUString sCompleteStatement;
        try
        {
            ::rtl::OUString sFilter;
            if (::cppu::any2bool(_rxLivingForm->getPropertyValue(PROPERTY_APPLYFILTER)))
                _rxLivingForm->getPropertyValue(PROPERTY_FILTER) >>= sFilter;
            ::rtl::OUString sSort;
            _rxLivingForm->getPropertyValue(PROPERTY_ORDER) >>= sSort;
            bHasFilterOrSort = (sFilter.len()>0) || (sSort.len()>0);

            _rxLivingForm->getPropertyValue(PROPERTY_ACTIVECOMMAND) >>= sCompleteStatement;
            if (_rxComposer.is())
            {
                _rxComposer->setQuery(sCompleteStatement);
                _rxComposer->setFilter(sFilter);
                _rxComposer->setOrder(sSort);
                sCompleteStatement = _rxComposer->getComposedQuery();
            }
        }
        catch(Exception&)
        {
            OSL_ENSURE(sal_False, "ODataClipboard::ODataClipboard: could not collect essential form attributes (part two) !");
            m_nFormats = 0;
            return;
        }

        // build the object description (as string)
        const sal_Unicode       cSeparator(11);
        const ::rtl::OUString   sSeparator(&cSeparator, 1);

        m_sCompatibleObjectDescription = sDatasourceName;
        m_sCompatibleObjectDescription  += sSeparator;
        m_sCompatibleObjectDescription  += bIsStatement ? ::rtl::OUString() : sObjectName;
        m_sCompatibleObjectDescription  += sSeparator;
        m_sCompatibleObjectDescription  += sObjectKind;
        m_sCompatibleObjectDescription  += sSeparator;
        m_sCompatibleObjectDescription  +=
                (CommandType::QUERY == nObjectType) && !bHasFilterOrSort
                ? ::rtl::OUString()
            : sCompleteStatement;
            // compatibility says : always add the statement, but don't if it is a "pure" query
        m_sCompatibleObjectDescription  += sSeparator;
    }

    // -----------------------------------------------------------------------------
    void ODataClipboard::addRow(sal_Int32 _nRow)
    {
        OSL_ENSURE(m_nFormats && DCF_OBJECT_DESCRIPTOR, "ODataClipboard::addRow: don't have this (object descriptor) format!");

        const sal_Unicode       cSeparator(11);
        const ::rtl::OUString   sSeparator(&cSeparator, 1);

        m_sCompatibleObjectDescription += ::rtl::OUString::valueOf((sal_Int32)_nRow);
        m_sCompatibleObjectDescription += sSeparator;
    }

    // -----------------------------------------------------------------------------
    sal_Bool ODataClipboard::WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, const ::com::sun::star::datatransfer::DataFlavor& rFlavor )
    {
        if (nUserObjectId == SOT_FORMAT_RTF || nUserObjectId == SOT_FORMATSTR_ID_HTML)
        {
            ODatabaseImportExport* pExport = reinterpret_cast<ODatabaseImportExport*>(pUserObject);
            if(pExport)
            {
                pExport->setStream(&rxOStm);
                return pExport->Write();
            }
        }
        return sal_False;
    }

    // -----------------------------------------------------------------------------
    void ODataClipboard::AddSupportedFormats()
    {
        // RTF?
        if (m_nFormats && DCF_RTF_TABLE)
            AddFormat(SOT_FORMAT_RTF);

        // HTML?
        if (m_nFormats && DCF_HTML_TABLE)
            AddFormat(SOT_FORMATSTR_ID_HTML);

        // object descriptor?
        if (m_nFormats && DCF_OBJECT_DESCRIPTOR)
        {
            switch (m_nObjectType)
            {
                case CommandType::TABLE:
                    AddFormat(SOT_FORMATSTR_ID_DBACCESS_TABLE);
                    break;
                case CommandType::QUERY:
                    AddFormat(SOT_FORMATSTR_ID_DBACCESS_QUERY);
                    break;
                case CommandType::COMMAND:
                    AddFormat(SOT_FORMATSTR_ID_DBACCESS_COMMAND);
                    break;
            }

            sal_Int32 nDescriptorLen = m_sCompatibleObjectDescription.getLength();
            if (nDescriptorLen)
            {
                if (m_sCompatibleObjectDescription.getStr()[nDescriptorLen] == 11)
                    m_sCompatibleObjectDescription = m_sCompatibleObjectDescription.copy(0, nDescriptorLen - 1);

                if (nDescriptorLen)
                    AddFormat(SOT_FORMATSTR_ID_SBA_DATAEXCHANGE);
            }
        }
    }

    // -----------------------------------------------------------------------------
    sal_Bool ODataClipboard::GetData( const DataFlavor& rFlavor )
    {
        ULONG nFormat = SotExchange::GetFormat(rFlavor);
        switch (nFormat)
        {
            case SOT_FORMAT_RTF:
                return SetObject(m_pRtf,SOT_FORMAT_RTF,rFlavor);

            case SOT_FORMATSTR_ID_HTML:
                return SetObject(m_pHtml,SOT_FORMATSTR_ID_HTML,rFlavor);

            case SOT_FORMATSTR_ID_DBACCESS_TABLE:
            case SOT_FORMATSTR_ID_DBACCESS_QUERY:
            case SOT_FORMATSTR_ID_DBACCESS_COMMAND:
                return SetAny(makeAny(m_aSeq), rFlavor);

            case SOT_FORMATSTR_ID_SBA_DATAEXCHANGE:
                return SetString(m_sCompatibleObjectDescription, rFlavor);
        }
        return sal_False;
    }

    // -----------------------------------------------------------------------------
    void ODataClipboard::ObjectReleased()
    {
        m_xHtml = m_xRtf = NULL;
        m_pHtml = NULL;
        m_pRtf = NULL;
        m_aSeq.realloc(0);
    }

    // -----------------------------------------------------------------------------
}

<|endoftext|>