<commit_before>/*
Copyright 2015 Esri
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.
A local copy of the license and additional notices are located with the
source distribution at:
http://github.com/Esri/lerc/
Contributors:  Thomas Maurer
*/
#include "RLE.h"
#include <cstring>

NAMESPACE_MRF_START

// -------------------------------------------------------------------------- ;

size_t RLE::computeNumBytesRLE(const Byte* arr, size_t numBytes) const
{
  if (arr == NULL || numBytes == 0)
    return 0;

  const Byte* ptr = arr;
  size_t sum = 0;
  size_t cntOdd = 0;
  size_t cntEven = 0;
  size_t cntTotal = 0;
  bool bOdd = true;

  while (cntTotal < numBytes - 1)
  {
    if (*ptr != *(ptr + 1))
    {
      if (bOdd)
      {
        cntOdd++;
      }
      else    // switch to odd mode
      {
        cntEven++;
        sum += 2 + 1;
        bOdd = true;
        cntOdd = 0;
        cntEven = 0;
      }
    }
    else
    {
      if (!bOdd)
      {
        cntEven++;
      }
      else
      {
        // count if we have enough equal bytes so it is worth switching to even
        bool foundEnough = false;
        if (cntTotal + m_minNumEven < numBytes)
        {
          int i = 1;
          while (i < m_minNumEven && ptr[i] == ptr[0]) i++;
          foundEnough = i < m_minNumEven ? false : true;
        }

        if (!foundEnough)    // stay in odd mode
        {
          cntOdd++;
        }
        else    // switch to even mode
        {
          if (cntOdd > 0)
            sum += 2 + cntOdd;
          bOdd = false;
          cntOdd = 0;
          cntEven = 0;
          cntEven++;
        }
      }
    }
    ptr++;
    cntTotal++;

    if (cntOdd == 32767)    // prevent short counters from overflow
    {
      sum += 2 + 32767;
      cntOdd = 0;
    }
    if (cntEven == 32767)
    {
      sum += 2 + 1;
      cntEven = 0;
    }
  }

  // don't forget the last byte
  if (bOdd)
  {
    cntOdd++;
    sum += 2 + cntOdd;
  }
  else
  {
    cntEven++;
    sum += 2 + 1;
  }

  return sum + 2;    // EOF short
}

// -------------------------------------------------------------------------- ;

bool RLE::compress(const Byte* arr, size_t numBytes,
                   Byte** arrRLE, size_t& numBytesRLE, bool verify) const
{
  if (arr == NULL || numBytes == 0)
    return false;

  numBytesRLE = computeNumBytesRLE(arr, numBytes);

  *arrRLE = new Byte[numBytesRLE];
  if (!*arrRLE)
    return false;

  const Byte* srcPtr = arr;
  Byte* cntPtr = *arrRLE;
  Byte* dstPtr = cntPtr + 2;
  /*size_t sum = 0;*/
  size_t cntOdd = 0;
  size_t cntEven = 0;
  size_t cntTotal = 0;
  bool bOdd = true;

  while (cntTotal < numBytes - 1)
  {
    if (*srcPtr != *(srcPtr + 1))
    {
      *dstPtr++ = *srcPtr;
      if (bOdd)
      {
        cntOdd++;
      }
      else    // switch to odd mode
      {
        cntEven++;
        writeCount(-(short)cntEven, &cntPtr, &dstPtr);    // - sign for even cnts
        /*sum += 2 + 1;*/
        bOdd = true;
        cntOdd = 0;
        cntEven = 0;
      }
    }
    else
    {
      if (!bOdd)
      {
        cntEven++;
      }
      else
      {
        // count if we have enough equal bytes so it is worth switching to even
        bool foundEnough = false;
        if (cntTotal + m_minNumEven < numBytes)
        {
          int i = 1;
          while (i < m_minNumEven && srcPtr[i] == srcPtr[0]) i++;
          foundEnough = i < m_minNumEven ? false : true;
        }

        if (!foundEnough)    // stay in odd mode
        {
          *dstPtr++ = *srcPtr;
          cntOdd++;
        }
        else    // switch to even mode
        {
          if (cntOdd > 0)
          {
            writeCount((short)cntOdd, &cntPtr, &dstPtr);    // + sign for odd cnts
            /*sum += 2 + cntOdd;*/
          }
          bOdd = false;
          cntOdd = 0;
          cntEven = 0;
          cntEven++;
        }
      }
    }

    if (cntOdd == 32767)    // prevent short counters from overflow
    {
      writeCount((short)cntOdd, &cntPtr, &dstPtr);
      /*sum += 2 + 32767;*/
      cntOdd = 0;
    }
    if (cntEven == 32767)
    {
      *dstPtr++ = *srcPtr;
      writeCount(-(short)cntEven, &cntPtr, &dstPtr);
      /*sum += 2 + 1;*/
      cntEven = 0;
    }

    srcPtr++;
    cntTotal++;
  }

  // don't forget the last byte
  *dstPtr++ = *srcPtr;
  if (bOdd)
  {
    cntOdd++;
    writeCount((short)cntOdd, &cntPtr, &dstPtr);
    /*sum += 2 + cntOdd;*/
  }
  else
  {
    cntEven++;
    writeCount(-(short)cntEven, &cntPtr, &dstPtr);
    /*sum += 2 + 1;*/
  }

  writeCount(-32768, &cntPtr, &dstPtr);    // write end of stream symbol
  /*sum += 2;*/

  if (verify)
  {
    Byte* arr2 = NULL;
    size_t numBytes2 = 0;
    if (!decompress(*arrRLE, &arr2, numBytes2) || numBytes2 != numBytes)
    {
      delete[] arr2;
      return false;
    }
    int nCheck = memcmp(arr, arr2, numBytes);
    delete[] arr2;
    if (nCheck != 0)
      return false;
  }

  return true;
}

// -------------------------------------------------------------------------- ;

bool RLE::decompress(const Byte* arrRLE, Byte** arr, size_t& numBytes) const
{
  if (!arrRLE)
    return false;

  // first count the encoded bytes
  const Byte* srcPtr = arrRLE;
  size_t sum = 0;
  short cnt = readCount(&srcPtr);
  while (cnt != -32768)
  {
    sum += (cnt < 0) ? -cnt : cnt;
    srcPtr += (cnt > 0) ? cnt : 1;
    cnt = readCount(&srcPtr);
  }

  numBytes = sum;
  *arr = new Byte[numBytes];
  if (!*arr)
    return false;

  return decompress(arrRLE, *arr);
}

// -------------------------------------------------------------------------- ;

bool RLE::decompress(const Byte* arrRLE, Byte* arr) const
{
  if (!arrRLE || !arr)
    return false;

  const Byte* srcPtr = arrRLE;
  Byte* dstPtr = arr;
  short cnt = readCount(&srcPtr);
  while (cnt != -32768)
  {
    int i = (cnt < 0) ? -cnt: cnt ;
    if (cnt > 0)
      while (i--) *dstPtr++ = *srcPtr++;
    else
    {
      Byte b = *srcPtr++;
      while (i--) *dstPtr++ = b;
    }
    cnt = readCount(&srcPtr);
  }

  return true;
}

// -------------------------------------------------------------------------- ;

void RLE::writeCount(short cnt, Byte** ppCnt, Byte** ppDst) const
{
  SWAP_2(cnt);    // write short's in little endian byte order, always
  memcpy(*ppCnt, &cnt, sizeof(short));
  *ppCnt = *ppDst;
  *ppDst += 2;
}

// -------------------------------------------------------------------------- ;

short RLE::readCount(const Byte** ppCnt) const
{
  short cnt;
  memcpy(&cnt, *ppCnt, sizeof(short));
  SWAP_2(cnt);
  *ppCnt += 2;
  return cnt;
}

// -------------------------------------------------------------------------- ;

NAMESPACE_MRF_END
<commit_msg>GDAL integration #54<commit_after>/*
Copyright 2015 Esri
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.
A local copy of the license and additional notices are located with the
source distribution at:
http://github.com/Esri/lerc/
Contributors:  Thomas Maurer
*/
#include "RLE.h"
#include <cstring>

NAMESPACE_MRF_START

// -------------------------------------------------------------------------- ;

size_t RLE::computeNumBytesRLE(const Byte* arr, size_t numBytes) const
{
  if (arr == NULL || numBytes == 0)
    return 0;

  const Byte* ptr = arr;
  size_t sum = 0;
  size_t cntOdd = 0;
  size_t cntEven = 0;
  size_t cntTotal = 0;
  bool bOdd = true;

  while (cntTotal < numBytes - 1)
  {
    if (*ptr != *(ptr + 1))
    {
      if (bOdd)
      {
        cntOdd++;
      }
      else    // switch to odd mode
      {
        cntEven++;
        sum += 2 + 1;
        bOdd = true;
        cntOdd = 0;
        cntEven = 0;
      }
    }
    else
    {
      if (!bOdd)
      {
        cntEven++;
      }
      else
      {
        // count if we have enough equal bytes so it is worth switching to even
        bool foundEnough = false;
        if (cntTotal + m_minNumEven < numBytes)
        {
          int i = 1;
          while (i < m_minNumEven && ptr[i] == ptr[0]) i++;
          foundEnough = i < m_minNumEven ? false : true;
        }

        if (!foundEnough)    // stay in odd mode
        {
          cntOdd++;
        }
        else    // switch to even mode
        {
          if (cntOdd > 0)
            sum += 2 + cntOdd;
          bOdd = false;
          cntOdd = 0;
          cntEven = 0;
          cntEven++;
        }
      }
    }
    ptr++;
    cntTotal++;

    if (cntOdd == 32767)    // prevent short counters from overflow
    {
      sum += 2 + 32767;
      cntOdd = 0;
    }
    if (cntEven == 32767)
    {
      sum += 2 + 1;
      cntEven = 0;
    }
  }

  // don't forget the last byte
  if (bOdd)
  {
    cntOdd++;
    sum += 2 + cntOdd;
  }
  else
  {
    cntEven++;
    sum += 2 + 1;
  }

  return sum + 2;    // EOF short
}

// -------------------------------------------------------------------------- ;

