<commit_before>
#include "OpenGLFunctions.h"

#include "UnitCube.h"

namespace
{
	struct vec3
    {
        vec3(float a, float b, float c)
        {
            _[0] = a; _[1] = b; _[2] = c;
        }
        float _[3];
    };

	typedef std::vector<vec3> Strip3;

	const Strip3 strip()
	{
		static vec3 vertices[] =
		{
		    vec3(-.5f,-.5f,-.5f)
		,   vec3(-.5f,-.5f, .5f)
		,   vec3(-.5f, .5f,-.5f)
		,   vec3(-.5f, .5f, .5f)
		,   vec3( .5f,-.5f,-.5f)
		,   vec3( .5f,-.5f, .5f)
		,   vec3( .5f, .5f,-.5f)
		,   vec3( .5f, .5f, .5f)
		};

		static vec3 normals[] =
		{
			vec3(-1.f, 0.f, 0.f)
		,   vec3( 1.f, 0.f, 0.f)
		,   vec3( 0.f,-1.f, 0.f)
		,   vec3( 0.f, 1.f, 0.f)
		,   vec3( 0.f, 0.f,-1.f)
		,   vec3( 0.f, 0.f, 1.f)
		,   vec3( 0.f, 0.f, 0.f)  // dummy
		};

		// use an interleaved array
        static vec3 strip[] =
        {
		    vertices[7], normals[6]
		,   vertices[3], normals[6]
		,   vertices[5], normals[5]
		,   vertices[1], normals[5]
		,   vertices[0], normals[2]
		,   vertices[3], normals[0]
		,   vertices[2], normals[0]
		,   vertices[7], normals[3]
		,   vertices[6], normals[3]
		,   vertices[5], normals[1]
		,   vertices[4], normals[1]
		,   vertices[0], normals[2]
		,   vertices[6], normals[4]
		,   vertices[2], normals[4]
		};

        Strip3 strip2;
        strip2.assign(strip, strip + 28);

        return strip2;
	}
}

UnitCube::UnitCube(
    OpenGLFunctions & gl
,   const GLuint vertexAttribLocation
,   const GLuint normalAttribLocation)
:   m_strip(QOpenGLBuffer::VertexBuffer)
{
    const Strip3 raw(strip());

    m_vao.create();
    m_vao.bind();

    m_strip.create();
    m_strip.setUsagePattern(QOpenGLBuffer::StaticDraw);
    m_strip.bind();
    m_strip.allocate(raw.data(), sizeof(vec3) * 2 * raw.size());

    gl.glVertexAttribPointer(vertexAttribLocation, 3, GL_FLOAT, GL_FALSE, sizeof(vec3) * 2, nullptr);
    gl.glEnableVertexAttribArray(vertexAttribLocation);

    gl.glVertexAttribPointer(normalAttribLocation, 3, GL_FLOAT, GL_FALSE, sizeof(vec3) * 2, reinterpret_cast<void*>(sizeof(vec3)));
    gl.glEnableVertexAttribArray(normalAttribLocation);

    m_vao.release();
}

void UnitCube::draw(OpenGLFunctions & gl)
{
    gl.glEnable(GL_DEPTH_TEST);

    m_vao.bind();
    gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 14);
    m_vao.release();
}<commit_msg>moep vector back<commit_after>
#include <vector>

#include "OpenGLFunctions.h"

#include "UnitCube.h"

namespace
{
	struct vec3
    {
        vec3(float a, float b, float c)
        {
            _[0] = a; _[1] = b; _[2] = c;
        }
        float _[3];
    };

	typedef std::vector<vec3> Strip3;

	const Strip3 strip()
	{
		static vec3 vertices[] =
		{
		    vec3(-.5f,-.5f,-.5f)
		,   vec3(-.5f,-.5f, .5f)
		,   vec3(-.5f, .5f,-.5f)
		,   vec3(-.5f, .5f, .5f)
		,   vec3( .5f,-.5f,-.5f)
		,   vec3( .5f,-.5f, .5f)
		,   vec3( .5f, .5f,-.5f)
		,   vec3( .5f, .5f, .5f)
		};

		static vec3 normals[] =
		{
			vec3(-1.f, 0.f, 0.f)
		,   vec3( 1.f, 0.f, 0.f)
		,   vec3( 0.f,-1.f, 0.f)
		,   vec3( 0.f, 1.f, 0.f)
		,   vec3( 0.f, 0.f,-1.f)
		,   vec3( 0.f, 0.f, 1.f)
		,   vec3( 0.f, 0.f, 0.f)  // dummy
		};

		// use an interleaved array
        static vec3 strip[] =
        {
		    vertices[7], normals[6]
		,   vertices[3], normals[6]
		,   vertices[5], normals[5]
		,   vertices[1], normals[5]
		,   vertices[0], normals[2]
		,   vertices[3], normals[0]
		,   vertices[2], normals[0]
		,   vertices[7], normals[3]
		,   vertices[6], normals[3]
		,   vertices[5], normals[1]
		,   vertices[4], normals[1]
		,   vertices[0], normals[2]
		,   vertices[6], normals[4]
		,   vertices[2], normals[4]
		};

        Strip3 strip2;
        strip2.assign(strip, strip + 28);

        return strip2;
	}
}

UnitCube::UnitCube(
    OpenGLFunctions & gl
,   const GLuint vertexAttribLocation
,   const GLuint normalAttribLocation)
:   m_strip(QOpenGLBuffer::VertexBuffer)
{
    const Strip3 raw(strip());

    m_vao.create();
    m_vao.bind();

    m_strip.create();
    m_strip.setUsagePattern(QOpenGLBuffer::StaticDraw);
    m_strip.bind();
    m_strip.allocate(raw.data(), sizeof(vec3) * 2 * raw.size());

    gl.glVertexAttribPointer(vertexAttribLocation, 3, GL_FLOAT, GL_FALSE, sizeof(vec3) * 2, nullptr);
    gl.glEnableVertexAttribArray(vertexAttribLocation);

    gl.glVertexAttribPointer(normalAttribLocation, 3, GL_FLOAT, GL_FALSE, sizeof(vec3) * 2, reinterpret_cast<void*>(sizeof(vec3)));
    gl.glEnableVertexAttribArray(normalAttribLocation);

    m_vao.release();
}

void UnitCube::draw(OpenGLFunctions & gl)
{
    gl.glEnable(GL_DEPTH_TEST);

    m_vao.bind();
    gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 14);
    m_vao.release();
}<|endoftext|>


<commit_before>//*******************************************************************
//
// License:  See top level LICENSE.txt file.
//
// Author: Ken Melero
//
// Description:  This class gives access to the Data Record Description
//               of a DTED Level 1 file.
//
// Notes:  Each elevation is a true value referenced to meas sea level
//         (MSL) datum recorded to the nearest meter.  The horizontal
//         position is referenced to precise longitude-latitiude
//         locations in terms of the current World Geodetic System
//         (WGS84) determined for each file by reference to the origin
//         at the southwest corner.  The elevations are evenly spaced
//         in latitude and longitude at the interval designated in the
//         User Header Label (UHL) in South to North profile sequence.
//
//********************************************************************
// $Id: ossimDtedRecord.cpp 14248 2009-04-08 19:38:11Z dburken $

#include <iostream>

#include <ossim/support_data/ossimDtedRecord.h>
#include <ossim/base/ossimConstants.h>
#include <ossim/base/ossimCommon.h>
#include <ossim/base/ossimEndian.h>
#include <ossim/base/ossimNotifyContext.h>

static const ossim_uint16 DATA_NULL_VALUE = 0xffff; // -32767
static const ossim_uint16 DATA_MIN_VALUE  = 0xfffe; // -32766
static const ossim_uint16 DATA_MAX_VALUE  = 0x7fff; // +32767
static const ossim_uint16 DATA_VALUE_MASK = 0x7fff; // 0111 1111 1111 1111
static const ossim_uint16 DATA_SIGN_MASK  = 0x8000; // 1000 0000 0000 0000
static const ossim_uint16 DATA_RECOGNITION_SENTINEL = 0xAA;  // 170

//***
// Offsets from start of data record (one record per longitude line):
//***
static const int BLOCK_COUNT_OFFSET = 2;
static const int LON_INDEX_OFFSET   = 4;
static const int LAT_INDEX_OFFSET   = 6;
static const int ELEV_DATA_OFFSET   = 8;
static const int RECORD_HDR_LENGTH  = 12;
static const int BYTES_PER_POINT    = 2;

//**************************************************************************
// CONSTRUCTOR
//**************************************************************************
ossimDtedRecord::ossimDtedRecord(std::istream& in,
                                 ossim_int32 offset,
                                 ossim_int32 num_points)
   :
      theRecSen("170"),
      theDataBlockCount(0),
      theLonCount(0),
      theLatCount(0),
      theCheckSum(0),
      thePoints(new ossim_int32[num_points]),
      thePointsData(new ossim_uint16[num_points]),
      theComputedCheckSum(0),
      theNumPoints(num_points),
      theStartOffset(offset),
      theStopOffset(offset + RECORD_HDR_LENGTH + (num_points*BYTES_PER_POINT))
{
   // Verify we are at a cell record by checking the Recognition Sentinel.
   ossim_uint8 buf[1];
   in.seekg(theStartOffset, std::ios::beg);
   in.read((char*)buf, 1);

#if 0
   printf("\nBuf: %02X", (int)buf[0]);  // Display in HEX
#endif

   if(!(buf[0] = DATA_RECOGNITION_SENTINEL))
   {
      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
      ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimDtedRecord::ossimDtedRecord: reading DTED's data record at: " << theStartOffset
                                          << std::endl;
      return;
   }

   // Valid data record, so let's process on.
   parse(in);

   //***
   // Note:  The validateCheckSum method works; however, our in-house
   //        dted has bad stored check sums even though the post are good.
   //        So this in temporarily shut off.
   //***
   // Verify Check Sum for uncorrupted elevation data.
   if(validateCheckSum(in) == false)
   {
      //***
      // Note:  The validateCheckSum method works; however, our in-house
      //        dted has bad stored check sums even though the posts are good.
      //        So this in temporarily shut off.
      //***
      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
      ossimNotify(ossimNotifyLevel_FATAL)
         << "FATAL ossimDtedRecord::ossimDtedRecord:"
         << "\nInvalid checksum in data record at: "
         << theStartOffset
         << "\nParsed Check Sum = " << theCheckSum
         << "\nComputed Check Sum = " << theComputedCheckSum
         << "\nDTED Elevation File is considered corrupted."
         << std::endl;
      return;
   }
}

ossimDtedRecord::~ossimDtedRecord()
{
   if (thePoints)
   {
      delete [] thePoints;
      thePoints = NULL;
   }
   if (thePointsData)
   {
      delete [] thePointsData;
      thePointsData = NULL;
   }
}

