<commit_before>#include <stdio.h>

#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>

#include "log.hpp"
#include "comm.hpp"
#include "commands.hpp"

#include "linenoise/linenoise.h"

#include <thread>
#include <chrono>
#include <vector>
#include <string>

namespace fcwt {

static void print_status(int sockfd)
{
    auto const msg = generate<status_request_message>();
    printf("Status request %d\n", msg.id);
    fuji_send(sockfd, &msg, sizeof(msg));
    uint8_t buf[1024];
    uint32_t receivedBytes = fuji_receive(sockfd, buf);
    printf("Status: %d bytes\n", receivedBytes);
    print_hex(buf, receivedBytes);
    print_uint32(buf, receivedBytes);
    print_ascii(buf, receivedBytes);

    if (receivedBytes >= 124)
    {
      uint32_t iso, white_balance, film_simulation, autofocus_point, flash;
      memcpy(&flash, &buf[8 + 8], 4);
      memcpy(&iso, &buf[8 + 58], 4);
      memcpy(&white_balance, &buf[8 + 88], 4);
      memcpy(&film_simulation, &buf[8 + 92], 4);
      memcpy(&autofocus_point, &buf[8 + 104], 4); // only seems to work for single point, have not found data for 'zone' yet

      printf("iso=%u (%u) raw=%u\n", iso & 0xffff, iso >> 16, iso);
      printf("white_balance=%d\n", white_balance);
      printf("film_simulation=%u raw=%08X\n", film_simulation >> 16, film_simulation);
      printf("autofocus_point(x/y)=(%u,%u) raw=%08X\n", autofocus_point >> 24, (autofocus_point >> 16) & 0xff, autofocus_point);
      printf("flash raw=%08X\n", flash);
    }

    receivedBytes = fuji_receive(sockfd, buf);
}

void image_stream_main(std::atomic<bool>& flag)
{
  LOG_INFO("image_stream_main");
  sock const sockfd2 = connect_to_camera(jpg_stream_server_port);

  std::vector<uint8_t> buffer(1024 * 1024);

  if (sockfd2 <= 0)
    return;

  unsigned int image = 0;
  while (flag)
  {
    uint32_t receivedBytes = fuji_receive(sockfd2, buffer.data(), buffer.size());
    LOG_INFO_FORMAT("image_stream_main received %d bytes", receivedBytes);

    char filename[1024];
    snprintf(filename, sizeof(filename), "out/img_%d.jpg", image++);
    FILE* file = fopen(filename, "wb");
    if (file)
    {
      int const header = 14; // not sure what's in the first 14 bytes
      fwrite(&buffer[header], receivedBytes, 1, file);
      fclose(file);
    }
    else
    {
      LOG_WARN_FORMAT("image_stream_main Failed to create file %s", filename);
    }
  }
}

char const* comamndStrings[] =
{
  "connect",
  "shutter",
  "stream",
  "info"
};

enum class command
{
  connect,
  shutter,
  stream,
  info,
  unknown,
  count = unknown
};

static void completion(char const* buf, linenoiseCompletions* lc)
{
  for (int i = 0; i < static_cast<int>(command::count); ++i)
  {
    char const* const cmd = comamndStrings[i];
    if (strstr(cmd, buf) == cmd)
      linenoiseAddCompletion(lc, cmd);
  }
}

bool getline(std::string& line)
{
  char* const str = linenoise("fcwt> ");
  if (!str)
    return false;

  line.assign(str);
  free(str);
  return true;
}

command parse_command(std::string const& line)
{
  for (int i = 0; i < static_cast<int>(command::count); ++i)
  {
    if (line == comamndStrings[i])
      return static_cast<command>(i);
  }

  return command::unknown;
}

int main()
{

  /* Set the completion callback. This will be called every time the
   * user uses the <tab> key. */
  linenoiseSetCompletionCallback(completion);

  sock sockfd;
  std::atomic<bool> imageStreamFlag(true);
  std::thread imageStreamThread;

  std::string line;
  while(getline(line))
  {
      linenoiseHistoryAdd(line.c_str());
      command cmd = parse_command(line);
      /* Do something with the string. */
      switch(cmd)
      {
        case command::connect:
        {
          if (sockfd <= 0)
          {
            sockfd = connect_to_camera(control_server_port);
            if (!init_control_connection(sockfd, "HackedClient"))
              printf("failure\n");
            else
              print_status(sockfd);
          }
          else
          {
            printf("already connected\n");
          }
        }
        break;
      case command::shutter:
      {
        if (!shutter(sockfd))
          printf("failure\n");
        print_status(sockfd);

      }
      break;

      case command::stream:
      {
        imageStreamThread = std::thread(([&]() { image_stream_main(imageStreamFlag); }));
      }
      break;

      case command::info:
      {
        print_status(sockfd);
      }
      break;

      default:
      {
        printf("Unreconized command: %s\n", line.c_str());
      }
    }
  }

  if (imageStreamThread.joinable())
  {
    imageStreamFlag = false;
    imageStreamThread.join();
  }

  terminate_control_connection(sockfd);

  return 0;
}

} // namespace fcwt

int main(const int argc, char const* argv[])
{
  return fcwt::main();
}
<commit_msg>Image format setting<commit_after>#include <stdio.h>

#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>

#include "log.hpp"
#include "comm.hpp"
#include "commands.hpp"

#include "linenoise/linenoise.h"

#include <thread>
#include <chrono>
#include <vector>
#include <string>

namespace fcwt {

static void print_status(int sockfd)
{
    auto const msg = generate<status_request_message>();
    printf("Status request %d\n", msg.id);
    fuji_send(sockfd, &msg, sizeof(msg));
    uint8_t buf[1024];
    uint32_t receivedBytes = fuji_receive(sockfd, buf);
    printf("Status: %d bytes\n", receivedBytes);
    print_hex(buf, receivedBytes);
    print_uint32(buf, receivedBytes);
    print_ascii(buf, receivedBytes);

    if (receivedBytes >= 124)
    {
      uint32_t iso, white_balance, film_simulation, autofocus_point, flash, image_format_unknown, image_size_aspect, image_format;
      memcpy(&flash, &buf[8 + 8], 4);
      memcpy(&iso, &buf[8 + 58], 4);
      memcpy(&white_balance, &buf[8 + 76], 4);
      memcpy(&white_balance, &buf[8 + 88], 4);
      memcpy(&film_simulation, &buf[8 + 92], 4);
      memcpy(&autofocus_point, &buf[8 + 104], 4); // only seems to work for single point, have not found data for 'zone' yet
      memcpy(&image_format_unknown, &buf[8 + 20], 4);
      memcpy(&image_format, &buf[8 + 44], 4);
      memcpy(&image_size_aspect, &buf[8 + 52], 4);

      printf("iso=%u (%u) raw=%u\n", iso & 0xffff, iso >> 16, iso);
      printf("white_balance=%d\n", white_balance);
      printf("film_simulation=%u raw=%08X\n", film_simulation >> 16, film_simulation);
      printf("autofocus_point(x/y)=(%u,%u) raw=%08X\n", autofocus_point >> 24, (autofocus_point >> 16) & 0xff, autofocus_point);
      printf("flash raw=%08X\n", flash);
      printf("image_format_unknown=%08X\n", image_format_unknown);
      printf("image_size_aspect=%u %08X\n", image_size_aspect, image_size_aspect);
      printf("image_format=%u %08X\n", image_format >> 16, image_format);
    }

    receivedBytes = fuji_receive(sockfd, buf);
}

void image_stream_main(std::atomic<bool>& flag)
{
  LOG_INFO("image_stream_main");
  sock const sockfd2 = connect_to_camera(jpg_stream_server_port);

  std::vector<uint8_t> buffer(1024 * 1024);

  if (sockfd2 <= 0)
    return;

  unsigned int image = 0;
  while (flag)
  {
    uint32_t receivedBytes = fuji_receive(sockfd2, buffer.data(), buffer.size());
    LOG_INFO_FORMAT("image_stream_main received %d bytes", receivedBytes);

    char filename[1024];
    snprintf(filename, sizeof(filename), "out/img_%d.jpg", image++);
    FILE* file = fopen(filename, "wb");
    if (file)
    {
      int const header = 14; // not sure what's in the first 14 bytes
      fwrite(&buffer[header], receivedBytes, 1, file);
      fclose(file);
    }
    else
    {
      LOG_WARN_FORMAT("image_stream_main Failed to create file %s", filename);
    }
  }
}

char const* comamndStrings[] =
{
  "connect",
  "shutter",
  "stream",
  "info"
};

enum class command
{
  connect,
  shutter,
  stream,
  info,
  unknown,
  count = unknown
};

static void completion(char const* buf, linenoiseCompletions* lc)
{
  for (int i = 0; i < static_cast<int>(command::count); ++i)
  {
    char const* const cmd = comamndStrings[i];
    if (strstr(cmd, buf) == cmd)
      linenoiseAddCompletion(lc, cmd);
  }
}

bool getline(std::string& line)
{
  char* const str = linenoise("fcwt> ");
  if (!str)
    return false;

  line.assign(str);
  free(str);
  return true;
}

command parse_command(std::string const& line)
{
  for (int i = 0; i < static_cast<int>(command::count); ++i)
  {
    if (line == comamndStrings[i])
      return static_cast<command>(i);
  }

  return command::unknown;
}

int main()
{

  /* Set the completion callback. This will be called every time the
   * user uses the <tab> key. */
  linenoiseSetCompletionCallback(completion);

  sock sockfd;
  std::atomic<bool> imageStreamFlag(true);
  std::thread imageStreamThread;

  std::string line;
  while(getline(line))
  {
      linenoiseHistoryAdd(line.c_str());
      command cmd = parse_command(line);
      /* Do something with the string. */
      switch(cmd)
      {
        case command::connect:
        {
          if (sockfd <= 0)
          {
            sockfd = connect_to_camera(control_server_port);
            if (!init_control_connection(sockfd, "HackedClient"))
              printf("failure\n");
            else
              print_status(sockfd);
          }
          else
          {
            printf("already connected\n");
          }
        }
        break;
      case command::shutter:
      {
        if (!shutter(sockfd))
          printf("failure\n");
        print_status(sockfd);

      }
      break;

      case command::stream:
      {
        imageStreamThread = std::thread(([&]() { image_stream_main(imageStreamFlag); }));
      }
      break;

      case command::info:
      {
        print_status(sockfd);
      }
      break;

      default:
      {
        printf("Unreconized command: %s\n", line.c_str());
      }
    }
  }

  if (imageStreamThread.joinable())
  {
    imageStreamFlag = false;
    imageStreamThread.join();
  }

  terminate_control_connection(sockfd);

  return 0;
}

} // namespace fcwt

int main(const int argc, char const* argv[])
{
  return fcwt::main();
}
<|endoftext|>


<commit_before>#include <stdio.h>

#include "ExpertSystem/CLIPSEnvironment.h"
#include "ExpertSystem/KnowledgeConstructor.h"
#include "ExpertSystem/KnowledgeConstructionEngine.h"
#include "rampancy/RampancyCompiler.h"

extern "C" {
   #include "clips.h"
}

