<commit_before>//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// IndexDataManagerPerfTest:
//   Performance test for index buffer management.
//

#include "ANGLEPerfTest.h"

#include <gmock/gmock.h>

#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/IndexBuffer.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"

using namespace testing;

namespace
{

class MockIndexBuffer : public rx::IndexBuffer
{
  public:
    MockIndexBuffer(unsigned int bufferSize, GLenum indexType)
        : mBufferSize(bufferSize),
          mIndexType(indexType)
    {
    }

    MOCK_METHOD3(initialize, gl::Error(unsigned int, GLenum, bool));
    MOCK_METHOD3(mapBuffer, gl::Error(unsigned int, unsigned int, void**));
    MOCK_METHOD0(unmapBuffer, gl::Error());
    MOCK_METHOD0(discard, gl::Error());
    MOCK_METHOD2(setSize, gl::Error(unsigned int, GLenum));

    // inlined for speed
    GLenum getIndexType() const override { return mIndexType; }
    unsigned int getBufferSize() const override { return mBufferSize; }

  private:
    unsigned int mBufferSize;
    GLenum mIndexType;
};

class MockBufferFactoryD3D : public rx::BufferFactoryD3D
{
  public:
    MockBufferFactoryD3D(unsigned int bufferSize, GLenum indexType)
        : mBufferSize(bufferSize),
          mIndexType(indexType)
    {
    }

    MOCK_METHOD0(createVertexBuffer, rx::VertexBuffer*());
    MOCK_CONST_METHOD1(getVertexConversionType, rx::VertexConversionType(const gl::VertexFormat &));
    MOCK_CONST_METHOD1(getVertexComponentType, GLenum(const gl::VertexFormat &));

    // Dependency injection
    rx::IndexBuffer* createIndexBuffer() override
    {
        return new MockIndexBuffer(mBufferSize, mIndexType);
    }

  private:
    unsigned int mBufferSize;
    GLenum mIndexType;
};

class MockBufferD3D : public rx::BufferD3D
{
  public:
    MockBufferD3D(rx::BufferFactoryD3D *factory, size_t bufferSize)
        : BufferD3D(factory),
          mBufferSize(bufferSize)
    {
    }

    // BufferImpl
    MOCK_METHOD3(setData, gl::Error(const void*, size_t, GLenum));
    MOCK_METHOD3(setSubData, gl::Error(const void*, size_t, size_t));
    MOCK_METHOD4(copySubData, gl::Error(BufferImpl*, GLintptr, GLintptr, GLsizeiptr));
    MOCK_METHOD2(map, gl::Error(GLenum, GLvoid **));
    MOCK_METHOD4(mapRange, gl::Error(size_t, size_t, GLbitfield, GLvoid **));
    MOCK_METHOD1(unmap, gl::Error(GLboolean *));

    // BufferD3D
    MOCK_METHOD0(markTransformFeedbackUsage, void());

    // inlined for speed
    bool supportsDirectBinding() const override { return false; }
    size_t getSize() const override { return mBufferSize; }
    gl::Error getData(const uint8_t **) override { return gl::Error(GL_NO_ERROR); }

  private:
    size_t mBufferSize;
};

class IndexDataManagerPerfTest : public ANGLEPerfTest
{
  public:
    IndexDataManagerPerfTest();

    void step(float dt, double totalTime) override;

    rx::IndexDataManager mIndexDataManager;
    GLsizei mIndexCount;
    unsigned int mBufferSize;
    MockBufferFactoryD3D mMockFactory;
    gl::Buffer mIndexBuffer;
    std::vector<GLshort> mIndexData;
};

MockBufferD3D *InitMockBufferD3D(MockBufferFactoryD3D *mockFactory, unsigned int bufferSize)
{
    MockBufferD3D *mockBufferD3D = new MockBufferD3D(mockFactory, static_cast<size_t>(bufferSize));

    EXPECT_CALL(*mockFactory, createVertexBuffer()).WillOnce(Return(nullptr)).RetiresOnSaturation();
    mockBufferD3D->initializeStaticData();

    return mockBufferD3D;
}

IndexDataManagerPerfTest::IndexDataManagerPerfTest()
    : ANGLEPerfTest("IndexDataManger", "_run"),
      mIndexDataManager(&mMockFactory, rx::RENDERER_D3D11),
      mIndexCount(4000),
      mBufferSize(mIndexCount * 2),
      mMockFactory(mBufferSize, GL_UNSIGNED_SHORT),
      mIndexBuffer(InitMockBufferD3D(&mMockFactory, mBufferSize), 1),
      mIndexData(mIndexCount)
{
    for (GLsizei index = 0; index < mIndexCount; ++index)
    {
        mIndexData[index] = static_cast<GLshort>(index);
    }
}

void IndexDataManagerPerfTest::step(float dt, double totalTime)
{
    rx::TranslatedIndexData translatedIndexData;

    for (unsigned int iteration = 0; iteration < 100; ++iteration)
    {
        mIndexBuffer.getIndexRange(GL_UNSIGNED_SHORT, 0, mIndexCount, &translatedIndexData.indexRange);
        mIndexDataManager.prepareIndexData(GL_UNSIGNED_SHORT, mIndexCount, &mIndexBuffer, nullptr, &translatedIndexData);
    }

    if (mTimer->getElapsedTime() >= 5.0)
    {
        mRunning = false;
    }
}

TEST_F(IndexDataManagerPerfTest, Run)
{
    run();
}

}
<commit_msg>Fix crash in IndexDataManagerPerfTest.<commit_after>//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// IndexDataManagerPerfTest:
//   Performance test for index buffer management.
//

#include "ANGLEPerfTest.h"

#include <gmock/gmock.h>

#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/IndexBuffer.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"

using namespace testing;

namespace
{

class MockIndexBuffer : public rx::IndexBuffer
{
  public:
    MockIndexBuffer(unsigned int bufferSize, GLenum indexType)
        : mBufferSize(bufferSize),
          mIndexType(indexType)
    {
    }

    MOCK_METHOD3(initialize, gl::Error(unsigned int, GLenum, bool));
    MOCK_METHOD3(mapBuffer, gl::Error(unsigned int, unsigned int, void**));
    MOCK_METHOD0(unmapBuffer, gl::Error());
    MOCK_METHOD0(discard, gl::Error());
    MOCK_METHOD2(setSize, gl::Error(unsigned int, GLenum));

    // inlined for speed
    GLenum getIndexType() const override { return mIndexType; }
    unsigned int getBufferSize() const override { return mBufferSize; }

  private:
    unsigned int mBufferSize;
    GLenum mIndexType;
};

class MockBufferFactoryD3D : public rx::BufferFactoryD3D
{
  public:
    MockBufferFactoryD3D(unsigned int bufferSize, GLenum indexType)
        : mBufferSize(bufferSize),
          mIndexType(indexType)
    {
    }

    MOCK_METHOD0(createVertexBuffer, rx::VertexBuffer*());
    MOCK_CONST_METHOD1(getVertexConversionType, rx::VertexConversionType(const gl::VertexFormat &));
    MOCK_CONST_METHOD1(getVertexComponentType, GLenum(const gl::VertexFormat &));

    // Dependency injection
    rx::IndexBuffer* createIndexBuffer() override
    {
        return new MockIndexBuffer(mBufferSize, mIndexType);
    }

  private:
    unsigned int mBufferSize;
    GLenum mIndexType;
};

class MockBufferD3D : public rx::BufferD3D
{
  public:
    MockBufferD3D(rx::BufferFactoryD3D *factory)
        : BufferD3D(factory),
          mData()
    {
    }

    // BufferImpl
    gl::Error setData(const void *data, size_t size, GLenum) override
    {
        mData.resize(size);
        if (data && size > 0)
        {
            memcpy(&mData[0], data, size);
        }
        return gl::Error(GL_NO_ERROR);
    }

    MOCK_METHOD3(setSubData, gl::Error(const void*, size_t, size_t));
    MOCK_METHOD4(copySubData, gl::Error(BufferImpl*, GLintptr, GLintptr, GLsizeiptr));
    MOCK_METHOD2(map, gl::Error(GLenum, GLvoid **));
    MOCK_METHOD4(mapRange, gl::Error(size_t, size_t, GLbitfield, GLvoid **));
    MOCK_METHOD1(unmap, gl::Error(GLboolean *));

    // BufferD3D
    MOCK_METHOD0(markTransformFeedbackUsage, void());

    // inlined for speed
    bool supportsDirectBinding() const override { return false; }
    size_t getSize() const override { return mData.size(); }

    gl::Error getData(const uint8_t **outData) override
    {
        *outData = &mData[0];
        return gl::Error(GL_NO_ERROR);
    }

  private:
    std::vector<uint8_t> mData;
};

class IndexDataManagerPerfTest : public ANGLEPerfTest
{
  public:
    IndexDataManagerPerfTest();

    void step(float dt, double totalTime) override;

    rx::IndexDataManager mIndexDataManager;
    GLsizei mIndexCount;
    unsigned int mBufferSize;
    MockBufferFactoryD3D mMockFactory;
    gl::Buffer mIndexBuffer;
};

MockBufferD3D *InitMockBufferD3D(MockBufferFactoryD3D *mockFactory)
{
    MockBufferD3D *mockBufferD3D = new MockBufferD3D(mockFactory);

    EXPECT_CALL(*mockFactory, createVertexBuffer()).WillOnce(Return(nullptr)).RetiresOnSaturation();
    mockBufferD3D->initializeStaticData();

    return mockBufferD3D;
}

IndexDataManagerPerfTest::IndexDataManagerPerfTest()
    : ANGLEPerfTest("IndexDataManger", "_run"),
      mIndexDataManager(&mMockFactory, rx::RENDERER_D3D11),
      mIndexCount(4000),
      mBufferSize(mIndexCount * sizeof(GLushort)),
      mMockFactory(mBufferSize, GL_UNSIGNED_SHORT),
      mIndexBuffer(InitMockBufferD3D(&mMockFactory), 1)
{
    std::vector<GLushort> indexData(mIndexCount);
    for (GLsizei index = 0; index < mIndexCount; ++index)
    {
        indexData[index] = static_cast<GLushort>(index);
    }
    mIndexBuffer.bufferData(&indexData[0], indexData.size() * sizeof(GLushort), GL_STATIC_DRAW);
}

void IndexDataManagerPerfTest::step(float dt, double totalTime)
{
    rx::TranslatedIndexData translatedIndexData;
    for (unsigned int iteration = 0; iteration < 100; ++iteration)
    {
        mIndexBuffer.getIndexRange(GL_UNSIGNED_SHORT, 0, mIndexCount, &translatedIndexData.indexRange);
        mIndexDataManager.prepareIndexData(GL_UNSIGNED_SHORT, mIndexCount, &mIndexBuffer, nullptr, &translatedIndexData);
    }

    if (mTimer->getElapsedTime() >= 5.0)
    {
        mRunning = false;
    }
}

TEST_F(IndexDataManagerPerfTest, Run)
{
    run();
}

}
<|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: wkb.cpp 19 2005-03-22 13:53:27Z pavlenko $

#include <mapnik/wkb.hpp>

#include <mapnik/geom_util.hpp>
#include <mapnik/feature.hpp>

namespace mapnik
{
   struct wkb_reader
   {
      private:
         enum wkbByteOrder {
            wkbXDR=0,
            wkbNDR=1
         };
         const char* wkb_;
         unsigned size_;
         unsigned pos_;
         wkbByteOrder byteOrder_;
         bool needSwap_;
      public:

         enum wkbGeometryType {
            wkbPoint=1,
            wkbLineString=2,
            wkbPolygon=3,
            wkbMultiPoint=4,
            wkbMultiLineString=5,
            wkbMultiPolygon=6,
            wkbGeometryCollection=7
         };

