<commit_before>
#include "snake.h"

#include <list>
#include <cstdlib> // rand
#include <cassert>

#include "display.h"

namespace ssnake
{

Snake::Snake(Display* displayHandle,
             const SnakeTextureList& textureList,
             const Vec2& startingPos,
             const size_t startingLength)
{
    display = displayHandle;

    Vec2 win = {display->getSize_x(), display->getSize_y()};

    snakeTextures = textureList;

    // starting directions depend on starting postions
    // so don't immediately face a wall
    if (startingPos.x < (win.x / 2))
    {
        direction = RIGHT;
    }
    else
    {
        direction = LEFT;
    }

    // For now, truncate requested length if length doesn't fit
    if (static_cast<size_t>(startingPos.x) < startingLength)
    {
        length = startingPos.x;
    }
    else
    {
        length = startingLength;
    }

    // initialize positions
    int directionModifier = 1;
    if (direction == RIGHT)
    {
        directionModifier = -1;
    }
    for (int i = length - 1; i >= 0; --i)
    {
        Vec2 coord;
        coord.x = startingPos.x + directionModifier*i;
        coord.y = startingPos.y;
        if (coord.x > 0 && coord.x < win.x && coord.y > 0 && coord.y < win.y)
        {
            pos.push_back(coord);
        }
    }
}

void Snake::ai_getDirection(const std::list<Vec2>& foodList)
{
    if (pos.empty())
    {
        return;
    }

    Vec2 coord = pos.back();
    Vec2 win = {display->getSize_x(), display->getSize_y()};

    Direction_t ai_dir = direction;
    Direction_t newDir = ai_dir;

    int xOffset = win.x - coord.x;
    int yOffset = win.y - coord.y;

    // prevent hitting wall
    if (coord.x < 4 || coord.y < 4 || xOffset < 4 || yOffset < 4)
    {
        if (ai_dir != LEFT && coord.x < 4)
        {
            newDir = RIGHT;
        }
        else if (ai_dir != RIGHT && xOffset < 4)
        {
            newDir = LEFT;
        }
        if (ai_dir != UP && coord.y < 4)
        {
            newDir = DOWN;
        }
        else if (ai_dir != DOWN && yOffset < 4)
        {
            newDir = UP;
        }
        // if can't go backwards have to do multi-step turn around
        if ((ai_dir == LEFT && coord.x < 4) || (ai_dir == RIGHT && xOffset < 4))
        {
            if ((rand() % 2) == 1 && coord.y > 4)
            {
                newDir = UP;
            }
            else if (yOffset > 4)
            {
                newDir = DOWN;
            }
            else
            {
                newDir = UP;
            }
        }
        if ((ai_dir == UP && coord.y < 4) || (ai_dir == DOWN && yOffset < 4))
        {
            if ((rand() % 2) == 1 && coord.x > 4)
            {
                newDir = RIGHT;
            }
            else if (xOffset > 4)
            {
                newDir = LEFT;
            }
            else
            {
                newDir = RIGHT;
            }
        }
    } // end if (coord.x < 4 || coord.y < 4 || xOffset < 4 || yOffset < 4)
    else // not near wall, so evasive maneuvers not required, do something else
    {
        // random movement every so often
        if (coord.x > 3 && coord.y > 3 && xOffset > 3 && yOffset > 3)
        {
            int randn = rand() % 16;
            if (ai_dir == DOWN || ai_dir == UP)
            {
                if (randn == 1)
                {
                    newDir = LEFT;
                }
                else if (randn == 2)
                {
                    newDir = RIGHT;
                }
            }
            else
            {
                if (randn == 1)
                {
                    newDir = UP;
                }
                else if (randn == 2)
                {
                    newDir = DOWN;
                }
            }
        }

        // Only go for food if close to it and not near a wall
        for (std::list<Vec2>::const_iterator food = foodList.cbegin(); food != foodList.cend(); ++food)
        {
            if (ai_dir != LEFT && (food->x - coord.x) <= 3 && food->x > coord.x && food->x <= (win.x-4))
            {
                newDir = RIGHT;
                break;
            }
            else if (ai_dir != RIGHT && (coord.x - food->x) <= 3 && coord.x > food->x && food->x >= 4)
            {
                newDir = LEFT;
                break;
            }
            else if (ai_dir != DOWN && (coord.y - food->y) <= 3 && coord.y > food->y && food->y >= 4)
            {
                newDir = UP;
                break;
            }
            else if (ai_dir != UP && (food->y - coord.y) <= 3 && food->y > coord.y && food->y <= (win.y-4))
            {
                newDir = DOWN;
                break;
            }
        }
    }

    direction = newDir;

    return;
}

bool Snake::checkCollision()
{
    // head collision with other snake will leave snake empty from checkslice
    if (pos.empty())
    {
        return true;
    }

    Vec2 win = {display->getSize_x(), display->getSize_y()};

    Vec2 head = pos.back();

    // wall collision
    if (head.x >= (win.x - 1) || head.x <= 0 || head.y >= (win.y - 1) || head.y <= 0)
    {
        display->drawTexture(TEXTURE_COLLISION, head);

        return true;
    }

    // self collision
    // If checkSlice with itself happens first, then any collision segment will be removed
    if (length > 4)
    {
        std::list<Vec2>::const_iterator stop = --(--(--( --pos.cend() ))); // It isn't possible to self-hit segments just before the head
        for (std::list<Vec2>::const_iterator it = pos.cbegin(); it != stop; ++it)
        {
            if (head.x == it->x && head.y == it->y)
            {
                return true;
            }
        }
    }

    return false;
}

bool Snake::checkFood(const Vec2& food)
{
    if (pos.empty())
    {
        return false;
    }

    Vec2 snakeHead = pos.back();

    if (snakeHead.y != food.y || snakeHead.x != food.x)
    {
        return false;
    }

    ++length;

    return true;
}

bool Snake::checkTouch(const Vec2& checkedPos) const
{
    if (pos.empty())
    {
        return false;
    }

    for (std::list<Vec2>::const_iterator it = pos.cbegin(); it != pos.cend(); ++it)
    {
        if (checkedPos.x == it->x && checkedPos.y == it->y)
        {
            return true;
        }
    }

    return false;
}

size_t Snake::checkSlice(std::list<Snake>& snakeList)
{
    if (pos.empty())
    {
        return 0;
    }

    size_t totalCount = 0;

    Vec2 ss_coord = pos.back();

    for (std::list<Snake>::iterator slicedIter = snakeList.begin(); slicedIter != snakeList.end(); ++slicedIter)
    {
        if (slicedIter->pos.empty())
        {
            continue;
        }

        Vec2 sd_coord;

        int checkSize = slicedIter->pos.size();

        // Decrease collision-checksize by 1 as work-around to make snake not collide with it's own head
        // It can't actually hit the three segments behind head, so subtracting 3 more allows skipping checking those
        if (this == &(*slicedIter))
        {
            checkSize -= 4;
            if (checkSize < 0)
            {
                checkSize = 0;
            }
        }

        std::list<Vec2>::iterator it = slicedIter->pos.begin();
        std::list<Vec2>::iterator cut;
        for (int i = 1; i <= checkSize; ++i)
        {
            sd_coord = *it++;

            if (ss_coord.x == sd_coord.x && ss_coord.y == sd_coord.y)
            {
                cut = it;
                totalCount += i;

                assert(static_cast<int>(slicedIter->length) >= i);
                slicedIter->length -= i;

                if (slicedIter->length != 0)
                {
                    for (it = slicedIter->pos.begin(); it != cut; ++it)
                    {
                        display->drawTexture(TEXTURE_BACKGROUND, *it);
                    }
                }
                slicedIter->pos.erase(slicedIter->pos.begin(), cut);

                break;
            }
        }
    }

    return totalCount;
}

Direction_t Snake::getDirection() const
{
    return direction;
}

size_t Snake::getLength() const
{
    return length;
}

void Snake::move()
{
    if (pos.empty())
    {
        return;
    }

    Vec2 coord = pos.back();

    switch (direction)
    {
        case (LEFT) :
            --coord.x;
            break;
        case (RIGHT) :
            ++coord.x;
            break;
        case (UP) :
            --coord.y;
            break;
        case (DOWN) :
            ++coord.y;
            break;
    }

    display->moveSnakeHead(pos.back(), coord, snakeTextures);
    if (pos.size() > 1)
    {
        std::list<Vec2>::iterator start = ++pos.begin();
        std::list<Vec2>::iterator stop = --pos.end();
        for (std::list<Vec2>::iterator it = start; it != stop;)
        {
            display->moveSnakeBody(*it, *(++it), snakeTextures);
        }
        if (length <= pos.size())
        {
            display->moveSnakeTail(pos.front(), *(start), snakeTextures);
        }
    }
    else
    {
        display->drawTexture(TEXTURE_BACKGROUND, pos.back());
    }

    // remove at tail but not if length increased
    if (length <= pos.size())
    {
        pos.pop_front();
    }

    pos.push_back(coord);

    return;
}

void Snake::setDirection(Direction_t newDirection)
{
    if ( ( (newDirection == LEFT && direction != RIGHT) ||
           (newDirection == RIGHT && direction != LEFT) ||
           (newDirection == UP && direction != DOWN) ||
           (newDirection == DOWN && direction != UP)
         ) ||
         (length == 1)
       )
    {
        direction = newDirection;
    }
}

}
<commit_msg>Make checkCollision iteration less ugly<commit_after>
#include "snake.h"

#include <list>
#include <cstdlib> // rand
#include <cassert>

#include "display.h"