int main(int argc, char** argv, char* const *envp) {
   CLIPSEnvironment env;
   env.batchStar("Init.clp");
   env.reset();
   env.eval("(set-current-module MAIN)");
   rampancy::Compiler compiler(env, argv[0], envp);
   if(compiler.compileToKnowledge(argc, (const char**) argv)) {
      env.eval("(save-instances \"instances\")");
   } else {
      env.eval("(printout t \"ERROR: Something went wrong\" crlf)");
   }
}
<commit_msg>Modified kc to save all visible instances<commit_after>#include <stdio.h>

#include "ExpertSystem/CLIPSEnvironment.h"
#include "ExpertSystem/KnowledgeConstructor.h"
#include "ExpertSystem/KnowledgeConstructionEngine.h"
#include "rampancy/RampancyCompiler.h"

extern "C" {
   #include "clips.h"
}

int main(int argc, char** argv, char* const *envp) {
   CLIPSEnvironment env;
   env.batchStar("Init.clp");
   env.eval("(set-current-module MAIN)");
   rampancy::Compiler compiler(env, envp);
   if(compiler.compileToKnowledge(argc, (const char**) argv)) {
      env.eval("(save-instances \"instances\" visible)");
   } else {
      env.eval("(printout t \"ERROR: Something went wrong\" crlf)");
   }
   llvm::llvm_shutdown();
}
<|endoftext|>


<commit_before>//===-- llc.cpp - Implement the LLVM Native Code Generator ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the llc code generator driver. It provides a convenient
// command-line interface for generating native assembly-language code
// or C code, given LLVM bytecode.
//
//===----------------------------------------------------------------------===//

#include "llvm/Bytecode/Reader.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
#include "llvm/Target/SubtargetFeature.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/System/Signals.h"
#include "llvm/Config/config.h"
#include "llvm/LinkAllVMCore.h"
#include <fstream>
#include <iostream>
#include <memory>

using namespace llvm;

// General options for llc.  Other pass-specific options are specified
// within the corresponding llc passes, and target-specific options
// and back-end code generation options are specified with the target machine.
//
static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input bytecode>"), cl::init("-"));

static cl::opt<std::string>
OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));

static cl::opt<bool> Force("f", cl::desc("Overwrite output files"));

static cl::opt<bool> Fast("fast",
      cl::desc("Generate code quickly, potentially sacrificing code quality"));

static cl::opt<std::string>
TargetTriple("mtriple", cl::desc("Override target triple for module"));

static cl::opt<const TargetMachineRegistry::Entry*, false, TargetNameParser>
MArch("march", cl::desc("Architecture to generate code for:"));

static cl::opt<std::string>
MCPU("mcpu",
  cl::desc("Target a specific cpu type (-mcpu=help for details)"),
  cl::value_desc("cpu-name"),
  cl::init(""));

static cl::list<std::string>
MAttrs("mattr",
  cl::CommaSeparated,
  cl::desc("Target specific attributes (-mattr=help for details)"),
  cl::value_desc("a1,+a2,-a3,..."));

cl::opt<TargetMachine::CodeGenFileType>
FileType("filetype", cl::init(TargetMachine::AssemblyFile),
  cl::desc("Choose a file type (not all types are supported by all targets):"),
  cl::values(
       clEnumValN(TargetMachine::AssemblyFile,    "asm",
                  "  Emit an assembly ('.s') file"),
       clEnumValN(TargetMachine::ObjectFile,    "obj",
                  "  Emit a native object ('.o') file [experimental]"),
       clEnumValN(TargetMachine::DynamicLibrary, "dynlib",
                  "  Emit a native dynamic library ('.so') file"
                  " [experimental]"),
       clEnumValEnd));

cl::opt<bool> NoVerify("disable-verify", cl::Hidden,
                       cl::desc("Do not verify input module"));

// GetFileNameRoot - Helper function to get the basename of a filename.
static inline std::string
GetFileNameRoot(const std::string &InputFilename) {
  std::string IFN = InputFilename;
  std::string outputFilename;
  int Len = IFN.length();
  if ((Len > 2) &&
      IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') {
    outputFilename = std::string(IFN.begin(), IFN.end()-3); // s/.bc/.s/
  } else {
    outputFilename = IFN;
  }
  return outputFilename;
}

// main - Entry point for the llc compiler.
//
int main(int argc, char **argv) {
  try {
    cl::ParseCommandLineOptions(argc, argv, " llvm system compiler\n");
    sys::PrintStackTraceOnErrorSignal();

    // Load the module to be compiled...
    std::auto_ptr<Module> M(ParseBytecodeFile(InputFilename));
    if (M.get() == 0) {
      std::cerr << argv[0] << ": bytecode didn't read correctly.\n";
      return 1;
    }
    Module &mod = *M.get();

    // If we are supposed to override the target triple, do so now.
    if (!TargetTriple.empty())
      mod.setTargetTriple(TargetTriple);

    // Allocate target machine.  First, check whether the user has
    // explicitly specified an architecture to compile for.
    if (MArch == 0) {
      std::string Err;
      MArch = TargetMachineRegistry::getClosestStaticTargetForModule(mod, Err);
      if (MArch == 0) {
        std::cerr << argv[0] << ": error auto-selecting target for module '"
                  << Err << "'.  Please use the -march option to explicitly "
                  << "pick a target.\n";
        return 1;
      }
    }

    // Package up features to be passed to target/subtarget
    std::string FeaturesStr;
    if (MCPU.size() || MAttrs.size()) {
      SubtargetFeatures Features;
      Features.setCPU(MCPU);
      for (unsigned i = 0; i != MAttrs.size(); ++i)
        Features.AddFeature(MAttrs[i]);
      FeaturesStr = Features.getString();
    }

    std::auto_ptr<TargetMachine> target(MArch->CtorFn(mod, FeaturesStr));
    assert(target.get() && "Could not allocate target machine!");
    TargetMachine &Target = *target.get();

    // Build up all of the passes that we want to do to the module...
    PassManager Passes;
    Passes.add(new TargetData(*Target.getTargetData()));

#ifndef NDEBUG
    if(!NoVerify)
      Passes.add(createVerifierPass());
#endif

    // Figure out where we are going to send the output...
    std::ostream *Out = 0;
    if (OutputFilename != "") {
      if (OutputFilename != "-") {
        // Specified an output filename?
        if (!Force && std::ifstream(OutputFilename.c_str())) {
          // If force is not specified, make sure not to overwrite a file!
          std::cerr << argv[0] << ": error opening '" << OutputFilename
                    << "': file exists!\n"
                    << "Use -f command line argument to force output\n";
          return 1;
        }
        Out = new std::ofstream(OutputFilename.c_str());

        // Make sure that the Out file gets unlinked from the disk if we get a
        // SIGINT
        sys::RemoveFileOnSignal(sys::Path(OutputFilename));
      } else {
        Out = &std::cout;
      }
    } else {
      if (InputFilename == "-") {
        OutputFilename = "-";
        Out = &std::cout;
      } else {
        OutputFilename = GetFileNameRoot(InputFilename);

        switch (FileType) {
        case TargetMachine::AssemblyFile:
          if (MArch->Name[0] != 'c' || MArch->Name[1] != 0)  // not CBE
            OutputFilename += ".s";
          else
            OutputFilename += ".cbe.c";
          break;
        case TargetMachine::ObjectFile:
          OutputFilename += ".o";
          break;
        case TargetMachine::DynamicLibrary:
          OutputFilename += LTDL_SHLIB_EXT;
          break;
        }

        if (!Force && std::ifstream(OutputFilename.c_str())) {
          // If force is not specified, make sure not to overwrite a file!
          std::cerr << argv[0] << ": error opening '" << OutputFilename
                    << "': file exists!\n"
                    << "Use -f command line argument to force output\n";
          return 1;
        }

        Out = new std::ofstream(OutputFilename.c_str());
        if (!Out->good()) {
          std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
          delete Out;
          return 1;
        }

        // Make sure that the Out file gets unlinked from the disk if we get a
        // SIGINT
        sys::RemoveFileOnSignal(sys::Path(OutputFilename));
      }
    }

    // Ask the target to add backend passes as necessary.
    if (Target.addPassesToEmitFile(Passes, *Out, FileType, Fast)) {
      std::cerr << argv[0] << ": target '" << Target.getName()
                << "' does not support generation of this file type!\n";
      if (Out != &std::cout) delete Out;
      // And the Out file is empty and useless, so remove it now.
      sys::Path(OutputFilename).eraseFromDisk();
      return 1;
    } else {
      // Run our queue of passes all at once now, efficiently.
      Passes.run(*M.get());
    }

    // Delete the ostream if it's not a stdout stream
    if (Out != &std::cout) delete Out;

    return 0;
  } catch (const std::string& msg) {
    std::cerr << argv[0] << ": " << msg << "\n";
  } catch (...) {
    std::cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
  }
  return 1;
}
<commit_msg>Remove use of target::getName()<commit_after>//===-- llc.cpp - Implement the LLVM Native Code Generator ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the llc code generator driver. It provides a convenient
// command-line interface for generating native assembly-language code
// or C code, given LLVM bytecode.
//
//===----------------------------------------------------------------------===//

#include "llvm/Bytecode/Reader.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
#include "llvm/Target/SubtargetFeature.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/System/Signals.h"
#include "llvm/Config/config.h"
#include "llvm/LinkAllVMCore.h"
#include <fstream>
#include <iostream>
#include <memory>

using namespace llvm;

// General options for llc.  Other pass-specific options are specified
// within the corresponding llc passes, and target-specific options
// and back-end code generation options are specified with the target machine.
//
static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input bytecode>"), cl::init("-"));

static cl::opt<std::string>
OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));

static cl::opt<bool> Force("f", cl::desc("Overwrite output files"));

static cl::opt<bool> Fast("fast",
      cl::desc("Generate code quickly, potentially sacrificing code quality"));

static cl::opt<std::string>
TargetTriple("mtriple", cl::desc("Override target triple for module"));

static cl::opt<const TargetMachineRegistry::Entry*, false, TargetNameParser>
MArch("march", cl::desc("Architecture to generate code for:"));

static cl::opt<std::string>
MCPU("mcpu",
  cl::desc("Target a specific cpu type (-mcpu=help for details)"),
  cl::value_desc("cpu-name"),
  cl::init(""));

static cl::list<std::string>
MAttrs("mattr",
  cl::CommaSeparated,
  cl::desc("Target specific attributes (-mattr=help for details)"),
  cl::value_desc("a1,+a2,-a3,..."));

cl::opt<TargetMachine::CodeGenFileType>
FileType("filetype", cl::init(TargetMachine::AssemblyFile),
  cl::desc("Choose a file type (not all types are supported by all targets):"),
  cl::values(
       clEnumValN(TargetMachine::AssemblyFile,    "asm",
                  "  Emit an assembly ('.s') file"),
       clEnumValN(TargetMachine::ObjectFile,    "obj",
                  "  Emit a native object ('.o') file [experimental]"),
       clEnumValN(TargetMachine::DynamicLibrary, "dynlib",
                  "  Emit a native dynamic library ('.so') file"
                  " [experimental]"),
       clEnumValEnd));

cl::opt<bool> NoVerify("disable-verify", cl::Hidden,
                       cl::desc("Do not verify input module"));