bool RLE::compress(const Byte* arr, size_t numBytes,
                   Byte** arrRLE, size_t& numBytesRLE, bool verify) const
{
  if (arr == NULL || numBytes == 0)
    return false;

  numBytesRLE = computeNumBytesRLE(arr, numBytes);

  *arrRLE = new Byte[numBytesRLE];
  if (!*arrRLE)
    return false;

  const Byte* srcPtr = arr;
  Byte* cntPtr = *arrRLE;
  Byte* dstPtr = cntPtr + 2;
  /*size_t sum = 0;*/
  size_t cntOdd = 0;
  size_t cntEven = 0;
  size_t cntTotal = 0;
  bool bOdd = true;

  while (cntTotal < numBytes - 1)
  {
    if (*srcPtr != *(srcPtr + 1))
    {
      *dstPtr++ = *srcPtr;
      if (bOdd)
      {
        cntOdd++;
      }
      else    // switch to odd mode
      {
        cntEven++;
        writeCount(-(short)cntEven, &cntPtr, &dstPtr);    // - sign for even cnts
        /*sum += 2 + 1;*/
        bOdd = true;
        cntOdd = 0;
        cntEven = 0;
      }
    }
    else
    {
      if (!bOdd)
      {
        cntEven++;
      }
      else
      {
        // count if we have enough equal bytes so it is worth switching to even
        bool foundEnough = false;
        if (cntTotal + m_minNumEven < numBytes)
        {
          int i = 1;
          while (i < m_minNumEven && srcPtr[i] == srcPtr[0]) i++;
          foundEnough = i < m_minNumEven ? false : true;
        }

        if (!foundEnough)    // stay in odd mode
        {
          *dstPtr++ = *srcPtr;
          cntOdd++;
        }
        else    // switch to even mode
        {
          if (cntOdd > 0)
          {
            writeCount((short)cntOdd, &cntPtr, &dstPtr);    // + sign for odd cnts
            /*sum += 2 + cntOdd;*/
          }
          bOdd = false;
          cntOdd = 0;
          cntEven = 0;
          cntEven++;
        }
      }
    }

    if (cntOdd == 32767)    // prevent short counters from overflow
    {
      writeCount((short)cntOdd, &cntPtr, &dstPtr);
      /*sum += 2 + 32767;*/
      cntOdd = 0;
    }
    if (cntEven == 32767)
    {
      *dstPtr++ = *srcPtr;
      writeCount(-(short)cntEven, &cntPtr, &dstPtr);
      /*sum += 2 + 1;*/
      cntEven = 0;
    }

    srcPtr++;
    cntTotal++;
  }

  // don't forget the last byte
  *dstPtr++ = *srcPtr;
  if (bOdd)
  {
    cntOdd++;
    writeCount((short)cntOdd, &cntPtr, &dstPtr);
    /*sum += 2 + cntOdd;*/
  }
  else
  {
    cntEven++;
    writeCount(-(short)cntEven, &cntPtr, &dstPtr);
    /*sum += 2 + 1;*/
  }

  writeCount(-32768, &cntPtr, &dstPtr);    // write end of stream symbol
  /*sum += 2;*/

  if (verify)
  {
    Byte* arr2 = NULL;
    size_t numBytes2 = 0;
    if (!decompress(*arrRLE, &arr2, numBytes2) || numBytes2 != numBytes)
    {
      delete[] arr2;
      return false;
    }
    int nCheck = memcmp(arr, arr2, numBytes);
    delete[] arr2;
    if (nCheck != 0)
      return false;
  }

  return true;
}

// -------------------------------------------------------------------------- ;

bool RLE::decompress(const Byte* arrRLE, Byte** arr, size_t& numBytes) const
{
  if (!arrRLE)
    return false;

  // first count the encoded bytes
  const Byte* srcPtr = arrRLE;
  size_t sum = 0;
  short cnt = readCount(&srcPtr);
  while (cnt != -32768)
  {
    sum += (cnt < 0) ? -cnt : cnt;
    srcPtr += (cnt > 0) ? cnt : 1;
    cnt = readCount(&srcPtr);
  }

  numBytes = sum;
  if( numBytes == 0 )
  {
    *arr = NULL;
    return true;
  }
  *arr = new Byte[numBytes];
  if (!*arr)
    return false;

  return decompress(arrRLE, *arr);
}

// -------------------------------------------------------------------------- ;

bool RLE::decompress(const Byte* arrRLE, Byte* arr) const
{
  if (!arrRLE || !arr)
    return false;

  const Byte* srcPtr = arrRLE;
  Byte* dstPtr = arr;
  short cnt = readCount(&srcPtr);
  while (cnt != -32768)
  {
    int i = (cnt < 0) ? -cnt: cnt ;
    if (cnt > 0)
      while (i--) *dstPtr++ = *srcPtr++;
    else
    {
      Byte b = *srcPtr++;
      while (i--) *dstPtr++ = b;
    }
    cnt = readCount(&srcPtr);
  }

  return true;
}

// -------------------------------------------------------------------------- ;

void RLE::writeCount(short cnt, Byte** ppCnt, Byte** ppDst) const
{
  SWAP_2(cnt);    // write short's in little endian byte order, always
  memcpy(*ppCnt, &cnt, sizeof(short));
  *ppCnt = *ppDst;
  *ppDst += 2;
}

// -------------------------------------------------------------------------- ;

short RLE::readCount(const Byte** ppCnt) const
{
  short cnt;
  memcpy(&cnt, *ppCnt, sizeof(short));
  SWAP_2(cnt);
  *ppCnt += 2;
  return cnt;
}

// -------------------------------------------------------------------------- ;

NAMESPACE_MRF_END
<|endoftext|>


<commit_before>/*
* Copyright (C) 2007-2013 German Aerospace Center (DLR/SC)
*
* Created: 2014-05-26 Martin Siggel <Martin.Siggel@dlr.de>
*
* 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 "CTiglMakeLoft.h"
#include "tigl_config.h"

#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
#include <TopExp.hxx>
#include <BRep_Builder.hxx>
#include <BRepLib.hxx>
#include <BRepTools.hxx>
#ifdef LOFTALGO_FOUND
  #include <MakePatches.hxx>
#endif
#include <BRepOffsetAPI_ThruSections.hxx>
#include <BRepBuilderAPI_FindPlane.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include <BRepBuilderAPI_Sewing.hxx>
#include <StdFail_NotDone.hxx>
#include <Precision.hxx>

namespace
{
    TopoDS_Solid MakeSolid(TopoDS_Shape& shell, const TopoDS_Wire& wire1,
                           const TopoDS_Wire& wire2, const Standard_Real presPln,
                           TopoDS_Face& face1, TopoDS_Face& face2);

    TopoDS_Shape MakeShells(TopoDS_Shape& shell, const Standard_Real presPln);
} // namespace

CTiglMakeLoft::CTiglMakeLoft(double tolerance)
{
    _hasPerformed = false;
    _makeSolid = true;
    _result.Nullify();
    _myTolerance = tolerance;
    _makeSmooth = false;
}

CTiglMakeLoft::CTiglMakeLoft(const TopoDS_Shape &profiles, const TopoDS_Shape &guides, double tolerance)
{
    _hasPerformed = false;
    _result.Nullify();
    _myTolerance = tolerance;
    addProfiles(profiles);
    addGuides(guides);
}

void CTiglMakeLoft::addProfiles(const TopoDS_Shape &profiles)
{
    if (profiles.ShapeType() == TopAbs_COMPOUND) {
        for (TopoDS_Iterator anIter(profiles); anIter.More(); anIter.Next()) {
            TopoDS_Wire aSh = TopoDS::Wire(anIter.Value());
            this->profiles.push_back(aSh);
        }
    }
    else {
        this->profiles.push_back(TopoDS::Wire(profiles));
    }
}

void CTiglMakeLoft::addGuides(const TopoDS_Shape &guides)
{
    if (guides.ShapeType() == TopAbs_COMPOUND) {
        for (TopoDS_Iterator anIter(guides); anIter.More(); anIter.Next()) {
            TopoDS_Wire aSh = TopoDS::Wire(anIter.Value());
            this->guides.push_back(aSh);
        }
    }
    else {
        this->guides.push_back(TopoDS::Wire(guides));
    }
}

TopoDS_Shape &CTiglMakeLoft::Shape()
{
    Perform();

    return _result;
}

CTiglMakeLoft::operator TopoDS_Shape &()
{
    return Shape();
}

void CTiglMakeLoft::Perform()
{
    if (_hasPerformed) {
        return;
    }

    if (guides.size() > 0) {
#ifdef LOFTALGO_FOUND
        // to the loft with guides
        makeLoftWithGuides();
#else
        makeLoftWithGuides();
#endif
    }
    else {
        makeLoftWithoutGuides();
    }
    _hasPerformed = true;
}

void CTiglMakeLoft::setMakeSolid(bool enabled)
{
    _makeSolid = enabled;
}

void CTiglMakeLoft::setMakeSmooth(bool enabled)
{
    _makeSmooth = enabled;
}

/**
 * @brief Builds the loft using profiles and guide curves
 */
void CTiglMakeLoft::makeLoftWithGuides()
{
#ifdef LOFTALGO_FOUND
    BRep_Builder b;
    TopoDS_Compound cprof, cguid;
    b.MakeCompound(cprof);
    b.MakeCompound(cguid);

    for (unsigned int i = 0; i < profiles.size(); ++i) {
        TopoDS_Wire& profile =  profiles[i];
        b.Add(cprof, profile);
    }
    for (unsigned int i = 0; i < guides.size(); ++i) {
        TopoDS_Wire& guide =  guides[i];
        b.Add(cguid, guide);
    }

    BRepTools::Write(cprof, "profiles.brep");
    BRepTools::Write(cguid, "guides.brep");

    MakePatches SurfMaker(cguid, cprof);
    // Don't sew yet. We do it later in solid creation
    SurfMaker.Perform(_myTolerance, 1e-4, GeomFill_CoonsC2Style, Standard_False);
    TopoDS_Shape faces = SurfMaker.Patches();
    printf("Status: %d\n" , SurfMaker.GetStatus());

    if (_makeSolid) {
        // check if the first wire is the same as the last
        Standard_Boolean vClosed = (profiles[0].IsSame(profiles[profiles.size()-1]));

        if (vClosed) {
            // we dont need side caps, just make shell and close it
            TopoDS_Shape shell = MakeShells(faces, _myTolerance);

            TopoDS_Solid solid;
            BRep_Builder B;
            B.MakeSolid(solid);
            B.Add(solid, shell);

            // verify the orientation of the solid
            BRepClass3d_SolidClassifier clas3d(solid);
            clas3d.PerformInfinitePoint(Precision::Confusion());
            if (clas3d.State() == TopAbs_IN) {
                B.MakeSolid(solid);
                TopoDS_Shape aLocalShape = faces.Reversed();
                B.Add(solid, TopoDS::Shell(aLocalShape));
            }
            _result = solid;
        }
        else {
            // make solid by adding side caps
            TopoDS_Wire wire1 = TopoDS::Wire(profiles[0]);
            TopoDS_Wire wire2 = TopoDS::Wire(profiles[profiles.size()-1]);
            TopoDS_Face innerCap, outerCap;
            _result = faces;
            _result = MakeSolid(faces, wire1, wire2, 1e-6, innerCap, outerCap);
        }
    }
    else {
        // don't make solid
        _result = MakeShells(faces, 1e-6);
    }
    BRepLib::EncodeRegularity(_result);
#endif // LOFTALGO_FOUND
}

