<commit_before>// Author: Enrico Guiraud, Danilo Piparo CERN  09/2017

/*************************************************************************
 * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_RDATASOURCE
#define ROOT_RDATASOURCE

#include "ROOT/RStringView.hxx"
#include "RtypesCore.h" // ULong64_t
#include <algorithm>    // std::transform
#include <vector>
#include <typeinfo>

namespace ROOT {
namespace RDF {
   class RDataSource;
}
}

/// Print a RDataSource at the prompt
namespace cling {
std::string printValue(ROOT::RDF::RDataSource *ds);
} // namespace cling

namespace ROOT {

namespace Internal {
namespace TDS {

/// Mother class of TTypedPointerHolder. The instances
/// of this class can be put in a container. Upon destruction,
/// the correct deletion of the pointer is performed in the
/// derived class.
class TPointerHolder {
protected:
   void *fPointer{nullptr};

public:
   TPointerHolder(void *ptr) : fPointer(ptr) {}
   void *GetPointer() { return fPointer; }
   void *GetPointerAddr() { return &fPointer; }
   virtual TPointerHolder *GetDeepCopy() = 0;
   virtual ~TPointerHolder(){};
};

/// Class to wrap a pointer and delete the memory associated to it
/// correctly
template <typename T>
class TTypedPointerHolder final : public TPointerHolder {
public:
   TTypedPointerHolder(T *ptr) : TPointerHolder((void *)ptr) {}

   virtual TPointerHolder *GetDeepCopy()
   {
      const auto typedPtr = static_cast<T *>(fPointer);
      return new TTypedPointerHolder(new T(*typedPtr));
   }

   ~TTypedPointerHolder() { delete static_cast<T *>(fPointer); }
};

} // ns TDS
} // ns Internal

namespace RDF {

// clang-format off
/**
\class ROOT::RDF::RDataSource
\ingroup dataframe
\brief RDataSource defines an API that RDataFrame can use to read arbitrary data formats.

A concrete RDataSource implementation (i.e. a class that inherits from RDataSource and implements all of its pure
methods) provides an adaptor that RDataFrame can leverage to read any kind of tabular data formats.
RDataFrame calls into RDataSource to retrieve information about the data, retrieve (thread-local) readers or "cursors"
for selected columns and to advance the readers to the desired data entry.

The sequence of calls that RDataFrame (or any other client of a RDataSource) performs is the following:

 - SetNSlots() : inform RDataSource of the desired level of parallelism
 - GetColumnReaders() : retrieve from RDataSource per-thread readers for the desired columns
 - Initialise() : inform RDataSource that an event-loop is about to start
 - GetEntryRanges() : retrieve from RDataSource a set of ranges of entries that can be processed concurrently
 - InitSlot() : inform RDataSource that a certain thread is about to start working on a certain range of entries
 - SetEntry() : inform RDataSource that a certain thread is about to start working on a certain entry
 - FinaliseSlot() : inform RDataSource that a certain thread finished working on a certain range of entries
 - Finalise() : inform RDataSource that an event-loop finished

RDataSource implementations must support running multiple event-loops consecutively (although sequentially) on the same dataset.
 - \b SetNSlots() is called once per RDataSource object, typically when it is associated to a RDataFrame.
 - \b GetColumnReaders() can be called several times, potentially with the same arguments, also in-between event-loops, but not during an event-loop.
 - \b Initialise() and \b Finalise() are called once per event-loop,  right before starting and right after finishing.
 - \b InitSlot(), \b SetEntry(), and \b FinaliseSlot() can be called concurrently from multiple threads, multiple times per event-loop.
*/
class RDataSource {
   // clang-format on
protected:
   using Record_t = std::vector<void *>;
   friend std::string cling::printValue(::ROOT::RDF::RDataSource *);

   virtual std::string AsString() {return "generic data source";};

public:
   virtual ~RDataSource() = default;

   // clang-format off
   /// \brief Inform RDataSource of the number of processing slots (i.e. worker threads) used by the associated RDataFrame.
   /// Slots numbers are used to simplify parallel execution: RDataFrame guarantees that different threads will always
   /// pass different slot values when calling methods concurrently.
   // clang-format on
   virtual void SetNSlots(unsigned int nSlots) = 0;

   // clang-format off
   /// \brief Returns a reference to the collection of the dataset's column names
   // clang-format on
   virtual const std::vector<std::string> &GetColumnNames() const = 0;

   /// \brief Checks if the dataset has a certain column
   /// \param[in] columnName The name of the column
   virtual bool HasColumn(std::string_view) const = 0;

   // clang-format off
   /// \brief Type of a column as a string, e.g. `GetTypeName("x") == "double"`. Required for jitting e.g. `df.Filter("x>0")`.
   /// \param[in] columnName The name of the column
   // clang-format on
   virtual std::string GetTypeName(std::string_view) const = 0;

   // clang-format off
   /// Called at most once per column by RDF. Return vector of pointers to pointers to column values - one per slot.
   /// \tparam T The type of the data stored in the column
   /// \param[in] columnName The name of the column
   ///
   /// These pointers are veritable cursors: it's a responsibility of the RDataSource implementation that they point to
   /// the "right" memory region.
   // clang-format on
   template <typename T>
   std::vector<T **> GetColumnReaders(std::string_view columnName)
   {
      auto typeErasedVec = GetColumnReadersImpl(columnName, typeid(T));
      std::vector<T **> typedVec(typeErasedVec.size());
      std::transform(typeErasedVec.begin(), typeErasedVec.end(), typedVec.begin(),
                     [](void *p) { return static_cast<T **>(p); });
      return typedVec;
   }

   // clang-format off
   /// \brief Return ranges of entries to distribute to tasks.
   /// They are required to be contiguous intervals with no entries skipped. Supposing a dataset with nEntries, the
   /// intervals must start at 0 and end at nEntries, e.g. [0-5],[5-10] for 10 entries.
   // clang-format on
   virtual std::vector<std::pair<ULong64_t, ULong64_t>> GetEntryRanges() = 0;

   // clang-format off
   /// \brief Advance the "cursors" returned by GetColumnReaders to the selected entry for a particular slot.
   /// \param[in] slot The data processing slot that needs to be considered
   /// \param[in] entry The entry which needs to be pointed to by the reader pointers
   /// Slots are adopted to accommodate parallel data processing.
   /// Different workers will loop over different ranges and
   /// will be labelled by different "slot" values.
   /// Returns *true* if the entry has to be processed, *false* otherwise.
   // clang-format on
   virtual bool SetEntry(unsigned int slot, ULong64_t entry) = 0;

   // clang-format off
   /// \brief Convenience method called before starting an event-loop.
   /// This method might be called multiple times over the lifetime of a RDataSource, since
   /// users can run multiple event-loops with the same RDataFrame.
   /// Ideally, `Initialise` should set the state of the RDataSource so that multiple identical event-loops
   /// will produce identical results.
   // clang-format on
   virtual void Initialise() {}

   // clang-format off
   /// \brief Convenience method called at the start of the data processing associated to a slot.
   /// \param[in] slot The data processing slot wihch needs to be initialised
   /// \param[in] firstEntry The first entry of the range that the task will process.
   /// This method might be called multiple times per thread per event-loop.
   // clang-format on
   virtual void InitSlot(unsigned int /*slot*/, ULong64_t /*firstEntry*/) {}

   // clang-format off
   /// \brief Convenience method called at the end of the data processing associated to a slot.
   /// \param[in] slot The data processing slot wihch needs to be finalised
   /// This method might be called multiple times per thread per event-loop.
   // clang-format on
   virtual void FinaliseSlot(unsigned int /*slot*/) {}

   // clang-format off
   /// \brief Convenience method called after concluding an event-loop.
   /// See Initialise for more details.
   // clang-format on
   virtual void Finalise() {}

protected:
   /// type-erased vector of pointers to pointers to column values - one per slot
   virtual Record_t GetColumnReadersImpl(std::string_view name, const std::type_info &) = 0;
};

} // ns RDF

} // ns ROOT

/// Print a RDataSource at the prompt
namespace cling {
inline std::string printValue(ROOT::RDF::RDataSource *ds) {
   return ds->AsString();
}
} // namespace cling

#endif // ROOT_TDATASOURCE
<commit_msg>[RDF] Fix build on osx making the string include explicit<commit_after>// Author: Enrico Guiraud, Danilo Piparo CERN  09/2017

/*************************************************************************
 * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_RDATASOURCE
#define ROOT_RDATASOURCE

#include "ROOT/RStringView.hxx"
#include "RtypesCore.h" // ULong64_t
#include <algorithm>    // std::transform
#include <string>
#include <vector>
#include <typeinfo>

namespace ROOT {
namespace RDF {
   class RDataSource;
}
}

/// Print a RDataSource at the prompt
namespace cling {
std::string printValue(ROOT::RDF::RDataSource *ds);
} // namespace cling

namespace ROOT {

namespace Internal {
namespace TDS {

/// Mother class of TTypedPointerHolder. The instances
/// of this class can be put in a container. Upon destruction,
/// the correct deletion of the pointer is performed in the
/// derived class.
class TPointerHolder {
protected:
   void *fPointer{nullptr};

public:
   TPointerHolder(void *ptr) : fPointer(ptr) {}
   void *GetPointer() { return fPointer; }
   void *GetPointerAddr() { return &fPointer; }
   virtual TPointerHolder *GetDeepCopy() = 0;
   virtual ~TPointerHolder(){};
};

/// Class to wrap a pointer and delete the memory associated to it
/// correctly
template <typename T>
class TTypedPointerHolder final : public TPointerHolder {
public:
   TTypedPointerHolder(T *ptr) : TPointerHolder((void *)ptr) {}

   virtual TPointerHolder *GetDeepCopy()
   {
      const auto typedPtr = static_cast<T *>(fPointer);
      return new TTypedPointerHolder(new T(*typedPtr));
   }

   ~TTypedPointerHolder() { delete static_cast<T *>(fPointer); }
};

} // ns TDS
} // ns Internal

namespace RDF {

// clang-format off
/**
\class ROOT::RDF::RDataSource
\ingroup dataframe
\brief RDataSource defines an API that RDataFrame can use to read arbitrary data formats.

A concrete RDataSource implementation (i.e. a class that inherits from RDataSource and implements all of its pure
methods) provides an adaptor that RDataFrame can leverage to read any kind of tabular data formats.
RDataFrame calls into RDataSource to retrieve information about the data, retrieve (thread-local) readers or "cursors"
for selected columns and to advance the readers to the desired data entry.

The sequence of calls that RDataFrame (or any other client of a RDataSource) performs is the following:

 - SetNSlots() : inform RDataSource of the desired level of parallelism
 - GetColumnReaders() : retrieve from RDataSource per-thread readers for the desired columns
 - Initialise() : inform RDataSource that an event-loop is about to start
 - GetEntryRanges() : retrieve from RDataSource a set of ranges of entries that can be processed concurrently
 - InitSlot() : inform RDataSource that a certain thread is about to start working on a certain range of entries
 - SetEntry() : inform RDataSource that a certain thread is about to start working on a certain entry
 - FinaliseSlot() : inform RDataSource that a certain thread finished working on a certain range of entries
 - Finalise() : inform RDataSource that an event-loop finished

RDataSource implementations must support running multiple event-loops consecutively (although sequentially) on the same dataset.
 - \b SetNSlots() is called once per RDataSource object, typically when it is associated to a RDataFrame.
 - \b GetColumnReaders() can be called several times, potentially with the same arguments, also in-between event-loops, but not during an event-loop.
 - \b Initialise() and \b Finalise() are called once per event-loop,  right before starting and right after finishing.
 - \b InitSlot(), \b SetEntry(), and \b FinaliseSlot() can be called concurrently from multiple threads, multiple times per event-loop.
*/
class RDataSource {
   // clang-format on
protected:
   using Record_t = std::vector<void *>;
   friend std::string cling::printValue(::ROOT::RDF::RDataSource *);