// GetFileNameRoot - Helper function to get the basename of a filename.
static inline std::string
GetFileNameRoot(const std::string &InputFilename) {
  std::string IFN = InputFilename;
  std::string outputFilename;
  int Len = IFN.length();
  if ((Len > 2) &&
      IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') {
    outputFilename = std::string(IFN.begin(), IFN.end()-3); // s/.bc/.s/
  } else {
    outputFilename = IFN;
  }
  return outputFilename;
}

// main - Entry point for the llc compiler.
//
int main(int argc, char **argv) {
  try {
    cl::ParseCommandLineOptions(argc, argv, " llvm system compiler\n");
    sys::PrintStackTraceOnErrorSignal();

    // Load the module to be compiled...
    std::auto_ptr<Module> M(ParseBytecodeFile(InputFilename));
    if (M.get() == 0) {
      std::cerr << argv[0] << ": bytecode didn't read correctly.\n";
      return 1;
    }
    Module &mod = *M.get();

    // If we are supposed to override the target triple, do so now.
    if (!TargetTriple.empty())
      mod.setTargetTriple(TargetTriple);

    // Allocate target machine.  First, check whether the user has
    // explicitly specified an architecture to compile for.
    if (MArch == 0) {
      std::string Err;
      MArch = TargetMachineRegistry::getClosestStaticTargetForModule(mod, Err);
      if (MArch == 0) {
        std::cerr << argv[0] << ": error auto-selecting target for module '"
                  << Err << "'.  Please use the -march option to explicitly "
                  << "pick a target.\n";
        return 1;
      }
    }

    // Package up features to be passed to target/subtarget
    std::string FeaturesStr;
    if (MCPU.size() || MAttrs.size()) {
      SubtargetFeatures Features;
      Features.setCPU(MCPU);
      for (unsigned i = 0; i != MAttrs.size(); ++i)
        Features.AddFeature(MAttrs[i]);
      FeaturesStr = Features.getString();
    }

    std::auto_ptr<TargetMachine> target(MArch->CtorFn(mod, FeaturesStr));
    assert(target.get() && "Could not allocate target machine!");
    TargetMachine &Target = *target.get();

    // Build up all of the passes that we want to do to the module...
    PassManager Passes;
    Passes.add(new TargetData(*Target.getTargetData()));

#ifndef NDEBUG
    if(!NoVerify)
      Passes.add(createVerifierPass());
#endif

    // Figure out where we are going to send the output...
    std::ostream *Out = 0;
    if (OutputFilename != "") {
      if (OutputFilename != "-") {
        // Specified an output filename?
        if (!Force && std::ifstream(OutputFilename.c_str())) {
          // If force is not specified, make sure not to overwrite a file!
          std::cerr << argv[0] << ": error opening '" << OutputFilename
                    << "': file exists!\n"
                    << "Use -f command line argument to force output\n";
          return 1;
        }
        Out = new std::ofstream(OutputFilename.c_str());

        // Make sure that the Out file gets unlinked from the disk if we get a
        // SIGINT
        sys::RemoveFileOnSignal(sys::Path(OutputFilename));
      } else {
        Out = &std::cout;
      }
    } else {
      if (InputFilename == "-") {
        OutputFilename = "-";
        Out = &std::cout;
      } else {
        OutputFilename = GetFileNameRoot(InputFilename);

        switch (FileType) {
        case TargetMachine::AssemblyFile:
          if (MArch->Name[0] != 'c' || MArch->Name[1] != 0)  // not CBE
            OutputFilename += ".s";
          else
            OutputFilename += ".cbe.c";
          break;
        case TargetMachine::ObjectFile:
          OutputFilename += ".o";
          break;
        case TargetMachine::DynamicLibrary:
          OutputFilename += LTDL_SHLIB_EXT;
          break;
        }

        if (!Force && std::ifstream(OutputFilename.c_str())) {
          // If force is not specified, make sure not to overwrite a file!
          std::cerr << argv[0] << ": error opening '" << OutputFilename
                    << "': file exists!\n"
                    << "Use -f command line argument to force output\n";
          return 1;
        }

        Out = new std::ofstream(OutputFilename.c_str());
        if (!Out->good()) {
          std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
          delete Out;
          return 1;
        }

        // Make sure that the Out file gets unlinked from the disk if we get a
        // SIGINT
        sys::RemoveFileOnSignal(sys::Path(OutputFilename));
      }
    }

    // Ask the target to add backend passes as necessary.
    if (Target.addPassesToEmitFile(Passes, *Out, FileType, Fast)) {
      std::cerr << argv[0] << ": target does not support generation of this"
                << " file type!\n";
      if (Out != &std::cout) delete Out;
      // And the Out file is empty and useless, so remove it now.
      sys::Path(OutputFilename).eraseFromDisk();
      return 1;
    } else {
      // Run our queue of passes all at once now, efficiently.
      Passes.run(*M.get());
    }

    // Delete the ostream if it's not a stdout stream
    if (Out != &std::cout) delete Out;

    return 0;
  } catch (const std::string& msg) {
    std::cerr << argv[0] << ": " << msg << "\n";
  } catch (...) {
    std::cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
  }
  return 1;
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
// LLVM INTERPRETER/DEBUGGER/PROFILER UTILITY
//
// This utility is an interactive frontend to almost all other LLVM
// functionality.  It may be used as an interpreter to run code, a debugger to
// find problems, or a profiler to analyze execution frequencies.
//
//===----------------------------------------------------------------------===//

#include "Interpreter.h"
#include "llvm/Support/CommandLine.h"

cl::StringList InputArgv(""   , "Input command line", cl::ConsumeAfter);
cl::String MainFunction ("f"      , "Function to execute", cl::NoFlags, "main");
cl::Flag   DebugMode    ("debug"  , "Start program in debugger");
cl::Alias  DebugModeA   ("d"      , "Alias for -debug", cl::NoFlags, DebugMode);
cl::Flag   TraceMode    ("trace"  , "Enable Tracing");
cl::Flag   ProfileMode  ("profile", "Enable Profiling [unimp]");

//===----------------------------------------------------------------------===//
// Interpreter ctor - Initialize stuff
//
Interpreter::Interpreter() : ExitCode(0), Profile(ProfileMode),
                             Trace(TraceMode), CurFrame(-1) {
  CurMod = 0;
  loadModule(InputArgv.size() ? InputArgv[0] : "");

  // Initialize the "backend"
  initializeExecutionEngine();
}

//===----------------------------------------------------------------------===//
// main Driver function
//
int main(int argc, char** argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm interpreter\n");

  // Create the interpreter...
  Interpreter I;

  // Handle alternate names of the program.  If started as llp, enable profiling
  // if started as ldb, enable debugging...
  //
  if (argv[0] == "ldb")       // TODO: Obviously incorrect, but you get the idea
    DebugMode = true;
  else if (argv[0] == "llp")
    ProfileMode = true;

  // If running with the profiler, enable it now...
  if (ProfileMode) I.enableProfiling();
  if (TraceMode) I.enableTracing();

  // Start interpreter into the main function...
  //
  if (!I.callMainMethod(MainFunction, InputArgv) && !DebugMode) {
    // If not in debug mode and if the call succeeded, run the code now...
    I.run();
  }

  // If debug mode, allow the user to interact... also, if the user pressed
  // ctrl-c or execution hit an error, enter the event loop...
  if (DebugMode || I.isStopped())
    I.handleUserInput();

  // Return the status code of the program executed...
  return I.getExitCode();
}
<commit_msg>Oops, accidentally broke reading from stdin when doing command line arguments<commit_after>//===----------------------------------------------------------------------===//
// LLVM INTERPRETER/DEBUGGER/PROFILER UTILITY
//
// This utility is an interactive frontend to almost all other LLVM
// functionality.  It may be used as an interpreter to run code, a debugger to
// find problems, or a profiler to analyze execution frequencies.
//
//===----------------------------------------------------------------------===//

#include "Interpreter.h"
#include "llvm/Support/CommandLine.h"

cl::StringList InputArgv(""   , "Input command line", cl::ConsumeAfter);
cl::String MainFunction ("f"      , "Function to execute", cl::NoFlags, "main");
cl::Flag   DebugMode    ("debug"  , "Start program in debugger");
cl::Alias  DebugModeA   ("d"      , "Alias for -debug", cl::NoFlags, DebugMode);
cl::Flag   TraceMode    ("trace"  , "Enable Tracing");
cl::Flag   ProfileMode  ("profile", "Enable Profiling [unimp]");

//===----------------------------------------------------------------------===//
// Interpreter ctor - Initialize stuff
//
Interpreter::Interpreter() : ExitCode(0), Profile(ProfileMode),
                             Trace(TraceMode), CurFrame(-1) {
  CurMod = 0;
  loadModule(InputArgv.size() ? InputArgv[0] : "-");

  // Initialize the "backend"
  initializeExecutionEngine();
}

//===----------------------------------------------------------------------===//
// main Driver function
//
int main(int argc, char** argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm interpreter\n");

  // Create the interpreter...
  Interpreter I;

  // Handle alternate names of the program.  If started as llp, enable profiling
  // if started as ldb, enable debugging...
  //
  if (argv[0] == "ldb")       // TODO: Obviously incorrect, but you get the idea
    DebugMode = true;
  else if (argv[0] == "llp")
    ProfileMode = true;

  // If running with the profiler, enable it now...
  if (ProfileMode) I.enableProfiling();
  if (TraceMode) I.enableTracing();

  // Start interpreter into the main function...
  //
  if (!I.callMainMethod(MainFunction, InputArgv) && !DebugMode) {
    // If not in debug mode and if the call succeeded, run the code now...
    I.run();
  }

  // If debug mode, allow the user to interact... also, if the user pressed
  // ctrl-c or execution hit an error, enter the event loop...
  if (DebugMode || I.isStopped())
    I.handleUserInput();

  // Return the status code of the program executed...
  return I.getExitCode();
}
<|endoftext|>


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

#ifndef _ZYCORE_TMP_HPP_
#define _ZYCORE_TMP_HPP_

namespace zycore
{
namespace mpl
{

/**
 * @brief   End type indicating that there are no more elements in a container.
 */
class End {};

// ============================================================================================== //
// [Stack]                                                                                //
// ============================================================================================== //

/**
 * @brief   Stack of types.
 * @tparam  ElementsT   Initial content of the stack, top element up front.
 */
template<typename... ElementsT>
class Stack final
{
private:
    /**
     * @brief   Push implementation.
     * @tparam  ItemT   The new item to push.
     */
    template<typename ItemT>
    struct PushImpl
    {
        using NewStack = Stack<ItemT, ElementsT...>;
    };

    /**
     * @brief   Pop implementation capturing on empty stacks.
     * @tparam  StackT  Type stack type.
     */
    template<typename StackT>
    struct PopImpl
    {
        using NewStack = StackT;
        using Item = End;
    };

    /**
     * @brief   Pop implementation capturing on stacks with elements.
     * @tparam  StackT  Type stack type.
     */
    template<template<typename...> class StackT, typename... ContentT, typename TopItemT>
    struct PopImpl<StackT<TopItemT, ContentT...>>
    {
        using NewStack = StackT<ContentT...>;
        using Item = TopItemT;
    };
public:
    template<typename ItemT>
    using Push = typename PushImpl<ItemT>::NewStack;

    using Pop = typename PopImpl<Stack<ElementsT...>>::NewStack;
    using Top = typename PopImpl<Stack<ElementsT...>>::Item;

    static const std::size_t kSize = sizeof...(ElementsT);
    static const bool kEmpty = kSize == 0;
};

// ============================================================================================== //
// [SliceView]                                                                                //
// ============================================================================================== //

namespace internal
{

template<
    typename InContainerT,
    typename OutContainerT,
    std::size_t startT,
    std::size_t endT,
    std::size_t curT,
    typename=void>
struct SliceViewImpl2
    : SliceViewImpl2<
        typename InContainerT::PopFront,
        std::conditional_t<
            curT >= startT && curT <= endT,
            typename OutContainerT::template PushFront<typename InContainerT::Top>,
            OutContainerT>,
        startT,
        endT,
        curT + 1>
{};

template<
    typename InContainerT,
    typename OutContainerT,
    std::size_t startT,
    std::size_t endT,
    std::size_t curT>
struct SliceViewImpl2<
    InContainerT,
    OutContainerT,
    startT, endT, curT,
    std::enable_if_t<InContainerT::kEmpty>>
{
    using Projection = OutContainerT;
};

template<typename ContainerT, std::size_t startT, std::size_t endT>
struct SliceViewImpl;

template<
    template<typename...> class ContainerT,
    typename... ElementsT,
    std::size_t startT,
    std::size_t endT>
struct SliceViewImpl<ContainerT<ElementsT...>, startT, endT>
    : SliceViewImpl2<ContainerT<ElementsT...>, ContainerT<>, startT, endT, 0> {};

} // namespace internal

/**
 * @brief   Slices an MPL container.
 * @tparam  ContainerT  The container to be sliced.
 * @tparam  startT      The index to start slicing.
 * @tparam  endT        The index to stop slicing.
 */
template<typename ContainerT, std::size_t startT, std::size_t endT>
using SliceView = typename internal::SliceViewImpl<ContainerT, startT, endT>::Projection;

// ============================================================================================== //
// [Vector]                                                                                //
// ============================================================================================== //

template<typename... ContentT>
class Vector
{
    template<typename ItemT>
    struct PushBackImpl
    {
        using NewContainer = Vector<ContentT..., ItemT>;
    };

    template<typename ItemT>
    struct PushFrontImpl
    {
        using NewContainer = Vector<ItemT, ContentT...>;
    };

    template<typename ContainerT>
    struct PopFrontImpl
    {
        using NewContainer = ContainerT;
        using Item = End;
    };

    template<typename... ElementsT, typename FrontItemT>
    struct PopFrontImpl<Vector<FrontItemT, ElementsT...>>
    {
        using NewContainer = Vector<ElementsT...>;
        using Item = FrontItemT;
    };
public:
    static const std::size_t kSize = sizeof...(ContentT);
    static const bool kEmpty = kSize == 0;

    template<typename ItemT>
    using PushFront = typename PushFrontImpl<ItemT>::NewContainer;
    template<typename ItemT>
    using PushBack = typename PushBackImpl<ItemT>::NewContainer;

    using PopFront = typename PopFrontImpl<Vector<ContentT...>>::NewContainer;
    using Top = typename PopFrontImpl<Vector<ContentT...>>::Item;

    using PopBack = SliceView<Vector<ContentT...>, 0, kSize - 1>;
    using Bottom = typename SliceView<Vector<ContentT...>, kSize - 1, kSize>::Top;
};

// ============================================================================================== //

} // namespace mpl
} // namespace zycore

#endif // _ZYCORE_TMP_HPP_
<commit_msg>added missing include to Mpl.hpp<commit_after>/**
 * This file is part of the zyan core library (zyantific.com).
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Joel Höner (athre0z)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef _ZYCORE_TMP_HPP_
#define _ZYCORE_TMP_HPP_

#include <type_traits>

namespace zycore
{
namespace mpl
{

/**
 * @brief   End type indicating that there are no more elements in a container.
 */
class End {};

// ============================================================================================== //
// [Stack]                                                                                //
// ============================================================================================== //

/**
 * @brief   Stack of types.
 * @tparam  ElementsT   Initial content of the stack, top element up front.
 */
template<typename... ElementsT>
class Stack final
{
private:
    /**
     * @brief   Push implementation.
     * @tparam  ItemT   The new item to push.
     */
    template<typename ItemT>
    struct PushImpl
    {
        using NewStack = Stack<ItemT, ElementsT...>;
    };

    /**
     * @brief   Pop implementation capturing on empty stacks.
     * @tparam  StackT  Type stack type.
     */
    template<typename StackT>
    struct PopImpl
    {
        using NewStack = StackT;
        using Item = End;
    };

    /**
     * @brief   Pop implementation capturing on stacks with elements.
     * @tparam  StackT  Type stack type.
     */
    template<template<typename...> class StackT, typename... ContentT, typename TopItemT>
    struct PopImpl<StackT<TopItemT, ContentT...>>
    {
        using NewStack = StackT<ContentT...>;
        using Item = TopItemT;
    };
public:
    template<typename ItemT>
    using Push = typename PushImpl<ItemT>::NewStack;

    using Pop = typename PopImpl<Stack<ElementsT...>>::NewStack;
    using Top = typename PopImpl<Stack<ElementsT...>>::Item;

    static const std::size_t kSize = sizeof...(ElementsT);
    static const bool kEmpty = kSize == 0;
};

// ============================================================================================== //
// [SliceView]                                                                                //
// ============================================================================================== //

namespace internal
{

template<
    typename InContainerT,
    typename OutContainerT,
    std::size_t startT,
    std::size_t endT,
    std::size_t curT,
    typename=void>
struct SliceViewImpl2
    : SliceViewImpl2<
        typename InContainerT::PopFront,
        std::conditional_t<
            curT >= startT && curT <= endT,
            typename OutContainerT::template PushFront<typename InContainerT::Top>,
            OutContainerT>,
        startT,
        endT,
        curT + 1>
{};

template<
    typename InContainerT,
    typename OutContainerT,
    std::size_t startT,
    std::size_t endT,
    std::size_t curT>
struct SliceViewImpl2<
    InContainerT,
    OutContainerT,
    startT, endT, curT,
    std::enable_if_t<InContainerT::kEmpty>>
{
    using Projection = OutContainerT;
};

template<typename ContainerT, std::size_t startT, std::size_t endT>
struct SliceViewImpl;

template<
    template<typename...> class ContainerT,
    typename... ElementsT,
    std::size_t startT,
    std::size_t endT>
struct SliceViewImpl<ContainerT<ElementsT...>, startT, endT>
    : SliceViewImpl2<ContainerT<ElementsT...>, ContainerT<>, startT, endT, 0> {};

} // namespace internal

/**
 * @brief   Slices an MPL container.
 * @tparam  ContainerT  The container to be sliced.
 * @tparam  startT      The index to start slicing.
 * @tparam  endT        The index to stop slicing.
 */
template<typename ContainerT, std::size_t startT, std::size_t endT>
using SliceView = typename internal::SliceViewImpl<ContainerT, startT, endT>::Projection;

// ============================================================================================== //
// [Vector]                                                                                //
// ============================================================================================== //

template<typename... ContentT>
class Vector
{
    template<typename ItemT>
    struct PushBackImpl
    {
        using NewContainer = Vector<ContentT..., ItemT>;
    };

    template<typename ItemT>
    struct PushFrontImpl
    {
        using NewContainer = Vector<ItemT, ContentT...>;
    };

    template<typename ContainerT>
    struct PopFrontImpl
    {
        using NewContainer = ContainerT;
        using Item = End;
    };

    template<typename... ElementsT, typename FrontItemT>
    struct PopFrontImpl<Vector<FrontItemT, ElementsT...>>
    {
        using NewContainer = Vector<ElementsT...>;
        using Item = FrontItemT;
    };
public:
    static const std::size_t kSize = sizeof...(ContentT);
    static const bool kEmpty = kSize == 0;

    template<typename ItemT>
    using PushFront = typename PushFrontImpl<ItemT>::NewContainer;
    template<typename ItemT>
    using PushBack = typename PushBackImpl<ItemT>::NewContainer;

    using PopFront = typename PopFrontImpl<Vector<ContentT...>>::NewContainer;
    using Top = typename PopFrontImpl<Vector<ContentT...>>::Item;

    using PopBack = SliceView<Vector<ContentT...>, 0, kSize - 1>;
    using Bottom = typename SliceView<Vector<ContentT...>, kSize - 1, kSize>::Top;
};

// ============================================================================================== //

} // namespace mpl
} // namespace zycore

