<commit_before>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkottieSlide.h"

#include "SkAnimTimer.h"
#include "SkCanvas.h"
#include "Skottie.h"

SkottieSlide::SkottieSlide(const SkString& name, const SkString& path)
    : fPath(path) {
    fName = name;
}

void SkottieSlide::load(SkScalar w, SkScalar h) {
    fAnimation  = skottie::Animation::MakeFromFile(fPath.c_str());
    fWinSize    = SkSize::Make(w, h);
    fTimeBase   = 0; // force a time reset

    if (fAnimation) {
        fAnimation->setShowInval(fShowAnimationInval);
        SkDebugf("loaded Bodymovin animation v: %s, size: [%f %f], fr: %f\n",
                 fAnimation->version().c_str(),
                 fAnimation->size().width(),
                 fAnimation->size().height(),
                 fAnimation->frameRate());
    } else {
        SkDebugf("failed to load Bodymovin animation: %s\n", fPath.c_str());
    }
}

void SkottieSlide::unload() {
    fAnimation.reset();
}

SkISize SkottieSlide::getDimensions() const {
    // We always scale to fill the window.
    return fWinSize.toCeil();
}

void SkottieSlide::draw(SkCanvas* canvas) {
    if (fAnimation) {
        SkAutoCanvasRestore acr(canvas, true);
        const auto dstR = SkRect::MakeSize(fWinSize);
        fAnimation->render(canvas, &dstR);
    }
}

bool SkottieSlide::animate(const SkAnimTimer& timer) {
    if (fTimeBase == 0) {
        // Reset the animation time.
        fTimeBase = timer.msec();
    }

    if (fAnimation) {
        auto t = timer.msec() - fTimeBase;
        fAnimation->animationTick(t);
    }
    return true;
}

bool SkottieSlide::onChar(SkUnichar c) {
    switch (c) {
    case 'I':
        if (fAnimation) {
            fShowAnimationInval = !fShowAnimationInval;
            fAnimation->setShowInval(fShowAnimationInval);
        }
        break;
    default:
        break;
    }

    return INHERITED::onChar(c);
}

bool SkottieSlide::onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state, uint32_t) {
    switch (state) {
    case sk_app::Window::kUp_InputState:
        fShowAnimationInval = !fShowAnimationInval;
        fAnimation->setShowInval(fShowAnimationInval);
        break;
    default:
        break;
    }

    return true;
}
<commit_msg>Don't consume mouse events in SkottieSlide<commit_after>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkottieSlide.h"

#include "SkAnimTimer.h"
#include "SkCanvas.h"
#include "Skottie.h"

SkottieSlide::SkottieSlide(const SkString& name, const SkString& path)
    : fPath(path) {
    fName = name;
}

void SkottieSlide::load(SkScalar w, SkScalar h) {
    fAnimation  = skottie::Animation::MakeFromFile(fPath.c_str());
    fWinSize    = SkSize::Make(w, h);
    fTimeBase   = 0; // force a time reset

    if (fAnimation) {
        fAnimation->setShowInval(fShowAnimationInval);
        SkDebugf("loaded Bodymovin animation v: %s, size: [%f %f], fr: %f\n",
                 fAnimation->version().c_str(),
                 fAnimation->size().width(),
                 fAnimation->size().height(),
                 fAnimation->frameRate());
    } else {
        SkDebugf("failed to load Bodymovin animation: %s\n", fPath.c_str());
    }
}

void SkottieSlide::unload() {
    fAnimation.reset();
}

SkISize SkottieSlide::getDimensions() const {
    // We always scale to fill the window.
    return fWinSize.toCeil();
}

void SkottieSlide::draw(SkCanvas* canvas) {
    if (fAnimation) {
        SkAutoCanvasRestore acr(canvas, true);
        const auto dstR = SkRect::MakeSize(fWinSize);
        fAnimation->render(canvas, &dstR);
    }
}

bool SkottieSlide::animate(const SkAnimTimer& timer) {
    if (fTimeBase == 0) {
        // Reset the animation time.
        fTimeBase = timer.msec();
    }

    if (fAnimation) {
        auto t = timer.msec() - fTimeBase;
        fAnimation->animationTick(t);
    }
    return true;
}

bool SkottieSlide::onChar(SkUnichar c) {
    switch (c) {
    case 'I':
        if (fAnimation) {
            fShowAnimationInval = !fShowAnimationInval;
            fAnimation->setShowInval(fShowAnimationInval);
        }
        break;
    default:
        break;
    }

    return INHERITED::onChar(c);
}

bool SkottieSlide::onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state, uint32_t) {
    switch (state) {
    case sk_app::Window::kUp_InputState:
        fShowAnimationInval = !fShowAnimationInval;
        fAnimation->setShowInval(fShowAnimationInval);
        break;
    default:
        break;
    }

    return false;
}
<|endoftext|>


<commit_before>// Copyright 2017 Global Phasing Ltd.
//
// Read any supported coordinate file.

#ifndef GEMMI_MMREAD_HPP_
#define GEMMI_MMREAD_HPP_

#include "chemcomp_xyz.hpp" // for make_structure_from_chemcomp_block
#include "cif.hpp"       // for cif::read
#include "fail.hpp"      // for fail
#include "input.hpp"     // for BasicInput
#include "json.hpp"      // for read_mmjson
#include "mmcif.hpp"     // for make_structure_from_block
#include "model.hpp"     // for Structure
#include "pdb.hpp"       // for read_pdb
#include "util.hpp"      // for iends_with

namespace gemmi {

inline CoorFormat coor_format_from_ext(const std::string& path) {
  if (iends_with(path, ".pdb") || iends_with(path, ".ent"))
    return CoorFormat::Pdb;
  if (iends_with(path, ".cif") || iends_with(path, ".mmcif"))
    return CoorFormat::Mmcif;
  if (iends_with(path, ".json"))
    return CoorFormat::Mmjson;
  return CoorFormat::Unknown;
}

template<typename T>
Structure read_structure(T&& input, CoorFormat format=CoorFormat::Unknown) {
  bool any = (format == CoorFormat::UnknownAny);
  if (format == CoorFormat::Unknown || any)
    format = coor_format_from_ext(input.basepath());
  switch (format) {
    case CoorFormat::Pdb:
      return read_pdb(input);
    case CoorFormat::Mmcif: {
      cif::Document doc = cif::read(input);
      if (any) {
        int n = check_chemcomp_block_number(doc);
        // first handle special case - refmac dictionary or CCD file
        if (n != -1)
          return make_structure_from_chemcomp_block(doc.blocks[n]);
      }
      return make_structure(doc);
    }
    case CoorFormat::Mmjson:
      return make_structure_from_block(cif::read_mmjson(input).sole_block());
    case CoorFormat::ChemComp:
      return make_structure_from_chemcomp_doc(cif::read(input));
    case CoorFormat::Unknown:
    case CoorFormat::UnknownAny:
      fail("Unknown format of " +
           (input.path().empty() ? "coordinate file" : input.path()) + ".");
  }
  unreachable();
}

inline Structure read_structure_file(const std::string& path,
                                     CoorFormat format=CoorFormat::Unknown) {
  return read_structure(BasicInput(path), format);
}

} // namespace gemmi
#endif
<commit_msg>read_structure: optional format detection from the content<commit_after>// Copyright 2017 Global Phasing Ltd.
//
// Read any supported coordinate file.

#ifndef GEMMI_MMREAD_HPP_
#define GEMMI_MMREAD_HPP_

#include "chemcomp_xyz.hpp" // for make_structure_from_chemcomp_block
#include "cif.hpp"       // for cif::read
#include "fail.hpp"      // for fail
#include "input.hpp"     // for BasicInput
#include "json.hpp"      // for read_mmjson
#include "mmcif.hpp"     // for make_structure_from_block
#include "model.hpp"     // for Structure
#include "pdb.hpp"       // for read_pdb
#include "util.hpp"      // for iends_with

namespace gemmi {

inline CoorFormat coor_format_from_ext(const std::string& path) {
  if (iends_with(path, ".pdb") || iends_with(path, ".ent"))
    return CoorFormat::Pdb;
  if (iends_with(path, ".cif") || iends_with(path, ".mmcif"))
    return CoorFormat::Mmcif;
  if (iends_with(path, ".json"))
    return CoorFormat::Mmjson;
  return CoorFormat::Unknown;
}

// If it's neither CIF nor JSON nor almost empty - we assume PDB.
inline CoorFormat coor_format_from_content(const char* buf, const char* end) {
  while (buf < end - 8) {
    if (std::isspace(*buf)) {
      ++buf;
    } else if (*buf == '#') {
      while (buf < end - 8 && *buf != '\n')
        ++buf;
    } else if (*buf == '{') {
      return CoorFormat::Mmjson;
    } else if (ialpha4_id(buf) == ialpha4_id("data") && buf[4] == '_') {
      return CoorFormat::Mmcif;
    } else {
      return CoorFormat::Pdb;
    }
  }
  return CoorFormat::Unknown;
}

inline Structure make_structure_from_doc(const cif::Document& doc, bool possible_chemcomp) {
  if (possible_chemcomp) {
    // check for special case - refmac dictionary or CCD file
    int n = check_chemcomp_block_number(doc);
    if (n != -1)
      return make_structure_from_chemcomp_block(doc.blocks[n]);
  }
  return make_structure(doc);
}

inline Structure read_structure_from_char_array(char* data, size_t size,
                                                const std::string& path) {
  CoorFormat format = coor_format_from_content(data, data + size);
  if (format == CoorFormat::Pdb)
    return read_pdb_from_memory(data, size, path);
  if (format == CoorFormat::Mmcif)
    return make_structure_from_doc(cif::read_memory(data, size, path.c_str()), true);
  if (format == CoorFormat::Mmjson)
    return make_structure(cif::read_mmjson_insitu(data, size, path));
  fail("wrong format of coordinate file " + path);
}

template<typename T>
Structure read_structure(T&& input, CoorFormat format=CoorFormat::Unknown) {
  bool any = (format == CoorFormat::UnknownAny);
  if (format == CoorFormat::Unknown || any)
    format = coor_format_from_ext(input.basepath());
  if (format == CoorFormat::Unknown && any) { // detect using the content
    CharArray mem = read_into_buffer(input);
    return read_structure_from_char_array(mem.data(), mem.size(), input.path());
  }
  switch (format) {
    case CoorFormat::Pdb:
      return read_pdb(input);
    case CoorFormat::Mmcif:
      return make_structure_from_doc(cif::read(input), any);
    case CoorFormat::Mmjson:
      return make_structure(cif::read_mmjson(input));
    case CoorFormat::ChemComp:
      return make_structure_from_chemcomp_doc(cif::read(input));
    case CoorFormat::Unknown:
    case CoorFormat::UnknownAny:
      fail("Unknown format of " +
           (input.path().empty() ? "coordinate file" : input.path()) + ".");
  }
  unreachable();
}

inline Structure read_structure_file(const std::string& path,
                                     CoorFormat format=CoorFormat::Unknown) {
  return read_structure(BasicInput(path), format);
}

} // namespace gemmi
#endif
<|endoftext|>