   virtual std::string AsString() {return "generic data source";};

public:
   virtual ~RDataSource() = default;

   // clang-format off
   /// \brief Inform RDataSource of the number of processing slots (i.e. worker threads) used by the associated RDataFrame.
   /// Slots numbers are used to simplify parallel execution: RDataFrame guarantees that different threads will always
   /// pass different slot values when calling methods concurrently.
   // clang-format on
   virtual void SetNSlots(unsigned int nSlots) = 0;

   // clang-format off
   /// \brief Returns a reference to the collection of the dataset's column names
   // clang-format on
   virtual const std::vector<std::string> &GetColumnNames() const = 0;

   /// \brief Checks if the dataset has a certain column
   /// \param[in] columnName The name of the column
   virtual bool HasColumn(std::string_view) const = 0;

   // clang-format off
   /// \brief Type of a column as a string, e.g. `GetTypeName("x") == "double"`. Required for jitting e.g. `df.Filter("x>0")`.
   /// \param[in] columnName The name of the column
   // clang-format on
   virtual std::string GetTypeName(std::string_view) const = 0;

   // clang-format off
   /// Called at most once per column by RDF. Return vector of pointers to pointers to column values - one per slot.
   /// \tparam T The type of the data stored in the column
   /// \param[in] columnName The name of the column
   ///
   /// These pointers are veritable cursors: it's a responsibility of the RDataSource implementation that they point to
   /// the "right" memory region.
   // clang-format on
   template <typename T>
   std::vector<T **> GetColumnReaders(std::string_view columnName)
   {
      auto typeErasedVec = GetColumnReadersImpl(columnName, typeid(T));
      std::vector<T **> typedVec(typeErasedVec.size());
      std::transform(typeErasedVec.begin(), typeErasedVec.end(), typedVec.begin(),
                     [](void *p) { return static_cast<T **>(p); });
      return typedVec;
   }

   // clang-format off
   /// \brief Return ranges of entries to distribute to tasks.
   /// They are required to be contiguous intervals with no entries skipped. Supposing a dataset with nEntries, the
   /// intervals must start at 0 and end at nEntries, e.g. [0-5],[5-10] for 10 entries.
   // clang-format on
   virtual std::vector<std::pair<ULong64_t, ULong64_t>> GetEntryRanges() = 0;

   // clang-format off
   /// \brief Advance the "cursors" returned by GetColumnReaders to the selected entry for a particular slot.
   /// \param[in] slot The data processing slot that needs to be considered
   /// \param[in] entry The entry which needs to be pointed to by the reader pointers
   /// Slots are adopted to accommodate parallel data processing.
   /// Different workers will loop over different ranges and
   /// will be labelled by different "slot" values.
   /// Returns *true* if the entry has to be processed, *false* otherwise.
   // clang-format on
   virtual bool SetEntry(unsigned int slot, ULong64_t entry) = 0;

   // clang-format off
   /// \brief Convenience method called before starting an event-loop.
   /// This method might be called multiple times over the lifetime of a RDataSource, since
   /// users can run multiple event-loops with the same RDataFrame.
   /// Ideally, `Initialise` should set the state of the RDataSource so that multiple identical event-loops
   /// will produce identical results.
   // clang-format on
   virtual void Initialise() {}

   // clang-format off
   /// \brief Convenience method called at the start of the data processing associated to a slot.
   /// \param[in] slot The data processing slot wihch needs to be initialised
   /// \param[in] firstEntry The first entry of the range that the task will process.
   /// This method might be called multiple times per thread per event-loop.
   // clang-format on
   virtual void InitSlot(unsigned int /*slot*/, ULong64_t /*firstEntry*/) {}

   // clang-format off
   /// \brief Convenience method called at the end of the data processing associated to a slot.
   /// \param[in] slot The data processing slot wihch needs to be finalised
   /// This method might be called multiple times per thread per event-loop.
   // clang-format on
   virtual void FinaliseSlot(unsigned int /*slot*/) {}

   // clang-format off
   /// \brief Convenience method called after concluding an event-loop.
   /// See Initialise for more details.
   // clang-format on
   virtual void Finalise() {}

protected:
   /// type-erased vector of pointers to pointers to column values - one per slot
   virtual Record_t GetColumnReadersImpl(std::string_view name, const std::type_info &) = 0;
};

} // ns RDF

} // ns ROOT

/// Print a RDataSource at the prompt
namespace cling {
inline std::string printValue(ROOT::RDF::RDataSource *ds) {
   return ds->AsString();
}
} // namespace cling

#endif // ROOT_TDATASOURCE
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "rdostudioframeview.h"
#include "rdostudioframedoc.h"
#include "rdostudiomodel.h"
#include "rdostudioapp.h"
#include "rdostudiomainfrm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// ----------------------------------------------------------------------------
// ---------- RDOStudioFrameView
// ----------------------------------------------------------------------------
IMPLEMENT_DYNCREATE(RDOStudioFrameView, CView)

BEGIN_MESSAGE_MAP(RDOStudioFrameView, CView)
	//{{AFX_MSG_MAP(RDOStudioFrameView)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_SETFOCUS()
	ON_WM_SIZE()
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	//}}AFX_MSG_MAP
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

RDOStudioFrameView::RDOStudioFrameView():
	CView(),
	frameBmpRect( 0, 0, 0, 0 ),
	newClientRect( 0, 0, 0, 0 ),
	xPos( 0 ),
	yPos( 0 ),
	bgColor( studioApp.mainFrame->style_frame.theme->backgroundColor ),
	mustBeInit( true )
{
	dc.CreateCompatibleDC( NULL );
}

RDOStudioFrameView::~RDOStudioFrameView()
{
}

BOOL RDOStudioFrameView::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CView::PreCreateWindow( cs ) ) return FALSE;

	cs.style &= ~WS_BORDER;
	cs.style |= WS_HSCROLL | WS_VSCROLL;
	cs.lpszClass = AfxRegisterWndClass( 0, ::LoadCursor(NULL, IDC_ARROW) );

	return TRUE;
}

int RDOStudioFrameView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if ( CView::OnCreate(lpCreateStruct) == -1 ) return -1;

	updateScrollBars();

	return 0;
}

void RDOStudioFrameView::OnDraw(CDC* pDC)
{
//	RDOStudioFrameDoc* pDoc = GetDocument();
//	ASSERT_VALID(pDoc);

	int index = model->frameManager.findFrameIndex( this );
	CSingleLock lock_draw( model->frameManager.getFrameDraw( index ) );
	lock_draw.Lock();

	GetClientRect( &newClientRect );

	CBitmap* pOldBitmap = dc.SelectObject( &frameBmp );
/*
	pDC->SetStretchBltMode( HALFTONE );
	double k1 = (double)newClientRect.bottom / frameBmpRect.bottom;
	double k2 = (double)newClientRect.right / frameBmpRect.right;
	double k = min( k1, k2 );
	if ( k > 1 ) k = 1;
	CRect rect( 0, 0, frameBmpRect.right * k, frameBmpRect.bottom * k );
	rect.OffsetRect( (newClientRect.right - rect.right) / 2, (newClientRect.bottom - rect.bottom) / 2 );
	pDC->StretchBlt( rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, &dc, 0, 0, frameBmpRect.right, frameBmpRect.bottom, SRCCOPY );
	if ( rect.left ) {
		pDC->FillSolidRect( 0, 0, rect.left, newClientRect.bottom, bgColor );
		pDC->FillSolidRect( rect.right, 0, newClientRect.right, newClientRect.bottom, bgColor );
	}
	if ( rect.top ) {
		pDC->FillSolidRect( 0, 0, newClientRect.right, rect.top, bgColor );
		pDC->FillSolidRect( 0, rect.bottom, newClientRect.right, newClientRect.bottom, bgColor );
	}
*/

	pDC->BitBlt( 0, 0, newClientRect.right, newClientRect.bottom, &dc, xPos, yPos, SRCCOPY );
	if ( newClientRect.right - frameBmpRect.right > 0 ) {
		pDC->FillSolidRect( frameBmpRect.right, 0, newClientRect.right - frameBmpRect.right, newClientRect.bottom, bgColor );
	}
	if ( newClientRect.bottom - frameBmpRect.bottom > 0 ) {
		pDC->FillSolidRect( 0, frameBmpRect.bottom, newClientRect.right, newClientRect.bottom - frameBmpRect.bottom, bgColor );
	}

	dc.SelectObject( pOldBitmap );

	lock_draw.Unlock();

	model->frameManager.getFrameTimer( index )->SetEvent();
}

BOOL RDOStudioFrameView::OnPreparePrinting(CPrintInfo* pInfo)
{
	return DoPreparePrinting(pInfo);
}

void RDOStudioFrameView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
}

void RDOStudioFrameView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
}

#ifdef _DEBUG
void RDOStudioFrameView::AssertValid() const
{
	CView::AssertValid();
}

void RDOStudioFrameView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

RDOStudioFrameDoc* RDOStudioFrameView::GetDocument()
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(RDOStudioFrameDoc)));
	return (RDOStudioFrameDoc*)m_pDocument;
}
#endif

void RDOStudioFrameView::OnDestroy()
{
	model->frameManager.getFrameClose( model->frameManager.findFrameIndex( this ) )->SetEvent();
	model->frameManager.disconnectFrameDoc( GetDocument() );
	CView::OnDestroy();
}

void RDOStudioFrameView::OnSetFocus(CWnd* pOldWnd)
{
	CView::OnSetFocus( pOldWnd );
	model->frameManager.setLastShowedFrame( model->frameManager.findFrameIndex( this ) );
}

void RDOStudioFrameView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	GetClientRect( &newClientRect );

	updateScrollBars();
}

void RDOStudioFrameView::updateScrollBars()
{
	SCROLLINFO si;
	si.cbSize = sizeof( si );
	si.fMask  = SIF_RANGE | SIF_PAGE | SIF_POS;

	if ( xPos > frameBmpRect.right - newClientRect.right ) xPos = frameBmpRect.right - newClientRect.right;
	if ( xPos < 0 ) xPos = 0;
	si.nMin   = 0;
	si.nMax   = frameBmpRect.right;
	si.nPos   = xPos;
	si.nPage  = newClientRect.right;
	SetScrollInfo( SB_HORZ, &si, TRUE );

	if ( yPos > frameBmpRect.bottom - newClientRect.bottom ) yPos = frameBmpRect.bottom - newClientRect.bottom;
	if ( yPos < 0 ) yPos = 0;
	si.nMin   = 0;
	si.nMax   = frameBmpRect.bottom;
	si.nPos   = yPos;
	si.nPage  = newClientRect.bottom;
	SetScrollInfo( SB_VERT, &si, TRUE );
}

