<commit_before>#include <array>
#include <vector>
#include <fstream>

#include "png/png.h"
#include "png/zlib.h"

#include "ArcV/Processing/Image.hpp"

namespace Arcv {

namespace {

bool validatePng(std::istream& file) {
  std::array<png_byte, PNG_HEADER_SIZE> header;

  file.read(reinterpret_cast<char*>(header.data()), PNG_HEADER_SIZE);

  return (png_sig_cmp(header.data(), 0, PNG_HEADER_SIZE) == 0);
}

void readPng(png_structp pngReadPtr, png_bytep data, png_size_t length) {
  png_voidp inPtr = png_get_io_ptr(pngReadPtr);
  static_cast<std::istream*>(inPtr)->read(reinterpret_cast<char*>(data), length);
}

void writePng(png_structp pngWritePtr, png_bytep data, png_size_t length) {
  png_voidp outPtr = png_get_io_ptr(pngWritePtr);
  static_cast<std::ostream*>(outPtr)->write(reinterpret_cast<const char*>(data), length);
}

} // namespace

Matrix<> Image::read(const std::string& fileName) {
  std::ifstream file(fileName, std::ios_base::in | std::ios_base::binary);
  assert(("Error: Not a valid PNG", file.good() && validatePng(file)));

  png_structp pngReadStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
  assert(("Error: Couldn't initialize PNG read struct", pngReadStruct));

  png_infop pngInfoStruct = png_create_info_struct(pngReadStruct);
  assert(("Error: Couldn't initialize PNG info struct", pngInfoStruct));

  png_set_read_fn(pngReadStruct, &file, readPng);

  // Setting the amount signature bytes we've already read
  png_set_sig_bytes(pngReadStruct, PNG_HEADER_SIZE);

  png_read_info(pngReadStruct, pngInfoStruct);

  uint32_t width = static_cast<uint32_t>(png_get_image_width(pngReadStruct, pngInfoStruct));
  uint32_t height = static_cast<uint32_t>(png_get_image_height(pngReadStruct, pngInfoStruct));
  uint32_t bitDepth = png_get_bit_depth(pngReadStruct, pngInfoStruct);
  uint8_t channels = png_get_channels(pngReadStruct, pngInfoStruct);
  uint8_t colorType = png_get_color_type(pngReadStruct, pngInfoStruct);
  Colorspace colorspace;

  switch (colorType) {
    case PNG_COLOR_TYPE_GRAY:
      if (bitDepth < 8)
        png_set_expand_gray_1_2_4_to_8(pngReadStruct);
      colorspace = ARCV_COLORSPACE_GRAY;
      bitDepth = 8;
      break;

    case PNG_COLOR_TYPE_GRAY_ALPHA:
      colorspace = ARCV_COLORSPACE_GRAY_ALPHA;
      break;

    case PNG_COLOR_TYPE_PALETTE:
      png_set_palette_to_rgb(pngReadStruct);
      colorspace = ARCV_COLORSPACE_RGB;
      channels = 3;
      break;

    case PNG_COLOR_TYPE_RGB:
    default:
      colorspace = ARCV_COLORSPACE_RGB;
      break;

    case PNG_COLOR_TYPE_RGB_ALPHA:
      colorspace = ARCV_COLORSPACE_RGBA;
      break;
  }

  png_set_scale_16(pngReadStruct);

  // Adding full alpha channel to the image if it possesses transparency
  if (png_get_valid(pngReadStruct, pngInfoStruct, PNG_INFO_tRNS)) {
    png_set_tRNS_to_alpha(pngReadStruct);
    channels += 1;
  }

  png_read_update_info(pngReadStruct, pngInfoStruct);

  Matrix<uint8_t> mat(width, height, channels, static_cast<uint8_t>(bitDepth), colorspace);

  std::vector<png_bytep> rowPtrs(height);

  // Defining an array to contain image's pixels
  mat.getData().resize(width * height * channels);

  // Mapping row's elements to data's
  for (uint32_t i = 0; i < height; ++i) {
    rowPtrs[i] = &mat.getData()[width * channels * i];
  }

  png_read_image(pngReadStruct, rowPtrs.data());
  png_read_end(pngReadStruct, pngInfoStruct);
  png_destroy_read_struct(&pngReadStruct, 0, static_cast<const png_infopp>(0));

  return Matrix<>(mat);
}

void Image::write(const Matrix<>& mat, const std::string& fileName) {
  std::ofstream file(fileName);
  const Matrix<uint8_t> matToWrite(mat);

  png_structp pngWriteStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
  assert(("Error: Couldn't initialize PNG write struct", pngWriteStruct));

  png_infop pngInfoStruct = png_create_info_struct(pngWriteStruct);
  assert(("Error: Couldn't initialize PNG info struct", pngInfoStruct));

  uint32_t colorType;
  unsigned short channels = 0;
  switch (matToWrite.getColorspace()) {
    case ARCV_COLORSPACE_GRAY:
      colorType = PNG_COLOR_TYPE_GRAY;
      channels = 1;
      break;

    case ARCV_COLORSPACE_GRAY_ALPHA:
      colorType = PNG_COLOR_TYPE_GRAY_ALPHA;
      channels = 2;
      break;

    case ARCV_COLORSPACE_RGB:
    case ARCV_COLORSPACE_HSV:
    default:
      colorType = PNG_COLOR_TYPE_RGB;
      channels = 3;
      break;

    case ARCV_COLORSPACE_RGBA:
      colorType = PNG_COLOR_TYPE_RGBA;
      channels = 4;
      break;
  }

  png_set_compression_level(pngWriteStruct, 6);

  if (channels * matToWrite.getImgBitDepth() >= 16) {
    png_set_compression_strategy(pngWriteStruct, Z_FILTERED);
    png_set_filter(pngWriteStruct, 0, PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_PAETH);
  } else {
    png_set_compression_strategy(pngWriteStruct, Z_DEFAULT_STRATEGY);
  }

  png_set_IHDR(pngWriteStruct,
               pngInfoStruct,
               matToWrite.getWidth(),
               matToWrite.getHeight(),
               matToWrite.getImgBitDepth(),
               colorType,
               PNG_INTERLACE_NONE,
               PNG_COMPRESSION_TYPE_BASE,
               PNG_FILTER_TYPE_BASE);

  png_set_write_fn(pngWriteStruct, &file, writePng, nullptr);
  png_write_info(pngWriteStruct, pngInfoStruct);

  for (uint32_t i = 0; i < matToWrite.getHeight(); ++i) {
    png_write_row(pngWriteStruct,
                  &matToWrite.getData()[matToWrite.getWidth() * channels * i]);
  }

  png_write_end(pngWriteStruct, pngInfoStruct);
  png_destroy_write_struct(&pngWriteStruct, &pngInfoStruct);
}

} // namespace Arcv
<commit_msg>[Update] Removed useless stuff in PNG's saving function<commit_after>#include <array>
#include <vector>
#include <fstream>

#include "png/png.h"
#include "png/zlib.h"

#include "ArcV/Processing/Image.hpp"

namespace Arcv {

namespace {

bool validatePng(std::istream& file) {
  std::array<png_byte, PNG_HEADER_SIZE> header;

  file.read(reinterpret_cast<char*>(header.data()), PNG_HEADER_SIZE);

  return (png_sig_cmp(header.data(), 0, PNG_HEADER_SIZE) == 0);
}

void readPng(png_structp pngReadPtr, png_bytep data, png_size_t length) {
  png_voidp inPtr = png_get_io_ptr(pngReadPtr);
  static_cast<std::istream*>(inPtr)->read(reinterpret_cast<char*>(data), length);
}

void writePng(png_structp pngWritePtr, png_bytep data, png_size_t length) {
  png_voidp outPtr = png_get_io_ptr(pngWritePtr);
  static_cast<std::ostream*>(outPtr)->write(reinterpret_cast<const char*>(data), length);
}

} // namespace

Matrix<> Image::read(const std::string& fileName) {
  std::ifstream file(fileName, std::ios_base::in | std::ios_base::binary);
  assert(("Error: Not a valid PNG", file.good() && validatePng(file)));

  png_structp pngReadStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
  assert(("Error: Couldn't initialize PNG read struct", pngReadStruct));

  png_infop pngInfoStruct = png_create_info_struct(pngReadStruct);
  assert(("Error: Couldn't initialize PNG info struct", pngInfoStruct));

  png_set_read_fn(pngReadStruct, &file, readPng);

  // Setting the amount signature bytes we've already read
  png_set_sig_bytes(pngReadStruct, PNG_HEADER_SIZE);

  png_read_info(pngReadStruct, pngInfoStruct);

  uint32_t width = static_cast<uint32_t>(png_get_image_width(pngReadStruct, pngInfoStruct));
  uint32_t height = static_cast<uint32_t>(png_get_image_height(pngReadStruct, pngInfoStruct));
  uint32_t bitDepth = png_get_bit_depth(pngReadStruct, pngInfoStruct);
  uint8_t channels = png_get_channels(pngReadStruct, pngInfoStruct);
  uint8_t colorType = png_get_color_type(pngReadStruct, pngInfoStruct);
  Colorspace colorspace;

  switch (colorType) {
    case PNG_COLOR_TYPE_GRAY:
      if (bitDepth < 8)
        png_set_expand_gray_1_2_4_to_8(pngReadStruct);
      colorspace = ARCV_COLORSPACE_GRAY;
      bitDepth = 8;
      break;

    case PNG_COLOR_TYPE_GRAY_ALPHA:
      colorspace = ARCV_COLORSPACE_GRAY_ALPHA;
      break;

    case PNG_COLOR_TYPE_PALETTE:
      png_set_palette_to_rgb(pngReadStruct);
      colorspace = ARCV_COLORSPACE_RGB;
      channels = 3;
      break;

    case PNG_COLOR_TYPE_RGB:
    default:
      colorspace = ARCV_COLORSPACE_RGB;
      break;

    case PNG_COLOR_TYPE_RGB_ALPHA:
      colorspace = ARCV_COLORSPACE_RGBA;
      break;
  }

  png_set_scale_16(pngReadStruct);

  // Adding full alpha channel to the image if it possesses transparency
  if (png_get_valid(pngReadStruct, pngInfoStruct, PNG_INFO_tRNS)) {
    png_set_tRNS_to_alpha(pngReadStruct);
    channels += 1;
  }

  png_read_update_info(pngReadStruct, pngInfoStruct);

  Matrix<uint8_t> mat(width, height, channels, static_cast<uint8_t>(bitDepth), colorspace);

  std::vector<png_bytep> rowPtrs(height);

  // Defining an array to contain image's pixels
  mat.getData().resize(width * height * channels);

  // Mapping row's elements to data's
  for (uint32_t i = 0; i < height; ++i) {
    rowPtrs[i] = &mat.getData()[width * channels * i];
  }

  png_read_image(pngReadStruct, rowPtrs.data());
  png_read_end(pngReadStruct, pngInfoStruct);
  png_destroy_read_struct(&pngReadStruct, 0, static_cast<const png_infopp>(0));

  return Matrix<>(mat);
}

void Image::write(const Matrix<>& mat, const std::string& fileName) {
  std::ofstream file(fileName);
  const Matrix<uint8_t> matToWrite(mat);

  png_structp pngWriteStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
  assert(("Error: Couldn't initialize PNG write struct", pngWriteStruct));

  png_infop pngInfoStruct = png_create_info_struct(pngWriteStruct);
  assert(("Error: Couldn't initialize PNG info struct", pngInfoStruct));

  uint32_t colorType;
  switch (matToWrite.getColorspace()) {
    case ARCV_COLORSPACE_GRAY:
      colorType = PNG_COLOR_TYPE_GRAY;
      break;

    case ARCV_COLORSPACE_GRAY_ALPHA:
      colorType = PNG_COLOR_TYPE_GRAY_ALPHA;
      break;

    case ARCV_COLORSPACE_RGB:
    case ARCV_COLORSPACE_HSV:
    default:
      colorType = PNG_COLOR_TYPE_RGB;
      break;

    case ARCV_COLORSPACE_RGBA:
      colorType = PNG_COLOR_TYPE_RGBA;
      break;
  }

  png_set_compression_level(pngWriteStruct, 6);

  if (matToWrite.getChannelCount() * matToWrite.getImgBitDepth() >= 16) {
    png_set_compression_strategy(pngWriteStruct, Z_FILTERED);
    png_set_filter(pngWriteStruct, 0, PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_PAETH);
  } else {
    png_set_compression_strategy(pngWriteStruct, Z_DEFAULT_STRATEGY);
  }

  png_set_IHDR(pngWriteStruct,
               pngInfoStruct,
               matToWrite.getWidth(),
               matToWrite.getHeight(),
               matToWrite.getImgBitDepth(),
               colorType,
               PNG_INTERLACE_NONE,
               PNG_COMPRESSION_TYPE_BASE,
               PNG_FILTER_TYPE_BASE);

  png_set_write_fn(pngWriteStruct, &file, writePng, nullptr);
  png_write_info(pngWriteStruct, pngInfoStruct);

  for (uint32_t i = 0; i < matToWrite.getHeight(); ++i) {
    png_write_row(pngWriteStruct, &matToWrite.getData()[matToWrite.getWidth() * matToWrite.getChannelCount() * i]);
  }

  png_write_end(pngWriteStruct, pngInfoStruct);
  png_destroy_write_struct(&pngWriteStruct, &pngInfoStruct);
}

} // namespace Arcv
<|endoftext|>