//**************************************************************************
// parse()
//**************************************************************************
void ossimDtedRecord::parse(std::istream& in)
{
   // DTED is stored in big endian byte order so swap the bytes if needed.
   bool swap_bytes = ossim::byteOrder() == OSSIM_LITTLE_ENDIAN ? true : false;

   ossim_sint16 s;

   // parse data block count
   in.seekg(theStartOffset + BLOCK_COUNT_OFFSET, std::ios::beg);
   in.read((char*)&s, 2);
   theDataBlockCount =
      (swap_bytes ? ( ( (s & 0x00ff) << 8) | ( (s & 0xff00) >> 8) ) : s);

   // parse lon count
   in.seekg(theStartOffset + LON_INDEX_OFFSET, std::ios::beg);
   in.read((char*)&s, 2);
   theLonCount =
      (swap_bytes ? ( ( (s & 0x00ff) << 8) | ( (s & 0xff00) >> 8) ) : s);

   // parse lat count
   in.seekg(theStartOffset + LAT_INDEX_OFFSET, std::ios::beg);
   in.read((char*)&s, 2);
   theLatCount =
      (swap_bytes ? ( ( (s & 0x00ff) << 8) | ( (s & 0xff00) >> 8) ) : s);

   // Parse all elevation points.
   in.seekg(theStartOffset + ELEV_DATA_OFFSET, std::ios::beg);
   for(int i = 0; i < theNumPoints; ++i)
   {
      in.read((char*)&s, 2);
      s = (swap_bytes ? ( ( (s & 0x00ff) << 8) | ( (s & 0xff00) >> 8) ) : s);
      if (s & DATA_SIGN_MASK)
      {
         s = (s & DATA_VALUE_MASK) * -1;
      }
      thePoints[i] = static_cast<ossim_int32>(s);
      thePointsData[i] = s;
   }
}

//**************************************************************************
// validateCheckSum()
//**************************************************************************
bool ossimDtedRecord::validateCheckSum(std::istream& in)
{
   // DTED is stored in big endian byte order so swap the bytes if needed.
   bool swap_bytes = ossim::byteOrder() == OSSIM_LITTLE_ENDIAN ? true : false;

   // Compute the check sum.
   in.seekg(theStartOffset, std::ios::beg);
   theComputedCheckSum = 0;
   ossim_int32 bytesToRead = (theNumPoints * 2) + ELEV_DATA_OFFSET;
   int i = 0;

   for(i = 0; i < bytesToRead; i++)
   {
      ossim_uint8 c;
      in.read((char*)&c, 1);
      theComputedCheckSum += static_cast<ossim_uint32>(c);
   }

   // Read the stored check sum and swap the byte if needed.
   in.read((char*)&theCheckSum, 4);
   if (swap_bytes)
   {
      ossimEndian swapper;
      swapper.swap(theCheckSum);
   }

   // Compare computed and parsed checksums.
   if(theCheckSum != theComputedCheckSum)
   {
      return false;
   }
   return true;
}

ossimString ossimDtedRecord::recognitionSentinel() const
{
   return theRecSen;
}

ossim_int32 ossimDtedRecord::dataBlockCount() const
{
   return theDataBlockCount;
}

ossim_int32 ossimDtedRecord::lonCount() const
{
   return theLonCount;
}

ossim_int32 ossimDtedRecord::latCount() const
{
   return theLatCount;
}

ossim_uint32 ossimDtedRecord::checkSum() const
{
   return theCheckSum;
}

ossim_uint32 ossimDtedRecord::computedCheckSum() const
{
   return theComputedCheckSum;
}

ossim_int32 ossimDtedRecord::numPoints() const
{
   return theNumPoints;
}

ossim_int32 ossimDtedRecord::getPoint(ossim_int32 i) const
{
   return thePoints[i];
}

ossim_uint16 ossimDtedRecord::getPointData(ossim_int32 i) const
{
   return thePointsData[i];
}

ossim_int32*  ossimDtedRecord::points() const
{
   return thePoints;
}

ossim_uint16* ossimDtedRecord::pointsData() const
{
   return thePointsData;
}

ossim_int32 ossimDtedRecord::startOffset() const
{
   return theStartOffset;
}

ossim_int32 ossimDtedRecord::stopOffset() const
{
   return theStopOffset;
}

//**************************************************************************
// operator <<
//**************************************************************************
std::ostream& operator<<( std::ostream& os, const ossimDtedRecord& rec)
{
   os << "\nDTED Record:"
      << "\n-------------------------------"
      << "\n Recognition Sentinel: " << rec.theRecSen
      << "\nData Block Count:      " << rec.theDataBlockCount
      << "\nLon Count:             " << rec.theLonCount
      << "\nLat Count:             " << rec.theLatCount
      << "\nNum Points:            " << rec.theNumPoints
      << "\nParsed Check Sum:      " << rec.theCheckSum
      << "\nComputed Check Sum     " << rec.theComputedCheckSum
      << "\nStart Offset:          " << rec.theStartOffset
      << "\nStop Offset:           " << rec.theStopOffset
      << std::endl;
   int i = 0;

   for(i = 0; i < rec.theNumPoints; i++)
   {
      os << "\nPoint[" << i << "]: " << rec.thePoints[i];
   }

   os << std::endl;

   return os;
}
<commit_msg>OSSIM: fix clearly intended comparison instead of affectation<commit_after>//*******************************************************************
//
// License:  See top level LICENSE.txt file.
//
// Author: Ken Melero
//
// Description:  This class gives access to the Data Record Description
//               of a DTED Level 1 file.
//
// Notes:  Each elevation is a true value referenced to meas sea level
//         (MSL) datum recorded to the nearest meter.  The horizontal
//         position is referenced to precise longitude-latitiude
//         locations in terms of the current World Geodetic System
//         (WGS84) determined for each file by reference to the origin
//         at the southwest corner.  The elevations are evenly spaced
//         in latitude and longitude at the interval designated in the
//         User Header Label (UHL) in South to North profile sequence.
//
//********************************************************************
// $Id: ossimDtedRecord.cpp 14248 2009-04-08 19:38:11Z dburken $

#include <iostream>

#include <ossim/support_data/ossimDtedRecord.h>
#include <ossim/base/ossimConstants.h>
#include <ossim/base/ossimCommon.h>
#include <ossim/base/ossimEndian.h>
#include <ossim/base/ossimNotifyContext.h>

static const ossim_uint16 DATA_NULL_VALUE = 0xffff; // -32767
static const ossim_uint16 DATA_MIN_VALUE  = 0xfffe; // -32766
static const ossim_uint16 DATA_MAX_VALUE  = 0x7fff; // +32767
static const ossim_uint16 DATA_VALUE_MASK = 0x7fff; // 0111 1111 1111 1111
static const ossim_uint16 DATA_SIGN_MASK  = 0x8000; // 1000 0000 0000 0000
static const ossim_uint16 DATA_RECOGNITION_SENTINEL = 0xAA;  // 170

//***
// Offsets from start of data record (one record per longitude line):
//***
static const int BLOCK_COUNT_OFFSET = 2;
static const int LON_INDEX_OFFSET   = 4;
static const int LAT_INDEX_OFFSET   = 6;
static const int ELEV_DATA_OFFSET   = 8;
static const int RECORD_HDR_LENGTH  = 12;
static const int BYTES_PER_POINT    = 2;

//**************************************************************************
// CONSTRUCTOR
//**************************************************************************
ossimDtedRecord::ossimDtedRecord(std::istream& in,
                                 ossim_int32 offset,
                                 ossim_int32 num_points)
   :
      theRecSen("170"),
      theDataBlockCount(0),
      theLonCount(0),
      theLatCount(0),
      theCheckSum(0),
      thePoints(new ossim_int32[num_points]),
      thePointsData(new ossim_uint16[num_points]),
      theComputedCheckSum(0),
      theNumPoints(num_points),
      theStartOffset(offset),
      theStopOffset(offset + RECORD_HDR_LENGTH + (num_points*BYTES_PER_POINT))
{
   // Verify we are at a cell record by checking the Recognition Sentinel.
   ossim_uint8 buf[1];
   in.seekg(theStartOffset, std::ios::beg);
   in.read((char*)buf, 1);

#if 0
   printf("\nBuf: %02X", (int)buf[0]);  // Display in HEX
#endif

   if(buf[0] != DATA_RECOGNITION_SENTINEL)
   {
      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
      ossimNotify(ossimNotifyLevel_FATAL) << "FATAL ossimDtedRecord::ossimDtedRecord: reading DTED's data record at: " << theStartOffset
                                          << std::endl;
      return;
   }

   // Valid data record, so let's process on.
   parse(in);

   //***
   // Note:  The validateCheckSum method works; however, our in-house
   //        dted has bad stored check sums even though the post are good.
   //        So this in temporarily shut off.
   //***
   // Verify Check Sum for uncorrupted elevation data.
   if(validateCheckSum(in) == false)
   {
      //***
      // Note:  The validateCheckSum method works; however, our in-house
      //        dted has bad stored check sums even though the posts are good.
      //        So this in temporarily shut off.
      //***
      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
      ossimNotify(ossimNotifyLevel_FATAL)
         << "FATAL ossimDtedRecord::ossimDtedRecord:"
         << "\nInvalid checksum in data record at: "
         << theStartOffset
         << "\nParsed Check Sum = " << theCheckSum
         << "\nComputed Check Sum = " << theComputedCheckSum
         << "\nDTED Elevation File is considered corrupted."
         << std::endl;
      return;
   }
}

ossimDtedRecord::~ossimDtedRecord()
{
   if (thePoints)
   {
      delete [] thePoints;
      thePoints = NULL;
   }
   if (thePointsData)
   {
      delete [] thePointsData;
      thePointsData = NULL;
   }
}

//**************************************************************************
// parse()
//**************************************************************************
void ossimDtedRecord::parse(std::istream& in)
{
   // DTED is stored in big endian byte order so swap the bytes if needed.
   bool swap_bytes = ossim::byteOrder() == OSSIM_LITTLE_ENDIAN ? true : false;

   ossim_sint16 s;

   // parse data block count
   in.seekg(theStartOffset + BLOCK_COUNT_OFFSET, std::ios::beg);
   in.read((char*)&s, 2);
   theDataBlockCount =
      (swap_bytes ? ( ( (s & 0x00ff) << 8) | ( (s & 0xff00) >> 8) ) : s);

   // parse lon count
   in.seekg(theStartOffset + LON_INDEX_OFFSET, std::ios::beg);
   in.read((char*)&s, 2);
   theLonCount =
      (swap_bytes ? ( ( (s & 0x00ff) << 8) | ( (s & 0xff00) >> 8) ) : s);

   // parse lat count
   in.seekg(theStartOffset + LAT_INDEX_OFFSET, std::ios::beg);
   in.read((char*)&s, 2);
   theLatCount =
      (swap_bytes ? ( ( (s & 0x00ff) << 8) | ( (s & 0xff00) >> 8) ) : s);

   // Parse all elevation points.
   in.seekg(theStartOffset + ELEV_DATA_OFFSET, std::ios::beg);
   for(int i = 0; i < theNumPoints; ++i)
   {
      in.read((char*)&s, 2);
      s = (swap_bytes ? ( ( (s & 0x00ff) << 8) | ( (s & 0xff00) >> 8) ) : s);
      if (s & DATA_SIGN_MASK)
      {
         s = (s & DATA_VALUE_MASK) * -1;
      }
      thePoints[i] = static_cast<ossim_int32>(s);
      thePointsData[i] = s;
   }
}