namespace ssnake
{

Snake::Snake(Display* displayHandle,
             const SnakeTextureList& textureList,
             const Vec2& startingPos,
             const size_t startingLength)
{
    display = displayHandle;

    Vec2 win = {display->getSize_x(), display->getSize_y()};

    snakeTextures = textureList;

    // starting directions depend on starting postions
    // so don't immediately face a wall
    if (startingPos.x < (win.x / 2))
    {
        direction = RIGHT;
    }
    else
    {
        direction = LEFT;
    }

    // For now, truncate requested length if length doesn't fit
    if (static_cast<size_t>(startingPos.x) < startingLength)
    {
        length = startingPos.x;
    }
    else
    {
        length = startingLength;
    }

    // initialize positions
    int directionModifier = 1;
    if (direction == RIGHT)
    {
        directionModifier = -1;
    }
    for (int i = length - 1; i >= 0; --i)
    {
        Vec2 coord;
        coord.x = startingPos.x + directionModifier*i;
        coord.y = startingPos.y;
        if (coord.x > 0 && coord.x < win.x && coord.y > 0 && coord.y < win.y)
        {
            pos.push_back(coord);
        }
    }
}

void Snake::ai_getDirection(const std::list<Vec2>& foodList)
{
    if (pos.empty())
    {
        return;
    }

    Vec2 coord = pos.back();
    Vec2 win = {display->getSize_x(), display->getSize_y()};

    Direction_t ai_dir = direction;
    Direction_t newDir = ai_dir;

    int xOffset = win.x - coord.x;
    int yOffset = win.y - coord.y;

    // prevent hitting wall
    if (coord.x < 4 || coord.y < 4 || xOffset < 4 || yOffset < 4)
    {
        if (ai_dir != LEFT && coord.x < 4)
        {
            newDir = RIGHT;
        }
        else if (ai_dir != RIGHT && xOffset < 4)
        {
            newDir = LEFT;
        }
        if (ai_dir != UP && coord.y < 4)
        {
            newDir = DOWN;
        }
        else if (ai_dir != DOWN && yOffset < 4)
        {
            newDir = UP;
        }
        // if can't go backwards have to do multi-step turn around
        if ((ai_dir == LEFT && coord.x < 4) || (ai_dir == RIGHT && xOffset < 4))
        {
            if ((rand() % 2) == 1 && coord.y > 4)
            {
                newDir = UP;
            }
            else if (yOffset > 4)
            {
                newDir = DOWN;
            }
            else
            {
                newDir = UP;
            }
        }
        if ((ai_dir == UP && coord.y < 4) || (ai_dir == DOWN && yOffset < 4))
        {
            if ((rand() % 2) == 1 && coord.x > 4)
            {
                newDir = RIGHT;
            }
            else if (xOffset > 4)
            {
                newDir = LEFT;
            }
            else
            {
                newDir = RIGHT;
            }
        }
    } // end if (coord.x < 4 || coord.y < 4 || xOffset < 4 || yOffset < 4)
    else // not near wall, so evasive maneuvers not required, do something else
    {
        // random movement every so often
        if (coord.x > 3 && coord.y > 3 && xOffset > 3 && yOffset > 3)
        {
            int randn = rand() % 16;
            if (ai_dir == DOWN || ai_dir == UP)
            {
                if (randn == 1)
                {
                    newDir = LEFT;
                }
                else if (randn == 2)
                {
                    newDir = RIGHT;
                }
            }
            else
            {
                if (randn == 1)
                {
                    newDir = UP;
                }
                else if (randn == 2)
                {
                    newDir = DOWN;
                }
            }
        }

        // Only go for food if close to it and not near a wall
        for (std::list<Vec2>::const_iterator food = foodList.cbegin(); food != foodList.cend(); ++food)
        {
            if (ai_dir != LEFT && (food->x - coord.x) <= 3 && food->x > coord.x && food->x <= (win.x-4))
            {
                newDir = RIGHT;
                break;
            }
            else if (ai_dir != RIGHT && (coord.x - food->x) <= 3 && coord.x > food->x && food->x >= 4)
            {
                newDir = LEFT;
                break;
            }
            else if (ai_dir != DOWN && (coord.y - food->y) <= 3 && coord.y > food->y && food->y >= 4)
            {
                newDir = UP;
                break;
            }
            else if (ai_dir != UP && (food->y - coord.y) <= 3 && food->y > coord.y && food->y <= (win.y-4))
            {
                newDir = DOWN;
                break;
            }
        }
    }

    direction = newDir;

    return;
}

bool Snake::checkCollision()
{
    // head collision with other snake will leave snake empty from checkslice
    if (pos.empty())
    {
        return true;
    }

    Vec2 win = {display->getSize_x(), display->getSize_y()};

    Vec2 head = pos.back();

    // wall collision
    if (head.x >= (win.x - 1) || head.x <= 0 || head.y >= (win.y - 1) || head.y <= 0)
    {
        display->drawTexture(TEXTURE_COLLISION, head);

        return true;
    }

    // self collision
    // If checkSlice with itself happens first, then any collision segment will be removed
    if (pos.size() > 4)
    {
        // It isn't possible to self-hit segments just before the head
        int checkLength = pos.size() - 4;
        std::list<Vec2>::const_iterator it = pos.cbegin();
        for (int i = 0; i < checkLength; ++i, ++it)
        {
            if (head.x == it->x && head.y == it->y)
            {
                return true;
            }
        }
    }

    return false;
}

bool Snake::checkFood(const Vec2& food)
{
    if (pos.empty())
    {
        return false;
    }

    Vec2 snakeHead = pos.back();

    if (snakeHead.y != food.y || snakeHead.x != food.x)
    {
        return false;
    }

    ++length;

    return true;
}

bool Snake::checkTouch(const Vec2& checkedPos) const
{
    if (pos.empty())
    {
        return false;
    }

    for (std::list<Vec2>::const_iterator it = pos.cbegin(); it != pos.cend(); ++it)
    {
        if (checkedPos.x == it->x && checkedPos.y == it->y)
        {
            return true;
        }
    }

    return false;
}

size_t Snake::checkSlice(std::list<Snake>& snakeList)
{
    if (pos.empty())
    {
        return 0;
    }

    size_t totalCount = 0;

    Vec2 ss_coord = pos.back();

    for (std::list<Snake>::iterator slicedIter = snakeList.begin(); slicedIter != snakeList.end(); ++slicedIter)
    {
        if (slicedIter->pos.empty())
        {
            continue;
        }

        Vec2 sd_coord;

        int checkSize = slicedIter->pos.size();

        // Decrease collision-checksize by 1 as work-around to make snake not collide with it's own head
        // It can't actually hit the three segments behind head, so subtracting 3 more allows skipping checking those
        if (this == &(*slicedIter))
        {
            checkSize -= 4;
            if (checkSize < 0)
            {
                checkSize = 0;
            }
        }

        std::list<Vec2>::iterator it = slicedIter->pos.begin();
        std::list<Vec2>::iterator cut;
        for (int i = 1; i <= checkSize; ++i)
        {
            sd_coord = *it++;

            if (ss_coord.x == sd_coord.x && ss_coord.y == sd_coord.y)
            {
                cut = it;
                totalCount += i;

                assert(static_cast<int>(slicedIter->length) >= i);
                slicedIter->length -= i;

                if (slicedIter->length != 0)
                {
                    for (it = slicedIter->pos.begin(); it != cut; ++it)
                    {
                        display->drawTexture(TEXTURE_BACKGROUND, *it);
                    }
                }
                slicedIter->pos.erase(slicedIter->pos.begin(), cut);

                break;
            }
        }
    }

    return totalCount;
}

Direction_t Snake::getDirection() const
{
    return direction;
}

size_t Snake::getLength() const
{
    return length;
}

void Snake::move()
{
    if (pos.empty())
    {
        return;
    }

    Vec2 coord = pos.back();

    switch (direction)
    {
        case (LEFT) :
            --coord.x;
            break;
        case (RIGHT) :
            ++coord.x;
            break;
        case (UP) :
            --coord.y;
            break;
        case (DOWN) :
            ++coord.y;
            break;
    }

    display->moveSnakeHead(pos.back(), coord, snakeTextures);
    if (pos.size() > 1)
    {
        std::list<Vec2>::iterator start = ++pos.begin();
        std::list<Vec2>::iterator stop = --pos.end();
        for (std::list<Vec2>::iterator it = start; it != stop;)
        {
            display->moveSnakeBody(*it, *(++it), snakeTextures);
        }
        if (length <= pos.size())
        {
            display->moveSnakeTail(pos.front(), *(start), snakeTextures);
        }
    }
    else
    {
        display->drawTexture(TEXTURE_BACKGROUND, pos.back());
    }

    // remove at tail but not if length increased
    if (length <= pos.size())
    {
        pos.pop_front();
    }

    pos.push_back(coord);

    return;
}

void Snake::setDirection(Direction_t newDirection)
{
    if ( ( (newDirection == LEFT && direction != RIGHT) ||
           (newDirection == RIGHT && direction != LEFT) ||
           (newDirection == UP && direction != DOWN) ||
           (newDirection == DOWN && direction != UP)
         ) ||
         (length == 1)
       )
    {
        direction = newDirection;
    }
}

}
<|endoftext|>


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

//$Id$

#if !defined LABEL_COLLISION_DETECTOR
#define LABEL_COLLISION_DETECTOR
// mapnik
#include <mapnik/quad_tree.hpp>
#include <mapnik/value.hpp>
// stl
#include <vector>
#include <unicode/unistr.h>

namespace mapnik
{
   //this needs to be tree structure
   //as a proof of a concept _only_ we use sequential scan

   struct label_collision_detector
   {
      typedef std::vector<box2d<double> > label_placements;

      bool has_plasement(box2d<double> const& box)
      {
         label_placements::const_iterator itr=labels_.begin();
         for( ; itr !=labels_.end();++itr)
         {
            if (itr->intersects(box))
            {
               return false;
            }
         }
         labels_.push_back(box);
         return true;
      }
      void clear()
      {
         labels_.clear();
      }

   private:

      label_placements labels_;
   };

   // quad_tree based label collision detector
   class label_collision_detector2 : boost::noncopyable
   {
      typedef quad_tree<box2d<double> > tree_t;
      tree_t tree_;
   public:

      explicit label_collision_detector2(box2d<double> const& extent)
         : tree_(extent) {}

      bool has_placement(box2d<double> const& box)
      {
         tree_t::query_iterator itr = tree_.query_in_box(box);
         tree_t::query_iterator end = tree_.query_end();

         for ( ;itr != end; ++itr)
         {
            if (itr->intersects(box))
            {
               return false;
            }
         }

         tree_.insert(box,box);
         return true;
      }

      void clear()
      {
         tree_.clear();
      }

   };

   // quad_tree based label collision detector with seperate check/insert
   class label_collision_detector3 : boost::noncopyable
   {
      typedef quad_tree< box2d<double> > tree_t;
      tree_t tree_;
   public:

