<commit_before>/*
 * Copyright 2015 Georgia Institute of Technology
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file    rmq.hpp
 * @author  Patrick Flick <patrick.flick@gmail.com>
 * @brief   Implements a succinct Range-Minimum-Query in a STL compatible format.
 */
#ifndef RMQ_HPP
#define RMQ_HPP

#include <vector>
#include <iterator>
#include <limits>
#include <algorithm>
#include <iostream>
//#include <cstdint>
#include <stdint.h>
#include <assert.h>

#include "bitops.hpp"

template<typename Iterator, typename index_t = std::size_t>
class rmq {
public:
    // superblock size is log^(2+epsilon)(n)
    // we choose it as bitsize^2:
    //  - 64 bits -> 4096
    //  - 32 bits -> 1024
    //  - both bound by 2^16 -> uint16_t
    //  block size: one cache line
    const static int DEFAULT_BLOCK_SIZE = 64/sizeof(index_t);
    // cache line of blocks per superblock
    const static int DEFAULT_SUPERBLOCK_SIZE = 64/sizeof(uint16_t) * 64/sizeof(index_t);
protected:
    index_t n;

    // the original sequence
    Iterator _begin;
    Iterator _end;
    // level sizes
    index_t superblock_size;
    index_t block_size;

    // number of blocks per level
    index_t n_blocks;
    index_t n_superblocks;
    index_t n_blocks_per_superblock;

    // saves minimum as block index for combination of superblocks relative to
    // global start index
    std::vector<std::vector<index_t> > superblock_mins;
    // saves minimum for combination of blocks relative to superblock start
    // index
    std::vector<std::vector<uint16_t> > block_mins;

public:
    rmq(Iterator begin, Iterator end,
        index_t superblock_size = DEFAULT_SUPERBLOCK_SIZE,
        index_t block_size = DEFAULT_BLOCK_SIZE)
        : _begin(begin), _end(end), superblock_size(superblock_size), block_size(block_size)
    {
        // get size
        assert((index_t)std::distance(begin, end) < std::numeric_limits<index_t>::max());
        n = std::distance(begin, end);

        // superblock size should be divisable by block size
        assert(superblock_size % block_size == 0);

        // get number of blocks
        n_superblocks = (n-1) / superblock_size + 1;
        n_blocks = (n-1) / block_size + 1;
        n_blocks_per_superblock = superblock_size / block_size;

        assert(superblock_size-1 <= std::numeric_limits<uint16_t>::max());

        // start by finding index of mins per block
        // for each superblock
        superblock_mins.push_back(std::vector<index_t>(n_superblocks));
        block_mins.push_back(std::vector<uint16_t>(n_blocks));
        Iterator it = begin;
        while (it != end) {
            // find index of minimum block in superblock
            Iterator min_pos = it;
            Iterator sb_end_it = it;
            std::advance(sb_end_it, std::min<std::size_t>(std::distance(it, end), superblock_size));
            for (Iterator block_it = it; block_it != sb_end_it; ) {
                Iterator block_end_it = block_it;
                std::advance(block_end_it, std::min<std::size_t>(std::distance(block_it, end), block_size));
                Iterator block_min_pos = std::min_element(block_it, block_end_it);
                // save minimum for superblock min
                if (*block_min_pos < *min_pos) {
                    min_pos = block_min_pos;
                }
                // save minimum for block min, relative to superblock start
                index_t block_min_idx = static_cast<index_t>(std::distance(it, block_min_pos));
                assert(block_min_idx < superblock_size);
                block_mins[0][std::distance(begin, block_it) / block_size] = static_cast<uint16_t>(block_min_idx);
                block_it = block_end_it;
            }
            superblock_mins[0][std::distance(begin, it) / superblock_size] = static_cast<index_t>(std::distance(begin, min_pos));
            it = sb_end_it;
        }

        // fill superblock lookup with dynamic programming
        index_t level = 1;
        for (index_t dist = 2; dist/2 < n_superblocks; dist <<= 1) {
            superblock_mins.push_back(std::vector<index_t>(n_superblocks - dist/2));
            for (index_t i = 0; i+dist/2 < n_superblocks; ++i) {
                index_t right_idx = std::min(i+dist/2, n_superblocks-dist/4-1);
                if (*(begin + superblock_mins[level-1][right_idx]) < *(begin + superblock_mins[level-1][i])) {
                    assert(i < superblock_mins.back().size());
                    assert(superblock_mins.size() == level+1);
                    assert(superblock_mins[level-1].size() > right_idx);
                    superblock_mins.back()[i] = superblock_mins[level-1][right_idx];
                } else {
                    assert(i < superblock_mins.back().size());
                    assert(superblock_mins.size() == level+1);
                    superblock_mins.back()[i] = superblock_mins[level-1][i];
                }
            }
            level++;
        }

        // now the same thing for blocks (but index relative to their
        // superblock)
        level = 1;
        index_t last_sb_nblocks = n_blocks - (n_superblocks-1)*n_blocks_per_superblock;
        for (index_t dist = 2; dist/2 < std::min(n_blocks,n_blocks_per_superblock); dist <<= 1) {
            if (n_blocks - n_superblocks*dist/2 == 0)
                break;
            index_t last_sb_cur_nblocks = 0;
            if (last_sb_nblocks > dist/2)
                last_sb_cur_nblocks = last_sb_nblocks - dist/2;
            block_mins.push_back(std::vector<uint16_t>((n_superblocks-1)*(n_blocks_per_superblock - dist/2) + last_sb_cur_nblocks));
            for (index_t sb = 0; sb < n_superblocks; ++sb) {
                index_t pre_sb_offset = sb*(n_blocks_per_superblock - dist/4);
                index_t sb_offset = sb*(n_blocks_per_superblock - dist/2);
                index_t blocks_in_sb = std::min(n_blocks - sb*n_blocks_per_superblock, n_blocks_per_superblock);
                for (index_t i = 0; i+dist/2 < blocks_in_sb; ++i) {
                    // TODO: right_idx might become negative for last superblock??
                    index_t right_idx = std::min(i + dist/2, blocks_in_sb-dist/4-1);
                    if (*(begin + block_mins[level-1][right_idx+pre_sb_offset] + sb*superblock_size)
                      < *(begin + block_mins[level-1][i        +pre_sb_offset] + sb*superblock_size))
                    {
                        block_mins.back()[i+sb_offset] = block_mins[level-1][right_idx+pre_sb_offset];
                    } else {
                        block_mins.back()[i+sb_offset] = block_mins[level-1][i+pre_sb_offset];
                    }
                }
            }
            level++;
        }

        //assert(check_superblock_correctness());
        //assert(check_block_correctness());
    }

    Iterator query(Iterator range_begin, Iterator range_end) {
        // find superblocks fully contained within range
        index_t begin_idx = std::distance(_begin, range_begin);
        index_t end_idx = std::distance(_begin, range_end);
        assert(begin_idx < end_idx);
        assert(end_idx <= n);

        // round up to next superblock
        index_t left_sb  = (begin_idx - 1) / superblock_size + 1;
        if (begin_idx == 0)
            left_sb = 0;
        // round down to prev superblock
        index_t right_sb = end_idx / superblock_size;

        // init result
        Iterator min_pos = range_begin;

        // if there is at least one superblock
        if (left_sb < right_sb) {
            // get largest power of two that doesn't exceed the number of
            // superblocks from (left,right)
            index_t n_sb = right_sb - left_sb;
            unsigned int dist = floorlog2(n_sb);

            assert(dist < superblock_mins.size() && left_sb < superblock_mins[dist].size());
            min_pos = _begin + superblock_mins[dist][left_sb];
            assert(dist < superblock_mins.size() && right_sb - (1<<dist) < superblock_mins[dist].size());
            Iterator right_sb_min = _begin + superblock_mins[dist][right_sb - (1 << dist)];
            if (*right_sb_min < *min_pos) {
                min_pos = right_sb_min;
            }
        }

        // go to left -> blocks -> sub-block
        if (left_sb <= right_sb && left_sb != 0 && begin_idx != left_sb*superblock_size) {
            index_t left_b = (begin_idx - 1) / block_size + 1;
            index_t left_b_gidx = left_b * block_size;
            left_b -= (left_sb - 1)*n_blocks_per_superblock;
            index_t n_b = n_blocks_per_superblock - left_b;
            if (n_b > 0) {
                unsigned int level = ceillog2(n_b);
                index_t sb_offset = (left_sb-1)*(n_blocks_per_superblock - (1<<level)/2);
                Iterator block_min_it = _begin + block_mins[level][left_b + sb_offset] + (left_sb-1)*superblock_size;
                // return this new min if its the same or smaller
                if (!(*min_pos < *block_min_it))
                    min_pos = block_min_it;
            }

            // go left into remaining block, if elements left
            if (left_b_gidx > begin_idx) {
                // linearly search (at most block_size elements)
                Iterator inblock_min_it = std::min_element(range_begin, _begin + left_b_gidx);
                if (!(*min_pos < *inblock_min_it)) {
                    min_pos = inblock_min_it;
                }
            }
        }

        // go to right -> blocks -> sub-block
        if (left_sb <= right_sb && right_sb != n_superblocks && end_idx != right_sb*superblock_size) {
            index_t left_b = right_sb*n_blocks_per_superblock;
            index_t right_b = end_idx / block_size;
            index_t n_b = right_b - left_b;
            if (n_b > 0) {
                unsigned int dist = floorlog2(n_b);
                index_t sb_offset = right_sb*((1<<dist)/2);
                Iterator block_min_it = _begin + block_mins[dist][left_b - sb_offset] + (right_sb)*superblock_size;
                if (*block_min_it < *min_pos)
                    min_pos = block_min_it;
                block_min_it = _begin + block_mins[dist][right_b - sb_offset - (1<<dist)] + (right_sb)*superblock_size;
                if (*block_min_it < *min_pos)
                    min_pos = block_min_it;
            }

            // go right into remaining block, if elements left
            index_t left_gl_idx = right_b*block_size;
            if (left_gl_idx < end_idx) {
                // linearly search (at most block_size elements)
                Iterator inblock_min_it = std::min_element(_begin + left_gl_idx, range_end);
                if (*inblock_min_it < *min_pos) {
                    min_pos = inblock_min_it;
                }
            }
        }

        // if there are no superblocks covered (both indeces in same superblock)
        if (left_sb > right_sb) {
            index_t left_b = (begin_idx - 1) / block_size + 1;
            if (begin_idx == 0)
                left_b = 0;
            index_t right_b = end_idx / block_size;

            if (left_b < right_b) {
                // if blocks are in between: get mins of blocks in range
                // NOTE: there was a while if-else block here to handle the
                //       case if blocks would span accross the boundary of two
                //       superblocks, this should however never happen
                //       git blame this line to find where this code was removed
                // assert blocks lie in the same superblock
                assert(left_b / n_blocks_per_superblock == right_b / n_blocks_per_superblock);

                unsigned int dist = floorlog2(right_b - left_b);
                index_t sb_offset = 0;
                index_t sb_size_offset = 0;
                if (left_sb > 1) {
                    sb_offset = (left_sb-1)*((1<<dist)/2);
                    sb_size_offset = (left_sb-1)*superblock_size;
                }
                Iterator block_min_it = _begin + block_mins[dist][left_b - sb_offset] + sb_size_offset;
                if (*block_min_it < *min_pos)
                    min_pos = block_min_it;
                block_min_it = _begin + block_mins[dist][right_b - sb_offset - (1<<dist)] + sb_size_offset;
                if (*block_min_it < *min_pos)
                    min_pos = block_min_it;

                // remaining inblock
                if (begin_idx < left_b*block_size) {
                    Iterator inblock_min_it = std::min_element(range_begin, _begin + left_b*block_size);
                    if (!(*min_pos < *inblock_min_it)) {
                        min_pos = inblock_min_it;
                    }
                }
                if (end_idx > right_b*block_size) {
                    Iterator inblock_min_it = std::min_element(_begin + right_b*block_size, range_end);
                    if (*inblock_min_it < *min_pos) {
                        min_pos = inblock_min_it;
                    }
                }
            } else {
                // no blocks at all
                Iterator inblock_min_it = std::min_element(range_begin, range_end);
                if (*inblock_min_it < *min_pos) {
                    min_pos = inblock_min_it;
                }
            }

        }

        // return the minimum found
        return min_pos;
    }
}; // class rmq