void RDOStudioFrameView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	SCROLLINFO si;
	si.cbSize = sizeof( si );
	switch( nSBCode ) {
		case SB_PAGEUP:
			GetScrollInfo( SB_HORZ, &si, SIF_PAGE );
			xPos -= si.nPage;
			break;

		case SB_PAGEDOWN:
			GetScrollInfo( SB_HORZ, &si, SIF_PAGE );
			xPos += si.nPage;
			break;

		case SB_LINEUP:
			xPos--;
			break;

		case SB_LINEDOWN:
			xPos++;
			break;

		case SB_THUMBTRACK: {
			GetScrollInfo( SB_HORZ, &si, SIF_TRACKPOS );
			xPos += si.nTrackPos - xPos;
			break;
		}
	}
	if ( xPos > frameBmpRect.right - newClientRect.right ) xPos = frameBmpRect.right - newClientRect.right;
	if ( xPos < 0 ) xPos = 0;
	si.fMask = SIF_POS;
	si.nPos  = xPos;
	SetScrollInfo( SB_HORZ, &si, TRUE );
	InvalidateRect( NULL );
	UpdateWindow();
}

void RDOStudioFrameView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	SCROLLINFO si;
	si.cbSize = sizeof( si );
	switch( nSBCode ) {
		case SB_PAGEUP:
			GetScrollInfo( SB_VERT, &si, SIF_PAGE );
			yPos -= si.nPage;
			break;

		case SB_PAGEDOWN:
			GetScrollInfo( SB_VERT, &si, SIF_PAGE );
			yPos += si.nPage;
			break;

		case SB_LINEUP:
			yPos--;
			break;

		case SB_LINEDOWN:
			yPos++;
			break;

		case SB_THUMBTRACK: {
			GetScrollInfo( SB_VERT, &si, SIF_TRACKPOS );
			yPos += si.nTrackPos - yPos;
			break;
		}
	}
	if ( yPos > frameBmpRect.bottom - newClientRect.bottom ) yPos = frameBmpRect.bottom - newClientRect.bottom;
	if ( yPos < 0 ) yPos = 0;
	si.fMask = SIF_POS;
	si.nPos  = yPos;
	SetScrollInfo( SB_VERT, &si, TRUE );
	InvalidateRect( NULL );
	UpdateWindow();
}
<commit_msg>don't draw not inited bmp<commit_after>#include "stdafx.h"
#include "rdostudioframeview.h"
#include "rdostudioframedoc.h"
#include "rdostudiomodel.h"
#include "rdostudioapp.h"
#include "rdostudiomainfrm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// ----------------------------------------------------------------------------
// ---------- RDOStudioFrameView
// ----------------------------------------------------------------------------
IMPLEMENT_DYNCREATE(RDOStudioFrameView, CView)

BEGIN_MESSAGE_MAP(RDOStudioFrameView, CView)
	//{{AFX_MSG_MAP(RDOStudioFrameView)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_SETFOCUS()
	ON_WM_SIZE()
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	//}}AFX_MSG_MAP
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

RDOStudioFrameView::RDOStudioFrameView():
	CView(),
	frameBmpRect( 0, 0, 0, 0 ),
	newClientRect( 0, 0, 0, 0 ),
	xPos( 0 ),
	yPos( 0 ),
	bgColor( studioApp.mainFrame->style_frame.theme->backgroundColor ),
	mustBeInit( true )
{
	dc.CreateCompatibleDC( NULL );
}

RDOStudioFrameView::~RDOStudioFrameView()
{
}

BOOL RDOStudioFrameView::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CView::PreCreateWindow( cs ) ) return FALSE;

	cs.style &= ~WS_BORDER;
	cs.style |= WS_HSCROLL | WS_VSCROLL;
	cs.lpszClass = AfxRegisterWndClass( 0, ::LoadCursor(NULL, IDC_ARROW) );

	return TRUE;
}

int RDOStudioFrameView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if ( CView::OnCreate(lpCreateStruct) == -1 ) return -1;

	updateScrollBars();

	return 0;
}

void RDOStudioFrameView::OnDraw(CDC* pDC)
{
//	RDOStudioFrameDoc* pDoc = GetDocument();
//	ASSERT_VALID(pDoc);

	int index = model->frameManager.findFrameIndex( this );
	CSingleLock lock_draw( model->frameManager.getFrameDraw( index ) );
	lock_draw.Lock();

	GetClientRect( &newClientRect );

	if ( !mustBeInit ) {
		CBitmap* pOldBitmap = dc.SelectObject( &frameBmp );
/*
		pDC->SetStretchBltMode( HALFTONE );
		double k1 = (double)newClientRect.bottom / frameBmpRect.bottom;
		double k2 = (double)newClientRect.right / frameBmpRect.right;
		double k = min( k1, k2 );
		if ( k > 1 ) k = 1;
		CRect rect( 0, 0, frameBmpRect.right * k, frameBmpRect.bottom * k );
		rect.OffsetRect( (newClientRect.right - rect.right) / 2, (newClientRect.bottom - rect.bottom) / 2 );
		pDC->StretchBlt( rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, &dc, 0, 0, frameBmpRect.right, frameBmpRect.bottom, SRCCOPY );
		if ( rect.left ) {
			pDC->FillSolidRect( 0, 0, rect.left, newClientRect.bottom, bgColor );
			pDC->FillSolidRect( rect.right, 0, newClientRect.right, newClientRect.bottom, bgColor );
		}
		if ( rect.top ) {
			pDC->FillSolidRect( 0, 0, newClientRect.right, rect.top, bgColor );
			pDC->FillSolidRect( 0, rect.bottom, newClientRect.right, newClientRect.bottom, bgColor );
		}
*/

		pDC->BitBlt( 0, 0, newClientRect.right, newClientRect.bottom, &dc, xPos, yPos, SRCCOPY );
		dc.SelectObject( pOldBitmap );
	}

	if ( newClientRect.right - frameBmpRect.right > 0 ) {
		pDC->FillSolidRect( frameBmpRect.right, 0, newClientRect.right - frameBmpRect.right, newClientRect.bottom, bgColor );
	}
	if ( newClientRect.bottom - frameBmpRect.bottom > 0 ) {
		pDC->FillSolidRect( 0, frameBmpRect.bottom, newClientRect.right, newClientRect.bottom - frameBmpRect.bottom, bgColor );
	}

	lock_draw.Unlock();

	model->frameManager.getFrameTimer( index )->SetEvent();
}

BOOL RDOStudioFrameView::OnPreparePrinting(CPrintInfo* pInfo)
{
	return DoPreparePrinting(pInfo);
}

void RDOStudioFrameView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
}

void RDOStudioFrameView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
}

#ifdef _DEBUG
void RDOStudioFrameView::AssertValid() const
{
	CView::AssertValid();
}

void RDOStudioFrameView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

RDOStudioFrameDoc* RDOStudioFrameView::GetDocument()
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(RDOStudioFrameDoc)));
	return (RDOStudioFrameDoc*)m_pDocument;
}
#endif

void RDOStudioFrameView::OnDestroy()
{
	model->frameManager.getFrameClose( model->frameManager.findFrameIndex( this ) )->SetEvent();
	model->frameManager.disconnectFrameDoc( GetDocument() );
	CView::OnDestroy();
}

void RDOStudioFrameView::OnSetFocus(CWnd* pOldWnd)
{
	CView::OnSetFocus( pOldWnd );
	model->frameManager.setLastShowedFrame( model->frameManager.findFrameIndex( this ) );
}

void RDOStudioFrameView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	GetClientRect( &newClientRect );

	updateScrollBars();
}

void RDOStudioFrameView::updateScrollBars()
{
	SCROLLINFO si;
	si.cbSize = sizeof( si );
	si.fMask  = SIF_RANGE | SIF_PAGE | SIF_POS;

	if ( xPos > frameBmpRect.right - newClientRect.right ) xPos = frameBmpRect.right - newClientRect.right;
	if ( xPos < 0 ) xPos = 0;
	si.nMin   = 0;
	si.nMax   = frameBmpRect.right;
	si.nPos   = xPos;
	si.nPage  = newClientRect.right;
	SetScrollInfo( SB_HORZ, &si, TRUE );

	if ( yPos > frameBmpRect.bottom - newClientRect.bottom ) yPos = frameBmpRect.bottom - newClientRect.bottom;
	if ( yPos < 0 ) yPos = 0;
	si.nMin   = 0;
	si.nMax   = frameBmpRect.bottom;
	si.nPos   = yPos;
	si.nPage  = newClientRect.bottom;
	SetScrollInfo( SB_VERT, &si, TRUE );
}

void RDOStudioFrameView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	SCROLLINFO si;
	si.cbSize = sizeof( si );
	switch( nSBCode ) {
		case SB_PAGEUP:
			GetScrollInfo( SB_HORZ, &si, SIF_PAGE );
			xPos -= si.nPage;
			break;

		case SB_PAGEDOWN:
			GetScrollInfo( SB_HORZ, &si, SIF_PAGE );
			xPos += si.nPage;
			break;

		case SB_LINEUP:
			xPos--;
			break;

		case SB_LINEDOWN:
			xPos++;
			break;

		case SB_THUMBTRACK: {
			GetScrollInfo( SB_HORZ, &si, SIF_TRACKPOS );
			xPos += si.nTrackPos - xPos;
			break;
		}
	}
	if ( xPos > frameBmpRect.right - newClientRect.right ) xPos = frameBmpRect.right - newClientRect.right;
	if ( xPos < 0 ) xPos = 0;
	si.fMask = SIF_POS;
	si.nPos  = xPos;
	SetScrollInfo( SB_HORZ, &si, TRUE );
	InvalidateRect( NULL );
	UpdateWindow();
}

void RDOStudioFrameView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	SCROLLINFO si;
	si.cbSize = sizeof( si );
	switch( nSBCode ) {
		case SB_PAGEUP:
			GetScrollInfo( SB_VERT, &si, SIF_PAGE );
			yPos -= si.nPage;
			break;

		case SB_PAGEDOWN:
			GetScrollInfo( SB_VERT, &si, SIF_PAGE );
			yPos += si.nPage;
			break;

		case SB_LINEUP:
			yPos--;
			break;

		case SB_LINEDOWN:
			yPos++;
			break;

		case SB_THUMBTRACK: {
			GetScrollInfo( SB_VERT, &si, SIF_TRACKPOS );
			yPos += si.nTrackPos - yPos;
			break;
		}
	}
	if ( yPos > frameBmpRect.bottom - newClientRect.bottom ) yPos = frameBmpRect.bottom - newClientRect.bottom;
	if ( yPos < 0 ) yPos = 0;
	si.fMask = SIF_POS;
	si.nPos  = yPos;
	SetScrollInfo( SB_VERT, &si, TRUE );
	InvalidateRect( NULL );
	UpdateWindow();
}
<|endoftext|>


<commit_before>/*
The MIT License (MIT)

Copyright (c) 2013-2014 winlin

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 SRS_CORE_PERFORMANCE_HPP
#define SRS_CORE_PERFORMANCE_HPP

/*
#include <srs_core_performance.hpp>
*/

#include <srs_core.hpp>

/**
* this file defines the perfromance options.
*/