<commit_before>#include "hornet/java.hh"

#include "hornet/vm.hh"

#include <classfile_constants.h>
#include <cassert>
#include <stack>

namespace hornet {

static inline uint16_t read_opc_u2(char *p)
{
    return p[1] << 8 | p[2];
}

void interp(method* method)
{
    std::valarray<object*> locals(method->max_locals);

    std::stack<object*> ostack;

    uint16_t pc = 0;

next_insn:
    assert(pc < method->code_length);

    uint8_t opc = method->code[pc];

    switch (opc) {
    case JVM_OPC_aload_0:
    case JVM_OPC_aload_1:
    case JVM_OPC_aload_2:
    case JVM_OPC_aload_3: {
        uint16_t idx = opc - JVM_OPC_aload_0;
        ostack.push(locals[idx]);
        break;
    }
    case JVM_OPC_pop: {
        ostack.pop();
        break;
    }
    case JVM_OPC_dup: {
        auto value = ostack.top();
        ostack.push(value);
        break;
    }
    case JVM_OPC_goto: {
        int16_t offset = read_opc_u2(method->code + pc);
        pc += offset;
        goto next_insn;
    }
    case JVM_OPC_return: {
        ostack.empty();
        return;
    }
    case JVM_OPC_invokespecial: {
        break;
    }
    case JVM_OPC_new: {
        auto obj = gc_new_object(nullptr);
        ostack.push(obj);
        break;
    }
    default:
        fprintf(stderr, "error: unsupported bytecode: %u\n", opc);
        abort();
    }

    pc += opcode_length[opc];

    goto next_insn;
}

}
<commit_msg>interp: Switch to value type<commit_after>#include "hornet/java.hh"

#include "hornet/vm.hh"

#include <classfile_constants.h>
#include <cassert>
#include <stack>

namespace hornet {

static inline uint16_t read_opc_u2(char *p)
{
    return p[1] << 8 | p[2];
}

typedef uint64_t value_t;

value_t object_to_value(object* obj)
{
    return reinterpret_cast<value_t>(obj);
}

value_t int32_to_value(int32_t n)
{
    return static_cast<value_t>(n);
}

void interp(method* method)
{
    std::valarray<value_t> locals(method->max_locals);

    std::stack<value_t> ostack;

    uint16_t pc = 0;

next_insn:
    assert(pc < method->code_length);

    uint8_t opc = method->code[pc];

    switch (opc) {
    case JVM_OPC_aload_0:
    case JVM_OPC_aload_1:
    case JVM_OPC_aload_2:
    case JVM_OPC_aload_3: {
        uint16_t idx = opc - JVM_OPC_aload_0;
        ostack.push(locals[idx]);
        break;
    }
    case JVM_OPC_pop: {
        ostack.pop();
        break;
    }
    case JVM_OPC_dup: {
        auto value = ostack.top();
        ostack.push(value);
        break;
    }
    case JVM_OPC_goto: {
        int16_t offset = read_opc_u2(method->code + pc);
        pc += offset;
        goto next_insn;
    }
    case JVM_OPC_return: {
        ostack.empty();
        return;
    }
    case JVM_OPC_invokespecial: {
        break;
    }
    case JVM_OPC_new: {
        auto obj = gc_new_object(nullptr);
        ostack.push(object_to_value(obj));
        break;
    }
    default:
        fprintf(stderr, "error: unsupported bytecode: %u\n", opc);
        abort();
    }

    pc += opcode_length[opc];

    goto next_insn;
}

}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <vector>
#include <tuple>

#include "acmacs-base/argv.hh"
#include "acmacs-base/filesystem.hh"
#include "acmacs-base/named-type.hh"
#include "acmacs-base/string.hh"
#include "acmacs-base/string-split.hh"
#include "acmacs-base/read-file.hh"
#include "acmacs-chart-2/factory-import.hh"
#include "acmacs-chart-2/factory-export.hh"
#include "acmacs-chart-2/chart.hh"
#include "acmacs-chart-2/chart-modify.hh"

// ----------------------------------------------------------------------

inline bool is_acmacs_file(const fs::path& path)
{
    if (path.extension() == ".ace")
        return true;
    if (path.extension() == ".bz2" && path.stem().extension() == ".acd1")
        return true;
    return false;
}

// ----------------------------------------------------------------------

class SerumIds
{
  public:
    using Name = acmacs::chart::Name;
    using Passage = acmacs::virus::Passage;
    using Reassortant = acmacs::virus::Reassortant;
    using Annotations = acmacs::chart::Annotations;
    using SerumId = acmacs::chart::SerumId;
    using SerumIdRoot = acmacs::named_string_t<struct SerumIdRootTag>;
    using SerumEntry = std::tuple<Name, Reassortant, Annotations, SerumId, Passage>;
    using TableEntry = std::tuple<acmacs::chart::VirusType, acmacs::chart::Lab, acmacs::chart::Assay, acmacs::chart::RbcSpecies, acmacs::chart::TableDate>;
    using Entry = std::tuple<SerumIdRoot, SerumId, Name, Reassortant, Annotations, acmacs::chart::VirusType, acmacs::chart::Lab, acmacs::chart::Assay, acmacs::chart::RbcSpecies,
                             acmacs::chart::TableDate, Passage>;
    using Entries = std::vector<Entry>;
    using EntryPtr = typename Entries::const_iterator;
    using PerSerumIdEntry = std::tuple<EntryPtr, EntryPtr>;
    using PerSerumIdRootEntry = std::tuple<EntryPtr, EntryPtr, std::vector<PerSerumIdEntry>>;
    using PerSerumIdRootEntries = std::vector<PerSerumIdRootEntry>;

    SerumIds() = default;

    size_t size() const { return data_.size(); }

    // returns number of files processed
    size_t scan_directory(std::string dirname)
    {
        size_t charts_processed = 0;
        for (auto& entry : fs::directory_iterator(dirname)) {
            if (const auto pathname = entry.path(); entry.is_regular_file() && is_acmacs_file(pathname)) {
                auto chart = acmacs::chart::import_from_file(pathname);
                std::tuple table(chart->info()->virus_type(), chart->info()->lab(), chart->info()->assay(), chart->info()->rbc_species(), chart->info()->date());
                auto sera = chart->sera();
                for (auto serum : *sera)
                    add({serum->name(), serum->reassortant(), serum->annotations(), serum->serum_id(), serum->passage()}, table);
                ++charts_processed;
            }
        }
        sort();
        scan();
        return charts_processed;
    }

    void print(bool print_good) const
    {
        const bool show_assay = std::get<acmacs::chart::VirusType>(*std::get<0>(per_root_.front())) == "A(H3N2)";
        const bool show_rbc = show_assay;
        for (const auto& per_root_entry : per_root_) {
            const auto name = make_name(std::get<0>(per_root_entry)), name_last = make_name(std::get<1>(per_root_entry) - 1);
            if (const bool good = std::get<2>(per_root_entry).size() == 1; !good || print_good) {
                std::cout << fmt::format("{} {}\n", std::get<SerumIdRoot>(*std::get<0>(per_root_entry)), std::get<1>(per_root_entry) - std::get<0>(per_root_entry));
                for (const auto& per_serum_id_entry : std::get<2>(per_root_entry)) {
                    const auto tabs = tables(std::get<0>(per_serum_id_entry), std::get<1>(per_serum_id_entry), show_assay, show_rbc);
                    std::cout << fmt::format("    {} {} [{}]", std::get<SerumId>(*std::get<0>(per_serum_id_entry)), tabs.size(), make_name(std::get<0>(per_serum_id_entry)));
                    for (const auto& table : tabs)
                        std::cout << ' ' << table;
                    std::cout << '\n';
                }
                if (!good) {
                    const auto& sids = std::get<2>(per_root_entry);
                    if (std::get<SerumId>(*std::get<0>(sids.front())) != std::get<SerumId>(*std::get<0>(sids.back()))) {
                        const auto sid = std::max_element(sids.begin(), sids.end(),
                                                          [](const auto& e1, const auto& e2) -> bool { return (std::get<1>(e1) - std::get<0>(e1)) < (std::get<1>(e2) - std::get<0>(e2)); });
                        for (auto ep = sids.begin(); ep != sids.end(); ++ep) {
                            if (ep != sid) {
                                std::cout << "  --fix ";
                                const auto sid1 = std::get<SerumId>(*std::get<0>(*ep)), sid2 = std::get<SerumId>(*std::get<0>(*sid));
                                if ((std::get<1>(*ep) - std::get<0>(*ep)) == (std::get<1>(*sid) - std::get<0>(*sid)) && sid2.size() < sid1.size())
                                    std::cout << sid2 << '^' << sid1;
                                else
                                    std::cout << sid1 << '^' << sid2;
                                std::cout << '\n';
                            }
                        }
                    }
                }
            }
        }
    }

  private:
    Entries data_;
    PerSerumIdRootEntries per_root_;

    void sort() { std::sort(data_.begin(), data_.end()); /* data_.erase(std::unique(data_.begin(), data_.end()), data_.end()); */ }

    void add(const SerumEntry& serum, const TableEntry& table)
    {
        data_.emplace_back(serum_id_root(serum, table), std::get<SerumId>(serum), std::get<Name>(serum), std::get<Reassortant>(serum), std::get<Annotations>(serum),
                           std::get<acmacs::chart::VirusType>(table), std::get<acmacs::chart::Lab>(table), std::get<acmacs::chart::Assay>(table), std::get<acmacs::chart::RbcSpecies>(table),
                           std::get<acmacs::chart::TableDate>(table), std::get<Passage>(serum));
    }

    void scan()
    {
        for (EntryPtr entry_ptr = data_.begin(); entry_ptr != data_.end(); ++entry_ptr) {
            if (per_root_.empty() || std::get<SerumIdRoot>(*entry_ptr) != std::get<SerumIdRoot>(*std::get<0>(per_root_.back()))) {
                per_root_.emplace_back(entry_ptr, entry_ptr + 1, std::vector<PerSerumIdEntry>{{entry_ptr, entry_ptr + 1}});
            }
            else {
                std::get<1>(per_root_.back()) = entry_ptr + 1;
                const auto last = std::get<0>(std::get<2>(per_root_.back()).back());
                const auto name = make_name(entry_ptr), name_last = make_name(last);
                if (std::get<SerumId>(*entry_ptr) != std::get<SerumId>(*last) || name != name_last) {
                    std::get<2>(per_root_.back()).emplace_back(entry_ptr, entry_ptr + 1);
                }
                else {
                    std::get<1>(std::get<2>(per_root_.back()).back()) = entry_ptr + 1;
                }
            }
        }
        std::cout << "per_root_ " << per_root_.size() << '\n';
    }

    SerumIdRoot serum_id_root(const SerumEntry& serum, const TableEntry& table) const
    {
        const auto& serum_id = std::get<SerumId>(serum);
        if (std::get<acmacs::chart::Lab>(table) == "MELB") {
            if (serum_id.size() > 6 && (serum_id[0] == 'F' || serum_id[0] == 'R' || serum_id[0] == 'A') && serum_id[5] == '-' && serum_id.back() == 'D')
                return SerumIdRoot(serum_id.substr(0, 5));
            else
                return SerumIdRoot(serum_id);
        }
        else
            return SerumIdRoot(serum_id);
    }

    static inline std::string make_name(EntryPtr ptr) { return string::join({std::get<Name>(*ptr), std::get<Reassortant>(*ptr), string::join(" ", std::get<Annotations>(*ptr))}); }

    static inline std::vector<std::string> tables(EntryPtr first, EntryPtr last, bool assay, bool rbc)
    {
        std::vector<std::string> tables(static_cast<size_t>(last - first));
        std::transform(first, last, tables.begin(), [assay, rbc](const auto& entry) {
            std::vector<std::string> fields;
            if (assay)
                fields.push_back(*std::get<acmacs::chart::Assay>(entry));
            if (rbc)
                fields.push_back(*std::get<acmacs::chart::RbcSpecies>(entry));
            fields.push_back(*std::get<acmacs::chart::TableDate>(entry));
            return string::join(":", fields);
        });
        std::reverse(tables.begin(), tables.end());
        return tables;
    }

}; // class SerumIds

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