#endif // RMQ_HPP
<commit_msg>fix rmq class properties<commit_after>/*
 * Copyright 2015 Georgia Institute of Technology
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file    rmq.hpp
 * @author  Patrick Flick <patrick.flick@gmail.com>
 * @brief   Implements a succinct Range-Minimum-Query in a STL compatible format.
 */
#ifndef RMQ_HPP
#define RMQ_HPP

#include <vector>
#include <iterator>
#include <limits>
#include <algorithm>
#include <iostream>
//#include <cstdint>
#include <stdint.h>
#include <assert.h>

#include "bitops.hpp"

template<typename Iterator, typename index_t = std::size_t>
class rmq {
public:
    // superblock size is log^(2+epsilon)(n)
    // we choose it as bitsize^2:
    //  - 64 bits -> 4096
    //  - 32 bits -> 1024
    //  - both bound by 2^16 -> uint16_t
    //  block size: one cache line
    const static int DEFAULT_BLOCK_SIZE = 64/sizeof(index_t);
    // cache line of blocks per superblock
    const static int DEFAULT_SUPERBLOCK_SIZE = 64/sizeof(uint16_t) * 64/sizeof(index_t);
protected:
    index_t n;

    // the original sequence
    Iterator _begin;
    Iterator _end;
    // level sizes
    index_t superblock_size;
    index_t block_size;

    // number of blocks per level
    index_t n_blocks;
    index_t n_superblocks;
    index_t n_blocks_per_superblock;

    // saves minimum as block index for combination of superblocks relative to
    // global start index
    std::vector<std::vector<index_t> > superblock_mins;
    // saves minimum for combination of blocks relative to superblock start
    // index
    std::vector<std::vector<uint16_t> > block_mins;

public:

    rmq() : n(0) {}

    rmq(const rmq& o) = default;
    rmq(rmq&& o) = default;
    rmq& operator=(const rmq& o) = default;
    rmq& operator=(rmq&& o) = default;

    rmq(Iterator begin, Iterator end,
        index_t superblock_size = DEFAULT_SUPERBLOCK_SIZE,
        index_t block_size = DEFAULT_BLOCK_SIZE)
        : _begin(begin), _end(end), superblock_size(superblock_size), block_size(block_size)
    {
        // get size
        assert((index_t)std::distance(begin, end) < std::numeric_limits<index_t>::max());
        n = std::distance(begin, end);

        // superblock size should be divisable by block size
        assert(superblock_size % block_size == 0);

        // get number of blocks
        n_superblocks = (n-1) / superblock_size + 1;
        n_blocks = (n-1) / block_size + 1;
        n_blocks_per_superblock = superblock_size / block_size;

        assert(superblock_size-1 <= std::numeric_limits<uint16_t>::max());

        // start by finding index of mins per block
        // for each superblock
        superblock_mins.push_back(std::vector<index_t>(n_superblocks));
        block_mins.push_back(std::vector<uint16_t>(n_blocks));
        Iterator it = begin;
        while (it != end) {
            // find index of minimum block in superblock
            Iterator min_pos = it;
            Iterator sb_end_it = it;
            std::advance(sb_end_it, std::min<std::size_t>(std::distance(it, end), superblock_size));
            for (Iterator block_it = it; block_it != sb_end_it; ) {
                Iterator block_end_it = block_it;
                std::advance(block_end_it, std::min<std::size_t>(std::distance(block_it, end), block_size));
                Iterator block_min_pos = std::min_element(block_it, block_end_it);
                // save minimum for superblock min
                if (*block_min_pos < *min_pos) {
                    min_pos = block_min_pos;
                }
                // save minimum for block min, relative to superblock start
                index_t block_min_idx = static_cast<index_t>(std::distance(it, block_min_pos));
                assert(block_min_idx < superblock_size);
                block_mins[0][std::distance(begin, block_it) / block_size] = static_cast<uint16_t>(block_min_idx);
                block_it = block_end_it;
            }
            superblock_mins[0][std::distance(begin, it) / superblock_size] = static_cast<index_t>(std::distance(begin, min_pos));
            it = sb_end_it;
        }

        // fill superblock lookup with dynamic programming
        index_t level = 1;
        for (index_t dist = 2; dist/2 < n_superblocks; dist <<= 1) {
            superblock_mins.push_back(std::vector<index_t>(n_superblocks - dist/2));
            for (index_t i = 0; i+dist/2 < n_superblocks; ++i) {
                index_t right_idx = std::min(i+dist/2, n_superblocks-dist/4-1);
                if (*(begin + superblock_mins[level-1][right_idx]) < *(begin + superblock_mins[level-1][i])) {
                    assert(i < superblock_mins.back().size());
                    assert(superblock_mins.size() == level+1);
                    assert(superblock_mins[level-1].size() > right_idx);
                    superblock_mins.back()[i] = superblock_mins[level-1][right_idx];
                } else {
                    assert(i < superblock_mins.back().size());
                    assert(superblock_mins.size() == level+1);
                    superblock_mins.back()[i] = superblock_mins[level-1][i];
                }
            }
            level++;
        }

        // now the same thing for blocks (but index relative to their
        // superblock)
        level = 1;
        index_t last_sb_nblocks = n_blocks - (n_superblocks-1)*n_blocks_per_superblock;
        for (index_t dist = 2; dist/2 < std::min(n_blocks,n_blocks_per_superblock); dist <<= 1) {
            if (n_blocks - n_superblocks*dist/2 == 0)
                break;
            index_t last_sb_cur_nblocks = 0;
            if (last_sb_nblocks > dist/2)
                last_sb_cur_nblocks = last_sb_nblocks - dist/2;
            block_mins.push_back(std::vector<uint16_t>((n_superblocks-1)*(n_blocks_per_superblock - dist/2) + last_sb_cur_nblocks));
            for (index_t sb = 0; sb < n_superblocks; ++sb) {
                index_t pre_sb_offset = sb*(n_blocks_per_superblock - dist/4);
                index_t sb_offset = sb*(n_blocks_per_superblock - dist/2);
                index_t blocks_in_sb = std::min(n_blocks - sb*n_blocks_per_superblock, n_blocks_per_superblock);
                for (index_t i = 0; i+dist/2 < blocks_in_sb; ++i) {
                    // TODO: right_idx might become negative for last superblock??
                    index_t right_idx = std::min(i + dist/2, blocks_in_sb-dist/4-1);
                    if (*(begin + block_mins[level-1][right_idx+pre_sb_offset] + sb*superblock_size)
                      < *(begin + block_mins[level-1][i        +pre_sb_offset] + sb*superblock_size))
                    {
                        block_mins.back()[i+sb_offset] = block_mins[level-1][right_idx+pre_sb_offset];
                    } else {
                        block_mins.back()[i+sb_offset] = block_mins[level-1][i+pre_sb_offset];
                    }
                }
            }
            level++;
        }

        //assert(check_superblock_correctness());
        //assert(check_block_correctness());
    }