/**
* to improve read performance, merge some packets then read,
* when it on and read small bytes, we sleep to wait more data.,
* that is, we merge some data to read together.
* @see SrsConfig::get_mr_enabled()
* @see SrsConfig::get_mr_sleep_ms()
* @see https://github.com/winlinvip/simple-rtmp-server/issues/241
* @example, for the default settings, this algorithm will use:
*       that is, when got nread bytes smaller than 4KB, sleep(780ms).
*/
/**
* https://github.com/winlinvip/simple-rtmp-server/issues/241#issuecomment-65554690
* The merged read algorithm is ok and can be simplified for:
*   1. Suppose the client network is ok. All algorithm go wrong when netowrk is not ok.
*   2. Suppose the client send each packet one by one. Although send some together, it's same.
*   3. SRS MR algorithm will read all data then sleep.
* So, the MR algorithm is:
*   while true:
*       read all data from socket.
*       sleep a while
* For example, sleep 120ms. Then there is, and always 120ms data in buffer.
* That is, the latency is 120ms(the sleep time).
*/
#define SRS_PERF_MERGED_READ
// the default config of mr.
#define SRS_PERF_MR_ENABLED false
#define SRS_PERF_MR_SLEEP 350

/**
* the MW(merged-write) send cache time in ms.
* the default value, user can override it in config.
* to improve send performance, cache msgs and send in a time.
* for example, cache 500ms videos and audios, then convert all these
* msgs to iovecs, finally use writev to send.
* @remark this largely improve performance, from 3.5k+ to 7.5k+.
*       the latency+ when cache+.
* @remark the socket send buffer default to 185KB, it large enough.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/194
* @see SrsConfig::get_mw_sleep_ms()
* @remark the mw sleep and msgs to send, maybe:
*       mw_sleep        msgs        iovs
*       350             43          86
*       400             44          88
*       500             46          92
*       600             46          92
*       700             82          164
*       800             81          162
*       900             80          160
*       1000            88          176
*       1100            91          182
*       1200            89          178
*       1300            119         238
*       1400            120         240
*       1500            119         238
*       1600            131         262
*       1700            131         262
*       1800            133         266
*       1900            141         282
*       2000            150         300
*/
// the default config of mw.
#define SRS_PERF_MW_SLEEP 350
/**
* use iovs cache in each msg,
* for the shared ptr message, we calc once and used for every copy.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251
* @remark if enable this, donot use protocol iovs cache.
* @remark when reload change the chunk size, previous clients error.
*/
#undef SRS_PERF_MW_MSG_IOVS_CACHE
/**
* how many msgs can be send entirely.
* for play clients to get msgs then totally send out.
* for the mw sleep set to 1800, the msgs is about 133.
* @remark, recomment to 128.
* @remark, when mic enabled, use larger iovs cache, to 512.
*/
#ifndef SRS_PERF_MW_MSG_IOVS_CACHE
    #define SRS_PERF_MW_MSGS 128
#else
    #define SRS_PERF_MW_MSGS 512
#endif

/**
* whether set the socket send buffer size.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251
*/
#undef SRS_PERF_MW_SO_SNDBUF
/**
* whether set the socket recv buffer size.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251
*/
#undef SRS_PERF_MW_SO_RCVBUF
/**
* whether enable the fast cache.
* @remark this improve performance for large connectios.
* @remark this also introduce complex, default to disable it.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251
*/
#undef SRS_PERF_QUEUE_FAST_CACHE
/**
* whether enable the fast vector for qeueue.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251
*/
#undef SRS_PERF_QUEUE_FAST_VECTOR
/**
* whether use cond wait to send messages.
* @remark this improve performance for large connectios.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251
*/
#undef SRS_PERF_QUEUE_COND_WAIT

/**
* how many chunk stream to cache, [0, N].
* to imporove about 10% performance when chunk size small, and 5% for large chunk.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/249
* @remark 0 to disable the chunk stream cache.
*/
#define SRS_PERF_CHUNK_STREAM_CACHE 16

/**
* the gop cache and play cache queue.
*/
// whether gop cache is on.
#define SRS_PERF_GOP_CACHE true
// in seconds, the live queue length.
#define SRS_PERF_PLAY_QUEUE 30

#endif

<commit_msg>for bug #251, add min msgs for queue cond wait.<commit_after>/*
The MIT License (MIT)

Copyright (c) 2013-2014 winlin

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 SRS_CORE_PERFORMANCE_HPP
#define SRS_CORE_PERFORMANCE_HPP

/*
#include <srs_core_performance.hpp>
*/

#include <srs_core.hpp>

/**
* this file defines the perfromance options.
*/

/**
* to improve read performance, merge some packets then read,
* when it on and read small bytes, we sleep to wait more data.,
* that is, we merge some data to read together.
* @see SrsConfig::get_mr_enabled()
* @see SrsConfig::get_mr_sleep_ms()
* @see https://github.com/winlinvip/simple-rtmp-server/issues/241
* @example, for the default settings, this algorithm will use:
*       that is, when got nread bytes smaller than 4KB, sleep(780ms).
*/
/**
* https://github.com/winlinvip/simple-rtmp-server/issues/241#issuecomment-65554690
* The merged read algorithm is ok and can be simplified for:
*   1. Suppose the client network is ok. All algorithm go wrong when netowrk is not ok.
*   2. Suppose the client send each packet one by one. Although send some together, it's same.
*   3. SRS MR algorithm will read all data then sleep.
* So, the MR algorithm is:
*   while true:
*       read all data from socket.
*       sleep a while
* For example, sleep 120ms. Then there is, and always 120ms data in buffer.
* That is, the latency is 120ms(the sleep time).
*/
#define SRS_PERF_MERGED_READ
// the default config of mr.
#define SRS_PERF_MR_ENABLED false
#define SRS_PERF_MR_SLEEP 350

/**
* the MW(merged-write) send cache time in ms.
* the default value, user can override it in config.
* to improve send performance, cache msgs and send in a time.
* for example, cache 500ms videos and audios, then convert all these
* msgs to iovecs, finally use writev to send.
* @remark this largely improve performance, from 3.5k+ to 7.5k+.
*       the latency+ when cache+.
* @remark the socket send buffer default to 185KB, it large enough.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/194
* @see SrsConfig::get_mw_sleep_ms()
* @remark the mw sleep and msgs to send, maybe:
*       mw_sleep        msgs        iovs
*       350             43          86
*       400             44          88
*       500             46          92
*       600             46          92
*       700             82          164
*       800             81          162
*       900             80          160
*       1000            88          176
*       1100            91          182
*       1200            89          178
*       1300            119         238
*       1400            120         240
*       1500            119         238
*       1600            131         262
*       1700            131         262
*       1800            133         266
*       1900            141         282
*       2000            150         300
*/
// the default config of mw.
#define SRS_PERF_MW_SLEEP 350
/**
* use iovs cache in each msg,
* for the shared ptr message, we calc once and used for every copy.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251
* @remark if enable this, donot use protocol iovs cache.
* @remark when reload change the chunk size, previous clients error.
*/
#undef SRS_PERF_MW_MSG_IOVS_CACHE
/**
* how many msgs can be send entirely.
* for play clients to get msgs then totally send out.
* for the mw sleep set to 1800, the msgs is about 133.
* @remark, recomment to 128.
* @remark, when mic enabled, use larger iovs cache, to 512.
*/
#ifndef SRS_PERF_MW_MSG_IOVS_CACHE
    #define SRS_PERF_MW_MSGS 128
#else
    #define SRS_PERF_MW_MSGS 512
#endif

/**
* whether set the socket send buffer size.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251
*/
#undef SRS_PERF_MW_SO_SNDBUF
/**
* whether set the socket recv buffer size.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251
*/
#undef SRS_PERF_MW_SO_RCVBUF
/**
* whether enable the fast cache.
* @remark this improve performance for large connectios.
* @remark this also introduce complex, default to disable it.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251
*/
#undef SRS_PERF_QUEUE_FAST_CACHE
/**
* whether enable the fast vector for qeueue.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251
*/
#undef SRS_PERF_QUEUE_FAST_VECTOR
#if defined(SRS_PERF_QUEUE_FAST_CACHE) && defined(SRS_PERF_QUEUE_FAST_VECTOR)
    #error "fast cache conflict with fast vector"
#endif
/**
* whether use cond wait to send messages.
* @remark this improve performance for large connectios.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/251
*/
#undef SRS_PERF_QUEUE_COND_WAIT
#ifdef SRS_PERF_QUEUE_COND_WAIT
    #define SRS_PERF_MW_MIN_MSGS 8
#endif

/**
* how many chunk stream to cache, [0, N].
* to imporove about 10% performance when chunk size small, and 5% for large chunk.
* @see https://github.com/winlinvip/simple-rtmp-server/issues/249
* @remark 0 to disable the chunk stream cache.
*/
#define SRS_PERF_CHUNK_STREAM_CACHE 16

/**
* the gop cache and play cache queue.
*/
// whether gop cache is on.
#define SRS_PERF_GOP_CACHE true
// in seconds, the live queue length.
#define SRS_PERF_PLAY_QUEUE 30

#endif

<|endoftext|>


<commit_before>#include <iconv.h>

#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <cstring>
#include <cerrno>
#include <cstdio>

using namespace v8;
using namespace node;

namespace {

class Iconv: public ObjectWrap {
public:
  static void Initialize(Handle<Object>& target);
  static Handle<Value> New(const Arguments& args);
  static Handle<Value> Convert(const Arguments& args);

  Iconv(iconv_t conv);
  ~Iconv(); // destructor may not run if program is short-lived or aborted

  // the actual conversion happens here
  Handle<Value> Convert(char* data, size_t length);

private:
  iconv_t conv_;
};

Iconv::Iconv(iconv_t conv): conv_(conv) {
  assert(conv_ != (iconv_t) -1);
}

Iconv::~Iconv() {
  iconv_close(conv_);
}

// the actual conversion happens here
Handle<Value> Iconv::Convert(char* data, size_t length) {
  assert(conv_ != (iconv_t) -1);
  assert(data != 0);

  char *inbuf;
  char *outbuf;
  size_t inbytesleft;
  size_t outbytesleft;

  inbuf = data;
  inbytesleft = length;

  char tmp[1024];
  outbuf = tmp;
  outbytesleft = sizeof(tmp);

  size_t n = iconv(conv_, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
  if (n == (size_t) -1) {
    const char* message = "Unexpected error.";

    switch (errno) {
    case E2BIG:
      message = "Output buffer not large enough. This is a bug.";
      break;
    case EILSEQ:
      message = "Illegal character sequence.";
      break;
    case EINVAL:
      message = "Incomplete character sequence.";
      break;
    }

    return ThrowException(ErrnoException(errno, "iconv", message));
  }

  n = sizeof(tmp) - outbytesleft;
  Buffer& b = *Buffer::New(n);
  memcpy(b.data(), tmp, n);

  return b.handle_;
}

Handle<Value> Iconv::Convert(const Arguments& args) {
  HandleScope scope;

  Iconv* self = ObjectWrap::Unwrap<Iconv>(args.This());
  Local<Value> arg = args[0];

  if (arg->IsString()) {
    String::Utf8Value string(arg->ToString());
    return self->Convert(*string, string.length());
  }

  if (arg->IsObject()) {
    Handle<Value> object = arg->ToObject();
    if (Buffer::HasInstance(object)) {
      Buffer& buffer = *ObjectWrap::Unwrap<Buffer>(arg->ToObject());
      return self->Convert(buffer.data(), buffer.length());
    }
  }

  return Undefined();
}

Handle<Value> Iconv::New(const Arguments& args) {
  HandleScope scope;

  String::AsciiValue sourceEncoding(args[0]->ToString());
  String::AsciiValue targetEncoding(args[1]->ToString());

  iconv_t conv = iconv_open(*targetEncoding, *sourceEncoding);
  if (conv == (iconv_t) -1) {
    return ThrowException(ErrnoException(errno, "iconv_open", "Conversion not supported."));
  }

  Iconv* instance = new Iconv(conv);
  instance->Wrap(args.Holder());

  return args.This();
}

void Iconv::Initialize(Handle<Object>& target) {
  HandleScope scope;

  Local<FunctionTemplate> t = FunctionTemplate::New(Iconv::New);
  t->InstanceTemplate()->SetInternalFieldCount(1);

  NODE_SET_PROTOTYPE_METHOD(t, "convert", Iconv::Convert);

  target->Set(String::NewSymbol("Iconv"), t->GetFunction());
}

extern "C" void init(Handle<Object> target) {
  Iconv::Initialize(target);
}

} // namespace
<commit_msg>Bump result buffer from 1K to 4K for great recoding justice.<commit_after>#include <iconv.h>

#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <cstring>
#include <cerrno>
#include <cstdio>

using namespace v8;
using namespace node;

namespace {

class Iconv: public ObjectWrap {
public:
  static void Initialize(Handle<Object>& target);
  static Handle<Value> New(const Arguments& args);
  static Handle<Value> Convert(const Arguments& args);