void CTiglMakeLoft::makeLoftWithoutGuides()
{
    bool isRuled = !_makeSmooth;
    BRepOffsetAPI_ThruSections lofter(_makeSolid, isRuled, _myTolerance);
    for (unsigned int i = 0; i < profiles.size(); ++i) {
        TopoDS_Wire& profile =  profiles[i];
        lofter.AddWire(profile);
    }
    lofter.CheckCompatibility(Standard_False);

    if (_makeSmooth) {
        lofter.SetMaxDegree(2); //surfaces will be C1-continuous
        lofter.SetParType(Approx_Centripetal);
    }

    _result = lofter.Shape();
}

namespace
{
    // Creates a face to close a profile
    // Code taken from opencascade, BRepOffsetAPI_ThruSections
    Standard_Boolean CreateSideCap(const TopoDS_Wire& W,
                                   const Standard_Real presPln,
                                   TopoDS_Face& theFace)
    {
        Standard_Boolean isDegen = Standard_True;
        TopoDS_Iterator iter(W);
        for (; iter.More(); iter.Next())
        {
            const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
            if (!BRep_Tool::Degenerated(anEdge))
                isDegen = Standard_False;
        }
        if (isDegen)
            return Standard_True;

        Standard_Boolean Ok = Standard_False;
        if (!W.IsNull()) {
            BRepBuilderAPI_FindPlane Searcher( W, presPln );
            if (Searcher.Found()) {
                theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W);
                Ok = Standard_True;
            }
            else {
                // try to find another surface
                BRepBuilderAPI_MakeFace MF( W );
                if (MF.IsDone())
                {
                    theFace = MF.Face();
                    Ok = Standard_True;
                }
            }
        }

        return Ok;
    }

    // Code adapted from opencascade, BRepOffsetAPI_ThruSections
    TopoDS_Solid MakeSolid(TopoDS_Shape& shell,
                           const TopoDS_Wire& wire1, const TopoDS_Wire& wire2,
                           const Standard_Real presPln,
                           TopoDS_Face& face1, TopoDS_Face& face2)
    {
        if (shell.IsNull()) {
            StdFail_NotDone::Raise("Thrusections is not build");
        }
        Standard_Boolean B = shell.Closed();

        BRepBuilderAPI_Sewing sewingAlgo;
        sewingAlgo.Add(shell);

        if (!B) {
            // It is necessary to close the extremities
            B =  CreateSideCap(wire1, presPln, face1);
            if (B) {
                B =  CreateSideCap(wire2, presPln, face2);
                if (B) {
                    if (!face1.IsNull()) {
                        sewingAlgo.Add(face1);
                    }
                    if (!face2.IsNull()) {
                        sewingAlgo.Add(face2);
                    }
                }
            }
        }

        sewingAlgo.Perform();
        TopoDS_Shape shellClosed  = sewingAlgo.SewedShape();
        shellClosed.Closed(Standard_True);

        // make solid from shell
        TopoDS_Solid solid;
        BRep_Builder solidMaker;
        solidMaker.MakeSolid(solid);
        solidMaker.Add(solid, shellClosed);

        // verify the orientation the solid
        BRepClass3d_SolidClassifier clas3d(solid);
        clas3d.PerformInfinitePoint(Precision::Confusion());
        if (clas3d.State() == TopAbs_IN) {
            solidMaker.MakeSolid(solid);
            TopoDS_Shape aLocalShape = shellClosed.Reversed();
            solidMaker.Add(solid, TopoDS::Shell(aLocalShape));
        }

        solid.Closed(Standard_True);
        return solid;
    }

    TopoDS_Shape MakeShells(TopoDS_Shape& shell, const Standard_Real presPln)
    {
        if (shell.IsNull()) {
            StdFail_NotDone::Raise("Thrusections is not build");
        }

        BRepBuilderAPI_Sewing BB(presPln);
        BB.Add(shell);
        BB.Perform();

        TopoDS_Shape shellClosed  = BB.SewedShape();
        return shellClosed;
    }

} // namespace
<commit_msg>Fixed lofting algorithm in case leading edge curve is not at alpha = 0<commit_after>/*
* Copyright (C) 2007-2013 German Aerospace Center (DLR/SC)
*
* Created: 2014-05-26 Martin Siggel <Martin.Siggel@dlr.de>
*
* 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 "CTiglMakeLoft.h"
#include "tigl_config.h"

#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
#include <TopExp.hxx>
#include <BRep_Builder.hxx>
#include <BRepLib.hxx>
#include <BRepTools.hxx>
#ifdef LOFTALGO_FOUND
  #include <MakePatches.hxx>
#endif
#include <BRepOffsetAPI_ThruSections.hxx>
#include <BRepBuilderAPI_FindPlane.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include <BRepAlgo.hxx>
#include <BRepBuilderAPI_Sewing.hxx>
#include <StdFail_NotDone.hxx>
#include <Precision.hxx>

namespace
{
    TopoDS_Solid MakeSolid(TopoDS_Shape& shell, const TopoDS_Wire& wire1,
                           const TopoDS_Wire& wire2, const Standard_Real presPln,
                           TopoDS_Face& face1, TopoDS_Face& face2);

    TopoDS_Shape MakeShells(TopoDS_Shape& shell, const Standard_Real presPln);
} // namespace

CTiglMakeLoft::CTiglMakeLoft(double tolerance)
{
    _hasPerformed = false;
    _makeSolid = true;
    _result.Nullify();
    _myTolerance = tolerance;
    _makeSmooth = false;
}

CTiglMakeLoft::CTiglMakeLoft(const TopoDS_Shape &profiles, const TopoDS_Shape &guides, double tolerance)
{
    _hasPerformed = false;
    _result.Nullify();
    _myTolerance = tolerance;
    addProfiles(profiles);
    addGuides(guides);
}

void CTiglMakeLoft::addProfiles(const TopoDS_Shape &profiles)
{
    if (profiles.ShapeType() == TopAbs_COMPOUND) {
        for (TopoDS_Iterator anIter(profiles); anIter.More(); anIter.Next()) {
            TopoDS_Wire aSh = TopoDS::Wire(anIter.Value());
            this->profiles.push_back(aSh);
        }
    }
    else {
        this->profiles.push_back(TopoDS::Wire(profiles));
    }
}

void CTiglMakeLoft::addGuides(const TopoDS_Shape &guides)
{
    if (guides.ShapeType() == TopAbs_COMPOUND) {
        for (TopoDS_Iterator anIter(guides); anIter.More(); anIter.Next()) {
            TopoDS_Wire aSh = TopoDS::Wire(anIter.Value());
            this->guides.push_back(aSh);
        }
    }
    else {
        this->guides.push_back(TopoDS::Wire(guides));
    }
}

TopoDS_Shape &CTiglMakeLoft::Shape()
{
    Perform();

    return _result;
}

CTiglMakeLoft::operator TopoDS_Shape &()
{
    return Shape();
}

void CTiglMakeLoft::Perform()
{
    if (_hasPerformed) {
        return;
    }

    if (guides.size() > 0) {
#ifdef LOFTALGO_FOUND
        // to the loft with guides
        makeLoftWithGuides();
#else
        makeLoftWithGuides();
#endif
    }
    else {
        makeLoftWithoutGuides();
    }
    _hasPerformed = true;
}

void CTiglMakeLoft::setMakeSolid(bool enabled)
{
    _makeSolid = enabled;
}

void CTiglMakeLoft::setMakeSmooth(bool enabled)
{
    _makeSmooth = enabled;
}

/**
 * @brief Builds the loft using profiles and guide curves
 */
void CTiglMakeLoft::makeLoftWithGuides()
{
#ifdef LOFTALGO_FOUND
    BRep_Builder b;
    TopoDS_Compound cprof, cguid;
    b.MakeCompound(cprof);
    b.MakeCompound(cguid);

    for (unsigned int i = 0; i < profiles.size(); ++i) {
        TopoDS_Wire& profile =  profiles[i];

        // remove leading edge split in profile
        profile =  BRepAlgo::ConcatenateWire(profile,GeomAbs_C1);
        b.Add(cprof, profile);
    }
    for (unsigned int i = 0; i < guides.size(); ++i) {
        TopoDS_Wire& guide =  guides[i];
        b.Add(cguid, guide);
    }

#ifdef DEBUG
    static iLoft = 0;
    BRepTools::Write(cprof, "profiles.brep");
    BRepTools::Write(cguid, "guides.brep");
    iLoft++;
#endif

    MakePatches SurfMaker(cguid, cprof);
    // Don't sew yet. We do it later in solid creation
    SurfMaker.Perform(_myTolerance, 1e-4, GeomFill_CoonsC2Style, Standard_False);
    TopoDS_Shape faces = SurfMaker.Patches();
    if (SurfMaker.GetStatus() > 0) {
        LOG(ERROR) << "Could not create loft with guide curves. " << "Error code = " << SurfMaker.GetStatus();
        return;
    }

    printf("Status: %d\n" , SurfMaker.GetStatus());

    if (_makeSolid) {
        // check if the first wire is the same as the last
        Standard_Boolean vClosed = (profiles[0].IsSame(profiles[profiles.size()-1]));

        if (vClosed) {
            // we dont need side caps, just make shell and close it
            TopoDS_Shape shell = MakeShells(faces, _myTolerance);

            TopoDS_Solid solid;
            BRep_Builder B;
            B.MakeSolid(solid);
            B.Add(solid, shell);

            // verify the orientation of the solid
            BRepClass3d_SolidClassifier clas3d(solid);
            clas3d.PerformInfinitePoint(Precision::Confusion());
            if (clas3d.State() == TopAbs_IN) {
                B.MakeSolid(solid);
                TopoDS_Shape aLocalShape = faces.Reversed();
                B.Add(solid, TopoDS::Shell(aLocalShape));
            }
            _result = solid;
        }
        else {
            // make solid by adding side caps
            TopoDS_Wire wire1 = TopoDS::Wire(profiles[0]);
            TopoDS_Wire wire2 = TopoDS::Wire(profiles[profiles.size()-1]);
            TopoDS_Face innerCap, outerCap;
            _result = faces;
            _result = MakeSolid(faces, wire1, wire2, 1e-6, innerCap, outerCap);
        }
    }
    else {
        // don't make solid
        _result = MakeShells(faces, 1e-6);
    }
    BRepLib::EncodeRegularity(_result);
#endif // LOFTALGO_FOUND
}

void CTiglMakeLoft::makeLoftWithoutGuides()
{
    bool isRuled = !_makeSmooth;
    BRepOffsetAPI_ThruSections lofter(_makeSolid, isRuled, _myTolerance);
    for (unsigned int i = 0; i < profiles.size(); ++i) {
        TopoDS_Wire& profile =  profiles[i];
        lofter.AddWire(profile);
    }
    lofter.CheckCompatibility(Standard_False);

    if (_makeSmooth) {
        lofter.SetMaxDegree(2); //surfaces will be C1-continuous
        lofter.SetParType(Approx_Centripetal);
    }

    _result = lofter.Shape();
}