         wkb_reader(const char* wkb,unsigned size)
            : wkb_(wkb),
              size_(size),
              pos_(0),
              byteOrder_((wkbByteOrder)wkb_[0])
         {
            ++pos_;

#ifndef WORDS_BIGENDIAN
            needSwap_=byteOrder_?wkbXDR:wkbNDR;
#else
            needSwap_=byteOrder_?wkbNDR:wkbXDR;
#endif
         }

         ~wkb_reader() {}

         void read_multi(Feature & feature)
         {
            int type=read_integer();
            switch (type)
            {
               case wkbPoint:
                  read_point(feature);
                  break;
               case wkbLineString:
                  read_linestring(feature);
                  break;
               case wkbPolygon:
                  read_polygon(feature);
                  break;
               case wkbMultiPoint:
                  read_multipoint(feature);
                  break;
               case wkbMultiLineString:
                  read_multilinestring(feature);
                  break;
               case wkbMultiPolygon:
                  read_multipolygon(feature);
                  break;
               case wkbGeometryCollection:
                  break;
               default:
                  break;
            }
         }

         void read(Feature & feature)
         {
            int type=read_integer();
            switch (type)
            {
               case wkbPoint:
                  read_point(feature);
                  break;
               case wkbLineString:
                  read_linestring(feature);
                  break;
               case wkbPolygon:
                  read_polygon(feature);
                  break;
               case wkbMultiPoint:
                  read_multipoint_2(feature);
                  break;
               case wkbMultiLineString:
                  read_multilinestring_2(feature);
                  break;
               case wkbMultiPolygon:
                  read_multipolygon_2(feature);
                  break;
               case wkbGeometryCollection:
                  break;
               default:
                  break;
            }
         }

      private:
         wkb_reader(const wkb_reader&);
         wkb_reader& operator=(const wkb_reader&);

         int read_integer()
         {
            int n;

            if (!needSwap_)
            {
               memcpy(&n,wkb_+pos_,4);
            }
            else
            {
               const char* b=wkb_+pos_;
               n = (b[3]&0xff) | ((b[2]&0xff)<<8) | ((b[1]&0xff)<<16) | ((b[0]&0xff)<<24);
            }
            pos_+=4;

            return n;
         }

         double read_double()
         {
            double d;

            if (!needSwap_)
            {
               memcpy(&d,wkb_+pos_,8);
            }
            else
            {
               // we rely on the fact that "long long" is in C standard,
               // but not in C++ yet
               // this is not quite portable
               const char* b= wkb_+pos_;
               long long n = ((long long)b[7]&0xff) |
                             (((long long)b[6]&0xff)<<8) |
                             (((long long)b[5]&0xff)<<16) |
                             (((long long)b[4]&0xff)<<24) |
                             (((long long)b[3]&0xff)<<32) |
                             (((long long)b[2]&0xff)<<40) |
                             (((long long)b[1]&0xff)<<48) |
                             (((long long)b[0]&0xff)<<56);
               memcpy(&d,&n,8);
            }
            pos_+=8;

            return d;
         }

         void read_coords(CoordinateArray& ar)
         {
            int size=sizeof(coord<double,2>)*ar.size();
            if (!needSwap_)
            {
               std::memcpy(&ar[0],wkb_+pos_,size);

            }
            else
            {
               for (unsigned i=0;i<ar.size();++i)
               {
                  ar[i].x=read_double();
                  ar[i].y=read_double();
               }
            }
            pos_+=size;
         }

         void read_point(Feature & feature)
         {
            geometry2d * pt = new point<vertex2d>;
            double x = read_double();
            double y = read_double();
            pt->move_to(x,y);
            feature.add_geometry(pt);
         }

         void read_multipoint(Feature & feature)
         {
            int num_points = read_integer();
            for (int i=0;i<num_points;++i)
            {
               pos_+=5;
               read_point(feature);
            }
         }

         void read_multipoint_2(Feature & feature)
         {
            geometry2d * pt = new point<vertex2d>;
            int num_points = read_integer();
            for (int i=0;i<num_points;++i)
            {
               pos_+=5;
               double x = read_double();
               double y = read_double();
               pt->move_to(x,y);
            }
            feature.add_geometry(pt);
         }

         void read_linestring(Feature & feature)
         {
            geometry2d * line = new line_string<vertex2d>;
            int num_points=read_integer();
            CoordinateArray ar(num_points);
            read_coords(ar);
            line->set_capacity(num_points);
            line->move_to(ar[0].x,ar[0].y);
            for (int i=1;i<num_points;++i)
            {
               line->line_to(ar[i].x,ar[i].y);
            }
            feature.add_geometry(line);
         }

         void read_multilinestring(Feature & feature)
         {
            int num_lines=read_integer();
            for (int i=0;i<num_lines;++i)
            {
               pos_+=5;
               read_linestring(feature);
            }
         }

         void read_multilinestring_2(Feature & feature)
         {
            geometry2d * line = new line_string<vertex2d>;
            int num_lines=read_integer();
            unsigned capacity = 0;
            for (int i=0;i<num_lines;++i)
            {
               pos_+=5;
               int num_points=read_integer();
               capacity+=num_points;
               CoordinateArray ar(num_points);
               read_coords(ar);
               line->set_capacity(capacity);
               line->move_to(ar[0].x,ar[0].y);
               for (int i=1;i<num_points;++i)
               {
                  line->line_to(ar[i].x,ar[i].y);
               }
            }
            feature.add_geometry(line);
         }

         void read_polygon(Feature & feature)
         {
            geometry2d * poly = new polygon<vertex2d>;
            int num_rings=read_integer();
            unsigned capacity = 0;
            for (int i=0;i<num_rings;++i)
            {
               int num_points=read_integer();
               capacity+=num_points;
               CoordinateArray ar(num_points);
               read_coords(ar);
               poly->set_capacity(capacity);
               poly->move_to(ar[0].x,ar[0].y);
               for (int j=1;j<num_points;++j)
               {
                  poly->line_to(ar[j].x,ar[j].y);
               }
               poly->line_to(ar[0].x,ar[0].y);
            }
            feature.add_geometry(poly);
         }

         void read_multipolygon(Feature & feature)
         {
            int num_polys=read_integer();
            for (int i=0;i<num_polys;++i)
            {
               pos_+=5;
               read_polygon(feature);
            }
         }

         void read_multipolygon_2(Feature & feature)
         {
            geometry2d * poly = new polygon<vertex2d>;
            int num_polys=read_integer();
            unsigned capacity = 0;
            for (int i=0;i<num_polys;++i)
            {
               pos_+=5;
               int num_rings=read_integer();
               for (int i=0;i<num_rings;++i)
               {
                  int num_points=read_integer();
                  capacity += num_points;
                  CoordinateArray ar(num_points);
                  read_coords(ar);
                  poly->set_capacity(capacity);
                  poly->move_to(ar[0].x,ar[0].y);

                  for (int j=1;j<num_points;++j)
                  {
                     poly->line_to(ar[j].x,ar[j].y);
                  }
                  poly->line_to(ar[0].x,ar[0].y);
               }
            }
            feature.add_geometry(poly);
         }
   };

   void geometry_utils::from_wkb(Feature & feature,const char* wkb, unsigned size, bool multiple_geometries)
   {
      wkb_reader reader(wkb,size);
      if (multiple_geometries)
         return reader.read_multi(feature);
      else
         return reader.read(feature);
   }
}
<commit_msg>The final line_to is not required in the WKB reader since the last and first points of the polygon geometry will be the same<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: wkb.cpp 19 2005-03-22 13:53:27Z pavlenko $

#include <mapnik/wkb.hpp>

#include <mapnik/geom_util.hpp>
#include <mapnik/feature.hpp>

namespace mapnik
{
   struct wkb_reader
   {
      private:
         enum wkbByteOrder {
            wkbXDR=0,
            wkbNDR=1
         };
         const char* wkb_;
         unsigned size_;
         unsigned pos_;
         wkbByteOrder byteOrder_;
         bool needSwap_;
      public:

         enum wkbGeometryType {
            wkbPoint=1,
            wkbLineString=2,
            wkbPolygon=3,
            wkbMultiPoint=4,
            wkbMultiLineString=5,
            wkbMultiPolygon=6,
            wkbGeometryCollection=7
         };

         wkb_reader(const char* wkb,unsigned size)
            : wkb_(wkb),
              size_(size),
              pos_(0),
              byteOrder_((wkbByteOrder)wkb_[0])
         {
            ++pos_;

#ifndef WORDS_BIGENDIAN
            needSwap_=byteOrder_?wkbXDR:wkbNDR;
#else
            needSwap_=byteOrder_?wkbNDR:wkbXDR;
#endif
         }

         ~wkb_reader() {}

         void read_multi(Feature & feature)
         {
            int type=read_integer();
            switch (type)
            {
               case wkbPoint:
                  read_point(feature);
                  break;
               case wkbLineString:
                  read_linestring(feature);
                  break;
               case wkbPolygon:
                  read_polygon(feature);
                  break;
               case wkbMultiPoint:
                  read_multipoint(feature);
                  break;
               case wkbMultiLineString:
                  read_multilinestring(feature);
                  break;
               case wkbMultiPolygon:
                  read_multipolygon(feature);
                  break;
               case wkbGeometryCollection:
                  break;
               default:
                  break;
            }
         }

         void read(Feature & feature)
         {
            int type=read_integer();
            switch (type)
            {
               case wkbPoint:
                  read_point(feature);
                  break;
               case wkbLineString:
                  read_linestring(feature);
                  break;
               case wkbPolygon:
                  read_polygon(feature);
                  break;
               case wkbMultiPoint:
                  read_multipoint_2(feature);
                  break;
               case wkbMultiLineString:
                  read_multilinestring_2(feature);
                  break;
               case wkbMultiPolygon:
                  read_multipolygon_2(feature);
                  break;
               case wkbGeometryCollection:
                  break;
               default:
                  break;
            }
         }

      private:
         wkb_reader(const wkb_reader&);
         wkb_reader& operator=(const wkb_reader&);

         int read_integer()
         {
            int n;

            if (!needSwap_)
            {
               memcpy(&n,wkb_+pos_,4);
            }
            else
            {
               const char* b=wkb_+pos_;
               n = (b[3]&0xff) | ((b[2]&0xff)<<8) | ((b[1]&0xff)<<16) | ((b[0]&0xff)<<24);
            }
            pos_+=4;

            return n;
         }

         double read_double()
         {
            double d;

            if (!needSwap_)
            {
               memcpy(&d,wkb_+pos_,8);
            }
            else
            {
               // we rely on the fact that "long long" is in C standard,
               // but not in C++ yet
               // this is not quite portable
               const char* b= wkb_+pos_;
               long long n = ((long long)b[7]&0xff) |
                             (((long long)b[6]&0xff)<<8) |
                             (((long long)b[5]&0xff)<<16) |
                             (((long long)b[4]&0xff)<<24) |
                             (((long long)b[3]&0xff)<<32) |
                             (((long long)b[2]&0xff)<<40) |
                             (((long long)b[1]&0xff)<<48) |
                             (((long long)b[0]&0xff)<<56);
               memcpy(&d,&n,8);
            }
            pos_+=8;

            return d;
         }

         void read_coords(CoordinateArray& ar)
         {
            int size=sizeof(coord<double,2>)*ar.size();
            if (!needSwap_)
            {
               std::memcpy(&ar[0],wkb_+pos_,size);

            }
            else
            {
               for (unsigned i=0;i<ar.size();++i)
               {
                  ar[i].x=read_double();
                  ar[i].y=read_double();
               }
            }
            pos_+=size;
         }