      explicit label_collision_detector3(box2d<double> const& extent)
         : tree_(extent) {}

      bool has_placement(box2d<double> const& box)
      {
         tree_t::query_iterator itr = tree_.query_in_box(box);
         tree_t::query_iterator end = tree_.query_end();

         for ( ;itr != end; ++itr)
         {
            if (itr->intersects(box))
            {
               return false;
            }
         }

         return true;
      }

      void insert(box2d<double> const& box)
      {
         tree_.insert(box, box);
      }

      void clear()
      {
         tree_.clear();
      }
   };

   //quad tree based label collission detector so labels dont appear within a given distance
   class label_collision_detector4 : boost::noncopyable
   {
      struct label
      {
         label(box2d<double> const& b) : box(b) {}
         label(box2d<double> const& b, UnicodeString const& t) : box(b), text(t) {}

         box2d<double> box;
         UnicodeString text;
      };

      typedef quad_tree< label > tree_t;
      box2d<double> extent_;
      tree_t tree_;

   public:

      explicit label_collision_detector4(box2d<double> const& extent)
         : extent_(extent),
           tree_(extent) {}

      bool has_placement(box2d<double> const& box)
      {
         tree_t::query_iterator itr = tree_.query_in_box(box);
         tree_t::query_iterator end = tree_.query_end();

         for ( ;itr != end; ++itr)
         {
            if (itr->box.intersects(box))
            {
               return false;
            }
         }

         return true;
      }

      bool has_placement(box2d<double> const& box, UnicodeString const& text, double distance)
      {
         box2d<double> bigger_box(box.minx() - distance, box.miny() - distance, box.maxx() + distance, box.maxy() + distance);
         tree_t::query_iterator itr = tree_.query_in_box(bigger_box);
         tree_t::query_iterator end = tree_.query_end();

         for ( ;itr != end; ++itr)
         {
            if (itr->box.intersects(box) || (text == itr->text && itr->box.intersects(bigger_box)))
            {
               return false;
            }
         }

         return true;
      }

      bool has_point_placement(box2d<double> const& box, double distance)
      {
         box2d<double> bigger_box(box.minx() - distance, box.miny() - distance, box.maxx() + distance, box.maxy() + distance);
         tree_t::query_iterator itr = tree_.query_in_box(bigger_box);
         tree_t::query_iterator end = tree_.query_end();

         for ( ;itr != end; ++itr)
         {
            if (itr->box.intersects(bigger_box))
            {
               return false;
            }
         }

         return true;
      }

      void insert(box2d<double> const& box)
      {
         tree_.insert(label(box), box);
      }

      void insert(box2d<double> const& box, UnicodeString const& text)
      {
         tree_.insert(label(box, text), box);
      }

      void clear()
      {
         tree_.clear();
      }

      box2d<double> const& extent() const
      {
         return extent_;
      }
   };
}

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

//$Id$

#ifndef LABEL_COLLISION_DETECTOR_HPP
#define LABEL_COLLISION_DETECTOR_HPP

// mapnik
#include <mapnik/quad_tree.hpp>
// stl
#include <vector>
#include <unicode/unistr.h>

namespace mapnik
{
   //this needs to be tree structure
   //as a proof of a concept _only_ we use sequential scan

   struct label_collision_detector
   {
      typedef std::vector<box2d<double> > label_placements;

      bool has_plasement(box2d<double> const& box)
      {
         label_placements::const_iterator itr=labels_.begin();
         for( ; itr !=labels_.end();++itr)
         {
            if (itr->intersects(box))
            {
               return false;
            }
         }
         labels_.push_back(box);
         return true;
      }
      void clear()
      {
         labels_.clear();
      }

   private:

      label_placements labels_;
   };

   // quad_tree based label collision detector
   class label_collision_detector2 : boost::noncopyable
   {
      typedef quad_tree<box2d<double> > tree_t;
      tree_t tree_;
   public:

      explicit label_collision_detector2(box2d<double> const& extent)
         : tree_(extent) {}

      bool has_placement(box2d<double> const& box)
      {
         tree_t::query_iterator itr = tree_.query_in_box(box);
         tree_t::query_iterator end = tree_.query_end();

         for ( ;itr != end; ++itr)
         {
            if (itr->intersects(box))
            {
               return false;
            }
         }

         tree_.insert(box,box);
         return true;
      }

      void clear()
      {
         tree_.clear();
      }

   };

   // quad_tree based label collision detector with seperate check/insert
   class label_collision_detector3 : boost::noncopyable
   {
      typedef quad_tree< box2d<double> > tree_t;
      tree_t tree_;
   public:

      explicit label_collision_detector3(box2d<double> const& extent)
         : tree_(extent) {}

      bool has_placement(box2d<double> const& box)
      {
         tree_t::query_iterator itr = tree_.query_in_box(box);
         tree_t::query_iterator end = tree_.query_end();

         for ( ;itr != end; ++itr)
         {
            if (itr->intersects(box))
            {
               return false;
            }
         }

         return true;
      }

      void insert(box2d<double> const& box)
      {
         tree_.insert(box, box);
      }

      void clear()
      {
         tree_.clear();
      }
   };

   //quad tree based label collission detector so labels dont appear within a given distance
   class label_collision_detector4 : boost::noncopyable
   {
      struct label
      {
         label(box2d<double> const& b) : box(b) {}
         label(box2d<double> const& b, UnicodeString const& t) : box(b), text(t) {}

         box2d<double> box;
         UnicodeString text;
      };

      typedef quad_tree< label > tree_t;
      box2d<double> extent_;
      tree_t tree_;

   public:

      explicit label_collision_detector4(box2d<double> const& extent)
         : extent_(extent),
           tree_(extent) {}

      bool has_placement(box2d<double> const& box)
      {
         tree_t::query_iterator itr = tree_.query_in_box(box);
         tree_t::query_iterator end = tree_.query_end();

         for ( ;itr != end; ++itr)
         {
            if (itr->box.intersects(box))
            {
               return false;
            }
         }

         return true;
      }

      bool has_placement(box2d<double> const& box, UnicodeString const& text, double distance)
      {
         box2d<double> bigger_box(box.minx() - distance, box.miny() - distance, box.maxx() + distance, box.maxy() + distance);
         tree_t::query_iterator itr = tree_.query_in_box(bigger_box);
         tree_t::query_iterator end = tree_.query_end();

         for ( ;itr != end; ++itr)
         {
            if (itr->box.intersects(box) || (text == itr->text && itr->box.intersects(bigger_box)))
            {
               return false;
            }
         }

         return true;
      }

      bool has_point_placement(box2d<double> const& box, double distance)
      {
         box2d<double> bigger_box(box.minx() - distance, box.miny() - distance, box.maxx() + distance, box.maxy() + distance);
         tree_t::query_iterator itr = tree_.query_in_box(bigger_box);
         tree_t::query_iterator end = tree_.query_end();

         for ( ;itr != end; ++itr)
         {
            if (itr->box.intersects(bigger_box))
            {
               return false;
            }
         }

         return true;
      }

      void insert(box2d<double> const& box)
      {
         tree_.insert(label(box), box);
      }

      void insert(box2d<double> const& box, UnicodeString const& text)
      {
         tree_.insert(label(box, text), box);
      }

      void clear()
      {
         tree_.clear();
      }

      box2d<double> const& extent() const
      {
         return extent_;
      }
   };
}

#endif // LABEL_COLLISION_DETECTOR_HPP
<|endoftext|>