class FixSerumIds
{
  public:
    FixSerumIds(std::string_view program_name) : program_name_(program_name) {}
    void add_fix(std::string_view fix_entry)
    {
        const auto fields = acmacs::string::split(fix_entry, "^");
        data_.emplace_back(fields[0], fields[1]);
    }

    // returns number of files updated
    size_t fix_charts_in_directory(std::string dirname)
    {
        size_t fixed_charts = 0;
        for (auto& entry : fs::directory_iterator(dirname)) {
            if (const auto pathname = entry.path(); entry.is_regular_file() && is_acmacs_file(pathname)) {
                acmacs::chart::ChartModify chart(acmacs::chart::import_from_file(pathname));
                if (fix_in_chart(chart)) {
                    acmacs::file::backup(pathname, acmacs::file::backup_move::yes);
                    acmacs::chart::export_factory(chart, make_export_filename(pathname), fs::path(program_name_).filename(), report_time::no);
                    ++fixed_charts;
                }
            }
        }
        return fixed_charts;
    }

  private:
    std::string_view program_name_;
    std::vector<std::pair<std::string, std::string>> data_;

    bool fix_in_chart(acmacs::chart::ChartModify& chart)
    {
        auto sera = chart.sera_modify();
        bool modified = false;
        for (size_t serum_no = 0; serum_no < sera->size(); ++ serum_no) {
            auto& serum = sera->at(serum_no);
            const auto sid = serum.serum_id();
            for (const auto& fix : data_) {
                if (sid == fix.first) {
                    std::cout << chart.info()->make_name() << " FIX " << *serum.name() << ' ' << *serum.reassortant() << ' ' << string::join(" ", serum.annotations()) << ' ' << serum.serum_id()
                              << " --> " << fix.second << '\n';
                    serum.serum_id(fix.second);
                    modified = true;
                    break;
                }
            }
        }
        return modified;
    }

    fs::path make_export_filename(const fs::path& pathname) const
    {
        if (pathname.extension() == ".ace")
            return pathname;
        if (pathname.extension() == ".bz2" && pathname.stem().extension() == ".acd1")
            return pathname.stem().stem() += ".ace";
        throw std::runtime_error("cannot figure out export filename for: " + pathname.string());
    }

}; // class FixSerumIds

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

using namespace acmacs::argv;

struct Options : public argv
{
    Options(int a_argc, const char* const a_argv[], on_error on_err = on_error::exit) : argv() { parse(a_argc, a_argv, on_err); }

    option<str_array> fix{*this, "fix"};
    // argument<str> period{*this, arg_name{"monthly|yearly|weekly"}, mandatory};
    // argument<Date> start{*this, arg_name{"start-date"}, mandatory};
    // argument<Date> end{*this, arg_name{"end-date"}, mandatory};
    // argument<str> output{*this, arg_name{"output.json"}, dflt{""}};
};

// ----------------------------------------------------------------------