  Iconv(iconv_t conv);
  ~Iconv(); // destructor may not run if program is short-lived or aborted

  // the actual conversion happens here
  Handle<Value> Convert(char* data, size_t length);

private:
  iconv_t conv_;
};

Iconv::Iconv(iconv_t conv): conv_(conv) {
  assert(conv_ != (iconv_t) -1);
}

Iconv::~Iconv() {
  iconv_close(conv_);
}

// the actual conversion happens here
Handle<Value> Iconv::Convert(char* data, size_t length) {
  assert(conv_ != (iconv_t) -1);
  assert(data != 0);

  char *inbuf;
  char *outbuf;
  size_t inbytesleft;
  size_t outbytesleft;

  inbuf = data;
  inbytesleft = length;

  char tmp[4096];
  outbuf = tmp;
  outbytesleft = sizeof(tmp);

  size_t n = iconv(conv_, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
  if (n == (size_t) -1) {
    const char* message = "Unexpected error.";

    switch (errno) {
    case E2BIG:
      message = "Output buffer not large enough. This is a bug.";
      break;
    case EILSEQ:
      message = "Illegal character sequence.";
      break;
    case EINVAL:
      message = "Incomplete character sequence.";
      break;
    }

    return ThrowException(ErrnoException(errno, "iconv", message));
  }

  n = sizeof(tmp) - outbytesleft;
  Buffer& b = *Buffer::New(n);
  memcpy(b.data(), tmp, n);

  return b.handle_;
}

Handle<Value> Iconv::Convert(const Arguments& args) {
  HandleScope scope;

  Iconv* self = ObjectWrap::Unwrap<Iconv>(args.This());
  Local<Value> arg = args[0];

  if (arg->IsString()) {
    String::Utf8Value string(arg->ToString());
    return self->Convert(*string, string.length());
  }

  if (arg->IsObject()) {
    Handle<Value> object = arg->ToObject();
    if (Buffer::HasInstance(object)) {
      Buffer& buffer = *ObjectWrap::Unwrap<Buffer>(arg->ToObject());
      return self->Convert(buffer.data(), buffer.length());
    }
  }

  return Undefined();
}

Handle<Value> Iconv::New(const Arguments& args) {
  HandleScope scope;

  String::AsciiValue sourceEncoding(args[0]->ToString());
  String::AsciiValue targetEncoding(args[1]->ToString());

  iconv_t conv = iconv_open(*targetEncoding, *sourceEncoding);
  if (conv == (iconv_t) -1) {
    return ThrowException(ErrnoException(errno, "iconv_open", "Conversion not supported."));
  }

  Iconv* instance = new Iconv(conv);
  instance->Wrap(args.Holder());

  return args.This();
}

void Iconv::Initialize(Handle<Object>& target) {
  HandleScope scope;

  Local<FunctionTemplate> t = FunctionTemplate::New(Iconv::New);
  t->InstanceTemplate()->SetInternalFieldCount(1);

  NODE_SET_PROTOTYPE_METHOD(t, "convert", Iconv::Convert);

  target->Set(String::NewSymbol("Iconv"), t->GetFunction());
}

extern "C" void init(Handle<Object> target) {
  Iconv::Initialize(target);
}

} // namespace
<|endoftext|>


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

#include "chrome/browser/privacy_blacklist/blacklist_manager.h"

#include "base/command_line.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/privacy_blacklist/blacklist.h"
#include "chrome/browser/privacy_blacklist/blacklist_manager.h"
#include "chrome/browser/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_source.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

void GetBlacklistHasMatchOnIOThread(const BlacklistManager* manager,
                                    const GURL& url,
                                    bool *has_match) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  const Blacklist* blacklist = manager->GetCompiledBlacklist();
  scoped_ptr<Blacklist::Match> match(blacklist->findMatch(url));
  *has_match = (match.get() != NULL);
  ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
                         new MessageLoop::QuitTask());
}

}  // namespace

class BlacklistManagerBrowserTest : public ExtensionBrowserTest {
 public:
  virtual void SetUp() {
    CommandLine::ForCurrentProcess()->AppendSwitch(
        switches::kEnablePrivacyBlacklists);
    ExtensionBrowserTest::SetUp();
  }

  virtual void SetUpInProcessBrowserTestFixture() {
    ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();

    received_blacklist_notification_ = false;
    host_resolver()->AddSimulatedFailure("www.example.com");
  }

  // NotificationObserver
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    if (type != NotificationType::BLACKLIST_MANAGER_ERROR &&
        type != NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED) {
      ExtensionBrowserTest::Observe(type, source, details);
      return;
    }
    received_blacklist_notification_ = true;
    MessageLoop::current()->Quit();
  }

 protected:
  BlacklistManager* GetBlacklistManager() {
    return browser()->profile()->GetBlacklistManager();
  }

  bool GetAndResetReceivedBlacklistNotification() {
    bool result = received_blacklist_notification_;
    received_blacklist_notification_ = false;
    return result;
  }

  bool BlacklistHasMatch(const std::string& url) {
    bool has_match = false;
    ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
                           NewRunnableFunction(GetBlacklistHasMatchOnIOThread,
                                               GetBlacklistManager(),
                                               GURL(url),
                                               &has_match));
    ui_test_utils::RunMessageLoop();
    return has_match;
  }

 private:
  bool received_blacklist_notification_;
};

IN_PROC_BROWSER_TEST_F(BlacklistManagerBrowserTest, Basic) {
  static const char kTestUrl[] = "http://www.example.com/annoying_ads/ad.jpg";

  NotificationRegistrar registrar;
  registrar.Add(this,
                NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED,
                Source<Profile>(browser()->profile()));

  // Test loading an extension with blacklist.
  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("common").AppendASCII("privacy_blacklist")));

  // Wait until the blacklist is loaded and ready.
  if (!GetAndResetReceivedBlacklistNotification())
    ui_test_utils::RunMessageLoop();

  // The blacklist should block our test URL.
  EXPECT_TRUE(BlacklistHasMatch(kTestUrl));

  // TODO(phajdan.jr): Verify that we really blocked the request etc.
  ui_test_utils::NavigateToURL(browser(), GURL(kTestUrl));
}
<commit_msg>Mark BlacklistManagerBrowserTest.Basic as flaky. BUG=29113<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/privacy_blacklist/blacklist_manager.h"

#include "base/command_line.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/privacy_blacklist/blacklist.h"
#include "chrome/browser/privacy_blacklist/blacklist_manager.h"
#include "chrome/browser/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_source.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

void GetBlacklistHasMatchOnIOThread(const BlacklistManager* manager,
                                    const GURL& url,
                                    bool *has_match) {
  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
  const Blacklist* blacklist = manager->GetCompiledBlacklist();
  scoped_ptr<Blacklist::Match> match(blacklist->findMatch(url));
  *has_match = (match.get() != NULL);
  ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
                         new MessageLoop::QuitTask());
}

}  // namespace

class BlacklistManagerBrowserTest : public ExtensionBrowserTest {
 public:
  virtual void SetUp() {
    CommandLine::ForCurrentProcess()->AppendSwitch(
        switches::kEnablePrivacyBlacklists);
    ExtensionBrowserTest::SetUp();
  }

  virtual void SetUpInProcessBrowserTestFixture() {
    ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();

    received_blacklist_notification_ = false;
    host_resolver()->AddSimulatedFailure("www.example.com");
  }

  // NotificationObserver
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    if (type != NotificationType::BLACKLIST_MANAGER_ERROR &&
        type != NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED) {
      ExtensionBrowserTest::Observe(type, source, details);
      return;
    }
    received_blacklist_notification_ = true;
    MessageLoop::current()->Quit();
  }

 protected:
  BlacklistManager* GetBlacklistManager() {
    return browser()->profile()->GetBlacklistManager();
  }

  bool GetAndResetReceivedBlacklistNotification() {
    bool result = received_blacklist_notification_;
    received_blacklist_notification_ = false;
    return result;
  }

  bool BlacklistHasMatch(const std::string& url) {
    bool has_match = false;
    ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
                           NewRunnableFunction(GetBlacklistHasMatchOnIOThread,
                                               GetBlacklistManager(),
                                               GURL(url),
                                               &has_match));
    ui_test_utils::RunMessageLoop();
    return has_match;
  }

 private:
  bool received_blacklist_notification_;
};

IN_PROC_BROWSER_TEST_F(BlacklistManagerBrowserTest, FLAKY_Basic) {
  static const char kTestUrl[] = "http://www.example.com/annoying_ads/ad.jpg";

  NotificationRegistrar registrar;
  registrar.Add(this,
                NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED,
                Source<Profile>(browser()->profile()));

  // Test loading an extension with blacklist.
  ASSERT_TRUE(LoadExtension(
      test_data_dir_.AppendASCII("common").AppendASCII("privacy_blacklist")));

  // Wait until the blacklist is loaded and ready.
  if (!GetAndResetReceivedBlacklistNotification())
    ui_test_utils::RunMessageLoop();

  // The blacklist should block our test URL.
  EXPECT_TRUE(BlacklistHasMatch(kTestUrl));

  // TODO(phajdan.jr): Verify that we really blocked the request etc.
  ui_test_utils::NavigateToURL(browser(), GURL(kTestUrl));
}
<|endoftext|>


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

#include "JobSubmitCommand.h"
#include "CoasterError.h"
#include <cstring>
#include <string>

using namespace Coaster;

using std::cout;
using std::map;
using std::ostream;
using std::string;
using std::stringstream;
using std::vector;

void add(string& ss, const char* key, const string* value);
void add(string& ss, const char* key, const string& value);
void add(string& ss, const char* key, const char* value);
void add(string& ss, const char* key, const char* value, int n);

string JobSubmitCommand::NAME("SUBMITJOB");

JobSubmitCommand::JobSubmitCommand(Job* pjob, const std::string& pconfigId): Command(&NAME) {
	job = pjob;
	configId = pconfigId;
}