#endif // _ZYCORE_TMP_HPP_
<|endoftext|>


<commit_before>/*

 ===== IMPORTANT =====

 This is sample code demonstrating API, technology or techniques in development.
 Although this sample code has been reviewed for technical accuracy, it is not
 final. Apple is supplying this information to help you plan for the adoption of
 the technologies and programming interfaces described herein. This information
 is subject to change, and software implemented based on this sample code should
 be tested with final operating system software and final documentation. Newer
 versions of this sample code may be provid
 ed with future seeds of the API or
 technology. For information about updates to this and other developer
 documentation, view the New & Updated sidebars in subsequent documentation
 seeds.

 =====================

 File: Texture2D.m
 Abstract: Creates OpenGL 2D textures from images or text.

 Version: 1.6

 Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Inc.
 ("Apple") in consideration of your agreement to the following terms, and your
 use, installation, modification or redistribution of this Apple software
 constitutes acceptance of these terms.  If you do not agree with these terms,
 please do not use, install, modify or redistribute this Apple software.

 In consideration of your agreement to abide by the following terms, and subject
 to these terms, Apple grants you a personal, non-exclusive license, under
 Apple's copyrights in this original Apple software (the "Apple Software"), to
 use, reproduce, modify and redistribute the Apple Software, with or without
 modifications, in source and/or binary forms; provided that if you redistribute
 the Apple Software in its entirety and without modifications, you must retain
 this notice and the following text and disclaimers in all such redistributions
 of the Apple Software.
 Neither the name, trademarks, service marks or logos of Apple Inc. may be used
 to endorse or promote products derived from the Apple Software without specific
 prior written permission from Apple.  Except as expressly stated in this notice,
 no other rights or licenses, express or implied, are granted by Apple herein,
 including but not limited to any patent rights that may be infringed by your
 derivative works or by other works in which the Apple Software may be
 incorporated.

 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 COMBINATION WITH YOUR PRODUCTS.

 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
 DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
 CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
 APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 Copyright (C) 2008 Apple Inc. All Rights Reserved.

 */

#include "opengl/texture2D.h"

#include <OpenGLES/ES1/glext.h>

int Texture2D::nameCounter_ = 0;
GLfloat Texture2D::globalAlpha_ = 1;
GLfloat Texture2D::screen_height_ = 480;

Texture2D::Texture2D(const void *data, Texture2DPixelFormat pixelFormat, uint32_t width,
                     uint32_t height, ScreenSize size, string filename) {
  Init(data, pixelFormat, width, height, size, filename);
}

void Texture2D::SetGlobalAlpha(GLfloat alpha) {
  globalAlpha_ = alpha;
}