         void read_point(Feature & feature)
         {
            geometry2d * pt = new point<vertex2d>;
            double x = read_double();
            double y = read_double();
            pt->move_to(x,y);
            feature.add_geometry(pt);
         }

         void read_multipoint(Feature & feature)
         {
            int num_points = read_integer();
            for (int i=0;i<num_points;++i)
            {
               pos_+=5;
               read_point(feature);
            }
         }

         void read_multipoint_2(Feature & feature)
         {
            geometry2d * pt = new point<vertex2d>;
            int num_points = read_integer();
            for (int i=0;i<num_points;++i)
            {
               pos_+=5;
               double x = read_double();
               double y = read_double();
               pt->move_to(x,y);
            }
            feature.add_geometry(pt);
         }

         void read_linestring(Feature & feature)
         {
            geometry2d * line = new line_string<vertex2d>;
            int num_points=read_integer();
            CoordinateArray ar(num_points);
            read_coords(ar);
            line->set_capacity(num_points);
            line->move_to(ar[0].x,ar[0].y);
            for (int i=1;i<num_points;++i)
            {
               line->line_to(ar[i].x,ar[i].y);
            }
            feature.add_geometry(line);
         }

         void read_multilinestring(Feature & feature)
         {
            int num_lines=read_integer();
            for (int i=0;i<num_lines;++i)
            {
               pos_+=5;
               read_linestring(feature);
            }
         }

         void read_multilinestring_2(Feature & feature)
         {
            geometry2d * line = new line_string<vertex2d>;
            int num_lines=read_integer();
            unsigned capacity = 0;
            for (int i=0;i<num_lines;++i)
            {
               pos_+=5;
               int num_points=read_integer();
               capacity+=num_points;
               CoordinateArray ar(num_points);
               read_coords(ar);
               line->set_capacity(capacity);
               line->move_to(ar[0].x,ar[0].y);
               for (int i=1;i<num_points;++i)
               {
                  line->line_to(ar[i].x,ar[i].y);
               }
            }
            feature.add_geometry(line);
         }

         void read_polygon(Feature & feature)
         {
            geometry2d * poly = new polygon<vertex2d>;
            int num_rings=read_integer();
            unsigned capacity = 0;
            for (int i=0;i<num_rings;++i)
            {
               int num_points=read_integer();
               capacity+=num_points;
               CoordinateArray ar(num_points);
               read_coords(ar);
               poly->set_capacity(capacity);
               poly->move_to(ar[0].x,ar[0].y);
               for (int j=1;j<num_points;++j)
               {
                  poly->line_to(ar[j].x,ar[j].y);
               }
            }
            feature.add_geometry(poly);
         }

         void read_multipolygon(Feature & feature)
         {
            int num_polys=read_integer();
            for (int i=0;i<num_polys;++i)
            {
               pos_+=5;
               read_polygon(feature);
            }
         }

         void read_multipolygon_2(Feature & feature)
         {
            geometry2d * poly = new polygon<vertex2d>;
            int num_polys=read_integer();
            unsigned capacity = 0;
            for (int i=0;i<num_polys;++i)
            {
               pos_+=5;
               int num_rings=read_integer();
               for (int i=0;i<num_rings;++i)
               {
                  int num_points=read_integer();
                  capacity += num_points;
                  CoordinateArray ar(num_points);
                  read_coords(ar);
                  poly->set_capacity(capacity);
                  poly->move_to(ar[0].x,ar[0].y);

                  for (int j=1;j<num_points;++j)
                  {
                     poly->line_to(ar[j].x,ar[j].y);
                  }
                  poly->line_to(ar[0].x,ar[0].y);
               }
            }
            feature.add_geometry(poly);
         }
   };

   void geometry_utils::from_wkb(Feature & feature,const char* wkb, unsigned size, bool multiple_geometries)
   {
      wkb_reader reader(wkb,size);
      if (multiple_geometries)
         return reader.read_multi(feature);
      else
         return reader.read(feature);
   }
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright 2018 MINRES Technologies GmbH
 *
 * 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.
 *******************************************************************************/

#include <scc/perf_estimator.h>
#include <scc/report.h>

#if defined(_WIN32)
#include <Windows.h>
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__MACH__) && defined(__APPLE__))
#include <ctime>
#include <sys/resource.h>
#include <sys/times.h>
#include <unistd.h>
#else
#error "Cannot compile file because of an unknown method to retrieve OS time."
#endif

namespace scc {
using namespace sc_core;

SC_HAS_PROCESS(perf_estimator);

perf_estimator::perf_estimator(const sc_module_name& nm, sc_time beat_delay_)
: sc_module(nm)
, beat_delay(beat_delay_) {
    soc.set();
    if(beat_delay.value()) {
        SC_METHOD(beat);
    }
}

perf_estimator::~perf_estimator() {
    time_stamp eod;
    eod.set();
    SCCINFO(SCMOD) << "constr & elab time: " << (eoe.proc_clock_stamp - soc.proc_clock_stamp) << "s";
    SCCINFO(SCMOD) << "simulation time:    " << (eos.proc_clock_stamp - sos.proc_clock_stamp) << "s";
}

void perf_estimator::end_of_elaboration() { eoe.set(); }

void perf_estimator::start_of_simulation() { sos.set(); }

void perf_estimator::end_of_simulation() {
    eos.set();
    sc_time now = sc_time_stamp();
    unsigned long long elapsed_wall = (eos.wall_clock_stamp - sos.wall_clock_stamp).total_microseconds();
    auto elapsed_proc = (unsigned long long)((eos.proc_clock_stamp - sos.proc_clock_stamp) * 1000000);
    auto elapsed_sim = (unsigned long long)(now.to_seconds() * 1000000.);
    if(elapsed_sim > 0) {
        double wall_perf = elapsed_wall / elapsed_sim;
        double proc_perf = elapsed_proc / elapsed_sim;
        SCCINFO(SCMOD) << "Wall clock (process clock) based simulation real time factor is " << wall_perf << "("
                       << proc_perf << ")";
    }
}

void perf_estimator::beat() {
    SCCINFO(SCMOD) << "Heart beat";
    next_trigger(beat_delay);
}
} /* namespace scc */

double scc::perf_estimator::time_stamp::get_cpu_time() {
#if defined(_WIN32)
    FILETIME create_time;
    FILETIME exit_time;
    FILETIME kernel_time;
    FILETIME user_time;
    if(GetProcessTimes(GetCurrentProcess(), &create_tiem, &exit_time, &kernel_time, &user_time) != -1) {
        SYSTEMTIME system_time;
        if(FileTimeToSystemTime(&user_time, system_time) != -1)
            return (double)system_time.wHour * 3600.0 + (double)system_time.wMinute * 60.0 +
                   (double)system_time.wSecond + (double)system_time.wMilliseconds / 1000.;
    }
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__MACH__) && defined(__APPLE__))
#if _POSIX_TIMERS > 0
    {
        clockid_t id;
        struct timespec stamp;
#if _POSIX_CPUTIME > 0
        if(clock_getcpuclockid(0, &id) == -1)
#endif
#if defined(CLOCK_PROCESS_CPUTIME_ID)
            id = CLOCK_PROCESS_CPUTIME_ID;
#elif defined(CLOCK_VIRTUAL)
        id = CLOCK_VIRTUAL;
#else
        id = (clockid_t)-1;
#endif
        if(id != (clockid_t)-1 && clock_gettime(id, &stamp) != -1)
            return (double)stamp.tv_sec + (double)stamp.tv_nsec / 1000000000.0;
    }
#endif
#if defined(RUSAGE_SELF)
    {
        struct rusage usage;
        if(getrusage(RUSAGE_SELF, &usage) != -1)
            return (double)usage.ru_utime.tv_sec + (double)usage.ru_utime.tv_usec / 1000000.0;
    }
#endif
#if defined(_SC_CLK_TICK)
    {
        const double ticks = (double)sysconf(_SC_CLK_TCK);
        struct tms s;
        if(times(&s) != (clock_t)-1)
            return (double)s.tms_utime / ticks;
    }
#endif
#if defined(CLOCKS_PER_SEC)
    {
        clock_t c = clock();
        if(c != (clock_t)-1)
            return (double)c / (double)CLOCKS_PER_SEC;
    }
#endif
#endif
    return 1.0;
}
<commit_msg>Fixed heart beat to skip first beat at 0ns<commit_after>/*******************************************************************************
 * Copyright 2018 MINRES Technologies GmbH
 *
 * 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.
 *******************************************************************************/

#include <scc/perf_estimator.h>
#include <scc/report.h>

#if defined(_WIN32)
#include <Windows.h>
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__MACH__) && defined(__APPLE__))
#include <ctime>
#include <sys/resource.h>
#include <sys/times.h>
#include <unistd.h>
#else
#error "Cannot compile file because of an unknown method to retrieve OS time."
#endif

namespace scc {
using namespace sc_core;

SC_HAS_PROCESS(perf_estimator);

perf_estimator::perf_estimator(const sc_module_name& nm, sc_time beat_delay_)
: sc_module(nm)
, beat_delay(beat_delay_) {
    soc.set();
    if(beat_delay.value()) {
        SC_METHOD(beat);
    }
}

perf_estimator::~perf_estimator() {
    time_stamp eod;
    eod.set();
    SCCINFO(SCMOD) << "constr & elab time: " << (eoe.proc_clock_stamp - soc.proc_clock_stamp) << "s";
    SCCINFO(SCMOD) << "simulation time:    " << (eos.proc_clock_stamp - sos.proc_clock_stamp) << "s";
}

void perf_estimator::end_of_elaboration() { eoe.set(); }

void perf_estimator::start_of_simulation() { sos.set(); }

void perf_estimator::end_of_simulation() {
    eos.set();
    sc_time now = sc_time_stamp();
    unsigned long long elapsed_wall = (eos.wall_clock_stamp - sos.wall_clock_stamp).total_microseconds();
    auto elapsed_proc = (unsigned long long)((eos.proc_clock_stamp - sos.proc_clock_stamp) * 1000000);
    auto elapsed_sim = (unsigned long long)(now.to_seconds() * 1000000.);
    if(elapsed_sim > 0) {
        double wall_perf = elapsed_wall / elapsed_sim;
        double proc_perf = elapsed_proc / elapsed_sim;
        SCCINFO(SCMOD) << "Wall clock (process clock) based simulation real time factor is " << wall_perf << "("
                       << proc_perf << ")";
    }
}

void perf_estimator::beat() {
    if(sc_time_stamp().value())
      SCCINFO(SCMOD) << "Heart beat";
    next_trigger(beat_delay);
}
} /* namespace scc */

double scc::perf_estimator::time_stamp::get_cpu_time() {
#if defined(_WIN32)
    FILETIME create_time;
    FILETIME exit_time;
    FILETIME kernel_time;
    FILETIME user_time;
    if(GetProcessTimes(GetCurrentProcess(), &create_tiem, &exit_time, &kernel_time, &user_time) != -1) {
        SYSTEMTIME system_time;
        if(FileTimeToSystemTime(&user_time, system_time) != -1)
            return (double)system_time.wHour * 3600.0 + (double)system_time.wMinute * 60.0 +
                   (double)system_time.wSecond + (double)system_time.wMilliseconds / 1000.;
    }
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__MACH__) && defined(__APPLE__))
#if _POSIX_TIMERS > 0
    {
        clockid_t id;
        struct timespec stamp;
#if _POSIX_CPUTIME > 0
        if(clock_getcpuclockid(0, &id) == -1)
#endif
#if defined(CLOCK_PROCESS_CPUTIME_ID)
            id = CLOCK_PROCESS_CPUTIME_ID;
#elif defined(CLOCK_VIRTUAL)
        id = CLOCK_VIRTUAL;
#else
        id = (clockid_t)-1;
#endif
        if(id != (clockid_t)-1 && clock_gettime(id, &stamp) != -1)
            return (double)stamp.tv_sec + (double)stamp.tv_nsec / 1000000000.0;
    }