<commit_before>/**************************************************************************
**
** Copyright (c) 2012 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "androidrunner.h"

#include "androiddeploystep.h"
#include "androidconfigurations.h"
#include "androidglobal.h"
#include "androidrunconfiguration.h"
#include "androidmanager.h"

#include <projectexplorer/target.h>

#include <QTime>
#include <QtConcurrentRun>

namespace Android {
namespace Internal {

AndroidRunner::AndroidRunner(QObject *parent, AndroidRunConfiguration *runConfig, bool debuggingMode)
    : QThread(parent)
{
    m_useCppDebugger = debuggingMode && runConfig->debuggerAspect()->useCppDebugger();
    m_useQmlDebugger = debuggingMode && runConfig->debuggerAspect()->useQmlDebugger();
    m_remoteGdbChannel = runConfig->remoteChannel();
    m_qmlPort = runConfig->debuggerAspect()->qmlDebugServerPort();
    ProjectExplorer::Target *target = runConfig->target();
    AndroidDeployStep *ds = runConfig->deployStep();
    if ((m_useLocalQtLibs = ds->useLocalQtLibs())) {
        m_localLibs = AndroidManager::loadLocalLibs(target, ds->deviceAPILevel());
        m_localJars = AndroidManager::loadLocalJars(target, ds->deviceAPILevel());
    }
    m_intentName = AndroidManager::intentName(target);
    m_packageName = m_intentName.left(m_intentName.indexOf(QLatin1Char('/')));
    m_deviceSerialNumber = ds->deviceSerialNumber();
    m_processPID = -1;
    m_gdbserverPID = -1;
    connect(&m_checkPIDTimer, SIGNAL(timeout()), SLOT(checkPID()));
    connect(&m_adbLogcatProcess, SIGNAL(readyReadStandardOutput()), SLOT(logcatReadStandardOutput()));
    connect(&m_adbLogcatProcess, SIGNAL(readyReadStandardError()) , SLOT(logcatReadStandardError()));
}

AndroidRunner::~AndroidRunner()
{
    stop();
}

void AndroidRunner::checkPID()
{
    QProcess psProc;
    psProc.start(AndroidConfigurations::instance().adbToolPath().toString(),
                 QStringList() << QLatin1String("-s") << m_deviceSerialNumber
                 << QLatin1String("shell") << QLatin1String("ps"));
    if (!psProc.waitForFinished(-1)) {
        psProc.terminate();
        return;
    }
    qint64 pid = -1;
    QList<QByteArray> procs = psProc.readAll().split('\n');
    foreach (const QByteArray &proc, procs) {
        if (proc.trimmed().endsWith(m_packageName.toLatin1())) {
            QRegExp rx(QLatin1String("(\\d+)"));
            if (rx.indexIn(QLatin1String(proc), proc.indexOf(' ')) > 0) {
                pid = rx.cap(1).toLongLong();
                break;
            }
        }
    }

    if (-1 != m_processPID && pid == -1) {
        m_processPID = -1;
        emit remoteProcessFinished(tr("\n\n'%1' died.").arg(m_packageName));
        return;
    }
    m_processPID = pid;

    if (!m_useCppDebugger)
        return;
    m_gdbserverPID = -1;
    foreach (const QByteArray &proc, procs) {
        if (proc.trimmed().endsWith("gdbserver")) {
            QRegExp rx(QLatin1String("(\\d+)"));
            if (rx.indexIn(QLatin1String(proc), proc.indexOf(' ')) > 0) {
                m_gdbserverPID = rx.cap(1).toLongLong();
                break;
            }
        }
    }
}

void AndroidRunner::killPID()
{
    checkPID(); //updates m_processPID and m_gdbserverPID
    for (int tries = 0; tries < 10 && (m_processPID != -1 || m_gdbserverPID != -1); ++tries) {
        if (m_processPID != -1) {
            adbKill(m_processPID, m_deviceSerialNumber, 2000);
            adbKill(m_processPID, m_deviceSerialNumber, 2000, m_packageName);
        }

        if (m_gdbserverPID != -1) {
            adbKill(m_gdbserverPID, m_deviceSerialNumber, 2000);
            adbKill(m_gdbserverPID, m_deviceSerialNumber, 2000, m_packageName);
        }
        checkPID();
    }
}

void AndroidRunner::start()
{
    QtConcurrent::run(this,&AndroidRunner::asyncStart);
}

void AndroidRunner::asyncStart()
{
    QMutexLocker locker(&m_mutex);
    m_processPID = -1;
    killPID(); // kill any process with this name
    QString extraParams;
    QProcess adbStarProc;
    if (m_useCppDebugger) {
        QStringList arguments;
        arguments << QLatin1String("-s") << m_deviceSerialNumber
                  << QLatin1String("forward") << QString::fromLatin1("tcp%1").arg(m_remoteGdbChannel)
                  << QString::fromLatin1("localfilesystem:/data/data/%1/debug-socket").arg(m_packageName);
        adbStarProc.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
        if (!adbStarProc.waitForStarted()) {
            emit remoteProcessFinished(tr("Failed to forward C++ debugging ports. Reason: %1.").arg(adbStarProc.errorString()));
            return;
        }
        if (!adbStarProc.waitForFinished(-1)) {
            emit remoteProcessFinished(tr("Failed to forward C++ debugging ports."));
            return;
        }
        extraParams = QLatin1String("-e native_debug true -e gdbserver_socket +debug-socket");
    }
    if (m_useQmlDebugger) {
        QStringList arguments;
        QString port = QString::fromLatin1("tcp:%1").arg(m_qmlPort);
        arguments << QLatin1String("-s") << m_deviceSerialNumber
                  << QLatin1String("forward") << port << port; // currently forward to same port on device and host
        adbStarProc.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
        if (!adbStarProc.waitForStarted()) {
            emit remoteProcessFinished(tr("Failed to forward QML debugging ports. Reason: %1.").arg(adbStarProc.errorString()));
            return;
        }
        if (!adbStarProc.waitForFinished(-1)) {
            emit remoteProcessFinished(tr("Failed to forward QML debugging ports."));
            return;
        }
        extraParams+=QString::fromLatin1(" -e qml_debug true -e qmljsdebugger port:%1")
                .arg(m_qmlPort);
    }

    if (m_useLocalQtLibs) {
        extraParams += QLatin1String(" -e use_local_qt_libs true");
        extraParams += QLatin1String(" -e libs_prefix /data/local/qt/");
        extraParams += QLatin1String(" -e load_local_libs ") + m_localLibs;
        extraParams += QLatin1String(" -e load_local_jars ") + m_localJars;
    }

    extraParams = extraParams.trimmed();
    QStringList arguments;
    arguments << QLatin1String("-s") << m_deviceSerialNumber
              << QLatin1String("shell") << QLatin1String("am")
              << QLatin1String("start") << QLatin1String("-n") << m_intentName;

    if (extraParams.length())
        arguments << extraParams.split(QLatin1Char(' '));

    adbStarProc.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
    if (!adbStarProc.waitForStarted()) {
        emit remoteProcessFinished(tr("Failed to start the activity. Reason: %1.").arg(adbStarProc.errorString()));
        return;
    }
    if (!adbStarProc.waitForFinished(-1)) {
        adbStarProc.terminate();
        emit remoteProcessFinished(tr("Unable to start '%1'.").arg(m_packageName));
        return;
    }
    QTime startTime = QTime::currentTime();
    while (m_processPID == -1 && startTime.secsTo(QTime::currentTime()) < 10) { // wait up to 10 seconds for application to start
        checkPID();
    }
    if (m_processPID == -1) {
        emit remoteProcessFinished(tr("Cannot find %1 process.").arg(m_packageName));
        return;
    }

    if (m_useCppDebugger) {
        startTime = QTime::currentTime();
        while (m_gdbserverPID == -1 && startTime.secsTo(QTime::currentTime()) < 25) { // wait up to 25 seconds to connect
            checkPID();
        }
        msleep(200); // give gdbserver more time to start
    }

    QMetaObject::invokeMethod(this, "startLogcat", Qt::QueuedConnection);
}

void AndroidRunner::startLogcat()
{
    m_checkPIDTimer.start(1000); // check if the application is alive every 1 seconds
    m_adbLogcatProcess.start(AndroidConfigurations::instance().adbToolPath().toString(),
                             QStringList() << QLatin1String("-s") << m_deviceSerialNumber
                             << QLatin1String("logcat"));
    emit remoteProcessStarted(5039);
}

void AndroidRunner::stop()
{
    QMutexLocker locker(&m_mutex);
    m_adbLogcatProcess.terminate();
    m_adbLogcatProcess.waitForFinished(-1);
    m_checkPIDTimer.stop();
    if (m_processPID == -1)
        return; // don't emit another signal
    QtConcurrent::run(this, &AndroidRunner::asyncStop);
}
void AndroidRunner::asyncStop()
{
    killPID();
    emit remoteProcessFinished(tr("\n\n'%1' killed.").arg(m_packageName));
}

void AndroidRunner::logcatReadStandardError()
{
    emit remoteErrorOutput(m_adbLogcatProcess.readAllStandardError());
}

void AndroidRunner::logcatReadStandardOutput()
{
    m_logcat += m_adbLogcatProcess.readAllStandardOutput();
    bool keepLastLine = m_logcat.endsWith('\n');
    QByteArray line;
    QByteArray pid(QString::fromLatin1("%1):").arg(m_processPID).toLatin1());
    foreach (line, m_logcat.split('\n')) {
        if (!line.contains(pid))
            continue;
        if (line.endsWith('\r'))
            line.chop(1);
        line.append('\n');
        if (line.startsWith("E/"))
            emit remoteErrorOutput(line);
        else
            emit remoteOutput(line);

    }
    if (keepLastLine)
        m_logcat = line;
}

void AndroidRunner::adbKill(qint64 pid, const QString &device, int timeout, const QString &runAsPackageName)
{
    QProcess process;
    QStringList arguments;

    arguments << QLatin1String("-s") << device;
    arguments << QLatin1String("shell");
    if (runAsPackageName.size())
        arguments << QLatin1String("run-as") << runAsPackageName;
    arguments << QLatin1String("kill") << QLatin1String("-9");
    arguments << QString::number(pid);

    process.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
    if (!process.waitForFinished(timeout))
        process.terminate();
}

QString AndroidRunner::displayName() const
{
    return m_packageName;
}

} // namespace Internal
} // namespace Qt4ProjectManager
<commit_msg>Fix Android ps output processing when ps is really busybox.<commit_after>/**************************************************************************
**
** Copyright (c) 2012 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "androidrunner.h"

#include "androiddeploystep.h"
#include "androidconfigurations.h"
#include "androidglobal.h"
#include "androidrunconfiguration.h"
#include "androidmanager.h"

#include <projectexplorer/target.h>

#include <QTime>
#include <QtConcurrentRun>

namespace Android {
namespace Internal {

AndroidRunner::AndroidRunner(QObject *parent, AndroidRunConfiguration *runConfig, bool debuggingMode)
    : QThread(parent)
{
    m_useCppDebugger = debuggingMode && runConfig->debuggerAspect()->useCppDebugger();
    m_useQmlDebugger = debuggingMode && runConfig->debuggerAspect()->useQmlDebugger();
    m_remoteGdbChannel = runConfig->remoteChannel();
    m_qmlPort = runConfig->debuggerAspect()->qmlDebugServerPort();
    ProjectExplorer::Target *target = runConfig->target();
    AndroidDeployStep *ds = runConfig->deployStep();
    if ((m_useLocalQtLibs = ds->useLocalQtLibs())) {
        m_localLibs = AndroidManager::loadLocalLibs(target, ds->deviceAPILevel());
        m_localJars = AndroidManager::loadLocalJars(target, ds->deviceAPILevel());
    }
    m_intentName = AndroidManager::intentName(target);
    m_packageName = m_intentName.left(m_intentName.indexOf(QLatin1Char('/')));
    m_deviceSerialNumber = ds->deviceSerialNumber();
    m_processPID = -1;
    m_gdbserverPID = -1;
    connect(&m_checkPIDTimer, SIGNAL(timeout()), SLOT(checkPID()));
    connect(&m_adbLogcatProcess, SIGNAL(readyReadStandardOutput()), SLOT(logcatReadStandardOutput()));
    connect(&m_adbLogcatProcess, SIGNAL(readyReadStandardError()) , SLOT(logcatReadStandardError()));
}

AndroidRunner::~AndroidRunner()
{
    stop();
}

void AndroidRunner::checkPID()
{
    QProcess psProc;
    QLatin1String psCmd = QLatin1String("ps");
    QLatin1String psPidRx = QLatin1String("\\d+\\s+(\\d+)");

    // Detect busybox, as we need to pass -w to it to get wide output.
    psProc.start(AndroidConfigurations::instance().adbToolPath().toString(),
                 QStringList() << QLatin1String("-s") << m_deviceSerialNumber
                 << QLatin1String("shell") << QLatin1String("readlink") << QLatin1String("$(which ps)"));
    if (!psProc.waitForFinished(-1)) {
        psProc.terminate();
        return;
    }
    QByteArray which = psProc.readAll();
    if (which.startsWith("busybox")) {
        psCmd = QLatin1String("ps -w");
        psPidRx = QLatin1String("(\\d+)");
    }

    psProc.start(AndroidConfigurations::instance().adbToolPath().toString(),
                 QStringList() << QLatin1String("-s") << m_deviceSerialNumber
                 << QLatin1String("shell") << psCmd);
    if (!psProc.waitForFinished(-1)) {
        psProc.kill();
        return;
    }
    QRegExp rx(psPidRx);
    qint64 pid = -1;
    QList<QByteArray> procs = psProc.readAll().split('\n');
    foreach (const QByteArray &proc, procs) {
        if (proc.trimmed().endsWith(m_packageName.toLatin1())) {
            if (rx.indexIn(QLatin1String(proc)) > -1) {
                pid = rx.cap(1).toLongLong();
                break;
            }
        }
    }

    if (-1 != m_processPID && pid == -1) {
        m_processPID = -1;
        emit remoteProcessFinished(tr("\n\n'%1' died.").arg(m_packageName));
        return;
    }
    m_processPID = pid;

    if (!m_useCppDebugger)
        return;
    m_gdbserverPID = -1;
    foreach (const QByteArray &proc, procs) {
        if (proc.trimmed().endsWith("gdbserver")) {
            if (rx.indexIn(QLatin1String(proc)) > -1) {
                m_gdbserverPID = rx.cap(1).toLongLong();
                break;
            }
        }
    }
}

void AndroidRunner::killPID()
{
    checkPID(); //updates m_processPID and m_gdbserverPID
    for (int tries = 0; tries < 10 && (m_processPID != -1 || m_gdbserverPID != -1); ++tries) {
        if (m_processPID != -1) {
            adbKill(m_processPID, m_deviceSerialNumber, 2000);
            adbKill(m_processPID, m_deviceSerialNumber, 2000, m_packageName);
        }

        if (m_gdbserverPID != -1) {
            adbKill(m_gdbserverPID, m_deviceSerialNumber, 2000);
            adbKill(m_gdbserverPID, m_deviceSerialNumber, 2000, m_packageName);
        }
        checkPID();
    }
}

void AndroidRunner::start()
{
    QtConcurrent::run(this,&AndroidRunner::asyncStart);
}

void AndroidRunner::asyncStart()
{
    QMutexLocker locker(&m_mutex);
    m_processPID = -1;
    killPID(); // kill any process with this name
    QString extraParams;
    QProcess adbStarProc;
    if (m_useCppDebugger) {
        QStringList arguments;
        arguments << QLatin1String("-s") << m_deviceSerialNumber
                  << QLatin1String("forward") << QString::fromLatin1("tcp%1").arg(m_remoteGdbChannel)
                  << QString::fromLatin1("localfilesystem:/data/data/%1/debug-socket").arg(m_packageName);
        adbStarProc.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
        if (!adbStarProc.waitForStarted()) {
            emit remoteProcessFinished(tr("Failed to forward C++ debugging ports. Reason: %1.").arg(adbStarProc.errorString()));
            return;
        }
        if (!adbStarProc.waitForFinished(-1)) {
            emit remoteProcessFinished(tr("Failed to forward C++ debugging ports."));
            return;
        }
        extraParams = QLatin1String("-e native_debug true -e gdbserver_socket +debug-socket");
    }
    if (m_useQmlDebugger) {
        QStringList arguments;
        QString port = QString::fromLatin1("tcp:%1").arg(m_qmlPort);
        arguments << QLatin1String("-s") << m_deviceSerialNumber
                  << QLatin1String("forward") << port << port; // currently forward to same port on device and host
        adbStarProc.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
        if (!adbStarProc.waitForStarted()) {
            emit remoteProcessFinished(tr("Failed to forward QML debugging ports. Reason: %1.").arg(adbStarProc.errorString()));
            return;
        }
        if (!adbStarProc.waitForFinished(-1)) {
            emit remoteProcessFinished(tr("Failed to forward QML debugging ports."));
            return;
        }
        extraParams+=QString::fromLatin1(" -e qml_debug true -e qmljsdebugger port:%1")
                .arg(m_qmlPort);
    }

    if (m_useLocalQtLibs) {
        extraParams += QLatin1String(" -e use_local_qt_libs true");
        extraParams += QLatin1String(" -e libs_prefix /data/local/qt/");
        extraParams += QLatin1String(" -e load_local_libs ") + m_localLibs;
        extraParams += QLatin1String(" -e load_local_jars ") + m_localJars;
    }

    extraParams = extraParams.trimmed();
    QStringList arguments;
    arguments << QLatin1String("-s") << m_deviceSerialNumber
              << QLatin1String("shell") << QLatin1String("am")
              << QLatin1String("start") << QLatin1String("-n") << m_intentName;

    if (extraParams.length())
        arguments << extraParams.split(QLatin1Char(' '));

    adbStarProc.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
    if (!adbStarProc.waitForStarted()) {
        emit remoteProcessFinished(tr("Failed to start the activity. Reason: %1.").arg(adbStarProc.errorString()));
        return;
    }
    if (!adbStarProc.waitForFinished(-1)) {
        adbStarProc.terminate();
        emit remoteProcessFinished(tr("Unable to start '%1'.").arg(m_packageName));
        return;
    }
    QTime startTime = QTime::currentTime();
    while (m_processPID == -1 && startTime.secsTo(QTime::currentTime()) < 10) { // wait up to 10 seconds for application to start
        checkPID();
    }
    if (m_processPID == -1) {
        emit remoteProcessFinished(tr("Cannot find %1 process.").arg(m_packageName));
        return;
    }

    if (m_useCppDebugger) {
        startTime = QTime::currentTime();
        while (m_gdbserverPID == -1 && startTime.secsTo(QTime::currentTime()) < 25) { // wait up to 25 seconds to connect
            checkPID();
        }
        msleep(200); // give gdbserver more time to start
    }

    QMetaObject::invokeMethod(this, "startLogcat", Qt::QueuedConnection);
}

void AndroidRunner::startLogcat()
{
    m_checkPIDTimer.start(1000); // check if the application is alive every 1 seconds
    m_adbLogcatProcess.start(AndroidConfigurations::instance().adbToolPath().toString(),
                             QStringList() << QLatin1String("-s") << m_deviceSerialNumber
                             << QLatin1String("logcat"));
    emit remoteProcessStarted(5039);
}

void AndroidRunner::stop()
{
    QMutexLocker locker(&m_mutex);
    m_adbLogcatProcess.terminate();
    m_adbLogcatProcess.waitForFinished(-1);
    m_checkPIDTimer.stop();
    if (m_processPID == -1)
        return; // don't emit another signal
    QtConcurrent::run(this, &AndroidRunner::asyncStop);
}
void AndroidRunner::asyncStop()
{
    killPID();
    emit remoteProcessFinished(tr("\n\n'%1' killed.").arg(m_packageName));
}

void AndroidRunner::logcatReadStandardError()
{
    emit remoteErrorOutput(m_adbLogcatProcess.readAllStandardError());
}

void AndroidRunner::logcatReadStandardOutput()
{
    m_logcat += m_adbLogcatProcess.readAllStandardOutput();
    bool keepLastLine = m_logcat.endsWith('\n');
    QByteArray line;
    QByteArray pid(QString::fromLatin1("%1):").arg(m_processPID).toLatin1());
    foreach (line, m_logcat.split('\n')) {
        if (!line.contains(pid))
            continue;
        if (line.endsWith('\r'))
            line.chop(1);
        line.append('\n');
        if (line.startsWith("E/"))
            emit remoteErrorOutput(line);
        else
            emit remoteOutput(line);

    }
    if (keepLastLine)
        m_logcat = line;
}

void AndroidRunner::adbKill(qint64 pid, const QString &device, int timeout, const QString &runAsPackageName)
{
    QProcess process;
    QStringList arguments;

    arguments << QLatin1String("-s") << device;
    arguments << QLatin1String("shell");
    if (runAsPackageName.size())
        arguments << QLatin1String("run-as") << runAsPackageName;
    arguments << QLatin1String("kill") << QLatin1String("-9");
    arguments << QString::number(pid);

    process.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
    if (!process.waitForFinished(timeout))
        process.terminate();
}

QString AndroidRunner::displayName() const
{
    return m_packageName;
}

} // namespace Internal
} // namespace Qt4ProjectManager
<|endoftext|>


<commit_before>// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include <stdio.h>

#include "Arduino.h"

asm(".global _printf_float");
asm(".global _scanf_float");

extern "C" {
    size_t _write(int handle, const unsigned char *buf, size_t bufSize)
    {
        /* Check for the command to flush all handles */
        if (handle == -1) {
            return 0;
        }

        /* Check for stdout and stderr (only necessary if FILE descriptors are enabled.) */
        if (handle != 1 && handle != 2) {
            return -1;
        }

        size_t nChars = 0;
        for (; bufSize > 0; --bufSize, ++buf, ++nChars) {
            Serial.write(*buf);
        }
        return nChars;
    }
}
<commit_msg>Add note about _printf_float and _scanf_float<commit_after>// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include <stdio.h>