void Texture2D::DrawAtPoint(ScreenPoint point) {
  DrawAtPoint(point, 1.f, 1.f, 0.f, 0.f);
}

void Texture2D::DrawAtPoint(ScreenPoint point, GLfloat alpha, GLfloat zoom, GLfloat angle, GLfloat z) {
  if (!name_) {
    return;
  }

  // Swap vertical coordinate system.
  point.y = screen_height_ - point.y;

  GLfloat width = (GLfloat)width_ * max_s_,
  height = (GLfloat)height_ * max_t_;

  glLoadIdentity();
  glBindTexture(GL_TEXTURE_2D, name_);
  glVertexPointer(3, GL_FLOAT, 0, vertices_);
  glTexCoordPointer(2, GL_FLOAT, 0, coordinates_);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
  glTranslatef(point.x + width/2.0, point.y - height/2.0, 0.0);
  glRotatef(angle, 0.f, 0.f, 1.f);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glColor4f(1.f, 1.f, 1.f, alpha*globalAlpha_);
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void Texture2D::DrawAtPointLeftRatio(ScreenPoint point, GLfloat leftRatio) {
  if (!name_) {
    return;
  }

  // Swap vertical coordinate system.
  // TODO make this not screen size dependent.
  point.y = screen_height_ - point.y;

  GLfloat    width = (GLfloat)width_ * max_s_ * leftRatio,
  height = (GLfloat)height_ * max_t_;

  coordinates_[2] = coordinates_[6] = leftRatio * max_s_;

  vertices_[0] = -width/2.0;
  vertices_[1] = -height/2.0;

  vertices_[3] = width/2.0;
  vertices_[4] = -height/2.0;

  vertices_[6] = -width/2.0;
  vertices_[7] = height/2.0;

  vertices_[9] = width/2.0;
  vertices_[10] = height/2.0;

  glLoadIdentity();
  glBindTexture(GL_TEXTURE_2D, name_);
  glVertexPointer(3, GL_FLOAT, 0, vertices_);
  glTexCoordPointer(2, GL_FLOAT, 0, coordinates_);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glTranslatef(point.x + width/2.0, point.y - height/2.0, 0.0);
  //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void Texture2D::DrawAtPointRightRatio(ScreenPoint point, GLfloat rightRatio) {
  if (!name_) {
    return;
  }

  // Swap vertical coordinate system.
  point.y = screen_height_ - point.y;

  GLfloat    width = (GLfloat)width_ * max_s_ * rightRatio,
  height = (GLfloat)height_ * max_t_;

  coordinates_[0] = coordinates_[4] = (1.0 - rightRatio) * max_s_;

  vertices_[0] = -width/2.0;
  vertices_[1] = -height/2.0;

  vertices_[3] = width/2.0;
  vertices_[4] = -height/2.0;

  vertices_[6] = -width/2.0;
  vertices_[7] = height/2.0;

  vertices_[9] = width/2.0;
  vertices_[10] = height/2.0;

  glLoadIdentity();
  glBindTexture(GL_TEXTURE_2D, name_);
  glVertexPointer(3, GL_FLOAT, 0, vertices_);
  glTexCoordPointer(2, GL_FLOAT, 0, coordinates_);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glTranslatef(point.x + width/2.0 + (1.0 - rightRatio) * (GLfloat)width_ * max_s_, point.y - height/2.0, 0.0);
  //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void Texture2D::DrawAtPointAngle(ScreenPoint point, GLfloat angle) {
  if (!name_) {
    return;
  }

  // Swap vertical coordinate system.
  point.y = screen_height_ - point.y;

  GLfloat    width = (GLfloat)width_ * max_s_,
  height = (GLfloat)height_ * max_t_;

  glLoadIdentity();
  glBindTexture(GL_TEXTURE_2D, name_);
  glVertexPointer(3, GL_FLOAT, 0, vertices_);
  glTexCoordPointer(2, GL_FLOAT, 0, coordinates_);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glTranslatef(point.x + width/2.0, point.y - height/2.0, 0.0);
  glRotatef(angle, 0.f, 0.f, 1.f);
  //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void Texture2D::Delete() {
  assert(name_);
  glDeleteTextures(1, &name_);
  name_ = 0;
}

// Private

void Texture2D::Init(const void *data, Texture2DPixelFormat pixelFormat, uint32_t width,
                     uint32_t height, ScreenSize size, string filename) {
  GLint saveName;
  filename_ = filename;

  //glGenTextures(1, &name_);
  name_ = ++nameCounter_;

  glGetIntegerv(GL_TEXTURE_BINDING_2D, &saveName);
  glBindTexture(GL_TEXTURE_2D, name_);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  switch(pixelFormat) {
    case kTexture2DPixelFormat_RGBA8888:
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
      break;
    case kTexture2DPixelFormat_RGB565:
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
      break;
    case kTexture2DPixelFormat_A8:
      glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
      break;
    default:
      break;
      // TODO [NSException raise:NSInternalInconsistencyException format:@""];

  }
  glBindTexture(GL_TEXTURE_2D, saveName);

  size_ = size;
  width_ = width;
  height_ = height;
  format_ = pixelFormat;
  max_s_ = size.width / (float)width;
  max_t_ = size.height / (float)height;

  coordinates_[0] = 0;
  coordinates_[1] = max_t_;

  coordinates_[2] = max_s_;
  coordinates_[3] = max_t_;

  coordinates_[4] = 0;
  coordinates_[5] = 0;

  coordinates_[6] = max_s_;
  coordinates_[7] = 0;

  vertices_[0] = -size.width/2.0;
  vertices_[1] = -size.height/2.0;
  vertices_[2] = 0;

  vertices_[3] = size.width/2.0;
  vertices_[4] = -size.height/2.0;
  vertices_[5] = 0;

  vertices_[6] = -size.width/2.0;
  vertices_[7] = size.height/2.0;
  vertices_[8] = 0.0;

  vertices_[9] = size.width/2.0;
  vertices_[10] = size.height/2.0;
  vertices_[11] = 0.0;
}
<commit_msg>Support zoom.<commit_after>/*

 ===== IMPORTANT =====

 This is sample code demonstrating API, technology or techniques in development.
 Although this sample code has been reviewed for technical accuracy, it is not
 final. Apple is supplying this information to help you plan for the adoption of
 the technologies and programming interfaces described herein. This information
 is subject to change, and software implemented based on this sample code should
 be tested with final operating system software and final documentation. Newer
 versions of this sample code may be provid
 ed with future seeds of the API or
 technology. For information about updates to this and other developer
 documentation, view the New & Updated sidebars in subsequent documentation
 seeds.

 =====================

 File: Texture2D.m
 Abstract: Creates OpenGL 2D textures from images or text.

 Version: 1.6

 Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Inc.
 ("Apple") in consideration of your agreement to the following terms, and your
 use, installation, modification or redistribution of this Apple software
 constitutes acceptance of these terms.  If you do not agree with these terms,
 please do not use, install, modify or redistribute this Apple software.

 In consideration of your agreement to abide by the following terms, and subject
 to these terms, Apple grants you a personal, non-exclusive license, under
 Apple's copyrights in this original Apple software (the "Apple Software"), to
 use, reproduce, modify and redistribute the Apple Software, with or without
 modifications, in source and/or binary forms; provided that if you redistribute
 the Apple Software in its entirety and without modifications, you must retain
 this notice and the following text and disclaimers in all such redistributions
 of the Apple Software.
 Neither the name, trademarks, service marks or logos of Apple Inc. may be used
 to endorse or promote products derived from the Apple Software without specific
 prior written permission from Apple.  Except as expressly stated in this notice,
 no other rights or licenses, express or implied, are granted by Apple herein,
 including but not limited to any patent rights that may be infringed by your
 derivative works or by other works in which the Apple Software may be
 incorporated.

 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 COMBINATION WITH YOUR PRODUCTS.

 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
 DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
 CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
 APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 Copyright (C) 2008 Apple Inc. All Rights Reserved.

 */

#include "opengl/texture2D.h"

#include <OpenGLES/ES1/glext.h>

int Texture2D::nameCounter_ = 0;
GLfloat Texture2D::globalAlpha_ = 1;
GLfloat Texture2D::screen_height_ = 480;

Texture2D::Texture2D(const void *data, Texture2DPixelFormat pixelFormat, uint32_t width,
                     uint32_t height, ScreenSize size, string filename) {
  Init(data, pixelFormat, width, height, size, filename);
}

void Texture2D::SetGlobalAlpha(GLfloat alpha) {
  globalAlpha_ = alpha;
}

void Texture2D::DrawAtPoint(ScreenPoint point) {
  DrawAtPoint(point, 1.f, 1.f, 0.f, 0.f);
}

void Texture2D::DrawAtPoint(ScreenPoint point, GLfloat alpha, GLfloat zoom, GLfloat angle, GLfloat z) {
  if (!name_) {
    return;
  }

  // Swap vertical coordinate system.
  point.y = screen_height_ - point.y;

  GLfloat width = (GLfloat)width_ * max_s_,
  height = (GLfloat)height_ * max_t_;

  glLoadIdentity();
  glBindTexture(GL_TEXTURE_2D, name_);
  glVertexPointer(3, GL_FLOAT, 0, vertices_);
  glTexCoordPointer(2, GL_FLOAT, 0, coordinates_);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
  glTranslatef(point.x + width/2.0, point.y - height/2.0, 0.0);
  glScalef(zoom, zoom, 0);
  glRotatef(angle, 0.f, 0.f, 1.f);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glColor4f(1.f, 1.f, 1.f, alpha*globalAlpha_);
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void Texture2D::DrawAtPointLeftRatio(ScreenPoint point, GLfloat leftRatio) {
  if (!name_) {
    return;
  }

  // Swap vertical coordinate system.
  // TODO make this not screen size dependent.
  point.y = screen_height_ - point.y;

  GLfloat    width = (GLfloat)width_ * max_s_ * leftRatio,
  height = (GLfloat)height_ * max_t_;

  coordinates_[2] = coordinates_[6] = leftRatio * max_s_;

  vertices_[0] = -width/2.0;
  vertices_[1] = -height/2.0;

  vertices_[3] = width/2.0;
  vertices_[4] = -height/2.0;

  vertices_[6] = -width/2.0;
  vertices_[7] = height/2.0;

  vertices_[9] = width/2.0;
  vertices_[10] = height/2.0;

  glLoadIdentity();
  glBindTexture(GL_TEXTURE_2D, name_);
  glVertexPointer(3, GL_FLOAT, 0, vertices_);
  glTexCoordPointer(2, GL_FLOAT, 0, coordinates_);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glTranslatef(point.x + width/2.0, point.y - height/2.0, 0.0);
  //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void Texture2D::DrawAtPointRightRatio(ScreenPoint point, GLfloat rightRatio) {
  if (!name_) {
    return;
  }

  // Swap vertical coordinate system.
  point.y = screen_height_ - point.y;

  GLfloat    width = (GLfloat)width_ * max_s_ * rightRatio,
  height = (GLfloat)height_ * max_t_;

  coordinates_[0] = coordinates_[4] = (1.0 - rightRatio) * max_s_;

  vertices_[0] = -width/2.0;
  vertices_[1] = -height/2.0;

  vertices_[3] = width/2.0;
  vertices_[4] = -height/2.0;

  vertices_[6] = -width/2.0;
  vertices_[7] = height/2.0;

  vertices_[9] = width/2.0;
  vertices_[10] = height/2.0;

  glLoadIdentity();
  glBindTexture(GL_TEXTURE_2D, name_);
  glVertexPointer(3, GL_FLOAT, 0, vertices_);
  glTexCoordPointer(2, GL_FLOAT, 0, coordinates_);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glTranslatef(point.x + width/2.0 + (1.0 - rightRatio) * (GLfloat)width_ * max_s_, point.y - height/2.0, 0.0);
  //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void Texture2D::DrawAtPointAngle(ScreenPoint point, GLfloat angle) {
  if (!name_) {
    return;
  }

  // Swap vertical coordinate system.
  point.y = screen_height_ - point.y;

  GLfloat    width = (GLfloat)width_ * max_s_,
  height = (GLfloat)height_ * max_t_;

  glLoadIdentity();
  glBindTexture(GL_TEXTURE_2D, name_);
  glVertexPointer(3, GL_FLOAT, 0, vertices_);
  glTexCoordPointer(2, GL_FLOAT, 0, coordinates_);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glTranslatef(point.x + width/2.0, point.y - height/2.0, 0.0);
  glRotatef(angle, 0.f, 0.f, 1.f);
  //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void Texture2D::Delete() {
  assert(name_);
  glDeleteTextures(1, &name_);
  name_ = 0;
}

// Private

void Texture2D::Init(const void *data, Texture2DPixelFormat pixelFormat, uint32_t width,
                     uint32_t height, ScreenSize size, string filename) {
  GLint saveName;
  filename_ = filename;

  //glGenTextures(1, &name_);
  name_ = ++nameCounter_;

  glGetIntegerv(GL_TEXTURE_BINDING_2D, &saveName);
  glBindTexture(GL_TEXTURE_2D, name_);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  switch(pixelFormat) {
    case kTexture2DPixelFormat_RGBA8888:
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
      break;
    case kTexture2DPixelFormat_RGB565:
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
      break;
    case kTexture2DPixelFormat_A8:
      glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
      break;
    default:
      break;
      // TODO [NSException raise:NSInternalInconsistencyException format:@""];

  }
  glBindTexture(GL_TEXTURE_2D, saveName);

  size_ = size;
  width_ = width;
  height_ = height;
  format_ = pixelFormat;
  max_s_ = size.width / (float)width;
  max_t_ = size.height / (float)height;

  coordinates_[0] = 0;
  coordinates_[1] = max_t_;

  coordinates_[2] = max_s_;
  coordinates_[3] = max_t_;

  coordinates_[4] = 0;
  coordinates_[5] = 0;

  coordinates_[6] = max_s_;
  coordinates_[7] = 0;

  vertices_[0] = -size.width/2.0;
  vertices_[1] = -size.height/2.0;
  vertices_[2] = 0;

  vertices_[3] = size.width/2.0;
  vertices_[4] = -size.height/2.0;
  vertices_[5] = 0;

  vertices_[6] = -size.width/2.0;
  vertices_[7] = size.height/2.0;
  vertices_[8] = 0.0;

  vertices_[9] = size.width/2.0;
  vertices_[10] = size.height/2.0;
  vertices_[11] = 0.0;
}
<|endoftext|>


<commit_before>#include <QtNetwork>
#include <QtWidgets>

#define USER_AGENT  "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)" \
                    "Chrome/55.0.0.0 Safari/537.36 DobosTorta/dev-" GIT_VERSION

#define CONNECTION_NAME  "dobostorta-downloader.sock"

class TortaRequestHandler : public QLocalServer {
Q_OBJECT

private:
    TortaRequestHandler() {
        listen(CONNECTION_NAME);
        connect(this, &QLocalServer::newConnection, this, &TortaRequestHandler::newConnection);
    }

    void newConnection() {
        QLocalSocket *sock = nextPendingConnection();
        connect(sock, &QLocalSocket::disconnected, sock, &QLocalSocket::close);

        sock->waitForReadyRead();

        QDataStream stream(sock);
        QByteArray data;
        stream >> data;
        emit receivedRequest({data});
    }

public:
    ~TortaRequestHandler() {
        close();
    }

    static TortaRequestHandler *open() {
        auto server = new TortaRequestHandler();
        if (server->isListening())
            return server;

        delete server;
        return nullptr;
    }

    static bool request(const QUrl &url) {
        QLocalSocket sock;
        sock.connectToServer(CONNECTION_NAME);

        if (!sock.isValid()) {
            qCritical() << tr("Failed to open socket: ") << sock.errorString();
            return false;
        }

        QByteArray block;
        QDataStream stream(&block, QIODevice::WriteOnly);
        stream << url.toEncoded();
        sock.write(block);

        sock.waitForBytesWritten();

        return true;
    }

signals:
    void receivedRequest(const QUrl &url);
};

class TortaDownload : public QWidget {
Q_OBJECT

private:
    QNetworkReply * const reply;
    QVBoxLayout layout;
    QProgressBar progress;
    QPushButton button;
    QTimer intervalTimer;
    QElapsedTimer elapsedTimer;

    void saveTo(const QString &path) {
        QFile file(path);
        if (!file.open(QIODevice::WriteOnly)) {
            (new QErrorMessage(this))->showMessage(tr("Failed open %1: %2")
                                                   .arg(path).arg(file.errorString()));
            return;
        }

        file.write(reply->readAll());
        file.close();
    }

    static QString bytesToKMG(int bytes) {
        static const char* units[] = {"B", "KB", "MB", "GB", "TB", "PB", nullptr};
        for (int i=0; units[i+1] != nullptr; i++) {
            if (bytes < qPow(1024, i + 1)) {
                if (qPow(1024, i + 1) / 10 < bytes)
                    return QString("%1%2")
                             .arg(static_cast<float>(bytes) / qPow(1024, i + 1), 0, 'f', 1)
                             .arg(units[i + 1]);
                else if (bytes < qPow(1024, i + 1) / 100)
                    return QString("%1%2")
                             .arg(static_cast<float>(bytes) / qPow(1024, i), 0, 'f', 1)
                             .arg(units[i]);
                else
                    return QString("%1%2").arg(bytes / qPow(1024, i), 0, 'f', 0).arg(units[i]);
            }
        }
        return QString("%1PB").arg(bytes / qPow(1024, 5), 0, 'f', 0);
    }

    void setProgressBarColor(const QColor &color) {
        QPalette p;
        p.setColor(QPalette::Highlight, color);
        progress.setPalette(p);
    }

public:
    TortaDownload(QWidget *parent, QNetworkReply *reply, const QString &filePath)
            : QWidget(parent), reply(reply), layout(this), progress(this), button("cancel", this) {
        setLayout(&layout);

        auto horizontal = new QHBoxLayout;
        layout.addLayout(horizontal);

        auto left = new QVBoxLayout;
        horizontal->addLayout(left, 1);

        QFileInfo info(filePath);
        auto path = new QHBoxLayout;
        path->setAlignment(Qt::AlignLeft);
        path->setSpacing(0);
        left->addLayout(path);
        auto fpath = new QLabel(info.dir().path() + "/", this);
        path->addWidget(fpath);
        auto fname = new QLabel(info.fileName(), this);
        fname->setStyleSheet("font-weight: bold;");
        path->addWidget(fname);

        auto url = new QLabel(QString("%1").arg(reply->url().toString()),
                              this);
        url->setOpenExternalLinks(true);
        left->addWidget(url);

        horizontal->addWidget(&button);
        connect(&button, &QPushButton::clicked, [this, reply]{
            if (reply->isRunning())
                reply->abort();
            else
                emit clear();
        });

        progress.setFormat("%p% [%vB / %mB]");
        setProgressBarColor(Qt::darkGray);
        layout.addWidget(&progress);

        connect(reply, &QNetworkReply::downloadProgress, [this](qint64 received, qint64 total){
            updateProgressFormat();

            progress.setRange(0, total);
            progress.setValue(received);
        });
        connect(reply, &QNetworkReply::finished, [this, filePath, reply]{
            if (reply->error() && reply->error() != QNetworkReply::OperationCanceledError) {
                (new QErrorMessage(this))->showMessage(tr("Failed download: %1")
                                                       .arg(reply->errorString()));
            } else {
                saveTo(filePath);
            }
            button.setText("clear");

            intervalTimer.stop();
            if (!reply->error()) {
                progress.setFormat(QString("done [%1]").arg(bytesToKMG(progress.maximum())));
                setProgressBarColor(Qt::gray);
            } else {
                progress.setFormat(QString("%p% [%1] %2").arg(bytesToKMG(progress.maximum()))
                                                         .arg(reply->errorString()));
                setProgressBarColor(Qt::darkRed);
            }
        });
        intervalTimer.setSingleShot(false);
        connect(&intervalTimer, &QTimer::timeout, this, &TortaDownload::updateProgressFormat);
        intervalTimer.start(1000);
        elapsedTimer.start();
    }

signals:
    void clear();

private slots:
    void updateProgressFormat() {
        const int remain = qMax(
            0.0f,
            ((progress.maximum() * elapsedTimer.elapsed()) / static_cast<float>(progress.value())
            - elapsedTimer.elapsed()) / 1000
        );

        QString remainStr;
        if (remain < 60)
            remainStr = QString("%1 sec").arg(remain);
        else if (remain < 60 * 60)
            remainStr = QString("%1' %2\"").arg(remain/60).arg(remain % 60, 2, 'd', 0, '0');
        else
            remainStr = QString("%1:%2'").arg(remain/60/60).arg(remain/60 % 60, 2, 'd', 0, '0');

        progress.setFormat("%p% " + QString("[%1 / %2] %3").arg(bytesToKMG(progress.value()))
                                                           .arg(bytesToKMG(progress.maximum()))
                                                           .arg(remainStr));
    }
};

class TortaDL : public QScrollArea {
Q_OBJECT

private:
    QVBoxLayout layout;
    QNetworkAccessManager manager;
    TortaRequestHandler *handler;

protected:
    void closeEvent(QCloseEvent *e) {
        handler->close();
        QWidget::closeEvent(e);
    }

public:
    TortaDL(TortaRequestHandler *handler) : handler(handler) {
        setWindowTitle("Dobostorta downloader");

        layout.setAlignment(Qt::AlignTop);
        auto listArea = new QWidget(this);
        listArea->setLayout(&layout);
        setWidget(listArea);
        setWidgetResizable(true);

        connect(handler, &TortaRequestHandler::receivedRequest,
                [this](const QUrl &url){ startDownload(url); });
    }

    void startDownload(const QUrl &url, const QString &fname) {
        QNetworkRequest request(url);
        request.setRawHeader("User-Agent", USER_AGENT);

        auto dl = new TortaDownload(widget(), manager.get(request), fname);

        layout.addWidget(dl);

        connect(dl, &TortaDownload::clear, [this, dl]{
            layout.removeWidget(dl);
            delete dl;
        });
    }

    bool startDownload(const QUrl &url) {
        const QString filter(QMimeDatabase().mimeTypeForFile(url.fileName()).filterString());
        const QString path(QFileDialog::getSaveFileName(
            this,
            tr("Save file"),
            QFileInfo(QFileDialog().directory(), url.fileName()).absoluteFilePath(),
            filter + tr(";; All files (*)")
        ));
        if (path != "")
            startDownload(url, path);
        return path != "";
    }
};

int main(int argc, char **argv) {
    if (argc == 1) {
        qWarning("Dobostorta Downloader\n$ %s URL...", argv[0]);
        return -1;
    }

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication app(argc, argv);

    auto handler = TortaRequestHandler::open();
    if (handler == nullptr) {
        for (int i=1; i<argc; i++) {
            if (!TortaRequestHandler::request({argv[i]}))
                return -1;
        }

        return 0;
    }

    TortaDL win(handler);

    bool started = false;
    for (int i=1; i<argc; i++)
        started = started || win.startDownload({argv[i]});

    if (!started) {
        win.close();
        return 1;
    }

    win.show();

    return app.exec();
}

#include "main.moc"
<commit_msg>Enhanced error message box of torta-dl<commit_after>#include <QtNetwork>
#include <QtWidgets>

#define USER_AGENT  "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)" \
                    "Chrome/55.0.0.0 Safari/537.36 DobosTorta/dev-" GIT_VERSION

#define CONNECTION_NAME  "dobostorta-downloader.sock"

class TortaRequestHandler : public QLocalServer {
Q_OBJECT

private:
    TortaRequestHandler() {
        listen(CONNECTION_NAME);
        connect(this, &QLocalServer::newConnection, this, &TortaRequestHandler::newConnection);
    }

    void newConnection() {
        QLocalSocket *sock = nextPendingConnection();
        connect(sock, &QLocalSocket::disconnected, sock, &QLocalSocket::close);

        sock->waitForReadyRead();

        QDataStream stream(sock);
        QByteArray data;
        stream >> data;
        emit receivedRequest({data});
    }

public:
    ~TortaRequestHandler() {
        close();
    }

    static TortaRequestHandler *open() {
        auto server = new TortaRequestHandler();
        if (server->isListening())
            return server;

        delete server;
        return nullptr;
    }

    static bool request(const QUrl &url) {
        QLocalSocket sock;
        sock.connectToServer(CONNECTION_NAME);

        if (!sock.isValid()) {
            qCritical() << tr("Failed to open socket: ") << sock.errorString();
            return false;
        }

        QByteArray block;
        QDataStream stream(&block, QIODevice::WriteOnly);
        stream << url.toEncoded();
        sock.write(block);

        sock.waitForBytesWritten();

        return true;
    }

signals:
    void receivedRequest(const QUrl &url);
};

class TortaDownload : public QWidget {
Q_OBJECT

private:
    QNetworkReply * const reply;
    QVBoxLayout layout;
    QProgressBar progress;
    QPushButton button;
    QTimer intervalTimer;
    QElapsedTimer elapsedTimer;

    void saveTo(const QString &path) {
        QFile file(path);
        if (!file.open(QIODevice::WriteOnly)) {
            QMessageBox message(QMessageBox::Critical,
                                reply->url().toString(),
                                tr("Failed create %1\n%2").arg(path, file.errorString()),
                                QMessageBox::Retry | QMessageBox::Abort,
                                this);
            if (message.exec() == QMessageBox::Retry)
                saveTo(path);
            return;
        }

        file.write(reply->readAll());
        file.close();
    }

    static QString bytesToKMG(int bytes) {
        static const char* units[] = {"B", "KB", "MB", "GB", "TB", "PB", nullptr};
        for (int i=0; units[i+1] != nullptr; i++) {
            if (bytes < qPow(1024, i + 1)) {
                if (qPow(1024, i + 1) / 10 < bytes)
                    return QString("%1%2")
                             .arg(static_cast<float>(bytes) / qPow(1024, i + 1), 0, 'f', 1)
                             .arg(units[i + 1]);
                else if (bytes < qPow(1024, i + 1) / 100)
                    return QString("%1%2")
                             .arg(static_cast<float>(bytes) / qPow(1024, i), 0, 'f', 1)
                             .arg(units[i]);
                else
                    return QString("%1%2").arg(bytes / qPow(1024, i), 0, 'f', 0).arg(units[i]);
            }
        }
        return QString("%1PB").arg(bytes / qPow(1024, 5), 0, 'f', 0);
    }

    void setProgressBarColor(const QColor &color) {
        QPalette p;
        p.setColor(QPalette::Highlight, color);
        progress.setPalette(p);
    }

public:
    TortaDownload(QWidget *parent, QNetworkReply *reply, const QString &filePath)
            : QWidget(parent), reply(reply), layout(this), progress(this), button("cancel", this) {
        setLayout(&layout);

        auto horizontal = new QHBoxLayout;
        layout.addLayout(horizontal);

        auto left = new QVBoxLayout;
        horizontal->addLayout(left, 1);

        QFileInfo info(filePath);
        auto path = new QHBoxLayout;
        path->setAlignment(Qt::AlignLeft);
        path->setSpacing(0);
        left->addLayout(path);
        auto fpath = new QLabel(info.dir().path() + "/", this);
        path->addWidget(fpath);
        auto fname = new QLabel(info.fileName(), this);
        fname->setStyleSheet("font-weight: bold;");
        path->addWidget(fname);

        auto url = new QLabel(QString("%1").arg(reply->url().toString()),
                              this);
        url->setOpenExternalLinks(true);
        left->addWidget(url);

        horizontal->addWidget(&button);
        connect(&button, &QPushButton::clicked, [this, reply]{
            if (reply->isRunning())
                reply->abort();
            else
                emit clear();
        });

        progress.setFormat("%p% [%vB / %mB]");
        setProgressBarColor(Qt::darkGray);
        layout.addWidget(&progress);

        connect(reply, &QNetworkReply::downloadProgress, [this](qint64 received, qint64 total){
            updateProgressFormat();

            progress.setRange(0, total);
            progress.setValue(received);
        });
        connect(reply, &QNetworkReply::finished, [this, filePath, reply]{
            if (reply->error() && reply->error() != QNetworkReply::OperationCanceledError) {
                QMessageBox message(QMessageBox::Critical,
                                    reply->url().toString(),
                                    tr("Failed download\n%1").arg(reply->errorString()),
                                    QMessageBox::Retry | QMessageBox::Abort,
                                    this);
                if (message.exec() == QMessageBox::Retry)
                    emit retry();
            } else {
                saveTo(filePath);
            }
            button.setText("clear");

            intervalTimer.stop();
            if (!reply->error()) {
                progress.setFormat(QString("done [%1]").arg(bytesToKMG(progress.maximum())));
                setProgressBarColor(Qt::gray);
            } else {
                progress.setFormat(QString("%p% [%1] %2").arg(bytesToKMG(progress.maximum()))
                                                         .arg(reply->errorString()));
                setProgressBarColor(Qt::darkRed);
            }
        });
        intervalTimer.setSingleShot(false);
        connect(&intervalTimer, &QTimer::timeout, this, &TortaDownload::updateProgressFormat);
        intervalTimer.start(1000);
        elapsedTimer.start();
    }

signals:
    void clear();
    void retry();

private slots:
    void updateProgressFormat() {
        const int remain = qMax(
            0.0f,
            ((progress.maximum() * elapsedTimer.elapsed()) / static_cast<float>(progress.value())
            - elapsedTimer.elapsed()) / 1000
        );

        QString remainStr;
        if (remain < 60)
            remainStr = QString("%1 sec").arg(remain);
        else if (remain < 60 * 60)
            remainStr = QString("%1' %2\"").arg(remain/60).arg(remain % 60, 2, 'd', 0, '0');
        else
            remainStr = QString("%1:%2'").arg(remain/60/60).arg(remain/60 % 60, 2, 'd', 0, '0');

        progress.setFormat("%p% " + QString("[%1 / %2] %3").arg(bytesToKMG(progress.value()))
                                                           .arg(bytesToKMG(progress.maximum()))
                                                           .arg(remainStr));
    }
};

class TortaDL : public QScrollArea {
Q_OBJECT

private:
    QVBoxLayout layout;
    QNetworkAccessManager manager;
    TortaRequestHandler *handler;

protected:
    void closeEvent(QCloseEvent *e) {
        handler->close();
        QWidget::closeEvent(e);
    }

public:
    TortaDL(TortaRequestHandler *handler) : handler(handler) {
        setWindowTitle("Dobostorta downloader");

        layout.setAlignment(Qt::AlignTop);
        auto listArea = new QWidget(this);
        listArea->setLayout(&layout);
        setWidget(listArea);
        setWidgetResizable(true);

        connect(handler, &TortaRequestHandler::receivedRequest,
                [this](const QUrl &url){ startDownload(url); });
    }

    void startDownload(const QUrl &url, const QString &fname) {
        QNetworkRequest request(url);
        request.setRawHeader("User-Agent", USER_AGENT);

        auto dl = new TortaDownload(widget(), manager.get(request), fname);

        layout.addWidget(dl);

        connect(dl, &TortaDownload::retry, [this, url, fname]{ startDownload(url, fname); });
        connect(dl, &TortaDownload::clear, [this, dl]{
            layout.removeWidget(dl);
            delete dl;
        });
    }

    bool startDownload(const QUrl &url) {
        const QString filter(QMimeDatabase().mimeTypeForFile(url.fileName()).filterString());
        const QString path(QFileDialog::getSaveFileName(
            this,
            tr("Save file"),
            QFileInfo(QFileDialog().directory(), url.fileName()).absoluteFilePath(),
            filter + tr(";; All files (*)")
        ));
        if (path != "")
            startDownload(url, path);
        return path != "";
    }
};

int main(int argc, char **argv) {
    if (argc == 1) {
        qWarning("Dobostorta Downloader\n$ %s URL...", argv[0]);
        return -1;
    }

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication app(argc, argv);

    auto handler = TortaRequestHandler::open();
    if (handler == nullptr) {
        for (int i=1; i<argc; i++) {
            if (!TortaRequestHandler::request({argv[i]}))
                return -1;
        }

        return 0;
    }

    TortaDL win(handler);

    bool started = false;
    for (int i=1; i<argc; i++)
        started = started || win.startDownload({argv[i]});

    if (!started) {
        win.close();
        return 1;
    }

    win.show();

    return app.exec();
}

#include "main.moc"
<|endoftext|>


<commit_before>// RubDivSolver.cpp

#include "RubDivSolver.h"
#include "RubDivPuzzle.h"

RubDivSolver::RubDivSolver( void )
{
	puzzleClone = 0;
}

RubDivSolver::~RubDivSolver( void )
{
}

bool RubDivSolver::Solve( const RubDivPuzzle* puzzle, RubDivPuzzle::MoveList& moveList )
{
	wxASSERT( puzzleClone == 0 );

	// We only deal with the vertical case, which is really no different than the horizontal case.
	if( puzzle->GetOrientation() != RubDivPuzzle::VERTICAL )
		return false;

	moveList.clear();
	puzzleClone = puzzle->Clone();
	while( !puzzleClone->IsSolved() )
	{
		RubDivPuzzle::MoveList algorithm;
		if( FindAlgorithm( algorithm ) )
		{
			bool manipulated = puzzleClone->ManipulatePuzzle( algorithm );
			wxASSERT( manipulated );
			ConcatinateMoveList( moveList, algorithm );
		}
		else
		{
			RubDivPuzzle::Move rotateMove;
			rotateMove.squareOffset = 2;
			rotateMove.rotateCCWCount = 1;
			rotateMove.rowOrColumn = -1;
			rotateMove.shiftDir = RubDivPuzzle::SHIFT_NONE;

			bool manipulated = puzzleClone->ManipulatePuzzle( rotateMove );
			wxASSERT( manipulated );
			moveList.push_back( rotateMove );
		}
	}

	delete puzzleClone;
	puzzleClone = 0;

	CompressMoveList( moveList );

	return true;
}

void RubDivSolver::ConcatinateMoveList( RubDivPuzzle::MoveList& moveListDest, const RubDivPuzzle::MoveList& moveListSource )
{
	RubDivPuzzle::MoveList::const_iterator iter = moveListSource.begin();
	while( iter != moveListSource.end() )
	{
		const RubDivPuzzle::Move& move = *iter;
		moveListDest.push_back( move );
		iter++;
	}
}

bool RubDivSolver::FindAlgorithm( RubDivPuzzle::MoveList& algorithm )
{
	int size = puzzleClone->GetSize();

	for( int i = 0; i < size; i++ )
	{
		RubDivPuzzle::MoveList algorithmCCW, algorithmCW;

		RubDivPuzzle::Move rotationMove;
		rotationMove.squareOffset = 1;
		rotationMove.rowOrColumn = -1;
		rotationMove.shiftDir = RubDivPuzzle::SHIFT_NONE;

		rotationMove.rotateCCWCount = 1;
		bool foundCCW = FindAlgorithmForRow( i, rotationMove, algorithmCCW );

		rotationMove.rotateCCWCount = 3;
		bool foundCW = FindAlgorithmForRow( i, rotationMove, algorithmCW );

		if( foundCCW && foundCW )
		{
			if( algorithmCCW.size() > algorithmCW.size() )
				ConcatinateMoveList( algorithm, algorithmCCW );
			else
				ConcatinateMoveList( algorithm, algorithmCW );
		}
		else if( foundCCW )
			ConcatinateMoveList( algorithm, algorithmCCW );
		else if( foundCW )
			ConcatinateMoveList( algorithm, algorithmCW );

		if( algorithm.size() > 0 )
			return true;
	}

	return false;
}

// Notice that for puzzles with an odd size, the centers cannot move.
// So to avoid this special case, we always restore color A to the top
// square, and color B to the bottom square.
bool RubDivSolver::FindAlgorithmForRow( int row, const RubDivPuzzle::Move& rotationMove, RubDivPuzzle::MoveList& algorithm )
{
	int size = puzzleClone->GetSize();

	int preservationColumn;
	if( rotationMove.rotateCCWCount == 1 )
		preservationColumn = row;
	else if( rotationMove.rotateCCWCount == 3 )
		preservationColumn = size - 1 - row;
	else
		return false;

	RubDivPuzzle::MoveList shiftMoveList;
	RubDivPuzzle::MoveList inverseShiftMoveList;

	for( int j = 0; j < size; j++ )
	{
		if( j == preservationColumn )
			continue;

		if( puzzleClone->GetColor( 1, row, j ) == RubDivPuzzle::Element::COLOR_B && puzzleClone->GetColor( 2, row, j ) == RubDivPuzzle::Element::COLOR_A )
		{
			RubDivPuzzle::Move shiftMove;
			shiftMove.squareOffset = -1;
			shiftMove.rotateCCWCount = 0;
			shiftMove.rowOrColumn = j;
			shiftMove.shiftDir = RubDivPuzzle::SHIFT_BACKWARD;
			shiftMoveList.push_back( shiftMove );

			RubDivPuzzle::Move inverseShiftMove;
			shiftMove.Invert( inverseShiftMove );
			inverseShiftMoveList.push_back( inverseShiftMove );
		}
	}

	if( shiftMoveList.size() == 0 )
		return false;

	ConcatinateMoveList( algorithm, shiftMoveList );

	algorithm.push_back( rotationMove );

	RubDivPuzzle::Move preservationShiftMove;
	preservationShiftMove.squareOffset = -1;
	preservationShiftMove.rotateCCWCount = 0;
	preservationShiftMove.rowOrColumn = preservationColumn;
	preservationShiftMove.shiftDir = RubDivPuzzle::SHIFT_BACKWARD;
	algorithm.push_back( preservationShiftMove );

	RubDivPuzzle::Move inverseRotationMove;
	rotationMove.Invert( inverseRotationMove );
	algorithm.push_back( inverseRotationMove );

	ConcatinateMoveList( algorithm, inverseShiftMoveList );

	algorithm.push_back( rotationMove );

	RubDivPuzzle::Move inversePreservationShiftMove;
	preservationShiftMove.Invert( inversePreservationShiftMove );
	algorithm.push_back( inversePreservationShiftMove );

	algorithm.push_back( inverseRotationMove );

	return true;
}

void RubDivSolver::CompressMoveList( RubDivPuzzle::MoveList& moveList )
{
	//...
}

// RubDivSolver.cpp<commit_msg>interesting comment<commit_after>// RubDivSolver.cpp

#include "RubDivSolver.h"
#include "RubDivPuzzle.h"

RubDivSolver::RubDivSolver( void )
{
	puzzleClone = 0;
}

RubDivSolver::~RubDivSolver( void )
{
}

bool RubDivSolver::Solve( const RubDivPuzzle* puzzle, RubDivPuzzle::MoveList& moveList )
{
	wxASSERT( puzzleClone == 0 );

	// We only deal with the vertical case, which is really no different than the horizontal case.
	if( puzzle->GetOrientation() != RubDivPuzzle::VERTICAL )
		return false;

	moveList.clear();
	puzzleClone = puzzle->Clone();
	while( !puzzleClone->IsSolved() )
	{
		RubDivPuzzle::MoveList algorithm;
		if( FindAlgorithm( algorithm ) )
		{
			bool manipulated = puzzleClone->ManipulatePuzzle( algorithm );
			wxASSERT( manipulated );
			ConcatinateMoveList( moveList, algorithm );
		}
		else
		{
			RubDivPuzzle::Move rotateMove;
			rotateMove.squareOffset = 2;
			rotateMove.rotateCCWCount = 1;
			rotateMove.rowOrColumn = -1;
			rotateMove.shiftDir = RubDivPuzzle::SHIFT_NONE;

			bool manipulated = puzzleClone->ManipulatePuzzle( rotateMove );
			wxASSERT( manipulated );
			moveList.push_back( rotateMove );
		}
	}

	delete puzzleClone;
	puzzleClone = 0;

	CompressMoveList( moveList );

	return true;
}

void RubDivSolver::ConcatinateMoveList( RubDivPuzzle::MoveList& moveListDest, const RubDivPuzzle::MoveList& moveListSource )
{
	RubDivPuzzle::MoveList::const_iterator iter = moveListSource.begin();
	while( iter != moveListSource.end() )
	{
		const RubDivPuzzle::Move& move = *iter;
		moveListDest.push_back( move );
		iter++;
	}
}

// Note that this could generalize even further by solving multiple rows at the same time and using multiple preservation columns.
// As long as there's no collision between the columns we solve in the rows and the preservation columns, it works out.
bool RubDivSolver::FindAlgorithm( RubDivPuzzle::MoveList& algorithm )
{
	int size = puzzleClone->GetSize();

	for( int i = 0; i < size; i++ )
	{
		RubDivPuzzle::MoveList algorithmCCW, algorithmCW;

		RubDivPuzzle::Move rotationMove;
		rotationMove.squareOffset = 1;
		rotationMove.rowOrColumn = -1;
		rotationMove.shiftDir = RubDivPuzzle::SHIFT_NONE;

		rotationMove.rotateCCWCount = 1;
		bool foundCCW = FindAlgorithmForRow( i, rotationMove, algorithmCCW );

		rotationMove.rotateCCWCount = 3;
		bool foundCW = FindAlgorithmForRow( i, rotationMove, algorithmCW );

		if( foundCCW && foundCW )
		{
			if( algorithmCCW.size() > algorithmCW.size() )
				ConcatinateMoveList( algorithm, algorithmCCW );
			else
				ConcatinateMoveList( algorithm, algorithmCW );
		}
		else if( foundCCW )
			ConcatinateMoveList( algorithm, algorithmCCW );
		else if( foundCW )
			ConcatinateMoveList( algorithm, algorithmCW );

		if( algorithm.size() > 0 )
			return true;
	}

	return false;
}

// Notice that for puzzles with an odd size, the centers cannot move.
// So to avoid this special case, we always restore color A to the top
// square, and color B to the bottom square.
bool RubDivSolver::FindAlgorithmForRow( int row, const RubDivPuzzle::Move& rotationMove, RubDivPuzzle::MoveList& algorithm )
{
	int size = puzzleClone->GetSize();

	int preservationColumn;
	if( rotationMove.rotateCCWCount == 1 )
		preservationColumn = row;
	else if( rotationMove.rotateCCWCount == 3 )
		preservationColumn = size - 1 - row;
	else
		return false;

	RubDivPuzzle::MoveList shiftMoveList;
	RubDivPuzzle::MoveList inverseShiftMoveList;

	for( int j = 0; j < size; j++ )
	{
		if( j == preservationColumn )
			continue;

		if( puzzleClone->GetColor( 1, row, j ) == RubDivPuzzle::Element::COLOR_B && puzzleClone->GetColor( 2, row, j ) == RubDivPuzzle::Element::COLOR_A )
		{
			RubDivPuzzle::Move shiftMove;
			shiftMove.squareOffset = -1;
			shiftMove.rotateCCWCount = 0;
			shiftMove.rowOrColumn = j;
			shiftMove.shiftDir = RubDivPuzzle::SHIFT_BACKWARD;
			shiftMoveList.push_back( shiftMove );

			RubDivPuzzle::Move inverseShiftMove;
			shiftMove.Invert( inverseShiftMove );
			inverseShiftMoveList.push_back( inverseShiftMove );
		}
	}

	if( shiftMoveList.size() == 0 )
		return false;

	ConcatinateMoveList( algorithm, shiftMoveList );

	algorithm.push_back( rotationMove );

	RubDivPuzzle::Move preservationShiftMove;
	preservationShiftMove.squareOffset = -1;
	preservationShiftMove.rotateCCWCount = 0;
	preservationShiftMove.rowOrColumn = preservationColumn;
	preservationShiftMove.shiftDir = RubDivPuzzle::SHIFT_BACKWARD;
	algorithm.push_back( preservationShiftMove );

	RubDivPuzzle::Move inverseRotationMove;
	rotationMove.Invert( inverseRotationMove );
	algorithm.push_back( inverseRotationMove );

	ConcatinateMoveList( algorithm, inverseShiftMoveList );

	algorithm.push_back( rotationMove );

	RubDivPuzzle::Move inversePreservationShiftMove;
	preservationShiftMove.Invert( inversePreservationShiftMove );
	algorithm.push_back( inversePreservationShiftMove );

	algorithm.push_back( inverseRotationMove );

	return true;
}

void RubDivSolver::CompressMoveList( RubDivPuzzle::MoveList& moveList )
{
	//...
}

// RubDivSolver.cpp<|endoftext|>