<commit_before>//===-- InstrinsicInst.cpp - Intrinsic Instruction Wrappers -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements methods that make it really easy to deal with intrinsic
// functions with the isa/dyncast family of functions.  In particular, this
// allows you to do things like:
//
//     if (DbgStopPointInst *SPI = dyn_cast<DbgStopPointInst>(Inst))
//        ... SPI->getFileName() ... SPI->getDirectory() ...
//
// All intrinsic function calls are instances of the call instruction, so these
// are all subclasses of the CallInst class.  Note that none of these classes
// has state or virtual methods, which is an important part of this gross/neat
// hack working.
//
// In some cases, arguments to intrinsics need to be generic and are defined as
// type pointer to empty struct { }*.  To access the real item of interest the
// cast instruction needs to be stripped away.
//
//===----------------------------------------------------------------------===//

#include "llvm/IntrinsicInst.h"
#include "llvm/Constants.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
/// DbgInfoIntrinsic - This is the common base class for debug info intrinsics
///

static Value *CastOperand(Value *C) {
  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
    if (CE->isCast())
      return CE->getOperand(0);
  return NULL;
}

Value *DbgInfoIntrinsic::StripCast(Value *C) {
  if (Value *CO = CastOperand(C)) {
    C = StripCast(CO);
  } else if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
    if (GV->hasInitializer())
      if (Value *CO = CastOperand(GV->getInitializer()))
        C = StripCast(CO);
  }
  return dyn_cast<GlobalVariable>(C);
}

//===----------------------------------------------------------------------===//
/// DbgStopPointInst - This represents the llvm.dbg.stoppoint instruction.
///

Value *DbgStopPointInst::getFileName() const {
  // Once the operand indices are verified, update this assert
  assert(LLVMDebugVersion == (6 << 16) && "Verify operand indices");
  GlobalVariable *GV = cast<GlobalVariable>(getContext());
  if (!GV->hasInitializer()) return NULL;
  ConstantStruct *CS = cast<ConstantStruct>(GV->getInitializer());
  return CS->getOperand(4);
}

Value *DbgStopPointInst::getDirectory() const {
  // Once the operand indices are verified, update this assert
  assert(LLVMDebugVersion == (6 << 16) && "Verify operand indices");
  GlobalVariable *GV = cast<GlobalVariable>(getContext());
  if (!GV->hasInitializer()) return NULL;
  ConstantStruct *CS = cast<ConstantStruct>(GV->getInitializer());
  return CS->getOperand(4);
}
<commit_msg>Unbreak DbgStopPointInst::getFileName().<commit_after>//===-- InstrinsicInst.cpp - Intrinsic Instruction Wrappers -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements methods that make it really easy to deal with intrinsic
// functions with the isa/dyncast family of functions.  In particular, this
// allows you to do things like:
//
//     if (DbgStopPointInst *SPI = dyn_cast<DbgStopPointInst>(Inst))
//        ... SPI->getFileName() ... SPI->getDirectory() ...
//
// All intrinsic function calls are instances of the call instruction, so these
// are all subclasses of the CallInst class.  Note that none of these classes
// has state or virtual methods, which is an important part of this gross/neat
// hack working.
//
// In some cases, arguments to intrinsics need to be generic and are defined as
// type pointer to empty struct { }*.  To access the real item of interest the
// cast instruction needs to be stripped away.
//
//===----------------------------------------------------------------------===//

#include "llvm/IntrinsicInst.h"
#include "llvm/Constants.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
/// DbgInfoIntrinsic - This is the common base class for debug info intrinsics
///

static Value *CastOperand(Value *C) {
  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
    if (CE->isCast())
      return CE->getOperand(0);
  return NULL;
}

Value *DbgInfoIntrinsic::StripCast(Value *C) {
  if (Value *CO = CastOperand(C)) {
    C = StripCast(CO);
  } else if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
    if (GV->hasInitializer())
      if (Value *CO = CastOperand(GV->getInitializer()))
        C = StripCast(CO);
  }
  return dyn_cast<GlobalVariable>(C);
}

//===----------------------------------------------------------------------===//
/// DbgStopPointInst - This represents the llvm.dbg.stoppoint instruction.
///

Value *DbgStopPointInst::getFileName() const {
  // Once the operand indices are verified, update this assert
  assert(LLVMDebugVersion == (6 << 16) && "Verify operand indices");
  GlobalVariable *GV = cast<GlobalVariable>(getContext());
  if (!GV->hasInitializer()) return NULL;
  ConstantStruct *CS = cast<ConstantStruct>(GV->getInitializer());
  return CS->getOperand(3);
}

Value *DbgStopPointInst::getDirectory() const {
  // Once the operand indices are verified, update this assert
  assert(LLVMDebugVersion == (6 << 16) && "Verify operand indices");
  GlobalVariable *GV = cast<GlobalVariable>(getContext());
  if (!GV->hasInitializer()) return NULL;
  ConstantStruct *CS = cast<ConstantStruct>(GV->getInitializer());
  return CS->getOperand(4);
}
<|endoftext|>


<commit_before>#ifndef CROCHEMORE_HPP
#define CROCHEMORE_HPP

#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <bitset>
#include <boost/dynamic_bitset.hpp>

namespace str
{

/*!
    computes the next maximum suffix (MS) given the previous one. Also computes the period of it.
    \a l -> end index of pattern
    \a s -> starting position of the maximum suffix
    \a p -> per(MS(pattern[0...l]))
    Function is needed later in determining the jump to make by checking whether
    per(pattern[0..l]) == per(MS(pattern[0..l]))
*/
template<typename T>
void updateMS(const std::basic_string<T> & pattern, size_t & l, size_t & s, size_t & p)
{
    if (l == 0)
    {
        /*
            maximum suffix is pattern[s..l)
            setting p to 1 mean that no characters really match
        */
        l = 1;
        s = 0;
        p = 1;
        return;
    }
    size_t i = l;
    while (i < l+1)
    {
        if (pattern[i-p] > pattern[i])
        {
            /*
                set the maximum suffix to be recomputed
            */
            i = i - (i-s) % p;
            s = i;
            p = 1;
        }
        else if (pattern[i-p] < pattern[i])
        {
            /*
                increase maximum suffix
                set the period be the length of the maximum suffix
                this yields that no characters really match
                (no border)
            */
            p = i-s+1;
        }
        /*
            the characters are equal
            the maximum suffix is extended
            the perioud is the same
            namely:
            we have that
            pattern[0...i] = A.A.A.A.A.B where B is a prefix of A
            so, it is so that the period holds, but we just continue to have equal characters
        */
        i++;
    }
    l+=1;
}

/*!
    searches for \a pattern in \a text
    returned is a \a std::vector of starting possitions.
*/
template<typename T>
std::vector<size_t> crochemoreSearch(const std::basic_string<T> & text, const std::basic_string<T> & pattern)
{
    std::vector<size_t> positions;
    size_t i=0,l=0, p=0, s= 0;
    while (i < text.length())
    {
        while (i+l < text.length() && l < pattern.length() && text[i+l]==pattern[l])
        {
            /*
                update the maximum suffix and the maximum pariod of it
            */
            updateMS(pattern, l, s, p);
        }
        if (l == pattern.length())
        {
            /*
                pattern[0..l) == text[i..i+l)
            */
            positions.push_back(i);
        }
        if (p <= l/3 && s != 0 && equal(pattern.begin(), pattern.begin()+s, pattern.begin()+p))
        {
            /*
                we have that pattern[0..s) == pattern[p..p+s)
                => per(pattern[0...l)) == per(MS(pattern[0...l))
                if p <= l/3 then we have that pattern[0...l) is 3 periodic
                essentially we skip l/3 characters since we have
                i+=p and l-=p
            */
            i += p;
            l -= p;
        }
        else
        {
            /*
                otherwise safely just skip l/3 characters and restart matching
            */
            i = i + l/3 + 1;
            l=0,s=0,p=0;
        }
    }
    /*
        use strict move semantics to prevent copying of data no matter the compiler
    */
    return move(positions);
}

/*!
    returns a \a boost::dynamic_bitset of size \a text.length() where
    bit[i] = 1 then text[i...) < pattern
    bit[i] = 0 else
*/
template<typename T>
boost::dynamic_bitset<> lowerBound(const std::basic_string<T> & text, const std::basic_string<T> & pattern)
{
    boost::dynamic_bitset<> bits = boost::dynamic_bitset<>(text.length());
    size_t i=0, l = 0, p = 0, s = 0, j = 0;
    size_t imax = 0, lmax = 0, pmax = 0, smax = 0, h = 0;
    while (i < text.length())
    {
        while (i+l < text.length() && l < pattern.length() && text[i+l]==pattern[l])
        {
            /*
                update the maximum suffix and the maximum pariod of it
            */
            updateMS(pattern, l, s, p);
        }
        if (l < pattern.length() && (i+l==text.length() || text[i+l] < pattern[l]))
        {
            /*
                we do not have a match
                we check whether the last compared character in the text is smaller than the last compared in pattern
                if we have reached the length of the text, then we "compare" with the empty string which is always smaller
                => we set the bit to 1
            */
            bits[i] = 1;
        }
        j = imax;
        if (l > lmax)
        {
            std::swap(l,lmax);
            std::swap(s,smax);
            std::swap(p,pmax);
            imax = i;
        }
        if ((0 < p && p <= l/3) && s != 0 && std::equal(pattern.begin(), pattern.begin()+s, pattern.begin()+p))
        {
            /*
                we make a skip but we must copy the bit set in the range
                we are skipping a period
                we just have to copy what we have set initially.
            */
            for (int f = 1; f < p; ++f) bits[i+f] = bits[j+f];
            i = i+p;
            l = l-p;
        }
        else
        {
            /*
                we make a skip but we must copy the bit set in the range
            */
            h = l/3 + 1;
            for (int f = 1; f < h; ++f) bits[i+f] = bits[j+f];
            i += h;
            l = 0, s = 0, p = 0;
        }
    }
    return std::move(bits);
}

template<typename T>
std::vector<size_t> stringRangeMatch(const std::basic_string<T> & text, const std::basic_string<T> & low, const std::basic_string<T> & top)
{
    boost::dynamic_bitset<> lowbits = lowerBound<T>(text,low);
    boost::dynamic_bitset<> topbits = lowerBound<T>(text,top);
    /*
        we have the bitsets for the lower and the upper bound
        obviously the lower bound is a subset of the upper bound
        namely if we have 1 for some index in the lower bound, the we have it in the upper bound
        we have to set those bits to 0
        we just have to do an XOR
    */
    lowbits ^= topbits;

    /*
        we have the bits now 1 where the suffix is in the given bound
        we have to search for them.
        lowbits.count() gives the count of the bits where we have 1
    */
    std::vector<size_t> positions(lowbits.count());
    size_t i = lowbits.find_first();
    size_t idx = 0;

    /*
        find the next bit's position and store the index
        note that if one decides to stop using the bitset and use multiple memory blocks to work with
        the best way to find the next bit set is to use the expression
        (val & -val) which is equivalen to (val & (~val + 1)) due to 2-complement of how integers are stored in memory
    */
    while (i != lowbits.npos) {
        positions[idx++] = i;
        i = lowbits.find_next(i);
    }

    /*
        explicitly move data
    */
    return std::move(positions);
}

}