void JobSubmitCommand::send(CoasterChannel* channel, CommandCallback* cb) {
	serialize();
	Command::send(channel, cb);
}

Job* JobSubmitCommand::getJob() {
	return job;
}

string JobSubmitCommand::getRemoteId() {
	if (!isReceiveCompleted() || isErrorReceived()) {
		throw CoasterError("getRemoteId called before reply was received");
	}
	string result;
	getInData()->at(0)->str(result);
	return result;
}

void JobSubmitCommand::serialize() {
	stringstream idSS;
	idSS << job->getIdentity();
	add(ss, "configid", configId);
	add(ss, "identity", idSS.str());
	add(ss, "executable", job->getExecutable());
	add(ss, "directory", job->getDirectory());

	add(ss, "stdin", job->getStdinLocation());
	add(ss, "stdout", job->getStdoutLocation());
	add(ss, "stderr", job->getStderrLocation());

	const vector<string*>& arguments = job->getArguments();
	for (vector<string*>::const_iterator i = arguments.begin(); i != arguments.end(); ++i) {
		add(ss, "arg", *i);
	}

	map<string, string>* env = job->getEnv();
	if (env != NULL) {
		for (map<string, string>::iterator i = env->begin(); i != env->end(); ++i) {
			add(ss, "env", string(i->first).append("=").append(i->second));
		}
	}

	map<string, string>* attributes = job->getAttributes();
	if (attributes != NULL) {
		for (map<string, string>::iterator i = attributes->begin(); i != attributes->end(); ++i) {
			add(ss, "attr", string(i->first).append("=").append(i->second));
		}
	}

	if (job->getJobManager().empty()) {
	cout<< "getJobManager == NULL, setting to :  fork "<< endl;
		add(ss, "jm", "fork");
	}
	else {
	const char *jm_string = (job->getJobManager()).c_str();
	cout<< "getJobManager != !NULL, setting to : "<< job->getJobManager() << endl;
		add(ss, "jm", jm_string);
	}
	addOutData(Buffer::wrap(ss));
}

void add(string& ss, const char* key, const string* value) {
	if (value != NULL) {
		add(ss, key, value->data(), value->length());
	}
}

void add(string& ss, const char* key, const string& value) {
	add(ss, key, value.data(), value.length());
}

void add(string& ss, const char* key, const char* value) {
	add(ss, key, value, -1);
}