#include "Arduino.h"

// these are needed by the serializer, so force link
asm(".global _printf_float");
asm(".global _scanf_float");

extern "C" {
    size_t _write(int handle, const unsigned char *buf, size_t bufSize)
    {
        /* Check for the command to flush all handles */
        if (handle == -1) {
            return 0;
        }

        /* Check for stdout and stderr (only necessary if FILE descriptors are enabled.) */
        if (handle != 1 && handle != 2) {
            return -1;
        }

        size_t nChars = 0;
        for (; bufSize > 0; --bufSize, ++buf, ++nChars) {
            Serial.write(*buf);
        }
        return nChars;
    }
}
<|endoftext|>


<commit_before>/*
This file is part of cphVB and copyright (c) 2012 the cphVB team:
http://cphvb.bitbucket.org

cphVB 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 3
of the License, or (at your option) any later version.

cphVB 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 General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with cphVB.

If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CPHVB_BRIDGE_CPP
#define __CPHVB_BRIDGE_CPP
#include "cphvb.h"

namespace cphvb {

template <typename T>
class Vector {

public:
    cphvb_array* array;

    Vector( Vector const& vector );
    Vector( int d0 );
    Vector( int d0, int d1 );

    // Operators: =, [], (), -> must be nonstatic member functions.
    // These are defined in cphvb_cppb_vector.hpp
    // The remaining are defined externally in *_operators.hpp
    Vector& operator=( const T rhs );
    Vector& operator=( Vector & rhs );

};

}

#include "cphvb_cppb_state.hpp"
#include "cphvb_cppb_traits.hpp"
#include "cphvb_cppb_operators.hpp"
#include "cphvb_cppb_functions.hpp"
#include "cphvb_cppb_vector.hpp"

#endif
<commit_msg>Minor.<commit_after>/*
This file is part of cphVB and copyright (c) 2012 the cphVB team:
http://cphvb.bitbucket.org

cphVB 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 3
of the License, or (at your option) any later version.

cphVB 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 General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with cphVB.

If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CPHVB_BRIDGE_CPP
#define __CPHVB_BRIDGE_CPP
#include "cphvb.h"

namespace cphvb {

template <typename T>
class Vector {

public:
    cphvb_array* array;

    Vector( Vector const& vector );
    Vector( int d0 );
    Vector( int d0, int d1 );

    // Operators:
    //
    // =, [], (), -> must be "internal" (nonstatic member functions),
    // these are defined in cphvb_cppb_vector.hpp
    //
    // The remaining operators are defined "externally" in: cphvb_cppb_operators.hpp
    //
    Vector& operator=( const T rhs );
    Vector& operator=( Vector & rhs );

};

}

#include "cphvb_cppb_state.hpp"         // Communication with cphVB runtime
#include "cphvb_cppb_traits.hpp"        // Traits for assigning constants and arrays.
#include "cphvb_cppb_operators.hpp"     // Vector operations via operator-overloads, auto-generated:
                                        // see ./codegen/* on how.
#include "cphvb_cppb_functions.hpp"     // Vector operations via functions, auto-generated:
                                        // see ./codegen/* on how.
#include "cphvb_cppb_vector.hpp"        // (De)Constructor, "internal" operator overloads.

#endif
<|endoftext|>


<commit_before><commit_msg>- Fixed update code now that the view file is called view.html. No need to rename it anymore when we update a time machine created with an old creator.<commit_after><|endoftext|>


<commit_before>#include "../Interface/Database.h"
#include "../Interface/Server.h"
#include "../Interface/DatabaseCursor.h"
#include "database.h"
#include "server_settings.h"
#include "MDBFileCache.h"
#include "../stringtools.h"

namespace
{

std::wstring get_files_cache_type(void)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
	db_results res=db->Read("SELECT tvalue FROM misc WHERE tkey='files_cache'");

	if(!res.empty())
	{
		return res[0][L"tvalue"];
	}
	return std::wstring();
}

void update_files_cache_type(std::string new_type)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
	IQuery *q=db->Prepare("UPDATE misc SET tvalue=? WHERE tkey='files_cache'");

	q->Bind(new_type);
	q->Write();
}

struct SCallbackData
{
	IDatabaseCursor* cur;
	int64 pos;
};

db_results create_callback(void *userdata)
{
	SCallbackData *data=(SCallbackData*)userdata;

	db_results ret;
	db_single_result res;

	if(data->cur->next(res))
	{
		ret.push_back(res);
	}

	return ret;
}

bool setup_lmdb_files_cache(void)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);

	IQuery *q_read=db->Prepare("SELECT shahash, filesize, fullpath, hashpath, created FROM files f WHERE f.created=(SELECT MAX(created) FROM files WHERE shahash=f.shahash AND filesize=f.filesize) ORDER BY shahash ASC, filesize ASC");

	SCallbackData data;
	data.cur=q_read->Cursor();
	data.pos=0;

	MDBFileCache filecache;
	if(filecache.has_error())
	{
		Server->Log("Error creating file cache", LL_ERROR);
		return false;
	}

	filecache.create(create_callback, &data);

	return true;
}

}

void create_files_cache(void)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
	ServerSettings settings(db);

	if(settings.getSettings()->filescache_type=="lmdb")
	{
		MDBFileCache::initFileCache(static_cast<size_t>(settings.getSettings()->filescache_size));
	}

	if(get_files_cache_type()==L"none" && settings.getSettings()->filescache_type=="lmdb")
	{
		if(setup_lmdb_files_cache())
		{
			update_files_cache_type(settings.getSettings()->filescache_type);
		}
	}

	if(settings.getSettings()->filescache_type=="none")
	{
		if(FileExists("urbackup/backup_server_files_cache.lmdb"))
		{
			Server->deleteFile("urbackup/backup_server_files_cache.lmdb");
			Server->deleteFile("urbackup/backup_server_files_cache.lmdb-lock");
		}

		update_files_cache_type(settings.getSettings()->filescache_type);
	}
}

FileCache* create_lmdb_files_cache(void)
{
	return new MDBFileCache();
}<commit_msg>Increased cache size for creating the files cache<commit_after>#include "../Interface/Database.h"
#include "../Interface/Server.h"
#include "../Interface/DatabaseCursor.h"
#include "database.h"
#include "server_settings.h"
#include "MDBFileCache.h"
#include "../stringtools.h"

namespace
{

std::wstring get_files_cache_type(void)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
	db_results res=db->Read("SELECT tvalue FROM misc WHERE tkey='files_cache'");

	if(!res.empty())
	{
		return res[0][L"tvalue"];
	}
	return std::wstring();
}

void update_files_cache_type(std::string new_type)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
	IQuery *q=db->Prepare("UPDATE misc SET tvalue=? WHERE tkey='files_cache'");

	q->Bind(new_type);
	q->Write();
}

struct SCallbackData
{
	IDatabaseCursor* cur;
	int64 pos;
};

db_results create_callback(void *userdata)
{
	SCallbackData *data=(SCallbackData*)userdata;

	db_results ret;
	db_single_result res;

	if(data->cur->next(res))
	{
		ret.push_back(res);
	}

	return ret;
}

bool setup_lmdb_files_cache(void)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);

	db_results cache_res;
	if(db->getEngineName()=="sqlite")
	{
		cache_res=db->Read("PRAGMA cache_size");
		db->Write("PRAGMA cache_size = -"+nconvert(500*1024));
	}

	Server->Log("Creating LMDB file entry cache. This might take a while...", LL_WARNING);

	IQuery *q_read=db->Prepare("SELECT shahash, filesize, fullpath, hashpath, created FROM files f WHERE f.created=(SELECT MAX(created) FROM files WHERE shahash=f.shahash AND filesize=f.filesize) ORDER BY shahash ASC, filesize ASC");

	SCallbackData data;
	data.cur=q_read->Cursor();
	data.pos=0;

	MDBFileCache filecache;
	if(filecache.has_error())
	{
		Server->Log("Error creating file cache", LL_ERROR);
		return false;
	}

	filecache.create(create_callback, &data);

	if(!cache_res.empty())
	{
		db->Write("PRAGMA cache_size = "+wnarrow(cache_res[0][L"cache_size"]));
		db->Write("PRAGMA shrink_memory");
	}

	return true;
}

}

void create_files_cache(void)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
	ServerSettings settings(db);

	if(settings.getSettings()->filescache_type=="lmdb")
	{
		MDBFileCache::initFileCache(static_cast<size_t>(settings.getSettings()->filescache_size));
	}

	if(get_files_cache_type()==L"none" && settings.getSettings()->filescache_type=="lmdb")
	{
		if(setup_lmdb_files_cache())
		{
			update_files_cache_type(settings.getSettings()->filescache_type);
		}
	}

	if(settings.getSettings()->filescache_type=="none")
	{
		if(FileExists("urbackup/backup_server_files_cache.lmdb"))
		{
			Server->deleteFile("urbackup/backup_server_files_cache.lmdb");
			Server->deleteFile("urbackup/backup_server_files_cache.lmdb-lock");
		}

		update_files_cache_type(settings.getSettings()->filescache_type);
	}
}

FileCache* create_lmdb_files_cache(void)
{
	return new MDBFileCache();
}<|endoftext|>


<commit_before>/* Copyright (c) 2012-2013, AOYAMA Kazuharu
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include <TBson>
#include <QDateTime>
#include <QRegExp>
#include <QStringList>
#include "mongo.h"

/*!
  \class TBson
  \brief The TBson class represents a Binary JSON for MongoDB.
*/