    Iterator query(Iterator range_begin, Iterator range_end) const {
        // find superblocks fully contained within range
        index_t begin_idx = std::distance(_begin, range_begin);
        index_t end_idx = std::distance(_begin, range_end);
        assert(begin_idx < end_idx);
        assert(end_idx <= n);

        // round up to next superblock
        index_t left_sb  = (begin_idx - 1) / superblock_size + 1;
        if (begin_idx == 0)
            left_sb = 0;
        // round down to prev superblock
        index_t right_sb = end_idx / superblock_size;

        // init result
        Iterator min_pos = range_begin;

        // if there is at least one superblock
        if (left_sb < right_sb) {
            // get largest power of two that doesn't exceed the number of
            // superblocks from (left,right)
            index_t n_sb = right_sb - left_sb;
            unsigned int dist = floorlog2(n_sb);

            assert(dist < superblock_mins.size() && left_sb < superblock_mins[dist].size());
            min_pos = _begin + superblock_mins[dist][left_sb];
            assert(dist < superblock_mins.size() && right_sb - (1<<dist) < superblock_mins[dist].size());
            Iterator right_sb_min = _begin + superblock_mins[dist][right_sb - (1 << dist)];
            if (*right_sb_min < *min_pos) {
                min_pos = right_sb_min;
            }
        }

        // go to left -> blocks -> sub-block
        if (left_sb <= right_sb && left_sb != 0 && begin_idx != left_sb*superblock_size) {
            index_t left_b = (begin_idx - 1) / block_size + 1;
            index_t left_b_gidx = left_b * block_size;
            left_b -= (left_sb - 1)*n_blocks_per_superblock;
            index_t n_b = n_blocks_per_superblock - left_b;
            if (n_b > 0) {
                unsigned int level = ceillog2(n_b);
                index_t sb_offset = (left_sb-1)*(n_blocks_per_superblock - (1<<level)/2);
                Iterator block_min_it = _begin + block_mins[level][left_b + sb_offset] + (left_sb-1)*superblock_size;
                // return this new min if its the same or smaller
                if (!(*min_pos < *block_min_it))
                    min_pos = block_min_it;
            }

            // go left into remaining block, if elements left
            if (left_b_gidx > begin_idx) {
                // linearly search (at most block_size elements)
                Iterator inblock_min_it = std::min_element(range_begin, _begin + left_b_gidx);
                if (!(*min_pos < *inblock_min_it)) {
                    min_pos = inblock_min_it;
                }
            }
        }

        // go to right -> blocks -> sub-block
        if (left_sb <= right_sb && right_sb != n_superblocks && end_idx != right_sb*superblock_size) {
            index_t left_b = right_sb*n_blocks_per_superblock;
            index_t right_b = end_idx / block_size;
            index_t n_b = right_b - left_b;
            if (n_b > 0) {
                unsigned int dist = floorlog2(n_b);
                index_t sb_offset = right_sb*((1<<dist)/2);
                Iterator block_min_it = _begin + block_mins[dist][left_b - sb_offset] + (right_sb)*superblock_size;
                if (*block_min_it < *min_pos)
                    min_pos = block_min_it;
                block_min_it = _begin + block_mins[dist][right_b - sb_offset - (1<<dist)] + (right_sb)*superblock_size;
                if (*block_min_it < *min_pos)
                    min_pos = block_min_it;
            }

            // go right into remaining block, if elements left
            index_t left_gl_idx = right_b*block_size;
            if (left_gl_idx < end_idx) {
                // linearly search (at most block_size elements)
                Iterator inblock_min_it = std::min_element(_begin + left_gl_idx, range_end);
                if (*inblock_min_it < *min_pos) {
                    min_pos = inblock_min_it;
                }
            }
        }

        // if there are no superblocks covered (both indeces in same superblock)
        if (left_sb > right_sb) {
            index_t left_b = (begin_idx - 1) / block_size + 1;
            if (begin_idx == 0)
                left_b = 0;
            index_t right_b = end_idx / block_size;

            if (left_b < right_b) {
                // if blocks are in between: get mins of blocks in range
                // NOTE: there was a while if-else block here to handle the
                //       case if blocks would span accross the boundary of two
                //       superblocks, this should however never happen
                //       git blame this line to find where this code was removed
                // assert blocks lie in the same superblock
                assert(left_b / n_blocks_per_superblock == right_b / n_blocks_per_superblock);

                unsigned int dist = floorlog2(right_b - left_b);
                index_t sb_offset = 0;
                index_t sb_size_offset = 0;
                if (left_sb > 1) {
                    sb_offset = (left_sb-1)*((1<<dist)/2);
                    sb_size_offset = (left_sb-1)*superblock_size;
                }
                Iterator block_min_it = _begin + block_mins[dist][left_b - sb_offset] + sb_size_offset;
                if (*block_min_it < *min_pos)
                    min_pos = block_min_it;
                block_min_it = _begin + block_mins[dist][right_b - sb_offset - (1<<dist)] + sb_size_offset;
                if (*block_min_it < *min_pos)
                    min_pos = block_min_it;

                // remaining inblock
                if (begin_idx < left_b*block_size) {
                    Iterator inblock_min_it = std::min_element(range_begin, _begin + left_b*block_size);
                    if (!(*min_pos < *inblock_min_it)) {
                        min_pos = inblock_min_it;
                    }
                }
                if (end_idx > right_b*block_size) {
                    Iterator inblock_min_it = std::min_element(_begin + right_b*block_size, range_end);
                    if (*inblock_min_it < *min_pos) {
                        min_pos = inblock_min_it;
                    }
                }
            } else {
                // no blocks at all
                Iterator inblock_min_it = std::min_element(range_begin, range_end);
                if (*inblock_min_it < *min_pos) {
                    min_pos = inblock_min_it;
                }
            }

        }

        // return the minimum found
        return min_pos;
    }
}; // class rmq

#endif // RMQ_HPP
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ipc/mojo/ipc_channel_mojo.h"

#include "base/base_paths.h"
#include "base/files/file.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/pickle.h"
#include "base/threading/thread.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_test_base.h"
#include "ipc/ipc_test_channel_listener.h"
#include "ipc/mojo/ipc_channel_mojo_host.h"
#include "ipc/mojo/ipc_channel_mojo_readers.h"

#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
#endif

namespace {

class ListenerThatExpectsOK : public IPC::Listener {
 public:
  ListenerThatExpectsOK()
      : received_ok_(false) {}

  virtual ~ListenerThatExpectsOK() {}

  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
    PickleIterator iter(message);
    std::string should_be_ok;
    EXPECT_TRUE(iter.ReadString(&should_be_ok));
    EXPECT_EQ(should_be_ok, "OK");
    received_ok_ = true;
    base::MessageLoop::current()->Quit();
    return true;
  }

  virtual void OnChannelError() OVERRIDE {
    // The connection should be healthy while the listener is waiting
    // message.  An error can occur after that because the peer
    // process dies.
    DCHECK(received_ok_);
  }

  static void SendOK(IPC::Sender* sender) {
    IPC::Message* message = new IPC::Message(
        0, 2, IPC::Message::PRIORITY_NORMAL);
    message->WriteString(std::string("OK"));
    ASSERT_TRUE(sender->Send(message));
  }

 private:
  bool received_ok_;
};

class ChannelClient {
 public:
  explicit ChannelClient(IPC::Listener* listener, const char* name) {
    channel_ = IPC::ChannelMojo::Create(NULL,
                                        IPCTestBase::GetChannelName(name),
                                        IPC::Channel::MODE_CLIENT,
                                        listener);
  }

  void Connect() {
    CHECK(channel_->Connect());
  }

  IPC::ChannelMojo* channel() const { return channel_.get(); }

 private:
  base::MessageLoopForIO main_message_loop_;
  scoped_ptr<IPC::ChannelMojo> channel_;
};

class IPCChannelMojoTest : public IPCTestBase {
 protected:
  virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
      const IPC::ChannelHandle& handle,
      base::TaskRunner* runner) OVERRIDE {
    host_.reset(new IPC::ChannelMojoHost(task_runner()));
    return IPC::ChannelMojo::CreateServerFactory(host_.get(), handle);
  }

  virtual bool DidStartClient() OVERRIDE {
    bool ok = IPCTestBase::DidStartClient();
    DCHECK(ok);
    host_->OnClientLaunched(client_process());
    return ok;
  }

 private:
  scoped_ptr<IPC::ChannelMojoHost> host_;
};

class TestChannelListenerWithExtraExpectations
    : public IPC::TestChannelListener {
 public:
  TestChannelListenerWithExtraExpectations()
      : is_connected_called_(false) {
  }

  virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
    IPC::TestChannelListener::OnChannelConnected(peer_pid);
    EXPECT_TRUE(base::kNullProcessId != peer_pid);
    is_connected_called_ = true;
  }

  bool is_connected_called() const { return is_connected_called_; }

 private:
  bool is_connected_called_;
};

TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
  Init("IPCChannelMojoTestClient");

  // Set up IPC channel and start client.
  TestChannelListenerWithExtraExpectations listener;
  CreateChannel(&listener);
  listener.Init(sender());
  ASSERT_TRUE(ConnectChannel());
  ASSERT_TRUE(StartClient());

  IPC::TestChannelListener::SendOneMessage(
      sender(), "hello from parent");

  base::MessageLoop::current()->Run();
  EXPECT_TRUE(base::kNullProcessId != this->channel()->GetPeerPID());

  this->channel()->Close();

  EXPECT_TRUE(WaitForClientShutdown());
  EXPECT_TRUE(listener.is_connected_called());
  EXPECT_TRUE(listener.HasSentAll());

  DestroyChannel();
}

// A long running process that connects to us
MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) {
  TestChannelListenerWithExtraExpectations listener;
  ChannelClient client(&listener, "IPCChannelMojoTestClient");
  client.Connect();
  listener.Init(client.channel());

  IPC::TestChannelListener::SendOneMessage(
      client.channel(), "hello from child");
  base::MessageLoop::current()->Run();
  EXPECT_TRUE(listener.is_connected_called());
  EXPECT_TRUE(listener.HasSentAll());

  return 0;
}

// Close given handle before use to simulate an error.
class ErraticChannelMojo : public IPC::ChannelMojo {
 public:
  ErraticChannelMojo(IPC::ChannelMojoHost* host,
                     const IPC::ChannelHandle& channel_handle,
                     IPC::Channel::Mode mode,
                     IPC::Listener* listener,
                     scoped_refptr<base::TaskRunner> runner)
      : ChannelMojo(host, channel_handle, mode, listener) {}

  virtual void OnConnected(mojo::ScopedMessagePipeHandle pipe) {
    MojoClose(pipe.get().value());
    OnConnected(pipe.Pass());
  }
};

// Exists to create ErraticChannelMojo.
class ErraticChannelFactory : public IPC::ChannelFactory {
 public:
  explicit ErraticChannelFactory(IPC::ChannelMojoHost* host,
                                 const IPC::ChannelHandle& handle,
                                 base::TaskRunner* runner)
      : host_(host), handle_(handle), runner_(runner) {}

  virtual std::string GetName() const OVERRIDE {
    return "";
  }

  virtual scoped_ptr<IPC::Channel> BuildChannel(
      IPC::Listener* listener) OVERRIDE {
    return scoped_ptr<IPC::Channel>(new ErraticChannelMojo(
        host_, handle_, IPC::Channel::MODE_SERVER, listener, runner_));
  }

 private:
  IPC::ChannelMojoHost* host_;
  IPC::ChannelHandle handle_;
  scoped_refptr<base::TaskRunner> runner_;
};

class ListenerExpectingErrors : public IPC::Listener {
 public:
  ListenerExpectingErrors()
      : has_error_(false) {
  }

  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
    return true;
  }

  virtual void OnChannelError() OVERRIDE {
    has_error_ = true;
    base::MessageLoop::current()->Quit();
  }

  bool has_error() const { return has_error_; }

 private:
  bool has_error_;
};

class IPCChannelMojoErrorTest : public IPCTestBase {
 protected:
  virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
      const IPC::ChannelHandle& handle,
      base::TaskRunner* runner) OVERRIDE {
    host_.reset(new IPC::ChannelMojoHost(task_runner()));
    return scoped_ptr<IPC::ChannelFactory>(
        new ErraticChannelFactory(host_.get(), handle, runner));
  }

  virtual bool DidStartClient() OVERRIDE {
    bool ok = IPCTestBase::DidStartClient();
    DCHECK(ok);
    host_->OnClientLaunched(client_process());
    return ok;
  }

 private:
  scoped_ptr<IPC::ChannelMojoHost> host_;
};

class ListenerThatQuits : public IPC::Listener {
 public:
  ListenerThatQuits() {
  }

  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
    return true;
  }

  virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
    base::MessageLoop::current()->Quit();
  }
};

// A long running process that connects to us.
MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
  ListenerThatQuits listener;
  ChannelClient client(&listener, "IPCChannelMojoErraticTestClient");
  client.Connect();

  base::MessageLoop::current()->Run();

  return 0;
}

// https://crbug.com/417439
TEST_F(IPCChannelMojoErrorTest, DISABLED_SendFailWithPendingMessages) {
  Init("IPCChannelMojoErraticTestClient");

  // Set up IPC channel and start client.
  ListenerExpectingErrors listener;
  CreateChannel(&listener);
  ASSERT_TRUE(ConnectChannel());

  // This messages are queued as pending.
  for (size_t i = 0; i < 2; ++i) {
    IPC::TestChannelListener::SendOneMessage(
        sender(), "hello from parent");
  }

  ASSERT_TRUE(StartClient());
  base::MessageLoop::current()->Run();

  this->channel()->Close();

  EXPECT_TRUE(WaitForClientShutdown());
  EXPECT_TRUE(listener.has_error());

  DestroyChannel();
}