#endif // CROCHEMORE_HPP
<commit_msg>added doc<commit_after>#ifndef CROCHEMORE_HPP
#define CROCHEMORE_HPP

#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <bitset>
#include <boost/dynamic_bitset.hpp>

namespace str
{

/*!
    computes the next maximum suffix (MS) given the previous one. Also computes the period of it.
    \a l -> end index of pattern
    \a s -> starting position of the maximum suffix
    \a p -> per(MS(pattern[0...l]))
    Function is needed later in determining the jump to make by checking whether
    per(pattern[0..l]) == per(MS(pattern[0..l]))
*/
template<typename T>
void updateMS(const std::basic_string<T> & pattern, size_t & l, size_t & s, size_t & p)
{
    if (l == 0)
    {
        /*
            maximum suffix is pattern[s..l)
            setting p to 1 mean that no characters really match
        */
        l = 1;
        s = 0;
        p = 1;
        return;
    }
    size_t i = l;
    while (i < l+1)
    {
        if (pattern[i-p] > pattern[i])
        {
            /*
                set the maximum suffix to be recomputed
            */
            i = i - (i-s) % p;
            s = i;
            p = 1;
        }
        else if (pattern[i-p] < pattern[i])
        {
            /*
                increase maximum suffix
                set the period be the length of the maximum suffix
                this yields that no characters really match
                (no border)
            */
            p = i-s+1;
        }
        /*
            the characters are equal
            the maximum suffix is extended
            the perioud is the same
            namely:
            we have that
            pattern[0...i] = A.A.A.A.A.B where B is a prefix of A
            so, it is so that the period holds, but we just continue to have equal characters
        */
        i++;
    }
    l+=1;
}

/*!
    searches for \a pattern in \a text
    returned is a \a std::vector of starting possitions.
*/
template<typename T>
std::vector<size_t> crochemoreSearch(const std::basic_string<T> & text, const std::basic_string<T> & pattern)
{
    std::vector<size_t> positions;
    size_t i=0,l=0, p=0, s= 0;
    while (i < text.length())
    {
        while (i+l < text.length() && l < pattern.length() && text[i+l]==pattern[l])
        {
            /*
                update the maximum suffix and the maximum pariod of it
            */
            updateMS(pattern, l, s, p);
        }
        if (l == pattern.length())
        {
            /*
                pattern[0..l) == text[i..i+l)
            */
            positions.push_back(i);
        }
        if (p <= l/3 && s != 0 && equal(pattern.begin(), pattern.begin()+s, pattern.begin()+p))
        {
            /*
                we have that pattern[0..s) == pattern[p..p+s)
                => per(pattern[0...l)) == per(MS(pattern[0...l))
                if p <= l/3 then we have that pattern[0...l) is 3 periodic
                essentially we skip l/3 characters since we have
                i+=p and l-=p
            */
            i += p;
            l -= p;
        }
        else
        {
            /*
                otherwise safely just skip l/3 characters and restart matching
            */
            i = i + l/3 + 1;
            l=0,s=0,p=0;
        }
    }
    /*
        use strict move semantics to prevent copying of data no matter the compiler
    */
    return move(positions);
}

/*!
    returns a \a boost::dynamic_bitset of size \a text.length() where
    bit[i] = 1 then text[i...) < pattern
    bit[i] = 0 else
*/
template<typename T>
boost::dynamic_bitset<> lowerBound(const std::basic_string<T> & text, const std::basic_string<T> & pattern)
{
    boost::dynamic_bitset<> bits = boost::dynamic_bitset<>(text.length());
    size_t i=0, l = 0, p = 0, s = 0, j = 0;
    size_t imax = 0, lmax = 0, pmax = 0, smax = 0, h = 0;
    while (i < text.length())
    {
        while (i+l < text.length() && l < pattern.length() && text[i+l]==pattern[l])
        {
            /*
                update the maximum suffix and the maximum pariod of it
            */
            updateMS(pattern, l, s, p);
        }
        if (l < pattern.length() && (i+l==text.length() || text[i+l] < pattern[l]))
        {
            /*
                we do not have a match
                we check whether the last compared character in the text is smaller than the last compared in pattern
                if we have reached the length of the text, then we "compare" with the empty string which is always smaller
                => we set the bit to 1
            */
            bits[i] = 1;
        }
        j = imax;
        if (l > lmax)
        {
            std::swap(l,lmax);
            std::swap(s,smax);
            std::swap(p,pmax);
            imax = i;
        }
        if ((0 < p && p <= l/3) && s != 0 && std::equal(pattern.begin(), pattern.begin()+s, pattern.begin()+p))
        {
            /*
                we make a skip but we must copy the bit set in the range
                we are skipping a period
                we just have to copy what we have set initially.
            */
            for (int f = 1; f < p; ++f) bits[i+f] = bits[j+f];
            i = i+p;
            l = l-p;
        }
        else
        {
            /*
                we make a skip but we must copy the bit set in the range
            */
            h = l/3 + 1;
            for (int f = 1; f < h; ++f) bits[i+f] = bits[j+f];
            i += h;
            l = 0, s = 0, p = 0;
        }
    }
    return std::move(bits);
}

/*!
    returns the starting positions of all suffixes in \a text which are lexicographically
    in the range (low,top).
*/
template<typename T>
std::vector<size_t> stringRangeMatch(const std::basic_string<T> & text, const std::basic_string<T> & low, const std::basic_string<T> & top)
{
    boost::dynamic_bitset<> lowbits = lowerBound<T>(text,low);
    boost::dynamic_bitset<> topbits = lowerBound<T>(text,top);
    /*
        we have the bitsets for the lower and the upper bound
        obviously the lower bound is a subset of the upper bound
        namely if we have 1 for some index in the lower bound, the we have it in the upper bound
        we have to set those bits to 0
        we just have to do an XOR
    */
    lowbits ^= topbits;

    /*
        we have the bits now 1 where the suffix is in the given bound
        we have to search for them.
        lowbits.count() gives the count of the bits where we have 1
    */
    std::vector<size_t> positions(lowbits.count());
    size_t i = lowbits.find_first();
    size_t idx = 0;

    /*
        find the next bit's position and store the index
        note that if one decides to stop using the bitset and use multiple memory blocks to work with
        the best way to find the next bit set is to use the expression
        (val & -val) which is equivalen to (val & (~val + 1)) due to 2-complement of how integers are stored in memory
    */
    while (i != lowbits.npos) {
        positions[idx++] = i;
        i = lowbits.find_next(i);
    }

    /*
        explicitly move data
    */
    return std::move(positions);
}

}

#endif // CROCHEMORE_HPP
<|endoftext|>


<commit_before>/*
    Copyright (c) 2009-2011 250bpm s.r.o.
    Copyright (c) 2011 Botond Ballo
    Copyright (c) 2007-2009 iMatix Corporation

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to
    deal in the Software without restriction, including without limitation the
    rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    sell copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    IN THE SOFTWARE.
*/

#ifndef __ZMQ_HPP_INCLUDED__
#define __ZMQ_HPP_INCLUDED__

#include <zmq.h>

#include <cassert>
#include <cstring>
#include <algorithm>
#include <exception>

//  Detect whether the compiler supports C++11 rvalue references.
#if (defined(__GNUC__) && (__GNUC__ > 4 || \
      (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \
      defined(__GXX_EXPERIMENTAL_CXX0X__))
    #define ZMQ_HAS_RVALUE_REFS
#endif
#if (defined(__clang__))
    #if __has_feature(cxx_rvalue_references)
        #define ZMQ_HAS_RVALUE_REFS
    #endif
#endif
#if (defined(_MSC_VER) && (_MSC_VER >= 1600))
    #define ZMQ_HAS_RVALUE_REFS
#endif

namespace zmq
{

    typedef zmq_free_fn free_fn;
    typedef zmq_pollitem_t pollitem_t;

    class error_t : public std::exception
    {
    public:

        error_t () : errnum (zmq_errno ()) {}

        virtual const char *what () const throw ()
        {
            return zmq_strerror (errnum);
        }

        int num () const
        {
            return errnum;
        }

    private:

        int errnum;
    };

    inline int poll (zmq_pollitem_t *items_, int nitems_, long timeout_ = -1)
    {
        int rc = zmq_poll (items_, nitems_, timeout_);
        if (rc < 0)
            throw error_t ();
        return rc;
    }

    inline void version (int *major_, int *minor_, int *patch_)
    {
        zmq_version (major_, minor_, patch_);
    }

    class message_t
    {
        friend class socket_t;

    public:

        inline message_t ()
        {
            int rc = zmq_msg_init (&msg);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t (size_t size_)
        {
            int rc = zmq_msg_init_size (&msg, size_);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t (void *data_, size_t size_, free_fn *ffn_,
            void *hint_ = NULL)
        {
            int rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
            if (rc != 0)
                throw error_t ();
        }

        inline ~message_t ()
        {
            int rc = zmq_msg_close (&msg);
            assert (rc == 0);
        }

        inline void rebuild ()
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init (&msg);
            if (rc != 0)
                throw error_t ();
        }

        inline void rebuild (size_t size_)
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init_size (&msg, size_);
            if (rc != 0)
                throw error_t ();
        }

        inline void rebuild (void *data_, size_t size_, free_fn *ffn_,
            void *hint_ = NULL)
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
            if (rc != 0)
                throw error_t ();
        }

        inline void move (message_t *msg_)
        {
            int rc = zmq_msg_move (&msg, &(msg_->msg));
            if (rc != 0)
                throw error_t ();
        }

        inline void copy (message_t *msg_)
        {
            int rc = zmq_msg_copy (&msg, &(msg_->msg));
            if (rc != 0)
                throw error_t ();
        }

        inline void *data ()
        {
            return zmq_msg_data (&msg);
        }

        inline size_t size ()
        {
            return zmq_msg_size (&msg);
        }

    private:

        //  The underlying message
        zmq_msg_t msg;