namespace
{
    // Creates a face to close a profile
    // Code taken from opencascade, BRepOffsetAPI_ThruSections
    Standard_Boolean CreateSideCap(const TopoDS_Wire& W,
                                   const Standard_Real presPln,
                                   TopoDS_Face& theFace)
    {
        Standard_Boolean isDegen = Standard_True;
        TopoDS_Iterator iter(W);
        for (; iter.More(); iter.Next())
        {
            const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
            if (!BRep_Tool::Degenerated(anEdge))
                isDegen = Standard_False;
        }
        if (isDegen)
            return Standard_True;

        Standard_Boolean Ok = Standard_False;
        if (!W.IsNull()) {
            BRepBuilderAPI_FindPlane Searcher( W, presPln );
            if (Searcher.Found()) {
                theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W);
                Ok = Standard_True;
            }
            else {
                // try to find another surface
                BRepBuilderAPI_MakeFace MF( W );
                if (MF.IsDone())
                {
                    theFace = MF.Face();
                    Ok = Standard_True;
                }
            }
        }

        return Ok;
    }

    // Code adapted from opencascade, BRepOffsetAPI_ThruSections
    TopoDS_Solid MakeSolid(TopoDS_Shape& shell,
                           const TopoDS_Wire& wire1, const TopoDS_Wire& wire2,
                           const Standard_Real presPln,
                           TopoDS_Face& face1, TopoDS_Face& face2)
    {
        if (shell.IsNull()) {
            StdFail_NotDone::Raise("Thrusections is not build");
        }
        Standard_Boolean B = shell.Closed();

        BRepBuilderAPI_Sewing sewingAlgo;
        sewingAlgo.Add(shell);

        if (!B) {
            // It is necessary to close the extremities
            B =  CreateSideCap(wire1, presPln, face1);
            if (B) {
                B =  CreateSideCap(wire2, presPln, face2);
                if (B) {
                    if (!face1.IsNull()) {
                        sewingAlgo.Add(face1);
                    }
                    if (!face2.IsNull()) {
                        sewingAlgo.Add(face2);
                    }
                }
            }
        }

        sewingAlgo.Perform();
        TopoDS_Shape shellClosed  = sewingAlgo.SewedShape();
        shellClosed.Closed(Standard_True);

        // make solid from shell
        TopoDS_Solid solid;
        BRep_Builder solidMaker;
        solidMaker.MakeSolid(solid);
        solidMaker.Add(solid, shellClosed);

        // verify the orientation the solid
        BRepClass3d_SolidClassifier clas3d(solid);
        clas3d.PerformInfinitePoint(Precision::Confusion());
        if (clas3d.State() == TopAbs_IN) {
            solidMaker.MakeSolid(solid);
            TopoDS_Shape aLocalShape = shellClosed.Reversed();
            solidMaker.Add(solid, TopoDS::Shell(aLocalShape));
        }

        solid.Closed(Standard_True);
        return solid;
    }

    TopoDS_Shape MakeShells(TopoDS_Shape& shell, const Standard_Real presPln)
    {
        if (shell.IsNull()) {
            StdFail_NotDone::Raise("Thrusections is not build");
        }

        BRepBuilderAPI_Sewing BB(presPln);
        BB.Add(shell);
        BB.Perform();

        TopoDS_Shape shellClosed  = BB.SewedShape();
        return shellClosed;
    }

} // namespace
<|endoftext|>


<commit_before>/**
 * @file thread.cpp
 * @brief  Brief description of file.
 *
 */

#include <angort/angort.h>
#include <pthread.h>
#include <unistd.h>
#include "../wrappers.h"

using namespace angort;

%name thread
%shared

// thread hook object Angort uses to do... stuff.

class MyThreadHookObject : public ThreadHookObject {
    // a big global lock
    pthread_mutex_t mutex;
public:
    MyThreadHookObject(){
        pthread_mutexattr_t attr;
        pthread_mutexattr_init(&attr);
        pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&mutex,&attr);
    }

    // single global mutex, nestable
    virtual void globalLock(){
        pthread_mutex_lock(&mutex);
    }
    virtual void globalUnlock(){
        pthread_mutex_unlock(&mutex);
    }
};

static MyThreadHookObject hook;

class Thread : public GarbageCollected {
    Runtime *runtime;
    bool running;
public:
    Value func;
    pthread_t thread;
    Thread(Angort *ang,Value *v,Value *arg) : GarbageCollected(){
        incRefCt(); // make sure we don't get deleted until complete
        func.copy(v);
        runtime = new Runtime(ang,"<thread>");
        runtime->pushval()->copy(arg);
        void *_threadfunc(void *);
//        printf("Creating thread at %p/%s\n",this,func.t->name);
        pthread_create(&thread,NULL,_threadfunc,this);
    }
    ~Thread(){
//        printf("Thread destroyed at %p\n",this);
    }
    void run(){
        running = true;
        const StringBuffer& buf = func.toString();
        runtime->runValue(&func);
        running = false;
        delete runtime;
        runtime = NULL;
        // decrement refct, and delete this if it's zero. This is kind
        // of OK, here - it's the last thing that happens.
        if(decRefCt())delete this;
    }
};

void *_threadfunc(void *p){
    Thread *t = (Thread *)p;
//    printf("starting thread at %p/%s\n",t,t->func.t->name);
    t->run();
//    printf("Thread func terminated OK?\n");
    return NULL;
}

class ThreadType : public GCType {
public:
    ThreadType(){
        add("thread","THRD");
    }

    Thread *get(Value *v){
        if(v->t!=this)
            throw RUNT(EX_TYPE,"not a thread");
        return (Thread *)(v->v.gc);
    }

    // create a new thread!
    void set(Value *v,Angort *ang,Value *func,Value *pass){
        if(func->t != Types::tCode)
            throw RUNT(EX_TYPE,"not a codeblock (can't be a closure)");
        v->clr();
        v->t=this;
        v->v.gc = new Thread(ang,func,pass);
        incRef(v);
    }
};

static ThreadType tThread;

static WrapperType<pthread_mutex_t> tMutex("MUTX");

%type mutex tMutex pthread_mutex_t
%type thread tThread Thread

// words

%wordargs create vc (arg func --) start a new thread
{
    Value v,p;
    p.copy(p0);
    v.copy(p1);
    tThread.set(a->pushval(),a->ang,&v,&p);
}

%word glock (--) global lock
{
    hook.globalLock();
}

%word unglock (--) global unlock
{
    hook.globalUnlock();
}

%wordargs join l (threadlist --) wait for threads to complete
{
    ArrayListIterator<Value> iter(p0);

    // check types first
    for(iter.first();!iter.isDone();iter.next()){
        Value *p = iter.current();
        if(p->t != &tThread)
            throw RUNT(EX_TYPE,"expected threads only in thread list");
    }

    // then join each in turn.
    for(iter.first();!iter.isDone();iter.next()){
        Value *p = iter.current();
        pthread_join(tThread.get(p)->thread,NULL);
    }
}

%word mutex (-- mutex) create a recursive mutex
{
    pthread_mutex_t *v = new pthread_mutex_t();
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init(v,&attr);

    tMutex.set(a->pushval(),v);
}

%wordargs lock A|mutex (mutex -- ) lock a mutex
{
    pthread_mutex_lock(p0);
}
%wordargs unlock A|mutex (mutex -- ) unlock a mutex
{
    pthread_mutex_unlock(p0);
}

%init
{
    fprintf(stderr,"Initialising THREAD plugin, %s %s\n",__DATE__,__TIME__);

    fprintf(stderr,
            "Todo: \n"
            "-make sure threads die correctly on end of function,\n"
            "-signal handling in both Angort and here\n"
            "-thread kill and join (list of threads)\n"
            "-thread data stored in Runtime so we can get thread\n"
            "-finer grained lock object\n"
            );
    a->ang->setThreadHookObject(&hook);
}

<commit_msg>thread: more locking on create/destroy, and uses global thread hook<commit_after>/**
 * @file thread.cpp
 * @brief  Brief description of file.
 *
 */

#include <angort/angort.h>
#include <pthread.h>
#include <unistd.h>
#include "../wrappers.h"

using namespace angort;

%name thread
%shared

// thread hook object Angort uses to do... stuff.

class MyThreadHookObject : public ThreadHookObject {
    // a big global lock
    pthread_mutex_t mutex;
public:
    MyThreadHookObject(){
        pthread_mutexattr_t attr;
        pthread_mutexattr_init(&attr);
        pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&mutex,&attr);
    }

    // single global mutex, nestable
    virtual void globalLock(){
        pthread_mutex_lock(&mutex);
    }
    virtual void globalUnlock(){
        pthread_mutex_unlock(&mutex);
    }
};

static MyThreadHookObject hook;

class Thread : public GarbageCollected {
    Runtime *runtime;
    bool running;
public:
    Value func;
    pthread_t thread;
    Thread(Angort *ang,Value *v,Value *arg) : GarbageCollected(){
        incRefCt(); // make sure we don't get deleted until complete
        func.copy(v);
        runtime = new Runtime(ang,"<thread>");
        runtime->pushval()->copy(arg);
        void *_threadfunc(void *);
//        printf("Creating thread at %p/%s\n",this,func.t->name);
        pthread_create(&thread,NULL,_threadfunc,this);
    }
    ~Thread(){
//        printf("Thread destroyed at %p\n",this);
    }
    void run(){
        running = true;
        const StringBuffer& buf = func.toString();
        runtime->runValue(&func);
        hook.globalLock();
        running = false;
        delete runtime;
        runtime = NULL;
        // decrement refct, and delete this if it's zero. This is kind
        // of OK, here - it's the last thing that happens.
        if(decRefCt())delete this;
        hook.globalUnlock();
    }
};

void *_threadfunc(void *p){
    Thread *t = (Thread *)p;
//    printf("starting thread at %p/%s\n",t,t->func.t->name);
    t->run();
//    printf("Thread func terminated OK?\n");
    return NULL;
}

class ThreadType : public GCType {
public:
    ThreadType(){
        add("thread","THRD");
    }

    Thread *get(Value *v){
        if(v->t!=this)
            throw RUNT(EX_TYPE,"not a thread");
        return (Thread *)(v->v.gc);
    }

    // create a new thread!
    void set(Value *v,Angort *ang,Value *func,Value *pass){
        if(func->t != Types::tCode)
            throw RUNT(EX_TYPE,"not a codeblock (can't be a closure)");
        hook.globalLock();
        v->clr();
        v->t=this;
        v->v.gc = new Thread(ang,func,pass);
        incRef(v);
        hook.globalUnlock();
    }
};