//**************************************************************************
// validateCheckSum()
//**************************************************************************
bool ossimDtedRecord::validateCheckSum(std::istream& in)
{
   // DTED is stored in big endian byte order so swap the bytes if needed.
   bool swap_bytes = ossim::byteOrder() == OSSIM_LITTLE_ENDIAN ? true : false;

   // Compute the check sum.
   in.seekg(theStartOffset, std::ios::beg);
   theComputedCheckSum = 0;
   ossim_int32 bytesToRead = (theNumPoints * 2) + ELEV_DATA_OFFSET;
   int i = 0;

   for(i = 0; i < bytesToRead; i++)
   {
      ossim_uint8 c;
      in.read((char*)&c, 1);
      theComputedCheckSum += static_cast<ossim_uint32>(c);
   }

   // Read the stored check sum and swap the byte if needed.
   in.read((char*)&theCheckSum, 4);
   if (swap_bytes)
   {
      ossimEndian swapper;
      swapper.swap(theCheckSum);
   }

   // Compare computed and parsed checksums.
   if(theCheckSum != theComputedCheckSum)
   {
      return false;
   }
   return true;
}

ossimString ossimDtedRecord::recognitionSentinel() const
{
   return theRecSen;
}

ossim_int32 ossimDtedRecord::dataBlockCount() const
{
   return theDataBlockCount;
}

ossim_int32 ossimDtedRecord::lonCount() const
{
   return theLonCount;
}

ossim_int32 ossimDtedRecord::latCount() const
{
   return theLatCount;
}

ossim_uint32 ossimDtedRecord::checkSum() const
{
   return theCheckSum;
}

ossim_uint32 ossimDtedRecord::computedCheckSum() const
{
   return theComputedCheckSum;
}

ossim_int32 ossimDtedRecord::numPoints() const
{
   return theNumPoints;
}

ossim_int32 ossimDtedRecord::getPoint(ossim_int32 i) const
{
   return thePoints[i];
}

ossim_uint16 ossimDtedRecord::getPointData(ossim_int32 i) const
{
   return thePointsData[i];
}

ossim_int32*  ossimDtedRecord::points() const
{
   return thePoints;
}

ossim_uint16* ossimDtedRecord::pointsData() const
{
   return thePointsData;
}

ossim_int32 ossimDtedRecord::startOffset() const
{
   return theStartOffset;
}

ossim_int32 ossimDtedRecord::stopOffset() const
{
   return theStopOffset;
}

//**************************************************************************
// operator <<
//**************************************************************************
std::ostream& operator<<( std::ostream& os, const ossimDtedRecord& rec)
{
   os << "\nDTED Record:"
      << "\n-------------------------------"
      << "\n Recognition Sentinel: " << rec.theRecSen
      << "\nData Block Count:      " << rec.theDataBlockCount
      << "\nLon Count:             " << rec.theLonCount
      << "\nLat Count:             " << rec.theLatCount
      << "\nNum Points:            " << rec.theNumPoints
      << "\nParsed Check Sum:      " << rec.theCheckSum
      << "\nComputed Check Sum     " << rec.theComputedCheckSum
      << "\nStart Offset:          " << rec.theStartOffset
      << "\nStop Offset:           " << rec.theStopOffset
      << std::endl;
   int i = 0;

   for(i = 0; i < rec.theNumPoints; i++)
   {
      os << "\nPoint[" << i << "]: " << rec.thePoints[i];
   }

   os << std::endl;

   return os;
}
<|endoftext|>


<commit_before>/* -*- mode: c++; fill-column: 132; c-basic-offset: 4; indent-tabs-mode: nil -*- */

// =-=-=-=-=-=-=-
#include "irods_file_object.hpp"
#include "irods_resource_manager.hpp"
#include "irods_hierarchy_parser.hpp"
#include "irods_log.hpp"
#include "irods_stacktrace.hpp"
#include "irods_hierarchy_parser.hpp"
#include "irods_resource_backport.hpp"

// =-=-=-=-=-=-=-
// irods includes
#include "miscServerFunct.hpp"
#include "dataObjOpr.hpp"
#include "objDesc.hpp"
//#include "rsGlobal.hpp"

// =-=-=-=-=-=-=-
// boost includes
#include <boost/asio/ip/host_name.hpp>

namespace irods {
// =-=-=-=-=-=-=-
// public - ctor
    file_object::file_object() :
        data_object(),
        file_descriptor_( -1 ),
        size_( 0 ),
        repl_requested_( -1 ) {
    } // file_object

// =-=-=-=-=-=-=-
// public - cctor
    file_object::file_object(
        const file_object& _rhs ) :
        data_object( _rhs ) {
        // =-=-=-=-=-=-=-
        // explicit initialization
        comm_           = _rhs.comm_;
        logical_path_   = _rhs.logical_path_;
        data_type_      = _rhs.data_type_;
        file_descriptor_ = _rhs.file_descriptor_;
        l1_desc_idx_    = _rhs.l1_desc_idx_;
        size_           = _rhs.size_;
        repl_requested_ = _rhs.repl_requested_;
        replicas_       = _rhs.replicas_;
        in_pdmo_        = _rhs.in_pdmo_;

    } // cctor

// =-=-=-=-=-=-=-
// public - ctor
    file_object::file_object(
        rsComm_t* _c,
        const std::string& _logical_path,
        const std::string& _fn,
        const std::string& _resc_hier,
        int _fd,
        int _m,
        int _f ) :
        data_object(
            _fn,
            _resc_hier,
            _m,
            _f ),
        comm_( _c ),
        logical_path_( _logical_path ),
        data_type_( "" ),
        file_descriptor_( _fd ),
        l1_desc_idx_( -1 ),
        size_( -1 ),
        repl_requested_( -1 ) {
        // =-=-=-=-=-=-=-
        // explicit initialization
        replicas_.empty();
    } // file_object

// from dataObjInfo
    file_object::file_object(
        rsComm_t*            _rsComm,
        const dataObjInfo_t* _dataObjInfo ) {
        logical_path( _dataObjInfo->objPath );

        comm_           = _rsComm;
        physical_path_  = _dataObjInfo->filePath;
        resc_hier_      = _dataObjInfo->rescHier;
        flags_          = _dataObjInfo->flags;
        repl_requested_ = _dataObjInfo->replNum;
        replicas_.empty();
        // should mode be set here? - hcj
        replKeyVal( &_dataObjInfo->condInput, &cond_input_ );
        int l1descInx = getL1descIndexByDataObjInfo( _dataObjInfo );
        if( l1descInx != -1 )
        {
            int l3descInx = L1desc[ l1descInx ].l3descInx;
            file_descriptor_ = FileDesc[ l3descInx ].fd;
        }
        else
        {
            file_descriptor_ = -1;
        }
    }

// =-=-=-=-=-=-=-
// public - dtor
    file_object::~file_object() {
        clearKeyVal( &cond_input_ );
    } // dtor

// =-=-=-=-=-=-=-
// public - assignment operator
    file_object& file_object::operator=(
        const file_object& _rhs ) {
        // =-=-=-=-=-=-=-
        // call base class assignment first
        data_object::operator=( _rhs );

        comm_           = _rhs.comm_;
        logical_path_   = _rhs.logical_path_;
        data_type_      = _rhs.data_type_;
        file_descriptor_ = _rhs.file_descriptor_;
        l1_desc_idx_    = _rhs.l1_desc_idx_;
        size_           = _rhs.size_;
        repl_requested_ = _rhs.repl_requested_;
        replicas_       = _rhs.replicas_;
        in_pdmo_        = _rhs.in_pdmo_;
        replKeyVal( &_rhs.cond_input_, &cond_input_ );

        return *this;

    }  // operator=

// public comparison operator
    bool file_object::operator==(
        const file_object& _rhs ) const {
        bool result = true;
        if ( this->repl_requested() != _rhs.repl_requested() ||
                this->logical_path() != _rhs.logical_path() ) {
            result = false;
        }
        return result;
    }

// =-=-=-=-=-=-=-
// plugin - resolve resource plugin for this object
    error file_object::resolve(
        const std::string& _interface,
        plugin_ptr&        _ptr ) {
        // =-=-=-=-=-=-=-
        // check to see if this is for a resource plugin
        // resolution, otherwise it is an error
        if ( RESOURCE_INTERFACE != _interface ) {
            std::stringstream msg;
            msg << "file_object does not support a [";
            msg << _interface;
            msg << "] for plugin resolution";
            return ERROR( SYS_INVALID_INPUT_PARAM, msg.str() );
        }

        error result = SUCCESS();
        error ret;

        hierarchy_parser hparse;
        ret = hparse.set_string( resc_hier() );

        if ( !ret.ok() ) {
            std::stringstream msg;
            msg << "error parsing resource hierarchy \"" << resc_hier() << "\"";
            result = PASSMSG( msg.str(), ret );
        }
        else {
            std::string resc;

            ret = hparse.first_resc( resc );
            if ( !ret.ok() ) {
                std::stringstream msg;
                msg << __FUNCTION__ << " - ERROR getting first resource from hierarchy.";
                result = PASSMSG( msg.str(), ret );
            }
            else {

                if ( resc.empty() && resc_hier().empty() ) {
                    //std::stringstream msg;
                    //msg << __FUNCTION__
                    //    << " - there is no resource specified in the resource hierarchy.";
                    //log(LOG_NOTICE, msg.str());
                }
                else if ( resc.empty() ) {
                    return ERROR( HIERARCHY_ERROR, "Hierarchy string is not empty but first resource is!" );
                }

                resource_ptr resc_ptr;
                ret = resc_mgr.resolve( resc, resc_ptr );
                if ( !ret.ok() ) {
                    std::stringstream msg;
                    msg << __FUNCTION__ << " - ERROR resolving resource \"" << resc << "\"";
                    result = PASSMSG( msg.str(), ret );
                }

                _ptr = boost::dynamic_pointer_cast< resource >( resc_ptr );
            }
        }

        return result;

    } // resolve

// =-=-=-=-=-=-=-
// public - get vars from object for rule engine
    error file_object::get_re_vars(
        keyValPair_t& _kvp ) {
        data_object::get_re_vars( _kvp );

        copyKeyVal( &cond_input_, &_kvp );

        addKeyVal( &_kvp, LOGICAL_PATH_KW, logical_path_.c_str() );
        addKeyVal( &_kvp, DATA_TYPE_KW,    data_type_.c_str() );

        std::stringstream fd;
        fd << file_descriptor_;
        addKeyVal( &_kvp, FILE_DESCRIPTOR_KW, fd.str().c_str() );

        std::stringstream idx;
        idx << l1_desc_idx_;
        addKeyVal( &_kvp, L1_DESC_IDX_KW, idx.str().c_str() );

        std::stringstream sz;
        sz << size_;
        addKeyVal( &_kvp, SIZE_KW, sz.str().c_str() );

        std::stringstream repl;
        repl << repl_requested_;
        addKeyVal( &_kvp, REPL_REQUESTED_KW, repl.str().c_str() );

        std::stringstream pdmo;
        pdmo << in_pdmo_;
        addKeyVal( &_kvp, IN_PDMO_KW, pdmo.str().c_str() );

        return SUCCESS();

    } // get_re_vars

// =-=-=-=-=-=-=-
// static factory to create file_object from dataobjinfo linked list
    error file_object_factory( rsComm_t*        _comm,
                               dataObjInp_t*    _data_obj_inp,
                               file_object_ptr  _file_obj ) {
        // =-=-=-=-=-=-=-
        // if a repl is requested, cache that fact
        char* repl_num_ptr = getValByKey( &_data_obj_inp->condInput, REPL_NUM_KW );
        std::string repl_num;
        if ( repl_num_ptr ) {
            repl_num = repl_num_ptr;
            rmKeyVal( &_data_obj_inp->condInput, REPL_NUM_KW );
        }

        // =-=-=-=-=-=-=-
        // make a call to build the linked list
        dataObjInfo_t* head_ptr = 0;

        int status = getDataObjInfoIncSpecColl( _comm, _data_obj_inp, &head_ptr );
        if ( status < 0 ) {
            status = getDataObjInfo( _comm, _data_obj_inp, &head_ptr, 0, 0 );
        }
        if ( 0 == head_ptr || status < 0 ) {
            if ( head_ptr ) {
                freeAllDataObjInfo( head_ptr );
            }

            char* sys_error;
            char* rods_error = rodsErrorName( status, &sys_error );
            std::stringstream msg;
            msg << "failed in call to getDataObjInfoIncSpecColl";
            msg << " for [";
            msg << _data_obj_inp->objPath;
            msg << "] ";
            msg << rods_error << " " << sys_error;
            return ERROR( status, msg.str() );
        }

        // =-=-=-=-=-=-=-
        // replace the keyword
        if ( !repl_num.empty() ) {
            addKeyVal(
                &_data_obj_inp->condInput,
                REPL_NUM_KW,
                repl_num.c_str() );
        }

        // =-=-=-=-=-=-=-
        // start populating file_object
        _file_obj->comm( _comm );
        _file_obj->logical_path( _data_obj_inp->objPath );
        _file_obj->resc_hier( head_ptr->rescHier );
        _file_obj->cond_input( _data_obj_inp->condInput );

        // =-=-=-=-=-=-=-
        // handle requested repl number
        if ( !repl_num.empty() ) {
            _file_obj->repl_requested( atoi( repl_num.c_str() ) );
        }

        // handle the case where we are being called as part of a pdmo
        char* in_pdmo = getValByKey( &_data_obj_inp->condInput, IN_PDMO_KW );
        if ( in_pdmo ) {
            _file_obj->in_pdmo( in_pdmo );
        }

        // =-=-=-=-=-=-=-
        // iterate over the linked list and populate
        // the physical_object vector in the file_object
        dataObjInfo_t* info_ptr = head_ptr;
        std::vector< physical_object > objects;
        while ( info_ptr ) {
            physical_object obj;

            obj.is_dirty( info_ptr->replStatus );
            obj.repl_num( info_ptr->replNum );
            obj.map_id( info_ptr->dataMapId );
            obj.size( info_ptr->dataSize );
            obj.id( info_ptr->dataId );
            obj.coll_id( info_ptr->collId );
            obj.name( info_ptr->objPath );
            obj.version( info_ptr->version );
            obj.type_name( info_ptr->dataType );
            obj.resc_group_name( info_ptr->rescGroupName );
            obj.resc_name( info_ptr->rescName );
            obj.path( info_ptr->filePath );
            obj.owner_name( info_ptr->dataOwnerName );
            obj.owner_zone( info_ptr->dataOwnerZone );
            obj.status( info_ptr->statusString );
            obj.checksum( info_ptr->chksum );
            obj.expiry_ts( info_ptr->dataExpiry );
            obj.mode( info_ptr->dataMode );
            obj.r_comment( info_ptr->dataComments );
            obj.create_ts( info_ptr->dataCreate );
            obj.modify_ts( info_ptr->dataModify );
            obj.resc_hier( info_ptr->rescHier );

            objects.push_back( obj );
            info_ptr = info_ptr->next;

        } // while

        _file_obj->replicas( objects );

        //delete head_ptr->rescInfo;
        //free( head_ptr );
        freeAllDataObjInfo( head_ptr );
        return SUCCESS();

    } // file_object_factory

}; // namespace irods