#if defined(OS_POSIX)
class ListenerThatExpectsFile : public IPC::Listener {
 public:
  ListenerThatExpectsFile()
      : sender_(NULL) {}

  virtual ~ListenerThatExpectsFile() {}

  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
    PickleIterator iter(message);

    base::ScopedFD fd;
    EXPECT_TRUE(message.ReadFile(&iter, &fd));
    base::File file(fd.release());
    std::string content(GetSendingFileContent().size(), ' ');
    file.Read(0, &content[0], content.size());
    EXPECT_EQ(content, GetSendingFileContent());
    base::MessageLoop::current()->Quit();
    ListenerThatExpectsOK::SendOK(sender_);
    return true;
  }

  virtual void OnChannelError() OVERRIDE {
    NOTREACHED();
  }

  static std::string GetSendingFileContent() {
    return "Hello";
  }

  static base::FilePath GetSendingFilePath() {
    base::FilePath path;
    bool ok = PathService::Get(base::DIR_CACHE, &path);
    EXPECT_TRUE(ok);
    return path.Append("ListenerThatExpectsFile.txt");
  }

  static void WriteAndSendFile(IPC::Sender* sender, base::File& file) {
    std::string content = GetSendingFileContent();
    file.WriteAtCurrentPos(content.data(), content.size());
    file.Flush();
    IPC::Message* message = new IPC::Message(
        0, 2, IPC::Message::PRIORITY_NORMAL);
    message->WriteFile(base::ScopedFD(file.TakePlatformFile()));
    ASSERT_TRUE(sender->Send(message));
  }

  void set_sender(IPC::Sender* sender) { sender_ = sender; }

 private:
  IPC::Sender* sender_;
};

TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
  Init("IPCChannelMojoTestSendPlatformHandleClient");

  ListenerThatExpectsOK listener;
  CreateChannel(&listener);
  ASSERT_TRUE(ConnectChannel());
  ASSERT_TRUE(StartClient());

  base::File file(ListenerThatExpectsFile::GetSendingFilePath(),
                  base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
                  base::File::FLAG_READ);
  ListenerThatExpectsFile::WriteAndSendFile(channel(), file);
  base::MessageLoop::current()->Run();

  this->channel()->Close();

  EXPECT_TRUE(WaitForClientShutdown());
  DestroyChannel();
}

MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
  ListenerThatExpectsFile listener;
  ChannelClient client(
      &listener, "IPCChannelMojoTestSendPlatformHandleClient");
  client.Connect();
  listener.set_sender(client.channel());

  base::MessageLoop::current()->Run();

  return 0;
}
#endif

}  // namespace
<commit_msg>Fix IPCChannelMojoErrorTest.SendFailWithPendingMessages<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ipc/mojo/ipc_channel_mojo.h"

#include "base/base_paths.h"
#include "base/files/file.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/pickle.h"
#include "base/threading/thread.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_test_base.h"
#include "ipc/ipc_test_channel_listener.h"
#include "ipc/mojo/ipc_channel_mojo_host.h"
#include "ipc/mojo/ipc_channel_mojo_readers.h"

#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
#endif

namespace {

class ListenerThatExpectsOK : public IPC::Listener {
 public:
  ListenerThatExpectsOK()
      : received_ok_(false) {}

  virtual ~ListenerThatExpectsOK() {}

  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
    PickleIterator iter(message);
    std::string should_be_ok;
    EXPECT_TRUE(iter.ReadString(&should_be_ok));
    EXPECT_EQ(should_be_ok, "OK");
    received_ok_ = true;
    base::MessageLoop::current()->Quit();
    return true;
  }

  virtual void OnChannelError() OVERRIDE {
    // The connection should be healthy while the listener is waiting
    // message.  An error can occur after that because the peer
    // process dies.
    DCHECK(received_ok_);
  }

  static void SendOK(IPC::Sender* sender) {
    IPC::Message* message = new IPC::Message(
        0, 2, IPC::Message::PRIORITY_NORMAL);
    message->WriteString(std::string("OK"));
    ASSERT_TRUE(sender->Send(message));
  }

 private:
  bool received_ok_;
};

class ChannelClient {
 public:
  explicit ChannelClient(IPC::Listener* listener, const char* name) {
    channel_ = IPC::ChannelMojo::Create(NULL,
                                        IPCTestBase::GetChannelName(name),
                                        IPC::Channel::MODE_CLIENT,
                                        listener);
  }

  void Connect() {
    CHECK(channel_->Connect());
  }

  IPC::ChannelMojo* channel() const { return channel_.get(); }

 private:
  base::MessageLoopForIO main_message_loop_;
  scoped_ptr<IPC::ChannelMojo> channel_;
};

class IPCChannelMojoTest : public IPCTestBase {
 protected:
  virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
      const IPC::ChannelHandle& handle,
      base::TaskRunner* runner) OVERRIDE {
    host_.reset(new IPC::ChannelMojoHost(task_runner()));
    return IPC::ChannelMojo::CreateServerFactory(host_.get(), handle);
  }

  virtual bool DidStartClient() OVERRIDE {
    bool ok = IPCTestBase::DidStartClient();
    DCHECK(ok);
    host_->OnClientLaunched(client_process());
    return ok;
  }

 private:
  scoped_ptr<IPC::ChannelMojoHost> host_;
};

class TestChannelListenerWithExtraExpectations
    : public IPC::TestChannelListener {
 public:
  TestChannelListenerWithExtraExpectations()
      : is_connected_called_(false) {
  }

  virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
    IPC::TestChannelListener::OnChannelConnected(peer_pid);
    EXPECT_TRUE(base::kNullProcessId != peer_pid);
    is_connected_called_ = true;
  }

  bool is_connected_called() const { return is_connected_called_; }

 private:
  bool is_connected_called_;
};

TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
  Init("IPCChannelMojoTestClient");

  // Set up IPC channel and start client.
  TestChannelListenerWithExtraExpectations listener;
  CreateChannel(&listener);
  listener.Init(sender());
  ASSERT_TRUE(ConnectChannel());
  ASSERT_TRUE(StartClient());

  IPC::TestChannelListener::SendOneMessage(
      sender(), "hello from parent");

  base::MessageLoop::current()->Run();
  EXPECT_TRUE(base::kNullProcessId != this->channel()->GetPeerPID());

  this->channel()->Close();

  EXPECT_TRUE(WaitForClientShutdown());
  EXPECT_TRUE(listener.is_connected_called());
  EXPECT_TRUE(listener.HasSentAll());

  DestroyChannel();
}

// A long running process that connects to us
MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) {
  TestChannelListenerWithExtraExpectations listener;
  ChannelClient client(&listener, "IPCChannelMojoTestClient");
  client.Connect();
  listener.Init(client.channel());

  IPC::TestChannelListener::SendOneMessage(
      client.channel(), "hello from child");
  base::MessageLoop::current()->Run();
  EXPECT_TRUE(listener.is_connected_called());
  EXPECT_TRUE(listener.HasSentAll());

  return 0;
}

class ListenerExpectingErrors : public IPC::Listener {
 public:
  ListenerExpectingErrors()
      : has_error_(false) {
  }

  virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
    base::MessageLoop::current()->Quit();
  }

  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
    return true;
  }

  virtual void OnChannelError() OVERRIDE {
    has_error_ = true;
    base::MessageLoop::current()->Quit();
  }

  bool has_error() const { return has_error_; }

 private:
  bool has_error_;
};

class IPCChannelMojoErrorTest : public IPCTestBase {
 protected:
  virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
      const IPC::ChannelHandle& handle,
      base::TaskRunner* runner) OVERRIDE {
    host_.reset(new IPC::ChannelMojoHost(task_runner()));
    return IPC::ChannelMojo::CreateServerFactory(host_.get(), handle);
  }

  virtual bool DidStartClient() OVERRIDE {
    bool ok = IPCTestBase::DidStartClient();
    DCHECK(ok);
    host_->OnClientLaunched(client_process());
    return ok;
  }

 private:
  scoped_ptr<IPC::ChannelMojoHost> host_;
};

class ListenerThatQuits : public IPC::Listener {
 public:
  ListenerThatQuits() {
  }

  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
    return true;
  }

  virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
    base::MessageLoop::current()->Quit();
  }
};

// A long running process that connects to us.
MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
  ListenerThatQuits listener;
  ChannelClient client(&listener, "IPCChannelMojoErraticTestClient");
  client.Connect();

  base::MessageLoop::current()->Run();

  return 0;
}

TEST_F(IPCChannelMojoErrorTest, SendFailWithPendingMessages) {
  Init("IPCChannelMojoErraticTestClient");

  // Set up IPC channel and start client.
  ListenerExpectingErrors listener;
  CreateChannel(&listener);
  ASSERT_TRUE(ConnectChannel());

  // This matches a value in mojo/system/constants.h
  const int kMaxMessageNumBytes = 4 * 1024 * 1024;
  std::string overly_large_data(kMaxMessageNumBytes, '*');
  // This messages are queued as pending.
  for (size_t i = 0; i < 10; ++i) {
    IPC::TestChannelListener::SendOneMessage(
        sender(), overly_large_data.c_str());
  }

  ASSERT_TRUE(StartClient());
  base::MessageLoop::current()->Run();

  this->channel()->Close();

  EXPECT_TRUE(WaitForClientShutdown());
  EXPECT_TRUE(listener.has_error());

  DestroyChannel();
}

#if defined(OS_POSIX)
class ListenerThatExpectsFile : public IPC::Listener {
 public:
  ListenerThatExpectsFile()
      : sender_(NULL) {}

  virtual ~ListenerThatExpectsFile() {}

  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
    PickleIterator iter(message);

    base::ScopedFD fd;
    EXPECT_TRUE(message.ReadFile(&iter, &fd));
    base::File file(fd.release());
    std::string content(GetSendingFileContent().size(), ' ');
    file.Read(0, &content[0], content.size());
    EXPECT_EQ(content, GetSendingFileContent());
    base::MessageLoop::current()->Quit();
    ListenerThatExpectsOK::SendOK(sender_);
    return true;
  }

  virtual void OnChannelError() OVERRIDE {
    NOTREACHED();
  }

  static std::string GetSendingFileContent() {
    return "Hello";
  }

  static base::FilePath GetSendingFilePath() {
    base::FilePath path;
    bool ok = PathService::Get(base::DIR_CACHE, &path);
    EXPECT_TRUE(ok);
    return path.Append("ListenerThatExpectsFile.txt");
  }

  static void WriteAndSendFile(IPC::Sender* sender, base::File& file) {
    std::string content = GetSendingFileContent();
    file.WriteAtCurrentPos(content.data(), content.size());
    file.Flush();
    IPC::Message* message = new IPC::Message(
        0, 2, IPC::Message::PRIORITY_NORMAL);
    message->WriteFile(base::ScopedFD(file.TakePlatformFile()));
    ASSERT_TRUE(sender->Send(message));
  }

  void set_sender(IPC::Sender* sender) { sender_ = sender; }

 private:
  IPC::Sender* sender_;
};

TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
  Init("IPCChannelMojoTestSendPlatformHandleClient");

  ListenerThatExpectsOK listener;
  CreateChannel(&listener);
  ASSERT_TRUE(ConnectChannel());
  ASSERT_TRUE(StartClient());

  base::File file(ListenerThatExpectsFile::GetSendingFilePath(),
                  base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
                  base::File::FLAG_READ);
  ListenerThatExpectsFile::WriteAndSendFile(channel(), file);
  base::MessageLoop::current()->Run();

  this->channel()->Close();

  EXPECT_TRUE(WaitForClientShutdown());
  DestroyChannel();
}

MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
  ListenerThatExpectsFile listener;
  ChannelClient client(
      &listener, "IPCChannelMojoTestSendPlatformHandleClient");
  client.Connect();
  listener.set_sender(client.channel());

  base::MessageLoop::current()->Run();

  return 0;
}
#endif

}  // namespace
<|endoftext|>


<commit_before>#include "enchanthighlighter.hh"
#include <enchant++.h>

EnchantHighlighter::EnchantHighlighter(QTextDocument *parent) :
    QSyntaxHighlighter(parent)
{
    format.setUnderlineColor(QColor(Qt::red));
    format.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline);
}

EnchantHighlighter::~EnchantHighlighter() {}

void EnchantHighlighter::check(const QString &text, int begin, int i) {
    QStringRef sub(&text, begin, i-begin);
    auto ba = sub.toUtf8();
    if(!dict->check(std::string {ba.data(), (std::string::size_type)ba.size()}))
        setFormat(begin, i-begin, format);
}

void EnchantHighlighter::highlightBlock(const QString& text) {
    if(!dict)
        return;
    int begin = 0;
    int i = 0;
    for(; i<text.length(); ++i) {
        auto ch = text.at(i);
        if(ch < 'A') {
            if(begin >= i)
                begin++;
            else if(begin<i) {
                check(text, begin, i);
                begin = i+1;
            }
        }
    }
    if(begin < i)
        check(text, begin, i);
}

bool EnchantHighlighter::setLanguage(const std::string &lang) {
    if(!enchant::Broker::instance()->dict_exists(lang))
        return false;
    dict.reset(enchant::Broker::instance()->request_dict(lang));
    return true;
}
<commit_msg>Rehilight on language changes<commit_after>#include "enchanthighlighter.hh"
#include <enchant++.h>

EnchantHighlighter::EnchantHighlighter(QTextDocument *parent) :
    QSyntaxHighlighter(parent)
{
    format.setUnderlineColor(QColor(Qt::red));
    format.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline);
}

EnchantHighlighter::~EnchantHighlighter() {}

void EnchantHighlighter::check(const QString &text, int begin, int i) {
    QStringRef sub(&text, begin, i-begin);
    auto ba = sub.toUtf8();
    if(!dict->check(std::string {ba.data(), (std::string::size_type)ba.size()}))
        setFormat(begin, i-begin, format);
}

void EnchantHighlighter::highlightBlock(const QString& text) {
    if(!dict)
        return;
    int begin = 0;
    int i = 0;
    for(; i<text.length(); ++i) {
        auto ch = text.at(i);
        if(ch < 'A') {
            if(begin >= i)
                begin++;
            else if(begin<i) {
                check(text, begin, i);
                begin = i+1;
            }
        }
    }
    if(begin < i)
        check(text, begin, i);
}

bool EnchantHighlighter::setLanguage(const std::string &lang) {
    if(!enchant::Broker::instance()->dict_exists(lang))
        return false;
	if(dict && dict->get_lang() == lang)
		return true;
    dict.reset(enchant::Broker::instance()->request_dict(lang));
	rehighlight();
    return true;
}
<|endoftext|>


<commit_before>#include "optiHit.hpp"

OptiHit calc_optihit(Scene const& scene,Ray const& ray)
{
  OptiHit optihit;
  float nearest_distance = 10000.0;
  optihit.closest_shape = nullptr;
  optihit.distance = 0.0;
  for (auto const& shape : scene.shapes) {
    optihit.hit = shape->intersect(ray, optihit.distance);
    if (optihit.hit && 0 < optihit.distance && optihit.distance < nearest_distance) {
      nearest_distance=optihit.distance;
      optihit.closest_shape = shape;
    }
  }
}
<commit_msg>corrigiert! optihit funktioniert wieder!<commit_after>#include "optiHit.hpp"

OptiHit calc_optihit(Scene const& scene,Ray const& ray)
{
  OptiHit optihit;
  float nearest_distance = 10000.0;
  optihit.closest_shape = nullptr;
  optihit.distance = 0.0;
  for (auto const& shape : scene.shapes) {
    optihit.hit = shape->intersect(ray, optihit.distance);
    if (optihit.hit && 0 < optihit.distance && optihit.distance < nearest_distance) {
      nearest_distance=optihit.distance;
      optihit.closest_shape = shape;
    }
  }
  return optihit;
}
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef URI_HPP
#define URI_HPP

#include <gsl.h>
#include <unordered_map>

namespace uri {

  /**
   * Representation of RFC 3986 URI's.
   * Ref. https://tools.ietf.org/html/rfc3986
   **/
  class URI {
  private:
    /** Non-owning pointer-size type */
    struct Span_t {
      size_t begin;
      size_t end;

      Span_t(const size_t b = 0U, const size_t e = 0U) noexcept
        : begin{b}
        , end{e}
      {}
    }; //< struct Span_t

  public:
    /*
     * Default constructor
     */
    URI() = default;

    /*
     * Default copy and move constructors
     */
    URI(URI&) = default;
    URI(URI&&) = default;

    /*
     * Default destructor
     */
    ~URI() = default;

    /*
     * Default assignment operators
     */
    URI& operator=(const URI&) = default;
    URI& operator=(URI&&) = default;

    //
    // We might do a span-based constructor later.
    // URI(gsl::span<const char>);
    //

    /**
     * @brief Construct using a C-String
     *
     * @param uri : A C-String representing a uri
     */
    URI(const char* uri);

    /**
     * @brief Construct using a string
     *
     * @param uri : A string representing a uri
     */
    URI(const std::string& uri);

    ///////////////////////////////////////////////
    //----------RFC-specified URI parts----------//
    ///////////////////////////////////////////////

    /**
     * @brief Get userinfo.
     *
     * E.g. 'username@'...
     *
     * @return The user's information
     */
    std::string userinfo() const;

    /** Get host. E.g. 'includeos.org', '10.0.0.42' etc. */
    const std::string host() const;

    /** Get raw port number. In decimal character representation */
    const std::string port_str() const;

    /** Get numeric port number.
     * @warning The RFC doesn't specify dimension. This funcion will truncate
     * any overflowing digits
     **/
    uint16_t port() const;

    /** Get the path. E.g. /pictures/logo.png  */
    std::string path() const;

    /** Get the complete unparsed query string. */
    const std::string query() const;

    /** Get the fragment part. E.g. "...#anchor1" */
    const std::string fragment() const;

    ///
    /// Convenience
    ///

    /**
     * Get the URI-decoded value of a query-string key.
     *
     * E.g. for query() => "?name=Bjarne%20Stroustrup",
     * query("name") returns "Bjarne Stroustrup" */
    std::string query(std::string key);

    /** String representation **/
    std::string to_string() const;

  private:

    std::unordered_map<std::string,std::string> queries_;
    Span_t uri_data_;
    Span_t userinfo_;
    Span_t host_;
    Span_t port_str_;
    uint16_t port_ = 0;
    Span_t path_;
    Span_t query_;
    Span_t fragment_;

    static const Span_t zero_span_;

    // A copy of the data, if the string-based constructor was used
    std::string uri_str_;

    /**
     * @brief Parse the given string representing a uri
     * into its given parts according to RFC 3986
     *
     * @param uri : The string representing a uri
     */
    void parse(const std::string& uri);

  }; // class uri::URI

  std::ostream& operator<< (std::ostream&, const URI&);

} // namespace uri

#endif
<commit_msg>Changed API doc for method API::host<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef URI_HPP
#define URI_HPP

#include <gsl.h>
#include <unordered_map>

namespace uri {

  /**
   * Representation of RFC 3986 URI's.
   * Ref. https://tools.ietf.org/html/rfc3986
   **/
  class URI {
  private:
    /** Non-owning pointer-size type */
    struct Span_t {
      size_t begin;
      size_t end;

      Span_t(const size_t b = 0U, const size_t e = 0U) noexcept
        : begin{b}
        , end{e}
      {}
    }; //< struct Span_t

  public:
    /*
     * Default constructor
     */
    URI() = default;

    /*
     * Default copy and move constructors
     */
    URI(URI&) = default;
    URI(URI&&) = default;

    /*
     * Default destructor
     */
    ~URI() = default;

    /*
     * Default assignment operators
     */
    URI& operator=(const URI&) = default;
    URI& operator=(URI&&) = default;

    //
    // We might do a span-based constructor later.
    // URI(gsl::span<const char>);
    //

    /**
     * @brief Construct using a C-String
     *
     * @param uri : A C-String representing a uri
     */
    URI(const char* uri);

    /**
     * @brief Construct using a string
     *
     * @param uri : A string representing a uri
     */
    URI(const std::string& uri);

    ///////////////////////////////////////////////
    //----------RFC-specified URI parts----------//
    ///////////////////////////////////////////////

    /**
     * @brief Get userinfo.
     *
     * E.g. 'username@'...
     *
     * @return The user's information
     */
    std::string userinfo() const;

    /**
     * @brief Get host.
     *
     * E.g. 'includeos.org', '10.0.0.42' etc.
     *
     * @return The host's information
     */
    std::string host() const;

    /** Get raw port number. In decimal character representation */
    const std::string port_str() const;

    /** Get numeric port number.
     * @warning The RFC doesn't specify dimension. This funcion will truncate
     * any overflowing digits
     **/
    uint16_t port() const;

    /** Get the path. E.g. /pictures/logo.png  */
    std::string path() const;

    /** Get the complete unparsed query string. */
    const std::string query() const;

    /** Get the fragment part. E.g. "...#anchor1" */
    const std::string fragment() const;

    ///
    /// Convenience
    ///

    /**
     * Get the URI-decoded value of a query-string key.
     *
     * E.g. for query() => "?name=Bjarne%20Stroustrup",
     * query("name") returns "Bjarne Stroustrup" */
    std::string query(std::string key);

    /** String representation **/
    std::string to_string() const;

  private:

    std::unordered_map<std::string,std::string> queries_;
    Span_t uri_data_;
    Span_t userinfo_;
    Span_t host_;
    Span_t port_str_;
    uint16_t port_ = 0;
    Span_t path_;
    Span_t query_;
    Span_t fragment_;