#endif
#if defined(RUSAGE_SELF)
    {
        struct rusage usage;
        if(getrusage(RUSAGE_SELF, &usage) != -1)
            return (double)usage.ru_utime.tv_sec + (double)usage.ru_utime.tv_usec / 1000000.0;
    }
#endif
#if defined(_SC_CLK_TICK)
    {
        const double ticks = (double)sysconf(_SC_CLK_TCK);
        struct tms s;
        if(times(&s) != (clock_t)-1)
            return (double)s.tms_utime / ticks;
    }
#endif
#if defined(CLOCKS_PER_SEC)
    {
        clock_t c = clock();
        if(c != (clock_t)-1)
            return (double)c / (double)CLOCKS_PER_SEC;
    }
#endif
#endif
    return 1.0;
}
<|endoftext|>


<commit_before>/* This file is part of the KDE project
 *
 * This file is part of the Marble Desktop Globe.
 *
 * Copyright 2004-2007 Torsten Rahn <tackat@kde.org>"
 * Copyright 2007      Inge Wallin  <ingwa@kde.org>"
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "MarbleAboutDialog.h"
#include "ui_MarbleAboutDialog.h"

#include <QtCore/QFile>
#include <QtGui/QTextFrame>
#include <QtCore/QTextStream>
#include <QtGui/QPixmap>

#include "MarbleDirs.h"

class MarbleAboutDialogPrivate
{
public:
    Ui::MarbleAboutDialog  uiWidget;

    bool authorsLoaded;
    bool dataLoaded;
    bool licenseLoaded;
};

MarbleAboutDialog::MarbleAboutDialog(QWidget *parent)
    : QDialog( parent ),
      d( new MarbleAboutDialogPrivate )
{
    d->uiWidget.setupUi( this );

    d->authorsLoaded = false;
    d->dataLoaded = false;
    d->licenseLoaded = false;

    d->uiWidget.m_pMarbleLogoLabel->setPixmap( QPixmap( MarbleDirs::path("svg/marble-logo-72dpi.png") ) );

    connect( d->uiWidget.tabWidget, SIGNAL( currentChanged( int ) ),
             this, SLOT( loadPageContents( int ) ) );

    d->uiWidget.m_pMarbleAboutBrowser->setHtml( tr("
(c) 2007, The Marble Project

http://edu.kde.org/marble") );

}

void MarbleAboutDialog::loadPageContents( int idx )
{
    QTextBrowser* browser = 0;

    if ( idx == 1 && d->authorsLoaded == false )
    {
        d->authorsLoaded = true;
        browser = d->uiWidget.m_pMarbleAuthorsBrowser;
        QString filename = MarbleDirs::path( "credits_authors.html" );
        if( !filename.isEmpty() )
        {
            QFile  f( filename );
            if( f.open( QIODevice::ReadOnly ) )
            {
                QTextStream ts( &f );
                browser->setHtml( ts.readAll() );
            }
            f.close();
        }
        QTextFrameFormat  format = browser->document()->rootFrame()->frameFormat();
        format.setMargin(12);
        browser->document()->rootFrame()->setFrameFormat( format );
    }

    if ( idx == 2 && d->dataLoaded == false )
    {
        d->dataLoaded = true;
        browser = d->uiWidget.m_pMarbleDataBrowser;
        QString filename = MarbleDirs::path( "credits_data.html" );
        if( !filename.isEmpty() )
        {
            QFile  f( filename );
            if( f.open( QIODevice::ReadOnly ) )
            {
                QTextStream ts( &f );
                browser->setHtml( ts.readAll() );
            }
            f.close();
        }
        QTextFrameFormat  format = browser->document()->rootFrame()->frameFormat();
        format.setMargin(12);
        browser->document()->rootFrame()->setFrameFormat( format );
    }

    if ( idx == 3 && d->licenseLoaded == false )
    {
        d->licenseLoaded = true;
        browser = d->uiWidget.m_pMarbleLicenseBrowser;
        QString filename = MarbleDirs::path( "LICENSE.txt" );
        if( !filename.isEmpty() )
        {
            QFile  f( filename );
            if( f.open( QIODevice::ReadOnly ) )
            {
                QTextStream ts( &f );
                browser->setText( ts.readAll() );
            }
            f.close();
        }
        QTextFrameFormat  format = browser->document()->rootFrame()->frameFormat();
        format.setMargin(12);
        browser->document()->rootFrame()->setFrameFormat( format );
    }
}

#include "MarbleAboutDialog.moc"

<commit_msg>- Adding missing border to first tab<commit_after>/* This file is part of the KDE project
 *
 * This file is part of the Marble Desktop Globe.
 *
 * Copyright 2004-2007 Torsten Rahn <tackat@kde.org>"
 * Copyright 2007      Inge Wallin  <ingwa@kde.org>"
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "MarbleAboutDialog.h"
#include "ui_MarbleAboutDialog.h"

#include <QtCore/QFile>
#include <QtGui/QTextFrame>
#include <QtCore/QTextStream>
#include <QtGui/QPixmap>

#include "MarbleDirs.h"

class MarbleAboutDialogPrivate
{
public:
    Ui::MarbleAboutDialog  uiWidget;

    bool authorsLoaded;
    bool dataLoaded;
    bool licenseLoaded;
};

MarbleAboutDialog::MarbleAboutDialog(QWidget *parent)
    : QDialog( parent ),
      d( new MarbleAboutDialogPrivate )
{
    d->uiWidget.setupUi( this );

    d->authorsLoaded = false;
    d->dataLoaded = false;
    d->licenseLoaded = false;

    d->uiWidget.m_pMarbleLogoLabel->setPixmap( QPixmap( MarbleDirs::path("svg/marble-logo-72dpi.png") ) );

    connect( d->uiWidget.tabWidget, SIGNAL( currentChanged( int ) ),
             this, SLOT( loadPageContents( int ) ) );

    QTextBrowser* browser = d->uiWidget.m_pMarbleAboutBrowser;
    browser->setHtml( tr("
(c) 2007, The Marble Project

http://edu.kde.org/marble") );

    QTextFrameFormat  format = browser->document()->rootFrame()->frameFormat();
    format.setMargin(12);
    browser->document()->rootFrame()->setFrameFormat( format );

}

void MarbleAboutDialog::loadPageContents( int idx )
{
    QTextBrowser* browser = 0;

    if ( idx == 1 && d->authorsLoaded == false )
    {
        d->authorsLoaded = true;
        browser = d->uiWidget.m_pMarbleAuthorsBrowser;
        QString filename = MarbleDirs::path( "credits_authors.html" );
        if( !filename.isEmpty() )
        {
            QFile  f( filename );
            if( f.open( QIODevice::ReadOnly ) )
            {
                QTextStream ts( &f );
                browser->setHtml( ts.readAll() );
            }
            f.close();
        }
        QTextFrameFormat  format = browser->document()->rootFrame()->frameFormat();
        format.setMargin(12);
        browser->document()->rootFrame()->setFrameFormat( format );
    }

    if ( idx == 2 && d->dataLoaded == false )
    {
        d->dataLoaded = true;
        browser = d->uiWidget.m_pMarbleDataBrowser;
        QString filename = MarbleDirs::path( "credits_data.html" );
        if( !filename.isEmpty() )
        {
            QFile  f( filename );
            if( f.open( QIODevice::ReadOnly ) )
            {
                QTextStream ts( &f );
                browser->setHtml( ts.readAll() );
            }
            f.close();
        }
        QTextFrameFormat  format = browser->document()->rootFrame()->frameFormat();
        format.setMargin(12);
        browser->document()->rootFrame()->setFrameFormat( format );
    }

    if ( idx == 3 && d->licenseLoaded == false )
    {
        d->licenseLoaded = true;
        browser = d->uiWidget.m_pMarbleLicenseBrowser;
        QString filename = MarbleDirs::path( "LICENSE.txt" );
        if( !filename.isEmpty() )
        {
            QFile  f( filename );
            if( f.open( QIODevice::ReadOnly ) )
            {
                QTextStream ts( &f );
                browser->setText( ts.readAll() );
            }
            f.close();
        }
        QTextFrameFormat  format = browser->document()->rootFrame()->frameFormat();
        format.setMargin(12);
        browser->document()->rootFrame()->setFrameFormat( format );
    }
}

#include "MarbleAboutDialog.moc"

<|endoftext|>


<commit_before>#include <Atema/Atema.hpp>

#include "BasicRenderPipeline.hpp"

#include <iostream>

using namespace at;

class TestLayer : public ApplicationLayer
{
public:
	TestLayer() :
		frameCount(0),
		frameDuration(0.0f)
	{
		initialize();
	}

	~TestLayer()
	{
		renderPipeline.reset();

		// Window & Renderer
		window.reset();

		Renderer::destroy();
	}

	void initialize()
	{
		maxFramesInFlight = 2;
		currentFrame = 0;
		indexCount = 0;

		Renderer::Settings settings;
		settings.maxFramesInFlight = maxFramesInFlight;
		//settings.mainWindowSettings.width = 1920;
		//settings.mainWindowSettings.height = 1080;

		Renderer::create<VulkanRenderer>(settings);

		// Window / SwapChain
		window = Renderer::getInstance().getMainWindow();

		RenderPipeline::Settings renderPipelineSettings;
		renderPipelineSettings.window = window;

		renderPipeline = std::make_shared<BasicRenderPipeline>(renderPipelineSettings);
	}

	void onEvent(Event& event) override
	{

	}

	void update(TimeStep ms) override
	{
		ATEMA_BENCHMARK("Application update")

		totalTime += ms.getSeconds();
		frameDuration += ms.getSeconds();

		if (window->shouldClose())
		{
			Application::instance().close();
			return;
		}

		window->processEvents();

		renderPipeline->update(ms);

		window->swapBuffers();

		frameCount++;

		if (frameDuration >= 0.5f)
		{
			const auto frameTime = frameDuration / static_cast<float>(frameCount);
			const auto fps = static_cast<unsigned>(1.0f / frameTime);

			window->setTitle("Atema (" + std::to_string(fps) + " fps / " + std::to_string(frameTime * 1000.0f) + " ms)");

			BenchmarkManager::getInstance().print(frameCount);
			BenchmarkManager::getInstance().reset();

			frameCount = 0;
			frameDuration = 0.0f;
		}
	}

	uint32_t maxFramesInFlight;
	uint32_t currentFrame;
	Ptr<Window> window;
	Ptr<SwapChain> swapChain;
	Ptr<RenderPass> renderPass;
	Ptr<Image> depthImage;
	std::vector<Ptr<Framebuffer>> framebuffers;
	Ptr<DescriptorSetLayout> descriptorSetLayout;
	Ptr<GraphicsPipeline> pipeline;
	std::vector<Ptr<CommandPool>> commandPools;
	std::vector<Ptr<CommandBuffer>> commandBuffers;
	std::vector<Ptr<Fence>> fences;
	std::vector<Ptr<Fence>> imageFences;
	std::vector<Ptr<Semaphore>> imageAvailableSemaphores;
	std::vector<Ptr<Semaphore>> renderFinishedSemaphores;
	Ptr<DescriptorPool> descriptorPool;

	Ptr<Buffer> vertexBuffer;
	Ptr<Buffer> indexBuffer;
	Ptr<Image> texture;
	Ptr<Sampler> sampler;
	std::vector<Ptr<Buffer>> uniformBuffers;
	std::vector<Ptr<DescriptorSet>> descriptorSets;

	uint32_t indexCount;

	float totalTime;

	Ptr<BasicRenderPipeline> renderPipeline;

	int frameCount;
	float frameDuration;

};

void basicApplication()
{
	auto layer = new TestLayer();

	auto& app = Application::instance();

	app.addLayer(layer);

	app.run();

	delete layer;
}

// MAIN
int main(int argc, char** argv)
{
	try
	{
		basicApplication();
	}
	catch (const std::exception& e)
	{
		std::cout << e.what() << std::endl;
		return -1;
	}

	return 0;
}<commit_msg>Examples - Sandbox - Cleaned code and removed old members<commit_after>#include <Atema/Atema.hpp>

#include "BasicRenderPipeline.hpp"

#include <iostream>

using namespace at;

class SandboxLayer : public ApplicationLayer
{
public:
	SandboxLayer() :
		frameCount(0),
		frameDuration(0.0f)
	{
		initialize();
	}

	~SandboxLayer()
	{
		renderPipeline.reset();

		// Window & Renderer
		window.reset();

		Renderer::destroy();
	}

	void initialize()
	{
		Renderer::Settings settings;
		settings.maxFramesInFlight = 2;
		//settings.mainWindowSettings.width = 1920;
		//settings.mainWindowSettings.height = 1080;

		Renderer::create<VulkanRenderer>(settings);

		// Window / SwapChain
		window = Renderer::getInstance().getMainWindow();

		RenderPipeline::Settings renderPipelineSettings;
		renderPipelineSettings.window = window;

		renderPipeline = std::make_shared<BasicRenderPipeline>(renderPipelineSettings);
	}

	void onEvent(Event& event) override
	{

	}

	void update(TimeStep ms) override
	{
		ATEMA_BENCHMARK("Application update")

		frameDuration += ms.getSeconds();

		if (window->shouldClose())
		{
			Application::instance().close();
			return;
		}

		window->processEvents();

		renderPipeline->update(ms);

		window->swapBuffers();

		frameCount++;

		if (frameDuration >= 0.5f)
		{
			const auto frameTime = frameDuration / static_cast<float>(frameCount);
			const auto fps = static_cast<unsigned>(1.0f / frameTime);

			window->setTitle("Atema (" + std::to_string(fps) + " fps / " + std::to_string(frameTime * 1000.0f) + " ms)");

			BenchmarkManager::getInstance().print(frameCount);
			BenchmarkManager::getInstance().reset();

			frameCount = 0;
			frameDuration = 0.0f;
		}
	}

	Ptr<Window> window;

	Ptr<BasicRenderPipeline> renderPipeline;

	int frameCount;
	float frameDuration;
};

// MAIN
int main(int argc, char** argv)
{
	try
	{
		auto sandboxLayer = std::make_unique<SandboxLayer>();

		auto& app = Application::instance();

		app.addLayer(sandboxLayer.get());

		app.run();
	}
	catch (const std::exception& e)
	{
		std::cout << e.what() << std::endl;

		return -1;
	}

	return 0;
}<|endoftext|>


<commit_before>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>

#include "FibIndicationWrapper.h"
#include "FibRequestProxy.h"
#include "GeneratedTypes.h"

sem_t test_sem;

class FibIndication : public FibIndicationWrapper
{
public:
    virtual void fibresult(uint32_t v) {
      fprintf(stderr, "fibresult: %d\n", v);
	sem_post(&test_sem);
    }
    virtual void fibnote(uint32_t v) {
      fprintf(stderr, "fibnote: %d\n", v);
    }
    FibIndication(unsigned int id) : FibIndicationWrapper(id) {}
};

FibRequestProxy *fibRequestProxy = 0;
FibIndication *fibIndication;

int main(int argc, const char **argv)
{
  int i;
  // these use the default poller
  fibRequestProxy = new FibRequestProxy(IfcNames_FibRequest);
  fibIndication = new FibIndication(IfcNames_FibIndication);

  if(sem_init(&test_sem, 1, 0)){
    fprintf(stderr, "failed to init test_sem\n");
    return -1;
  }
  pthread_t tid;
  fprintf(stderr, "creating exec thread\n");
  if(pthread_create(&tid, NULL,  portalExec, NULL)){
   fprintf(stderr, "error creating exec thread\n");
   exit(1);
  }

  for (i = 0; i < 10; i += 1) {
    fprintf(stderr, "fib(%d)\n", i);
    fibRequestProxy->fib(i);
    sem_wait(&test_sem);
  }

  return 0;
}
<commit_msg>change to first 20 fibs<commit_after>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>

#include "FibIndicationWrapper.h"
#include "FibRequestProxy.h"
#include "GeneratedTypes.h"

sem_t test_sem;

class FibIndication : public FibIndicationWrapper
{
public:
    virtual void fibresult(uint32_t v) {
      fprintf(stderr, "fibresult: %d\n", v);
	sem_post(&test_sem);
    }
    virtual void fibnote(uint32_t v) {
      fprintf(stderr, "fibnote: %d\n", v);
    }
    FibIndication(unsigned int id) : FibIndicationWrapper(id) {}
};

FibRequestProxy *fibRequestProxy = 0;
FibIndication *fibIndication;

int main(int argc, const char **argv)
{
  int i;
  // these use the default poller
  fibRequestProxy = new FibRequestProxy(IfcNames_FibRequest);
  fibIndication = new FibIndication(IfcNames_FibIndication);

  if(sem_init(&test_sem, 1, 0)){
    fprintf(stderr, "failed to init test_sem\n");
    return -1;
  }
  pthread_t tid;
  fprintf(stderr, "creating exec thread\n");
  if(pthread_create(&tid, NULL,  portalExec, NULL)){
   fprintf(stderr, "error creating exec thread\n");
   exit(1);
  }

  for (i = 0; i < 20; i += 1) {
    fprintf(stderr, "fib(%d)\n", i);
    fibRequestProxy->fib(i);
    sem_wait(&test_sem);
  }

  return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

const int UFSIZE = 100010;
int union_find[UFSIZE];

void init() {
  for (auto i=0; i<UFSIZE; i++) {
    union_find[i] = i;
  }
}

int root(int a) {
  if (a == union_find[a]) return a;
  return (union_find[a] = root(union_find[a]));
}

bool issame(int a, int b) {
  return root(a) == root(b);
}

void unite(int a, int b) {
  union_find[root(a)] = root(b);
}

bool isroot(int a) {
  return root(a) == a;
}

int N, M;
int a[100010];
int b[100010];
int Q;
int x[100010];
int y[100010];
tuple<int, int> parent[100010];
int d[100010][20];
int depth[100010];
vector<int> V[100010];

int lca(int u, int v) {
  if (depth[u] > depth[v]) swap(u, v);
  for (auto k = 0; k < 20; ++k) {
    if ((depth[v] - depth[u]) >> k & 1) {
      v = d[v][k];
    }
  }
  if (u == v) return u;
  for (auto k = 19; k >= 0; --k) {
    if (d[k][u] != d[k][v]) {
      u = d[u][k];
      v = d[v][k];
    }
  }
  return d[u][0];
}

int main() {
  // initが必要
  init();
  fill(&d[0][0], &d[0][0]+100010*20, -1);
  fill(parent, parent+100010, make_tuple(-1, 0));
  cin >> N >> M;
  for (auto i = 0; i < M; ++i) {
    cin >> a[i] >> b[i];
    a[i]--;
    b[i]--;
  }
  cin >> Q;
  for (auto i = 0; i < Q; ++i) {
    cin >> x[i] >> y[i];
    x[i]--;
    y[i]--;
  }
  for (auto i = 0; i < M; ++i) {
    parent[root(a[i])] = make_tuple(root(b[i]), i);
    V[root(b[i])].push_back(root(a[i]));
    unite(a[i], b[i]);
  }
  for (auto i = 0; i < N; ++i) {
    d[i][0] = get<0>(parent[i]);
  }
  for (auto i = 1; i < 20; ++i) {
    for (auto j = 0; j < N; ++j) {
      if (d[j][i-1] >= 0) {
        d[j][i] = d[d[j][i-1]][i-1];
      }
    }
  }
  fill(depth, depth+100010, -1);
  for (auto i = 0; i < N; ++i) {
    if (d[i][0] == -1) {
      stack<tuple<int, int> > S;
      S.push(make_tuple(i, 0));
      while (!S.empty()) {
        int now = get<0>(S.top());
        int dep = get<1>(S.top());
        S.pop();
        if (depth[now] == -1) {
          depth[now] = dep;
          for (auto x : V[now]) {
            if (depth[x] == -1) {
              S.push(make_tuple(x, dep+1));
            }
          }
        }
      }
    }
  }
  for (auto i = 0; i < Q; ++i) {
    if (!issame(x[i], y[i])) {
      cout << -1 << endl;
    } else {
      int c = lca(x[i], y[i]);
      cout << get<1>(parent[c])+1 << endl;
    }
  }
}
<commit_msg>tried H.cpp to 'H'<commit_after>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

const int UFSIZE = 100010;
int union_find[UFSIZE];

void init() {
  for (auto i=0; i<UFSIZE; i++) {
    union_find[i] = i;
  }
}

int root(int a) {
  if (a == union_find[a]) return a;
  return (union_find[a] = root(union_find[a]));
}

bool issame(int a, int b) {
  return root(a) == root(b);
}

void unite(int a, int b) {
  union_find[root(a)] = root(b);
}

bool isroot(int a) {
  return root(a) == a;
}

int N, M;
int a[100010];
int b[100010];
int Q;
int x[100010];
int y[100010];
tuple<int, int> parent[100010];
int d[100010][20];
int depth[100010];
vector<int> V[100010];

int lca(int u, int v) {
  if (depth[u] > depth[v]) swap(u, v);
  for (auto k = 0; k < 20; ++k) {
    if ((depth[v] - depth[u]) >> k & 1) {
      v = d[v][k];
    }
  }
  if (u == v) return u;
  for (auto k = 19; k >= 0; --k) {
    if (d[k][u] != d[k][v]) {
      u = d[u][k];
      v = d[v][k];
    }
  }
  return d[u][0];
}

int main() {
  // initが必要
  init();
  fill(&d[0][0], &d[0][0]+100010*20, -1);
  fill(parent, parent+100010, make_tuple(-1, 0));
  cin >> N >> M;
  for (auto i = 0; i < M; ++i) {
    cin >> a[i] >> b[i];
    a[i]--;
    b[i]--;
  }
  cin >> Q;
  for (auto i = 0; i < Q; ++i) {
    cin >> x[i] >> y[i];
    x[i]--;
    y[i]--;
  }
  for (auto i = 0; i < M; ++i) {
    parent[root(a[i])] = make_tuple(root(b[i]), i);
    V[root(b[i])].push_back(root(a[i]));
    unite(a[i], b[i]);
  }
  for (auto i = 0; i < N; ++i) {
    d[i][0] = get<0>(parent[i]);
  }
  for (auto i = 1; i < 20; ++i) {
    for (auto j = 0; j < N; ++j) {
      if (d[j][i-1] >= 0) {
        d[j][i] = d[d[j][i-1]][i-1];
      }
    }
  }
  fill(depth, depth+100010, -1);
  for (auto i = 0; i < N; ++i) {
    if (d[i][0] == -1) {
      stack<tuple<int, int> > S;
      S.push(make_tuple(i, 0));
      while (!S.empty()) {
        int now = get<0>(S.top());
        int dep = get<1>(S.top());
        S.pop();
        if (depth[now] == -1) {
          depth[now] = dep;
          for (auto x : V[now]) {
            if (depth[x] == -1) {
              S.push(make_tuple(x, dep+1));
            }
          }
        }
      }
    }
  }
  for (auto i = 0; i < N; ++i) {
    cerr << "depth[" << i << "] = " << depth[i] << endl;
  }
  for (auto i = 0; i < Q; ++i) {
    if (!issame(x[i], y[i])) {
      cout << -1 << endl;
    } else {
      int c = lca(x[i], y[i]);
      cout << get<1>(parent[c])+1 << endl;
    }
  }
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// object that creates and contains a spawn position

#include "common.h"

#include "SpawnPosition.h"
#include "FlagInfo.h"
#include "TeamBases.h"
#include "WorldInfo.h"
#include "PlayerInfo.h"
#include "PlayerState.h"

// FIXME: from bzfs.cxx
extern int getCurMaxPlayers();
extern bool areFoes(TeamColor team1, TeamColor team2);
extern BasesList bases;
extern WorldInfo *world;
extern PlayerInfo player[];
extern PlayerState lastState[];

SpawnPosition::SpawnPosition(int playerId, bool onGroundOnly, bool notNearEdges) :
		curMaxPlayers(getCurMaxPlayers())
{
  team = player[playerId].getTeam();
  azimuth = (float)bzfrand() * 2.0f * M_PI;

  if (player[playerId].shouldRestartAtBase() &&
      (team >= RedTeam) && (team <= PurpleTeam) &&
      (bases.find(team) != bases.end())) {
    TeamBases &teamBases = bases[team];
    const TeamBase &base = teamBases.getRandomBase((int)(bzfrand() * 100));
    base.getRandomPosition(pos[0], pos[1], pos[2]);
    player[playerId].setRestartOnBase(false);
  } else {
    const float tankHeight = BZDB.eval(StateDatabase::BZDB_TANKHEIGHT);
    const float tankRadius = BZDB.eval(StateDatabase::BZDB_TANKRADIUS);
    safeSWRadius = (float)((BZDB.eval(StateDatabase::BZDB_SHOCKOUTRADIUS) + BZDB.eval(StateDatabase::BZDB_TANKRADIUS)) * 1.5);
    safeDistance = tankRadius * 20; // FIXME: is this a good value?
    const float size = BZDB.eval(StateDatabase::BZDB_WORLDSIZE);
    const float maxWorldHeight = world->getMaxWorldHeight();
    ObstacleLocation *building = NULL;

    // keep track of how much time we spend searching for a location
    TimeKeeper start = TimeKeeper::getCurrent();

    int inAirAttempts = 50;
    int tries = 0;
    float minProximity = size / 3.0f;
    float bestDist = -1.0f;
    bool foundspot = false;
    while (!foundspot) {
      if (!world->getZonePoint(std::string(Team::getName(team)), testPos)) {
        if (notNearEdges) {
          // don't spawn close to map edges in CTF mode
          testPos[0] = ((float)bzfrand() - 0.5f) * size * 0.6f;
          testPos[1] = ((float)bzfrand() - 0.5f) * size * 0.6f;
	} else {
          testPos[0] = ((float)bzfrand() - 0.5f) * (size - 2.0f * tankRadius);
          testPos[1] = ((float)bzfrand() - 0.5f) * (size - 2.0f * tankRadius);
	}
        testPos[2] = onGroundOnly ? 0.0f : ((float)bzfrand() * maxWorldHeight);
      }
      tries++;

      int type = world->inBuilding(&building, testPos[0], testPos[1], testPos[2],
                                   tankRadius, tankHeight);

      if (onGroundOnly) {
        if (type == NOT_IN_BUILDING)
          foundspot = true;
      } else {
        if ((type == NOT_IN_BUILDING) && (testPos[2] > 0.0f)) {
          testPos[2] = 0.0f;
          //Find any intersection regardless of z
          type = world->inBuilding(&building, testPos[0], testPos[1], testPos[2],
                                   tankRadius, maxWorldHeight);
        }

        // in a building? try climbing on roof until on top
        int lastType = type;
	int retriesRemaining = 100; // don't climb forever
        while (type != NOT_IN_BUILDING) {
          testPos[2] = building->pos[2] + building->size[2] + 0.0001f;
          tries++;
          lastType = type;
          type = world->inBuilding(&building, testPos[0], testPos[1], testPos[2],
                                   tankRadius, tankHeight);
	  if (--retriesRemaining <= 0) {
	    DEBUG1("Warning: getSpawnLocation had to climb too many buildings\n");
	    break;
	  }
        }
        // ok, when not on top of pyramid or teleporter
        if (lastType != IN_PYRAMID  &&  lastType != IN_TELEPORTER) {
          foundspot = true;
        }
        // only try up in the sky so many times
        if (--inAirAttempts <= 0) {
          onGroundOnly = true;
        }
      }

      // check every now and then if we have already used up 10ms of time
      if (tries >= 50) {
        tries = 0;
        if (TimeKeeper::getCurrent() - start > 0.01f) {
          if (bestDist < 0.0f) { // haven't found a single spot
            //Just drop the sucka in, and pray
            pos[0] = testPos[0];
            pos[1] = testPos[1];
            pos[2] = maxWorldHeight;
	    DEBUG1("Warning: getSpawnLocation ran out of time, just dropping the sucker in\n");
          }
          break;
        }
      }

      // check if spot is safe enough
      bool dangerous = isImminentlyDangerous();
      if (foundspot && !dangerous) {
	float enemyAngle;
	float dist = enemyProximityCheck(enemyAngle);
	if (dist > bestDist) { // best so far
	  bestDist = dist;
	  pos[0] = testPos[0];
	  pos[1] = testPos[1];
	  pos[2] = testPos[2];
	  azimuth = fmod((enemyAngle + M_PI), 2.0f * M_PI);
	}
	if (bestDist < minProximity) { // not good enough, keep looking
	  foundspot = false;
	  minProximity *= 0.99f; // relax requirements a little
	}
      } else if (dangerous) {
	foundspot = false;
      }
    }
  }
}

SpawnPosition::~SpawnPosition()
{
}

const bool SpawnPosition::isFacing(const float *enemyPos, const float enemyAzimuth,
				   const float deviation) const
{
  // determine angle from source to dest
  // (X) using only x & y, resultant will be z rotation
  float dx = testPos[0] - enemyPos[0];
  float dy = testPos[1] - enemyPos[1];
  float angActual;
  if (dx == 0) {
    // avoid divide by zero error
    angActual = (float)tan(dy / (1 / 1e12f));
  } else {
    angActual = (float)tan(dy / dx);
  }

  // see if our heading angle is within the bounds set by deviation
  // (X) only compare to z-rotation since that's all we're using
  if (((angActual + deviation / 2) > enemyAzimuth) &&
      ((angActual - deviation / 2) < enemyAzimuth)) {
    return true;
  } else {
    return false;
  }
}

const bool SpawnPosition::isImminentlyDangerous() const
{
  for (int i = 0; i < curMaxPlayers; i++) {
    if (player[i].isAlive() && areFoes(player[i].getTeam(), team)) {
      const FlagInfo *finfo =&flag[player[i].getFlag()];
      const FlagType *ftype = finfo->flag.type;
      float *enemyPos = lastState[i].pos;
      float enemyAngle = lastState[i].azimuth;
      // check for dangerous flags, etc
      // FIXME: any more?
      if (ftype == Flags::Laser) {  // don't spawn in the line of sight of an L
	if (isFacing(enemyPos, enemyAngle, M_PI / 9)) { // he's looking within 20 degrees of spawn point
	  return true;	// eek, don't spawn here
	}
      } else if (ftype == Flags::ShockWave) {  // don't spawn next to a SW
	if (distanceFrom(enemyPos) < safeSWRadius) { // too close to SW
	  return true;	// eek, don't spawn here
	}
      }
      // don't spawn in the line of sight of a normal-shot tank within a certain distance
      if (distanceFrom(enemyPos) < safeDistance) { // within danger zone?
	if (isFacing(enemyPos, enemyAngle, M_PI / 9)) { //and he's looking at me
	  return true;
	}
      }
    }
  }

  // TODO: should check world weapons also

  return false;
}

const float SpawnPosition::enemyProximityCheck(float &enemyAngle) const
{
  float worstDist = 1e12f; // huge number
  bool noEnemy    = true;

  for (int i = 0; i < curMaxPlayers; i++) {
    if (player[i].isAlive() && areFoes(player[i].getTeam(), team)) {
      float *enemyPos = lastState[i].pos;
      if (fabs(enemyPos[2] - testPos[2]) < 1.0f) {
        float x = enemyPos[0] - testPos[0];
        float y = enemyPos[1] - testPos[1];
        float distSq = x * x + y * y;
        if (distSq < worstDist) {
          worstDist  = distSq;
	  enemyAngle = lastState[i].azimuth;
	  noEnemy    = false;
	}
      }
    }
  }
  if (noEnemy)
    enemyAngle = (float)bzfrand() * 2.0f * M_PI;
  return sqrtf(worstDist);
}

const float SpawnPosition::distanceFrom(const float* farPos) const
{
  float dx = farPos[0] - testPos[0];
  float dy = farPos[1] - testPos[1];
  float dz = farPos[2] - testPos[2];
  return (float)sqrt(dx*dx + dy*dy + dz*dz);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Fix valgrind error; don't spawn if you'll be shot by friendly fire either<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// object that creates and contains a spawn position

#include "common.h"

#include "SpawnPosition.h"
#include "FlagInfo.h"
#include "TeamBases.h"
#include "WorldInfo.h"
#include "PlayerInfo.h"
#include "PlayerState.h"

// FIXME: from bzfs.cxx
extern int getCurMaxPlayers();
extern bool areFoes(TeamColor team1, TeamColor team2);
extern BasesList bases;
extern WorldInfo *world;
extern PlayerInfo player[];
extern PlayerState lastState[];

SpawnPosition::SpawnPosition(int playerId, bool onGroundOnly, bool notNearEdges) :
		curMaxPlayers(getCurMaxPlayers())
{
  team = player[playerId].getTeam();
  azimuth = (float)bzfrand() * 2.0f * M_PI;

  if (player[playerId].shouldRestartAtBase() &&
      (team >= RedTeam) && (team <= PurpleTeam) &&
      (bases.find(team) != bases.end())) {
    TeamBases &teamBases = bases[team];
    const TeamBase &base = teamBases.getRandomBase((int)(bzfrand() * 100));
    base.getRandomPosition(pos[0], pos[1], pos[2]);
    player[playerId].setRestartOnBase(false);
  } else {
    const float tankHeight = BZDB.eval(StateDatabase::BZDB_TANKHEIGHT);
    const float tankRadius = BZDB.eval(StateDatabase::BZDB_TANKRADIUS);
    safeSWRadius = (float)((BZDB.eval(StateDatabase::BZDB_SHOCKOUTRADIUS) + BZDB.eval(StateDatabase::BZDB_TANKRADIUS)) * 1.5);
    safeDistance = tankRadius * 20; // FIXME: is this a good value?
    const float size = BZDB.eval(StateDatabase::BZDB_WORLDSIZE);
    const float maxWorldHeight = world->getMaxWorldHeight();
    ObstacleLocation *building = NULL;

    // keep track of how much time we spend searching for a location
    TimeKeeper start = TimeKeeper::getCurrent();

    int inAirAttempts = 50;
    int tries = 0;
    float minProximity = size / 3.0f;
    float bestDist = -1.0f;
    bool foundspot = false;
    while (!foundspot) {
      if (!world->getZonePoint(std::string(Team::getName(team)), testPos)) {
        if (notNearEdges) {
          // don't spawn close to map edges in CTF mode
          testPos[0] = ((float)bzfrand() - 0.5f) * size * 0.6f;
          testPos[1] = ((float)bzfrand() - 0.5f) * size * 0.6f;
	} else {
          testPos[0] = ((float)bzfrand() - 0.5f) * (size - 2.0f * tankRadius);
          testPos[1] = ((float)bzfrand() - 0.5f) * (size - 2.0f * tankRadius);
	}
        testPos[2] = onGroundOnly ? 0.0f : ((float)bzfrand() * maxWorldHeight);
      }
      tries++;

      int type = world->inBuilding(&building, testPos[0], testPos[1], testPos[2],
                                   tankRadius, tankHeight);

      if (onGroundOnly) {
        if (type == NOT_IN_BUILDING)
          foundspot = true;
      } else {
        if ((type == NOT_IN_BUILDING) && (testPos[2] > 0.0f)) {
          testPos[2] = 0.0f;
          //Find any intersection regardless of z
          type = world->inBuilding(&building, testPos[0], testPos[1], testPos[2],
                                   tankRadius, maxWorldHeight);
        }

        // in a building? try climbing on roof until on top
        int lastType = type;
	int retriesRemaining = 100; // don't climb forever
        while (type != NOT_IN_BUILDING) {
          testPos[2] = building->pos[2] + building->size[2] + 0.0001f;
          tries++;
          lastType = type;
          type = world->inBuilding(&building, testPos[0], testPos[1], testPos[2],
                                   tankRadius, tankHeight);
	  if (--retriesRemaining <= 0) {
	    DEBUG1("Warning: getSpawnLocation had to climb too many buildings\n");
	    break;
	  }
        }
        // ok, when not on top of pyramid or teleporter
        if (lastType != IN_PYRAMID  &&  lastType != IN_TELEPORTER) {
          foundspot = true;
        }
        // only try up in the sky so many times
        if (--inAirAttempts <= 0) {
          onGroundOnly = true;
        }
      }

      // check every now and then if we have already used up 10ms of time
      if (tries >= 50) {
        tries = 0;
        if (TimeKeeper::getCurrent() - start > 0.01f) {
          if (bestDist < 0.0f) { // haven't found a single spot
            //Just drop the sucka in, and pray
            pos[0] = testPos[0];
            pos[1] = testPos[1];
            pos[2] = maxWorldHeight;
	    DEBUG1("Warning: getSpawnLocation ran out of time, just dropping the sucker in\n");
          }
          break;
        }
      }

      // check if spot is safe enough
      bool dangerous = isImminentlyDangerous();
      if (foundspot && !dangerous) {
	float enemyAngle;
	float dist = enemyProximityCheck(enemyAngle);
	if (dist > bestDist) { // best so far
	  bestDist = dist;
	  pos[0] = testPos[0];
	  pos[1] = testPos[1];
	  pos[2] = testPos[2];
	  azimuth = fmod((enemyAngle + M_PI), 2.0f * M_PI);
	}
	if (bestDist < minProximity) { // not good enough, keep looking
	  foundspot = false;
	  minProximity *= 0.99f; // relax requirements a little
	}
      } else if (dangerous) {
	foundspot = false;
      }
    }
  }
}

SpawnPosition::~SpawnPosition()
{
}

const bool SpawnPosition::isFacing(const float *enemyPos, const float enemyAzimuth,
				   const float deviation) const
{
  // determine angle from source to dest
  // (X) using only x & y, resultant will be z rotation
  float dx = testPos[0] - enemyPos[0];
  float dy = testPos[1] - enemyPos[1];
  float angActual;
  if (dx == 0) {
    // avoid divide by zero error
    angActual = (float)tan(dy / (1 / 1e12f));
  } else {
    angActual = (float)tan(dy / dx);
  }

  // see if our heading angle is within the bounds set by deviation
  // (X) only compare to z-rotation since that's all we're using
  if (((angActual + deviation / 2) > enemyAzimuth) &&
      ((angActual - deviation / 2) < enemyAzimuth)) {
    return true;
  } else {
    return false;
  }
}

const bool SpawnPosition::isImminentlyDangerous() const
{
  for (int i = 0; i < curMaxPlayers; i++) {
    if (player[i].isAlive()) {
      float *enemyPos = lastState[i].pos;
      float enemyAngle = lastState[i].azimuth;
      if (player[i].getFlag() >= 0) {
	// check for dangerous flags
      	const FlagInfo *finfo =&flag[player[i].getFlag()];
      	const FlagType *ftype = finfo->flag.type;
  	// FIXME: any more?
      	if (ftype == Flags::Laser) {  // don't spawn in the line of sight of an L
	  if (isFacing(enemyPos, enemyAngle, M_PI / 9)) { // he's looking within 20 degrees of spawn point
	    return true;	// eek, don't spawn here
	  }
      	} else if (ftype == Flags::ShockWave) {  // don't spawn next to a SW
	  if (distanceFrom(enemyPos) < safeSWRadius) { // too close to SW
	    return true;	// eek, don't spawn here
	  }
        }
      }
      // don't spawn in the line of sight of a normal-shot tank within a certain distance
      if (distanceFrom(enemyPos) < safeDistance) { // within danger zone?
	if (isFacing(enemyPos, enemyAngle, M_PI / 9)) { //and he's looking at me
	  return true;
	}
      }
    }
  }

  // TODO: should check world weapons also

  return false;
}

const float SpawnPosition::enemyProximityCheck(float &enemyAngle) const
{
  float worstDist = 1e12f; // huge number
  bool noEnemy    = true;

  for (int i = 0; i < curMaxPlayers; i++) {
    if (player[i].isAlive() && areFoes(player[i].getTeam(), team)) {
      float *enemyPos = lastState[i].pos;
      if (fabs(enemyPos[2] - testPos[2]) < 1.0f) {
        float x = enemyPos[0] - testPos[0];
        float y = enemyPos[1] - testPos[1];
        float distSq = x * x + y * y;
        if (distSq < worstDist) {
          worstDist  = distSq;
	  enemyAngle = lastState[i].azimuth;
	  noEnemy    = false;
	}
      }
    }
  }
  if (noEnemy)
    enemyAngle = (float)bzfrand() * 2.0f * M_PI;
  return sqrtf(worstDist);
}

const float SpawnPosition::distanceFrom(const float* farPos) const
{
  float dx = farPos[0] - testPos[0];
  float dy = farPos[1] - testPos[1];
  float dz = farPos[2] - testPos[2];
  return (float)sqrt(dx*dx + dy*dy + dz*dz);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/magnet_uri.hpp"

int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
{
	ec.clear();
	FILE* f = fopen(filename.c_str(), "rb");
	if (f == NULL)
	{
		ec.assign(errno, boost::system::get_generic_category());
		return -1;
	}

	int r = fseek(f, 0, SEEK_END);
	if (r != 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}
	long s = ftell(f);
	if (s < 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	if (s > limit)
	{
		fclose(f);
		return -2;
	}

	r = fseek(f, 0, SEEK_SET);
	if (r != 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	v.resize(s);
	if (s == 0)
	{
		fclose(f);
		return 0;
	}

	r = fread(&v[0], 1, v.size(), f);
	if (r < 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	fclose(f);

	if (r != s) return -3;

	return 0;
}

int line_longer_than(libtorrent::lazy_entry const& e, int limit)
{
	using namespace libtorrent;

	int line_len = 0;
	switch (e.type())
	{
	case lazy_entry::list_t:
		line_len += 4;
		if (line_len > limit) return -1;
		for (int i = 0; i < e.list_size(); ++i)
		{
			int ret = line_longer_than(*e.list_at(i), limit - line_len);
			if (ret == -1) return -1;
			line_len += ret + 2;
		}
		break;
	case lazy_entry::dict_t:
		line_len += 4;
		if (line_len > limit) return -1;
		for (int i = 0; i < e.dict_size(); ++i)
		{
			line_len += 4 + e.dict_at(i).first.size();
			if (line_len > limit) return -1;
			int ret = line_longer_than(*e.dict_at(i).second, limit - line_len);
			if (ret == -1) return -1;
			line_len += ret + 1;
		}
		break;
	case lazy_entry::string_t:
		line_len += 3 + e.string_length();
		break;
	case lazy_entry::int_t:
	{
		size_type val = e.int_value();
		while (val > 0)
		{
			++line_len;
			val /= 10;
		}
		line_len += 2;
	}
	break;
	case lazy_entry::none_t:
		line_len += 4;
		break;
	}

	if (line_len > limit) return -1;
	return line_len;
}

std::string print_entry(libtorrent::lazy_entry const& e, bool single_line = false, int indent = 0)
{
	using namespace libtorrent;

	char indent_str[200];
	memset(indent_str, ' ', 200);
	indent_str[0] = ',';
	indent_str[1] = '\n';
	indent_str[199] = 0;
	if (indent < 197 && indent >= 0) indent_str[indent+2] = 0;
	std::string ret;
	switch (e.type())
	{
		case lazy_entry::none_t: return "none";
		case lazy_entry::int_t:
		{
			char str[100];
			snprintf(str, sizeof(str), "%"PRId64, e.int_value());
			return str;
		}
		case lazy_entry::string_t:
		{
			bool printable = true;
			char const* str = e.string_ptr();
			for (int i = 0; i < e.string_length(); ++i)
			{
				using namespace std;
				if (is_print((unsigned char)str[i])) continue;
				printable = false;
				break;
			}
			ret += "'";
			if (printable)
			{
				ret += e.string_value();
				ret += "'";
				return ret;
			}
			for (int i = 0; i < e.string_length(); ++i)
			{
				char tmp[5];
				snprintf(tmp, sizeof(tmp), "%02x", (unsigned char)str[i]);
				ret += tmp;
			}
			ret += "'";
			return ret;
		}
		case lazy_entry::list_t:
		{
			ret += '[';
			bool one_liner = line_longer_than(e, 200) != -1 || single_line;

			if (!one_liner) ret += indent_str + 1;
			for (int i = 0; i < e.list_size(); ++i)
			{
				if (i == 0 && one_liner) ret += " ";
				ret += ::print_entry(*e.list_at(i), single_line, indent + 2);
				if (i < e.list_size() - 1) ret += (one_liner?", ":indent_str);
				else ret += (one_liner?" ":indent_str+1);
			}
			ret += "]";
			return ret;
		}
		case lazy_entry::dict_t:
		{
			ret += "{";
			bool one_liner = line_longer_than(e, 200) != -1 || single_line;

			if (!one_liner) ret += indent_str+1;
			for (int i = 0; i < e.dict_size(); ++i)
			{
				if (i == 0 && one_liner) ret += " ";
				std::pair<std::string, lazy_entry const*> ent = e.dict_at(i);
				ret += "'";
				ret += ent.first;
				ret += "': ";
				ret += ::print_entry(*ent.second, single_line, indent + 2);
				if (i < e.dict_size() - 1) ret += (one_liner?", ":indent_str);
				else ret += (one_liner?" ":indent_str+1);
			}
			ret += "}";
			return ret;
		}
	}
	return ret;
}

int main(int argc, char* argv[])
{
	using namespace libtorrent;

	if (argc < 2 || argc > 4)
	{
		fputs("usage: dump_torrent torrent-file [total-items-limit] [recursion-limit]\n", stderr);
		return 1;
	}

	int item_limit = 1000000;
	int depth_limit = 1000;

	if (argc > 2) item_limit = atoi(argv[2]);
	if (argc > 3) depth_limit = atoi(argv[3]);

	int size = file_size(argv[1]);
	if (size > 40 * 1000000)
	{
		fprintf(stderr, "file too big (%d), aborting\n", size);
		return 1;
	}
	std::vector<char> buf(size);
	error_code ec;
	int ret = load_file(argv[1], buf, ec, 40 * 1000000);
	if (ret != 0)
	{
		fprintf(stderr, "failed to load file: %s\n", ec.message().c_str());
		return 1;
	}
	lazy_entry e;
	int pos;
	printf("decoding. recursion limit: %d total item count limit: %d\n"
		, depth_limit, item_limit);
	ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec, &pos
		, depth_limit, item_limit);

	printf("\n\n----- raw info -----\n\n%s\n", ::print_entry(e).c_str());

	if (ret != 0)
	{
		fprintf(stderr, "failed to decode: '%s' at character: %d\n", ec.message().c_str(), pos);
		return 1;
	}

	torrent_info t(e, ec);
	if (ec)
	{
		fprintf(stderr, "%s\n", ec.message().c_str());
		return 1;
	}
	e.clear();
	std::vector<char>().swap(buf);

	// print info about torrent
	printf("\n\n----- torrent file info -----\n\n"
		"nodes:\n");

	typedef std::vector<std::pair<std::string, int> > node_vec;
	node_vec const& nodes = t.nodes();
	for (node_vec::const_iterator i = nodes.begin(), end(nodes.end());
		i != end; ++i)
	{
		printf("%s: %d\n", i->first.c_str(), i->second);
	}
	puts("trackers:\n");
	for (std::vector<announce_entry>::const_iterator i = t.trackers().begin();
		i != t.trackers().end(); ++i)
	{
		printf("%2d: %s\n", i->tier, i->url.c_str());
	}

	char ih[41];
	to_hex((char const*)&t.info_hash()[0], 20, ih);
	printf("number of pieces: %d\n"
		"piece length: %d\n"
		"info hash: %s\n"
		"comment: %s\n"
		"created by: %s\n"
		"magnet link: %s\n"
		"name: %s\n"
		"number of files: %d\n"
		"files:\n"
		, t.num_pieces()
		, t.piece_length()
		, ih
		, t.comment().c_str()
		, t.creator().c_str()
		, make_magnet_uri(t).c_str()
		, t.name().c_str()
		, t.num_files());
	int index = 0;
	for (torrent_info::file_iterator i = t.begin_files();
		i != t.end_files(); ++i, ++index)
	{
		int first = t.map_file(index, 0, 0).piece;
		int last = t.map_file(index, (std::max)(size_type(i->size)-1, size_type(0)), 0).piece;
		printf(" %8"PRIx64" %11"PRId64" %c%c%c%c [ %5d, %5d ] %7u %s %s %s%s\n"
			, i->offset
			, i->size
			, (i->pad_file?'p':'-')
			, (i->executable_attribute?'x':'-')
			, (i->hidden_attribute?'h':'-')
			, (i->symlink_attribute?'l':'-')
			, first, last
			, boost::uint32_t(t.files().mtime(*i))
			, t.files().hash(*i) != sha1_hash(0) ? to_hex(t.files().hash(*i).to_string()).c_str() : ""
			, t.files().file_path(*i).c_str()
			, i->symlink_attribute ? "-> ": ""
			, i->symlink_attribute && i->symlink_index != -1 ? t.files().symlink(*i).c_str() : "");
	}

	return 0;
}

<commit_msg>make dump_torrent build without deprecated functions<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/magnet_uri.hpp"

int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
{
	ec.clear();
	FILE* f = fopen(filename.c_str(), "rb");
	if (f == NULL)
	{
		ec.assign(errno, boost::system::get_generic_category());
		return -1;
	}

	int r = fseek(f, 0, SEEK_END);
	if (r != 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}
	long s = ftell(f);
	if (s < 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	if (s > limit)
	{
		fclose(f);
		return -2;
	}

	r = fseek(f, 0, SEEK_SET);
	if (r != 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	v.resize(s);
	if (s == 0)
	{
		fclose(f);
		return 0;
	}

	r = fread(&v[0], 1, v.size(), f);
	if (r < 0)
	{
		ec.assign(errno, boost::system::get_generic_category());
		fclose(f);
		return -1;
	}

	fclose(f);

	if (r != s) return -3;

	return 0;
}

int line_longer_than(libtorrent::lazy_entry const& e, int limit)
{
	using namespace libtorrent;

	int line_len = 0;
	switch (e.type())
	{
	case lazy_entry::list_t:
		line_len += 4;
		if (line_len > limit) return -1;
		for (int i = 0; i < e.list_size(); ++i)
		{
			int ret = line_longer_than(*e.list_at(i), limit - line_len);
			if (ret == -1) return -1;
			line_len += ret + 2;
		}
		break;
	case lazy_entry::dict_t:
		line_len += 4;
		if (line_len > limit) return -1;
		for (int i = 0; i < e.dict_size(); ++i)
		{
			line_len += 4 + e.dict_at(i).first.size();
			if (line_len > limit) return -1;
			int ret = line_longer_than(*e.dict_at(i).second, limit - line_len);
			if (ret == -1) return -1;
			line_len += ret + 1;
		}
		break;
	case lazy_entry::string_t:
		line_len += 3 + e.string_length();
		break;
	case lazy_entry::int_t:
	{
		size_type val = e.int_value();
		while (val > 0)
		{
			++line_len;
			val /= 10;
		}
		line_len += 2;
	}
	break;
	case lazy_entry::none_t:
		line_len += 4;
		break;
	}

	if (line_len > limit) return -1;
	return line_len;
}

std::string print_entry(libtorrent::lazy_entry const& e, bool single_line = false, int indent = 0)
{
	using namespace libtorrent;

	char indent_str[200];
	memset(indent_str, ' ', 200);
	indent_str[0] = ',';
	indent_str[1] = '\n';
	indent_str[199] = 0;
	if (indent < 197 && indent >= 0) indent_str[indent+2] = 0;
	std::string ret;
	switch (e.type())
	{
		case lazy_entry::none_t: return "none";
		case lazy_entry::int_t:
		{
			char str[100];
			snprintf(str, sizeof(str), "%"PRId64, e.int_value());
			return str;
		}
		case lazy_entry::string_t:
		{
			bool printable = true;
			char const* str = e.string_ptr();
			for (int i = 0; i < e.string_length(); ++i)
			{
				using namespace std;
				if (is_print((unsigned char)str[i])) continue;
				printable = false;
				break;
			}
			ret += "'";
			if (printable)
			{
				ret += e.string_value();
				ret += "'";
				return ret;
			}
			for (int i = 0; i < e.string_length(); ++i)
			{
				char tmp[5];
				snprintf(tmp, sizeof(tmp), "%02x", (unsigned char)str[i]);
				ret += tmp;
			}
			ret += "'";
			return ret;
		}
		case lazy_entry::list_t:
		{
			ret += '[';
			bool one_liner = line_longer_than(e, 200) != -1 || single_line;

			if (!one_liner) ret += indent_str + 1;
			for (int i = 0; i < e.list_size(); ++i)
			{
				if (i == 0 && one_liner) ret += " ";
				ret += ::print_entry(*e.list_at(i), single_line, indent + 2);
				if (i < e.list_size() - 1) ret += (one_liner?", ":indent_str);
				else ret += (one_liner?" ":indent_str+1);
			}
			ret += "]";
			return ret;
		}
		case lazy_entry::dict_t:
		{
			ret += "{";
			bool one_liner = line_longer_than(e, 200) != -1 || single_line;

			if (!one_liner) ret += indent_str+1;
			for (int i = 0; i < e.dict_size(); ++i)
			{
				if (i == 0 && one_liner) ret += " ";
				std::pair<std::string, lazy_entry const*> ent = e.dict_at(i);
				ret += "'";
				ret += ent.first;
				ret += "': ";
				ret += ::print_entry(*ent.second, single_line, indent + 2);
				if (i < e.dict_size() - 1) ret += (one_liner?", ":indent_str);
				else ret += (one_liner?" ":indent_str+1);
			}
			ret += "}";
			return ret;
		}
	}
	return ret;
}

int main(int argc, char* argv[])
{
	using namespace libtorrent;

	if (argc < 2 || argc > 4)
	{
		fputs("usage: dump_torrent torrent-file [total-items-limit] [recursion-limit]\n", stderr);
		return 1;
	}

	int item_limit = 1000000;
	int depth_limit = 1000;

	if (argc > 2) item_limit = atoi(argv[2]);
	if (argc > 3) depth_limit = atoi(argv[3]);

	int size = file_size(argv[1]);
	if (size > 40 * 1000000)
	{
		fprintf(stderr, "file too big (%d), aborting\n", size);
		return 1;
	}
	std::vector<char> buf(size);
	error_code ec;
	int ret = load_file(argv[1], buf, ec, 40 * 1000000);
	if (ret != 0)
	{
		fprintf(stderr, "failed to load file: %s\n", ec.message().c_str());
		return 1;
	}
	lazy_entry e;
	int pos;
	printf("decoding. recursion limit: %d total item count limit: %d\n"
		, depth_limit, item_limit);
	ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec, &pos
		, depth_limit, item_limit);

	printf("\n\n----- raw info -----\n\n%s\n", ::print_entry(e).c_str());

	if (ret != 0)
	{
		fprintf(stderr, "failed to decode: '%s' at character: %d\n", ec.message().c_str(), pos);
		return 1;
	}

	torrent_info t(e, ec);
	if (ec)
	{
		fprintf(stderr, "%s\n", ec.message().c_str());
		return 1;
	}
	e.clear();
	std::vector<char>().swap(buf);

	// print info about torrent
	printf("\n\n----- torrent file info -----\n\n"
		"nodes:\n");

	typedef std::vector<std::pair<std::string, int> > node_vec;
	node_vec const& nodes = t.nodes();
	for (node_vec::const_iterator i = nodes.begin(), end(nodes.end());
		i != end; ++i)
	{
		printf("%s: %d\n", i->first.c_str(), i->second);
	}
	puts("trackers:\n");
	for (std::vector<announce_entry>::const_iterator i = t.trackers().begin();
		i != t.trackers().end(); ++i)
	{
		printf("%2d: %s\n", i->tier, i->url.c_str());
	}

	char ih[41];
	to_hex((char const*)&t.info_hash()[0], 20, ih);
	printf("number of pieces: %d\n"
		"piece length: %d\n"
		"info hash: %s\n"
		"comment: %s\n"
		"created by: %s\n"
		"magnet link: %s\n"
		"name: %s\n"
		"number of files: %d\n"
		"files:\n"
		, t.num_pieces()
		, t.piece_length()
		, ih
		, t.comment().c_str()
		, t.creator().c_str()
		, make_magnet_uri(t).c_str()
		, t.name().c_str()
		, t.num_files());
	file_storage const& st = t.files();
	for (int i = 0; i < st.num_files(); ++i)
	{
		int first = st.map_file(i, 0, 0).piece;
		int last = st.map_file(i, (std::max)(size_type(st.file_size(i))-1, size_type(0)), 0).piece;
		int flags = st.file_flags(i);
		printf(" %8" PRIx64 " %11" PRId64 " %c%c%c%c [ %5d, %5d ] %7u %s %s %s%s\n"
			, st.file_offset(i)
			, st.file_size(i)
			, ((flags & file_storage::flag_pad_file)?'p':'-')
			, ((flags & file_storage::flag_executable)?'x':'-')
			, ((flags & file_storage::flag_hidden)?'h':'-')
			, ((flags & file_storage::flag_symlink)?'l':'-')
			, first, last
			, boost::uint32_t(st.mtime(i))
			, st.hash(i) != sha1_hash(0) ? to_hex(st.hash(i).to_string()).c_str() : ""
			, st.file_path(i).c_str()
			, (flags & file_storage::flag_symlink) ? "-> " : ""
			, (flags & file_storage::flag_symlink) ? st.symlink(i).c_str() : "");
	}

	return 0;
}

<|endoftext|>