<commit_msg>[#858] removed a commented include line<commit_after>/* -*- mode: c++; fill-column: 132; c-basic-offset: 4; indent-tabs-mode: nil -*- */

// =-=-=-=-=-=-=-
#include "irods_file_object.hpp"
#include "irods_resource_manager.hpp"
#include "irods_hierarchy_parser.hpp"
#include "irods_log.hpp"
#include "irods_stacktrace.hpp"
#include "irods_hierarchy_parser.hpp"
#include "irods_resource_backport.hpp"

// =-=-=-=-=-=-=-
// irods includes
#include "miscServerFunct.hpp"
#include "dataObjOpr.hpp"
#include "objDesc.hpp"

// =-=-=-=-=-=-=-
// boost includes
#include <boost/asio/ip/host_name.hpp>

namespace irods {
// =-=-=-=-=-=-=-
// public - ctor
    file_object::file_object() :
        data_object(),
        file_descriptor_( -1 ),
        size_( 0 ),
        repl_requested_( -1 ) {
    } // file_object

// =-=-=-=-=-=-=-
// public - cctor
    file_object::file_object(
        const file_object& _rhs ) :
        data_object( _rhs ) {
        // =-=-=-=-=-=-=-
        // explicit initialization
        comm_           = _rhs.comm_;
        logical_path_   = _rhs.logical_path_;
        data_type_      = _rhs.data_type_;
        file_descriptor_ = _rhs.file_descriptor_;
        l1_desc_idx_    = _rhs.l1_desc_idx_;
        size_           = _rhs.size_;
        repl_requested_ = _rhs.repl_requested_;
        replicas_       = _rhs.replicas_;
        in_pdmo_        = _rhs.in_pdmo_;

    } // cctor

// =-=-=-=-=-=-=-
// public - ctor
    file_object::file_object(
        rsComm_t* _c,
        const std::string& _logical_path,
        const std::string& _fn,
        const std::string& _resc_hier,
        int _fd,
        int _m,
        int _f ) :
        data_object(
            _fn,
            _resc_hier,
            _m,
            _f ),
        comm_( _c ),
        logical_path_( _logical_path ),
        data_type_( "" ),
        file_descriptor_( _fd ),
        l1_desc_idx_( -1 ),
        size_( -1 ),
        repl_requested_( -1 ) {
        // =-=-=-=-=-=-=-
        // explicit initialization
        replicas_.empty();
    } // file_object

// from dataObjInfo
    file_object::file_object(
        rsComm_t*            _rsComm,
        const dataObjInfo_t* _dataObjInfo ) {
        logical_path( _dataObjInfo->objPath );

        comm_           = _rsComm;
        physical_path_  = _dataObjInfo->filePath;
        resc_hier_      = _dataObjInfo->rescHier;
        flags_          = _dataObjInfo->flags;
        repl_requested_ = _dataObjInfo->replNum;
        replicas_.empty();
        // should mode be set here? - hcj
        replKeyVal( &_dataObjInfo->condInput, &cond_input_ );
        int l1descInx = getL1descIndexByDataObjInfo( _dataObjInfo );
        if( l1descInx != -1 )
        {
            int l3descInx = L1desc[ l1descInx ].l3descInx;
            file_descriptor_ = FileDesc[ l3descInx ].fd;
        }
        else
        {
            file_descriptor_ = -1;
        }
    }

// =-=-=-=-=-=-=-
// public - dtor
    file_object::~file_object() {
        clearKeyVal( &cond_input_ );
    } // dtor

// =-=-=-=-=-=-=-
// public - assignment operator
    file_object& file_object::operator=(
        const file_object& _rhs ) {
        // =-=-=-=-=-=-=-
        // call base class assignment first
        data_object::operator=( _rhs );

        comm_           = _rhs.comm_;
        logical_path_   = _rhs.logical_path_;
        data_type_      = _rhs.data_type_;
        file_descriptor_ = _rhs.file_descriptor_;
        l1_desc_idx_    = _rhs.l1_desc_idx_;
        size_           = _rhs.size_;
        repl_requested_ = _rhs.repl_requested_;
        replicas_       = _rhs.replicas_;
        in_pdmo_        = _rhs.in_pdmo_;
        replKeyVal( &_rhs.cond_input_, &cond_input_ );

        return *this;

    }  // operator=

// public comparison operator
    bool file_object::operator==(
        const file_object& _rhs ) const {
        bool result = true;
        if ( this->repl_requested() != _rhs.repl_requested() ||
                this->logical_path() != _rhs.logical_path() ) {
            result = false;
        }
        return result;
    }

// =-=-=-=-=-=-=-
// plugin - resolve resource plugin for this object
    error file_object::resolve(
        const std::string& _interface,
        plugin_ptr&        _ptr ) {
        // =-=-=-=-=-=-=-
        // check to see if this is for a resource plugin
        // resolution, otherwise it is an error
        if ( RESOURCE_INTERFACE != _interface ) {
            std::stringstream msg;
            msg << "file_object does not support a [";
            msg << _interface;
            msg << "] for plugin resolution";
            return ERROR( SYS_INVALID_INPUT_PARAM, msg.str() );
        }

        error result = SUCCESS();
        error ret;

        hierarchy_parser hparse;
        ret = hparse.set_string( resc_hier() );

        if ( !ret.ok() ) {
            std::stringstream msg;
            msg << "error parsing resource hierarchy \"" << resc_hier() << "\"";
            result = PASSMSG( msg.str(), ret );
        }
        else {
            std::string resc;

            ret = hparse.first_resc( resc );
            if ( !ret.ok() ) {
                std::stringstream msg;
                msg << __FUNCTION__ << " - ERROR getting first resource from hierarchy.";
                result = PASSMSG( msg.str(), ret );
            }
            else {

                if ( resc.empty() && resc_hier().empty() ) {
                    //std::stringstream msg;
                    //msg << __FUNCTION__
                    //    << " - there is no resource specified in the resource hierarchy.";
                    //log(LOG_NOTICE, msg.str());
                }
                else if ( resc.empty() ) {
                    return ERROR( HIERARCHY_ERROR, "Hierarchy string is not empty but first resource is!" );
                }

                resource_ptr resc_ptr;
                ret = resc_mgr.resolve( resc, resc_ptr );
                if ( !ret.ok() ) {
                    std::stringstream msg;
                    msg << __FUNCTION__ << " - ERROR resolving resource \"" << resc << "\"";
                    result = PASSMSG( msg.str(), ret );
                }

                _ptr = boost::dynamic_pointer_cast< resource >( resc_ptr );
            }
        }

        return result;

    } // resolve

// =-=-=-=-=-=-=-
// public - get vars from object for rule engine
    error file_object::get_re_vars(
        keyValPair_t& _kvp ) {
        data_object::get_re_vars( _kvp );

        copyKeyVal( &cond_input_, &_kvp );

        addKeyVal( &_kvp, LOGICAL_PATH_KW, logical_path_.c_str() );
        addKeyVal( &_kvp, DATA_TYPE_KW,    data_type_.c_str() );

        std::stringstream fd;
        fd << file_descriptor_;
        addKeyVal( &_kvp, FILE_DESCRIPTOR_KW, fd.str().c_str() );

        std::stringstream idx;
        idx << l1_desc_idx_;
        addKeyVal( &_kvp, L1_DESC_IDX_KW, idx.str().c_str() );

        std::stringstream sz;
        sz << size_;
        addKeyVal( &_kvp, SIZE_KW, sz.str().c_str() );

        std::stringstream repl;
        repl << repl_requested_;
        addKeyVal( &_kvp, REPL_REQUESTED_KW, repl.str().c_str() );

        std::stringstream pdmo;
        pdmo << in_pdmo_;
        addKeyVal( &_kvp, IN_PDMO_KW, pdmo.str().c_str() );

        return SUCCESS();

    } // get_re_vars

// =-=-=-=-=-=-=-
// static factory to create file_object from dataobjinfo linked list
    error file_object_factory( rsComm_t*        _comm,
                               dataObjInp_t*    _data_obj_inp,
                               file_object_ptr  _file_obj ) {
        // =-=-=-=-=-=-=-
        // if a repl is requested, cache that fact
        char* repl_num_ptr = getValByKey( &_data_obj_inp->condInput, REPL_NUM_KW );
        std::string repl_num;
        if ( repl_num_ptr ) {
            repl_num = repl_num_ptr;
            rmKeyVal( &_data_obj_inp->condInput, REPL_NUM_KW );
        }

        // =-=-=-=-=-=-=-
        // make a call to build the linked list
        dataObjInfo_t* head_ptr = 0;

        int status = getDataObjInfoIncSpecColl( _comm, _data_obj_inp, &head_ptr );
        if ( status < 0 ) {
            status = getDataObjInfo( _comm, _data_obj_inp, &head_ptr, 0, 0 );
        }
        if ( 0 == head_ptr || status < 0 ) {
            if ( head_ptr ) {
                freeAllDataObjInfo( head_ptr );
            }

            char* sys_error;
            char* rods_error = rodsErrorName( status, &sys_error );
            std::stringstream msg;
            msg << "failed in call to getDataObjInfoIncSpecColl";
            msg << " for [";
            msg << _data_obj_inp->objPath;
            msg << "] ";
            msg << rods_error << " " << sys_error;
            return ERROR( status, msg.str() );
        }

        // =-=-=-=-=-=-=-
        // replace the keyword
        if ( !repl_num.empty() ) {
            addKeyVal(
                &_data_obj_inp->condInput,
                REPL_NUM_KW,
                repl_num.c_str() );
        }

        // =-=-=-=-=-=-=-
        // start populating file_object
        _file_obj->comm( _comm );
        _file_obj->logical_path( _data_obj_inp->objPath );
        _file_obj->resc_hier( head_ptr->rescHier );
        _file_obj->cond_input( _data_obj_inp->condInput );

        // =-=-=-=-=-=-=-
        // handle requested repl number
        if ( !repl_num.empty() ) {
            _file_obj->repl_requested( atoi( repl_num.c_str() ) );
        }

        // handle the case where we are being called as part of a pdmo
        char* in_pdmo = getValByKey( &_data_obj_inp->condInput, IN_PDMO_KW );
        if ( in_pdmo ) {
            _file_obj->in_pdmo( in_pdmo );
        }

        // =-=-=-=-=-=-=-
        // iterate over the linked list and populate
        // the physical_object vector in the file_object
        dataObjInfo_t* info_ptr = head_ptr;
        std::vector< physical_object > objects;
        while ( info_ptr ) {
            physical_object obj;

            obj.is_dirty( info_ptr->replStatus );
            obj.repl_num( info_ptr->replNum );
            obj.map_id( info_ptr->dataMapId );
            obj.size( info_ptr->dataSize );
            obj.id( info_ptr->dataId );
            obj.coll_id( info_ptr->collId );
            obj.name( info_ptr->objPath );
            obj.version( info_ptr->version );
            obj.type_name( info_ptr->dataType );
            obj.resc_group_name( info_ptr->rescGroupName );
            obj.resc_name( info_ptr->rescName );
            obj.path( info_ptr->filePath );
            obj.owner_name( info_ptr->dataOwnerName );
            obj.owner_zone( info_ptr->dataOwnerZone );
            obj.status( info_ptr->statusString );
            obj.checksum( info_ptr->chksum );
            obj.expiry_ts( info_ptr->dataExpiry );
            obj.mode( info_ptr->dataMode );
            obj.r_comment( info_ptr->dataComments );
            obj.create_ts( info_ptr->dataCreate );
            obj.modify_ts( info_ptr->dataModify );
            obj.resc_hier( info_ptr->rescHier );

            objects.push_back( obj );
            info_ptr = info_ptr->next;

        } // while

        _file_obj->replicas( objects );

        //delete head_ptr->rescInfo;
        //free( head_ptr );
        freeAllDataObjInfo( head_ptr );
        return SUCCESS();

    } // file_object_factory

}; // namespace irods

<|endoftext|>


<commit_before>// Demonstration of estimating an RC network using MST
// to accompany "Analyzing On-Chip Interconnect with Modern C++"
// Author: Jeff Trull <edaskel@att.net>

/*
Copyright (c) 2014 Jeffrey E. Trull

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

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

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

#include <iostream>
#include <vector>

#include <boost/iterator/counting_iterator.hpp>
#include <boost/graph/prim_minimum_spanning_tree.hpp>
#include <boost/property_map/function_property_map.hpp>

#include "ckt_graph.h"

// Define an implicit graph class
struct pin_distance_graph {
    // For Prim we must model "Vertex List Graph" and "Incidence Graph"
    // Graph requirements
    typedef size_t vertex_descriptor;
    typedef std::pair<size_t, size_t> edge_descriptor;
    typedef boost::undirected_tag directed_category;
    typedef boost::disallow_parallel_edge_tag edge_parallel_category;
    // inherit traversal from both concepts
    struct traversal_category : virtual public boost::vertex_list_graph_tag,
                                virtual public boost::incidence_graph_tag {};

    // Vertex List Graph requirements
    typedef boost::counting_iterator<size_t> vertex_iterator;
    typedef size_t vertices_size_type;

    // Incidence Graph requirements
    // The most complicated part is generating new edges
    // We need to make a standard conforming edge iterator
    // The Boost.Iterator library can help us make a "forward iterator"
    struct  edge_iterator_t : boost::iterator_facade<edge_iterator_t,
                                                     edge_descriptor,
                                                     boost::forward_traversal_tag,
                                                     edge_descriptor const&> {
        // Implementation constrained by two things:
        // 1) We need to provide a default constructor, so sentinel cannot reference graph
        // 2) We need to provide a non-const dereference operator for Prim, so must keep
        //    a true edge descriptor around

        edge_iterator_t()
            : g_(nullptr) {}  // initialize to invalid
        edge_iterator_t(pin_distance_graph const* g, vertex_descriptor u)
            : current_edge_(std::make_pair(u, 0)), g_(g) {
            advance_to_legal();
        }
    private:
        friend class boost::iterator_core_access;
        // iterator_facade requirements:
        void increment() {
            current_edge_.second++;
            advance_to_legal();
        }
        bool equal(edge_iterator_t const& other) const {
            // true if both invalid, or they match source/dest
            if (invalid()) {
                return other.invalid();
            } else {
                return !other.invalid() && (current_edge_ == other.current_edge_);
            }
        }
        edge_descriptor const& dereference() const {
            return current_edge_;
        }
        // implementation details for above:
        bool invalid() const {
            return ((g_ == nullptr) || (current_edge_.second >= num_vertices(*g_)));
        }
        void advance_to_legal() {
            // ensure target and source are not the same
            if (current_edge_.first == current_edge_.second) {
                current_edge_.second++;
            }
        }
        edge_descriptor current_edge_;
        pin_distance_graph const* g_;
    };

    typedef edge_iterator_t out_edge_iterator;
    typedef size_t degree_size_type;

    // Vertex List Graph free functions
    friend std::pair<vertex_iterator, vertex_iterator>
    vertices(pin_distance_graph const& g) {
        return std::make_pair(vertex_iterator(0), vertex_iterator(g.points_.size()));
    }

    friend vertices_size_type num_vertices(pin_distance_graph const& g) {
        return g.points_.size();
    }

    // Incidence Graph free functions
    friend vertex_descriptor source(edge_descriptor const& e, pin_distance_graph const&) {
        return e.first;
    }

    friend vertex_descriptor target(edge_descriptor const& e, pin_distance_graph const&) {
        return e.second;
    }

    friend std::pair<out_edge_iterator, out_edge_iterator>
    out_edges(vertex_descriptor u, pin_distance_graph const& g) {
        return std::make_pair(edge_iterator_t(&g, u), edge_iterator_t());
    }

    friend degree_size_type
    out_degree(vertex_descriptor, pin_distance_graph const& g) {
        return g.points_.size() - 1;  // "complete" graph, every node connected to every other
    }

    // Main functionality
    typedef std::pair<int, int> point_t;
    template<typename PtIter>
    pin_distance_graph(PtIter beg, PtIter end) : points_(beg, end) {}

    // Provide bracket operator a la adjacency_list
    point_t operator[](vertex_descriptor u) const {
        return points_[u];
    }

private:
    std::vector<point_t> points_;

};

// Run Prim on it
// Prim seems vertex-focused, as opposed to the edge-focused Kruskal
// since our edges are implicit I favored the former

int main() {
    using namespace boost;
    using namespace std;

    // Data for implicit graph - a list of points
    vector<pair<int, int>> pinlocs =
        {{-100, -100}, {-100, 100}, {0, 0}, {100, 100}, {100, -100},
         {-50, 0}, {103, 100}, {100, 90}};

    pin_distance_graph pdg(pinlocs.begin(), pinlocs.end());

    // Create Prim requirements (temporary data structures used in algorithm)

    // vertex index map.  Since we use size_t for vertex descriptors, they
    // are immediately usable as indices:
    auto vindex_map = typed_identity_property_map<size_t>();

    // Predecessor map
    vector<pin_distance_graph::vertex_descriptor> predvec(num_vertices(pdg));   // underlying storage
    auto predpmap = make_iterator_property_map(predvec.begin(), vindex_map);

    // Weight Map
    // Another case where we can be "implicit" - the weight of an edge is
    // the Manhattan distance between the vertices
    typedef pin_distance_graph::edge_descriptor edge_t;
    auto weightpmap = make_function_property_map<edge_t>(
        [&pdg](edge_t e) -> int {
            auto coord1 = pdg[source(e, pdg)];
            auto coord2 = pdg[target(e, pdg)];
            return abs(coord1.first - coord2.first) + abs(coord1.second - coord2.second);
        });

    // call Prim
    prim_minimum_spanning_tree(pdg, predpmap,
                               weight_map(weightpmap).
                               vertex_index_map(vindex_map));

    // produce output as SVG
    cout << "<svg xmlns=\"http://www.w3.org/2000/svg\"" << endl;
    cout << "     xmlns:xlink=\"http://www.w3.org/1999/xlink\">" << endl;
    auto vitpair = vertices(pdg);
    for (auto v : make_iterator_range(vitpair.first, vitpair.second)) {
        // SVG wants positive numbers, and the Y coordinate is canvas style (reversed from Cartesian)
        // so we will transform the data en route to the display for viewability:
        // scale by 2X, mirror Y axis, and add 400 to both
        int x2 = 400 + 2*pdg[v].first;
        int y2 = 400 - 2*pdg[v].second;
        if (predvec[v] == v) {
            // Root.  Make a red circle
            cout << "    <circle cx=\"" << x2 << "\" cy=\"" << y2 << "\" r=\"10\" style=\"fill:#cc0000\"/>" << endl;
        } else {
            // Not Root: a gray one
            cout << "    <circle cx=\"" << x2 << "\" cy=\"" << y2 << "\" r=\"10\" style=\"fill:#cccccc; stroke:#222222\"/>" << endl;
        }
    }
    // Go back and add lines on top of the circles (for visibility)
    for (auto v : make_iterator_range(vitpair.first, vitpair.second)) {
        int x2 = 400 + 2*pdg[v].first;
        int y2 = 400 - 2*pdg[v].second;
        if (predvec[v] != v) {
            int x1 = 400 + 2*pdg[predvec[v]].first;
            int y1 = 400 - 2*pdg[predvec[v]].second;
            // Make a line to the successor node
            cout << "    <line x1=\"" << x1 << "\" y1=\"" << y1 << "\" x2=\"" << x2 << "\" y2=\"" << y2 << "\" style=\"stroke:#666666; stroke-width:3px\"/>" << endl;
        }
    }
    cout << "</svg>" << endl;

    // Future work: turn resulting tree into an implicit graph compatible with ckt_graph_t,
    // with estimated RC values on edges

}
<commit_msg>tweak rmst output for better viewing<commit_after>// Demonstration of estimating an RC network using MST
// to accompany "Analyzing On-Chip Interconnect with Modern C++"
// Author: Jeff Trull <edaskel@att.net>

/*
Copyright (c) 2014 Jeffrey E. Trull

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

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

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

#include <iostream>
#include <vector>

#include <boost/iterator/counting_iterator.hpp>
#include <boost/graph/prim_minimum_spanning_tree.hpp>
#include <boost/property_map/function_property_map.hpp>

#include "ckt_graph.h"

// Define an implicit graph class
struct pin_distance_graph {
    // For Prim we must model "Vertex List Graph" and "Incidence Graph"
    // Graph requirements
    typedef size_t vertex_descriptor;
    typedef std::pair<size_t, size_t> edge_descriptor;
    typedef boost::undirected_tag directed_category;
    typedef boost::disallow_parallel_edge_tag edge_parallel_category;
    // inherit traversal from both concepts
    struct traversal_category : virtual public boost::vertex_list_graph_tag,
                                virtual public boost::incidence_graph_tag {};

    // Vertex List Graph requirements
    typedef boost::counting_iterator<size_t> vertex_iterator;
    typedef size_t vertices_size_type;

    // Incidence Graph requirements
    // The most complicated part is generating new edges
    // We need to make a standard conforming edge iterator
    // The Boost.Iterator library can help us make a "forward iterator"
    struct  edge_iterator_t : boost::iterator_facade<edge_iterator_t,
                                                     edge_descriptor,
                                                     boost::forward_traversal_tag,
                                                     edge_descriptor const&> {
        // Implementation constrained by two things:
        // 1) We need to provide a default constructor, so sentinel cannot reference graph
        // 2) We need to provide a non-const dereference operator for Prim, so must keep
        //    a true edge descriptor around

        edge_iterator_t()
            : g_(nullptr) {}  // initialize to invalid
        edge_iterator_t(pin_distance_graph const* g, vertex_descriptor u)
            : current_edge_(std::make_pair(u, 0)), g_(g) {
            advance_to_legal();
        }
    private:
        friend class boost::iterator_core_access;
        // iterator_facade requirements:
        void increment() {
            current_edge_.second++;
            advance_to_legal();
        }
        bool equal(edge_iterator_t const& other) const {
            // true if both invalid, or they match source/dest
            if (invalid()) {
                return other.invalid();
            } else {
                return !other.invalid() && (current_edge_ == other.current_edge_);
            }
        }
        edge_descriptor const& dereference() const {
            return current_edge_;
        }
        // implementation details for above:
        bool invalid() const {
            return ((g_ == nullptr) || (current_edge_.second >= num_vertices(*g_)));
        }
        void advance_to_legal() {
            // ensure target and source are not the same
            if (current_edge_.first == current_edge_.second) {
                current_edge_.second++;
            }
        }
        edge_descriptor current_edge_;
        pin_distance_graph const* g_;
    };

    typedef edge_iterator_t out_edge_iterator;
    typedef size_t degree_size_type;

    // Vertex List Graph free functions
    friend std::pair<vertex_iterator, vertex_iterator>
    vertices(pin_distance_graph const& g) {
        return std::make_pair(vertex_iterator(0), vertex_iterator(g.points_.size()));
    }

    friend vertices_size_type num_vertices(pin_distance_graph const& g) {
        return g.points_.size();
    }

    // Incidence Graph free functions
    friend vertex_descriptor source(edge_descriptor const& e, pin_distance_graph const&) {
        return e.first;
    }

    friend vertex_descriptor target(edge_descriptor const& e, pin_distance_graph const&) {
        return e.second;
    }

    friend std::pair<out_edge_iterator, out_edge_iterator>
    out_edges(vertex_descriptor u, pin_distance_graph const& g) {
        return std::make_pair(edge_iterator_t(&g, u), edge_iterator_t());
    }

    friend degree_size_type
    out_degree(vertex_descriptor, pin_distance_graph const& g) {
        return g.points_.size() - 1;  // "complete" graph, every node connected to every other
    }

    // Main functionality
    typedef std::pair<int, int> point_t;
    template<typename PtIter>
    pin_distance_graph(PtIter beg, PtIter end) : points_(beg, end) {}

    // Provide bracket operator a la adjacency_list
    point_t operator[](vertex_descriptor u) const {
        return points_[u];
    }

private:
    std::vector<point_t> points_;

};

// Run Prim on it
// Prim seems vertex-focused, as opposed to the edge-focused Kruskal
// since our edges are implicit I favored the former

int main() {
    using namespace boost;
    using namespace std;

    // Data for implicit graph - a list of points
    vector<pair<int, int>> pinlocs =
        {{-100, -100}, {-100, 100}, {0, 0}, {100, 100}, {100, -100},
         {-50, 0}, {103, 100}, {100, 90}};

    pin_distance_graph pdg(pinlocs.begin(), pinlocs.end());

    // Create Prim requirements (temporary data structures used in algorithm)

    // vertex index map.  Since we use size_t for vertex descriptors, they
    // are immediately usable as indices:
    auto vindex_map = typed_identity_property_map<size_t>();

    // Predecessor map
    vector<pin_distance_graph::vertex_descriptor> predvec(num_vertices(pdg));   // underlying storage
    auto predpmap = make_iterator_property_map(predvec.begin(), vindex_map);

    // Weight Map
    // Another case where we can be "implicit" - the weight of an edge is
    // the Manhattan distance between the vertices
    typedef pin_distance_graph::edge_descriptor edge_t;
    auto weightpmap = make_function_property_map<edge_t>(
        [&pdg](edge_t e) -> int {
            auto coord1 = pdg[source(e, pdg)];
            auto coord2 = pdg[target(e, pdg)];
            return abs(coord1.first - coord2.first) + abs(coord1.second - coord2.second);
        });

    // call Prim
    prim_minimum_spanning_tree(pdg, predpmap,
                               weight_map(weightpmap).
                               vertex_index_map(vindex_map));

    // produce output as SVG
    cout << "<svg xmlns=\"http://www.w3.org/2000/svg\"" << endl;
    cout << "     xmlns:xlink=\"http://www.w3.org/1999/xlink\">" << endl;
    auto vitpair = vertices(pdg);
    for (auto v : make_iterator_range(vitpair.first, vitpair.second)) {
        // SVG wants positive numbers, and the Y coordinate is canvas style (reversed from Cartesian)
        // so we will transform the data en route to the display for viewability:
        // scale by 2X, mirror Y axis, and add 250 to both
        int x2 = 250 + 2*pdg[v].first;
        int y2 = 250 - 2*pdg[v].second;
        if (predvec[v] == v) {
            // Root.  Make a red circle
            cout << "    <circle cx=\"" << x2 << "\" cy=\"" << y2 << "\" r=\"10\" style=\"fill:#cc0000\"/>" << endl;
        } else {
            // Not Root: a gray one
            cout << "    <circle cx=\"" << x2 << "\" cy=\"" << y2 << "\" r=\"10\" style=\"fill:#cccccc; stroke:#222222\"/>" << endl;
        }
    }
    // Go back and add lines on top of the circles (for visibility)
    for (auto v : make_iterator_range(vitpair.first, vitpair.second)) {
        int x2 = 250 + 2*pdg[v].first;
        int y2 = 250 - 2*pdg[v].second;
        if (predvec[v] != v) {
            int x1 = 250 + 2*pdg[predvec[v]].first;
            int y1 = 250 - 2*pdg[predvec[v]].second;
            // Make a line to the successor node
            cout << "    <line x1=\"" << x1 << "\" y1=\"" << y1 << "\" x2=\"" << x2 << "\" y2=\"" << y2 << "\" style=\"stroke:#666666; stroke-width:3px\"/>" << endl;
        }
    }
    cout << "</svg>" << endl;

    // Future work: turn resulting tree into an implicit graph compatible with ckt_graph_t,
    // with estimated RC values on edges

}
<|endoftext|>


<commit_before>#ifndef STRING_SLICE_HPP
#define STRING_SLICE_HPP

#include <iostream>
#include <string>
#include <cstdlib>

/**
 * A non-owning view into part of a std::string.
 */
struct StringSlice {
	char const * iter {
		nullptr
	}; // Iterator to the beginning of the string slice
	char const * iter_end {
		nullptr
	}; // Iterator to the end of the string slice

	StringSlice()
	{}

	StringSlice(char const * iter, char const * iter_end): iter {iter}, iter_end {iter_end}
	{}

	StringSlice(std::string::const_iterator iter, std::string::const_iterator iter_end): iter {&(*iter)}, iter_end {&(*iter_end)}
	{}

	void set_begin(char const * begin) {
		iter = begin;
	}

	void set_begin(std::string::const_iterator begin) {
		iter = &(*begin);
	}

	void set_end(char const * end) {
		iter_end = end;
	}

	void set_end(std::string::const_iterator end) {
		iter_end = &(*end);
	}

	std::string to_string() const {
		if (iter != iter_end)
			return std::string(iter, iter_end);
		else
			return std::string("");
	}

	size_t length() const {
		return std::distance(iter, iter_end);
	}

	bool operator==(const StringSlice &other) const {
		const auto len = length();
		const auto other_len = other.length();
		if (len != other_len)
			return false;

		for (int i = 0; i < len; ++i) {
			if (iter[i] != other.iter[i])
				return false;
		}

		return true;
	}

	bool operator!=(const StringSlice &other) const {
		return !(*this == other);
	}

	bool operator==(const std::string &other) const {
		const auto len = length();
		const auto other_len = other.length();
		if (len != other_len)
			return false;

		auto other_iter = other.begin();
		for (int i = 0; i < len; ++i) {
			if (iter[i] != other_iter[i])
				return false;
		}

		return true;
	}

	bool operator!=(const std::string &other) const {
		return !(*this == other);
	}

	bool operator==(const char* const str) const {
		const auto len = length();

		int i = 0;
		for (; i < len; ++i) {
			if (iter[i] != str[i] || str[i] == '\0')
				return false;
		}

		if (str[i] != '\0')
			return false;

		return true;
	}

	bool operator!=(const char* const str) const {
		return !(*this == str);
	}
};

// Allows StringSlice to be used with iostreams
static std::ostream& operator<< (std::ostream& out, const StringSlice& strslc)
{
	const auto length = strslc.length();

	if (length == 0)
		return out;

	for (size_t i = 0; i < length; ++i)
		out << strslc.iter[i];

	return out;
}

// Allows string slice to be hashed, for use in e.g. unordered_map
namespace std
{
template<>
struct hash<StringSlice> {
	typedef StringSlice argument_type;
	typedef std::size_t result_type;

	result_type operator()(argument_type const& s) const {
		// TODO: something more efficient that avoids allocating
		// a std::string.
		return std::hash<std::string>()(s.to_string());
	}
};
}

#endif // STRING_SLICE_HPP<commit_msg>Better formatting and comments for StringSlice.<commit_after>#ifndef STRING_SLICE_HPP
#define STRING_SLICE_HPP

#include <iostream>
#include <string>
#include <cstdlib>

/**
 * A non-owning view into part of a std::string.
 */
struct StringSlice {
	char const * iter = nullptr; // Iterator to the beginning of the string slice
	char const * iter_end = nullptr; // Iterator to the end of the string slice

	// Constructors
	StringSlice()
	{}

	StringSlice(char const * iter, char const * iter_end): iter {iter}, iter_end {iter_end}
	{}

	StringSlice(std::string::const_iterator iter, std::string::const_iterator iter_end): iter {&(*iter)}, iter_end {&(*iter_end)}
	{}

	// Methods for setting the begin/end of the string slice
	void set_begin(char const * begin) {
		iter = begin;
	}

	void set_begin(std::string::const_iterator begin) {
		iter = &(*begin);
	}

	void set_end(char const * end) {
		iter_end = end;
	}

	void set_end(std::string::const_iterator end) {
		iter_end = &(*end);
	}

	// Returns the length of the string slice
	size_t length() const {
		return std::distance(iter, iter_end);
	}

	// Creates and returns a std::string from the string slice
	std::string to_string() const {
		if (iter != iter_end)
			return std::string(iter, iter_end);
		else
			return std::string("");
	}

	// Comparing string slices to various string representations
	bool operator==(const StringSlice &other) const {
		const auto len = length();
		const auto other_len = other.length();
		if (len != other_len)
			return false;

		for (int i = 0; i < len; ++i) {
			if (iter[i] != other.iter[i])
				return false;
		}

		return true;
	}

	bool operator!=(const StringSlice &other) const {
		return !(*this == other);
	}

	bool operator==(const std::string &other) const {
		const auto len = length();
		const auto other_len = other.length();
		if (len != other_len)
			return false;

		auto other_iter = other.begin();
		for (int i = 0; i < len; ++i) {
			if (iter[i] != other_iter[i])
				return false;
		}

		return true;
	}

	bool operator!=(const std::string &other) const {
		return !(*this == other);
	}

	bool operator==(const char* const str) const {
		const auto len = length();

		int i = 0;
		for (; i < len; ++i) {
			if (iter[i] != str[i] || str[i] == '\0')
				return false;
		}

		if (str[i] != '\0')
			return false;

		return true;
	}

	bool operator!=(const char* const str) const {
		return !(*this == str);
	}
};

// Allows StringSlice to be used with iostreams
static std::ostream& operator<< (std::ostream& out, const StringSlice& strslc)
{
	const auto length = strslc.length();

	if (length == 0)
		return out;

	for (size_t i = 0; i < length; ++i)
		out << strslc.iter[i];

	return out;
}

// Allows string slice to be hashed, for use in e.g. unordered_map
namespace std
{
template<>
struct hash<StringSlice> {
	typedef StringSlice argument_type;
	typedef std::size_t result_type;

	result_type operator()(argument_type const& s) const {
		// TODO: something more efficient that avoids allocating
		// a std::string.
		return std::hash<std::string>()(s.to_string());
	}
};
}

#endif // STRING_SLICE_HPP<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) <2015> <Stephan Gatzka>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE combined

#include <boost/test/unit_test.hpp>

#include "json/cJSON.h"
#include "peer.h"
#include "router.h"
#include "state.h"

enum event {
	UNKNOWN_EVENT,
	ADD_EVENT,
	CHANGE_EVENT,
	REMOVE_EVENT
};

static char send_buffer[100000];

static struct peer *fetch_peer_1;
static bool message_for_wrong_peer;

static enum event fetch_peer_1_event;

static cJSON *parse_send_buffer(void)
{
	char *read_ptr = send_buffer;
	const char *end_parse;
	cJSON *root = cJSON_ParseWithOpts(read_ptr, &end_parse, 0);
	return root;
}

static enum event get_event_from_json(cJSON *json)
{
	cJSON *params = cJSON_GetObjectItem(json, "params");
	if (params == NULL) return UNKNOWN_EVENT;
	cJSON *event = cJSON_GetObjectItem(params, "event");
	if (event == NULL) return UNKNOWN_EVENT;
	if (event->type != cJSON_String) return UNKNOWN_EVENT;
	if (strcmp(event->valuestring, "add") == 0) return ADD_EVENT;
	if (strcmp(event->valuestring, "change") == 0) return CHANGE_EVENT;
	if (strcmp(event->valuestring, "remove") == 0) return REMOVE_EVENT;
	return UNKNOWN_EVENT;
}

extern "C" {
	int send_message(struct peer *p, const char *rendered, size_t len)
	{
		memcpy(send_buffer, rendered, len);
		if (p == fetch_peer_1) {
			cJSON *fetch_event = parse_send_buffer();
			fetch_peer_1_event = get_event_from_json(fetch_event);
			cJSON_Delete(fetch_event);
		} else {
			message_for_wrong_peer = true;
		}
		return 0;
	}

	int add_io(struct peer *p)
	{
		return 0;
	}

	void remove_io(const struct peer *p)
	{
		return;
	}

	void remove_all_methods_from_peer(struct peer *p)
	{
	}
}

struct F {
	F()
	{
		create_state_hashtable();
		p = alloc_peer(-1);
		fetch_peer_1 = alloc_peer(-1);
		message_for_wrong_peer = false;
		fetch_peer_1_event = UNKNOWN_EVENT;
	}
	~F()
	{
		free_peer(fetch_peer_1);
		free_peer(p);
		delete_state_hashtable();
	}

	struct peer *p;
};

static cJSON *create_fetch_params(const char *path_equals_string, const char *path_startsWith_string, const char *path_endsWith_string, const char *path_contains, int ignore_case)
{
	cJSON *root = cJSON_CreateObject();
	BOOST_REQUIRE(root != NULL);
	cJSON_AddStringToObject(root, "id", "fetch_id_1");
	cJSON *path = cJSON_CreateObject();
	BOOST_REQUIRE(path != NULL);
	cJSON_AddItemToObject(root, "path", path);
	if (strlen(path_equals_string)) {
		cJSON_AddStringToObject(path, "equals", path_equals_string);
	}

	if (strlen(path_startsWith_string)) {
		cJSON_AddStringToObject(path, "startsWith", path_startsWith_string);
	}

	if (strlen(path_endsWith_string)) {
		cJSON_AddStringToObject(path, "endsWith", path_endsWith_string);
	}

	if (strlen(path_contains)) {
		cJSON_AddStringToObject(path, "contains", path_contains);
	}

	if (ignore_case) {
		cJSON_AddBoolToObject(root, "caseInsensitive", 1);
	}

	return root;
}

BOOST_FIXTURE_TEST_CASE(fetch_matchers, F)
{
	const char *path = "foo/bar";
	const char *path_upper = "FOO/BAR";
	const char *path_startsWith = "foo";
	const char *path_endsWith = "bar";
	const char *path_contains = "oo/ba";

	int state_value = 12345;

	{
		cJSON *value = cJSON_CreateNumber(state_value);

		cJSON *error = add_state_to_peer(p, path, value);
		BOOST_CHECK(error == NULL);

		cJSON_Delete(value);
	}

	struct state *s = get_state(path);
	BOOST_CHECK(s->value->valueint == state_value);
	{
		/// is to fail because fetch is case sensitive
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params(path_upper, "", "", "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == UNKNOWN_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params(path, "", "", "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params("", path_startsWith, "", "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params("", "", path_endsWith, "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params("", "", "", path_contains, 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}
}

BOOST_FIXTURE_TEST_CASE(fetch_matchers_ignoring_case, F)
{
	const char *path = "foo/bar";
	const char *path_upper = "FOO/BAR";
	const char *path_startsWith = "FOO";
	const char *path_endsWith = "BAR";
	const char *path_contains = "OO/BA";

	int state_value = 12345;

	{
		cJSON *value = cJSON_CreateNumber(state_value);

		cJSON *error = add_state_to_peer(p, path, value);
		BOOST_CHECK(error == NULL);
		cJSON_Delete(value);
	}

	struct state *s = get_state(path);
	BOOST_CHECK(s->value->valueint == state_value);

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params(path_upper, "", "", "", 1);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params("", path_startsWith, "", "", 1);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params("", "", path_endsWith, "", 1);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params("", "", "", path_contains, 1);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}
}

BOOST_FIXTURE_TEST_CASE(fetch_and_change_and_remove, F)
{
	const char *path = "foo/bar";

	int state_value = 12345;

	{
		/// does not fetch anything because nothing does match
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params(path, "", "", "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == UNKNOWN_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		cJSON *value = cJSON_CreateNumber(state_value);

		cJSON *error = add_state_to_peer(p, path, value);
		BOOST_CHECK(error == NULL);

		cJSON_Delete(value);
	}

	struct state *s = get_state(path);
	BOOST_CHECK(s->value->valueint == state_value);

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params(path, "", "", "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);

		cJSON *new_value = cJSON_CreateNumber(4321);
		error = change_state(p, path, new_value);
		BOOST_REQUIRE(error == NULL);
		cJSON_Delete(new_value);

		BOOST_CHECK(fetch_peer_1_event == CHANGE_EVENT);

		BOOST_CHECK(!message_for_wrong_peer);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		/// fetch removal of state
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params(path, "", "", "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		remove_state_from_peer(p, path);

		BOOST_CHECK(fetch_peer_1_event == REMOVE_EVENT);
	}
}
<commit_msg>Delete no longer required JSON parameter object.<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) <2015> <Stephan Gatzka>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE combined

#include <boost/test/unit_test.hpp>

#include "json/cJSON.h"
#include "peer.h"
#include "router.h"
#include "state.h"

enum event {
	UNKNOWN_EVENT,
	ADD_EVENT,
	CHANGE_EVENT,
	REMOVE_EVENT
};

static char send_buffer[100000];

static struct peer *fetch_peer_1;
static bool message_for_wrong_peer;

static enum event fetch_peer_1_event;

static cJSON *parse_send_buffer(void)
{
	char *read_ptr = send_buffer;
	const char *end_parse;
	cJSON *root = cJSON_ParseWithOpts(read_ptr, &end_parse, 0);
	return root;
}

static enum event get_event_from_json(cJSON *json)
{
	cJSON *params = cJSON_GetObjectItem(json, "params");
	if (params == NULL) return UNKNOWN_EVENT;
	cJSON *event = cJSON_GetObjectItem(params, "event");
	if (event == NULL) return UNKNOWN_EVENT;
	if (event->type != cJSON_String) return UNKNOWN_EVENT;
	if (strcmp(event->valuestring, "add") == 0) return ADD_EVENT;
	if (strcmp(event->valuestring, "change") == 0) return CHANGE_EVENT;
	if (strcmp(event->valuestring, "remove") == 0) return REMOVE_EVENT;
	return UNKNOWN_EVENT;
}

extern "C" {
	int send_message(struct peer *p, const char *rendered, size_t len)
	{
		memcpy(send_buffer, rendered, len);
		if (p == fetch_peer_1) {
			cJSON *fetch_event = parse_send_buffer();
			fetch_peer_1_event = get_event_from_json(fetch_event);
			cJSON_Delete(fetch_event);
		} else {
			message_for_wrong_peer = true;
		}
		return 0;
	}

	int add_io(struct peer *p)
	{
		return 0;
	}

	void remove_io(const struct peer *p)
	{
		return;
	}

	void remove_all_methods_from_peer(struct peer *p)
	{
	}
}

struct F {
	F()
	{
		create_state_hashtable();
		p = alloc_peer(-1);
		fetch_peer_1 = alloc_peer(-1);
		message_for_wrong_peer = false;
		fetch_peer_1_event = UNKNOWN_EVENT;
	}
	~F()
	{
		free_peer(fetch_peer_1);
		free_peer(p);
		delete_state_hashtable();
	}

	struct peer *p;
};

static cJSON *create_fetch_params(const char *path_equals_string, const char *path_startsWith_string, const char *path_endsWith_string, const char *path_contains, int ignore_case)
{
	cJSON *root = cJSON_CreateObject();
	BOOST_REQUIRE(root != NULL);
	cJSON_AddStringToObject(root, "id", "fetch_id_1");
	cJSON *path = cJSON_CreateObject();
	BOOST_REQUIRE(path != NULL);
	cJSON_AddItemToObject(root, "path", path);
	if (strlen(path_equals_string)) {
		cJSON_AddStringToObject(path, "equals", path_equals_string);
	}

	if (strlen(path_startsWith_string)) {
		cJSON_AddStringToObject(path, "startsWith", path_startsWith_string);
	}

	if (strlen(path_endsWith_string)) {
		cJSON_AddStringToObject(path, "endsWith", path_endsWith_string);
	}

	if (strlen(path_contains)) {
		cJSON_AddStringToObject(path, "contains", path_contains);
	}

	if (ignore_case) {
		cJSON_AddBoolToObject(root, "caseInsensitive", 1);
	}

	return root;
}

BOOST_FIXTURE_TEST_CASE(fetch_matchers, F)
{
	const char *path = "foo/bar";
	const char *path_upper = "FOO/BAR";
	const char *path_startsWith = "foo";
	const char *path_endsWith = "bar";
	const char *path_contains = "oo/ba";

	int state_value = 12345;

	{
		cJSON *value = cJSON_CreateNumber(state_value);

		cJSON *error = add_state_to_peer(p, path, value);
		BOOST_CHECK(error == NULL);

		cJSON_Delete(value);
	}

	struct state *s = get_state(path);
	BOOST_CHECK(s->value->valueint == state_value);
	{
		/// is to fail because fetch is case sensitive
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params(path_upper, "", "", "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == UNKNOWN_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params(path, "", "", "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params("", path_startsWith, "", "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params("", "", path_endsWith, "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params("", "", "", path_contains, 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}
}

BOOST_FIXTURE_TEST_CASE(fetch_matchers_ignoring_case, F)
{
	const char *path = "foo/bar";
	const char *path_upper = "FOO/BAR";
	const char *path_startsWith = "FOO";
	const char *path_endsWith = "BAR";
	const char *path_contains = "OO/BA";

	int state_value = 12345;

	{
		cJSON *value = cJSON_CreateNumber(state_value);

		cJSON *error = add_state_to_peer(p, path, value);
		BOOST_CHECK(error == NULL);
		cJSON_Delete(value);
	}

	struct state *s = get_state(path);
	BOOST_CHECK(s->value->valueint == state_value);

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params(path_upper, "", "", "", 1);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params("", path_startsWith, "", "", 1);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params("", "", path_endsWith, "", 1);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params("", "", "", path_contains, 1);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}
}

BOOST_FIXTURE_TEST_CASE(fetch_and_change_and_remove, F)
{
	const char *path = "foo/bar";

	int state_value = 12345;

	{
		/// does not fetch anything because nothing does match
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params(path, "", "", "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == UNKNOWN_EVENT);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		cJSON *value = cJSON_CreateNumber(state_value);

		cJSON *error = add_state_to_peer(p, path, value);
		BOOST_CHECK(error == NULL);

		cJSON_Delete(value);
	}

	struct state *s = get_state(path);
	BOOST_CHECK(s->value->valueint == state_value);

	{
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params(path, "", "", "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		BOOST_CHECK(fetch_peer_1_event == ADD_EVENT);

		cJSON *new_value = cJSON_CreateNumber(4321);
		error = change_state(p, path, new_value);
		BOOST_REQUIRE(error == NULL);
		cJSON_Delete(new_value);

		BOOST_CHECK(fetch_peer_1_event == CHANGE_EVENT);

		BOOST_CHECK(!message_for_wrong_peer);
		remove_all_fetchers_from_peer(fetch_peer_1);
		cJSON_Delete(params);
	}

	{
		/// fetch removal of state
		struct fetch *f = NULL;
		cJSON *params = create_fetch_params(path, "", "", "", 0);
		cJSON *error = add_fetch_to_peer(fetch_peer_1, params, &f);
		BOOST_REQUIRE(error == NULL);
		int ret = add_fetch_to_states(f);
		BOOST_REQUIRE(ret == 0);

		remove_state_from_peer(p, path);

		BOOST_CHECK(fetch_peer_1_event == REMOVE_EVENT);
		cJSON_Delete(params);
	}
}
<|endoftext|>


<commit_before>/*
 * The MIT License
 *
 * Copyright 2017-2018 Norwegian University of Technology
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef FMI4CPP_FMUINSTANCE_HPP
#define FMI4CPP_FMUINSTANCE_HPP

#include <vector>
#include <memory>

#include "FmuVariableAccessor.hpp"

namespace fmi4cpp::fmi2 {

    template <typename T>
    class FmuInstance: public FmuVariableAccessor {

    protected:

        double simulationTime_ = 0.0;

    public:

        const double getSimulationTime() const {
            return simulationTime_;
        }

        virtual std::shared_ptr<T> getModelDescription() const = 0;

        virtual fmi2Status setupExperiment(double startTime = 0.0, double stopTime = 0.0, double tolerance = 0.0) = 0;

        virtual fmi2Status enterInitializationMode() = 0;

        virtual fmi2Status exitInitializationMode() = 0;

        virtual fmi2Status reset() = 0;

        virtual fmi2Status terminate() = 0;

        virtual fmi2Status getFMUstate(fmi2FMUstate &state) = 0;
        virtual fmi2Status setFMUstate(fmi2FMUstate state) = 0;
        virtual fmi2Status freeFMUstate(fmi2FMUstate &state) = 0;

        virtual fmi2Status serializeFMUstate(const fmi2FMUstate &state, std::vector<fmi2Byte> &serializedState) = 0;
        virtual fmi2Status deSerializeFMUstate(fmi2FMUstate &state, const std::vector<fmi2Byte> &serializedState) = 0;

        virtual fmi2Status getDirectionalDerivative(
                const std::vector<fmi2ValueReference> &vUnkownRef,
                const std::vector<fmi2ValueReference> &vKnownRef,
                const std::vector<fmi2Real> &dvKnownRef,
                std::vector<fmi2Real> &dvUnknownRef) const = 0;

        virtual ~FmuInstance() = default;

    };

}

#endif //FMI4CPP_FMUINSTANCE_HPP
<commit_msg>fix typo<commit_after>/*
 * The MIT License
 *
 * Copyright 2017-2018 Norwegian University of Technology
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef FMI4CPP_FMUINSTANCE_HPP
#define FMI4CPP_FMUINSTANCE_HPP

#include <vector>
#include <memory>

#include "FmuVariableAccessor.hpp"

namespace fmi4cpp::fmi2 {

    template <typename T>
    class FmuInstance: public FmuVariableAccessor {

    protected:

        double simulationTime_ = 0.0;

    public:

        const double getSimulationTime() const {
            return simulationTime_;
        }

        virtual std::shared_ptr<T> getModelDescription() const = 0;

        virtual fmi2Status setupExperiment(double startTime = 0.0, double stopTime = 0.0, double tolerance = 0.0) = 0;

        virtual fmi2Status enterInitializationMode() = 0;

        virtual fmi2Status exitInitializationMode() = 0;

        virtual fmi2Status reset() = 0;

        virtual fmi2Status terminate() = 0;

        virtual fmi2Status getFMUstate(fmi2FMUstate &state) = 0;
        virtual fmi2Status setFMUstate(fmi2FMUstate state) = 0;
        virtual fmi2Status freeFMUstate(fmi2FMUstate &state) = 0;

        virtual fmi2Status serializeFMUstate(const fmi2FMUstate &state, std::vector<fmi2Byte> &serializedState) = 0;
        virtual fmi2Status deSerializeFMUstate(fmi2FMUstate &state, const std::vector<fmi2Byte> &serializedState) = 0;

        virtual fmi2Status getDirectionalDerivative(
                const std::vector<fmi2ValueReference> &vUnknownRef,
                const std::vector<fmi2ValueReference> &vKnownRef,
                const std::vector<fmi2Real> &dvKnownRef,
                std::vector<fmi2Real> &dvUnknownRef) const = 0;

        virtual ~FmuInstance() = default;

    };

}

#endif //FMI4CPP_FMUINSTANCE_HPP
<|endoftext|>


<commit_before><commit_msg>Create 12908 - The book thief.cpp<commit_after><|endoftext|>