    static const Span_t zero_span_;

    // A copy of the data, if the string-based constructor was used
    std::string uri_str_;

    /**
     * @brief Parse the given string representing a uri
     * into its given parts according to RFC 3986
     *
     * @param uri : The string representing a uri
     */
    void parse(const std::string& uri);

  }; // class uri::URI

  std::ostream& operator<< (std::ostream&, const URI&);

} // namespace uri

#endif
<|endoftext|>


<commit_before>#include <libhackrf/hackrf.h>
#include <cstdio>
#include <vector>
#include "rf.h"

using namespace std;

struct global_args_t rf_global_args;

static vector<int> patterns[9];
static vector<float> filter;
static volatile Direction last_dir = none;
static volatile unsigned int pos = 0;

static hackrf_device *device = NULL;
static int last_gain_tx = 20;

void swap_direction(Direction *a, Direction *b) {
    Direction tmp = *a;
    *a = *b;
    *b = tmp;
}

void set_direction_map(struct direction_map_t *map, bool invert_steering, bool invert_throttle, bool swap_axes) {
    /* we are going to treat our struct like a 3x3 array */
    Direction *map_arr = (Direction *)map;

    map_arr[0] = fwd_left;
    map_arr[1] = fwd;
    map_arr[2] = fwd_right;
    map_arr[3] = left;
    map_arr[4] = none;
    map_arr[5] = right;
    map_arr[6] = back_left;
    map_arr[7] = back;
    map_arr[8] = back_right;

    if (swap_axes) {
        /* treat map_arr as 3x3 array, transform s.t. map_arr[i][j] becomes map_arr[j][i] */
        /* do this first so that invert_* work on the transformed values */
        for (int i=0; i<3; i++) {
            for (int j=0; j<3; j++) {
                if (i<j) {
                    swap_direction(map_arr + 3*j + i, map_arr + 3*i+ j);
                }
            }
        }
    }

    if (invert_steering) {
        /* treat map_arr as a 3x3 array, swap left and right columns */
        for (int i = 0; i < 9; i+=3) {
            swap_direction(map_arr + i, map_arr + i + 2);
        }
    }

    if (invert_throttle) {
        /* treat map_arr as a 3x3 array, swap top and bottom rows */
        for (int i = 0; i < 3; i++) {
            swap_direction(map_arr + i, map_arr + i + 6);
        }
    }
}

static void make_short_pulses(vector<int> &v, int num)
{
    for (int i = 0 ; i < num ; i++) {
        v.push_back(1);
        v.push_back(0);
    }
}

static void init_patterns()
{
    for (int i = 0 ; i < 8 ; i++) {
        // each pattern start with 4 long pulses
        for (int j = 0 ; j < 4 ; j++) {
            patterns[i].push_back(1);
            patterns[i].push_back(1);
            patterns[i].push_back(1);
            patterns[i].push_back(0);
        }
    }
    make_short_pulses(patterns[fwd], 10);
    make_short_pulses(patterns[fwd_left], 28);
    make_short_pulses(patterns[fwd_right], 34);
    make_short_pulses(patterns[back], 40);
    make_short_pulses(patterns[back_left], 52);
    make_short_pulses(patterns[back_right], 46);
    make_short_pulses(patterns[left], 58);
    make_short_pulses(patterns[right], 64);
    patterns[none].push_back(0);
    patterns[none].push_back(0);
    patterns[none].push_back(0);
    // moving averarge can be implemented more efficiently
    // but this allows playing with other type of filters
    for (int i = 0 ; i < 20 ; i++) {
        filter.push_back(0.9/20);
    }
}

static int tx_callback(hackrf_transfer* transfer) {
    int spb = rf_global_args.SAMPLE_RATE / rf_global_args.SYMBOL_RATE; // samples per bit
    for (int i = 0 ; i < transfer->valid_length/2 ; i++) {
        vector<int> &pattern = patterns[last_dir];
        int pattern_size = pattern.size();
        float sum = 0;
        for (int j = 0 ; j < (int)filter.size() ; j++) {
            int sample = pattern[((pos + j)/spb) % pattern_size];
            sum += filter[j] * sample;
        }
        pos += 1;
        transfer->buffer[i*2] = sum * 127;
        transfer->buffer[i*2+1] = 0;
    }
    return 0;
}

bool init_rf()
{
    init_patterns();
    int result = hackrf_init();
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_init() failed: (%d)\n", result);
        return false;
    }
    return true;
}

static void start_tx()
{
    int result = hackrf_open_by_serial(NULL, &device);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_open() failed: (%d)\n", result);
    }
    result = hackrf_set_sample_rate_manual(device, rf_global_args.SAMPLE_RATE, 1);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_sample_rate_set() failed: (%d)\n", result);
    }
    uint32_t baseband_filter_bw_hz = hackrf_compute_baseband_filter_bw_round_down_lt(rf_global_args.SAMPLE_RATE);
    result = hackrf_set_baseband_filter_bandwidth(device, baseband_filter_bw_hz);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_baseband_filter_bandwidth_set() failed: (%d)\n", result);
    }
    result = hackrf_set_freq(device, rf_global_args.FREQ);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_set_freq() failed: (%d)\n", result);
    }
    result = hackrf_set_amp_enable(device, 1);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_set_amp_enable() failed: (%d)\n", result);
    }
    result = hackrf_set_txvga_gain(device, last_gain_tx);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_set_txvga_gain() failed: (%d)\n", result);
    }
    result = hackrf_start_tx(device, tx_callback, NULL);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_start_tx() failed: (%d)\n", result);
    }
}

static void stop_tx()
{
    int result = hackrf_stop_tx(device);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_stop_tx() failed: (%d)\n", result);
    }
    result = hackrf_close(device);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_close() failed: (%d)\n", result);
    }
}

void state_change(Direction dir, int gain_tx)
{
    if (gain_tx != last_gain_tx) {
        last_gain_tx = gain_tx;
    }
    if (dir != last_dir) {
        if (last_dir == none) {
            last_dir = dir;
            pos = 0;
            start_tx();
            return;
        } else if (dir == none) {
            stop_tx();
        }
        last_dir = dir;
        pos = 0;
    }
}

void close_rf()
{
    hackrf_exit();
}

<commit_msg>Use hackrf_open() instead of hackrf_open_by_serial()<commit_after>#include <libhackrf/hackrf.h>
#include <cstdio>
#include <vector>
#include "rf.h"

using namespace std;

struct global_args_t rf_global_args;

static vector<int> patterns[9];
static vector<float> filter;
static volatile Direction last_dir = none;
static volatile unsigned int pos = 0;

static hackrf_device *device = NULL;
static int last_gain_tx = 20;

void swap_direction(Direction *a, Direction *b) {
    Direction tmp = *a;
    *a = *b;
    *b = tmp;
}

void set_direction_map(struct direction_map_t *map, bool invert_steering, bool invert_throttle, bool swap_axes) {
    /* we are going to treat our struct like a 3x3 array */
    Direction *map_arr = (Direction *)map;

    map_arr[0] = fwd_left;
    map_arr[1] = fwd;
    map_arr[2] = fwd_right;
    map_arr[3] = left;
    map_arr[4] = none;
    map_arr[5] = right;
    map_arr[6] = back_left;
    map_arr[7] = back;
    map_arr[8] = back_right;

    if (swap_axes) {
        /* treat map_arr as 3x3 array, transform s.t. map_arr[i][j] becomes map_arr[j][i] */
        /* do this first so that invert_* work on the transformed values */
        for (int i=0; i<3; i++) {
            for (int j=0; j<3; j++) {
                if (i<j) {
                    swap_direction(map_arr + 3*j + i, map_arr + 3*i+ j);
                }
            }
        }
    }

    if (invert_steering) {
        /* treat map_arr as a 3x3 array, swap left and right columns */
        for (int i = 0; i < 9; i+=3) {
            swap_direction(map_arr + i, map_arr + i + 2);
        }
    }

    if (invert_throttle) {
        /* treat map_arr as a 3x3 array, swap top and bottom rows */
        for (int i = 0; i < 3; i++) {
            swap_direction(map_arr + i, map_arr + i + 6);
        }
    }
}

static void make_short_pulses(vector<int> &v, int num)
{
    for (int i = 0 ; i < num ; i++) {
        v.push_back(1);
        v.push_back(0);
    }
}

static void init_patterns()
{
    for (int i = 0 ; i < 8 ; i++) {
        // each pattern start with 4 long pulses
        for (int j = 0 ; j < 4 ; j++) {
            patterns[i].push_back(1);
            patterns[i].push_back(1);
            patterns[i].push_back(1);
            patterns[i].push_back(0);
        }
    }
    make_short_pulses(patterns[fwd], 10);
    make_short_pulses(patterns[fwd_left], 28);
    make_short_pulses(patterns[fwd_right], 34);
    make_short_pulses(patterns[back], 40);
    make_short_pulses(patterns[back_left], 52);
    make_short_pulses(patterns[back_right], 46);
    make_short_pulses(patterns[left], 58);
    make_short_pulses(patterns[right], 64);
    patterns[none].push_back(0);
    patterns[none].push_back(0);
    patterns[none].push_back(0);
    // moving averarge can be implemented more efficiently
    // but this allows playing with other type of filters
    for (int i = 0 ; i < 20 ; i++) {
        filter.push_back(0.9/20);
    }
}

static int tx_callback(hackrf_transfer* transfer) {
    int spb = rf_global_args.SAMPLE_RATE / rf_global_args.SYMBOL_RATE; // samples per bit
    for (int i = 0 ; i < transfer->valid_length/2 ; i++) {
        vector<int> &pattern = patterns[last_dir];
        int pattern_size = pattern.size();
        float sum = 0;
        for (int j = 0 ; j < (int)filter.size() ; j++) {
            int sample = pattern[((pos + j)/spb) % pattern_size];
            sum += filter[j] * sample;
        }
        pos += 1;
        transfer->buffer[i*2] = sum * 127;
        transfer->buffer[i*2+1] = 0;
    }
    return 0;
}

bool init_rf()
{
    init_patterns();
    int result = hackrf_init();
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_init() failed: (%d)\n", result);
        return false;
    }
    return true;
}

static void start_tx()
{
    int result = hackrf_open(&device);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_open() failed: (%d)\n", result);
    }
    result = hackrf_set_sample_rate_manual(device, rf_global_args.SAMPLE_RATE, 1);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_sample_rate_set() failed: (%d)\n", result);
    }
    uint32_t baseband_filter_bw_hz = hackrf_compute_baseband_filter_bw_round_down_lt(rf_global_args.SAMPLE_RATE);
    result = hackrf_set_baseband_filter_bandwidth(device, baseband_filter_bw_hz);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_baseband_filter_bandwidth_set() failed: (%d)\n", result);
    }
    result = hackrf_set_freq(device, rf_global_args.FREQ);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_set_freq() failed: (%d)\n", result);
    }
    result = hackrf_set_amp_enable(device, 1);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_set_amp_enable() failed: (%d)\n", result);
    }
    result = hackrf_set_txvga_gain(device, last_gain_tx);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_set_txvga_gain() failed: (%d)\n", result);
    }
    result = hackrf_start_tx(device, tx_callback, NULL);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_start_tx() failed: (%d)\n", result);
    }
}