static ThreadType tThread;

static WrapperType<pthread_mutex_t> tMutex("MUTX");

%type mutex tMutex pthread_mutex_t
%type thread tThread Thread

// words

%wordargs create vc (arg func --) start a new thread
{
    Value v,p;
    p.copy(p0);
    v.copy(p1);
    tThread.set(a->pushval(),a->ang,&v,&p);
}

%word glock (--) global lock
{
    hook.globalLock();
}

%word unglock (--) global unlock
{
    hook.globalUnlock();
}

%wordargs join l (threadlist --) wait for threads to complete
{
    ArrayListIterator<Value> iter(p0);

    // check types first
    for(iter.first();!iter.isDone();iter.next()){
        Value *p = iter.current();
        if(p->t != &tThread)
            throw RUNT(EX_TYPE,"expected threads only in thread list");
    }

    // then join each in turn.
    for(iter.first();!iter.isDone();iter.next()){
        Value *p = iter.current();
        pthread_join(tThread.get(p)->thread,NULL);
    }
}

%word mutex (-- mutex) create a recursive mutex
{
    pthread_mutex_t *v = new pthread_mutex_t();
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init(v,&attr);

    tMutex.set(a->pushval(),v);
}

%wordargs lock A|mutex (mutex -- ) lock a mutex
{
    pthread_mutex_lock(p0);
}
%wordargs unlock A|mutex (mutex -- ) unlock a mutex
{
    pthread_mutex_unlock(p0);
}

%init
{
    fprintf(stderr,"Initialising THREAD plugin, %s %s\n",__DATE__,__TIME__);

    fprintf(stderr,
            "Todo: \n"
            "-make sure threads die correctly on end of function,\n"
            "-signal handling in both Angort and here\n"
            "-thread kill and join (list of threads)\n"
            "-thread data stored in Runtime so we can get thread\n"
            "-finer grained lock object\n"
            );
    Angort::setThreadHookObject(&hook);
}

<|endoftext|>


<commit_before>#include <stm32f3xx_hal.h>

#include <spi.h>

#include "gpio.hpp"
#include "myTask.hpp"
#include "spi.hpp"

static Gpio nRF24L01_1_CE(GPIOD, GPIO_PIN_13);
static Gpio nRF24L01_1_IRQ(GPIOB, GPIO_PIN_11);
static Gpio nRF24L01_1_CSN(GPIOD, GPIO_PIN_15);
static Spi nRF24L01_1_SPI(hspi2, nRF24L01_1_CSN);
static nRF24L01P_ESB nRF24L01_1(nRF24L01_1_SPI, nRF24L01_1_CE, nRF24L01_1_IRQ, 2);

static Gpio nRF24L01_2_CE(GPIOF, GPIO_PIN_6);
static Gpio nRF24L01_2_IRQ(GPIOC, GPIO_PIN_9);
static Gpio nRF24L01_2_CS(GPIOA, GPIO_PIN_15);
static Spi nRF24L01_2_SPI(hspi3, nRF24L01_2_CS);
static nRF24L01P_ESB nRF24L01_2(nRF24L01_2_SPI, nRF24L01_2_CE, nRF24L01_2_IRQ, 3);

static MyTask myTask(nRF24L01_1, nRF24L01_2);
<commit_msg>Typo<commit_after>#include <stm32f3xx_hal.h>

#include <spi.h>

#include "gpio.hpp"
#include "myTask.hpp"
#include "spi.hpp"

static Gpio nRF24L01_1_CE(GPIOD, GPIO_PIN_13);
static Gpio nRF24L01_1_IRQ(GPIOB, GPIO_PIN_11);
static Gpio nRF24L01_1_CSN(GPIOD, GPIO_PIN_15);
static Spi nRF24L01_1_SPI(hspi2, nRF24L01_1_CSN);
static nRF24L01P_ESB nRF24L01_1(nRF24L01_1_SPI, nRF24L01_1_CE, nRF24L01_1_IRQ, 2);

static Gpio nRF24L01_2_CE(GPIOF, GPIO_PIN_6);
static Gpio nRF24L01_2_IRQ(GPIOC, GPIO_PIN_9);
static Gpio nRF24L01_2_CSN(GPIOA, GPIO_PIN_15);
static Spi nRF24L01_2_SPI(hspi3, nRF24L01_2_CSN);
static nRF24L01P_ESB nRF24L01_2(nRF24L01_2_SPI, nRF24L01_2_CE, nRF24L01_2_IRQ, 3);

static MyTask myTask(nRF24L01_1, nRF24L01_2);
<|endoftext|>


<commit_before>#ifndef NANO_SIGNAL_SLOT_HPP
#define NANO_SIGNAL_SLOT_HPP

#include "nano_function.hpp"

#include <unordered_map>

namespace Nano
{

class Observer
{
    std::unordered_map<delegate_key_t, Observer*> tracked_connections;

    template <typename T> friend class Signal;

    void insert(delegate_key_t const& key, Observer* instance)
    {
        tracked_connections.emplace(key, instance);
    }
    void remove(delegate_key_t const& key)
    {
        tracked_connections.erase(key);
    }

    protected:

   ~Observer()
    {
        for (auto const& connection : tracked_connections)
        {
            if (auto const& subject = std::get<1>(connection))
            {
                subject->remove(std::get<0>(connection));
            }
        }
    }
};

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

template <typename T_rv> class Signal;
template <typename T_rv, typename... Args>
class Signal <T_rv(Args...)> : public Observer
{
    template <typename T>
    void sfinae_con(delegate_key_t const& key, typename T::Observer* instance)
    {
        Observer::insert(key, instance);
        instance->insert(key, this);
    }
    template <typename T>
    void sfinae_dis(delegate_key_t const& key, typename T::Observer* instance)
    {
        Observer::remove(key);
        instance->remove(key);
    }
    template <typename T> void sfinae_con(delegate_key_t const& key, ...)
    {
        Observer::insert(key, nullptr);
    }
    template <typename T> void sfinae_dis(delegate_key_t const& key, ...)
    {
        Observer::remove(key);
    }

    using function_t  = Function<T_rv(Args...)>;

    public: //------------------------------------------------------------------

    template <T_rv (*fun_ptr)(Args...)>
    void connect()
    {
        auto delegate = function_t::template bind<fun_ptr>();
        Observer::insert(delegate, nullptr);
    }
    template <typename T, T_rv (T::*mem_ptr)(Args...)>
    void connect(T* instance)
    {
        auto delegate = function_t::template bind<T, mem_ptr>(instance);
        sfinae_con<T>(delegate, instance);
    }
    template <typename T, T_rv (T::*mem_ptr)(Args...) const>
    void connect(T* instance)
    {
        auto delegate = function_t::template bind<T, mem_ptr>(instance);
        sfinae_con<T>(delegate, instance);
    }

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

    template <typename T, T_rv (T::*mem_ptr)(Args...)>
    void connect(T& instance)
    {
        auto delegate = function_t::template
            bind<T, mem_ptr>(std::addressof(instance));
        sfinae_con<T>(delegate, std::addressof(instance));
    }
    template <typename T, T_rv (T::*mem_ptr)(Args...) const>
    void connect(T& instance)
    {
        auto delegate = function_t::template
            bind<T, mem_ptr>(std::addressof(instance));
        sfinae_con<T>(delegate, std::addressof(instance));
    }

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

    template <T_rv (*fun_ptr)(Args...)>
    void disconnect()
    {
        auto delegate = function_t::template bind<fun_ptr>();
        Observer::remove(delegate);
    }
    template <typename T, T_rv (T::*mem_ptr)(Args...)>
    void disconnect(T* instance)
    {
        auto delegate = function_t::template bind<T, mem_ptr>(instance);
        sfinae_dis<T>(delegate, instance);
    }
    template <typename T, T_rv (T::*mem_ptr)(Args...) const>
    void disconnect(T* instance)
    {
        auto delegate = function_t::template bind<T, mem_ptr>(instance);
        sfinae_dis<T>(delegate, instance);
    }

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

    template <typename T, T_rv (T::*mem_ptr)(Args...)>
    void disconnect(T& instance)
    {
        auto delegate = function_t::template
            bind<T, mem_ptr>(std::addressof(instance));
        sfinae_dis<T>(delegate, std::addressof(instance));
    }
    template <typename T, T_rv (T::*mem_ptr)(Args...) const>
    void disconnect(T& instance)
    {
        auto delegate = function_t::template
            bind<T, mem_ptr>(std::addressof(instance));
        sfinae_dis<T>(delegate, std::addressof(instance));
    }

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

    void operator()(Args&&... args)
    {
        for (auto const& slot : tracked_connections)
        {
            function_t (std::get<0>(slot))(std::forward<Args>(args)...);
        }
    }
    template <typename Accumulator>
    void accumulate(Args&&... args, Accumulator&& lambda)
    {
        for (auto const& slot : tracked_connections)
        {
            lambda(function_t (std::get<0>(slot))(std::forward<Args>(args)...));
        }
    }

};

} // namespace Nano ------------------------------------------------------------

#endif // NANO_SIGNAL_SLOT_HPP_2_514
<commit_msg>no more nullptr test<commit_after>#ifndef NANO_SIGNAL_SLOT_HPP
#define NANO_SIGNAL_SLOT_HPP

#include "nano_function.hpp"

#include <unordered_map>

namespace Nano
{

class Observer
{
    std::unordered_map<delegate_key_t, Observer*> tracked_connections;

    template <typename T> friend class Signal;

    void insert(delegate_key_t const& key, Observer* instance)
    {
        tracked_connections.emplace(key, instance);
    }
    void remove(delegate_key_t const& key)
    {
        tracked_connections.erase(key);
    }

    protected:

   ~Observer()
    {
        for (auto const& connection : tracked_connections)
        {
            std::get<1> (connection)->remove(std::get<0>(connection));
        }
    }
};

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

template <typename T_rv> class Signal;
template <typename T_rv, typename... Args>
class Signal <T_rv(Args...)> : public Observer
{
    template <typename T>
    void sfinae_con(delegate_key_t const& key, typename T::Observer* instance)
    {
        Observer::insert(key, instance);
        instance->insert(key, this);
    }
    template <typename T>
    void sfinae_dis(delegate_key_t const& key, typename T::Observer* instance)
    {
        Observer::remove(key);
        instance->remove(key);
    }
    template <typename T> void sfinae_con(delegate_key_t const& key, ...)
    {
        Observer::insert(key, this);
    }
    template <typename T> void sfinae_dis(delegate_key_t const& key, ...)
    {
        Observer::remove(key);
    }

    using function_t  = Function<T_rv(Args...)>;

    public: //------------------------------------------------------------------