int main(int argc, const char* argv[])
{
    int exit_code = 0;
    try {
        Options opt(argc, argv);
        std::vector<std::pair<std::string, std::string>> fix_data;
        if (opt.fix.has_value()) {
            FixSerumIds fix_serum_ids(opt.program_name());
            for (const auto& fix_entry : opt.fix.get())
                fix_serum_ids.add_fix(fix_entry);
            const auto charts_modified = fix_serum_ids.fix_charts_in_directory(".");
            std::cerr << "INFO: charts modified: " << charts_modified << '\n';
        }
        else {
            SerumIds serum_ids;
            const auto charts_processed = serum_ids.scan_directory(".");
            std::cout << charts_processed << " charts processed\n";
            serum_ids.print(false);
        }
    }
    catch (std::exception& err) {
        std::cerr << "ERROR: " << err.what() << '\n';
        exit_code = 2;
    }
    return exit_code;
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>acmacs::chart::Date, Continent, SerumId, SerumSpecies are named_string_t based<commit_after>#include <iostream>
#include <string>
#include <vector>
#include <tuple>

#include "acmacs-base/argv.hh"
#include "acmacs-base/filesystem.hh"
#include "acmacs-base/named-type.hh"
#include "acmacs-base/string.hh"
#include "acmacs-base/string-split.hh"
#include "acmacs-base/read-file.hh"
#include "acmacs-chart-2/factory-import.hh"
#include "acmacs-chart-2/factory-export.hh"
#include "acmacs-chart-2/chart.hh"
#include "acmacs-chart-2/chart-modify.hh"

// ----------------------------------------------------------------------

inline bool is_acmacs_file(const fs::path& path)
{
    if (path.extension() == ".ace")
        return true;
    if (path.extension() == ".bz2" && path.stem().extension() == ".acd1")
        return true;
    return false;
}

// ----------------------------------------------------------------------

class SerumIds
{
  public:
    using Name = acmacs::chart::Name;
    using Passage = acmacs::virus::Passage;
    using Reassortant = acmacs::virus::Reassortant;
    using Annotations = acmacs::chart::Annotations;
    using SerumId = acmacs::chart::SerumId;
    using SerumIdRoot = acmacs::named_string_t<struct SerumIdRootTag>;
    using SerumEntry = std::tuple<Name, Reassortant, Annotations, SerumId, Passage>;
    using TableEntry = std::tuple<acmacs::chart::VirusType, acmacs::chart::Lab, acmacs::chart::Assay, acmacs::chart::RbcSpecies, acmacs::chart::TableDate>;
    using Entry = std::tuple<SerumIdRoot, SerumId, Name, Reassortant, Annotations, acmacs::chart::VirusType, acmacs::chart::Lab, acmacs::chart::Assay, acmacs::chart::RbcSpecies,
                             acmacs::chart::TableDate, Passage>;
    using Entries = std::vector<Entry>;
    using EntryPtr = typename Entries::const_iterator;
    using PerSerumIdEntry = std::tuple<EntryPtr, EntryPtr>;
    using PerSerumIdRootEntry = std::tuple<EntryPtr, EntryPtr, std::vector<PerSerumIdEntry>>;
    using PerSerumIdRootEntries = std::vector<PerSerumIdRootEntry>;

    SerumIds() = default;

    size_t size() const { return data_.size(); }

    // returns number of files processed
    size_t scan_directory(std::string dirname)
    {
        size_t charts_processed = 0;
        for (auto& entry : fs::directory_iterator(dirname)) {
            if (const auto pathname = entry.path(); entry.is_regular_file() && is_acmacs_file(pathname)) {
                auto chart = acmacs::chart::import_from_file(pathname);
                std::tuple table(chart->info()->virus_type(), chart->info()->lab(), chart->info()->assay(), chart->info()->rbc_species(), chart->info()->date());
                auto sera = chart->sera();
                for (auto serum : *sera)
                    add({serum->name(), serum->reassortant(), serum->annotations(), serum->serum_id(), serum->passage()}, table);
                ++charts_processed;
            }
        }
        sort();
        scan();
        return charts_processed;
    }

    void print(bool print_good) const
    {
        const bool show_assay = std::get<acmacs::chart::VirusType>(*std::get<0>(per_root_.front())) == "A(H3N2)";
        const bool show_rbc = show_assay;
        for (const auto& per_root_entry : per_root_) {
            const auto name = make_name(std::get<0>(per_root_entry)), name_last = make_name(std::get<1>(per_root_entry) - 1);
            if (const bool good = std::get<2>(per_root_entry).size() == 1; !good || print_good) {
                std::cout << fmt::format("{} {}\n", std::get<SerumIdRoot>(*std::get<0>(per_root_entry)), std::get<1>(per_root_entry) - std::get<0>(per_root_entry));
                for (const auto& per_serum_id_entry : std::get<2>(per_root_entry)) {
                    const auto tabs = tables(std::get<0>(per_serum_id_entry), std::get<1>(per_serum_id_entry), show_assay, show_rbc);
                    std::cout << fmt::format("    {} {} [{}]", std::get<SerumId>(*std::get<0>(per_serum_id_entry)), tabs.size(), make_name(std::get<0>(per_serum_id_entry)));
                    for (const auto& table : tabs)
                        std::cout << ' ' << table;
                    std::cout << '\n';
                }
                if (!good) {
                    const auto& sids = std::get<2>(per_root_entry);
                    if (std::get<SerumId>(*std::get<0>(sids.front())) != std::get<SerumId>(*std::get<0>(sids.back()))) {
                        const auto sid = std::max_element(sids.begin(), sids.end(),
                                                          [](const auto& e1, const auto& e2) -> bool { return (std::get<1>(e1) - std::get<0>(e1)) < (std::get<1>(e2) - std::get<0>(e2)); });
                        for (auto ep = sids.begin(); ep != sids.end(); ++ep) {
                            if (ep != sid) {
                                std::cout << "  --fix ";
                                const auto sid1 = std::get<SerumId>(*std::get<0>(*ep)), sid2 = std::get<SerumId>(*std::get<0>(*sid));
                                if ((std::get<1>(*ep) - std::get<0>(*ep)) == (std::get<1>(*sid) - std::get<0>(*sid)) && sid2.size() < sid1.size())
                                    std::cout << *sid2 << '^' << *sid1;
                                else
                                    std::cout << *sid1 << '^' << *sid2;
                                std::cout << '\n';
                            }
                        }
                    }
                }
            }
        }
    }

  private:
    Entries data_;
    PerSerumIdRootEntries per_root_;

    void sort() { std::sort(data_.begin(), data_.end()); /* data_.erase(std::unique(data_.begin(), data_.end()), data_.end()); */ }

    void add(const SerumEntry& serum, const TableEntry& table)
    {
        data_.emplace_back(serum_id_root(serum, table), std::get<SerumId>(serum), std::get<Name>(serum), std::get<Reassortant>(serum), std::get<Annotations>(serum),
                           std::get<acmacs::chart::VirusType>(table), std::get<acmacs::chart::Lab>(table), std::get<acmacs::chart::Assay>(table), std::get<acmacs::chart::RbcSpecies>(table),
                           std::get<acmacs::chart::TableDate>(table), std::get<Passage>(serum));
    }

    void scan()
    {
        for (EntryPtr entry_ptr = data_.begin(); entry_ptr != data_.end(); ++entry_ptr) {
            if (per_root_.empty() || std::get<SerumIdRoot>(*entry_ptr) != std::get<SerumIdRoot>(*std::get<0>(per_root_.back()))) {
                per_root_.emplace_back(entry_ptr, entry_ptr + 1, std::vector<PerSerumIdEntry>{{entry_ptr, entry_ptr + 1}});
            }
            else {
                std::get<1>(per_root_.back()) = entry_ptr + 1;
                const auto last = std::get<0>(std::get<2>(per_root_.back()).back());
                const auto name = make_name(entry_ptr), name_last = make_name(last);
                if (std::get<SerumId>(*entry_ptr) != std::get<SerumId>(*last) || name != name_last) {
                    std::get<2>(per_root_.back()).emplace_back(entry_ptr, entry_ptr + 1);
                }
                else {
                    std::get<1>(std::get<2>(per_root_.back()).back()) = entry_ptr + 1;
                }
            }
        }
        std::cout << "per_root_ " << per_root_.size() << '\n';
    }

    SerumIdRoot serum_id_root(const SerumEntry& serum, const TableEntry& table) const
    {
        const auto& serum_id = std::get<SerumId>(serum);
        if (std::get<acmacs::chart::Lab>(table) == "MELB") {
            if (serum_id.size() > 6 && (serum_id[0] == 'F' || serum_id[0] == 'R' || serum_id[0] == 'A') && serum_id[5] == '-' && serum_id->back() == 'D')
                return SerumIdRoot(serum_id->substr(0, 5));
            else
                return SerumIdRoot(serum_id);
        }
        else
            return SerumIdRoot(serum_id);
    }

    static inline std::string make_name(EntryPtr ptr) { return string::join({std::get<Name>(*ptr), std::get<Reassortant>(*ptr), string::join(" ", std::get<Annotations>(*ptr))}); }

    static inline std::vector<std::string> tables(EntryPtr first, EntryPtr last, bool assay, bool rbc)
    {
        std::vector<std::string> tables(static_cast<size_t>(last - first));
        std::transform(first, last, tables.begin(), [assay, rbc](const auto& entry) {
            std::vector<std::string> fields;
            if (assay)
                fields.push_back(*std::get<acmacs::chart::Assay>(entry));
            if (rbc)
                fields.push_back(*std::get<acmacs::chart::RbcSpecies>(entry));
            fields.push_back(*std::get<acmacs::chart::TableDate>(entry));
            return string::join(":", fields);
        });
        std::reverse(tables.begin(), tables.end());
        return tables;
    }

}; // class SerumIds

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

class FixSerumIds
{
  public:
    FixSerumIds(std::string_view program_name) : program_name_(program_name) {}
    void add_fix(std::string_view fix_entry)
    {
        const auto fields = acmacs::string::split(fix_entry, "^");
        data_.emplace_back(fields[0], fields[1]);
    }

    // returns number of files updated
    size_t fix_charts_in_directory(std::string dirname)
    {
        size_t fixed_charts = 0;
        for (auto& entry : fs::directory_iterator(dirname)) {
            if (const auto pathname = entry.path(); entry.is_regular_file() && is_acmacs_file(pathname)) {
                acmacs::chart::ChartModify chart(acmacs::chart::import_from_file(pathname));
                if (fix_in_chart(chart)) {
                    acmacs::file::backup(pathname, acmacs::file::backup_move::yes);
                    acmacs::chart::export_factory(chart, make_export_filename(pathname), fs::path(program_name_).filename(), report_time::no);
                    ++fixed_charts;
                }
            }
        }
        return fixed_charts;
    }

  private:
    std::string_view program_name_;
    std::vector<std::pair<std::string, std::string>> data_;

    bool fix_in_chart(acmacs::chart::ChartModify& chart)
    {
        auto sera = chart.sera_modify();
        bool modified = false;
        for (size_t serum_no = 0; serum_no < sera->size(); ++ serum_no) {
            auto& serum = sera->at(serum_no);
            const auto sid = serum.serum_id();
            for (const auto& fix : data_) {
                if (sid == fix.first) {
                    std::cout << fmt::format("{} FIX {} {} {} {} --> {}\n", chart.info()->make_name(), serum.name(), serum.reassortant(), string::join(" ", serum.annotations()), serum.serum_id(), fix.second);
                    serum.serum_id(acmacs::chart::SerumId{fix.second});
                    modified = true;
                    break;
                }
            }
        }
        return modified;
    }

    fs::path make_export_filename(const fs::path& pathname) const
    {
        if (pathname.extension() == ".ace")
            return pathname;
        if (pathname.extension() == ".bz2" && pathname.stem().extension() == ".acd1")
            return pathname.stem().stem() += ".ace";
        throw std::runtime_error("cannot figure out export filename for: " + pathname.string());
    }

}; // class FixSerumIds

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

using namespace acmacs::argv;

struct Options : public argv
{
    Options(int a_argc, const char* const a_argv[], on_error on_err = on_error::exit) : argv() { parse(a_argc, a_argv, on_err); }

    option<str_array> fix{*this, "fix"};
    // argument<str> period{*this, arg_name{"monthly|yearly|weekly"}, mandatory};
    // argument<Date> start{*this, arg_name{"start-date"}, mandatory};
    // argument<Date> end{*this, arg_name{"end-date"}, mandatory};
    // argument<str> output{*this, arg_name{"output.json"}, dflt{""}};
};

// ----------------------------------------------------------------------

int main(int argc, const char* argv[])
{
    int exit_code = 0;
    try {
        Options opt(argc, argv);
        std::vector<std::pair<std::string, std::string>> fix_data;
        if (opt.fix.has_value()) {
            FixSerumIds fix_serum_ids(opt.program_name());
            for (const auto& fix_entry : opt.fix.get())
                fix_serum_ids.add_fix(fix_entry);
            const auto charts_modified = fix_serum_ids.fix_charts_in_directory(".");
            std::cerr << "INFO: charts modified: " << charts_modified << '\n';
        }
        else {
            SerumIds serum_ids;
            const auto charts_processed = serum_ids.scan_directory(".");
            std::cout << charts_processed << " charts processed\n";
            serum_ids.print(false);
        }
    }
    catch (std::exception& err) {
        std::cerr << "ERROR: " << err.what() << '\n';
        exit_code = 2;
    }
    return exit_code;
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <vector>

#include "acmacs-base/argv.hh"
#include "acmacs-base/filesystem.hh"
#include "acmacs-chart-2/factory-import.hh"
#include "acmacs-chart-2/chart.hh"

// ----------------------------------------------------------------------

// using namespace acmacs::argv;

// struct Options : public argv
// {
//     Options(int a_argc, const char* const a_argv[], on_error on_err = on_error::exit) : argv() { parse(a_argc, a_argv, on_err); }

//     argument<str> period{*this, arg_name{"monthly|yearly|weekly"}, mandatory};
//     argument<Date> start{*this, arg_name{"start-date"}, mandatory};
//     argument<Date> end{*this, arg_name{"end-date"}, mandatory};
//     argument<str> output{*this, arg_name{"output.json"}, dflt{""}};
// };

// ----------------------------------------------------------------------

inline bool is_acmacs_file(const fs::path& path)
{
  if (path.extension() == ".ace")
    return true;
  if (path.extension() == ".bz2") {
    if (path.stem().extension() == ".acd1")
      return true;
  }
  return false;
}

// ----------------------------------------------------------------------

struct NameId
{
  NameId(std::string n, std::string si, std::string d) : name(n), serum_id(si), date(d) {}
  bool operator<(const NameId& rhs) const { if (name == rhs.name) { if (serum_id == rhs.serum_id) return date < rhs.date; else return serum_id < rhs.serum_id; } else return name < rhs.name; }
  bool operator==(const NameId& rhs) const { return name == rhs.name && serum_id == rhs.serum_id && date == rhs.date; }
  bool operator!=(const NameId& rhs) const { return !operator==(rhs); }
  std::string name;
  std::string serum_id;
  std::string date;
};

struct NameIds
{
  NameIds(std::string n) : name(n) {}
  std::string name;
  std::vector<std::pair<std::string, size_t>> id_count;
};

// ----------------------------------------------------------------------

int main(int /*argc*/, const char* /*argv*/[])
{
  int exit_code = 0;
  try {
    // Options opt(argc, argv);
    std::vector<NameId> name_id;
    size_t charts_processed = 0;
    for (auto& entry : fs::directory_iterator(".")) {
      if (entry.is_regular_file() && is_acmacs_file(entry.path())) {
        // std::cout << entry.path() << '\n';
        auto chart = acmacs::chart::import_from_file(entry.path());
        const std::string date = chart->info()->date();
        auto sera = chart->sera();
        for (auto serum : *sera)
          name_id.emplace_back(serum->designation_without_serum_id(), serum->serum_id(), date);
        ++charts_processed;
      }
    }
    std::cout << charts_processed << " charts processed\n";
    std::sort(name_id.begin(), name_id.end());
    // std::cout << name_id.size() << " sera found\n";
    // name_id.erase(std::unique(name_id.begin(), name_id.end()), name_id.end());
    std::cout << name_id.size() << " sera found\n";

    /* std::vector<std::pair<std::string, std::vector<std::string>>> name_ids; */
    /* for (const auto& entry : name_id) { */
    /*   if (name_ids.empty() || name_ids.back().first != entry.first) */
    /*     name_ids.emplace_back(entry.first, std::vector<std::string>{entry.second}); */
    /*   else */
    /*     name_ids.back().second.push_back(entry.second); */
    /* } */
    /* std::cout << name_ids.size() << " serum names found\n"; */

    /* for (const auto& entry : name_ids) { */
    /*   std::cout << entry.first << '\n'; */
    /*   for (const auto& serum_id : entry.second) { */
    /*     std::cout << "  " << serum_id; */
    /*     if (serum_id[0] == 'F' || serum_id[0] == 'R') { */
    /*       if (serum_id.back() != 'D') */
    /*         std::cout << "  Warning: FIX!"; */
    /*     } */
    /*     else */
    /*       std::cout << "  Warning: not MELB"; */
    /*     std::cout << '\n'; */
    /*   } */
    /* } */

  }
  catch (std::exception& err) {
    std::cerr << "ERROR: " << err.what() << '\n';
    exit_code = 2;
  }
  return exit_code;
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>scan serum ids of MELB tables<commit_after>#include <iostream>
#include <string>
#include <vector>
#include <tuple>

#include "acmacs-base/argv.hh"
#include "acmacs-base/filesystem.hh"
#include "acmacs-chart-2/factory-import.hh"
#include "acmacs-chart-2/chart.hh"

// ----------------------------------------------------------------------

// using namespace acmacs::argv;

// struct Options : public argv
// {
//     Options(int a_argc, const char* const a_argv[], on_error on_err = on_error::exit) : argv() { parse(a_argc, a_argv, on_err); }

//     argument<str> period{*this, arg_name{"monthly|yearly|weekly"}, mandatory};
//     argument<Date> start{*this, arg_name{"start-date"}, mandatory};
//     argument<Date> end{*this, arg_name{"end-date"}, mandatory};
//     argument<str> output{*this, arg_name{"output.json"}, dflt{""}};
// };

// ----------------------------------------------------------------------

inline bool is_acmacs_file(const fs::path& path)
{
  if (path.extension() == ".ace")
    return true;
  if (path.extension() == ".bz2") {
    if (path.stem().extension() == ".acd1")
      return true;
  }
  return false;
}

// ----------------------------------------------------------------------

class SerumIds
{
 public:
    using Name = acmacs::chart::Name;
    using Passage = acmacs::chart::Passage;
    using Reassortant = acmacs::chart::Reassortant;
    using Annotations = acmacs::chart::Annotations;
    using SerumId = acmacs::chart::SerumId;
    using SerumIdRoot = std::string;
    using SerumEntry = std::tuple<Name, Reassortant, Annotations, SerumId, Passage>;
    using TableEntry = std::tuple<>;

    SerumIds() = default;

    void add(const Name& name, const Reassortant& reassortant, const Annotations& annotations, const SerumId& serum_id, const Passage& passage);

 private:
      // std::map<SerumIdRoot, std::tuple<
};

struct NameId
{
  NameId(std::string n, std::string si, std::string d) : name(n), serum_id(si), date(d) {}
  bool operator<(const NameId& rhs) const { if (name == rhs.name) { if (serum_id == rhs.serum_id) return date < rhs.date; else return serum_id < rhs.serum_id; } else return name < rhs.name; }
  bool operator==(const NameId& rhs) const { return name == rhs.name && serum_id == rhs.serum_id && date == rhs.date; }
  bool operator!=(const NameId& rhs) const { return !operator==(rhs); }
  std::string name;
  std::string serum_id;
  std::string date;
};

struct NameIds
{
  NameIds(std::string n) : name(n) {}
  std::string name;
  std::vector<std::pair<std::string, size_t>> id_count;
};

// ----------------------------------------------------------------------

int main(int /*argc*/, const char* /*argv*/[])
{
    int exit_code = 0;
    try {
        // Options opt(argc, argv);
        std::vector<NameId> name_id;
        size_t charts_processed = 0;
        for (auto& entry : fs::directory_iterator(".")) {
            if (entry.is_regular_file() && is_acmacs_file(entry.path())) {
                // std::cout << entry.path() << '\n';
                auto chart = acmacs::chart::import_from_file(entry.path());
                const std::string date = chart->info()->date();
                auto sera = chart->sera();
                for (auto serum : *sera)
                    name_id.emplace_back(serum->designation_without_serum_id(), serum->serum_id(), date);
                ++charts_processed;
            }
        }
        std::cout << charts_processed << " charts processed\n";
        std::sort(name_id.begin(), name_id.end());
        // std::cout << name_id.size() << " sera found\n";
        // name_id.erase(std::unique(name_id.begin(), name_id.end()),
        // name_id.end());
        std::cout << name_id.size() << " sera found\n";

        // std::vector<std::pair<std::string, std::vector<std::string>>> name_ids;
        // for (const auto& entry : name_id) {
        //     if (name_ids.empty() || name_ids.back().first != entry.first)
        //         name_ids.emplace_back(entry.first, std::vector<std::string>{entry.second});
        //     else
        //         name_ids.back().second.push_back(entry.second);
        // }
        // std::cout << name_ids.size() << " serum names found\n";

        // for (const auto& entry : name_ids) {
        //     std::cout << entry.first << '\n';
        //     for (const auto& serum_id : entry.second) {
        //         std::cout << "  " << serum_id;
        //         if (serum_id[0] == 'F' || serum_id[0] == 'R') {
        //             if (serum_id.back() != 'D')
        //                 std::cout << "  Warning: FIX!";
        //         }
        //         else
        //             std::cout << "  Warning: not MELB";
        //         std::cout << '\n';
        //     }
        // }
    }
    catch (std::exception& err) {
        std::cerr << "ERROR: " << err.what() << '\n';
        exit_code = 2;
    }
    return exit_code;
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include "cmd.hpp"
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>

Cmd::Cmd ()
{}

Cmd::Cmd(string input1)
{
	uCmd = input1;
//	cout << "uCmd: " << uCmd << endl;
}

//where the magic happens
//uses fork and exec to execute commands and returns bool values to indicate a valid/invalid command
bool Cmd::execute(string cmd_s)
{

    pid_t pid;
    char* args[2];
    args[0] = (char*)cmd_s.c_str();
    args[1] = NULL;
    pid = fork();
	int status;

	if (pid == -1)
	{
		perror("fork");
		exit(1);
    }
    if (pid == 0) // child process
    {
         if(execvp(args[0], args) == -1)
         {
		     perror("exec");
		     exit(1);

         }
		 valid = true;
    }
    else // parent process
    {
		if (wait(0) == -1)
		{
			perror("wait");
			exit(1);
		}
		if (WEXITSTATUS(status) != 0)
		{
			return false;
		}
     }

	return true;

}

<commit_msg>added WEXITSTATUS<commit_after>#include "cmd.hpp"
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>

Cmd::Cmd ()
{}

Cmd::Cmd(string input1)
{
	uCmd = input1;
//	cout << "uCmd: " << uCmd << endl;
}

//where the magic happens
//uses fork and exec to execute commands and returns bool values to indicate a valid/invalid command
bool Cmd::execute(string cmd_s)
{

    pid_t pid;
    char* args[2];
    args[0] = (char*)cmd_s.c_str();
    args[1] = NULL;
    pid = fork();
	int status;

	if (pid == -1)
	{
		perror("fork");
		exit(1);
    }
    if (pid == 0) // child process
    {
         if(execvp(args[0], args) == -1)
         {
		     perror("exec");
		     exit(1);

         }
    }
    else // parent process
    {
		if (wait(0) == -1)
		{
			perror("wait");
			exit(1);
		}
		if (WEXITSTATUS(status) != 0)
		{
			return false;
		}
     }

	return true;

}

<|endoftext|>


<commit_before>#include <cctag/geometry/Ellipse.hpp>
#include <cctag/geometry/point.hpp>
#include <cctag/algebra/invert.hpp>
#include <cctag/progBase/exceptions.hpp>
#include <cctag/global.hpp>

#include <boost/math/special_functions/sign.hpp>
#include <boost/numeric/ublas/banded.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix_expression.hpp>

#include <algorithm>
#include <cmath>

namespace cctag {
namespace numerical {
namespace geometry {

using namespace boost::numeric::ublas;

Ellipse::Ellipse( const bounded_matrix<double, 3, 3>& matrix )
{
	_matrix = matrix;
	computeParameters();
}

Ellipse::Ellipse( const Point2dN<double>& center, const double a, const double b, const double angle )
{
	init( center, a, b, angle );
}

void Ellipse::init( const Point2dN<double>& center, const double a, const double b, const double angle )
{
	if( a < 0.0 || b < 0.0 )
	{
		CCTAG_THROW( exception::Bug()
			<< exception::dev( "Semi axes must be real positive!" ) );
	}

	_center = center;
	_a      = a;
	_b      = b;
	_angle  = angle;

	computeMatrix();
}

void Ellipse::setMatrix( const bounded_matrix<double, 3, 3>& matrix )
{
	_matrix = matrix;
	computeParameters();
}

void Ellipse::setParameters( const Point2dN<double>& center, const double a, const double b, const double angle )
{
	if( a < 0.0 || b < 0.0 )
	{
		CCTAG_THROW( exception::Bug()
			<< exception::dev( "Semi axes must be real positive!" ) );
	}
	_center = center;
	_a      = a;
	_b      = b;
	_angle  = angle;
	computeMatrix();
}

void Ellipse::setCenter( const Point2dN<double>& center )
{
	_center = center;
	computeMatrix();
}

void Ellipse::setA( const double a )
{
	if( a < 0.0 )
	{
		CCTAG_THROW( exception::Bug()
			<< exception::dev( "Semi axes must be real positive!" ) );
	}
	_a = a;
	computeMatrix();
}

void Ellipse::setB( const double b )
{
	if( b < 0.0 )
	{
		CCTAG_THROW( exception::Bug()
			<< exception::dev( "Semi axes must be real positive!" ) );
	}
	_b = b;
	computeMatrix();
}

void Ellipse::setAngle( const double angle )
{
	_angle = angle;
	computeMatrix();
}

Ellipse Ellipse::transform(const Matrix& mT) const
{
	using namespace boost::numeric::ublas;
	const Matrix a = prec_prod( boost::numeric::ublas::trans(mT), _matrix );
	const Matrix mET = prec_prod( a, mT );
	return Ellipse( mET );
}

void Ellipse::computeParameters()
{
	bounded_vector<double, 6> par;
	par( 0 ) = _matrix( 0, 0 );
	par( 1 ) = 2.0 * _matrix( 0, 1 );
	par( 2 ) = _matrix( 1, 1 );
	par( 3 ) = 2 * _matrix( 0, 2 );
	par( 4 ) = 2 * _matrix( 1, 2 );
	par( 5 ) = _matrix( 2, 2 );

	const double thetarad    = 0.5 * std::atan2( par( 1 ), par( 0 ) - par( 2 ) );
	const double cost        = std::cos( thetarad );
	const double sint        = std::sin( thetarad );
	const double sin_squared = sint * sint;
	const double cos_squared = cost * cost;
	const double cos_sin     = sint * cost;

	const double Ao  = par( 5 );
	const double Au  = par( 3 ) * cost + par( 4 ) * sint;
	const double Av  = -par( 3 ) * sint + par( 4 ) * cost;
	const double Auu = par( 0 ) * cos_squared + par( 2 ) * sin_squared + par( 1 ) * cos_sin;
	const double Avv = par( 0 ) * sin_squared + par( 2 ) * cos_squared - par( 1 ) * cos_sin;

	if( Auu == 0 || Avv == 0 )
	{
		_center = Point2dN<double>( 0.0, 0.0 );
		_a      = 0.0;
		_b      = 0.0;
		_angle  = 0.0;
	}
	else
	{
		const double tuCentre = -Au / ( 2.0 * Auu );
		const double tvCentre = -Av / ( 2.0 * Avv );
		const double wCentre  = Ao - Auu * tuCentre * tuCentre - Avv * tvCentre * tvCentre;

		_center = Point2dN<double>( tuCentre * cost - tvCentre * sint, tuCentre * sint + tvCentre * cost );

		const double Ru = -wCentre / Auu;
		const double Rv = -wCentre / Avv;

		const double aAux = std::sqrt( std::abs( Ru ) ) * boost::math::sign( Ru );
		const double bAux = std::sqrt( std::abs( Rv ) ) * boost::math::sign( Rv );

		if( aAux < 0.0 || bAux < 0.0 )
		{
			CCTAG_THROW( exception::Bug()
				<< exception::dev( "Semi axes must be real positive!" ) );
		}

		_a     = aAux;
		_b     = bAux;
		_angle = thetarad;
	}
}

/*
 * @brief Compute
 */
void Ellipse::getCanonicForm(Matrix& mCanonic, Matrix& mTprimal, Matrix& mTdual) const
{

  double q1 = _matrix(0,0);
  double q2 = _matrix(0,1);
  double q3 = _matrix(0,2);
  double q4 = _matrix(1,1);
  double q5 = _matrix(1,2);
  double q6 = _matrix(2,2);

  double par1 = q1;
  double par2 = 2*q2;
  double par3 = q4;
  double par4 = 2*q3;
  double par5 = 2*q5;
  double par6 = q6;

  double thetarad    = 0.5*atan2(par2,par1 - par3);
  double cost        = cos(thetarad);
  double sint        = sin(thetarad);
  double sin_squared = sint * sint;
  double cos_squared = cost * cost;
  double cos_sin     = sint * cost;

  double Ao          = par6;
  double Au          = par4 * cost + par5 * sint;
  double Av          = -par4 * sint + par5 * cost;
  double Auu         = par1 * cos_squared + par3 * sin_squared + par2 * cos_sin;
  double Avv         = par1 * sin_squared + par3 * cos_squared - par2 * cos_sin;

  double tuCentre    = - Au/(2*Auu);
  double tvCentre    = - Av/(2*Avv);

  double uCentre     = tuCentre * cost - tvCentre * sint;
  double vCentre     = tuCentre * sint + tvCentre * cost;

  double qt1 = cost*(cost*q1 + q2*sint) + sint*(cost*q2 + q4*sint);
  double qt2 = cost*(cost*q2 + q4*sint) - sint*(cost*q1 + q2*sint);
  double qt3 = cost*q3 + q5*sint + uCentre*(cost*q1 + q2*sint) + vCentre*(cost*q2 + q4*sint);
  double qt4 = cost*(cost*q4 - q2*sint) - sint*(cost*q2 - q1*sint);
  double qt5 = cost*q5 - q3*sint + uCentre*(cost*q2 - q1*sint) + vCentre*(cost*q4 - q2*sint);
  double qt6 =  q6 + uCentre*(q3 + q1*uCentre + q2*vCentre) + vCentre*(q5 + q2*uCentre + q4*vCentre) + q3*uCentre + q5*vCentre;

  mCanonic(0,0) = qt1;    mCanonic(0,1) = qt2;   mCanonic(0,2) = qt3;
  mCanonic(1,0) = qt2;    mCanonic(1,1) = qt4;   mCanonic(1,2) = qt5;
  mCanonic(2,0) = qt3;    mCanonic(2,1) = qt5;   mCanonic(2,2) = qt6;

  mTprimal(0,0) = cost;   mTprimal(0,1) = sint;  mTprimal(0,2) = - cost*uCentre - sint*vCentre;
  mTprimal(1,0) = -sint;  mTprimal(1,1) = cost;  mTprimal(1,2) = sint*uCentre - cost*vCentre;
  mTprimal(2,0) = 0;      mTprimal(2,1) = 0;     mTprimal(2,2) = cost*cost + sint*sint;

  mTdual(0,0) = cost;     mTdual(0,1) = -sint;   mTdual(0,2) = uCentre;
  mTdual(1,0) = sint;     mTdual(1,1) = cost;    mTdual(1,2) = vCentre;
  mTdual(2,0) = 0;        mTdual(2,1) = 0;       mTdual(2,2) = 1.0;

}

void Ellipse::computeMatrix()
{
  bounded_matrix<double, 3, 3> tmp;
  tmp( 0, 0 ) = std::cos( _angle ); tmp( 0, 1 ) = -std::sin( _angle ); tmp( 0, 2 ) = _center.x();
  tmp( 1, 0 ) = std::sin( _angle ); tmp( 1, 1 ) =  std::cos( _angle ); tmp( 1, 2 ) = _center.y();
  tmp( 2, 0 ) =             0.0; tmp( 2, 1 ) =              0.0; tmp( 2, 2 ) =        1.0;

  bounded_matrix<double, 3, 3> tmpInv;
  diagonal_matrix<double> diag( 3, 3 );
  diag( 0, 0 ) =  1.0 / ( _a * _a );
  diag( 1, 1 ) =  1.0 / ( _b * _b );
  diag( 2, 2 ) = -1.0;

  if( invert( tmp, tmpInv ) )
  {
          _matrix = prec_prod( diag, tmpInv );
          _matrix = prec_prod( trans( tmpInv ), _matrix );
  }
  else
  {
          CCTAG_THROW( exception::Bug()
                          << exception::dev( "Singular matrix!" ) );
  }
}

void scale(const Ellipse & ellipse, Ellipse & rescaleEllipse, double scale)
{
  rescaleEllipse.setCenter(Point2dN<double>( ellipse.center().x() * scale, ellipse.center().y() * scale ));
  rescaleEllipse.setA(ellipse.a() * scale);
  rescaleEllipse.setB(ellipse.b() * scale);
  rescaleEllipse.setAngle(ellipse.angle());
}

std::ostream& operator<<(std::ostream& os, const Ellipse& e)
{
  os  << "e = [ " << e.matrix()(0,0) << " " << e.matrix()(0,1) << " " << e.matrix()(0,2) << " ; "
      << e.matrix()(1,0) << " " << e.matrix()(1,1) << " " << e.matrix()(1,2) << " ; "
      << e.matrix()(2,0) << " " << e.matrix()(2,1) << " " << e.matrix()(2,2) << " ] ";
  return os;
}

/*
 * @brief Sort a set of points by angle along an elliptical arc. Possibly return a subset of these
 *        points if requested.
 */
void getSortedOuterPoints(
        const Ellipse & ellipse,
        const std::vector< cctag::DirectedPoint2d<double> > & points,
        std::vector< cctag::DirectedPoint2d<double> > & resPoints,
        const std::size_t requestedSize)
{
  // map with the key = angle and the point index
  // Sort points in points by angle
  //std::map<double, std::size_t> mapAngle;
  std::vector< std::pair<double, std::size_t> > vAngles;
  vAngles.reserve(points.size());
  for(std::size_t iPoint = 0 ; iPoint < points.size() ; ++iPoint)
  {
    double angle = atan2( ellipse.center().y() - points[iPoint].y() , ellipse.center().x() - points[iPoint].x() );
    //mapAngle.emplace(angle, iPoint);

    vAngles.emplace_back(angle, iPoint);
  }

  std::sort (vAngles.begin(), vAngles.end());

  // Get the final expected size of resPoints
  const std::size_t nOuterPoints = std::min( requestedSize, points.size() );
  std::size_t step = std::size_t( points.size() / ( nOuterPoints - 1 ) );

  CCTAG_COUT_VAR(vAngles.size());

  resPoints.clear();
  resPoints.reserve(nOuterPoints);

  CCTAG_COUT_VAR(points.size());
  CCTAG_COUT_VAR(step);

  // Get the final expected size of resPoints

  for(std::size_t iPoint = 0 ; iPoint < points.size() ; iPoint += step)
  {
    resPoints.push_back(points[vAngles[iPoint].second]);
  }
  CCTAG_COUT_VAR(resPoints.size());
}

}
}
}
<commit_msg>[identification] Clean getSortedOuterPoints function.<commit_after>#include <cctag/geometry/Ellipse.hpp>
#include <cctag/geometry/point.hpp>
#include <cctag/algebra/invert.hpp>
#include <cctag/progBase/exceptions.hpp>
#include <cctag/global.hpp>

#include <boost/math/special_functions/sign.hpp>
#include <boost/numeric/ublas/banded.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix_expression.hpp>

#include <algorithm>
#include <cmath>

namespace cctag {
namespace numerical {
namespace geometry {

using namespace boost::numeric::ublas;

Ellipse::Ellipse( const bounded_matrix<double, 3, 3>& matrix )
{
	_matrix = matrix;
	computeParameters();
}

Ellipse::Ellipse( const Point2dN<double>& center, const double a, const double b, const double angle )
{
	init( center, a, b, angle );
}

void Ellipse::init( const Point2dN<double>& center, const double a, const double b, const double angle )
{
	if( a < 0.0 || b < 0.0 )
	{
		CCTAG_THROW( exception::Bug()
			<< exception::dev( "Semi axes must be real positive!" ) );
	}

	_center = center;
	_a      = a;
	_b      = b;
	_angle  = angle;

	computeMatrix();
}

void Ellipse::setMatrix( const bounded_matrix<double, 3, 3>& matrix )
{
	_matrix = matrix;
	computeParameters();
}

void Ellipse::setParameters( const Point2dN<double>& center, const double a, const double b, const double angle )
{
	if( a < 0.0 || b < 0.0 )
	{
		CCTAG_THROW( exception::Bug()
			<< exception::dev( "Semi axes must be real positive!" ) );
	}
	_center = center;
	_a      = a;
	_b      = b;
	_angle  = angle;
	computeMatrix();
}

void Ellipse::setCenter( const Point2dN<double>& center )
{
	_center = center;
	computeMatrix();
}

void Ellipse::setA( const double a )
{
	if( a < 0.0 )
	{
		CCTAG_THROW( exception::Bug()
			<< exception::dev( "Semi axes must be real positive!" ) );
	}
	_a = a;
	computeMatrix();
}

void Ellipse::setB( const double b )
{
	if( b < 0.0 )
	{
		CCTAG_THROW( exception::Bug()
			<< exception::dev( "Semi axes must be real positive!" ) );
	}
	_b = b;
	computeMatrix();
}

void Ellipse::setAngle( const double angle )
{
	_angle = angle;
	computeMatrix();
}

Ellipse Ellipse::transform(const Matrix& mT) const
{
	using namespace boost::numeric::ublas;
	const Matrix a = prec_prod( boost::numeric::ublas::trans(mT), _matrix );
	const Matrix mET = prec_prod( a, mT );
	return Ellipse( mET );
}

void Ellipse::computeParameters()
{
	bounded_vector<double, 6> par;
	par( 0 ) = _matrix( 0, 0 );
	par( 1 ) = 2.0 * _matrix( 0, 1 );
	par( 2 ) = _matrix( 1, 1 );
	par( 3 ) = 2 * _matrix( 0, 2 );
	par( 4 ) = 2 * _matrix( 1, 2 );
	par( 5 ) = _matrix( 2, 2 );

	const double thetarad    = 0.5 * std::atan2( par( 1 ), par( 0 ) - par( 2 ) );
	const double cost        = std::cos( thetarad );
	const double sint        = std::sin( thetarad );
	const double sin_squared = sint * sint;
	const double cos_squared = cost * cost;
	const double cos_sin     = sint * cost;

	const double Ao  = par( 5 );
	const double Au  = par( 3 ) * cost + par( 4 ) * sint;
	const double Av  = -par( 3 ) * sint + par( 4 ) * cost;
	const double Auu = par( 0 ) * cos_squared + par( 2 ) * sin_squared + par( 1 ) * cos_sin;
	const double Avv = par( 0 ) * sin_squared + par( 2 ) * cos_squared - par( 1 ) * cos_sin;

	if( Auu == 0 || Avv == 0 )
	{
		_center = Point2dN<double>( 0.0, 0.0 );
		_a      = 0.0;
		_b      = 0.0;
		_angle  = 0.0;
	}
	else
	{
		const double tuCentre = -Au / ( 2.0 * Auu );
		const double tvCentre = -Av / ( 2.0 * Avv );
		const double wCentre  = Ao - Auu * tuCentre * tuCentre - Avv * tvCentre * tvCentre;

		_center = Point2dN<double>( tuCentre * cost - tvCentre * sint, tuCentre * sint + tvCentre * cost );

		const double Ru = -wCentre / Auu;
		const double Rv = -wCentre / Avv;

		const double aAux = std::sqrt( std::abs( Ru ) ) * boost::math::sign( Ru );
		const double bAux = std::sqrt( std::abs( Rv ) ) * boost::math::sign( Rv );

		if( aAux < 0.0 || bAux < 0.0 )
		{
			CCTAG_THROW( exception::Bug()
				<< exception::dev( "Semi axes must be real positive!" ) );
		}

		_a     = aAux;
		_b     = bAux;
		_angle = thetarad;
	}
}

/*
 * @brief Compute
 */
void Ellipse::getCanonicForm(Matrix& mCanonic, Matrix& mTprimal, Matrix& mTdual) const
{

  double q1 = _matrix(0,0);
  double q2 = _matrix(0,1);
  double q3 = _matrix(0,2);
  double q4 = _matrix(1,1);
  double q5 = _matrix(1,2);
  double q6 = _matrix(2,2);

  double par1 = q1;
  double par2 = 2*q2;
  double par3 = q4;
  double par4 = 2*q3;
  double par5 = 2*q5;
  double par6 = q6;

  double thetarad    = 0.5*atan2(par2,par1 - par3);
  double cost        = cos(thetarad);
  double sint        = sin(thetarad);
  double sin_squared = sint * sint;
  double cos_squared = cost * cost;
  double cos_sin     = sint * cost;

  double Ao          = par6;
  double Au          = par4 * cost + par5 * sint;
  double Av          = -par4 * sint + par5 * cost;
  double Auu         = par1 * cos_squared + par3 * sin_squared + par2 * cos_sin;
  double Avv         = par1 * sin_squared + par3 * cos_squared - par2 * cos_sin;

  double tuCentre    = - Au/(2*Auu);
  double tvCentre    = - Av/(2*Avv);

  double uCentre     = tuCentre * cost - tvCentre * sint;
  double vCentre     = tuCentre * sint + tvCentre * cost;

  double qt1 = cost*(cost*q1 + q2*sint) + sint*(cost*q2 + q4*sint);
  double qt2 = cost*(cost*q2 + q4*sint) - sint*(cost*q1 + q2*sint);
  double qt3 = cost*q3 + q5*sint + uCentre*(cost*q1 + q2*sint) + vCentre*(cost*q2 + q4*sint);
  double qt4 = cost*(cost*q4 - q2*sint) - sint*(cost*q2 - q1*sint);
  double qt5 = cost*q5 - q3*sint + uCentre*(cost*q2 - q1*sint) + vCentre*(cost*q4 - q2*sint);
  double qt6 =  q6 + uCentre*(q3 + q1*uCentre + q2*vCentre) + vCentre*(q5 + q2*uCentre + q4*vCentre) + q3*uCentre + q5*vCentre;

  mCanonic(0,0) = qt1;    mCanonic(0,1) = qt2;   mCanonic(0,2) = qt3;
  mCanonic(1,0) = qt2;    mCanonic(1,1) = qt4;   mCanonic(1,2) = qt5;
  mCanonic(2,0) = qt3;    mCanonic(2,1) = qt5;   mCanonic(2,2) = qt6;

  mTprimal(0,0) = cost;   mTprimal(0,1) = sint;  mTprimal(0,2) = - cost*uCentre - sint*vCentre;
  mTprimal(1,0) = -sint;  mTprimal(1,1) = cost;  mTprimal(1,2) = sint*uCentre - cost*vCentre;
  mTprimal(2,0) = 0;      mTprimal(2,1) = 0;     mTprimal(2,2) = cost*cost + sint*sint;

  mTdual(0,0) = cost;     mTdual(0,1) = -sint;   mTdual(0,2) = uCentre;
  mTdual(1,0) = sint;     mTdual(1,1) = cost;    mTdual(1,2) = vCentre;
  mTdual(2,0) = 0;        mTdual(2,1) = 0;       mTdual(2,2) = 1.0;

}

void Ellipse::computeMatrix()
{
  bounded_matrix<double, 3, 3> tmp;
  tmp( 0, 0 ) = std::cos( _angle ); tmp( 0, 1 ) = -std::sin( _angle ); tmp( 0, 2 ) = _center.x();
  tmp( 1, 0 ) = std::sin( _angle ); tmp( 1, 1 ) =  std::cos( _angle ); tmp( 1, 2 ) = _center.y();
  tmp( 2, 0 ) =             0.0; tmp( 2, 1 ) =              0.0; tmp( 2, 2 ) =        1.0;

  bounded_matrix<double, 3, 3> tmpInv;
  diagonal_matrix<double> diag( 3, 3 );
  diag( 0, 0 ) =  1.0 / ( _a * _a );
  diag( 1, 1 ) =  1.0 / ( _b * _b );
  diag( 2, 2 ) = -1.0;

  if( invert( tmp, tmpInv ) )
  {
          _matrix = prec_prod( diag, tmpInv );
          _matrix = prec_prod( trans( tmpInv ), _matrix );
  }
  else
  {
          CCTAG_THROW( exception::Bug()
                          << exception::dev( "Singular matrix!" ) );
  }
}

void scale(const Ellipse & ellipse, Ellipse & rescaleEllipse, double scale)
{
  rescaleEllipse.setCenter(Point2dN<double>( ellipse.center().x() * scale, ellipse.center().y() * scale ));
  rescaleEllipse.setA(ellipse.a() * scale);
  rescaleEllipse.setB(ellipse.b() * scale);
  rescaleEllipse.setAngle(ellipse.angle());
}

std::ostream& operator<<(std::ostream& os, const Ellipse& e)
{
  os  << "e = [ " << e.matrix()(0,0) << " " << e.matrix()(0,1) << " " << e.matrix()(0,2) << " ; "
      << e.matrix()(1,0) << " " << e.matrix()(1,1) << " " << e.matrix()(1,2) << " ; "
      << e.matrix()(2,0) << " " << e.matrix()(2,1) << " " << e.matrix()(2,2) << " ] ";
  return os;
}

/*
 * @brief Sort a set of points by angle along an elliptical arc. Possibly return a subset of these
 *        points if requested.
 */
void getSortedOuterPoints(
        const Ellipse & ellipse,
        const std::vector< cctag::DirectedPoint2d<double> > & points,
        std::vector< cctag::DirectedPoint2d<double> > & resPoints,
        const std::size_t requestedSize)
{
  // map with the key = angle and the point index
  // Sort points in points by angle
  //std::map<double, std::size_t> mapAngle;
  std::vector< std::pair<double, std::size_t> > vAngles;
  vAngles.reserve(points.size());
  for(std::size_t iPoint = 0 ; iPoint < points.size() ; ++iPoint)
  {
    double angle = atan2( ellipse.center().y() - points[iPoint].y() , ellipse.center().x() - points[iPoint].x() );
    //mapAngle.emplace(angle, iPoint);

    vAngles.emplace_back(angle, iPoint);
  }

  std::sort (vAngles.begin(), vAngles.end());

  // Get the final expected size of resPoints
  const std::size_t nOuterPoints = std::min( requestedSize, points.size() );
  std::size_t step = std::size_t( points.size() / ( nOuterPoints - 1 ) );

  resPoints.clear();
  resPoints.reserve(nOuterPoints);

  // Get the final expected size of resPoints

  for(std::size_t iPoint = 0 ; iPoint < points.size() ; iPoint += step)
  {
    resPoints.push_back(points[vAngles[iPoint].second]);
  }
}

}
}
}
<|endoftext|>


<commit_before>//===-- llvm-config.cpp - LLVM project configuration utility --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tool encapsulates information about an LLVM project configuration for
// use by other project's build environments (to determine installed path,
// available features, required libraries, etc.).
//
// Note that although this tool *may* be used by some parts of LLVM's build
// itself (i.e., the Makefiles use it to compute required libraries when linking
// tools), this tool is primarily designed to support external projects.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <set>
#include <vector>

using namespace llvm;

// Include the build time variables we can report to the user. This is generated
// at build time from the BuildVariables.inc.in file by the build system.
#include "BuildVariables.inc"

// Include the component table. This creates an array of struct
// AvailableComponent entries, which record the component name, library name,
// and required components for all of the available libraries.
//
// Not all components define a library, we also use "library groups" as a way to
// create entries for pseudo groups like x86 or all-targets.
#include "LibraryDependencies.inc"

/// \brief Traverse a single component adding to the topological ordering in
/// \arg RequiredLibs.
///
/// \param Name - The component to traverse.
/// \param ComponentMap - A prebuilt map of component names to descriptors.
/// \param VisitedComponents [in] [out] - The set of already visited components.
/// \param RequiredLibs [out] - The ordered list of required libraries.
static void VisitComponent(StringRef Name,
                           const StringMap<AvailableComponent*> &ComponentMap,
                           std::set<AvailableComponent*> &VisitedComponents,
                           std::vector<StringRef> &RequiredLibs) {
  // Lookup the component.
  AvailableComponent *AC = ComponentMap.lookup(Name);
  assert(AC && "Invalid component name!");

  // Add to the visited table.
  if (!VisitedComponents.insert(AC).second) {
    // We are done if the component has already been visited.
    return;
  }

  // Otherwise, visit all the dependencies.
  for (unsigned i = 0; AC->RequiredLibraries[i]; ++i) {
    VisitComponent(AC->RequiredLibraries[i], ComponentMap, VisitedComponents,
                   RequiredLibs);
  }

  // Add to the required library list.
  if (AC->Library)
    RequiredLibs.push_back(AC->Library);
}

/// \brief Compute the list of required libraries for a given list of
/// components, in an order suitable for passing to a linker (that is, libraries
/// appear prior to their dependencies).
///
/// \param Components - The names of the components to find libraries for.
/// \param RequiredLibs [out] - On return, the ordered list of libraries that
/// are required to link the given components.
void ComputeLibsForComponents(const std::vector<StringRef> &Components,
                              std::vector<StringRef> &RequiredLibs) {
  std::set<AvailableComponent*> VisitedComponents;

  // Build a map of component names to information.
  StringMap<AvailableComponent*> ComponentMap;
  for (unsigned i = 0; i != array_lengthof(AvailableComponents); ++i) {
    AvailableComponent *AC = &AvailableComponents[i];
    ComponentMap[AC->Name] = AC;
  }

  // Visit the components.
  for (unsigned i = 0, e = Components.size(); i != e; ++i) {
    // Users are allowed to provide mixed case component names.
    std::string ComponentLower = Components[i].lower();

    // Validate that the user supplied a valid component name.
    if (!ComponentMap.count(ComponentLower)) {
      llvm::errs() << "llvm-config: unknown component name: " << Components[i]
                   << "\n";
      exit(1);
    }

    VisitComponent(ComponentLower, ComponentMap, VisitedComponents,
                   RequiredLibs);
  }

  // The list is now ordered with leafs first, we want the libraries to printed
  // in the reverse order of dependency.
  std::reverse(RequiredLibs.begin(), RequiredLibs.end());
}

/* *** */

void usage() {
  errs() << "\
usage: llvm-config <OPTION>... [<COMPONENT>...]\n\
\n\
Get various configuration information needed to compile programs which use\n\
LLVM.  Typically called from 'configure' scripts.  Examples:\n\
  llvm-config --cxxflags\n\
  llvm-config --ldflags\n\
  llvm-config --libs engine bcreader scalaropts\n\
\n\
Options:\n\
  --version         Print LLVM version.\n\
  --prefix          Print the installation prefix.\n\
  --src-root        Print the source root LLVM was built from.\n\
  --obj-root        Print the object root used to build LLVM.\n\
  --bindir          Directory containing LLVM executables.\n\
  --includedir      Directory containing LLVM headers.\n\
  --libdir          Directory containing LLVM libraries.\n\
  --cppflags        C preprocessor flags for files that include LLVM headers.\n\
  --cflags          C compiler flags for files that include LLVM headers.\n\
  --cxxflags        C++ compiler flags for files that include LLVM headers.\n\
  --ldflags         Print Linker flags.\n\
  --libs            Libraries needed to link against LLVM components.\n\
  --libnames        Bare library names for in-tree builds.\n\
  --libfiles        Fully qualified library filenames for makefile depends.\n\
  --components      List of all possible components.\n\
  --targets-built   List of all targets currently built.\n\
  --host-target     Target triple used to configure LLVM.\n\
  --build-mode      Print build mode of LLVM tree (e.g. Debug or Release).\n\
Typical components:\n\
  all               All LLVM libraries (default).\n\
  backend           Either a native backend or the C backend.\n\
  engine            Either a native JIT or a bitcode interpreter.\n";
  exit(1);
}

/// \brief Compute the path to the main executable.
llvm::sys::Path GetExecutablePath(const char *Argv0) {
  // This just needs to be some symbol in the binary; C++ doesn't
  // allow taking the address of ::main however.
  void *P = (void*) (intptr_t) GetExecutablePath;
  return llvm::sys::Path::GetMainExecutable(Argv0, P);
}

int main(int argc, char **argv) {
  std::vector<StringRef> Components;
  bool PrintLibs = false, PrintLibNames = false, PrintLibFiles = false;
  bool HasAnyOption = false;

  // llvm-config is designed to support being run both from a development tree
  // and from an installed path. We try and auto-detect which case we are in so
  // that we can report the correct information when run from a development
  // tree.
  bool IsInDevelopmentTree, DevelopmentTreeLayoutIsCMakeStyle;
  llvm::SmallString<256> CurrentPath(GetExecutablePath(argv[0]).str());
  std::string CurrentExecPrefix;
  std::string ActiveObjRoot;

  // Create an absolute path, and pop up one directory (we expect to be inside a
  // bin dir).
  sys::fs::make_absolute(CurrentPath);
  CurrentExecPrefix = sys::path::parent_path(
    sys::path::parent_path(CurrentPath)).str();

  // Check to see if we are inside a development tree by comparing to possible
  // locations (prefix style or CMake style). This could be wrong in the face of
  // symbolic links, but is good enough.
  if (CurrentExecPrefix == std::string(LLVM_OBJ_ROOT) + "/" + LLVM_BUILDMODE) {
    IsInDevelopmentTree = true;
    DevelopmentTreeLayoutIsCMakeStyle = false;

    // If we are in a development tree, then check if we are in a BuildTools
    // directory. This indicates we are built for the build triple, but we
    // always want to provide information for the host triple.
    if (sys::path::filename(LLVM_OBJ_ROOT) == "BuildTools") {
      ActiveObjRoot = sys::path::parent_path(LLVM_OBJ_ROOT);
    } else {
      ActiveObjRoot = LLVM_OBJ_ROOT;
    }
  } else if (CurrentExecPrefix == std::string(LLVM_OBJ_ROOT) + "/bin") {
    IsInDevelopmentTree = true;
    DevelopmentTreeLayoutIsCMakeStyle = true;
    ActiveObjRoot = LLVM_OBJ_ROOT;
  } else {
    IsInDevelopmentTree = false;
  }

  // Compute various directory locations based on the derived location
  // information.
  std::string ActivePrefix, ActiveBinDir, ActiveIncludeDir, ActiveLibDir;
  std::string ActiveIncludeOption;
  if (IsInDevelopmentTree) {
    ActivePrefix = CurrentExecPrefix;

    // CMake organizes the products differently than a normal prefix style
    // layout.
    if (DevelopmentTreeLayoutIsCMakeStyle) {
      ActiveIncludeDir = ActiveObjRoot + "/include";
      ActiveBinDir = ActiveObjRoot + "/bin/" + LLVM_BUILDMODE;
      ActiveLibDir = ActiveObjRoot + "/lib/" + LLVM_BUILDMODE;
    } else {
      ActiveIncludeDir = ActiveObjRoot + "/include";
      ActiveBinDir = ActiveObjRoot + "/" + LLVM_BUILDMODE + "/bin";
      ActiveLibDir = ActiveObjRoot + "/" + LLVM_BUILDMODE + "/lib";
    }

    // We need to include files from both the source and object trees.
    ActiveIncludeOption = ("-I" + ActiveIncludeDir + " " +
                           "-I" + ActiveObjRoot + "/include");
  } else {
    ActivePrefix = CurrentExecPrefix;
    ActiveIncludeDir = ActivePrefix + "/include";
    ActiveBinDir = ActivePrefix + "/bin";
    ActiveLibDir = ActivePrefix + "/lib";
    ActiveIncludeOption = "-I" + ActiveIncludeDir;
  }

  raw_ostream &OS = outs();
  for (int i = 1; i != argc; ++i) {
    StringRef Arg = argv[i];

    if (Arg.startswith("-")) {
      HasAnyOption = true;
      if (Arg == "--version") {
        OS << PACKAGE_VERSION << '\n';
      } else if (Arg == "--prefix") {
        OS << ActivePrefix << '\n';
      } else if (Arg == "--bindir") {
        OS << ActiveBinDir << '\n';
      } else if (Arg == "--includedir") {
        OS << ActiveIncludeDir << '\n';
      } else if (Arg == "--libdir") {
        OS << ActiveLibDir << '\n';
      } else if (Arg == "--cppflags") {
        OS << ActiveIncludeOption << ' ' << LLVM_CPPFLAGS << '\n';
      } else if (Arg == "--cflags") {
        OS << ActiveIncludeOption << ' ' << LLVM_CFLAGS << '\n';
      } else if (Arg == "--cxxflags") {
        OS << ActiveIncludeOption << ' ' << LLVM_CXXFLAGS << '\n';
      } else if (Arg == "--ldflags") {
        OS << "-L" << ActiveLibDir << ' ' << LLVM_LDFLAGS
           << ' ' << LLVM_SYSTEM_LIBS << '\n';
      } else if (Arg == "--libs") {
        PrintLibs = true;
      } else if (Arg == "--libnames") {
        PrintLibNames = true;
      } else if (Arg == "--libfiles") {
        PrintLibFiles = true;
      } else if (Arg == "--components") {
        for (unsigned j = 0; j != array_lengthof(AvailableComponents); ++j) {
          OS << ' ';
          OS << AvailableComponents[j].Name;
        }
        OS << '\n';
      } else if (Arg == "--targets-built") {
        bool First = true;
        for (TargetRegistry::iterator I = TargetRegistry::begin(),
               E = TargetRegistry::end(); I != E; First = false, ++I) {
          if (!First)
            OS << ' ';
          OS << I->getName();
        }
        OS << '\n';
      } else if (Arg == "--host-target") {
        OS << LLVM_DEFAULT_TARGET_TRIPLE << '\n';
      } else if (Arg == "--build-mode") {
        OS << LLVM_BUILDMODE << '\n';
      } else if (Arg == "--obj-root") {
        OS << LLVM_OBJ_ROOT << '\n';
      } else if (Arg == "--src-root") {
        OS << LLVM_SRC_ROOT << '\n';
      } else {
        usage();
      }
    } else {
      Components.push_back(Arg);
    }
  }

  if (!HasAnyOption)
    usage();

  if (PrintLibs || PrintLibNames || PrintLibFiles) {
    // Construct the list of all the required libraries.
    std::vector<StringRef> RequiredLibs;
    ComputeLibsForComponents(Components, RequiredLibs);

    for (unsigned i = 0, e = RequiredLibs.size(); i != e; ++i) {
      StringRef Lib = RequiredLibs[i];
      if (i)
        OS << ' ';

      if (PrintLibNames) {
        OS << Lib;
      } else if (PrintLibFiles) {
        OS << ActiveLibDir << '/' << Lib;
      } else if (PrintLibs) {
        // If this is a typical library name, include it using -l.
        if (Lib.startswith("lib") && Lib.endswith(".a")) {
          OS << "-l" << Lib.slice(3, Lib.size()-2);
          continue;
        }

        // Otherwise, print the full path.
        OS << ActiveLibDir << '/' << Lib;
      }
    }
    OS << '\n';
  } else if (!Components.empty()) {
    errs() << "llvm-config: error: components given, but unused\n\n";
    usage();
  }

  return 0;
}
<commit_msg>llvm-config-2: Fix --cflags and --includedir which pointed at the wrong directory when running from a build directory.<commit_after>//===-- llvm-config.cpp - LLVM project configuration utility --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tool encapsulates information about an LLVM project configuration for
// use by other project's build environments (to determine installed path,
// available features, required libraries, etc.).
//
// Note that although this tool *may* be used by some parts of LLVM's build
// itself (i.e., the Makefiles use it to compute required libraries when linking
// tools), this tool is primarily designed to support external projects.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <set>
#include <vector>

using namespace llvm;

// Include the build time variables we can report to the user. This is generated
// at build time from the BuildVariables.inc.in file by the build system.
#include "BuildVariables.inc"

// Include the component table. This creates an array of struct
// AvailableComponent entries, which record the component name, library name,
// and required components for all of the available libraries.
//
// Not all components define a library, we also use "library groups" as a way to
// create entries for pseudo groups like x86 or all-targets.
#include "LibraryDependencies.inc"

/// \brief Traverse a single component adding to the topological ordering in
/// \arg RequiredLibs.
///
/// \param Name - The component to traverse.
/// \param ComponentMap - A prebuilt map of component names to descriptors.
/// \param VisitedComponents [in] [out] - The set of already visited components.
/// \param RequiredLibs [out] - The ordered list of required libraries.
static void VisitComponent(StringRef Name,
                           const StringMap<AvailableComponent*> &ComponentMap,
                           std::set<AvailableComponent*> &VisitedComponents,
                           std::vector<StringRef> &RequiredLibs) {
  // Lookup the component.
  AvailableComponent *AC = ComponentMap.lookup(Name);
  assert(AC && "Invalid component name!");

  // Add to the visited table.
  if (!VisitedComponents.insert(AC).second) {
    // We are done if the component has already been visited.
    return;
  }

  // Otherwise, visit all the dependencies.
  for (unsigned i = 0; AC->RequiredLibraries[i]; ++i) {
    VisitComponent(AC->RequiredLibraries[i], ComponentMap, VisitedComponents,
                   RequiredLibs);
  }

  // Add to the required library list.
  if (AC->Library)
    RequiredLibs.push_back(AC->Library);
}

/// \brief Compute the list of required libraries for a given list of
/// components, in an order suitable for passing to a linker (that is, libraries
/// appear prior to their dependencies).
///
/// \param Components - The names of the components to find libraries for.
/// \param RequiredLibs [out] - On return, the ordered list of libraries that
/// are required to link the given components.
void ComputeLibsForComponents(const std::vector<StringRef> &Components,
                              std::vector<StringRef> &RequiredLibs) {
  std::set<AvailableComponent*> VisitedComponents;

  // Build a map of component names to information.
  StringMap<AvailableComponent*> ComponentMap;
  for (unsigned i = 0; i != array_lengthof(AvailableComponents); ++i) {
    AvailableComponent *AC = &AvailableComponents[i];
    ComponentMap[AC->Name] = AC;
  }

  // Visit the components.
  for (unsigned i = 0, e = Components.size(); i != e; ++i) {
    // Users are allowed to provide mixed case component names.
    std::string ComponentLower = Components[i].lower();

    // Validate that the user supplied a valid component name.
    if (!ComponentMap.count(ComponentLower)) {
      llvm::errs() << "llvm-config: unknown component name: " << Components[i]
                   << "\n";
      exit(1);
    }

    VisitComponent(ComponentLower, ComponentMap, VisitedComponents,
                   RequiredLibs);
  }

  // The list is now ordered with leafs first, we want the libraries to printed
  // in the reverse order of dependency.
  std::reverse(RequiredLibs.begin(), RequiredLibs.end());
}

/* *** */

void usage() {
  errs() << "\
usage: llvm-config <OPTION>... [<COMPONENT>...]\n\
\n\
Get various configuration information needed to compile programs which use\n\
LLVM.  Typically called from 'configure' scripts.  Examples:\n\
  llvm-config --cxxflags\n\
  llvm-config --ldflags\n\
  llvm-config --libs engine bcreader scalaropts\n\
\n\
Options:\n\
  --version         Print LLVM version.\n\
  --prefix          Print the installation prefix.\n\
  --src-root        Print the source root LLVM was built from.\n\
  --obj-root        Print the object root used to build LLVM.\n\
  --bindir          Directory containing LLVM executables.\n\
  --includedir      Directory containing LLVM headers.\n\
  --libdir          Directory containing LLVM libraries.\n\
  --cppflags        C preprocessor flags for files that include LLVM headers.\n\
  --cflags          C compiler flags for files that include LLVM headers.\n\
  --cxxflags        C++ compiler flags for files that include LLVM headers.\n\
  --ldflags         Print Linker flags.\n\
  --libs            Libraries needed to link against LLVM components.\n\
  --libnames        Bare library names for in-tree builds.\n\
  --libfiles        Fully qualified library filenames for makefile depends.\n\
  --components      List of all possible components.\n\
  --targets-built   List of all targets currently built.\n\
  --host-target     Target triple used to configure LLVM.\n\
  --build-mode      Print build mode of LLVM tree (e.g. Debug or Release).\n\
Typical components:\n\
  all               All LLVM libraries (default).\n\
  backend           Either a native backend or the C backend.\n\
  engine            Either a native JIT or a bitcode interpreter.\n";
  exit(1);
}

/// \brief Compute the path to the main executable.
llvm::sys::Path GetExecutablePath(const char *Argv0) {
  // This just needs to be some symbol in the binary; C++ doesn't
  // allow taking the address of ::main however.
  void *P = (void*) (intptr_t) GetExecutablePath;
  return llvm::sys::Path::GetMainExecutable(Argv0, P);
}

int main(int argc, char **argv) {
  std::vector<StringRef> Components;
  bool PrintLibs = false, PrintLibNames = false, PrintLibFiles = false;
  bool HasAnyOption = false;

  // llvm-config is designed to support being run both from a development tree
  // and from an installed path. We try and auto-detect which case we are in so
  // that we can report the correct information when run from a development
  // tree.
  bool IsInDevelopmentTree, DevelopmentTreeLayoutIsCMakeStyle;
  llvm::SmallString<256> CurrentPath(GetExecutablePath(argv[0]).str());
  std::string CurrentExecPrefix;
  std::string ActiveObjRoot;

  // Create an absolute path, and pop up one directory (we expect to be inside a
  // bin dir).
  sys::fs::make_absolute(CurrentPath);
  CurrentExecPrefix = sys::path::parent_path(
    sys::path::parent_path(CurrentPath)).str();

  // Check to see if we are inside a development tree by comparing to possible
  // locations (prefix style or CMake style). This could be wrong in the face of
  // symbolic links, but is good enough.
  if (CurrentExecPrefix == std::string(LLVM_OBJ_ROOT) + "/" + LLVM_BUILDMODE) {
    IsInDevelopmentTree = true;
    DevelopmentTreeLayoutIsCMakeStyle = false;

    // If we are in a development tree, then check if we are in a BuildTools
    // directory. This indicates we are built for the build triple, but we
    // always want to provide information for the host triple.
    if (sys::path::filename(LLVM_OBJ_ROOT) == "BuildTools") {
      ActiveObjRoot = sys::path::parent_path(LLVM_OBJ_ROOT);
    } else {
      ActiveObjRoot = LLVM_OBJ_ROOT;
    }
  } else if (CurrentExecPrefix == std::string(LLVM_OBJ_ROOT) + "/bin") {
    IsInDevelopmentTree = true;
    DevelopmentTreeLayoutIsCMakeStyle = true;
    ActiveObjRoot = LLVM_OBJ_ROOT;
  } else {
    IsInDevelopmentTree = false;
  }

  // Compute various directory locations based on the derived location
  // information.
  std::string ActivePrefix, ActiveBinDir, ActiveIncludeDir, ActiveLibDir;
  std::string ActiveIncludeOption;
  if (IsInDevelopmentTree) {
    ActiveIncludeDir = std::string(LLVM_SRC_ROOT) + "/include";
    ActivePrefix = CurrentExecPrefix;

    // CMake organizes the products differently than a normal prefix style
    // layout.
    if (DevelopmentTreeLayoutIsCMakeStyle) {
      ActiveBinDir = ActiveObjRoot + "/bin/" + LLVM_BUILDMODE;
      ActiveLibDir = ActiveObjRoot + "/lib/" + LLVM_BUILDMODE;
    } else {
      ActiveBinDir = ActiveObjRoot + "/" + LLVM_BUILDMODE + "/bin";
      ActiveLibDir = ActiveObjRoot + "/" + LLVM_BUILDMODE + "/lib";
    }

    // We need to include files from both the source and object trees.
    ActiveIncludeOption = ("-I" + ActiveIncludeDir + " " +
                           "-I" + ActiveObjRoot + "/include");
  } else {
    ActivePrefix = CurrentExecPrefix;
    ActiveIncludeDir = ActivePrefix + "/include";
    ActiveBinDir = ActivePrefix + "/bin";
    ActiveLibDir = ActivePrefix + "/lib";
    ActiveIncludeOption = "-I" + ActiveIncludeDir;
  }

  raw_ostream &OS = outs();
  for (int i = 1; i != argc; ++i) {
    StringRef Arg = argv[i];

    if (Arg.startswith("-")) {
      HasAnyOption = true;
      if (Arg == "--version") {
        OS << PACKAGE_VERSION << '\n';
      } else if (Arg == "--prefix") {
        OS << ActivePrefix << '\n';
      } else if (Arg == "--bindir") {
        OS << ActiveBinDir << '\n';
      } else if (Arg == "--includedir") {
        OS << ActiveIncludeDir << '\n';
      } else if (Arg == "--libdir") {
        OS << ActiveLibDir << '\n';
      } else if (Arg == "--cppflags") {
        OS << ActiveIncludeOption << ' ' << LLVM_CPPFLAGS << '\n';
      } else if (Arg == "--cflags") {
        OS << ActiveIncludeOption << ' ' << LLVM_CFLAGS << '\n';
      } else if (Arg == "--cxxflags") {
        OS << ActiveIncludeOption << ' ' << LLVM_CXXFLAGS << '\n';
      } else if (Arg == "--ldflags") {
        OS << "-L" << ActiveLibDir << ' ' << LLVM_LDFLAGS
           << ' ' << LLVM_SYSTEM_LIBS << '\n';
      } else if (Arg == "--libs") {
        PrintLibs = true;
      } else if (Arg == "--libnames") {
        PrintLibNames = true;
      } else if (Arg == "--libfiles") {
        PrintLibFiles = true;
      } else if (Arg == "--components") {
        for (unsigned j = 0; j != array_lengthof(AvailableComponents); ++j) {
          OS << ' ';
          OS << AvailableComponents[j].Name;
        }
        OS << '\n';
      } else if (Arg == "--targets-built") {
        bool First = true;
        for (TargetRegistry::iterator I = TargetRegistry::begin(),
               E = TargetRegistry::end(); I != E; First = false, ++I) {
          if (!First)
            OS << ' ';
          OS << I->getName();
        }
        OS << '\n';
      } else if (Arg == "--host-target") {
        OS << LLVM_DEFAULT_TARGET_TRIPLE << '\n';
      } else if (Arg == "--build-mode") {
        OS << LLVM_BUILDMODE << '\n';
      } else if (Arg == "--obj-root") {
        OS << LLVM_OBJ_ROOT << '\n';
      } else if (Arg == "--src-root") {
        OS << LLVM_SRC_ROOT << '\n';
      } else {
        usage();
      }
    } else {
      Components.push_back(Arg);
    }
  }

  if (!HasAnyOption)
    usage();

  if (PrintLibs || PrintLibNames || PrintLibFiles) {
    // Construct the list of all the required libraries.
    std::vector<StringRef> RequiredLibs;
    ComputeLibsForComponents(Components, RequiredLibs);

    for (unsigned i = 0, e = RequiredLibs.size(); i != e; ++i) {
      StringRef Lib = RequiredLibs[i];
      if (i)
        OS << ' ';

      if (PrintLibNames) {
        OS << Lib;
      } else if (PrintLibFiles) {
        OS << ActiveLibDir << '/' << Lib;
      } else if (PrintLibs) {
        // If this is a typical library name, include it using -l.
        if (Lib.startswith("lib") && Lib.endswith(".a")) {
          OS << "-l" << Lib.slice(3, Lib.size()-2);
          continue;
        }

        // Otherwise, print the full path.
        OS << ActiveLibDir << '/' << Lib;
      }
    }
    OS << '\n';
  } else if (!Components.empty()) {
    errs() << "llvm-config: error: components given, but unused\n\n";
    usage();
  }

  return 0;
}
<|endoftext|>