void add(string& ss, const char* key, const char* value, int n) {
	if (value != NULL && n != 0) {
		ss.append(key);
		ss.append(1, '=');
		while (*value) {
			char c = *value;
			switch (c) {
				case '\n':
					ss.append(1, '\\');
					ss.append(1, 'n');
					break;
				case '\\':
					ss.append(1, '\\');
					ss.append(1, '\\');
					break;
				default:
					ss.append(1, c);
					break;
			}
			value++;
			n--;
		}
	}
	ss.append(1, '\n');
}
<commit_msg>Print debug messages at appropriate log level<commit_after>/*
 * Swift Parallel Scripting Language (http://swift-lang.org)
 *
 * Copyright 2012-2014 University of Chicago
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "JobSubmitCommand.h"
#include "CoasterError.h"
#include <cstring>
#include <string>

using namespace Coaster;

using std::map;
using std::ostream;
using std::string;
using std::stringstream;
using std::vector;

void add(string& ss, const char* key, const string* value);
void add(string& ss, const char* key, const string& value);
void add(string& ss, const char* key, const char* value);
void add(string& ss, const char* key, const char* value, int n);

string JobSubmitCommand::NAME("SUBMITJOB");

JobSubmitCommand::JobSubmitCommand(Job* pjob, const std::string& pconfigId): Command(&NAME) {
	job = pjob;
	configId = pconfigId;
}

void JobSubmitCommand::send(CoasterChannel* channel, CommandCallback* cb) {
	serialize();
	Command::send(channel, cb);
}

Job* JobSubmitCommand::getJob() {
	return job;
}

string JobSubmitCommand::getRemoteId() {
	if (!isReceiveCompleted() || isErrorReceived()) {
		throw CoasterError("getRemoteId called before reply was received");
	}
	string result;
	getInData()->at(0)->str(result);
	return result;
}

void JobSubmitCommand::serialize() {
	stringstream idSS;
	idSS << job->getIdentity();
	add(ss, "configid", configId);
	add(ss, "identity", idSS.str());
	add(ss, "executable", job->getExecutable());
	add(ss, "directory", job->getDirectory());

	add(ss, "stdin", job->getStdinLocation());
	add(ss, "stdout", job->getStdoutLocation());
	add(ss, "stderr", job->getStderrLocation());

	const vector<string*>& arguments = job->getArguments();
	for (vector<string*>::const_iterator i = arguments.begin(); i != arguments.end(); ++i) {
		add(ss, "arg", *i);
	}

	map<string, string>* env = job->getEnv();
	if (env != NULL) {
		for (map<string, string>::iterator i = env->begin(); i != env->end(); ++i) {
			add(ss, "env", string(i->first).append("=").append(i->second));
		}
	}

	map<string, string>* attributes = job->getAttributes();
	if (attributes != NULL) {
		for (map<string, string>::iterator i = attributes->begin(); i != attributes->end(); ++i) {
			add(ss, "attr", string(i->first).append("=").append(i->second));
		}
	}

	if (job->getJobManager().empty()) {
		LogDebug << "getJobManager == NULL, setting to :  fork "<< endl;
		add(ss, "jm", "fork");
	}
	else {
		const char *jm_string = (job->getJobManager()).c_str();
		LogDebug << "getJobManager != !NULL, setting to : "<< job->getJobManager() << endl;
		add(ss, "jm", jm_string);
	}
	addOutData(Buffer::wrap(ss));
}

void add(string& ss, const char* key, const string* value) {
	if (value != NULL) {
		add(ss, key, value->data(), value->length());
	}
}

void add(string& ss, const char* key, const string& value) {
	add(ss, key, value.data(), value.length());
}

void add(string& ss, const char* key, const char* value) {
	add(ss, key, value, -1);
}

void add(string& ss, const char* key, const char* value, int n) {
	if (value != NULL && n != 0) {
		ss.append(key);
		ss.append(1, '=');
		while (*value) {
			char c = *value;
			switch (c) {
				case '\n':
					ss.append(1, '\\');
					ss.append(1, 'n');
					break;
				case '\\':
					ss.append(1, '\\');
					ss.append(1, '\\');
					break;
				default:
					ss.append(1, c);
					break;
			}
			value++;
			n--;
		}
	}
	ss.append(1, '\n');
}
<|endoftext|>


<commit_before>#include <iostream>

#include <boost/lexical_cast.hpp>
#include <boost/fusion/adapted.hpp>

#include "restc-cpp/restc-cpp.h"
#include "restc-cpp/RequestBuilder.h"
#include "restc-cpp/IteratorFromJsonSerializer.h"

using namespace std;
using namespace restc_cpp;

// C++ structure that match the Json entries received
// from http://jsonplaceholder.typicode.com/posts/{id}
struct Post {
    int userId = 0;
    int id = 0;
    string title;
    string body;
};

// Add C++ reflection to the Post structure.
// This allows our Json (de)serialization to do it's magic.
BOOST_FUSION_ADAPT_STRUCT(
    Post,
    (int, userId)
    (int, id)
    (string, title)
    (string, body)
)

// The C++ main function - the place where any adventure starts
void first() {

    // Create and instantiate a Post from data received from the server.
    Post my_post = RestClient::Create()->ProcessWithPromiseT<Post>([&](Context& ctx) {
        // This is a co-routine, running in a worker-thread

        // Instantiate a Post structure.
        Post post;

        // Serialize it asynchronously. The asynchronously part does not really matter
        // here, but it may if you receive huge data structures.
        SerializeFromJson(post,

            // Construct a request to the server
            RequestBuilder(ctx)
                .Get("http://jsonplaceholder.typicode.com/posts/1")

                // Add some headers for good taste
                .Header("X-Client", "RESTC_CPP")
                .Header("X-Client-Purpose", "Testing")

                // Send the request
                .Execute());

        // Return the post instance trough a C++ future<>
        return post;
    })

    // Get the Post instance from the future<>, or any C++ exception thrown
    // within the lambda.
    .get();

    // Print the result for everyone to see.
    cout << "Received post# " << my_post.id << ", title: " << my_post.title;
}

void DoSomethingInteresting(Context& ctx) {
    // Here we are again in a co-routine, running in a worker-thread.

    // Asynchronously connect to a server and fetch some data.
    auto reply = ctx.Get("http://jsonplaceholder.typicode.com/posts/1");

    // Asynchronously fetch the entire data-set and return it as a string.
    auto json = reply->GetBodyAsString();

    // Just dump the data.
    cout << "Received data: " << json << endl;
}

void second() {
    auto rest_client = RestClient::Create();

    // Call DoSomethingInteresting as a co-routine in a worker-thread.
    rest_client->Process(DoSomethingInteresting);

    // Wait for the request to finish
    rest_client->CloseWhenReady(true);
}

void third() {

    auto rest_client = RestClient::Create();
    rest_client->ProcessWithPromise([&](Context& ctx) {
        // Here we are again in a co-routine, running in a worker-thread.

        // Asynchronously connect to a server and fetch some data.
        auto reply = RequestBuilder(ctx)
            .Get("http://localhost:3001/restricted/posts/1")

            // Authenticate as 'alice' with a very popular password
            .BasicAuthentication("alice", "12345")

            // Send the request.
            .Execute();

        // Dump the well protected data
        cout << "Got: " << reply->GetBodyAsString();

    }).get();
}

void forth() {

    // Add the proxy information to the properties used by the client
    Request::Properties properties;
    properties.proxy.type = Request::Proxy::Type::HTTP;
    properties.proxy.address = "http://127.0.0.1:3003";

    // Create the client with our configuration
    auto rest_client = RestClient::Create(properties);
    rest_client->ProcessWithPromise([&](Context& ctx) {
        // Here we are again in a co-routine, running in a worker-thread.

        // Asynchronously connect to a server trough a HTTP proxy and fetch some data.
        auto reply = RequestBuilder(ctx)
            .Get("http://api.example.com/normal/posts/1")

            // Send the request.
            .Execute();

        // Dump the data
        cout << "Got: " << reply->GetBodyAsString();

    }).get();
}

void fifth() {
    // Fetch a list of records asyncrouesly, one by one.
    // This allows us to process single items in a list
    // and fetching more data as we move forward.
    // This works basically as a database cursor, or
    // (literally) as a properly implemented C++ input iterator.

    // Create the REST clent
    auto rest_client = RestClient::Create();

    // Run our example in a lambda co-routine
    rest_client->Process([&](Context& ctx) {
        // This is the co-routine, running in a worker-thread

        // Construct a request to the server
        auto reply = RequestBuilder(ctx)
            .Get("http://jsonplaceholder.typicode.com/posts/")

            // Add some headers for good taste
            .Header("X-Client", "RESTC_CPP")
            .Header("X-Client-Purpose", "Testing")

            // Send the request
            .Execute();

        // Instatiate a serializer with begin() and end() methods that
        // allows us to work with the reply-data trough a C++
        // input iterator.
        IteratorFromJsonSerializer<Post> data{*reply};

        // Iterate over the data, fetch data asyncrounesly as we go.
        for(const auto& post : data) {
            cout << "Item #" << post.id << " Title: " << post.title << endl;
        }
    });

    // Wait for the request to finish
    rest_client->CloseWhenReady(true);
}

void sixth() {
    // Create the client without creating a worker thread
    auto rest_client = RestClient::CreateUseOwnThread();

    // Add a request to the queue of the io-service in the rest client instance
    rest_client->Process([&](Context& ctx) {
        // Here we are again in a co-routine, now in our own thread.

        // Asynchronously connect to a server trough a HTTP proxy and fetch some data.
        auto reply = RequestBuilder(ctx)
            .Get("http://jsonplaceholder.typicode.com/posts/1")

            // Send the request.
            .Execute();

        // Dump the data
        cout << "Got: " << reply->GetBodyAsString();

        // Shut down the io-service. This will cause run() (below) to return.
        rest_client->CloseWhenReady();

    });

    // Start the io-service, using this thread.
    rest_client->GetIoService().run();

    cout << "Done. Exiting normally." << endl;
}

// Use our own RequestBody implementation to supply
// data to a POST request
void seventh() {
    // Our own implementation of the raw data provider
    class MyBody : public RequestBody
    {
    public:
        MyBody() = default;

        Type GetType() const noexcept override {

            // This mode causes the request to use chunked data,
            // allowing us to send data without knowing the exact
            // size of the payload when we start.
            return Type::CHUNKED_LAZY_PULL;
        }

        std::uint64_t GetFixedSize() const override {
            throw runtime_error("Not implemented");
        }

        // This will be called until we return false to indicate
        // that we have no further data
        bool GetData(write_buffers_t& buffers) override {

            if (++count_ > 10) {

                // We are done.
                return false;
            }

            ostringstream data;
            data << "This is line #" << count_ << " of the payload.\r\n";

            // The buffer need to persist until we are called again, or the
            // instance is destroyed.
            data_buffer_ = data.str();

            buffers.emplace_back(data_buffer_.c_str(), data_buffer_.size());

            // We added data to buffers, so return true
            return true;
        }

        // Called if we get a HTTP redirect and need to start over again.
        void Reset() override {
            count_ = 0;
        }

    private:
        int count_ = 0;
        string data_buffer_;
    };

    // Create the REST clent
    auto rest_client = RestClient::Create();

    // Run our example in a lambda co-routine
    rest_client->Process([&](Context& ctx) {
        // This is the co-routine, running in a worker-thread

        // Construct a POST request to the server
        RequestBuilder(ctx)
            .Post("http://localhost:3001/upload_raw/")
            .Header("Content-Type", "text/text")
            .Body(make_unique<MyBody>())
            .Execute();
    });

    // Wait for the request to finish
    rest_client->CloseWhenReady(true);
}

struct DataItem {
    DataItem() = default;
    DataItem(string u, string m)
    : username{u}, motto{m} {}

    int id = 0;
    string username;
    string motto;
};

BOOST_FUSION_ADAPT_STRUCT(
    DataItem,
    (int, id)
    (string, username)
    (string, motto)
)

void eight() {

    // Create the REST clent
    auto rest_client = RestClient::Create();

    // Run our example in a lambda co-routine that returns a future
    rest_client->ProcessWithPromise([&](Context& ctx) {

        // Make a container for data
        std::vector<DataItem> data;

        // Add some data
        data.emplace_back("jgaa", "Carpe Diem!");
        data.emplace_back("trump", "Endorse greed!");
        data.emplace_back("anonymous", "We are great!");

        // Create a request
        auto reply = RequestBuilder(ctx)
            .Post("http://localhost:3001/upload_raw/") // URL

            // Provide data from a lambda
            .DataProvider([&](DataWriter& writer) {
                // Here we are called from Execute() below to provide data

                // Create a json serializer that can write data asynchronously
                RapidJsonInserter<DataItem> inserter(writer, true);

                // Serialize the items from our data container
                for(const auto& d : data) {

                    // Serialize one data item.
                    // If the buffers in the writer fills up, we will
                    // write data to the net asynchronously.
                    inserter.Add(d);
                }

                // Tell the inserter that we have no further data.
                inserter.Done();

            })

            // Execute the request
            .Execute();

    })

    // Wait for the request to finish.
    .get();
}

void ninth() {

    // Create the REST clent
    auto rest_client = RestClient::Create();

    // Run our example in a lambda co-routine that returns a future
    rest_client->ProcessWithPromise([&](Context& ctx) {

        // Make a container for data
        std::vector<DataItem> data;

        // Add some data
        data.emplace_back("jgaa", "Carpe Diem!");
        data.emplace_back("trump", "Endorse greed!");
        data.emplace_back("anonymous", "We are great!");

        // Prepare the request
        auto request = RequestBuilder(ctx)
            .Post("http://localhost:3001/upload_raw/") // URL

            // Make sure we get a DataWriter for chunked data
            // This is required when we add data after the request-
            // headers are sent.
            .Chunked()

            // Just create the request. Send nothing to the server.
            .Build();

        // Send the request to the server. This will send the
        // request line and the request headers.
        auto& writer = request->SendRequest(ctx);

        {
            // Create a json list serializer for our data object.
            RapidJsonInserter<DataItem> inserter(writer, true);

            // Write each item to the server
            for(const auto& d : data) {
                inserter.Add(d);
            }
        }

        // Finish the request and fetch the reply asynchronously
        // This function returns when we have the reply headers.
        // If we expect data in the reply, we can read it asynchronously
        // as shown in previous examples.
        auto reply = request->GetReply(ctx);

        cout << "The server replied with code: " << reply->GetResponseCode();

    })

    // Wait for the request to finish.
    .get();
}

void tenth() {
    // Construct our own ioservice.
    boost::asio::io_service ioservice;

    // Give it some work so it don't end prematurely
    boost::asio::io_service::work work(ioservice);

    // Start it in a worker-thread
    thread worker([&ioservice]() {
        cout << "ioservice is running" << endl;
        ioservice.run();
        cout << "ioservice is done" << endl;
    });

    // Now we have our own io-service running in a worker thread.
    // Create a RestClient instance that uses it.

    auto rest_client = RestClient::Create(ioservice);

    // Make a HTTP request
    rest_client->ProcessWithPromise([&](Context& ctx) {
        // Here we are in a co-routine, spawned from our io-service, running
        // in our worker thread.

        // Asynchronously connect to a server and fetch some data.
        auto reply = ctx.Get("http://jsonplaceholder.typicode.com/posts/1");

        // Asynchronously fetch the entire data-set and return it as a string.
        auto json = reply->GetBodyAsString();

        // Just dump the data.
        cout << "Received data: " << json << endl;
    })
    // Wait for the co-routine to end
    .get();

    // Stop the io-service
    // (We can not just remove 'work', as the rest client may have
    // timers pending in the io-service, keeping it running even after
    // work is gone).
    ioservice.stop();

    // Wait for the worker thread to end
    worker.join();

    cout << "Done." << endl;
}

void eleventh() {
    auto rest_client = RestClient::Create();
    rest_client->ProcessWithPromise([&](Context& ctx) {

        Post data;
        data.id = 10;
        data.userId = 14;
        data.title = "Hi there";
        data.body = "This is the body.";

        excluded_names_t exclusions{"id", "userId"};

        auto reply = RequestBuilder(ctx)
            .Post("http://localhost:3000/posts")

            // Suppress sending 'id' and 'userId' properties
            .Data(data, nullptr, &exclusions)

            .Execute();
    }).get();
}

void twelfth() {
    auto rest_client = RestClient::Create();
    RestClient::Create()->ProcessWithPromise([&](Context& ctx) {
        Post post;

        // Serialize with a limit of 2 kilobytes of memory usage by the post;
        SerializeFromJson(post,
            RequestBuilder(ctx)
                .Get("http://jsonplaceholder.typicode.com/posts/1")

                // Notice the limit of 2048 bytes
                .Execute(), nullptr, 2048);

        // Serialize with no limit;
        SerializeFromJson(post,
            RequestBuilder(ctx)
                .Get("http://jsonplaceholder.typicode.com/posts/1")

                // Notice how we disable the constraint by defining zero
                .Execute(), nullptr, 0);
    })
    .get();
}

int main() {
    try {
//         cout << "First: " << endl;
//         first();
//
//         cout << "Second: " << endl;
//         second();
//
//         cout << "Third: " << endl;
//         third();
//
//         cout << "Forth: " << endl;
//         forth();
//
//         cout << "Fifth: " << endl;
//         fifth();
//
//         cout << "Sixth: " << endl;
//         sixth();
//
//         cout << "Seventh: " << endl;
//         seventh();
//
//         cout << "Eight: " << endl;
//         eight();
//
//         cout << "Ninth: " << endl;
//         ninth();
//
//         cout << "Tenth: " << endl;
//         tenth();
//
//         cout << "Eleventh: " << endl;
//         eleventh();

        cout << "Twelfth: " << endl;
        twelfth();

    } catch(const exception& ex) {
        cerr << "Something threw up: " << ex.what() << endl;
        return 1;
    }
}
<commit_msg>Re-enabled all readme tests<commit_after>#include <iostream>

#include <boost/lexical_cast.hpp>
#include <boost/fusion/adapted.hpp>

#include "restc-cpp/restc-cpp.h"
#include "restc-cpp/RequestBuilder.h"
#include "restc-cpp/IteratorFromJsonSerializer.h"

using namespace std;
using namespace restc_cpp;

// C++ structure that match the Json entries received
// from http://jsonplaceholder.typicode.com/posts/{id}
struct Post {
    int userId = 0;
    int id = 0;
    string title;
    string body;
};

// Add C++ reflection to the Post structure.
// This allows our Json (de)serialization to do it's magic.
BOOST_FUSION_ADAPT_STRUCT(
    Post,
    (int, userId)
    (int, id)
    (string, title)
    (string, body)
)

// The C++ main function - the place where any adventure starts
void first() {

    // Create and instantiate a Post from data received from the server.
    Post my_post = RestClient::Create()->ProcessWithPromiseT<Post>([&](Context& ctx) {
        // This is a co-routine, running in a worker-thread

        // Instantiate a Post structure.
        Post post;

        // Serialize it asynchronously. The asynchronously part does not really matter
        // here, but it may if you receive huge data structures.
        SerializeFromJson(post,

            // Construct a request to the server
            RequestBuilder(ctx)
                .Get("http://jsonplaceholder.typicode.com/posts/1")

                // Add some headers for good taste
                .Header("X-Client", "RESTC_CPP")
                .Header("X-Client-Purpose", "Testing")

                // Send the request
                .Execute());

        // Return the post instance trough a C++ future<>
        return post;
    })

    // Get the Post instance from the future<>, or any C++ exception thrown
    // within the lambda.
    .get();

    // Print the result for everyone to see.
    cout << "Received post# " << my_post.id << ", title: " << my_post.title;
}

void DoSomethingInteresting(Context& ctx) {
    // Here we are again in a co-routine, running in a worker-thread.

    // Asynchronously connect to a server and fetch some data.
    auto reply = ctx.Get("http://jsonplaceholder.typicode.com/posts/1");

    // Asynchronously fetch the entire data-set and return it as a string.
    auto json = reply->GetBodyAsString();

    // Just dump the data.
    cout << "Received data: " << json << endl;
}

void second() {
    auto rest_client = RestClient::Create();

    // Call DoSomethingInteresting as a co-routine in a worker-thread.
    rest_client->Process(DoSomethingInteresting);

    // Wait for the request to finish
    rest_client->CloseWhenReady(true);
}

void third() {

    auto rest_client = RestClient::Create();
    rest_client->ProcessWithPromise([&](Context& ctx) {
        // Here we are again in a co-routine, running in a worker-thread.

        // Asynchronously connect to a server and fetch some data.
        auto reply = RequestBuilder(ctx)
            .Get("http://localhost:3001/restricted/posts/1")

            // Authenticate as 'alice' with a very popular password
            .BasicAuthentication("alice", "12345")

            // Send the request.
            .Execute();

        // Dump the well protected data
        cout << "Got: " << reply->GetBodyAsString();

    }).get();
}

void forth() {

    // Add the proxy information to the properties used by the client
    Request::Properties properties;
    properties.proxy.type = Request::Proxy::Type::HTTP;
    properties.proxy.address = "http://127.0.0.1:3003";

    // Create the client with our configuration
    auto rest_client = RestClient::Create(properties);
    rest_client->ProcessWithPromise([&](Context& ctx) {
        // Here we are again in a co-routine, running in a worker-thread.

        // Asynchronously connect to a server trough a HTTP proxy and fetch some data.
        auto reply = RequestBuilder(ctx)
            .Get("http://api.example.com/normal/posts/1")

            // Send the request.
            .Execute();

        // Dump the data
        cout << "Got: " << reply->GetBodyAsString();

    }).get();
}

void fifth() {
    // Fetch a list of records asyncrouesly, one by one.
    // This allows us to process single items in a list
    // and fetching more data as we move forward.
    // This works basically as a database cursor, or
    // (literally) as a properly implemented C++ input iterator.

    // Create the REST clent
    auto rest_client = RestClient::Create();

    // Run our example in a lambda co-routine
    rest_client->Process([&](Context& ctx) {
        // This is the co-routine, running in a worker-thread

        // Construct a request to the server
        auto reply = RequestBuilder(ctx)
            .Get("http://jsonplaceholder.typicode.com/posts/")

            // Add some headers for good taste
            .Header("X-Client", "RESTC_CPP")
            .Header("X-Client-Purpose", "Testing")

            // Send the request
            .Execute();

        // Instatiate a serializer with begin() and end() methods that
        // allows us to work with the reply-data trough a C++
        // input iterator.
        IteratorFromJsonSerializer<Post> data{*reply};

        // Iterate over the data, fetch data asyncrounesly as we go.
        for(const auto& post : data) {
            cout << "Item #" << post.id << " Title: " << post.title << endl;
        }
    });

    // Wait for the request to finish
    rest_client->CloseWhenReady(true);
}

void sixth() {
    // Create the client without creating a worker thread
    auto rest_client = RestClient::CreateUseOwnThread();

    // Add a request to the queue of the io-service in the rest client instance
    rest_client->Process([&](Context& ctx) {
        // Here we are again in a co-routine, now in our own thread.

        // Asynchronously connect to a server trough a HTTP proxy and fetch some data.
        auto reply = RequestBuilder(ctx)
            .Get("http://jsonplaceholder.typicode.com/posts/1")

            // Send the request.
            .Execute();

        // Dump the data
        cout << "Got: " << reply->GetBodyAsString();

        // Shut down the io-service. This will cause run() (below) to return.
        rest_client->CloseWhenReady();

    });

    // Start the io-service, using this thread.
    rest_client->GetIoService().run();

    cout << "Done. Exiting normally." << endl;
}

// Use our own RequestBody implementation to supply
// data to a POST request
void seventh() {
    // Our own implementation of the raw data provider
    class MyBody : public RequestBody
    {
    public:
        MyBody() = default;

        Type GetType() const noexcept override {

            // This mode causes the request to use chunked data,
            // allowing us to send data without knowing the exact
            // size of the payload when we start.
            return Type::CHUNKED_LAZY_PULL;
        }

        std::uint64_t GetFixedSize() const override {
            throw runtime_error("Not implemented");
        }

        // This will be called until we return false to indicate
        // that we have no further data
        bool GetData(write_buffers_t& buffers) override {

            if (++count_ > 10) {

                // We are done.
                return false;
            }

            ostringstream data;
            data << "This is line #" << count_ << " of the payload.\r\n";

            // The buffer need to persist until we are called again, or the
            // instance is destroyed.
            data_buffer_ = data.str();

            buffers.emplace_back(data_buffer_.c_str(), data_buffer_.size());

            // We added data to buffers, so return true
            return true;
        }

        // Called if we get a HTTP redirect and need to start over again.
        void Reset() override {
            count_ = 0;
        }

    private:
        int count_ = 0;
        string data_buffer_;
    };

    // Create the REST clent
    auto rest_client = RestClient::Create();

    // Run our example in a lambda co-routine
    rest_client->Process([&](Context& ctx) {
        // This is the co-routine, running in a worker-thread

        // Construct a POST request to the server
        RequestBuilder(ctx)
            .Post("http://localhost:3001/upload_raw/")
            .Header("Content-Type", "text/text")
            .Body(make_unique<MyBody>())
            .Execute();
    });

    // Wait for the request to finish
    rest_client->CloseWhenReady(true);
}

struct DataItem {
    DataItem() = default;
    DataItem(string u, string m)
    : username{u}, motto{m} {}

    int id = 0;
    string username;
    string motto;
};

BOOST_FUSION_ADAPT_STRUCT(
    DataItem,
    (int, id)
    (string, username)
    (string, motto)
)

void eight() {

    // Create the REST clent
    auto rest_client = RestClient::Create();

    // Run our example in a lambda co-routine that returns a future
    rest_client->ProcessWithPromise([&](Context& ctx) {

        // Make a container for data
        std::vector<DataItem> data;

        // Add some data
        data.emplace_back("jgaa", "Carpe Diem!");
        data.emplace_back("trump", "Endorse greed!");
        data.emplace_back("anonymous", "We are great!");

        // Create a request
        auto reply = RequestBuilder(ctx)
            .Post("http://localhost:3001/upload_raw/") // URL

            // Provide data from a lambda
            .DataProvider([&](DataWriter& writer) {
                // Here we are called from Execute() below to provide data

                // Create a json serializer that can write data asynchronously
                RapidJsonInserter<DataItem> inserter(writer, true);

                // Serialize the items from our data container
                for(const auto& d : data) {

                    // Serialize one data item.
                    // If the buffers in the writer fills up, we will
                    // write data to the net asynchronously.
                    inserter.Add(d);
                }

                // Tell the inserter that we have no further data.
                inserter.Done();

            })

            // Execute the request
            .Execute();

    })

    // Wait for the request to finish.
    .get();
}

void ninth() {

    // Create the REST clent
    auto rest_client = RestClient::Create();

    // Run our example in a lambda co-routine that returns a future
    rest_client->ProcessWithPromise([&](Context& ctx) {

        // Make a container for data
        std::vector<DataItem> data;

        // Add some data
        data.emplace_back("jgaa", "Carpe Diem!");
        data.emplace_back("trump", "Endorse greed!");
        data.emplace_back("anonymous", "We are great!");

        // Prepare the request
        auto request = RequestBuilder(ctx)
            .Post("http://localhost:3001/upload_raw/") // URL

            // Make sure we get a DataWriter for chunked data
            // This is required when we add data after the request-
            // headers are sent.
            .Chunked()

            // Just create the request. Send nothing to the server.
            .Build();

        // Send the request to the server. This will send the
        // request line and the request headers.
        auto& writer = request->SendRequest(ctx);

        {
            // Create a json list serializer for our data object.
            RapidJsonInserter<DataItem> inserter(writer, true);

            // Write each item to the server
            for(const auto& d : data) {
                inserter.Add(d);
            }
        }

        // Finish the request and fetch the reply asynchronously
        // This function returns when we have the reply headers.
        // If we expect data in the reply, we can read it asynchronously
        // as shown in previous examples.
        auto reply = request->GetReply(ctx);

        cout << "The server replied with code: " << reply->GetResponseCode();

    })

    // Wait for the request to finish.
    .get();
}

void tenth() {
    // Construct our own ioservice.
    boost::asio::io_service ioservice;

    // Give it some work so it don't end prematurely
    boost::asio::io_service::work work(ioservice);

    // Start it in a worker-thread
    thread worker([&ioservice]() {
        cout << "ioservice is running" << endl;
        ioservice.run();
        cout << "ioservice is done" << endl;
    });

    // Now we have our own io-service running in a worker thread.
    // Create a RestClient instance that uses it.

    auto rest_client = RestClient::Create(ioservice);

    // Make a HTTP request
    rest_client->ProcessWithPromise([&](Context& ctx) {
        // Here we are in a co-routine, spawned from our io-service, running
        // in our worker thread.

        // Asynchronously connect to a server and fetch some data.
        auto reply = ctx.Get("http://jsonplaceholder.typicode.com/posts/1");

        // Asynchronously fetch the entire data-set and return it as a string.
        auto json = reply->GetBodyAsString();

        // Just dump the data.
        cout << "Received data: " << json << endl;
    })
    // Wait for the co-routine to end
    .get();

    // Stop the io-service
    // (We can not just remove 'work', as the rest client may have
    // timers pending in the io-service, keeping it running even after
    // work is gone).
    ioservice.stop();

    // Wait for the worker thread to end
    worker.join();

    cout << "Done." << endl;
}

void eleventh() {
    auto rest_client = RestClient::Create();
    rest_client->ProcessWithPromise([&](Context& ctx) {

        Post data;
        data.id = 10;
        data.userId = 14;
        data.title = "Hi there";
        data.body = "This is the body.";

        excluded_names_t exclusions{"id", "userId"};

        auto reply = RequestBuilder(ctx)
            .Post("http://localhost:3000/posts")

            // Suppress sending 'id' and 'userId' properties
            .Data(data, nullptr, &exclusions)

            .Execute();
    }).get();
}

void twelfth() {
    auto rest_client = RestClient::Create();
    RestClient::Create()->ProcessWithPromise([&](Context& ctx) {
        Post post;

        // Serialize with a limit of 2 kilobytes of memory usage by the post;
        SerializeFromJson(post,
            RequestBuilder(ctx)
                .Get("http://jsonplaceholder.typicode.com/posts/1")

                // Notice the limit of 2048 bytes
                .Execute(), nullptr, 2048);

        // Serialize with no limit;
        SerializeFromJson(post,
            RequestBuilder(ctx)
                .Get("http://jsonplaceholder.typicode.com/posts/1")

                // Notice how we disable the constraint by defining zero
                .Execute(), nullptr, 0);
    })
    .get();
}

int main() {
    try {
        cout << "First: " << endl;
        first();

        cout << "Second: " << endl;
        second();

        cout << "Third: " << endl;
        third();

        cout << "Forth: " << endl;
        forth();

        cout << "Fifth: " << endl;
        fifth();

        cout << "Sixth: " << endl;
        sixth();

        cout << "Seventh: " << endl;
        seventh();

        cout << "Eight: " << endl;
        eight();

        cout << "Ninth: " << endl;
        ninth();

        cout << "Tenth: " << endl;
        tenth();

        cout << "Eleventh: " << endl;
        eleventh();

        cout << "Twelfth: " << endl;
        twelfth();

    } catch(const exception& ex) {
        cerr << "Something threw up: " << ex.what() << endl;
        return 1;
    }
}
<|endoftext|>