TBson::TBson()
    : bsonData(new bson)
{
    bson_init((bson *)bsonData);
}

TBson::~TBson()
{
    bson_destroy((bson *)bsonData);
    delete (bson *)bsonData;
}

QVariantMap TBson::fromBson(const TBson &bs)
{
    return TBson::fromBson(bs.constData());
}

QVariantMap TBson::fromBson(const TBsonObject *obj)
{
    QVariantMap ret;
    bson_iterator it[1];

    bson_iterator_init(it, (const bson *)obj);
    while (bson_iterator_more(it)) {
        bson_type t = bson_iterator_next(it);
        QString key(bson_iterator_key(it));

        switch (t) {
        case BSON_EOO:
            return ret;
            break;

        case BSON_DOUBLE:
            ret[key] = bson_iterator_double(it);
            break;

        case BSON_STRING:
            ret[key] = QString(bson_iterator_string(it));
            break;

        case BSON_ARRAY:  // FALL THROUGH
        case BSON_OBJECT: {
            bson sub[1];
            bson_iterator_subobject_init(it, sub, (bson_bool_t)true);
            ret[key] = fromBson(sub);
            break; }

        case BSON_BINDATA: {
            int len = bson_iterator_bin_len(it);
            ret[key] = QByteArray(bson_iterator_bin_data(it), len);
            break; }

        case BSON_UNDEFINED:
            ret[key] = QVariant();
            break;

        case BSON_OID: {
            char oidhex[25];
            bson_oid_to_string(bson_iterator_oid(it), oidhex);
            ret[key] = QString(oidhex);
            break; }

        case BSON_BOOL:
            ret[key] = (bool)bson_iterator_bool(it);
            break;

        case BSON_DATE: {
            QDateTime date;
            date.setMSecsSinceEpoch(bson_iterator_date(it));
            ret[key] = date;
            break; }

        case BSON_NULL:
            ret[key] = QVariant();
            break;

        case BSON_REGEX:
            ret[key] = QRegExp(QLatin1String(bson_iterator_regex(it)));
            break;

        case BSON_DBREF: // Deprecated
            break;

        case BSON_CODE:
            ret[key] = QString(bson_iterator_code(it));
            break;

        case BSON_SYMBOL:
            ret[key] = QString(bson_iterator_string(it));
            break;

        case BSON_INT:
            ret[key] = bson_iterator_int(it);
            break;
        case BSON_LONG:
            ret[key] = (qint64)bson_iterator_long(it);
            break;

        case BSON_CODEWSCOPE: // FALL THROUGH
        case BSON_TIMESTAMP:  // FALL THROUGH (internal use)
            // do nothing
            break;

        default:
            tError("fromBson() unknown type: %d", t);
            break;
        }
    }
    return ret;
}