static void stop_tx()
{
    int result = hackrf_stop_tx(device);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_stop_tx() failed: (%d)\n", result);
    }
    result = hackrf_close(device);
    if (result != HACKRF_SUCCESS) {
        fprintf(stderr, "hackrf_close() failed: (%d)\n", result);
    }
}

void state_change(Direction dir, int gain_tx)
{
    if (gain_tx != last_gain_tx) {
        last_gain_tx = gain_tx;
    }
    if (dir != last_dir) {
        if (last_dir == none) {
            last_dir = dir;
            pos = 0;
            start_tx();
            return;
        } else if (dir == none) {
            stop_tx();
        }
        last_dir = dir;
        pos = 0;
    }
}

void close_rf()
{
    hackrf_exit();
}

<|endoftext|>


<commit_before>#include "Sql.h"
#include "Server.h"

SqlStatement InsertIgnore(const SqlInsert& insert) {
	int dialect = (*(Watchdog*)(&SkylarkApp::TheApp())).sql.GetDialect();
	String s = SqlStatement(insert).Get(dialect);
	ASSERT(s.StartsWith("insert "));
	switch(dialect) {
	case SQLITE3:
		s = "insert or ignore " + s.Mid(7);
		break;
	case MY_SQL:
		s = "insert ignore " + s.Mid(7);
		break;
	default:
		NEVER_("InsertIgnore not implemented for this dialect");
	}
	return SqlStatement(s);
}

bool Upsert(Sql& sql, const SqlInsert& insert, const SqlUpdate& update) {
	sql * InsertIgnore(insert);
	if (sql.GetRowsProcessed() == 0) {
		sql * update;
		return false;
	}
	return true;
}

SqlBool Regexp(const SqlVal& a, const SqlVal& b) {
	return SqlBool(a, " regexp ", b, SqlS::COMP);
}

SqlVal SqlEmptyString(){
	static SqlVal s("''", SqlS::HIGH);
	return s;
}

SqlVal DateSub(const SqlVal& date, const SqlVal& interval) {
	int dialect = (*(Watchdog*)(&SkylarkApp::TheApp())).sql.GetDialect();
	switch(dialect) {
	case SQLITE3:
		return SqlFunc("datetime", SqlSet(date, "-" + ~interval));
	case MY_SQL:
		return SqlFunc("date_sub", SqlSet(date, interval));
	default:
		NEVER_("DateSub not implemented for this dialect");
		return SqlVal();
	}
}

SqlVal SqlInterval(const SqlVal& count, const String& unit) {
	int dialect = (*(Watchdog*)(&SkylarkApp::TheApp())).sql.GetDialect();
	switch(dialect) {
	case SQLITE3:
		return SqlTxt("interval " + ~count + " " + unit);
	case MY_SQL:
		return SqlVal("interval " + ~count + " " + unit, SqlS::HIGH);
	default:
		NEVER_("SqlInterval not implemented for this dialect");
		return SqlVal();
	}
}

SqlVal TimeDiff(const SqlVal& a, const SqlVal& b) {
	int dialect = (*(Watchdog*)(&SkylarkApp::TheApp())).sql.GetDialect();
	switch(dialect) {
	case SQLITE3:
		return SqlFunc("strftime", SqlSet("%s", b)) - SqlFunc("strftime", SqlSet("%s", a));
	case MY_SQL:
		return SqlFunc("timestampdiff", SqlSet(SqlVal("second", SqlS::HIGH), a, b));
	default:
		NEVER_("TimeDiff not implemented for this dialect");
		return SqlVal();
	}
}

String SqlEscape(const Value& in){
	if(in.IsNull() && !in.Is<String>() && !in.Is<WString>()) {
		return "NULL";
	}
	if(in.Is<int>() || in.Is<int64>() || in.Is<double>())
		return in.ToString();
	if(in.Is<Time>() || in.Is<Date>())
		return "\'" + in.ToString() + "\'";

	String str = in.ToString();
	const char* s = str.Begin();
	const char* lim = str.End();
	String t;
	t.Cat('\'');
	while(s < lim) {
		switch(*s) {
		case '\a': t.Cat("\\a"); break;
		case '\b': t.Cat("\\b"); break;
		case '\f': t.Cat("\\f"); break;
		case '\t': t.Cat("\\t"); break;
		case '\v': t.Cat("\\v"); break;
		case '\r': t.Cat("\\r"); break;
		case '\'': t.Cat("''"); break;
		case '\\': t.Cat("\\\\"); break;
		case '\n': t.Cat("\\n"); break;
		default:
			if(byte(*s) < 32 || (byte)*s >= 0x7f) {
				char h[4];
				int q = (byte)*s;
				h[0] = '\\';
				h[1] = (3 & (q >> 6)) + '0';
				h[2] = (7 & (q >> 3)) + '0';
				h[3] = (7 & q) + '0';
				t.Cat(h, 4);
			}
			else {
				t.Cat(*s);
			}
			break;
		}
		s++;
	}
	t.Cat('\'');
	return t;
}
<commit_msg>fixed date related functions for sqlite<commit_after>#include "Sql.h"
#include "Server.h"

SqlStatement InsertIgnore(const SqlInsert& insert) {
	int dialect = (*(Watchdog*)(&SkylarkApp::TheApp())).sql.GetDialect();
	String s = SqlStatement(insert).Get(dialect);
	ASSERT(s.StartsWith("insert "));
	switch(dialect) {
	case SQLITE3:
		s = "insert or ignore " + s.Mid(7);
		break;
	case MY_SQL:
		s = "insert ignore " + s.Mid(7);
		break;
	default:
		NEVER_("InsertIgnore not implemented for this dialect");
	}
	return SqlStatement(s);
}

bool Upsert(Sql& sql, const SqlInsert& insert, const SqlUpdate& update) {
	sql * InsertIgnore(insert);
	if (sql.GetRowsProcessed() == 0) {
		sql * update;
		return false;
	}
	return true;
}

SqlBool Regexp(const SqlVal& a, const SqlVal& b) {
	return SqlBool(a, " regexp ", b, SqlS::COMP);
}

SqlVal SqlEmptyString(){
	static SqlVal s("''", SqlS::HIGH);
	return s;
}

SqlVal DateSub(const SqlVal& date, const SqlVal& interval) {
	int dialect = (*(Watchdog*)(&SkylarkApp::TheApp())).sql.GetDialect();
	switch(dialect) {
	case SQLITE3:
		return SqlFunc("datetime", SqlSet(date, SqlVal("'-'||" + ~interval, SqlS::HIGH)));
	case MY_SQL:
		return SqlFunc("date_sub", SqlSet(date, interval));
	default:
		NEVER_("DateSub not implemented for this dialect");
		return SqlVal();
	}
}

SqlVal SqlInterval(const SqlVal& count, const String& unit) {
	int dialect = (*(Watchdog*)(&SkylarkApp::TheApp())).sql.GetDialect();
	switch(dialect) {
	case SQLITE3:
		return SqlVal(~count + "||" + ("' " + unit+"'"), SqlS::HIGH);
	case MY_SQL:
		return SqlVal("interval " + ~count + " " + unit, SqlS::HIGH);
	default:
		NEVER_("SqlInterval not implemented for this dialect");
		return SqlVal();
	}
}

SqlVal TimeDiff(const SqlVal& a, const SqlVal& b) {
	int dialect = (*(Watchdog*)(&SkylarkApp::TheApp())).sql.GetDialect();
	switch(dialect) {
	case SQLITE3:
		return SqlFunc("strftime", SqlSet("%s", b)) - SqlFunc("strftime", SqlSet("%s", a));
	case MY_SQL:
		return SqlFunc("timestampdiff", SqlSet(SqlVal("second", SqlS::HIGH), a, b));
	default:
		NEVER_("TimeDiff not implemented for this dialect");
		return SqlVal();
	}
}

String SqlEscape(const Value& in){
	if(in.IsNull() && !in.Is<String>() && !in.Is<WString>()) {
		return "NULL";
	}
	if(in.Is<int>() || in.Is<int64>() || in.Is<double>())
		return in.ToString();
	if(in.Is<Time>() || in.Is<Date>())
		return "\'" + in.ToString() + "\'";

	String str = in.ToString();
	const char* s = str.Begin();
	const char* lim = str.End();
	String t;
	t.Cat('\'');
	while(s < lim) {
		switch(*s) {
		case '\a': t.Cat("\\a"); break;
		case '\b': t.Cat("\\b"); break;
		case '\f': t.Cat("\\f"); break;
		case '\t': t.Cat("\\t"); break;
		case '\v': t.Cat("\\v"); break;
		case '\r': t.Cat("\\r"); break;
		case '\'': t.Cat("''"); break;
		case '\\': t.Cat("\\\\"); break;
		case '\n': t.Cat("\\n"); break;
		default:
			if(byte(*s) < 32 || (byte)*s >= 0x7f) {
				char h[4];
				int q = (byte)*s;
				h[0] = '\\';
				h[1] = (3 & (q >> 6)) + '0';
				h[2] = (7 & (q >> 3)) + '0';
				h[3] = (7 & q) + '0';
				t.Cat(h, 4);
			}
			else {
				t.Cat(*s);
			}
			break;
		}
		s++;
	}
	t.Cat('\'');
	return t;
}
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2015 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* 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 Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Plugins                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include "Binding_Base.h"
#include "Binding_Data.h"
#include "Binding_DisplayFlagsData.h"
#include "Binding_OptionsGroupData.h"
#include "Binding_Link.h"

#include <sofa/core/objectmodel/Base.h>
#include <sofa/core/objectmodel/BaseData.h>
using namespace sofa::core::objectmodel;
#include <sofa/core/visual/DisplayFlags.h>
using namespace sofa::core::visual;
#include <sofa/helper/OptionsGroup.h>
using namespace sofa::helper;

#include <sofa/helper/logging/Messaging.h>

extern "C" PyObject * Base_findData(PyObject *self, PyObject *args )
{
    Base* obj=((PySPtr<Base>*)self)->object.get();
    char *dataName;
    if (!PyArg_ParseTuple(args, "s",&dataName))
    {
        msg_error("Base_findData") <<"Base_findData_impl not a string\n";
        Py_RETURN_NONE;
    }
    BaseData * data = obj->findData(dataName);
    if (!data)
    {
        if( obj->hasField(dataName) )
            msg_error("Base_findData")<<"object '"<<obj->getName()<<"' has a field '"<<dataName<<"' but it is not a Data";
        else
        {
            msg_error("Base_findData")<<"object '"<<obj->getName()<<"' does no have a field '"<<dataName<<"'";
            std::stringstream s;
            obj->writeDatas(s,";");
            msg_error("Base_findData")<<s;
        }

        PyErr_BadArgument();

        Py_RETURN_NONE;
    }

    if (dynamic_cast<Data<DisplayFlags>*>(data))
        return SP_BUILD_PYPTR(DisplayFlagsData,BaseData,data,false);

    if (dynamic_cast<Data<OptionsGroup>*>(data))
        return SP_BUILD_PYPTR(OptionsGroupData,BaseData,data,false);

    return SP_BUILD_PYPTR(Data,BaseData,data,false);
}