    template <T_rv (*fun_ptr)(Args...)>
    void connect()
    {
        auto delegate = function_t::template bind<fun_ptr>();
        Observer::insert(delegate, this);
    }
    template <typename T, T_rv (T::*mem_ptr)(Args...)>
    void connect(T* instance)
    {
        auto delegate = function_t::template bind<T, mem_ptr>(instance);
        sfinae_con<T>(delegate, instance);
    }
    template <typename T, T_rv (T::*mem_ptr)(Args...) const>
    void connect(T* instance)
    {
        auto delegate = function_t::template bind<T, mem_ptr>(instance);
        sfinae_con<T>(delegate, instance);
    }

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

    template <typename T, T_rv (T::*mem_ptr)(Args...)>
    void connect(T& instance)
    {
        auto delegate = function_t::template
            bind<T, mem_ptr>(std::addressof(instance));
        sfinae_con<T>(delegate, std::addressof(instance));
    }
    template <typename T, T_rv (T::*mem_ptr)(Args...) const>
    void connect(T& instance)
    {
        auto delegate = function_t::template
            bind<T, mem_ptr>(std::addressof(instance));
        sfinae_con<T>(delegate, std::addressof(instance));
    }

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

    template <T_rv (*fun_ptr)(Args...)>
    void disconnect()
    {
        auto delegate = function_t::template bind<fun_ptr>();
        Observer::remove(delegate);
    }
    template <typename T, T_rv (T::*mem_ptr)(Args...)>
    void disconnect(T* instance)
    {
        auto delegate = function_t::template bind<T, mem_ptr>(instance);
        sfinae_dis<T>(delegate, instance);
    }
    template <typename T, T_rv (T::*mem_ptr)(Args...) const>
    void disconnect(T* instance)
    {
        auto delegate = function_t::template bind<T, mem_ptr>(instance);
        sfinae_dis<T>(delegate, instance);
    }

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

    template <typename T, T_rv (T::*mem_ptr)(Args...)>
    void disconnect(T& instance)
    {
        auto delegate = function_t::template
            bind<T, mem_ptr>(std::addressof(instance));
        sfinae_dis<T>(delegate, std::addressof(instance));
    }
    template <typename T, T_rv (T::*mem_ptr)(Args...) const>
    void disconnect(T& instance)
    {
        auto delegate = function_t::template
            bind<T, mem_ptr>(std::addressof(instance));
        sfinae_dis<T>(delegate, std::addressof(instance));
    }

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

    void operator()(Args&&... args)
    {
        for (auto const& slot : tracked_connections)
        {
            function_t (std::get<0>(slot))(std::forward<Args>(args)...);
        }
    }
    template <typename Accumulator>
    void accumulate(Args&&... args, Accumulator&& lambda)
    {
        for (auto const& slot : tracked_connections)
        {
            lambda(function_t (std::get<0>(slot))(std::forward<Args>(args)...));
        }
    }

};

} // namespace Nano ------------------------------------------------------------

#endif // NANO_SIGNAL_SLOT_HPP_2_514
<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg & Daniel Wallin
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/pch.hpp"

#include <libtorrent/kademlia/closest_nodes.hpp>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include "libtorrent/assert.hpp"

namespace libtorrent { namespace dht
{

using asio::ip::udp;

closest_nodes_observer::~closest_nodes_observer()
{
	if (m_algorithm) m_algorithm->failed(m_self, true);
}

void closest_nodes_observer::reply(msg const& in)
{
	if (!m_algorithm)
	{
		TORRENT_ASSERT(false);
		return;
	}

	if (!in.nodes.empty())
	{
		for (msg::nodes_t::const_iterator i = in.nodes.begin()
			, end(in.nodes.end()); i != end; ++i)
		{
			m_algorithm->traverse(i->id, i->addr);
		}
	}
	m_algorithm->finished(m_self);
	m_algorithm = 0;
}

void closest_nodes_observer::timeout()
{
	if (!m_algorithm) return;
	m_algorithm->failed(m_self);
	m_algorithm = 0;
}

closest_nodes::closest_nodes(
	node_id target
	, int branch_factor
	, int max_results
	, routing_table& table
	, rpc_manager& rpc
	, done_callback const& callback
)
	: traversal_algorithm(
		target
		, branch_factor
		, max_results
		, table
		, rpc
		, table.begin()
		, table.end()
	)
	, m_done_callback(callback)
{
	boost::intrusive_ptr<closest_nodes> self(this);
	add_requests();
}

void closest_nodes::invoke(node_id const& id, udp::endpoint addr)
{
	TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(closest_nodes_observer));
	observer_ptr o(new (m_rpc.allocator().malloc()) closest_nodes_observer(this, id, m_target));
#ifndef NDEBUG
	o->m_in_constructor = false;
#endif
	m_rpc.invoke(messages::find_node, addr, o);
}

void closest_nodes::done()
{
	std::vector<node_entry> results;
	int num_results = m_max_results;
	for (std::vector<result>::iterator i = m_results.begin()
		, end(m_results.end()); i != end && num_results >= 0; ++i)
	{
		if (i->flags & result::no_id) continue;
		if ((i->flags & result::queried) == 0) continue;
		results.push_back(node_entry(i->id, i->addr));
		--num_results;
	}
	m_done_callback(results);
}

void closest_nodes::initiate(
	node_id target
	, int branch_factor
	, int max_results
	, routing_table& table
	, rpc_manager& rpc
	, done_callback const& callback
)
{
	new closest_nodes(target, branch_factor, max_results, table, rpc, callback);
}

} } // namespace libtorrent::dht