static bool appendBsonValue(bson *b, const QString &key, const QVariant &value)
{
    const QLatin1String oidkey("_id");
    bool ok = true;
    int type = value.type();

    switch (type) {
    case QVariant::Int:
        bson_append_int(b, qPrintable(key), value.toInt(&ok));
        break;

    case QVariant::String:
        if (key == oidkey) {
            // OID
            bson_oid_t oid;
            bson_oid_from_string(&oid, qPrintable(value.toString()));
            bson_append_oid(b, oidkey.latin1(), &oid);
        } else {
            bson_append_string(b, qPrintable(key), qPrintable(value.toString()));
        }
        break;

    case QVariant::LongLong:
        bson_append_long(b, qPrintable(key), value.toLongLong(&ok));
        break;

    case QVariant::Map:
        bson_append_bson(b, qPrintable(key), (const bson *)TBson::toBson(value.toMap()).constData());
        break;

    case QVariant::Double:
        bson_append_double(b, qPrintable(key), value.toDouble(&ok));
        break;

    case QVariant::Bool:
        bson_append_bool(b, qPrintable(key), value.toBool());
        break;

    case QVariant::DateTime:
        bson_append_date(b, qPrintable(key), value.toDateTime().toMSecsSinceEpoch());
        break;

    case QVariant::ByteArray: {
        QByteArray ba = value.toByteArray();
        bson_append_binary(b, qPrintable(key), BSON_BIN_BINARY, ba.constData(), ba.length());
        break; }

    case QVariant::List: {
        bson_append_start_array(b, qPrintable(key));
        QVariantList lst = value.toList();

        for (QListIterator<QVariant> it(lst); it.hasNext(); ) {
            const QVariant &var = it.next();
            appendBsonValue(b, qPrintable(key), var);
        }

        bson_append_finish_array(b);
        break; }

    case QVariant::Invalid:
        bson_append_undefined(b,  qPrintable(key));
        break;

    default:
        tError("toBson() failed to convert  name:%s  type:%d", qPrintable(key), type);
        ok = false;
        break;
    }
    return ok;
}

TBson TBson::toBson(const QVariantMap &map)
{
    TBson ret;

    for (QMapIterator<QString, QVariant> it(map); it.hasNext(); ) {
        const QVariant &val = it.next().value();

        bool res = appendBsonValue((bson *)ret.data(), qPrintable(it.key()), val);
        if (!res)
            break;
    }

    bson_finish((bson *)ret.data());
    return ret;
}

TBson TBson::toBson(const QStringList &lst)
{
    TBson ret;

    for (QStringListIterator it(lst); it.hasNext(); ) {
        const QString &str = it.next();

        bool res = appendBsonValue((bson *)ret.data(), qPrintable(str), 1);
        if (!res)
            break;
    }

    bson_finish((bson *)ret.data());
    return ret;
}
<commit_msg>fix compile error on Qt4.6<commit_after>/* Copyright (c) 2012-2013, AOYAMA Kazuharu
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include <TBson>
#include <QDateTime>
#include <QRegExp>
#include <QStringList>
#include "mongo.h"

/*!
  \class TBson
  \brief The TBson class represents a Binary JSON for MongoDB.
*/

TBson::TBson()
    : bsonData(new bson)
{
    bson_init((bson *)bsonData);
}

TBson::~TBson()
{
    bson_destroy((bson *)bsonData);
    delete (bson *)bsonData;
}

QVariantMap TBson::fromBson(const TBson &bs)
{
    return TBson::fromBson(bs.constData());
}

QVariantMap TBson::fromBson(const TBsonObject *obj)
{
    QVariantMap ret;
    bson_iterator it[1];

    bson_iterator_init(it, (const bson *)obj);
    while (bson_iterator_more(it)) {
        bson_type t = bson_iterator_next(it);
        QString key(bson_iterator_key(it));

        switch (t) {
        case BSON_EOO:
            return ret;
            break;

        case BSON_DOUBLE:
            ret[key] = bson_iterator_double(it);
            break;

        case BSON_STRING:
            ret[key] = QString(bson_iterator_string(it));
            break;

        case BSON_ARRAY:  // FALL THROUGH
        case BSON_OBJECT: {
            bson sub[1];
            bson_iterator_subobject_init(it, sub, (bson_bool_t)true);
            ret[key] = fromBson(sub);
            break; }

        case BSON_BINDATA: {
            int len = bson_iterator_bin_len(it);
            ret[key] = QByteArray(bson_iterator_bin_data(it), len);
            break; }

        case BSON_UNDEFINED:
            ret[key] = QVariant();
            break;

        case BSON_OID: {
            char oidhex[25];
            bson_oid_to_string(bson_iterator_oid(it), oidhex);
            ret[key] = QString(oidhex);
            break; }

        case BSON_BOOL:
            ret[key] = (bool)bson_iterator_bool(it);
            break;

        case BSON_DATE: {
#if QT_VERSION >= 0x040700
            QDateTime date;
            date.setMSecsSinceEpoch(bson_iterator_date(it));
#else
            qint64 val = bson_iterator_date(it);
            qint64 days = val / 86400000;  // 24*60*60*1000
            int msecs = val % 86400000;
            QDate dt = QDate(1970, 1, 1).addDays(days);
            QTime tm = QTime(0, 0, 0).addMSecs(msecs);
            QDateTime date(dt, tm, Qt::UTC);
#endif
            ret[key] = date;
            break; }

        case BSON_NULL:
            ret[key] = QVariant();
            break;

        case BSON_REGEX:
            ret[key] = QRegExp(QLatin1String(bson_iterator_regex(it)));
            break;

        case BSON_DBREF: // Deprecated
            break;

        case BSON_CODE:
            ret[key] = QString(bson_iterator_code(it));
            break;

        case BSON_SYMBOL:
            ret[key] = QString(bson_iterator_string(it));
            break;

        case BSON_INT:
            ret[key] = bson_iterator_int(it);
            break;
        case BSON_LONG:
            ret[key] = (qint64)bson_iterator_long(it);
            break;

        case BSON_CODEWSCOPE: // FALL THROUGH
        case BSON_TIMESTAMP:  // FALL THROUGH (internal use)
            // do nothing
            break;

        default:
            tError("fromBson() unknown type: %d", t);
            break;
        }
    }
    return ret;
}

static bool appendBsonValue(bson *b, const QString &key, const QVariant &value)
{
    const QLatin1String oidkey("_id");
    bool ok = true;
    int type = value.type();

    switch (type) {
    case QVariant::Int:
        bson_append_int(b, qPrintable(key), value.toInt(&ok));
        break;

    case QVariant::String:
        if (key == oidkey) {
            // OID
            bson_oid_t oid;
            bson_oid_from_string(&oid, qPrintable(value.toString()));
            bson_append_oid(b, oidkey.latin1(), &oid);
        } else {
            bson_append_string(b, qPrintable(key), qPrintable(value.toString()));
        }
        break;

    case QVariant::LongLong:
        bson_append_long(b, qPrintable(key), value.toLongLong(&ok));
        break;

    case QVariant::Map:
        bson_append_bson(b, qPrintable(key), (const bson *)TBson::toBson(value.toMap()).constData());
        break;

    case QVariant::Double:
        bson_append_double(b, qPrintable(key), value.toDouble(&ok));
        break;

    case QVariant::Bool:
        bson_append_bool(b, qPrintable(key), value.toBool());
        break;

    case QVariant::DateTime: {
#if QT_VERSION >= 0x040700
        bson_append_date(b, qPrintable(key), value.toDateTime().toMSecsSinceEpoch());
#else
        QDateTime utcDate = value.toDateTime().toUTC();
        qint64 ms = utcDate.time().msec();
        qint64 tm = utcDate.toTime_t() * 1000LL;
        if (ms > 0) {
          tm += ms;
        }
        bson_append_date(b, qPrintable(key), tm);
#endif
        break; }

    case QVariant::ByteArray: {
        QByteArray ba = value.toByteArray();
        bson_append_binary(b, qPrintable(key), BSON_BIN_BINARY, ba.constData(), ba.length());
        break; }

    case QVariant::List: {
        bson_append_start_array(b, qPrintable(key));
        QVariantList lst = value.toList();

        for (QListIterator<QVariant> it(lst); it.hasNext(); ) {
            const QVariant &var = it.next();
            appendBsonValue(b, qPrintable(key), var);
        }

        bson_append_finish_array(b);
        break; }

    case QVariant::Invalid:
        bson_append_undefined(b,  qPrintable(key));
        break;

    default:
        tError("toBson() failed to convert  name:%s  type:%d", qPrintable(key), type);
        ok = false;
        break;
    }
    return ok;
}

TBson TBson::toBson(const QVariantMap &map)
{
    TBson ret;

    for (QMapIterator<QString, QVariant> it(map); it.hasNext(); ) {
        const QVariant &val = it.next().value();

        bool res = appendBsonValue((bson *)ret.data(), qPrintable(it.key()), val);
        if (!res)
            break;
    }

    bson_finish((bson *)ret.data());
    return ret;
}