        //  Disable implicit message copying, so that users won't use shared
        //  messages (less efficient) without being aware of the fact.
        message_t (const message_t&);
        void operator = (const message_t&);
    };

    class context_t
    {
        friend class socket_t;

    public:

        inline context_t (int io_threads_)
        {
            ptr = zmq_init (io_threads_);
            if (ptr == NULL)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline context_t (context_t &&rhs) : ptr (rhs.ptr)
        {
            rhs.ptr = NULL;
        }
        inline context_t &operator = (context_t &&rhs)
        {
            std::swap (ptr, rhs.ptr);
            return *this;
        }
#endif

        inline ~context_t ()
        {
            if (ptr == NULL)
                return;
            int rc = zmq_term (ptr);
            assert (rc == 0);
        }

        //  Be careful with this, it's probably only useful for
        //  using the C api together with an existing C++ api.
        //  Normally you should never need to use this.
        inline operator void* ()
        {
            return ptr;
        }

    private:

        void *ptr;

        context_t (const context_t&);
        void operator = (const context_t&);
    };

    class socket_t
    {
    public:

        inline socket_t (context_t &context_, int type_)
        {
            ptr = zmq_socket (context_.ptr, type_);
            if (ptr == NULL)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline socket_t(socket_t&& rhs) : ptr(rhs.ptr)
        {
            rhs.ptr = NULL;
        }
        inline socket_t& operator=(socket_t&& rhs)
        {
            std::swap(ptr, rhs.ptr);
            return *this;
        }
#endif

        inline ~socket_t ()
        {
            close();
        }

        inline operator void* ()
        {
            return ptr;
        }

        inline void close()
        {
            if(ptr == NULL)
                // already closed
                return ;
            int rc = zmq_close (ptr);
            if (rc != 0)
                throw error_t ();
            ptr = 0 ;
        }

        inline void setsockopt (int option_, const void *optval_,
            size_t optvallen_)
        {
            int rc = zmq_setsockopt (ptr, option_, optval_, optvallen_);
            if (rc != 0)
                throw error_t ();
        }

        inline void getsockopt (int option_, void *optval_,
            size_t *optvallen_)
        {
            int rc = zmq_getsockopt (ptr, option_, optval_, optvallen_);
            if (rc != 0)
                throw error_t ();
        }

        inline void bind (const char *addr_)
        {
            int rc = zmq_bind (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline void connect (const char *addr_)
        {
            int rc = zmq_connect (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline size_t send (const void *buf_, size_t len_, int flags_ = 0)
        {
            int nbytes = zmq_send (ptr, buf_, len_, flags_);
            if (nbytes >= 0)
                return (size_t) nbytes;
            if (zmq_errno () == EAGAIN)
                return 0;
            throw error_t ();
        }

        inline bool send (message_t &msg_, int flags_ = 0)
        {
            int nbytes = zmq_sendmsg (ptr, &(msg_.msg), flags_);
            if (nbytes >= 0)
                return true;
            if (zmq_errno () == EAGAIN)
                return false;
            throw error_t ();
        }

        inline size_t recv (void *buf_, size_t len_, int flags_ = 0)
        {
            int nbytes = zmq_recv (ptr, buf_, len_, flags_);
            if (nbytes >= 0)
                return (size_t) nbytes;
            if (zmq_errno () == EAGAIN)
                return 0;
            throw error_t ();
        }

        inline bool recv (message_t *msg_, int flags_ = 0)
        {
            int nbytes = zmq_recvmsg (ptr, &(msg_->msg), flags_);
            if (nbytes >= 0)
                return true;
            if (zmq_errno () == EAGAIN)
                return false;
            throw error_t ();
        }

    private:

        void *ptr;

        socket_t (const socket_t&);
        void operator = (const socket_t&);
    };

}

#endif

<commit_msg>Prevent exception to be thrown in the destructor<commit_after>/*
    Copyright (c) 2009-2011 250bpm s.r.o.
    Copyright (c) 2011 Botond Ballo
    Copyright (c) 2007-2009 iMatix Corporation

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to
    deal in the Software without restriction, including without limitation the
    rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    sell copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    IN THE SOFTWARE.
*/

#ifndef __ZMQ_HPP_INCLUDED__
#define __ZMQ_HPP_INCLUDED__

#include <zmq.h>

#include <cassert>
#include <cstring>
#include <algorithm>
#include <exception>

//  Detect whether the compiler supports C++11 rvalue references.
#if (defined(__GNUC__) && (__GNUC__ > 4 || \
      (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \
      defined(__GXX_EXPERIMENTAL_CXX0X__))
    #define ZMQ_HAS_RVALUE_REFS
#endif
#if (defined(__clang__))
    #if __has_feature(cxx_rvalue_references)
        #define ZMQ_HAS_RVALUE_REFS
    #endif
#endif
#if (defined(_MSC_VER) && (_MSC_VER >= 1600))
    #define ZMQ_HAS_RVALUE_REFS
#endif

namespace zmq
{

    typedef zmq_free_fn free_fn;
    typedef zmq_pollitem_t pollitem_t;

    class error_t : public std::exception
    {
    public:

        error_t () : errnum (zmq_errno ()) {}

        virtual const char *what () const throw ()
        {
            return zmq_strerror (errnum);
        }

        int num () const
        {
            return errnum;
        }

    private:

        int errnum;
    };

    inline int poll (zmq_pollitem_t *items_, int nitems_, long timeout_ = -1)
    {
        int rc = zmq_poll (items_, nitems_, timeout_);
        if (rc < 0)
            throw error_t ();
        return rc;
    }

    inline void version (int *major_, int *minor_, int *patch_)
    {
        zmq_version (major_, minor_, patch_);
    }

    class message_t
    {
        friend class socket_t;

    public:

        inline message_t ()
        {
            int rc = zmq_msg_init (&msg);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t (size_t size_)
        {
            int rc = zmq_msg_init_size (&msg, size_);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t (void *data_, size_t size_, free_fn *ffn_,
            void *hint_ = NULL)
        {
            int rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
            if (rc != 0)
                throw error_t ();
        }

        inline ~message_t ()
        {
            int rc = zmq_msg_close (&msg);
            assert (rc == 0);
        }

        inline void rebuild ()
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init (&msg);
            if (rc != 0)
                throw error_t ();
        }

        inline void rebuild (size_t size_)
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init_size (&msg, size_);
            if (rc != 0)
                throw error_t ();
        }

        inline void rebuild (void *data_, size_t size_, free_fn *ffn_,
            void *hint_ = NULL)
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
            if (rc != 0)
                throw error_t ();
        }

        inline void move (message_t *msg_)
        {
            int rc = zmq_msg_move (&msg, &(msg_->msg));
            if (rc != 0)
                throw error_t ();
        }

        inline void copy (message_t *msg_)
        {
            int rc = zmq_msg_copy (&msg, &(msg_->msg));
            if (rc != 0)
                throw error_t ();
        }

        inline void *data ()
        {
            return zmq_msg_data (&msg);
        }

        inline size_t size ()
        {
            return zmq_msg_size (&msg);
        }

    private:

        //  The underlying message
        zmq_msg_t msg;

        //  Disable implicit message copying, so that users won't use shared
        //  messages (less efficient) without being aware of the fact.
        message_t (const message_t&);
        void operator = (const message_t&);
    };

    class context_t
    {
        friend class socket_t;

    public:

        inline context_t (int io_threads_)
        {
            ptr = zmq_init (io_threads_);
            if (ptr == NULL)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline context_t (context_t &&rhs) : ptr (rhs.ptr)
        {
            rhs.ptr = NULL;
        }
        inline context_t &operator = (context_t &&rhs)
        {
            std::swap (ptr, rhs.ptr);
            return *this;
        }
#endif

        inline ~context_t ()
        {
            if (ptr == NULL)
                return;
            int rc = zmq_term (ptr);
            assert (rc == 0);
        }

        //  Be careful with this, it's probably only useful for
        //  using the C api together with an existing C++ api.
        //  Normally you should never need to use this.
        inline operator void* ()
        {
            return ptr;
        }

    private:

        void *ptr;

        context_t (const context_t&);
        void operator = (const context_t&);
    };

    class socket_t
    {
    public:

        inline socket_t (context_t &context_, int type_)
        {
            ptr = zmq_socket (context_.ptr, type_);
            if (ptr == NULL)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline socket_t(socket_t&& rhs) : ptr(rhs.ptr)
        {
            rhs.ptr = NULL;
        }
        inline socket_t& operator=(socket_t&& rhs)
        {
            std::swap(ptr, rhs.ptr);
            return *this;
        }
#endif

        inline ~socket_t ()
        {
            close();
        }

        inline operator void* ()
        {
            return ptr;
        }

        inline void close()
        {
            if(ptr == NULL)
                // already closed
                return ;
            int rc = zmq_close (ptr);
            assert (rc == 0);
            ptr = 0 ;
        }

        inline void setsockopt (int option_, const void *optval_,
            size_t optvallen_)
        {
            int rc = zmq_setsockopt (ptr, option_, optval_, optvallen_);
            if (rc != 0)
                throw error_t ();
        }

        inline void getsockopt (int option_, void *optval_,
            size_t *optvallen_)
        {
            int rc = zmq_getsockopt (ptr, option_, optval_, optvallen_);
            if (rc != 0)
                throw error_t ();
        }

        inline void bind (const char *addr_)
        {
            int rc = zmq_bind (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline void connect (const char *addr_)
        {
            int rc = zmq_connect (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline size_t send (const void *buf_, size_t len_, int flags_ = 0)
        {
            int nbytes = zmq_send (ptr, buf_, len_, flags_);
            if (nbytes >= 0)
                return (size_t) nbytes;
            if (zmq_errno () == EAGAIN)
                return 0;
            throw error_t ();
        }

        inline bool send (message_t &msg_, int flags_ = 0)
        {
            int nbytes = zmq_sendmsg (ptr, &(msg_.msg), flags_);
            if (nbytes >= 0)
                return true;
            if (zmq_errno () == EAGAIN)
                return false;
            throw error_t ();
        }

        inline size_t recv (void *buf_, size_t len_, int flags_ = 0)
        {
            int nbytes = zmq_recv (ptr, buf_, len_, flags_);
            if (nbytes >= 0)
                return (size_t) nbytes;
            if (zmq_errno () == EAGAIN)
                return 0;
            throw error_t ();
        }

        inline bool recv (message_t *msg_, int flags_ = 0)
        {
            int nbytes = zmq_recvmsg (ptr, &(msg_->msg), flags_);
            if (nbytes >= 0)
                return true;
            if (zmq_errno () == EAGAIN)
                return false;
            throw error_t ();
        }

    private:

        void *ptr;

        socket_t (const socket_t&);
        void operator = (const socket_t&);
    };

}

#endif

<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: color.hpp 39 2005-04-10 20:39:53Z pavlenko $

#ifndef COLOR_HPP
#define COLOR_HPP

// mapnik
#include <mapnik/config.hpp>
//boost
#include <boost/format.hpp>
#include <boost/cstdint.hpp>

// stl
#include <sstream>

namespace mapnik {

    class MAPNIK_DECL color
    {
    private:
        boost::uint8_t red_;
        boost::uint8_t green_;
        boost::uint8_t blue_;
        boost::uint8_t alpha_;

    public:
        color()
            : red_(0xff),
            green_(0xff),
            blue_(0xff),
            alpha_(0xff)
            {}

        color(int red,int green,int blue,int alpha=0xff)
            :  red_(red),
            green_(green),
            blue_(blue),
            alpha_(alpha)
            {}

        color( std::string const& css_string);

        color(const color& rhs)
            : red_(rhs.red_),
            green_(rhs.green_),
            blue_(rhs.blue_),
            alpha_(rhs.alpha_)
            {}

        color& operator=(const color& rhs)
        {
            if (this==&rhs) return *this;
            red_=rhs.red_;
            green_=rhs.green_;
            blue_=rhs.blue_;
            alpha_=rhs.alpha_;
            return *this;
        }

        inline unsigned red() const
        {
            return red_;
        }

        inline unsigned int green() const
        {
            return green_;
        }
        inline unsigned int blue() const
        {
            return blue_;
        }
        inline unsigned int alpha() const
        {
            return alpha_;
        }

        inline void set_red(unsigned red)
        {
            red_ = red;
        }
        inline void set_green(unsigned green)
        {
            green_ = green;
        }

        inline void set_blue(unsigned blue)
        {
            blue_ = blue;
        }
        inline void set_alpha(unsigned int alpha)
        {
            alpha_ = alpha;
        }

        inline unsigned int rgba() const
        {
#ifdef MAPNIK_BIG_ENDIAN
            return (alpha_) | (blue_ << 8) | (green_ << 16) | (red_ << 24) ;
#else
            return (alpha_ << 24) | (blue_ << 16) | (green_ << 8) | (red_) ;
#endif
        }

        inline bool operator==(color const& other) const
        {
            return rgba() == other.rgba();
        }

        inline bool operator!=(color const& other) const
        {
            return rgba() != other.rgba();
        }

        std::string to_string() const;

        std::string to_hex_string() const;
    };
}

#endif //COLOR_HPP
<commit_msg>add missing header so that MAPNIK_BIG_ENDIAN is propertly defined<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: color.hpp 39 2005-04-10 20:39:53Z pavlenko $

#ifndef COLOR_HPP
#define COLOR_HPP

// mapnik
#include <mapnik/config.hpp>
#include <mapnik/global.hpp>

//boost
#include <boost/format.hpp>
#include <boost/cstdint.hpp>

// stl
#include <sstream>

namespace mapnik {

    class MAPNIK_DECL color
    {
    private:
        boost::uint8_t red_;
        boost::uint8_t green_;
        boost::uint8_t blue_;
        boost::uint8_t alpha_;

    public:
        color()
            : red_(0xff),
            green_(0xff),
            blue_(0xff),
            alpha_(0xff)
            {}

        color(int red,int green,int blue,int alpha=0xff)
            :  red_(red),
            green_(green),
            blue_(blue),
            alpha_(alpha)
            {}

        color( std::string const& css_string);

        color(const color& rhs)
            : red_(rhs.red_),
            green_(rhs.green_),
            blue_(rhs.blue_),
            alpha_(rhs.alpha_)
            {}

        color& operator=(const color& rhs)
        {
            if (this==&rhs) return *this;
            red_=rhs.red_;
            green_=rhs.green_;
            blue_=rhs.blue_;
            alpha_=rhs.alpha_;
            return *this;
        }

        inline unsigned red() const
        {
            return red_;
        }

        inline unsigned int green() const
        {
            return green_;
        }
        inline unsigned int blue() const
        {
            return blue_;
        }
        inline unsigned int alpha() const
        {
            return alpha_;
        }

        inline void set_red(unsigned red)
        {
            red_ = red;
        }
        inline void set_green(unsigned green)
        {
            green_ = green;
        }

        inline void set_blue(unsigned blue)
        {
            blue_ = blue;
        }
        inline void set_alpha(unsigned int alpha)
        {
            alpha_ = alpha;
        }

        inline unsigned int rgba() const
        {
#ifdef MAPNIK_BIG_ENDIAN
            return (alpha_) | (blue_ << 8) | (green_ << 16) | (red_ << 24) ;
#else
            return (alpha_ << 24) | (blue_ << 16) | (green_ << 8) | (red_) ;
#endif
        }

        inline bool operator==(color const& other) const
        {
            return rgba() == other.rgba();
        }

        inline bool operator!=(color const& other) const
        {
            return rgba() != other.rgba();
        }

        std::string to_string() const;

        std::string to_hex_string() const;
    };
}

#endif //COLOR_HPP
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
 *  Main authors:
 *     Guido Tack <guido.tack@monash.edu>
 */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef __MINIZINC_TYPE_HH__
#define __MINIZINC_TYPE_HH__

#include <string>
#include <sstream>

namespace MiniZinc {

  /// Type of a MiniZinc expression
  class Type {
  public:
    /// Type-inst
    enum TypeInst { TI_PAR, TI_VAR, TI_SVAR };
    /// Basic type
    enum BaseType { BT_BOOL, BT_INT, BT_FLOAT, BT_STRING, BT_ANN,
                    BT_BOT, BT_TOP, BT_UNKNOWN };
    /// Whether the expression is plain or set
    enum SetType { ST_PLAIN, ST_SET };
    /// Whether the expression is normal or optional
    enum OptType { OT_PRESENT, OT_OPTIONAL };
  private:
    unsigned int _ti : 3;
    unsigned int _bt : 4;
    unsigned int _st  : 1;
    unsigned int _ot  : 1;
    /// Number of array dimensions
    int _dim : 20;
  public:
    /// Default constructor
    Type(void) : _ti(TI_PAR), _bt(BT_UNKNOWN), _st(ST_PLAIN),
                 _ot(OT_PRESENT), _dim(0) {}

    /// Access type-inst
    TypeInst ti(void) const { return static_cast<TypeInst>(_ti); }
    /// Set type-inst
    void ti(const TypeInst& t) { _ti = t; }

    /// Access basic type
    BaseType bt(void) const { return static_cast<BaseType>(_bt); }
    /// Set basic type
    void bt(const BaseType& b) { _bt = b; }

    /// Access set type
    SetType st(void) const { return static_cast<SetType>(_st); }
    /// Set set type
    void st(const SetType& s) { _st = s; }

    /// Access opt type
    OptType ot(void) const { return static_cast<OptType>(_ot); }
    /// Set opt type
    void ot(const OptType& o) { _ot = o; }

    /// Access dimensions
    int dim(void) const { return _dim; }
    /// Set dimensions
    void dim(int d) { _dim = d; }

  protected:
    /// Constructor
    Type(const TypeInst& ti, const BaseType& bt, const SetType& st,
         int dim)
      : _ti(ti), _bt(bt), _st(st), _ot(OT_PRESENT), _dim(dim) {}
  public:
    static Type parint(int dim=0) {
      return Type(TI_PAR,BT_INT,ST_PLAIN,dim);
    }
    static Type parbool(int dim=0) {
      return Type(TI_PAR,BT_BOOL,ST_PLAIN,dim);
    }
    static Type parfloat(int dim=0) {
      return Type(TI_PAR,BT_FLOAT,ST_PLAIN,dim);
    }
    static Type parstring(int dim=0) {
      return Type(TI_PAR,BT_STRING,ST_PLAIN,dim);
    }
    static Type ann(int dim=0) {
      return Type(TI_PAR,BT_ANN,ST_PLAIN,dim);
    }
    static Type parsetint(int dim=0) {
      return Type(TI_PAR,BT_INT,ST_SET,dim);
    }
    static Type parsetbool(int dim=0) {
      return Type(TI_PAR,BT_BOOL,ST_SET,dim);
    }
    static Type parsetfloat(int dim=0) {
      return Type(TI_PAR,BT_FLOAT,ST_SET,dim);
    }
    static Type parsetstring(int dim=0) {
      return Type(TI_PAR,BT_STRING,ST_SET,dim);
    }
    static Type varint(int dim=0) {
      return Type(TI_VAR,BT_INT,ST_PLAIN,dim);
    }
    static Type varbool(int dim=0) {
      return Type(TI_VAR,BT_BOOL,ST_PLAIN,dim);
    }
    static Type varfloat(int dim=0) {
      return Type(TI_VAR,BT_FLOAT,ST_PLAIN,dim);
    }
    static Type varsetint(int dim=0) {
      return Type(TI_VAR,BT_INT,ST_SET,dim);
    }
    static Type varbot(int dim=0) {
      return Type(TI_VAR,BT_BOT,ST_PLAIN,dim);
    }
    static Type bot(int dim=0) {
      return Type(TI_PAR,BT_BOT,ST_PLAIN,dim);
    }
    static Type top(int dim=0) {
      return Type(TI_PAR,BT_TOP,ST_PLAIN,dim);
    }
    static Type vartop(int dim=0) {
      return Type(TI_VAR,BT_TOP,ST_PLAIN,dim);
    }
    static Type optvartop(int dim=0) {
      Type t(TI_VAR,BT_TOP,ST_PLAIN,dim);
      t._ot = OT_OPTIONAL;
      return t;
    }

    bool isunknown(void) const { return _bt==BT_UNKNOWN; }
    bool isplain(void) const {
      return _dim==0 && _st==ST_PLAIN && _ot==OT_PRESENT;
    }
    bool isint(void) const { return _dim==0 && _st==ST_PLAIN && _bt==BT_INT; }
    bool isbot(void) const { return _bt==BT_BOT; }
    bool isfloat(void) const { return _dim==0 && _st==ST_PLAIN && _bt==BT_FLOAT; }
    bool isbool(void) const { return _dim==0 && _st==ST_PLAIN && _bt==BT_BOOL; }
    bool isstring(void) const { return isplain() && _bt==BT_STRING; }
    bool isvar(void) const { return _ti!=TI_PAR; }
    bool isvarint(void) const { return ti!=TI_PAR && _dim==0 && _st==ST_PLAIN && _bt==BT_INT; }
    bool issvar(void) const { return _ti==TI_SVAR; }
    bool ispar(void) const { return _ti==TI_PAR; }
    bool isopt(void) const { return _ot==OT_OPTIONAL; }
    bool ispresent(void) const { return _ot==OT_PRESENT; }
    bool isset(void) const { return _dim==0 && _st==ST_SET; }
    bool isintset(void) const {
      return isset() && (_bt==BT_INT || _bt==BT_BOT);
    }
    bool isann(void) const { return isplain() && _bt==BT_ANN; }
    bool isintarray(void) const {
      return _dim==1 && _st==ST_PLAIN && _ot==OT_PRESENT && _bt==BT_INT;
    }
    bool isboolarray(void) const {
      return _dim==1 && _st==ST_PLAIN && _ot==OT_PRESENT && _bt==BT_BOOL;
    }
    bool isintsetarray(void) const {
      return _dim==1 && _st==ST_SET && _bt==BT_INT;
    }

    bool operator== (const Type& t) const {
      return _ti==t._ti && _bt==t._bt && _st==t._st &&
             _ot==t._ot && _dim==t._dim;
    }
    bool operator!= (const Type& t) const {
      return !this->operator==(t);
    }
  // protected:

    /* We add 1 to _dim in toInt to ensure that it is non-negative
       (and subtract it again in fromInt). */
    int toInt(void) const {
      return
      + (static_cast<int>(_ot)<<28)
      + (static_cast<int>(_ti)<<25)
      + (static_cast<int>(_bt)<<21)
      + (static_cast<int>(_st)<<20)
      + (_dim + 1);
    }
    static Type fromInt(int i) {
      Type t;
      t._ot = static_cast<OptType>((i >> 28) & 0x1);
      t._ti = static_cast<TypeInst>((i >> 25) & 0x7);
      t._bt = static_cast<BaseType>((i >> 21) & 0xF);
      t._st = static_cast<SetType>((i >> 20) & 0x1);
      t._dim = (i & 0xFFFFF) - 1;
      return t;
    }
    std::string toString(void) const {
      std::ostringstream oss;
      if (_dim>0)
        oss<<"array["<<_dim<<"] of ";
      if (_dim<0)
        oss<<"array[$_] of ";
      if (_ot==OT_OPTIONAL) oss<<"opt ";
      switch (_ti) {
        case TI_PAR: oss<<"par "; break;
        case TI_VAR: oss<<"var "; break;
        case TI_SVAR: oss<<"svar "; break;
      }
      if (_st==ST_SET) oss<<"set of ";
      switch (_bt) {
        case BT_INT: oss<<"int"; break;
        case BT_BOOL: oss<<"bool"; break;
        case BT_FLOAT: oss<<"float"; break;
        case BT_STRING: oss<<"string"; break;
        case BT_ANN: oss<<"ann"; break;
        case BT_BOT: oss<<"bot"; break;
        case BT_TOP: oss<<"top"; break;
        case BT_UNKNOWN: oss<<"??? "; break;
      }
      return oss.str();
    }
  public:
    /// Check if this type is a subtype of \a t
    bool isSubtypeOf(const Type& t) const {
      // either same dimension or t has variable dimension
      if (_dim!=t._dim && (_dim==0 || t._dim!=-1))
        return false;
      // same type, this is present or both optional
      if (_ti==t._ti && _bt==t._bt && _st==t._st)
        return _ot==OT_PRESENT || _ot==t._ot;
      // this is par or svar, other than that same type as t
      if ((_ti==TI_PAR || _ti==TI_SVAR) && _bt==t._bt && _st==t._st)
        return _ot==OT_PRESENT || _ot==t._ot;
      // t is svar, other than that same type as this
      if (t._ti==TI_SVAR && _bt==t._bt && _st==t._st)
        return _ot==OT_PRESENT || _ot==t._ot;
      if ( (_ti==TI_PAR || _ti==TI_SVAR) && t._bt==BT_BOT)
        return true;
      if ( _bt==BT_BOT && _st==t._st)
        return _ot==OT_PRESENT || _ot==t._ot;
      if (t._bt==BT_TOP && (_ot==OT_PRESENT || _ot==t._ot) &&
          (t._st==ST_PLAIN || _st==t._st) &&
          (_ti==TI_PAR || t._ti==TI_VAR))
        return true;
      return false;
    }

    /// Compare types
    int cmp(const Type& t) const {
      return toInt()<t.toInt() ? -1 : (toInt()>t.toInt() ? 1 : 0);
    }

  };

};

#endif
<commit_msg>added isvarbool() to Type<commit_after>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
 *  Main authors:
 *     Guido Tack <guido.tack@monash.edu>
 */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef __MINIZINC_TYPE_HH__
#define __MINIZINC_TYPE_HH__

#include <string>
#include <sstream>

namespace MiniZinc {

  /// Type of a MiniZinc expression
  class Type {
  public:
    /// Type-inst
    enum TypeInst { TI_PAR, TI_VAR, TI_SVAR };
    /// Basic type
    enum BaseType { BT_BOOL, BT_INT, BT_FLOAT, BT_STRING, BT_ANN,
                    BT_BOT, BT_TOP, BT_UNKNOWN };
    /// Whether the expression is plain or set
    enum SetType { ST_PLAIN, ST_SET };
    /// Whether the expression is normal or optional
    enum OptType { OT_PRESENT, OT_OPTIONAL };
  private:
    unsigned int _ti : 3;
    unsigned int _bt : 4;
    unsigned int _st  : 1;
    unsigned int _ot  : 1;
    /// Number of array dimensions
    int _dim : 20;
  public:
    /// Default constructor
    Type(void) : _ti(TI_PAR), _bt(BT_UNKNOWN), _st(ST_PLAIN),
                 _ot(OT_PRESENT), _dim(0) {}

    /// Access type-inst
    TypeInst ti(void) const { return static_cast<TypeInst>(_ti); }
    /// Set type-inst
    void ti(const TypeInst& t) { _ti = t; }

    /// Access basic type
    BaseType bt(void) const { return static_cast<BaseType>(_bt); }
    /// Set basic type
    void bt(const BaseType& b) { _bt = b; }

    /// Access set type
    SetType st(void) const { return static_cast<SetType>(_st); }
    /// Set set type
    void st(const SetType& s) { _st = s; }

    /// Access opt type
    OptType ot(void) const { return static_cast<OptType>(_ot); }
    /// Set opt type
    void ot(const OptType& o) { _ot = o; }

    /// Access dimensions
    int dim(void) const { return _dim; }
    /// Set dimensions
    void dim(int d) { _dim = d; }

  protected:
    /// Constructor
    Type(const TypeInst& ti, const BaseType& bt, const SetType& st,
         int dim)
      : _ti(ti), _bt(bt), _st(st), _ot(OT_PRESENT), _dim(dim) {}
  public:
    static Type parint(int dim=0) {
      return Type(TI_PAR,BT_INT,ST_PLAIN,dim);
    }
    static Type parbool(int dim=0) {
      return Type(TI_PAR,BT_BOOL,ST_PLAIN,dim);
    }
    static Type parfloat(int dim=0) {
      return Type(TI_PAR,BT_FLOAT,ST_PLAIN,dim);
    }
    static Type parstring(int dim=0) {
      return Type(TI_PAR,BT_STRING,ST_PLAIN,dim);
    }
    static Type ann(int dim=0) {
      return Type(TI_PAR,BT_ANN,ST_PLAIN,dim);
    }
    static Type parsetint(int dim=0) {
      return Type(TI_PAR,BT_INT,ST_SET,dim);
    }
    static Type parsetbool(int dim=0) {
      return Type(TI_PAR,BT_BOOL,ST_SET,dim);
    }
    static Type parsetfloat(int dim=0) {
      return Type(TI_PAR,BT_FLOAT,ST_SET,dim);
    }
    static Type parsetstring(int dim=0) {
      return Type(TI_PAR,BT_STRING,ST_SET,dim);
    }
    static Type varint(int dim=0) {
      return Type(TI_VAR,BT_INT,ST_PLAIN,dim);
    }
    static Type varbool(int dim=0) {
      return Type(TI_VAR,BT_BOOL,ST_PLAIN,dim);
    }
    static Type varfloat(int dim=0) {
      return Type(TI_VAR,BT_FLOAT,ST_PLAIN,dim);
    }
    static Type varsetint(int dim=0) {
      return Type(TI_VAR,BT_INT,ST_SET,dim);
    }
    static Type varbot(int dim=0) {
      return Type(TI_VAR,BT_BOT,ST_PLAIN,dim);
    }
    static Type bot(int dim=0) {
      return Type(TI_PAR,BT_BOT,ST_PLAIN,dim);
    }
    static Type top(int dim=0) {
      return Type(TI_PAR,BT_TOP,ST_PLAIN,dim);
    }
    static Type vartop(int dim=0) {
      return Type(TI_VAR,BT_TOP,ST_PLAIN,dim);
    }
    static Type optvartop(int dim=0) {
      Type t(TI_VAR,BT_TOP,ST_PLAIN,dim);
      t._ot = OT_OPTIONAL;
      return t;
    }

    bool isunknown(void) const { return _bt==BT_UNKNOWN; }
    bool isplain(void) const {
      return _dim==0 && _st==ST_PLAIN && _ot==OT_PRESENT;
    }
    bool isint(void) const { return _dim==0 && _st==ST_PLAIN && _bt==BT_INT; }
    bool isbot(void) const { return _bt==BT_BOT; }
    bool isfloat(void) const { return _dim==0 && _st==ST_PLAIN && _bt==BT_FLOAT; }
    bool isbool(void) const { return _dim==0 && _st==ST_PLAIN && _bt==BT_BOOL; }
    bool isstring(void) const { return isplain() && _bt==BT_STRING; }
    bool isvar(void) const { return _ti!=TI_PAR; }
    bool isvarbool(void) const { return ti!=TI_PAR && _dim==0 && _st==ST_PLAIN && _bt==BT_BOOL; }
    bool isvarint(void) const { return ti!=TI_PAR && _dim==0 && _st==ST_PLAIN && _bt==BT_INT; }
    bool issvar(void) const { return _ti==TI_SVAR; }
    bool ispar(void) const { return _ti==TI_PAR; }
    bool isopt(void) const { return _ot==OT_OPTIONAL; }
    bool ispresent(void) const { return _ot==OT_PRESENT; }
    bool isset(void) const { return _dim==0 && _st==ST_SET; }
    bool isintset(void) const {
      return isset() && (_bt==BT_INT || _bt==BT_BOT);
    }
    bool isann(void) const { return isplain() && _bt==BT_ANN; }
    bool isintarray(void) const {
      return _dim==1 && _st==ST_PLAIN && _ot==OT_PRESENT && _bt==BT_INT;
    }
    bool isboolarray(void) const {
      return _dim==1 && _st==ST_PLAIN && _ot==OT_PRESENT && _bt==BT_BOOL;
    }
    bool isintsetarray(void) const {
      return _dim==1 && _st==ST_SET && _bt==BT_INT;
    }

    bool operator== (const Type& t) const {
      return _ti==t._ti && _bt==t._bt && _st==t._st &&
             _ot==t._ot && _dim==t._dim;
    }
    bool operator!= (const Type& t) const {
      return !this->operator==(t);
    }
  // protected:

    /* We add 1 to _dim in toInt to ensure that it is non-negative
       (and subtract it again in fromInt). */
    int toInt(void) const {
      return
      + (static_cast<int>(_ot)<<28)
      + (static_cast<int>(_ti)<<25)
      + (static_cast<int>(_bt)<<21)
      + (static_cast<int>(_st)<<20)
      + (_dim + 1);
    }
    static Type fromInt(int i) {
      Type t;
      t._ot = static_cast<OptType>((i >> 28) & 0x1);
      t._ti = static_cast<TypeInst>((i >> 25) & 0x7);
      t._bt = static_cast<BaseType>((i >> 21) & 0xF);
      t._st = static_cast<SetType>((i >> 20) & 0x1);
      t._dim = (i & 0xFFFFF) - 1;
      return t;
    }
    std::string toString(void) const {
      std::ostringstream oss;
      if (_dim>0)
        oss<<"array["<<_dim<<"] of ";
      if (_dim<0)
        oss<<"array[$_] of ";
      if (_ot==OT_OPTIONAL) oss<<"opt ";
      switch (_ti) {
        case TI_PAR: oss<<"par "; break;
        case TI_VAR: oss<<"var "; break;
        case TI_SVAR: oss<<"svar "; break;
      }
      if (_st==ST_SET) oss<<"set of ";
      switch (_bt) {
        case BT_INT: oss<<"int"; break;
        case BT_BOOL: oss<<"bool"; break;
        case BT_FLOAT: oss<<"float"; break;
        case BT_STRING: oss<<"string"; break;
        case BT_ANN: oss<<"ann"; break;
        case BT_BOT: oss<<"bot"; break;
        case BT_TOP: oss<<"top"; break;
        case BT_UNKNOWN: oss<<"??? "; break;
      }
      return oss.str();
    }
  public:
    /// Check if this type is a subtype of \a t
    bool isSubtypeOf(const Type& t) const {
      // either same dimension or t has variable dimension
      if (_dim!=t._dim && (_dim==0 || t._dim!=-1))
        return false;
      // same type, this is present or both optional
      if (_ti==t._ti && _bt==t._bt && _st==t._st)
        return _ot==OT_PRESENT || _ot==t._ot;
      // this is par or svar, other than that same type as t
      if ((_ti==TI_PAR || _ti==TI_SVAR) && _bt==t._bt && _st==t._st)
        return _ot==OT_PRESENT || _ot==t._ot;
      // t is svar, other than that same type as this
      if (t._ti==TI_SVAR && _bt==t._bt && _st==t._st)
        return _ot==OT_PRESENT || _ot==t._ot;
      if ( (_ti==TI_PAR || _ti==TI_SVAR) && t._bt==BT_BOT)
        return true;
      if ( _bt==BT_BOT && _st==t._st)
        return _ot==OT_PRESENT || _ot==t._ot;
      if (t._bt==BT_TOP && (_ot==OT_PRESENT || _ot==t._ot) &&
          (t._st==ST_PLAIN || _st==t._st) &&
          (_ti==TI_PAR || t._ti==TI_VAR))
        return true;
      return false;
    }

    /// Compare types
    int cmp(const Type& t) const {
      return toInt()<t.toInt() ? -1 : (toInt()>t.toInt() ? 1 : 0);
    }

  };

};

#endif
<|endoftext|>


<commit_before>#include "catch/single_include/catch.hpp"

#include "../include/dict/dict.hpp"

#include <vector>
#include <string>
#include <future>
#include <numeric>
#include <memory>

TEST_CASE("dict constructor", "[dict][constructor]") {
    SECTION("default") {
        boost::dict<int, std::string> d;
    }

    SECTION("init list") {
        boost::dict<int, int> d{{1,2}, {3,4}};

        CHECK(d[1] == 2);
        CHECK(d[3] == 4);
    }
}

struct fake_hasher {
    std::size_t operator()(int) const { return 42; }
};

TEST_CASE("dict operator[]", "[dict][operator[]]") {
    SECTION("simple operator[]") {
        boost::dict<int, std::string> d;
        CHECK(d.size() == 0);

        std::string test_string = "hello";

        d[2345] = test_string;

        CHECK(d[2345] == test_string);
        CHECK(d.size() == 1);
    }

    SECTION("operator[] collision") {
        boost::dict<int, std::string, fake_hasher> d;

        std::string test_string = "hello";
        std::string test_string2 = "hello2";

        d[1] = test_string;
        CHECK(d[1] == test_string);
        d[2] = test_string2;
        CHECK(d[2] == test_string2);
    }

    SECTION("operator[] overwrite") {
        boost::dict<int, std::string> d;

        std::string test_string = "hello";
        d[2345] = test_string;
        CHECK(d[2345] == test_string);

        std::string test_string2 = "hello2";
        d[2345] = test_string2;
        CHECK(d[2345] == test_string2);
    }
}

TEST_CASE("dict insert", "[dict][insert]") {
    SECTION("insert(value_type)") {
        boost::dict<int, int> d;
        auto res_success = d.insert(std::make_pair(1, 2));
        CHECK(res_success.first->first == 1);
        CHECK(res_success.first->second == 2);
        CHECK(res_success.second == true);
        CHECK(d[1] == 2);

        auto res_fail = d.insert(std::make_pair(1, 2));
        CHECK(res_fail.first->first == 1);
        CHECK(res_fail.first->second == 2);
        CHECK(res_fail.second == false);
    }
}

struct big_hash {
    std::size_t operator()(int x) const {
        return 1000000 + x;
    }
};

TEST_CASE("dict rehash", "[dict][rehash]") {
    SECTION("insert rehash") {
        boost::dict<int, int, big_hash> d;
        d[1] = 42;

        int i = 0;
        while(!d.next_is_rehash()) {
            d[i] = i;
            ++i;
        }

        d[42] = 42;
        CHECK(d[42] == 42);

    }

    SECTION("max_load_factor == 1") {
        boost::dict<int, int, big_hash> d;
        d.max_load_factor(1.0);

        // 11 is starting table size
        for(int i = 0; i != 11; ++i) {
            d[i] = i;
        }

        CHECK(d[10] == 10);
    }
}

struct only_moveable {
    only_moveable() = default;
    only_moveable(const only_moveable&) = delete;
    only_moveable& operator=(const only_moveable&) = delete;
    only_moveable(only_moveable&&) = default;
    only_moveable& operator=(only_moveable&&) = default;
};

TEST_CASE("dict emplace", "[dict][insert]") {
    SECTION("emplace") {
        boost::dict<int, int> d;
        auto res_success = d.emplace(1, 2);
        CHECK(res_success.first->first == 1);
        CHECK(res_success.first->second == 2);
        CHECK(res_success.second == true);
        CHECK(d[1] == 2);

        auto res_fail = d.emplace(1, 2);
        CHECK(res_fail.first->first == 1);
        CHECK(res_fail.first->second == 2);
        CHECK(res_fail.second == false);
    }

    SECTION("emplace moveable") {
        boost::dict<int, only_moveable> d;
        auto res_success = d.emplace(1, only_moveable());
        CHECK(res_success.first->first == 1);
        CHECK(res_success.second == true);

        auto res_fail = d.emplace(1, only_moveable());
        CHECK(res_fail.first->first == 1);
        CHECK(res_fail.second == false);
    }

    SECTION("emplace hint") {
        boost::dict<int, int> d;
        d[1] = 0;
        auto hint = d.find(1);
        auto res_fail = d.emplace_hint(hint, 1, 2);
        CHECK(res_fail.first->first == 1);
        CHECK(res_fail.first->second == 0);
        CHECK(res_fail.second == false);
    }
}

TEST_CASE("dict find", "[dict][find]") {
    SECTION("simple find") {
        boost::dict<int, int> d;
        auto fail_find = d.find(0);
        CHECK(fail_find == d.end());

        d[0] = 42;

        auto success_find = d.find(0);
        CHECK(success_find->first == 0);
        CHECK(success_find->second == 42);
    }
}

TEST_CASE("dict at", "[dict][at]") {
    SECTION("at") {
        boost::dict<int, int> d;
        d[0] = 1;
        CHECK(d.at(0) == 1);
        CHECK_THROWS_AS(d.at(42), std::out_of_range);
    }
}

TEST_CASE("dict count", "[dict][count]") {
        boost::dict<int, int> d;
        CHECK(d.count(0) == 0);

        d[0] = 1;

        CHECK(d.count(0) == 1);
}

TEST_CASE("equal range", "[dict][equal_range]") {
    boost::dict<int, int> d;
    d[0] = 1;

    auto range_fail = d.equal_range(42);
    for(auto iter = range_fail.first; iter != range_fail.second; ++iter) {
        CHECK(false);
    }

    auto range_success = d.equal_range(0);
    for(auto iter = range_success.first; iter != range_success.second; ++iter) {
        CHECK(iter->first == 0);
        CHECK(iter->second == 1);
    }
}

TEST_CASE("dict exists", "[dict][exists]") {}

struct destructor_check {
    destructor_check() = default;
    destructor_check(std::shared_ptr<bool> ptr) : _ptr(ptr) {}

    ~destructor_check() {
        if(_ptr) {
            *_ptr = true;
        }
    }

    std::shared_ptr<bool> _ptr;
};

TEST_CASE("dict erase", "[dict][erase]") {
    SECTION("simple erase") {
        boost::dict<int, std::string> d;

        std::string test_string = "hello";
        d[2345] = test_string;
        CHECK(d[2345] == test_string);

        CHECK(d.erase(2345) == 1);

        CHECK(d[2345] == "");

        CHECK(d.erase(2345) == 1);
        CHECK(d.erase(2345) == 0);
    }

    SECTION("erase check destructor") {
        boost::dict<int, destructor_check> d;
        auto ptr = std::make_shared<bool>(false);
        d[0] = destructor_check(ptr);

        d.erase(0);

        CHECK(*ptr == true);
    }
}

TEST_CASE("dict resize", "[dict][exists]") {
    boost::dict<int, std::string> d;
    CHECK(d.size() == 0);

    std::string test_string = "hello";

    d[2345] = test_string;

    CHECK(d[2345] == test_string);

    d.reserve(1000);
    CHECK(d.size() == 1);
    CHECK(d[2345] == test_string);
}

TEST_CASE("dict insert 1000", "[dict][stress]") {
    boost::dict<int, int> d;
    CHECK(d.size() == 0);

    for (int i = 0; i != 1000; ++i) {
        d[i] = i;
    }

    int res = 0;
    for(auto&& e: d) {
        res += e.second;
    }
    CHECK(res == 999 * 1000 / 2);
}

TEST_CASE("dict clear", "[dict][clear]") {
    boost::dict<int, int> d;
    d[1] = 2;

    d.clear();
    CHECK(d.size() == 0);
}

TEST_CASE("dict iteration", "[dict][iter]") {
    SECTION("empty iteration") {
        boost::dict<int, int> d;

        for (auto&& e : d) {
            (void)e;
            CHECK(false);
        }
    }

    SECTION("non-const iterator") {
        boost::dict<int, int> d;
        d[1] = 42;

        for (auto&& e : d) {
            CHECK(e.first == 1);
            CHECK(e.second == 42);
        }
    }

    SECTION("const iteration") {
        boost::dict<int, int> d;
        d[1] = 42;

        const auto& const_d = d;

        for (const auto& e : const_d) {
            CHECK(e.first == 1);
            CHECK(e.second == 42);
        }
    }

    SECTION("cbegin/cend iteration") {
        boost::dict<int, int> d;
        d[1] = 42;

        for (auto iter = d.cbegin(); iter != d.cend(); ++iter) {
            CHECK(iter->first == 1);
            CHECK(iter->second == 42);
        }
    }

    SECTION("skip iterator") {
        // relies on identity hashing for integers
        boost::dict<int, int> d;
        d[1] = 1;
        d[3] = 3;
        d[6] = 6;

        std::vector<int> keys;
        std::vector<int> values;
        for (auto&& e : d) {
            keys.push_back(e.first);
            values.push_back(e.second);
        }

        CHECK(keys == std::vector<int>({ 1, 3, 6 }));
        CHECK(values == std::vector<int>({ 1, 3, 6 }));
    }

    SECTION("modify") {
        boost::dict<int, int> d;
        d[1] = 42;

        for (auto&& e : d) {
            e.second = 21;
        }
        CHECK(d[1] == 21);
    }

    SECTION("const key") {
        boost::dict<int, int> d;
        static_assert(
            std::is_same<const int, decltype(d.begin()->first)>::value,
            "no const key");
    }
}
<commit_msg>added another constructor test<commit_after>#include "catch/single_include/catch.hpp"

#include "../include/dict/dict.hpp"

#include <vector>
#include <string>
#include <future>
#include <numeric>
#include <memory>

TEST_CASE("dict constructor", "[dict][constructor]") {
    SECTION("default") {
        boost::dict<int, std::string> d;
    }

    SECTION("iterators") {
        std::vector<std::pair<int, int>> v{{1, 2}, {3, 4}, {1, 42}};

        boost::dict<int, int> d(v.begin(), v.end());

        CHECK(d[1] == 2);
        CHECK(d[3] == 4);
    }

    SECTION("init list") {
        boost::dict<int, int> d{{1, 2}, {3, 4}, {1, 42}};

        CHECK(d[1] == 2);
        CHECK(d[3] == 4);
    }
}

struct fake_hasher {
    std::size_t operator()(int) const { return 42; }
};

TEST_CASE("dict operator[]", "[dict][operator[]]") {
    SECTION("simple operator[]") {
        boost::dict<int, std::string> d;
        CHECK(d.size() == 0);

        std::string test_string = "hello";

        d[2345] = test_string;

        CHECK(d[2345] == test_string);
        CHECK(d.size() == 1);
    }

    SECTION("operator[] collision") {
        boost::dict<int, std::string, fake_hasher> d;

        std::string test_string = "hello";
        std::string test_string2 = "hello2";

        d[1] = test_string;
        CHECK(d[1] == test_string);
        d[2] = test_string2;
        CHECK(d[2] == test_string2);
    }

    SECTION("operator[] overwrite") {
        boost::dict<int, std::string> d;

        std::string test_string = "hello";
        d[2345] = test_string;
        CHECK(d[2345] == test_string);

        std::string test_string2 = "hello2";
        d[2345] = test_string2;
        CHECK(d[2345] == test_string2);
    }
}

TEST_CASE("dict insert", "[dict][insert]") {
    SECTION("insert(value_type)") {
        boost::dict<int, int> d;
        auto res_success = d.insert(std::make_pair(1, 2));
        CHECK(res_success.first->first == 1);
        CHECK(res_success.first->second == 2);
        CHECK(res_success.second == true);
        CHECK(d[1] == 2);

        auto res_fail = d.insert(std::make_pair(1, 2));
        CHECK(res_fail.first->first == 1);
        CHECK(res_fail.first->second == 2);
        CHECK(res_fail.second == false);
    }
}

struct big_hash {
    std::size_t operator()(int x) const {
        return 1000000 + x;
    }
};

TEST_CASE("dict rehash", "[dict][rehash]") {
    SECTION("insert rehash") {
        boost::dict<int, int, big_hash> d;
        d[1] = 42;

        int i = 0;
        while(!d.next_is_rehash()) {
            d[i] = i;
            ++i;
        }

        d[42] = 42;
        CHECK(d[42] == 42);

    }

    SECTION("max_load_factor == 1") {
        boost::dict<int, int, big_hash> d;
        d.max_load_factor(1.0);

        // 11 is starting table size
        for(int i = 0; i != 11; ++i) {
            d[i] = i;
        }

        CHECK(d[10] == 10);
    }
}

struct only_moveable {
    only_moveable() = default;
    only_moveable(const only_moveable&) = delete;
    only_moveable& operator=(const only_moveable&) = delete;
    only_moveable(only_moveable&&) = default;
    only_moveable& operator=(only_moveable&&) = default;
};

TEST_CASE("dict emplace", "[dict][insert]") {
    SECTION("emplace") {
        boost::dict<int, int> d;
        auto res_success = d.emplace(1, 2);
        CHECK(res_success.first->first == 1);
        CHECK(res_success.first->second == 2);
        CHECK(res_success.second == true);
        CHECK(d[1] == 2);

        auto res_fail = d.emplace(1, 2);
        CHECK(res_fail.first->first == 1);
        CHECK(res_fail.first->second == 2);
        CHECK(res_fail.second == false);
    }

    SECTION("emplace moveable") {
        boost::dict<int, only_moveable> d;
        auto res_success = d.emplace(1, only_moveable());
        CHECK(res_success.first->first == 1);
        CHECK(res_success.second == true);

        auto res_fail = d.emplace(1, only_moveable());
        CHECK(res_fail.first->first == 1);
        CHECK(res_fail.second == false);
    }

    SECTION("emplace hint") {
        boost::dict<int, int> d;
        d[1] = 0;
        auto hint = d.find(1);
        auto res_fail = d.emplace_hint(hint, 1, 2);
        CHECK(res_fail.first->first == 1);
        CHECK(res_fail.first->second == 0);
        CHECK(res_fail.second == false);
    }
}

TEST_CASE("dict find", "[dict][find]") {
    SECTION("simple find") {
        boost::dict<int, int> d;
        auto fail_find = d.find(0);
        CHECK(fail_find == d.end());

        d[0] = 42;

        auto success_find = d.find(0);
        CHECK(success_find->first == 0);
        CHECK(success_find->second == 42);
    }
}

TEST_CASE("dict at", "[dict][at]") {
    SECTION("at") {
        boost::dict<int, int> d;
        d[0] = 1;
        CHECK(d.at(0) == 1);
        CHECK_THROWS_AS(d.at(42), std::out_of_range);
    }
}

TEST_CASE("dict count", "[dict][count]") {
        boost::dict<int, int> d;
        CHECK(d.count(0) == 0);

        d[0] = 1;

        CHECK(d.count(0) == 1);
}

TEST_CASE("equal range", "[dict][equal_range]") {
    boost::dict<int, int> d;
    d[0] = 1;

    auto range_fail = d.equal_range(42);
    for(auto iter = range_fail.first; iter != range_fail.second; ++iter) {
        CHECK(false);
    }

    auto range_success = d.equal_range(0);
    for(auto iter = range_success.first; iter != range_success.second; ++iter) {
        CHECK(iter->first == 0);
        CHECK(iter->second == 1);
    }
}

TEST_CASE("dict exists", "[dict][exists]") {}

struct destructor_check {
    destructor_check() = default;
    destructor_check(std::shared_ptr<bool> ptr) : _ptr(ptr) {}

    ~destructor_check() {
        if(_ptr) {
            *_ptr = true;
        }
    }

    std::shared_ptr<bool> _ptr;
};

TEST_CASE("dict erase", "[dict][erase]") {
    SECTION("simple erase") {
        boost::dict<int, std::string> d;

        std::string test_string = "hello";
        d[2345] = test_string;
        CHECK(d[2345] == test_string);

        CHECK(d.erase(2345) == 1);

        CHECK(d[2345] == "");

        CHECK(d.erase(2345) == 1);
        CHECK(d.erase(2345) == 0);
    }

    SECTION("erase check destructor") {
        boost::dict<int, destructor_check> d;
        auto ptr = std::make_shared<bool>(false);
        d[0] = destructor_check(ptr);

        d.erase(0);

        CHECK(*ptr == true);
    }
}

TEST_CASE("dict resize", "[dict][exists]") {
    boost::dict<int, std::string> d;
    CHECK(d.size() == 0);

    std::string test_string = "hello";

    d[2345] = test_string;

    CHECK(d[2345] == test_string);

    d.reserve(1000);
    CHECK(d.size() == 1);
    CHECK(d[2345] == test_string);
}

TEST_CASE("dict insert 1000", "[dict][stress]") {
    boost::dict<int, int> d;
    CHECK(d.size() == 0);

    for (int i = 0; i != 1000; ++i) {
        d[i] = i;
    }

    int res = 0;
    for(auto&& e: d) {
        res += e.second;
    }
    CHECK(res == 999 * 1000 / 2);
}

TEST_CASE("dict clear", "[dict][clear]") {
    boost::dict<int, int> d;
    d[1] = 2;

    d.clear();
    CHECK(d.size() == 0);
}

TEST_CASE("dict iteration", "[dict][iter]") {
    SECTION("empty iteration") {
        boost::dict<int, int> d;

        for (auto&& e : d) {
            (void)e;
            CHECK(false);
        }
    }

    SECTION("non-const iterator") {
        boost::dict<int, int> d;
        d[1] = 42;

        for (auto&& e : d) {
            CHECK(e.first == 1);
            CHECK(e.second == 42);
        }
    }

    SECTION("const iteration") {
        boost::dict<int, int> d;
        d[1] = 42;

        const auto& const_d = d;

        for (const auto& e : const_d) {
            CHECK(e.first == 1);
            CHECK(e.second == 42);
        }
    }

    SECTION("cbegin/cend iteration") {
        boost::dict<int, int> d;
        d[1] = 42;

        for (auto iter = d.cbegin(); iter != d.cend(); ++iter) {
            CHECK(iter->first == 1);
            CHECK(iter->second == 42);
        }
    }

    SECTION("skip iterator") {
        // relies on identity hashing for integers
        boost::dict<int, int> d;
        d[1] = 1;
        d[3] = 3;
        d[6] = 6;

        std::vector<int> keys;
        std::vector<int> values;
        for (auto&& e : d) {
            keys.push_back(e.first);
            values.push_back(e.second);
        }

        CHECK(keys == std::vector<int>({ 1, 3, 6 }));
        CHECK(values == std::vector<int>({ 1, 3, 6 }));
    }

    SECTION("modify") {
        boost::dict<int, int> d;
        d[1] = 42;

        for (auto&& e : d) {
            e.second = 21;
        }
        CHECK(d[1] == 21);
    }

    SECTION("const key") {
        boost::dict<int, int> d;
        static_assert(
            std::is_same<const int, decltype(d.begin()->first)>::value,
            "no const key");
    }
}
<|endoftext|>