extern "C" PyObject * Base_findLink(PyObject *self, PyObject *args)
{
    Base* obj=((PySPtr<Base>*)self)->object.get();
    char *linkName;
     if (!PyArg_ParseTuple(args, "s",&linkName))
         Py_RETURN_NONE;
    BaseLink * link = obj->findLink(linkName);
    if (!link)
    {
        if( obj->hasField(linkName) )
            msg_error("Base_findLink")<<"object '"<<obj->getName()<<"' has a field '"<<linkName<<"' but it is not a Link";
        else
        {
            msg_error("Base_findLink")<<"object '"<<obj->getName()<<"' does no have a field '"<<linkName<<"'";
            std::stringstream s;
            obj->writeDatas(s,";");
            msg_error("Base_findLink")<<s;
        }

        PyErr_BadArgument();
        Py_RETURN_NONE;
    }

    return SP_BUILD_PYPTR(Link,BaseLink,link,false);
}

// Generic accessor to Data fields (in python native type)
extern "C" PyObject* Base_GetAttr(PyObject *o, PyObject *attr_name)
{
    Base* obj=down_cast<Base>(((PySPtr<Base>*)o)->object.get());
    char *attrName = PyString_AsString(attr_name);
//    printf("Base_GetAttr type=%s name=%s attrName=%s\n",obj->getClassName().c_str(),obj->getName().c_str(),attrName);

    // see if a Data field has this name...
    BaseData * data = obj->findData(attrName);
    if (data) return GetDataValuePython(data); // we have our data... let's create the right Python type....

    // see if a Link has this name...
    BaseLink * link = obj->findLink(attrName);
    if (link) return GetLinkValuePython(link); // we have our link... let's create the right Python type....

    //        printf("Base_GetAttr ERROR data not found - type=%s name=%s attrName=%s\n",obj->getClassName().c_str(),obj->getName().c_str(),attrName);
    return PyObject_GenericGetAttr(o,attr_name);
}

extern "C" int Base_SetAttr(PyObject *o, PyObject *attr_name, PyObject *v)
{
    // attribute does not exist: see if a Data field has this name...
    Base* obj=down_cast<Base>(((PySPtr<Base>*)o)->object.get());
    char *attrName = PyString_AsString(attr_name);

//    printf("Base_SetAttr name=%s\n",dataName);
    BaseData * data = obj->findData(attrName);
    if (data)
    {
        if (SetDataValuePython(data,v)) return 0;
        else return -1;
    }

    BaseLink * link = obj->findLink(attrName);
    if (link)
    {
        if (SetLinkValuePython(link,v)) return 0;
        else return -1;
    }

    return PyObject_GenericSetAttr(o,attr_name,v);
}

extern "C" PyObject * Base_getClassName(PyObject * self, PyObject * /*args*/)
{
    // BaseNode is not binded in SofaPython, so getPathName is binded in Node instead
    Base* node = ((PySPtr<Base>*)self)->object.get();

    return PyString_FromString(node->getClassName().c_str());
}

extern "C" PyObject * Base_getTemplateName(PyObject * self, PyObject * /*args*/)
{
    // BaseNode is not binded in SofaPython, so getPathName is binded in Node instead
    Base* node = ((PySPtr<Base>*)self)->object.get();

    return PyString_FromString(node->getTemplateName().c_str());
}

extern "C" PyObject * Base_getName(PyObject * self, PyObject * /*args*/)
{
    // BaseNode is not binded in SofaPython, so getPathName is binded in Node instead
    Base* node = ((PySPtr<Base>*)self)->object.get();

    return PyString_FromString(node->getName().c_str());
}

SP_CLASS_METHODS_BEGIN(Base)
SP_CLASS_METHOD(Base,findData)
SP_CLASS_METHOD(Base,findLink)
SP_CLASS_METHOD(Base,getClassName)
SP_CLASS_METHOD(Base,getTemplateName)
SP_CLASS_METHOD(Base,getName)
SP_CLASS_METHODS_END

//SP_CLASS_DATA_ATTRIBUTE(Base,name)

SP_CLASS_ATTRS_BEGIN(Base)
//SP_CLASS_ATTR(Base,name)
SP_CLASS_ATTRS_END

SP_CLASS_TYPE_BASE_SPTR_ATTR_GETATTR(Base,Base)
<commit_msg>FIX build logger + SofaPython<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2015 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* 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 Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Plugins                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include "Binding_Base.h"
#include "Binding_Data.h"
#include "Binding_DisplayFlagsData.h"
#include "Binding_OptionsGroupData.h"
#include "Binding_Link.h"

#include <sofa/core/objectmodel/Base.h>
#include <sofa/core/objectmodel/BaseData.h>
using namespace sofa::core::objectmodel;
#include <sofa/core/visual/DisplayFlags.h>
using namespace sofa::core::visual;
#include <sofa/helper/OptionsGroup.h>
using namespace sofa::helper;

#include <sofa/helper/logging/Messaging.h>

extern "C" PyObject * Base_findData(PyObject *self, PyObject *args )
{
    Base* obj=((PySPtr<Base>*)self)->object.get();
    char *dataName;
    if (!PyArg_ParseTuple(args, "s",&dataName))
    {
        msg_error("Base_findData") <<"Base_findData_impl not a string\n";
        Py_RETURN_NONE;
    }
    BaseData * data = obj->findData(dataName);
    if (!data)
    {
        if( obj->hasField(dataName) )
            msg_error("Base_findData")<<"object '"<<obj->getName()<<"' has a field '"<<dataName<<"' but it is not a Data";
        else
        {
            msg_error("Base_findData")<<"object '"<<obj->getName()<<"' does no have a field '"<<dataName<<"'";
            std::stringstream s;
            obj->writeDatas(s,";");
            msg_error("Base_findData")<<s.str();
        }

        PyErr_BadArgument();

        Py_RETURN_NONE;
    }

    if (dynamic_cast<Data<DisplayFlags>*>(data))
        return SP_BUILD_PYPTR(DisplayFlagsData,BaseData,data,false);

    if (dynamic_cast<Data<OptionsGroup>*>(data))
        return SP_BUILD_PYPTR(OptionsGroupData,BaseData,data,false);

    return SP_BUILD_PYPTR(Data,BaseData,data,false);
}

extern "C" PyObject * Base_findLink(PyObject *self, PyObject *args)
{
    Base* obj=((PySPtr<Base>*)self)->object.get();
    char *linkName;
     if (!PyArg_ParseTuple(args, "s",&linkName))
         Py_RETURN_NONE;
    BaseLink * link = obj->findLink(linkName);
    if (!link)
    {
        if( obj->hasField(linkName) )
            msg_error("Base_findLink")<<"object '"<<obj->getName()<<"' has a field '"<<linkName<<"' but it is not a Link";
        else
        {
            msg_error("Base_findLink")<<"object '"<<obj->getName()<<"' does no have a field '"<<linkName<<"'";
            std::stringstream s;
            obj->writeDatas(s,";");
            msg_error("Base_findLink")<<s.str();
        }

        PyErr_BadArgument();
        Py_RETURN_NONE;
    }

    return SP_BUILD_PYPTR(Link,BaseLink,link,false);
}

// Generic accessor to Data fields (in python native type)
extern "C" PyObject* Base_GetAttr(PyObject *o, PyObject *attr_name)
{
    Base* obj=down_cast<Base>(((PySPtr<Base>*)o)->object.get());
    char *attrName = PyString_AsString(attr_name);
//    printf("Base_GetAttr type=%s name=%s attrName=%s\n",obj->getClassName().c_str(),obj->getName().c_str(),attrName);

    // see if a Data field has this name...
    BaseData * data = obj->findData(attrName);
    if (data) return GetDataValuePython(data); // we have our data... let's create the right Python type....

    // see if a Link has this name...
    BaseLink * link = obj->findLink(attrName);
    if (link) return GetLinkValuePython(link); // we have our link... let's create the right Python type....

    //        printf("Base_GetAttr ERROR data not found - type=%s name=%s attrName=%s\n",obj->getClassName().c_str(),obj->getName().c_str(),attrName);
    return PyObject_GenericGetAttr(o,attr_name);
}

extern "C" int Base_SetAttr(PyObject *o, PyObject *attr_name, PyObject *v)
{
    // attribute does not exist: see if a Data field has this name...
    Base* obj=down_cast<Base>(((PySPtr<Base>*)o)->object.get());
    char *attrName = PyString_AsString(attr_name);

//    printf("Base_SetAttr name=%s\n",dataName);
    BaseData * data = obj->findData(attrName);
    if (data)
    {
        if (SetDataValuePython(data,v)) return 0;
        else return -1;
    }

    BaseLink * link = obj->findLink(attrName);
    if (link)
    {
        if (SetLinkValuePython(link,v)) return 0;
        else return -1;
    }

    return PyObject_GenericSetAttr(o,attr_name,v);
}

extern "C" PyObject * Base_getClassName(PyObject * self, PyObject * /*args*/)
{
    // BaseNode is not binded in SofaPython, so getPathName is binded in Node instead
    Base* node = ((PySPtr<Base>*)self)->object.get();

    return PyString_FromString(node->getClassName().c_str());
}

extern "C" PyObject * Base_getTemplateName(PyObject * self, PyObject * /*args*/)
{
    // BaseNode is not binded in SofaPython, so getPathName is binded in Node instead
    Base* node = ((PySPtr<Base>*)self)->object.get();

    return PyString_FromString(node->getTemplateName().c_str());
}

extern "C" PyObject * Base_getName(PyObject * self, PyObject * /*args*/)
{
    // BaseNode is not binded in SofaPython, so getPathName is binded in Node instead
    Base* node = ((PySPtr<Base>*)self)->object.get();

    return PyString_FromString(node->getName().c_str());
}

SP_CLASS_METHODS_BEGIN(Base)
SP_CLASS_METHOD(Base,findData)
SP_CLASS_METHOD(Base,findLink)
SP_CLASS_METHOD(Base,getClassName)
SP_CLASS_METHOD(Base,getTemplateName)
SP_CLASS_METHOD(Base,getName)
SP_CLASS_METHODS_END

//SP_CLASS_DATA_ATTRIBUTE(Base,name)

SP_CLASS_ATTRS_BEGIN(Base)
//SP_CLASS_ATTR(Base,name)
SP_CLASS_ATTRS_END

SP_CLASS_TYPE_BASE_SPTR_ATTR_GETATTR(Base,Base)
<|endoftext|>