TBson TBson::toBson(const QStringList &lst)
{
    TBson ret;

    for (QStringListIterator it(lst); it.hasNext(); ) {
        const QString &str = it.next();

        bool res = appendBsonValue((bson *)ret.data(), qPrintable(str), 1);
        if (!res)
            break;
    }

    bson_finish((bson *)ret.data());
    return ret;
}
<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.

#include "src/thread.h"

#include <pthread.h>
#include <sys/mman.h>
#include <algorithm>
#include <cerrno>
#include <list>

#include "src/runtime.h"
#include "src/utils.h"

namespace art {

pthread_key_t Thread::pthread_key_self_;

Mutex* Mutex::Create(const char* name) {
  Mutex* mu = new Mutex(name);
  int result = pthread_mutex_init(&mu->lock_impl_, NULL);
  CHECK_EQ(0, result);
  return mu;
}

void Mutex::Lock() {
  int result = pthread_mutex_lock(&lock_impl_);
  CHECK_EQ(result, 0);
  SetOwner(Thread::Current());
}

bool Mutex::TryLock() {
  int result = pthread_mutex_lock(&lock_impl_);
  if (result == EBUSY) {
    return false;
  } else {
    CHECK_EQ(result, 0);
    SetOwner(Thread::Current());
    return true;
  }
}

void Mutex::Unlock() {
  CHECK(GetOwner() == Thread::Current());
  int result = pthread_mutex_unlock(&lock_impl_);
  CHECK_EQ(result, 0);
  SetOwner(Thread::Current());
}

void* ThreadStart(void *arg) {
  LOG(FATAL) << "Unimplemented";
  return NULL;
}

Thread* Thread::Create(size_t stack_size) {
  int prot = PROT_READ | PROT_WRITE;
  // TODO: require the stack size to be page aligned?
  size_t length = RoundUp(stack_size, 0x1000);
  void* stack_limit = mmap(NULL, length, prot, MAP_PRIVATE, -1, 0);
  if (stack_limit == MAP_FAILED) {
    LOG(FATAL) << "mmap";
    return false;
  }

  Thread* new_thread = new Thread;
  new_thread->stack_limit_ = static_cast<byte*>(stack_limit);
  new_thread->stack_base_ = new_thread->stack_limit_ + length;

  pthread_attr_t attr;
  int result = pthread_attr_init(&attr);
  CHECK_EQ(result, 0);

  result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  CHECK_EQ(result, 0);

  pthread_t handle;
  result = pthread_create(&handle, &attr, ThreadStart, new_thread);
  CHECK_EQ(result, 0);

  result = pthread_attr_destroy(&attr);
  CHECK_EQ(result, 0);

  InitCpu();

  return new_thread;
}

Thread* Thread::Attach() {
  Thread* thread = new Thread;

  thread->stack_limit_ = reinterpret_cast<byte*>(-1);  // TODO: getrlimit
  uintptr_t addr = reinterpret_cast<uintptr_t>(&thread);  // TODO: ask pthreads
  uintptr_t stack_base = RoundUp(addr, 4096);
  thread->stack_base_ = reinterpret_cast<byte*>(stack_base);
  // TODO: set the stack size

  thread->handle_ = pthread_self();

  thread->state_ = kRunnable;

  errno = pthread_setspecific(Thread::pthread_key_self_, thread);
  if (errno != 0) {
      PLOG(FATAL) << "pthread_setspecific failed";
  }

  InitCpu();

  return thread;
}

static void ThreadExitCheck(void* arg) {
  LG << "Thread exit check";
}

bool Thread::Init() {
  // Allocate a TLS slot.
  if (pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck) != 0) {
    PLOG(WARNING) << "pthread_key_create failed";
    return false;
  }

  // Double-check the TLS slot allocation.
  if (pthread_getspecific(pthread_key_self_) != NULL) {
    LOG(WARNING) << "newly-created pthread TLS slot is not NULL";
    return false;
  }

  // TODO: initialize other locks and condition variables

  return true;
}

static const char* kStateNames[] = {
  "New",
  "Runnable",
  "Blocked",
  "Waiting",
  "TimedWaiting",
  "Native",
  "Terminated",
};
std::ostream& operator<<(std::ostream& os, const Thread::State& state) {
  if (state >= Thread::kNew && state <= Thread::kTerminated) {
    os << kStateNames[state-Thread::kNew];
  } else {
    os << "State[" << static_cast<int>(state) << "]";
  }
  return os;
}

ThreadList* ThreadList::Create() {
  return new ThreadList;
}

ThreadList::ThreadList() {
  lock_ = Mutex::Create("ThreadList::Lock");
}

ThreadList::~ThreadList() {
  // Make sure that all threads have exited and unregistered when we
  // reach this point. This means that all daemon threads had been
  // shutdown cleanly.
  CHECK_EQ(list_.size(), 0U);
  delete lock_;
  lock_ = NULL;
}

void ThreadList::Register(Thread* thread) {
  MutexLock mu(lock_);
  CHECK(find(list_.begin(), list_.end(), thread) == list_.end());
  list_.push_front(thread);
}

void ThreadList::Unregister(Thread* thread) {
  MutexLock mu(lock_);
  CHECK(find(list_.begin(), list_.end(), thread) != list_.end());
  list_.remove(thread);
}

}  // namespace
<commit_msg>Fix build breakage.<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.

#include "src/thread.h"

#include <pthread.h>
#include <sys/mman.h>
#include <algorithm>
#include <cerrno>
#include <list>

#include "src/runtime.h"
#include "src/utils.h"

namespace art {

pthread_key_t Thread::pthread_key_self_;

Mutex* Mutex::Create(const char* name) {
  Mutex* mu = new Mutex(name);
  int result = pthread_mutex_init(&mu->lock_impl_, NULL);
  CHECK_EQ(0, result);
  return mu;
}

void Mutex::Lock() {
  int result = pthread_mutex_lock(&lock_impl_);
  CHECK_EQ(result, 0);
  SetOwner(Thread::Current());
}

bool Mutex::TryLock() {
  int result = pthread_mutex_lock(&lock_impl_);
  if (result == EBUSY) {
    return false;
  } else {
    CHECK_EQ(result, 0);
    SetOwner(Thread::Current());
    return true;
  }
}

void Mutex::Unlock() {
  CHECK(GetOwner() == Thread::Current());
  int result = pthread_mutex_unlock(&lock_impl_);
  CHECK_EQ(result, 0);
  SetOwner(Thread::Current());
}

void* ThreadStart(void *arg) {
  LOG(FATAL) << "Unimplemented";
  return NULL;
}

Thread* Thread::Create(size_t stack_size) {
  int prot = PROT_READ | PROT_WRITE;
  // TODO: require the stack size to be page aligned?
  size_t length = RoundUp(stack_size, 0x1000);
  void* stack_limit = mmap(NULL, length, prot, MAP_PRIVATE, -1, 0);
  if (stack_limit == MAP_FAILED) {
    LOG(FATAL) << "mmap";
    return false;
  }

  Thread* new_thread = new Thread;
  new_thread->InitCpu();
  new_thread->stack_limit_ = static_cast<byte*>(stack_limit);
  new_thread->stack_base_ = new_thread->stack_limit_ + length;

  pthread_attr_t attr;
  int result = pthread_attr_init(&attr);
  CHECK_EQ(result, 0);

  result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  CHECK_EQ(result, 0);

  pthread_t handle;
  result = pthread_create(&handle, &attr, ThreadStart, new_thread);
  CHECK_EQ(result, 0);

  result = pthread_attr_destroy(&attr);
  CHECK_EQ(result, 0);

  return new_thread;
}

Thread* Thread::Attach() {
  Thread* thread = new Thread;
  thread->InitCpu();
  thread->stack_limit_ = reinterpret_cast<byte*>(-1);  // TODO: getrlimit
  uintptr_t addr = reinterpret_cast<uintptr_t>(&thread);  // TODO: ask pthreads
  uintptr_t stack_base = RoundUp(addr, 4096);
  thread->stack_base_ = reinterpret_cast<byte*>(stack_base);
  // TODO: set the stack size

  thread->handle_ = pthread_self();

  thread->state_ = kRunnable;

  errno = pthread_setspecific(Thread::pthread_key_self_, thread);
  if (errno != 0) {
      PLOG(FATAL) << "pthread_setspecific failed";
  }

  return thread;
}

static void ThreadExitCheck(void* arg) {
  LG << "Thread exit check";
}

bool Thread::Init() {
  // Allocate a TLS slot.
  if (pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck) != 0) {
    PLOG(WARNING) << "pthread_key_create failed";
    return false;
  }

  // Double-check the TLS slot allocation.
  if (pthread_getspecific(pthread_key_self_) != NULL) {
    LOG(WARNING) << "newly-created pthread TLS slot is not NULL";
    return false;
  }

  // TODO: initialize other locks and condition variables

  return true;
}

static const char* kStateNames[] = {
  "New",
  "Runnable",
  "Blocked",
  "Waiting",
  "TimedWaiting",
  "Native",
  "Terminated",
};
std::ostream& operator<<(std::ostream& os, const Thread::State& state) {
  if (state >= Thread::kNew && state <= Thread::kTerminated) {
    os << kStateNames[state-Thread::kNew];
  } else {
    os << "State[" << static_cast<int>(state) << "]";
  }
  return os;
}

ThreadList* ThreadList::Create() {
  return new ThreadList;
}

ThreadList::ThreadList() {
  lock_ = Mutex::Create("ThreadList::Lock");
}

ThreadList::~ThreadList() {
  // Make sure that all threads have exited and unregistered when we
  // reach this point. This means that all daemon threads had been
  // shutdown cleanly.
  CHECK_EQ(list_.size(), 0U);
  delete lock_;
  lock_ = NULL;
}

void ThreadList::Register(Thread* thread) {
  MutexLock mu(lock_);
  CHECK(find(list_.begin(), list_.end(), thread) == list_.end());
  list_.push_front(thread);
}

void ThreadList::Unregister(Thread* thread) {
  MutexLock mu(lock_);
  CHECK(find(list_.begin(), list_.end(), thread) != list_.end());
  list_.remove(thread);
}

}  // namespace
<|endoftext|>


<commit_before>//stuff<commit_msg>Delete trash.cpp<commit_after><|endoftext|>