<commit_msg>minor dht fix<commit_after>/*

Copyright (c) 2006, Arvid Norberg & Daniel Wallin
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/pch.hpp"

#include <libtorrent/kademlia/closest_nodes.hpp>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include "libtorrent/assert.hpp"

namespace libtorrent { namespace dht
{

using asio::ip::udp;

closest_nodes_observer::~closest_nodes_observer()
{
	if (m_algorithm) m_algorithm->failed(m_self, true);
}

void closest_nodes_observer::reply(msg const& in)
{
	if (!m_algorithm)
	{
		TORRENT_ASSERT(false);
		return;
	}

	if (!in.nodes.empty())
	{
		for (msg::nodes_t::const_iterator i = in.nodes.begin()
			, end(in.nodes.end()); i != end; ++i)
		{
			m_algorithm->traverse(i->id, i->addr);
		}
	}
	m_algorithm->finished(m_self);
	m_algorithm = 0;
}

void closest_nodes_observer::timeout()
{
	if (!m_algorithm) return;
	m_algorithm->failed(m_self);
	m_algorithm = 0;
}

closest_nodes::closest_nodes(
	node_id target
	, int branch_factor
	, int max_results
	, routing_table& table
	, rpc_manager& rpc
	, done_callback const& callback
)
	: traversal_algorithm(
		target
		, branch_factor
		, max_results
		, table
		, rpc
		, table.begin()
		, table.end()
	)
	, m_done_callback(callback)
{
	boost::intrusive_ptr<closest_nodes> self(this);
	add_requests();
}

void closest_nodes::invoke(node_id const& id, udp::endpoint addr)
{
	TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(closest_nodes_observer));
	observer_ptr o(new (m_rpc.allocator().malloc()) closest_nodes_observer(this, id, m_target));
#ifndef NDEBUG
	o->m_in_constructor = false;
#endif
	m_rpc.invoke(messages::find_node, addr, o);
}

void closest_nodes::done()
{
	std::vector<node_entry> results;
	int num_results = m_max_results;
	for (std::vector<result>::iterator i = m_results.begin()
		, end(m_results.end()); i != end && num_results > 0; ++i)
	{
		if (i->flags & result::no_id) continue;
		if ((i->flags & result::queried) == 0) continue;
		results.push_back(node_entry(i->id, i->addr));
		--num_results;
	}
	m_done_callback(results);
}

void closest_nodes::initiate(
	node_id target
	, int branch_factor
	, int max_results
	, routing_table& table
	, rpc_manager& rpc
	, done_callback const& callback
)
{
	new closest_nodes(target, branch_factor, max_results, table, rpc, callback);
}

} } // namespace libtorrent::dht

<|endoftext|>


<commit_before>// Copyright (c) 2013, Cloudera, inc.
// Confidential Cloudera Information: Covered by NDA.

#include <boost/foreach.hpp>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <iostream>
#include <vector>

#include "kudu/common/row_operations.h"
#include "kudu/common/wire_protocol.h"
#include "kudu/consensus/consensus.pb.h"
#include "kudu/consensus/log_index.h"
#include "kudu/consensus/log_reader.h"
#include "kudu/gutil/stl_util.h"
#include "kudu/gutil/strings/numbers.h"
#include "kudu/util/env.h"
#include "kudu/util/pb_util.h"

DEFINE_bool(print_headers, true, "print the log segment headers/footers");
DEFINE_string(print_entries, "decoded",
              "How to print entries:\n"
              "  false|0|no = don't print\n"
              "  true|1|yes|decoded = print them decoded\n"
              "  pb = print the raw protobuf\n"
              "  id = print only their ids");
DEFINE_int32(truncate_data, 100,
             "Truncate the data fields to the given number of bytes "
             "before printing. Set to 0 to disable");
namespace kudu {
namespace log {

using consensus::CommitMsg;
using consensus::OperationType;
using consensus::ReplicateMsg;
using tserver::WriteRequestPB;
using std::string;
using std::vector;
using std::cout;
using std::endl;

enum PrintEntryType {
  DONT_PRINT,
  PRINT_PB,
  PRINT_DECODED,
  PRINT_ID
};

static PrintEntryType ParsePrintType() {
  if (ParseLeadingBoolValue(FLAGS_print_entries.c_str(), true) == false) {
    return DONT_PRINT;
  } else if (ParseLeadingBoolValue(FLAGS_print_entries.c_str(), false) == true ||
             FLAGS_print_entries == "decoded") {
    return PRINT_DECODED;
  } else if (FLAGS_print_entries == "pb") {
    return PRINT_PB;
  } else if (FLAGS_print_entries == "id") {
    return PRINT_ID;
  } else {
    LOG(FATAL) << "Unknown value for --print_entries: " << FLAGS_print_entries;
  }
}

void PrintIdOnly(const LogEntryPB& entry) {
  switch (entry.type()) {
    case log::REPLICATE:
    {
      cout << entry.replicate().id().term() << "." << entry.replicate().id().index() << "\t";
      cout << "REPLICATE "
           << OperationType_Name(entry.replicate().op_type());
      break;
    }
    case log::COMMIT:
    {
      cout << "COMMIT " << entry.commit().commited_op_id().term()
           << "." << entry.commit().commited_op_id().index();
      break;
    }
    default:
      cout << "UNKNOWN: " << entry.ShortDebugString();
  }

  cout << endl;
}

void PrintDecodedWriteRequestPB(const string& indent,
                                const Schema& tablet_schema,
                                const WriteRequestPB& write) {
  Schema request_schema;
  CHECK_OK(SchemaFromPB(write.schema(), &request_schema));

  Arena arena(32 * 1024, 1024 * 1024);
  RowOperationsPBDecoder dec(&write.row_operations(), &request_schema, &tablet_schema, &arena);
  vector<DecodedRowOperation> ops;
  CHECK_OK(dec.DecodeOperations(&ops));

  cout << indent << "Tablet: " << write.tablet_id() << endl;
  cout << indent << "Consistency: "
       << ExternalConsistencyMode_Name(write.external_consistency_mode()) << endl;
  if (write.has_propagated_timestamp()) {
    cout << indent << "Propagated TS: " << write.propagated_timestamp() << endl;
  }

  int i = 0;
  BOOST_FOREACH(const DecodedRowOperation& op, ops) {
    // TODO (KUDU-515): Handle the case when a tablet's schema changes
    // mid-segment.
    cout << indent << "op " << (i++) << ": " << op.ToString(tablet_schema) << endl;
  }
}

void PrintDecoded(const LogEntryPB& entry, const Schema& tablet_schema) {
  PrintIdOnly(entry);

  const string indent = "\t";
  if (entry.has_replicate()) {
    // We can actually decode REPLICATE messages.

    const ReplicateMsg& replicate = entry.replicate();
    if (replicate.op_type() == consensus::WRITE_OP) {
      PrintDecodedWriteRequestPB(indent, tablet_schema, replicate.write_request());
    } else {
      cout << indent << replicate.ShortDebugString() << endl;
    }
  } else if (entry.has_commit()) {
    // For COMMIT we'll just dump the PB
    cout << indent << entry.commit().ShortDebugString() << endl;
  }
}

void PrintSegment(const scoped_refptr<ReadableLogSegment>& segment) {
  PrintEntryType print_type = ParsePrintType();
  if (FLAGS_print_headers) {
    cout << "Header:\n" << segment->header().DebugString();
  }
  vector<LogEntryPB*> entries;
  CHECK_OK(segment->ReadEntries(&entries));

  if (print_type == DONT_PRINT) return;

  Schema tablet_schema;
  CHECK_OK(SchemaFromPB(segment->header().schema(), &tablet_schema));

  BOOST_FOREACH(LogEntryPB* entry, entries) {

    if (print_type == PRINT_PB) {
      if (FLAGS_truncate_data > 0) {
        pb_util::TruncateFields(entry, FLAGS_truncate_data);
      }

      cout << "Entry:\n" << entry->DebugString();
    } else if (print_type == PRINT_DECODED) {
      PrintDecoded(*entry, tablet_schema);
    } else if (print_type == PRINT_ID) {
      PrintIdOnly(*entry);
    }
  }
  if (FLAGS_print_headers && segment->HasFooter()) {
    cout << "Footer:\n" << segment->footer().DebugString();
  }
}

void DumpLog(const string &tserver_root_path, const string& tablet_oid) {
  Env *env = Env::Default();
  gscoped_ptr<LogReader> reader;
  FsManager fs_manager(env, tserver_root_path);
  CHECK_OK(LogReader::Open(&fs_manager, scoped_refptr<LogIndex>(), tablet_oid, NULL, &reader));

  SegmentSequence segments;
  CHECK_OK(reader->GetSegmentsSnapshot(&segments));

  BOOST_FOREACH(const scoped_refptr<ReadableLogSegment>& segment, segments) {
    PrintSegment(segment);
  }
}

void DumpSegment(const string &segment_path) {
  Env *env = Env::Default();
  gscoped_ptr<LogReader> reader;
  scoped_refptr<ReadableLogSegment> segment;
  CHECK_OK(ReadableLogSegment::Open(env, segment_path, &segment));
  CHECK(segment);
  PrintSegment(segment);
}

} // namespace log
} // namespace kudu

int main(int argc, char **argv) {
  google::InitGoogleLogging(argv[0]);
  google::ParseCommandLineFlags(&argc, &argv, true);
  if (argc < 2 || argc > 3) {
    std::cerr << "usage: " << argv[0] << " <tserver root path> <tablet_name>"
        " | <log segment path> " << std::endl;
    return 1;
  }
  if (argc == 2) {
    if (!kudu::Env::Default()->FileExists(argv[1])) {
      std::cerr << "Specified file \"" << argv[1] << "\" does not exist"
          << std::endl;
      return 1;
    }
    kudu::log::DumpSegment(argv[1]);
  } else {
    kudu::log::DumpLog(argv[1], argv[2]);
  }

  return 0;
}
<commit_msg>LogDump: Print transaction timestamps<commit_after>// Copyright (c) 2013, Cloudera, inc.
// Confidential Cloudera Information: Covered by NDA.

#include <boost/foreach.hpp>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <iostream>
#include <vector>

#include "kudu/common/row_operations.h"
#include "kudu/common/wire_protocol.h"
#include "kudu/consensus/consensus.pb.h"
#include "kudu/consensus/log_index.h"
#include "kudu/consensus/log_reader.h"
#include "kudu/gutil/stl_util.h"
#include "kudu/gutil/strings/numbers.h"
#include "kudu/util/env.h"
#include "kudu/util/pb_util.h"

DEFINE_bool(print_headers, true, "print the log segment headers/footers");
DEFINE_string(print_entries, "decoded",
              "How to print entries:\n"
              "  false|0|no = don't print\n"
              "  true|1|yes|decoded = print them decoded\n"
              "  pb = print the raw protobuf\n"
              "  id = print only their ids");
DEFINE_int32(truncate_data, 100,
             "Truncate the data fields to the given number of bytes "
             "before printing. Set to 0 to disable");
namespace kudu {
namespace log {

using consensus::CommitMsg;
using consensus::OperationType;
using consensus::ReplicateMsg;
using tserver::WriteRequestPB;
using std::string;
using std::vector;
using std::cout;
using std::endl;

enum PrintEntryType {
  DONT_PRINT,
  PRINT_PB,
  PRINT_DECODED,
  PRINT_ID
};

static PrintEntryType ParsePrintType() {
  if (ParseLeadingBoolValue(FLAGS_print_entries.c_str(), true) == false) {
    return DONT_PRINT;
  } else if (ParseLeadingBoolValue(FLAGS_print_entries.c_str(), false) == true ||
             FLAGS_print_entries == "decoded") {
    return PRINT_DECODED;
  } else if (FLAGS_print_entries == "pb") {
    return PRINT_PB;
  } else if (FLAGS_print_entries == "id") {
    return PRINT_ID;
  } else {
    LOG(FATAL) << "Unknown value for --print_entries: " << FLAGS_print_entries;
  }
}

void PrintIdOnly(const LogEntryPB& entry) {
  switch (entry.type()) {
    case log::REPLICATE:
    {
      cout << entry.replicate().id().term() << "." << entry.replicate().id().index()
           << "@" << entry.replicate().timestamp() << "\t";
      cout << "REPLICATE "
           << OperationType_Name(entry.replicate().op_type());
      break;
    }
    case log::COMMIT:
    {
      cout << "COMMIT " << entry.commit().commited_op_id().term()
           << "." << entry.commit().commited_op_id().index();
      break;
    }
    default:
      cout << "UNKNOWN: " << entry.ShortDebugString();
  }

  cout << endl;
}

void PrintDecodedWriteRequestPB(const string& indent,
                                const Schema& tablet_schema,
                                const WriteRequestPB& write) {
  Schema request_schema;
  CHECK_OK(SchemaFromPB(write.schema(), &request_schema));

  Arena arena(32 * 1024, 1024 * 1024);
  RowOperationsPBDecoder dec(&write.row_operations(), &request_schema, &tablet_schema, &arena);
  vector<DecodedRowOperation> ops;
  CHECK_OK(dec.DecodeOperations(&ops));

  cout << indent << "Tablet: " << write.tablet_id() << endl;
  cout << indent << "Consistency: "
       << ExternalConsistencyMode_Name(write.external_consistency_mode()) << endl;
  if (write.has_propagated_timestamp()) {
    cout << indent << "Propagated TS: " << write.propagated_timestamp() << endl;
  }

  int i = 0;
  BOOST_FOREACH(const DecodedRowOperation& op, ops) {
    // TODO (KUDU-515): Handle the case when a tablet's schema changes
    // mid-segment.
    cout << indent << "op " << (i++) << ": " << op.ToString(tablet_schema) << endl;
  }
}

void PrintDecoded(const LogEntryPB& entry, const Schema& tablet_schema) {
  PrintIdOnly(entry);

  const string indent = "\t";
  if (entry.has_replicate()) {
    // We can actually decode REPLICATE messages.

    const ReplicateMsg& replicate = entry.replicate();
    if (replicate.op_type() == consensus::WRITE_OP) {
      PrintDecodedWriteRequestPB(indent, tablet_schema, replicate.write_request());
    } else {
      cout << indent << replicate.ShortDebugString() << endl;
    }
  } else if (entry.has_commit()) {
    // For COMMIT we'll just dump the PB
    cout << indent << entry.commit().ShortDebugString() << endl;
  }
}

void PrintSegment(const scoped_refptr<ReadableLogSegment>& segment) {
  PrintEntryType print_type = ParsePrintType();
  if (FLAGS_print_headers) {
    cout << "Header:\n" << segment->header().DebugString();
  }
  vector<LogEntryPB*> entries;
  CHECK_OK(segment->ReadEntries(&entries));

  if (print_type == DONT_PRINT) return;

  Schema tablet_schema;
  CHECK_OK(SchemaFromPB(segment->header().schema(), &tablet_schema));

  BOOST_FOREACH(LogEntryPB* entry, entries) {

    if (print_type == PRINT_PB) {
      if (FLAGS_truncate_data > 0) {
        pb_util::TruncateFields(entry, FLAGS_truncate_data);
      }

      cout << "Entry:\n" << entry->DebugString();
    } else if (print_type == PRINT_DECODED) {
      PrintDecoded(*entry, tablet_schema);
    } else if (print_type == PRINT_ID) {
      PrintIdOnly(*entry);
    }
  }
  if (FLAGS_print_headers && segment->HasFooter()) {
    cout << "Footer:\n" << segment->footer().DebugString();
  }
}

void DumpLog(const string &tserver_root_path, const string& tablet_oid) {
  Env *env = Env::Default();
  gscoped_ptr<LogReader> reader;
  FsManager fs_manager(env, tserver_root_path);
  CHECK_OK(LogReader::Open(&fs_manager, scoped_refptr<LogIndex>(), tablet_oid, NULL, &reader));

  SegmentSequence segments;
  CHECK_OK(reader->GetSegmentsSnapshot(&segments));

  BOOST_FOREACH(const scoped_refptr<ReadableLogSegment>& segment, segments) {
    PrintSegment(segment);
  }
}

void DumpSegment(const string &segment_path) {
  Env *env = Env::Default();
  gscoped_ptr<LogReader> reader;
  scoped_refptr<ReadableLogSegment> segment;
  CHECK_OK(ReadableLogSegment::Open(env, segment_path, &segment));
  CHECK(segment);
  PrintSegment(segment);
}

} // namespace log
} // namespace kudu

int main(int argc, char **argv) {
  google::InitGoogleLogging(argv[0]);
  google::ParseCommandLineFlags(&argc, &argv, true);
  if (argc < 2 || argc > 3) {
    std::cerr << "usage: " << argv[0] << " <tserver root path> <tablet_name>"
        " | <log segment path> " << std::endl;
    return 1;
  }
  if (argc == 2) {
    if (!kudu::Env::Default()->FileExists(argv[1])) {
      std::cerr << "Specified file \"" << argv[1] << "\" does not exist"
          << std::endl;
      return 1;
    }
    kudu::log::DumpSegment(argv[1]);
  } else {
    kudu::log::DumpLog(argv[1], argv[2]);
  }

  return 0;
}
<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
// Copyright 2008      Jens-Michael Hoffmann <jensmh@gmx.de>
// Copyright 2008      Pino Toscano <pino@kde.org>
//

#include "QHttpNetworkPlugin.h"

#include <QtCore/QBuffer>
#include <QtCore/QMetaObject>
#include <QtNetwork/QHttp>
#include <QtNetwork/QHttpResponseHeader>

#include "StoragePolicy.h"

using namespace Marble;

QHttpHttpJob::QHttpHttpJob( const QUrl & sourceUrl, const QString & destFileName, const QString &id )
        : HttpJob( sourceUrl, destFileName, id ),
        m_data(),
        m_buffer( 0 ),
        m_http( 0 ),
        m_currentRequest( -1 )
{
}

QHttpHttpJob::~QHttpHttpJob()
{

    delete m_http;
    delete m_buffer;
}

void QHttpHttpJob::prepareExecution()
{
    // job can be executed more than once because of redirection
    // perhaps better to make a new job than (FIXME)
    if ( !m_http ) {
        m_http = new QHttp;
        m_buffer = new QBuffer ( &m_data );
        m_buffer->open ( QIODevice::WriteOnly );

        connect( m_http, SIGNAL( requestFinished( int, bool ) ),
                 this, SLOT( httpRequestFinished( int, bool ) ) );
    }
}

void QHttpHttpJob::execute()
{
    emit statusMessage ( tr ( "Downloading data..." ) );

    m_http->setHost( sourceUrl().host(),
                     sourceUrl().port() != -1 ? sourceUrl().port() : 80 );
    if ( !sourceUrl().userName().isEmpty() )
        m_http->setUser( sourceUrl().userName(), sourceUrl().password() );
    // if Url has query item like in panoramio API requests source.path()
    // chops it , this "if" gurantees its correct treatement
    QString cleanupPath;
    if ( sourceUrl().hasQuery() == true ) {
        cleanupPath = QString( sourceUrl().toString( QUrl::RemoveAuthority | QUrl::RemoveScheme ) );
    }
    else {
        cleanupPath = QUrl::toPercentEncoding( sourceUrl().path(), "/", " -" );
    }

//    qDebug() << sourceUrl().host() << "and path=" << cleanupPath;
    QHttpRequestHeader header ( QLatin1String ( "GET" ), cleanupPath );
    header.setValue ( "Connection", "Keep-Alive" );
    header.setValue ( "User-Agent", "Marble TinyWebBrowser" );
    header.setValue ( "Host", sourceUrl().host() );

    m_currentRequest = m_http->request( header, 0, m_buffer );
}

void QHttpHttpJob::httpRequestFinished( int requestId, bool error )
{
    if ( requestId != m_currentRequest )
        return;

    QHttpResponseHeader responseHeader = m_http->lastResponse();
//     qDebug() << "responseHeader.statusCode():" << responseHeader.statusCode()
//              << responseHeader.reasonPhrase();

//    FIXME: Check whether this assumption is a safe on:
//    ( Problem: Conditional jump later on depends on uninitialised value )
//
//    if ( responseHeader.isValid() == false )
//        return;

    if ( responseHeader.statusCode() == 301 )
    {
        QUrl newLocation ( responseHeader.value ( "Location" ) );
        setSourceUrl ( newLocation );
        setDestinationFileName ( newLocation.path() );
        m_currentRequest = -1;

        // Let's try again
        QMetaObject::invokeMethod( this, "execute", Qt::QueuedConnection );
        return;
    }

    if ( responseHeader.statusCode() != 200 )
    {
        emit statusMessage ( tr ( "Download failed: %1." )
                             .arg ( responseHeader.reasonPhrase() ) );
        emit jobDone ( this, 1 );

        return;
    }

    if ( error != 0 )
    {
        emit statusMessage ( tr ( "Download failed: %1." )
                             .arg ( m_http->errorString() ) );
        emit jobDone ( this, error );

        return;

    }

    if ( storagePolicy() && !storagePolicy()->updateFile ( originalDestinationFileName(), data() ) )
    {
        emit statusMessage ( tr ( "Download failed: %1." )
                             .arg ( storagePolicy()->lastErrorMessage() ) );
        emit jobDone ( this, error );

        return;
    }

    emit statusMessage ( tr ( "Download finished." ) );

    emit jobDone ( this, 0 );
}

QHttpNetworkPlugin::QHttpNetworkPlugin()
{
}

QHttpNetworkPlugin::~QHttpNetworkPlugin()
{
}

QString QHttpNetworkPlugin::nameId() const
{
    return QString::fromLatin1( "QHttp" );
}

HttpJob *QHttpNetworkPlugin::createJob( const QUrl &source, const QString &destination,
                                        const QString &id )
{
    return new QHttpHttpJob( source, destination, id );
}

Q_EXPORT_PLUGIN2( QHttpNetworkPlugin, Marble::QHttpNetworkPlugin )

#include "QHttpNetworkPlugin.moc"
<commit_msg>White space cleanup.<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
// Copyright 2008      Jens-Michael Hoffmann <jensmh@gmx.de>
// Copyright 2008      Pino Toscano <pino@kde.org>
//

#include "QHttpNetworkPlugin.h"

#include <QtCore/QBuffer>
#include <QtCore/QMetaObject>
#include <QtNetwork/QHttp>
#include <QtNetwork/QHttpResponseHeader>

#include "StoragePolicy.h"

using namespace Marble;

QHttpHttpJob::QHttpHttpJob( const QUrl & sourceUrl, const QString & destFileName,
                            const QString &id )
        : HttpJob( sourceUrl, destFileName, id ),
        m_data(),
        m_buffer( 0 ),
        m_http( 0 ),
        m_currentRequest( -1 )
{
}

QHttpHttpJob::~QHttpHttpJob()
{
    delete m_http;
    delete m_buffer;
}

void QHttpHttpJob::prepareExecution()
{
    // job can be executed more than once because of redirection
    // perhaps better to make a new job than (FIXME)
    if ( !m_http ) {
        m_http = new QHttp;
        m_buffer = new QBuffer( &m_data );
        m_buffer->open( QIODevice::WriteOnly );

        connect( m_http, SIGNAL( requestFinished( int, bool ) ),
                 this, SLOT( httpRequestFinished( int, bool ) ) );
    }
}

void QHttpHttpJob::execute()
{
    emit statusMessage( tr( "Downloading data..." ) );

    m_http->setHost( sourceUrl().host(),
                     sourceUrl().port() != -1 ? sourceUrl().port() : 80 );
    if ( !sourceUrl().userName().isEmpty() )
        m_http->setUser( sourceUrl().userName(), sourceUrl().password() );
    // if Url has query item like in panoramio API requests source.path()
    // chops it , this "if" gurantees its correct treatement
    QString cleanupPath;
    if ( sourceUrl().hasQuery() == true ) {
        cleanupPath = QString( sourceUrl().toString( QUrl::RemoveAuthority | QUrl::RemoveScheme ) );
    }
    else {
        cleanupPath = QUrl::toPercentEncoding( sourceUrl().path(), "/", " -" );
    }

//    qDebug() << sourceUrl().host() << "and path=" << cleanupPath;
    QHttpRequestHeader header( QLatin1String( "GET" ), cleanupPath );
    header.setValue( "Connection", "Keep-Alive" );
    header.setValue( "User-Agent", "Marble TinyWebBrowser" );
    header.setValue( "Host", sourceUrl().host() );

    m_currentRequest = m_http->request( header, 0, m_buffer );
}

void QHttpHttpJob::httpRequestFinished( int requestId, bool error )
{
    if ( requestId != m_currentRequest )
        return;

    QHttpResponseHeader responseHeader = m_http->lastResponse();
//     qDebug() << "responseHeader.statusCode():" << responseHeader.statusCode()
//              << responseHeader.reasonPhrase();

//    FIXME: Check whether this assumption is a safe on:
//    ( Problem: Conditional jump later on depends on uninitialised value )
//
//    if ( responseHeader.isValid() == false )
//        return;

    if ( responseHeader.statusCode() == 301 )
    {
        QUrl newLocation( responseHeader.value( "Location" ) );
        setSourceUrl( newLocation );
        setDestinationFileName( newLocation.path() );
        m_currentRequest = -1;

        // Let's try again
        QMetaObject::invokeMethod( this, "execute", Qt::QueuedConnection );
        return;
    }

    if ( responseHeader.statusCode() != 200 )
    {
        emit statusMessage( tr( "Download failed: %1." )
                            .arg( responseHeader.reasonPhrase() ) );
        emit jobDone( this, 1 );
        return;
    }

    if ( error != 0 )
    {
        emit statusMessage( tr( "Download failed: %1." )
                            .arg( m_http->errorString() ) );
        emit jobDone( this, error );
        return;
    }

    if ( storagePolicy() && !storagePolicy()->updateFile( originalDestinationFileName(), data() ) )
    {
        emit statusMessage( tr( "Download failed: %1." )
                            .arg( storagePolicy()->lastErrorMessage() ) );
        emit jobDone( this, error );
        return;
    }

    emit statusMessage( tr( "Download finished." ));
    emit jobDone( this, 0 );
}

QHttpNetworkPlugin::QHttpNetworkPlugin()
{
}

QHttpNetworkPlugin::~QHttpNetworkPlugin()
{
}

QString QHttpNetworkPlugin::nameId() const
{
    return QString::fromLatin1( "QHttp" );
}

HttpJob *QHttpNetworkPlugin::createJob( const QUrl &source, const QString &destination,
                                        const QString &id )
{
    return new QHttpHttpJob( source, destination, id );
}

Q_EXPORT_PLUGIN2( QHttpNetworkPlugin, Marble::QHttpNetworkPlugin )

#include "QHttpNetworkPlugin.moc"
<|endoftext|>