text:
//
// async_tcp_client.cpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include <boost/asio/buffer.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/read_until.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/write.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <string>

using boost::asio::steady_timer;
using boost::asio::ip::tcp;

//
// This class manages socket timeouts by applying the concept of a deadline.
// Some asynchronous operations are given deadlines by which they must complete.
// Deadlines are enforced by an "actor" that persists for the lifetime of the
// client object:
//
//  +----------------+
//  |                |
//  | check_deadline |<---+
//  |                |    |
//  +----------------+    | async_wait()
//              |         |
//              +---------+
//
// If the deadline actor determines that the deadline has expired, the socket
// is closed and any outstanding operations are consequently cancelled.
//
// Connection establishment involves trying each endpoint in turn until a
// connection is successful, or the available endpoints are exhausted. If the
// deadline actor closes the socket, the connect actor is woken up and moves to
// the next endpoint.
//
//  +---------------+
//  |               |
//  | start_connect |<---+
//  |               |    |
//  +---------------+    |
//           |           |
//  async_-  |    +----------------+
// connect() |    |                |
//           +--->| handle_connect |
//                |                |
//                +----------------+
//                          :
// Once a connection is     :
// made, the connect        :
// actor forks in two -     :
//                          :
// an actor for reading     :       and an actor for
// inbound messages:        :       sending heartbeats:
//                          :
//  +------------+          :          +-------------+
//  |            |<- - - - -+- - - - ->|             |
//  | start_read |                     | start_write |<---+
//  |            |<---+                |             |    |
//  +------------+    |                +-------------+    | async_wait()
//          |         |                        |          |
//  async_- |    +-------------+       async_- |    +--------------+
//   read_- |    |             |       write() |    |              |
//  until() +--->| handle_read |               +--->| handle_write |
//               |             |                    |              |
//               +-------------+                    +--------------+
//
// The input actor reads messages from the socket, where messages are delimited
// by the newline character. The deadline for a complete message is 30 seconds.
//
// The heartbeat actor sends a heartbeat (a message that consists of a single
// newline character) every 10 seconds. In this example, no deadline is applied
// to message sending.
//
class client
{
public:
  client(boost::asio::io_context& io_context)
    : stopped_(false),
      socket_(io_context),
      deadline_(io_context),
      heartbeat_timer_(io_context)
  {
  }

  // Called by the user of the client class to initiate the connection process.
  // The endpoints will have been obtained using a tcp::resolver.
  void start(tcp::resolver::results_type endpoints)
  {
    // Start the connect actor.
    endpoints_ = endpoints;
    start_connect(endpoints_.begin());

    // Start the deadline actor. You will note that we're not setting any
    // particular deadline here. Instead, the connect and input actors will
    // update the deadline prior to each asynchronous operation.
    deadline_.async_wait(boost::bind(&client::check_deadline, this));
  }

  // This function terminates all the actors to shut down the connection. It
  // may be called by the user of the client class, or by the class itself in
  // response to graceful termination or an unrecoverable error.
  void stop()
  {
    stopped_ = true;
    boost::system::error_code ignored_ec;
    socket_.close(ignored_ec);
    deadline_.cancel();
    heartbeat_timer_.cancel();
  }

private:
  void start_connect(tcp::resolver::results_type::iterator endpoint_iter)
  {
    if (endpoint_iter != endpoints_.end())
    {
      std::cout << "Trying " << endpoint_iter->endpoint() << "...\n";

      // Set a deadline for the connect operation.
      deadline_.expires_after(boost::asio::chrono::seconds(60));

      // Start the asynchronous connect operation.
      socket_.async_connect(endpoint_iter->endpoint(),
          boost::bind(&client::handle_connect,
            this, _1, endpoint_iter));
    }
    else
    {
      // There are no more endpoints to try. Shut down the client.
      stop();
    }
  }

  void handle_connect(const boost::system::error_code& ec,
      tcp::resolver::results_type::iterator endpoint_iter)
  {
    if (stopped_)
      return;

    // The async_connect() function automatically opens the socket at the start
    // of the asynchronous operation. If the socket is closed at this time then
    // the timeout handler must have run first.
    if (!socket_.is_open())
    {
      std::cout << "Connect timed out\n";

      // Try the next available endpoint.
      start_connect(++endpoint_iter);
    }

    // Check if the connect operation failed before the deadline expired.
    else if (ec)
    {
      std::cout << "Connect error: " << ec.message() << "\n";

      // We need to close the socket used in the previous connection attempt
      // before starting a new one.
      socket_.close();

      // Try the next available endpoint.
      start_connect(++endpoint_iter);
    }

    // Otherwise we have successfully established a connection.
    else
    {
      std::cout << "Connected to " << endpoint_iter->endpoint() << "\n";

      // Start the input actor.
      start_read();

      // Start the heartbeat actor.
      start_write();
    }
  }

  void start_read()
  {
    // Set a deadline for the read operation.
    deadline_.expires_after(boost::asio::chrono::seconds(30));

    // Start an asynchronous operation to read a newline-delimited message.
    boost::asio::async_read_until(socket_,
        boost::asio::dynamic_buffer(input_buffer_), '\n',
        boost::bind(&client::handle_read, this, _1, _2));
  }

  void handle_read(const boost::system::error_code& ec, std::size_t n)
  {
    if (stopped_)
      return;

    if (!ec)
    {
      // Extract the newline-delimited message from the buffer.
      std::string line(input_buffer_.substr(0, n - 1));
      input_buffer_.erase(0, n);

      // Empty messages are heartbeats and so ignored.
      if (!line.empty())
      {
        std::cout << "Received: " << line << "\n";
      }

      start_read();
    }
    else
    {
      std::cout << "Error on receive: " << ec.message() << "\n";

      stop();
    }
  }

  void start_write()
  {
    if (stopped_)
      return;

    // Start an asynchronous operation to send a heartbeat message.
    boost::asio::async_write(socket_, boost::asio::buffer("\n", 1),
        boost::bind(&client::handle_write, this, _1));
  }

  void handle_write(const boost::system::error_code& ec)
  {
    if (stopped_)
      return;

    if (!ec)
    {
      // Wait 10 seconds before sending the next heartbeat.
      heartbeat_timer_.expires_after(boost::asio::chrono::seconds(10));
      heartbeat_timer_.async_wait(boost::bind(&client::start_write, this));
    }
    else
    {
      std::cout << "Error on heartbeat: " << ec.message() << "\n";

      stop();
    }
  }

  void check_deadline()
  {
    if (stopped_)
      return;

    // Check whether the deadline has passed. We compare the deadline against
    // the current time since a new asynchronous operation may have moved the
    // deadline before this actor had a chance to run.
    if (deadline_.expiry() <= steady_timer::clock_type::now())
    {
      // The deadline has passed. The socket is closed so that any outstanding
      // asynchronous operations are cancelled.
      socket_.close();

      // There is no longer an active deadline. The expiry is set to the
      // maximum time point so that the actor takes no action until a new
      // deadline is set.
      deadline_.expires_at(steady_timer::time_point::max());
    }

    // Put the actor back to sleep.
    deadline_.async_wait(boost::bind(&client::check_deadline, this));
  }

private:
  bool stopped_;
  tcp::resolver::results_type endpoints_;
  tcp::socket socket_;
  std::string input_buffer_;
  steady_timer deadline_;
  steady_timer heartbeat_timer_;
};

int main(int argc, char* argv[])
{
  try
  {
    if (argc != 3)
    {
      std::cerr << "Usage: client <host> <port>\n";
      return 1;
    }

    boost::asio::io_context io_context;
    tcp::resolver r(io_context);
    client c(io_context);

    c.start(r.resolve(argv[1], argv[2]));

    io_context.run();
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << "\n";
  }

  return 0;
}


text:
/**
* @file llsnapshotlivepreview.cpp
* @brief Implementation of llsnapshotlivepreview
* @author Gilbert@lindenlab.com
*
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2014, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
* $/LicenseInfo$
*/

#include "llviewerprecompiledheaders.h"

#include "llagent.h"
#include "llagentbenefits.h"
#include "llagentcamera.h"
#include "llagentui.h"
#include "llcombobox.h"
#include "llfloaterperms.h"
#include "llfloaterreg.h"
#include "llfloaterflickr.h" // <FS:Ansariel> Share to Flickr
#include "llimagefilter.h"
#include "llimagefiltersmanager.h"
#include "llimagebmp.h"
#include "llimagej2c.h"
#include "llimagejpeg.h"
#include "llimagepng.h"
#include "lllandmarkactions.h"
#include "lllocalcliprect.h"
#include "llresmgr.h"
#include "llnotificationsutil.h"
#include "llslurl.h"
#include "llsnapshotlivepreview.h"
#include "lltoolfocus.h"
#include "llviewercontrol.h"
#include "llviewermenufile.h"	// upload_new_resource()
#include "llviewerstats.h"
#include "llvfile.h"
#include "llvfs.h"
#include "llwindow.h"
#include "llworld.h"
#include <boost/filesystem.hpp>

const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;

F32 SHINE_TIME = 0.5f;
F32 SHINE_WIDTH = 0.6f;
F32 SHINE_OPACITY = 0.3f;
F32 FALL_TIME = 0.6f;
S32 BORDER_WIDTH = 6;
S32 TOP_PANEL_HEIGHT = 30;

const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512

std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList;
LLPointer<LLImageFormatted> LLSnapshotLivePreview::sSaveLocalImage = NULL;

LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p)
	:	LLView(p),
	mColor(1.f, 0.f, 0.f, 0.5f),
	mCurImageIndex(0),
	mPreviewImage(NULL),
    mThumbnailImage(NULL) ,
    mBigThumbnailImage(NULL) ,
	mThumbnailWidth(0),
	mThumbnailHeight(0),
    mThumbnailSubsampled(FALSE),
	mPreviewImageEncoded(NULL),
	mFormattedImage(NULL),
	mShineCountdown(0),
	mFlashAlpha(0.f),
	mNeedsFlash(TRUE),
	mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),
	mDataSize(0),
	mSnapshotType(LLSnapshotModel::SNAPSHOT_POSTCARD),
	mSnapshotFormat(LLSnapshotModel::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),
	mSnapshotUpToDate(FALSE),
	mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
	mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
	mSnapshotActive(FALSE),
	mSnapshotBufferType(LLSnapshotModel::SNAPSHOT_TYPE_COLOR),
    mFilterName(""),
    mAllowRenderUI(TRUE),
    mAllowFullScreenPreview(TRUE),
    mViewContainer(NULL),
	mFixedThumbnailWidth(0),
	mFixedThumbnailHeight(0),
	mFixedThumbnailImageWidth(0),
	mFixedThumbnailImageHeight(0)
{
	setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
	mSnapshotDelayTimer.setTimerExpirySec(0.0f);
	mSnapshotDelayTimer.start();
	// 	gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
	sList.insert(this);
	setFollowsAll();
	mWidth[0] = gViewerWindow->getWindowWidthRaw();
	mWidth[1] = gViewerWindow->getWindowWidthRaw();
	mHeight[0] = gViewerWindow->getWindowHeightRaw();
	mHeight[1] = gViewerWindow->getWindowHeightRaw();
	mImageScaled[0] = FALSE;
	mImageScaled[1] = FALSE;

	mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
	mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
	mThumbnailUpdateLock = FALSE ;
	mThumbnailUpToDate   = FALSE ;
	mBigThumbnailUpToDate = FALSE ;

	mForceUpdateSnapshot = FALSE;
}

LLSnapshotLivePreview::~LLSnapshotLivePreview()
{
	// delete images
	mPreviewImage = NULL;
	mPreviewImageEncoded = NULL;
	mFormattedImage = NULL;

	// 	gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
	sList.erase(this);
	sSaveLocalImage = NULL;
}

void LLSnapshotLivePreview::setMaxImageSize(S32 size)
{
    mMaxImageSize = llmin(size,(S32)(MAX_SNAPSHOT_IMAGE_SIZE));
}

LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
{
	return mViewerImage[mCurImageIndex];
}

F32 LLSnapshotLivePreview::getImageAspect()
{
	if (!getCurrentImage())
	{
		return 0.f;
	}
	// mKeepAspectRatio) == gSavedSettings.getBOOL("KeepAspectForSnapshot"))
    return (mKeepAspectRatio ? ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()) : ((F32)getWidth()) / ((F32)getHeight()));
}

void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay)
{
	LL_DEBUGS("Snapshot") << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << LL_ENDL;

	// Update snapshot if requested.
	if (new_snapshot)
	{
        if (getSnapshotUpToDate())
        {
            S32 old_image_index = mCurImageIndex;
            mCurImageIndex = (mCurImageIndex + 1) % 2;
            setSize(mWidth[old_image_index], mHeight[old_image_index]);
            mFallAnimTimer.start();
        }
        mSnapshotUpToDate = FALSE;

        // Update snapshot source rect depending on whether we keep the aspect ratio.
        LLRect& rect = mImageRect[mCurImageIndex];
        rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);

        F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
        F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());

        if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
        {
            if (image_aspect_ratio > window_aspect_ratio)
            {
                // trim off top and bottom
                S32 new_height = ll_round((F32)getRect().getWidth() / image_aspect_ratio);
                rect.mBottom += (getRect().getHeight() - new_height) / 2;
                rect.mTop -= (getRect().getHeight() - new_height) / 2;
            }
            else if (image_aspect_ratio < window_aspect_ratio)
            {
                // trim off left and right
                S32 new_width = ll_round((F32)getRect().getHeight() * image_aspect_ratio);
                rect.mLeft += (getRect().getWidth() - new_width) / 2;
                rect.mRight -= (getRect().getWidth() - new_width) / 2;
            }
        }

        // Stop shining animation.
        mShineAnimTimer.stop();
		mSnapshotDelayTimer.start();
		mSnapshotDelayTimer.resetWithExpiry(delay);

		mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();

        // Tell the floater container that the snapshot is in the process of updating itself
        if (mViewContainer)
        {
            mViewContainer->notify(LLSD().with("snapshot-updating", true));
        }
	}

	// Update thumbnail if requested.
	if (new_thumbnail)
	{
		mThumbnailUpToDate = FALSE ;
        mBigThumbnailUpToDate = FALSE;
	}
}

// Return true if the quality has been changed, false otherwise
bool LLSnapshotLivePreview::setSnapshotQuality(S32 quality, bool set_by_user)
{
	llclamp(quality, 0, 100);
	if (quality != mSnapshotQuality)
	{
		mSnapshotQuality = quality;
        if (set_by_user)
        {
            gSavedSettings.setS32("SnapshotQuality", quality);
        }
        mFormattedImage = NULL;     // Invalidate the already formatted image if any
        return true;
	}
    return false;
}

void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
{
	F32 line_width ;
	glGetFloatv(GL_LINE_WIDTH, &line_width) ;
	gGL.setLineWidth(2.0f * line_width) ; // <FS> Line width OGL core profile fix by Rye Mutt
	LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ;
	gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y,
		mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ;
	gGL.setLineWidth(line_width) ; // <FS> Line width OGL core profile fix by Rye Mutt

	//draw four alpha rectangles to cover areas outside of the snapshot image
	if(!mKeepAspectRatio)
	{
		LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ;
		S32 dwl = 0, dwr = 0 ;
		if(mThumbnailWidth > mPreviewRect.getWidth())
		{
			dwl = (mThumbnailWidth - mPreviewRect.getWidth()) >> 1 ;
			dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ;

			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y,
				mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
			gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y,
				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
		}

		if(mThumbnailHeight > mPreviewRect.getHeight())
		{
			S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ;
			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y ,
				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ;

			dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ;
			gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh,
				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ;
		}
	}
}

//called when the frame is frozen.
void LLSnapshotLivePreview::draw()
{
	if (getCurrentImage() &&
		mPreviewImageEncoded.notNull() &&
		getSnapshotUpToDate())
	{
		LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f);
		gl_rect_2d(getRect(), bg_color);
		const LLRect& rect = getImageRect();
		LLRect shadow_rect = rect;
		shadow_rect.stretch(BORDER_WIDTH);
		gl_drop_shadow(shadow_rect.mLeft, shadow_rect.mTop, shadow_rect.mRight, shadow_rect.mBottom, LLColor4(0.f, 0.f, 0.f, mNeedsFlash ? 0.f :0.5f), 10);

		LLColor4 image_color(1.f, 1.f, 1.f, 1.f);
		gGL.color4fv(image_color.mV);
		gGL.getTexUnit(0)->bind(getCurrentImage());
		// calculate UV scale
		F32 uv_width = isImageScaled() ? 1.f : llmin((F32)getWidth() / (F32)getCurrentImage()->getWidth(), 1.f);
		F32 uv_height = isImageScaled() ? 1.f : llmin((F32)getHeight() / (F32)getCurrentImage()->getHeight(), 1.f);
		gGL.pushMatrix();
		{
			gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom + TOP_PANEL_HEIGHT, 0.f);
			// <FS:Ansariel> Remove QUADS rendering mode
			//gGL.begin(LLRender::QUADS);
			//{
			//	gGL.texCoord2f(uv_width, uv_height);
			//	gGL.vertex2i(rect.getWidth(), rect.getHeight() );

			//	gGL.texCoord2f(0.f, uv_height);
			//	gGL.vertex2i(0, rect.getHeight() );

			//	gGL.texCoord2f(0.f, 0.f);
			//	gGL.vertex2i(0, 0);

			//	gGL.texCoord2f(uv_width, 0.f);
			//	gGL.vertex2i(rect.getWidth(), 0);
			//}
			//gGL.end();
			gGL.begin(LLRender::TRIANGLES);
			{
				gGL.texCoord2f(uv_width, uv_height);
				gGL.vertex2i(rect.getWidth(), rect.getHeight() );

				gGL.texCoord2f(0.f, uv_height);
				gGL.vertex2i(0, rect.getHeight() );

				gGL.texCoord2f(0.f, 0.f);
				gGL.vertex2i(0, 0);

				gGL.texCoord2f(uv_width, uv_height);
				gGL.vertex2i(rect.getWidth(), rect.getHeight() );

				gGL.texCoord2f(0.f, 0.f);
				gGL.vertex2i(0, 0);

				gGL.texCoord2f(uv_width, 0.f);
				gGL.vertex2i(rect.getWidth(), 0);
			}
			gGL.end();
			// </FS:Ansariel>
		}
		gGL.popMatrix();

		gGL.color4f(1.f, 1.f, 1.f, mFlashAlpha);
		gl_rect_2d(getRect());
		if (mNeedsFlash)
		{
			if (mFlashAlpha < 1.f)
			{
				mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f));
			}
			else
			{
				mNeedsFlash = FALSE;
			}
		}
		else
		{
			mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f));
		}

		// Draw shining animation if appropriate.
		if (mShineCountdown > 0)
		{
			mShineCountdown--;
			if (mShineCountdown == 0)
			{
				mShineAnimTimer.start();
			}
		}
		else if (mShineAnimTimer.getStarted())
		{
			LL_DEBUGS("Snapshot") << "Drawing shining animation" << LL_ENDL;
			F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);

			// draw "shine" effect
			LLRect local_rect(0, getRect().getHeight() + TOP_PANEL_HEIGHT, getRect().getWidth(), 0);
			LLLocalClipRect clip(local_rect);
			{
				// draw diagonal stripe with gradient that passes over screen
				S32 x1 = gViewerWindow->getWindowWidthScaled() * ll_round((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f)));
				S32 x2 = x1 + ll_round(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
				S32 x3 = x2 + ll_round(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
				S32 y1 = 0;
				S32 y2 = gViewerWindow->getWindowHeightScaled() + TOP_PANEL_HEIGHT;

				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
				// <FS:Ansariel> Remove QUADS rendering mode
				//gGL.begin(LLRender::QUADS);
				//{
				//	gGL.color4f(1.f, 1.f, 1.f, 0.f);
				//	gGL.vertex2i(x1, y1);
				//	gGL.vertex2i(x1 + gViewerWindow->getWindowWidthScaled(), y2);
				//	gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
				//	gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
				//	gGL.vertex2i(x2, y1);

				//	gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
				//	gGL.vertex2i(x2, y1);
				//	gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
				//	gGL.color4f(1.f, 1.f, 1.f, 0.f);
				//	gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2);
				//	gGL.vertex2i(x3, y1);
				//}
				//gGL.end();
				gGL.begin(LLRender::TRIANGLES);
				{
					gGL.color4f(1.f, 1.f, 1.f, 0.f);
					gGL.vertex2i(x1, y1);
					gGL.vertex2i(x1 + gViewerWindow->getWindowWidthScaled(), y2);
					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);

					gGL.color4f(1.f, 1.f, 1.f, 0.f);
					gGL.vertex2i(x1, y1);
					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
					gGL.vertex2i(x2, y1);

					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
					gGL.vertex2i(x2, y1);
					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
					gGL.color4f(1.f, 1.f, 1.f, 0.f);
					gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2);

					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
					gGL.vertex2i(x2, y1);
					gGL.color4f(1.f, 1.f, 1.f, 0.f);
					gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2);
					gGL.vertex2i(x3, y1);
				}
				gGL.end();
				// </FS:Ansariel>
			}

			// if we're at the end of the animation, stop
			if (shine_interp >= 1.f)
			{
				mShineAnimTimer.stop();
			}
		}
	}

	// draw old image dropping away
	if (mFallAnimTimer.getStarted())
	{
		S32 old_image_index = (mCurImageIndex + 1) % 2;
		if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME)
		{
			LL_DEBUGS("Snapshot") << "Drawing fall animation" << LL_ENDL;
			F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME;
			F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f);
			LLColor4 image_color(1.f, 1.f, 1.f, alpha);
			gGL.color4fv(image_color.mV);
			gGL.getTexUnit(0)->bind(mViewerImage[old_image_index]);
			// calculate UV scale
			// *FIX get this to work with old image
			BOOL rescale = !mImageScaled[old_image_index] && mViewerImage[mCurImageIndex].notNull();
			F32 uv_width = rescale ? llmin((F32)mWidth[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f) : 1.f;
			F32 uv_height = rescale ? llmin((F32)mHeight[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f) : 1.f;
			gGL.pushMatrix();
			{
				LLRect& rect = mImageRect[old_image_index];
				gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom - ll_round(getRect().getHeight() * 2.f * (fall_interp * fall_interp)), 0.f);
				gGL.rotatef(-45.f * fall_interp, 0.f, 0.f, 1.f);
				// <FS:Ansariel> Remove QUADS rendering mode
				//gGL.begin(LLRender::QUADS);
				//{
				//	gGL.texCoord2f(uv_width, uv_height);
				//	gGL.vertex2i(rect.getWidth(), rect.getHeight() );

				//	gGL.texCoord2f(0.f, uv_height);
				//	gGL.vertex2i(0, rect.getHeight() );

				//	gGL.texCoord2f(0.f, 0.f);
				//	gGL.vertex2i(0, 0);

				//	gGL.texCoord2f(uv_width, 0.f);
				//	gGL.vertex2i(rect.getWidth(), 0);
				//}
				//gGL.end();
				gGL.begin(LLRender::TRIANGLES);
				{
					gGL.texCoord2f(uv_width, uv_height);
					gGL.vertex2i(rect.getWidth(), rect.getHeight() );

					gGL.texCoord2f(0.f, uv_height);
					gGL.vertex2i(0, rect.getHeight() );

					gGL.texCoord2f(0.f, 0.f);
					gGL.vertex2i(0, 0);

					gGL.texCoord2f(uv_width, uv_height);
					gGL.vertex2i(rect.getWidth(), rect.getHeight() );

					gGL.texCoord2f(0.f, 0.f);
					gGL.vertex2i(0, 0);

					gGL.texCoord2f(uv_width, 0.f);
					gGL.vertex2i(rect.getWidth(), 0);
				}
				gGL.end();
				// </FS:Ansariel>
			}
			gGL.popMatrix();
		}
	}
}

/*virtual*/
void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_parent)
{
	LLRect old_rect = getRect();
	LLView::reshape(width, height, called_from_parent);
	if (old_rect.getWidth() != width || old_rect.getHeight() != height)
	{
		LL_DEBUGS("Window", "Snapshot") << "window reshaped, updating thumbnail" << LL_ENDL;
		if (mViewContainer && mViewContainer->isInVisibleChain())
		{
			// We usually resize only on window reshape, so give it a chance to redraw, assign delay
			updateSnapshot(
				TRUE, // new snapshot is needed
				FALSE, // thumbnail will be updated either way.
				AUTO_SNAPSHOT_TIME_DELAY); // shutter delay.
		}
	}
}

BOOL LLSnapshotLivePreview::setThumbnailImageSize()
{
	if (getWidth() < 10 || getHeight() < 10)
	{
		return FALSE ;
	}
	S32 width  = (mThumbnailSubsampled ? mPreviewImage->getWidth()  : gViewerWindow->getWindowWidthRaw());
	S32 height = (mThumbnailSubsampled ? mPreviewImage->getHeight() : gViewerWindow->getWindowHeightRaw()) ;

	F32 aspect_ratio = ((F32)width) / ((F32)height);

	// UI size for thumbnail
	S32 max_width  = mThumbnailPlaceholderRect.getWidth();
	S32 max_height = mThumbnailPlaceholderRect.getHeight();

	if (aspect_ratio > (F32)max_width / (F32)max_height)
	{
		// image too wide, shrink to width
		mThumbnailWidth = max_width;
		mThumbnailHeight = ll_round((F32)max_width / aspect_ratio);
	}
	else
	{
		// image too tall, shrink to height
		mThumbnailHeight = max_height;
		mThumbnailWidth = ll_round((F32)max_height * aspect_ratio);
	}

	if (mThumbnailWidth > width || mThumbnailHeight > height)
	{
		return FALSE ;//if the window is too small, ignore thumbnail updating.
	}

	// <FS:Ansariel> Show miniature thumbnail on collapsed snapshot panel
	if (mFixedThumbnailWidth > 0 && mFixedThumbnailHeight > 0)
	{
		if (aspect_ratio > (F32)mFixedThumbnailWidth / (F32)mFixedThumbnailHeight)
		{
			// image too wide, shrink to width
			mFixedThumbnailImageWidth = mFixedThumbnailWidth;
			mFixedThumbnailImageHeight = ll_round((F32)mFixedThumbnailWidth / aspect_ratio);
		}
		else
		{
			// image too tall, shrink to height
			mFixedThumbnailImageHeight = mFixedThumbnailHeight;
			mFixedThumbnailImageWidth = ll_round((F32)mFixedThumbnailHeight * aspect_ratio);
		}
	}
	// </FS:Ansariel>

	S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ;
	if (!mKeepAspectRatio)
	{
		F32 ratio_x = (F32)getWidth()  / width ;
		F32 ratio_y = (F32)getHeight() / height ;

        if (ratio_x > ratio_y)
        {
            top = (S32)(top * ratio_y / ratio_x) ;
        }
        else
        {
            right = (S32)(right * ratio_x / ratio_y) ;
        }
		left = (S32)((mThumbnailWidth - right) * 0.5f) ;
		bottom = (S32)((mThumbnailHeight - top) * 0.5f) ;
		top += bottom ;
		right += left ;
	}
	mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ;

	return TRUE ;
}

void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
{
	if(mThumbnailUpdateLock) //in the process of updating
	{
		return ;
	}
	if(getThumbnailUpToDate() && !force_update)//already updated
	{
		return ;
	}
	if(getWidth() < 10 || getHeight() < 10)
	{
		return ;
	}

	////lock updating
	mThumbnailUpdateLock = TRUE ;

	if(!setThumbnailImageSize())
	{
		mThumbnailUpdateLock = FALSE ;
		mThumbnailUpToDate = TRUE ;
		return ;
	}

    // Invalidate the big thumbnail when we regenerate the small one
    mBigThumbnailUpToDate = FALSE;

	if(mThumbnailImage)
	{
		resetThumbnailImage() ;
	}

	LLPointer<LLImageRaw> raw = new LLImageRaw;

    if (mThumbnailSubsampled)
    {
        // The thumbnail is be a subsampled version of the preview (used in SL Share previews, i.e. Flickr, Twitter)
		raw->resize( mPreviewImage->getWidth(),
                     mPreviewImage->getHeight(),
                     mPreviewImage->getComponents());
        raw->copy(mPreviewImage);
        // Scale to the thumbnail size
        if (!raw->scale(mThumbnailWidth, mThumbnailHeight))
        {
            raw = NULL ;
        }
    }
    else
    {
		// <FS:Ansariel> Show miniature thumbnail on collapsed snapshot panel
		S32 width = mThumbnailWidth;
		S32 height = mThumbnailHeight;
		if (mFixedThumbnailImageWidth > 0 && mFixedThumbnailImageHeight > 0)
		{
			width = mFixedThumbnailImageWidth;
			height = mFixedThumbnailImageHeight;
		}
		// </FS:Ansariel>

        // The thumbnail is a screen view with screen grab positioning preview
        if(!gViewerWindow->thumbnailSnapshot(raw,
                                         // <FS:Ansariel> Show miniature thumbnail on collapsed snapshot panel
                                         //mThumbnailWidth, mThumbnailHeight,
                                         width, height,
                                         // </FS:Ansariel>
                                         mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"),
                                         gSavedSettings.getBOOL("RenderHUDInSnapshot"),
                                         FALSE,
                                         mSnapshotBufferType) )
        {
            raw = NULL ;
        }
    }

	if (raw)
	{
        // Filter the thumbnail
        // Note: filtering needs to be done *before* the scaling to power of 2 or the effect is distorted
        if (getFilter() != "")
        {
            std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
            if (filter_path != "")
            {
                LLImageFilter filter(filter_path);
                filter.executeFilter(raw);
            }
            else
            {
                LL_WARNS("Snapshot") << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL;
            }
        }
        // Scale to a power of 2 so it can be mapped to a texture
        raw->expandToPowerOfTwo();
		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
		mThumbnailUpToDate = TRUE ;
	}

	//unlock updating
	mThumbnailUpdateLock = FALSE ;
}

LLViewerTexture* LLSnapshotLivePreview::getBigThumbnailImage()
{
	if (mThumbnailUpdateLock) //in the process of updating
	{
		return NULL;
	}
	if (mBigThumbnailUpToDate && mBigThumbnailImage)//already updated
	{
		return mBigThumbnailImage;
	}

	LLPointer<LLImageRaw> raw = new LLImageRaw;

	if (raw)
	{
        // The big thumbnail is a new filtered version of the preview (used in SL Share previews, i.e. Flickr, Twitter)
        mBigThumbnailWidth = mPreviewImage->getWidth();
        mBigThumbnailHeight = mPreviewImage->getHeight();
        raw->resize( mBigThumbnailWidth,
                     mBigThumbnailHeight,
                     mPreviewImage->getComponents());
        raw->copy(mPreviewImage);

        // Filter
        // Note: filtering needs to be done *before* the scaling to power of 2 or the effect is distorted
        if (getFilter() != "")
        {
            std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
            if (filter_path != "")
            {
                LLImageFilter filter(filter_path);
                filter.executeFilter(raw);
            }
            else
            {
                LL_WARNS("Snapshot") << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL;
            }
        }
        // Scale to a power of 2 so it can be mapped to a texture
        raw->expandToPowerOfTwo();
		mBigThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
		mBigThumbnailUpToDate = TRUE ;
	}

    return mBigThumbnailImage ;
}

// Called often. Checks whether it's time to grab a new snapshot and if so, does it.
// Returns TRUE if new snapshot generated, FALSE otherwise.
//static
BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
{
	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;
	if (previewp->getWidth() == 0 || previewp->getHeight() == 0)
	{
		LL_WARNS("Snapshot") << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << LL_ENDL;
		return FALSE;
	}

	if (previewp->mSnapshotDelayTimer.getStarted()) // Wait for a snapshot delay timer
	{
		if (!previewp->mSnapshotDelayTimer.hasExpired())
		{
			return FALSE;
		}
		previewp->mSnapshotDelayTimer.stop();
	}

	if (LLToolCamera::getInstance()->hasMouseCapture()) // Hide full-screen preview while camming, either don't take snapshots while ALT-zoom active
	{
		previewp->setVisible(FALSE);
		return FALSE;
	}

	// If we're in freeze-frame and/or auto update mode and camera has moved, update snapshot.
	LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
	LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
	if (previewp->mForceUpdateSnapshot ||
		(((gSavedSettings.getBOOL("AutoSnapshot") && LLView::isAvailable(previewp->mViewContainer)) ||
		(gSavedSettings.getBOOL("FreezeTime") && previewp->mAllowFullScreenPreview)) &&
		(new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f)))
	{
		previewp->mCameraPos = new_camera_pos;
		previewp->mCameraRot = new_camera_rot;
		// request a new snapshot whenever the camera moves, with a time delay
		BOOL new_snapshot = gSavedSettings.getBOOL("AutoSnapshot") || previewp->mForceUpdateSnapshot;
		LL_DEBUGS("Snapshot") << "camera moved, updating thumbnail" << LL_ENDL;
		previewp->updateSnapshot(
			new_snapshot, // whether a new snapshot is needed or merely invalidate the existing one
			FALSE, // or if 1st arg is false, whether to produce a new thumbnail image.
			new_snapshot ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); // shutter delay if 1st arg is true.
		previewp->mForceUpdateSnapshot = FALSE;
	}

	if (previewp->getSnapshotUpToDate() && previewp->getThumbnailUpToDate())
	{
		return FALSE;
	}

	// time to produce a snapshot
	if(!previewp->getSnapshotUpToDate())
    {
        LL_DEBUGS("Snapshot") << "producing snapshot" << LL_ENDL;
        if (!previewp->mPreviewImage)
        {
            previewp->mPreviewImage = new LLImageRaw;
        }

        previewp->mSnapshotActive = TRUE;

        previewp->setVisible(FALSE);
        previewp->setEnabled(FALSE);

        previewp->getWindow()->incBusyCount();
        previewp->setImageScaled(FALSE);

        // grab the raw image
        if (gViewerWindow->rawSnapshot(
                previewp->mPreviewImage,
                previewp->getWidth(),
                previewp->getHeight(),
                previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
                previewp->getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE,
                previewp->mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"),
                gSavedSettings.getBOOL("RenderHUDInSnapshot"),
                FALSE,
                previewp->mSnapshotBufferType,
                previewp->getMaxImageSize()))
        {
            // Invalidate/delete any existing encoded image
            previewp->mPreviewImageEncoded = NULL;
            // Invalidate/delete any existing formatted image
            previewp->mFormattedImage = NULL;
            // Update the data size
            previewp->estimateDataSize();

            // Full size preview is set: get the decoded image result and save it for animation
            if (gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview)
            {
                previewp->prepareFreezeFrame();
            }

            // The snapshot is updated now...
            previewp->mSnapshotUpToDate = TRUE;

            // We need to update the thumbnail though
            previewp->setThumbnailImageSize();
            previewp->generateThumbnailImage(TRUE) ;
        }
        previewp->getWindow()->decBusyCount();
        previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview); // only show fullscreen preview when in freeze frame mode
        previewp->mSnapshotActive = FALSE;
        LL_DEBUGS("Snapshot") << "done creating snapshot" << LL_ENDL;
    }

    if (!previewp->getThumbnailUpToDate())
	{
		previewp->generateThumbnailImage() ;
	}

    // Tell the floater container that the snapshot is updated now
    if (previewp->mViewContainer)
    {
        previewp->mViewContainer->notify(LLSD().with("snapshot-updated", true));
    }

	return TRUE;
}

void LLSnapshotLivePreview::prepareFreezeFrame()
{
    // Get the decoded version of the formatted image
    getEncodedImage();

    // We need to scale that a bit for display...
    LLPointer<LLImageRaw> scaled = new LLImageRaw(
        mPreviewImageEncoded->getData(),
        mPreviewImageEncoded->getWidth(),
        mPreviewImageEncoded->getHeight(),
        mPreviewImageEncoded->getComponents());

    if (!scaled->isBufferInvalid())
    {
        // leave original image dimensions, just scale up texture buffer
        if (mPreviewImageEncoded->getWidth() > 1024 || mPreviewImageEncoded->getHeight() > 1024)
        {
            // go ahead and shrink image to appropriate power of 2 for display
            scaled->biasedScaleToPowerOfTwo(1024);
            setImageScaled(TRUE);
        }
        else
        {
            // expand image but keep original image data intact
            scaled->expandToPowerOfTwo(1024, FALSE);
        }

        mViewerImage[mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
        LLPointer<LLViewerTexture> curr_preview_image = mViewerImage[mCurImageIndex];
        gGL.getTexUnit(0)->bind(curr_preview_image);
        curr_preview_image->setFilteringOption(getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
        curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);

        if (gSavedSettings.getBOOL("UseFreezeFrame") && mAllowFullScreenPreview)
        {
            mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
        }
    }
}

S32 LLSnapshotLivePreview::getEncodedImageWidth() const
{
    S32 width = getWidth();
    if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
    {
        width = LLImageRaw::biasedDimToPowerOfTwo(width,MAX_TEXTURE_SIZE);
    }
    return width;
}
S32 LLSnapshotLivePreview::getEncodedImageHeight() const
{
    S32 height = getHeight();
    if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
    {
        height = LLImageRaw::biasedDimToPowerOfTwo(height,MAX_TEXTURE_SIZE);
    }
    return height;
}

LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()
{
	if (!mPreviewImageEncoded)
	{
		mPreviewImageEncoded = new LLImageRaw;

		mPreviewImageEncoded->resize(
            mPreviewImage->getWidth(),
            mPreviewImage->getHeight(),
            mPreviewImage->getComponents());

        if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
		{
            // We don't store the intermediate formatted image in mFormattedImage in the J2C case
			LL_DEBUGS("Snapshot") << "Encoding new image of format J2C" << LL_ENDL;
			LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
            // Copy the preview
			LLPointer<LLImageRaw> scaled = new LLImageRaw(
                                                          mPreviewImage->getData(),
                                                          mPreviewImage->getWidth(),
                                                          mPreviewImage->getHeight(),
                                                          mPreviewImage->getComponents());
            // Scale it as required by J2C
			scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
			setImageScaled(TRUE);
            // Compress to J2C
			if (formatted->encode(scaled, 0.f))
			{
                // We can update the data size precisely at that point
				mDataSize = formatted->getDataSize();
                // Decompress back
				formatted->decode(mPreviewImageEncoded, 0);
			}
		}
		else
		{
            // Update mFormattedImage if necessary
            getFormattedImage();
            if (getSnapshotFormat() == LLSnapshotModel::SNAPSHOT_FORMAT_BMP)
            {
                // BMP hack : copy instead of decode otherwise decode will crash.
                mPreviewImageEncoded->copy(mPreviewImage);
            }
            else
            {
                // Decode back
                mFormattedImage->decode(mPreviewImageEncoded, 0);
            }
		}
	}
    return mPreviewImageEncoded;
}

// We actually estimate the data size so that we do not require actual compression when showing the preview
// Note : whenever formatted image is computed, mDataSize will be updated to reflect the true size
void LLSnapshotLivePreview::estimateDataSize()
{
    // Compression ratio
    F32 ratio = 1.0;

    if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
    {
        ratio = 8.0;    // This is what we shoot for when compressing to J2C
    }
    else
    {
        LLSnapshotModel::ESnapshotFormat format = getSnapshotFormat();
        switch (format)
        {
            case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:
                ratio = 3.0;    // Average observed PNG compression ratio
                break;
            case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:
                // Observed from JPG compression tests
                ratio = (110 - mSnapshotQuality) / 2;
                break;
            case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:
                ratio = 1.0;    // No compression with BMP
                break;
        }
    }
    mDataSize = (S32)((F32)mPreviewImage->getDataSize() / ratio);
}

LLPointer<LLImageFormatted>	LLSnapshotLivePreview::getFormattedImage()
{
    if (!mFormattedImage)
    {
        // Apply the filter to mPreviewImage
        if (getFilter() != "")
        {
            std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
            if (filter_path != "")
            {
                LLImageFilter filter(filter_path);
                filter.executeFilter(mPreviewImage);
            }
            else
            {
                LL_WARNS("Snapshot") << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL;
            }
        }

        // Create the new formatted image of the appropriate format.
        LLSnapshotModel::ESnapshotFormat format = getSnapshotFormat();
        LL_DEBUGS("Snapshot") << "Encoding new image of format " << format << LL_ENDL;

        switch (format)
        {
		    case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:
                mFormattedImage = new LLImagePNG();
                break;
			case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:
                mFormattedImage = new LLImageJPEG(mSnapshotQuality);
                break;
			case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:
                mFormattedImage = new LLImageBMP();
                break;
        }
        if (mFormattedImage->encode(mPreviewImage, 0))
        {
            // We can update the data size precisely at that point
            mDataSize = mFormattedImage->getDataSize();
        }
    }
    return mFormattedImage;
}

void LLSnapshotLivePreview::setSize(S32 w, S32 h)
{
    LL_DEBUGS("Snapshot") << "setSize(" << w << ", " << h << ")" << LL_ENDL;
	setWidth(w);
	setHeight(h);
}

void LLSnapshotLivePreview::setSnapshotFormat(LLSnapshotModel::ESnapshotFormat format)
{
    if (mSnapshotFormat != format)
    {
        mFormattedImage = NULL;     // Invalidate the already formatted image if any
        mSnapshotFormat = format;
    }
}

void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
{
	w = getWidth();
	h = getHeight();
}

void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)
{
	LL_DEBUGS("Snapshot") << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << LL_ENDL;
	// gen a new uuid for this asset
	LLTransactionID tid;
	tid.generate();
	LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());

	LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
	LLPointer<LLImageRaw> scaled = new LLImageRaw(mPreviewImage->getData(),
		mPreviewImage->getWidth(),
		mPreviewImage->getHeight(),
		mPreviewImage->getComponents());

	// Apply the filter to mPreviewImage
	if (getFilter() != "")
	{
		std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
		if (filter_path != "")
		{
			LLImageFilter filter(filter_path);
			filter.executeFilter(scaled);
		}
		else
		{
			LL_WARNS("Snapshot") << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL;
		}
	}

	scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
	LL_DEBUGS("Snapshot") << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << LL_ENDL;

	if (formatted->encode(scaled, 0.0f))
	{
		LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE);
		std::string pos_string;
		LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
		std::string who_took_it;
		LLAgentUI::buildFullname(who_took_it);
		S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
        std::string res_name = outfit_snapshot ? name : "Snapshot : " + pos_string;
        std::string res_desc = outfit_snapshot ? "" : "Taken by " + who_took_it + " at " + pos_string;
        LLFolderType::EType folder_type = outfit_snapshot ? LLFolderType::FT_NONE : LLFolderType::FT_SNAPSHOT_CATEGORY;
        LLInventoryType::EType inv_type = outfit_snapshot ? LLInventoryType::IT_NONE : LLInventoryType::IT_SNAPSHOT;

        LLResourceUploadInfo::ptr_t assetUploadInfo(new LLResourceUploadInfo(
            tid, LLAssetType::AT_TEXTURE, res_name, res_desc, 0,
            folder_type, inv_type,
            PERM_ALL, LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
            expected_upload_cost, !outfit_snapshot));

        upload_new_resource(assetUploadInfo);

		gViewerWindow->playSnapshotAnimAndSound();
	}
	else
	{
		LLNotificationsUtil::add("ErrorEncodingSnapshot");
		LL_WARNS("Snapshot") << "Error encoding snapshot" << LL_ENDL;
	}

	add(LLStatViewer::SNAPSHOT, 1);

	mDataSize = 0;
}

void LLSnapshotLivePreview::saveLocal(const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb)
{
    // Update mFormattedImage if necessary
    getFormattedImage();

    // Save the formatted image
	saveLocal(mFormattedImage, success_cb, failure_cb);
}

//Check if failed due to insufficient memory
void LLSnapshotLivePreview::saveLocal(LLPointer<LLImageFormatted> image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb)
{
	sSaveLocalImage = image;

	gViewerWindow->saveImageNumbered(sSaveLocalImage, FALSE, success_cb, failure_cb);
}

ext: cpp

max_stars_repo_name: SaladDais/LLUDP-Encryption

max_issues_repo_name: SaladDais/LLUDP-Encryption

max_forks_repo_name: SaladDais/LLUDP-Encryption


text:
/*
 *  Copyright (c), 2020, EPFL - Blue Brain Project
 *
 *  Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 *
 */
#pragma once

#include <Eigen/Eigen>

namespace HighFive {

namespace details {

//compute size for single Eigen Matrix
template <typename T, int M, int N>
inline size_t compute_total_size(const Eigen::Matrix<T,M,N>& matrix) {
    return matrix.rows() * matrix.cols();
}

//compute size for  std::vector of Eigens
template <typename T, int M, int N>
inline size_t compute_total_size(const std::vector<Eigen::Matrix<T,M,N>>& vec) {
    return std::accumulate(vec.begin(), vec.end(), size_t{0u},
        [](size_t so_far, const Eigen::Matrix<T,M,N>& v) {
            return so_far + static_cast<size_t>(v.rows()) * static_cast<size_t>(v.cols());
        });
}

#ifdef H5_USE_BOOST
// compute size for  boost::multi_array of Eigens
template <typename T, size_t Dims>
inline size_t compute_total_size(const boost::multi_array<T, Dims>& vec) {
    return std::accumulate(vec.origin(), vec.origin() + vec.num_elements(), size_t{0u},
        [](size_t so_far, const T& v) {
            return so_far + static_cast<size_t>(v.rows()) * static_cast<size_t>(v.cols());
        });
}
#endif

//compute total row size for std::vector of Eigens
template <typename T, int M, int N>
inline size_t compute_total_row_size(const std::vector<Eigen::Matrix<T,M,N>>& vec) {
    return std::accumulate(vec.begin(), vec.end(), size_t{0u},
        [](size_t so_far, const Eigen::Matrix<T,M,N>& v) {
            return so_far + static_cast<size_t>(v.rows());
        });
}

// apply conversion to eigen matrix
template <typename T, int M, int N>
struct data_converter<Eigen::Matrix<T, M, N>, void> {

    typedef Eigen::Matrix<T, M, N> MatrixTMN;

    inline data_converter(const DataSpace& space)
        : _dims(space.getDimensions()) {
        assert(_dims.size() == 2);
    }

    inline T* transform_read(MatrixTMN& array) {
        if (_dims[0] != static_cast<size_t>(array.rows()) ||
            _dims[1] != static_cast<size_t>(array.cols())) {
            array.resize(static_cast<typename MatrixTMN::Index>(_dims[0]),
                         static_cast<typename MatrixTMN::Index>(_dims[1]));
        }
        return array.data();
    }

    inline const T* transform_write(const MatrixTMN& array) {
        return array.data();
    }

    inline void process_result(MatrixTMN&) {}

    std::vector<size_t> _dims;
};

template <typename T, int M, int N>
inline void vectors_to_single_buffer(const std::vector<Eigen::Matrix<T,M,N>>& vec,
                                     const std::vector<size_t>& dims,
                                     const size_t current_dim,
                                     std::vector<T>& buffer) {

    check_dimensions_vector(compute_total_row_size(vec), dims[current_dim], current_dim);
    for (const auto& k : vec) {
        std::copy(k.data(), k.data() + k.size(), std::back_inserter(buffer));
    }
}

// apply conversion to std::vector of eigen matrix
template <typename T, int M, int N>
struct data_converter<std::vector<Eigen::Matrix<T,M,N>>, void> {

    typedef Eigen::Matrix<T, M, N> MatrixTMN;

    inline data_converter(const DataSpace& space)
        : _dims(space.getDimensions()), _space(space) {
        assert(_dims.size() == 2);
    }

    inline T * transform_read(std::vector<MatrixTMN>& /* vec */) {
        _vec_align.resize(compute_total_size(_space.getDimensions()));
        return _vec_align.data();
    }

    inline const T* transform_write(const std::vector<MatrixTMN>& vec) {
        _vec_align.reserve(compute_total_size(vec));
        vectors_to_single_buffer<T, M, N>(vec, _dims, 0, _vec_align);
        return _vec_align.data();
    }

    inline void process_result(std::vector<MatrixTMN>& vec) {
        T* start = _vec_align.data();
        if (vec.size() > 0) {
            for(auto& v : vec){
                v = Eigen::Map<MatrixTMN>(start, v.rows(), v.cols());
                start += v.rows()*v.cols();
            }
        }
        else if (M == -1 || N == -1) {
            std::ostringstream ss;
            ss << "Dynamic size(-1) used without pre-defined vector data layout.\n"
               << "Initiliaze vector elements using Zero, i.e.:\n"
               << "\t vector<MatrixXd> vec(5, MatrixXd::Zero(20,5))";
            throw DataSetException(ss.str());
        }
        else {
            for (size_t i = 0; i < _dims[0] / static_cast<size_t>(M); ++i) {
                vec.emplace_back(Eigen::Map<MatrixTMN>(start, M, N));
                start += M * N;
            }
        }
    }

    std::vector<size_t> _dims;
    std::vector<typename type_of_array<T>::type> _vec_align;
    const DataSpace& _space;
};

#ifdef H5_USE_BOOST
template <typename T, int M, int N, std::size_t Dims>
struct data_converter<boost::multi_array<Eigen::Matrix<T, M, N>, Dims>, void> {
    typedef typename boost::multi_array<Eigen::Matrix<T, M, N>, Dims> MultiArrayEigen;

    inline data_converter(const DataSpace& space)
        : _dims(space.getDimensions())
        , _space(space) {
        assert(_dims.size() == Dims);
    }

    inline T* transform_read(const MultiArrayEigen& /*array*/) {
        _vec_align.resize(compute_total_size(_space.getDimensions()));
        return _vec_align.data();
    }

    inline const T* transform_write(const MultiArrayEigen& array) {
        _vec_align.reserve(compute_total_size(array));
        for (auto e = array.origin(); e < array.origin() + array.num_elements(); ++e) {
            std::copy(e->data(), e->data() + e->size(), std::back_inserter(_vec_align));
        }
        return _vec_align.data();
    }

    inline void process_result(MultiArrayEigen& vec) {
        T* start = _vec_align.data();
        if (M != -1 && N != -1) {
            for (auto v = vec.origin(); v < vec.origin() + vec.num_elements(); ++v) {
                *v = Eigen::Map<Eigen::Matrix<T, M, N>>(start, v->rows(), v->cols());
                start += v->rows() * v->cols();
            }
        } else {
            if (vec.origin()->rows() > 0 && vec.origin()->cols() > 0) {
                const auto VEC_M = vec.origin()->rows(), VEC_N = vec.origin()->cols();
                for (auto v = vec.origin(); v < vec.origin() + vec.num_elements(); ++v) {
                    assert(v->rows() == VEC_M && v->cols() == VEC_N);
                    *v = Eigen::Map<Eigen::Matrix<T, M, N>>(start, VEC_M, VEC_N);
                    start += VEC_M * VEC_N;
                }
            } else {
                throw DataSetException(
                    "Dynamic size(-1) used without pre-defined multi_array data layout.\n"
                    "Initialize vector elements using  MatrixXd::Zero");
            }
        }
    }

    std::vector<size_t> _dims;
    const DataSpace& _space;
    std::vector<typename type_of_array<T>::type> _vec_align;
};
#endif  // H5_USE_BOOST

}  // namespace details

}  // namespace HighFive

ext: hpp

max_stars_repo_name: xelliott/HighFive

max_issues_repo_name: xelliott/HighFive

max_forks_repo_name: xelliott/HighFive


text:
//!
//! Contains the functions to seralise and unserialise GDF datatypes.
//!
//! \file comms/messages.hpp
//! \author Lachlan McCalman
//! \date 2014
//! \license Affero General Public License version 3 or later
//! \copyright (c) 2014, NICTA
//!

#pragma once

// Standard Library
#include <string>
#include <vector>
//Prerequisites
#include <boost/range/adaptor/reversed.hpp>
// Project
#include "datatypes.hpp"

namespace stateline
{
  namespace comms
  {
    //! Defines the bytes actually sent in the subject frame of GDF messages.
    //! Allows us to use a switch statement on the subject.
    //!
    enum Subject : uint
    {
      HELLO = 0,
      HEARTBEAT = 1,
      PROBLEMSPEC = 2,
      JOBREQUEST = 3,
      JOB = 4,
      JOBSWAP = 5,
      ALLDONE = 6,
      GOODBYE = 7
    };

    //! Identifies a particular message code, defined as a Subject enum.
    //!
    //! \param s The subject enum being queried (a uint really).
    //! \return The name of the corresponding message.
    //!
    std::string subjectString(Subject s);

    //! Define valid messages to send on the GDFP-SW (GDF Server-Worker Protocol)
    //!
    class Message
    {
    public:

      //! Constructor to build a message.
      //!
      //! \param addr The address to send the message to.
      //! \param subj The subject of the message (eg. HELLO, JOB etc).
      //! \param d A vector of data to send in the message. Each element of
      //!          the vector is sent as a separate frame.
      //!
      Message(const std::vector<std::string>& addr, const Subject& subj,
          const std::vector<std::string>& d);

      //! Create a new message with no address.
      //!
      //! \param subj The subject of the message (eg. HELLO, JOB etc).
      //! \param d A vector of data to send in the message. Each element of
      //!          the vector is sent as a separate frame.
      //!
      //!
      Message(const Subject& subj, const std::vector<std::string>& d);

      //! Create a new message with no data.
      //!
      //! \param addr The address to send the message to.
      //! \param subj The subject of the message (eg. HELLO, JOB etc).
      //!
      Message(const std::vector<std::string>& addr, const Subject& subj);

      //! Constructor to build a message with no data or address.
      //!
      //! \param subj The subject of the message (eg. HELLO, JOB etc).
      //!
      Message(const Subject& subj);

      //! Equality comparator for testing purposes.
      //!
      //! \param m The message to compare with.
      //! \return True if the message is equal to this message.
      //!
      bool operator==(const Message& m) const;

      //! Allows a message to be printed with std::cout.
      //!
      //! \param os the output stream.
      //! \param m the message object.
      //!
      friend std::ostream& operator<<(std::ostream& os, const Message& m);

      //! The destination address of this message.
      std::vector<std::string> address;

      //! The subject of the message (e.g. HELLO).
      Subject subject;

      //! The data that this message contains.
      std::vector<std::string> data;
    };

    //! Print a message for logging and debugging purposes.
    //!
    //! \param os The output stream.
    //! \param m The message to print.
    //!
    std::ostream& operator<<(std::ostream& os, const Message& m);

    //! Convert an address to a string.
    //!
    //! \param addr The address to convert.
    //! \return The address as a single string.
    //!
    std::string addressAsString(const std::vector<std::string>& addr);

    //! Print a message for logging and debugging purposes.
    //!
    //! \param m The message to print.
    //!
    void print(const Message& m);

  } // namespace comms
} // namespace obsidian


text:
#ifndef DAQI_SERVER_HPP
#define DAQI_SERVER_HPP

#include <atomic>
#include <list>
#include <string>
#include <functional>

#include <boost/asio/deadline_timer.hpp>

#include "daqi/def/asio_def.hpp"

#include "daqi/server_engine.hpp"
#include "daqi/application.hpp"
#include "daqi/handler.hpp"

namespace da4qi4
{

extern int const _detect_templates_interval_seconds_;

class Server
{
public:
    enum class WithSSL {no, yes};

    using OnNeedSSLPassword = std::function <std::string(std::size_t max_length
                                                         , SSLContextBase::password_purpose purpose)>;
    struct SSLOptions
    {
        enum class PrivateKeyType  {normal, RSA};

        explicit SSLOptions()
            : options(boost::asio::ssl::context::default_workarounds
                      | boost::asio::ssl::context::no_sslv2
                      | boost::asio::ssl::context::no_sslv3
                      | boost::asio::ssl::context::no_tlsv1)
            , private_key_type(PrivateKeyType::normal), private_key_file_format(SSLContextBase::pem)
            , will_verify_client(false), on_need_password(nullptr)
        {
        }

        explicit SSLOptions(OnNeedSSLPassword&& password_callback)
            : options(boost::asio::ssl::context::default_workarounds
                      | boost::asio::ssl::context::no_sslv2
                      | boost::asio::ssl::context::no_sslv3
                      | boost::asio::ssl::context::no_tlsv1)
            , private_key_type(PrivateKeyType::normal), private_key_file_format(SSLContextBase::pem)
            , will_verify_client(false)
            , on_need_password(std::forward<OnNeedSSLPassword>(password_callback))
        {
        }

        SSLOptions(SSLContextBase::options options)
            : options(options)
            , private_key_file_format(SSLContextBase::pem)
        {
        }

        SSLOptions(SSLContextBase::options options, OnNeedSSLPassword&& password_callback)
            : options(options)
            , private_key_type(PrivateKeyType::normal)
            , private_key_file_format(SSLContextBase::pem)
            , on_need_password(std::forward<OnNeedSSLPassword>(password_callback))
        {
        }

        void EnableSSLV3()
        {
            options &= ~boost::asio::ssl::context::no_sslv3;
        }

        void EnableTLSV1()
        {
            options &= ~boost::asio::ssl::context::no_tlsv1;
        }

        void EnableVerifyClient()
        {
            will_verify_client = true;
        }

        void DisableVerifyClient()
        {
            will_verify_client = false;
        }

        void InitFiles(std::string certificate_chain_file
                       , std::string private_key_file
                       , PrivateKeyType private_key_type = PrivateKeyType::normal
                       , std::string tmp_DiffieHellman_file = ""
                       , SSLContextBase::file_format private_key_file_format = SSLContextBase::pem)
        {
            this->certificate_chain_file = std::move(certificate_chain_file);   //.pem

            this->private_key_file = std::move(private_key_file);               //.key
            this->private_key_type = private_key_type;                          //is RSA private key?
            this->private_key_file_format = private_key_file_format;

            if (!tmp_DiffieHellman_file.empty())
            {
                this->tmp_DiffieHellman_file = std::move(tmp_DiffieHellman_file);
                options |= SSLContextBase::single_dh_use;
            }
        }

        SSLContextBase::options options;

        std::string certificate_chain_file;

        std::string private_key_file;
        PrivateKeyType private_key_type;
        SSLContextBase::file_format private_key_file_format;

        std::string tmp_DiffieHellman_file;

        bool will_verify_client;

        OnNeedSSLPassword on_need_password;
    };

private:
    Server(Tcp::endpoint endpoint, size_t thread_count, SSLOptions const* ssl_opts = nullptr);

public:
    using IdleFunction = std::function<void (void)>;

    using Ptr = std::unique_ptr<Server>;

    static Ptr Supply(unsigned short port, size_t thread_count);
    static Ptr Supply(std::string const& host, unsigned short port, size_t thread_count);

    static Ptr Supply(std::string const& host, unsigned short port);
    static Ptr Supply(unsigned short port = 80);

    static Ptr SupplyWithSSL(SSLOptions const& ssl_opt, unsigned short port, size_t thread_count);
    static Ptr SupplyWithSSL(SSLOptions const& ssl_opt
                             , std::string const& host, unsigned short port, size_t thread_count);

    static Ptr SupplyWithSSL(SSLOptions const& ssl_opt, std::string const& host, unsigned short port);
    static Ptr SupplyWithSSL(SSLOptions const& ssl_opt, unsigned short port = 443);

    ~Server();

    IOContextPool* GetIOContextPool()
    {
        return &_ioc_pool;
    }

public:
    bool IsWithSSL() const
    {
        return _withssl == WithSSL::yes;
    }
public:
    void Run();
    void Stop();

public:
    void PauseIdleTimer();
    void ResumeIdleTimer();

    bool IsIdleTimerRunning() const
    {
        return _idle_running;
    }

    void EnableDetectTemplates(int interval_seconds = _detect_templates_interval_seconds_)
    {
        assert(interval_seconds > 0);

        _detect_templates_status.interval_seconds = interval_seconds;
        _detect_templates_status.next_timepoint = std::time(nullptr) + interval_seconds;

        _detect_templates = true;

        if (_running && !_idle_running)
        {
            ResumeIdleTimer();
        }
    }

    void DisableDetectTemplates()
    {
        _detect_templates = false;
    }

    bool IsEnabledDetetTemplates() const
    {
        return _detect_templates;
    }

    void AppendIdleFunction(int interval_seconds, IdleFunction func);

public:
    ApplicationPtr DefaultApp(std::string const& name = "");

    bool Mount(ApplicationPtr app);

public:
    ApplicationPtr AddHandler(HandlerMethod m, std::string const& url, Handler h)
    {
        return AddHandler(m, router_equals(url), h);
    }

    ApplicationPtr AddHandler(HandlerMethod m, router_equals r, Handler h);
    ApplicationPtr AddHandler(HandlerMethod m, router_starts r, Handler h);
    ApplicationPtr AddHandler(HandlerMethod m, router_regex r, Handler h);

    ApplicationPtr AddHandler(HandlerMethods ms, std::string const& url, Handler h)
    {
        return AddHandler(ms, router_equals(url), h);
    }
    ApplicationPtr AddHandler(HandlerMethods ms, router_equals r, Handler h);
    ApplicationPtr AddHandler(HandlerMethods ms, router_starts r, Handler h);
    ApplicationPtr AddHandler(HandlerMethods ms, router_regex r, Handler h);

    bool AddEqualsRouter(HandlerMethod m, std::vector<std::string> const& urls, Handler h);
    bool AddStartsRouter(HandlerMethod m, std::vector<std::string> const& urls, Handler h);
    bool AddRegexRouter(HandlerMethod m, std::vector<std::string> const& urls, Handler h);

public:
    ApplicationPtr PrepareApp(std::string const& url);

private:
    void start_accept();
    void do_accept();
    void do_stop();

private:
    void make_default_app_if_empty();
    void make_default_app(std::string const& name);

    void start_idle_timer();
    void on_idle_timer(errorcode const& ec);
    void stop_idle_timer();

private:
    WithSSL _withssl;
    int _idle_interval_seconds;

private:
    std::atomic_bool _running;
    std::atomic_bool _stopping;

    IOContextPool _ioc_pool;
    Tcp::acceptor _acceptor;
    boost::asio::signal_set _signals;
    std::unique_ptr<boost::asio::ssl::context> _ssl_ctx;

    std::atomic_bool _idle_running;

    std::atomic_bool _detect_templates;
    boost::asio::deadline_timer _idle_timer;

    struct IdleFunctionStatus
    {
        IdleFunctionStatus()
            : interval_seconds(0), next_timepoint(static_cast<std::time_t>(0))
        {}

        IdleFunctionStatus(IdleFunctionStatus const&) = default;

        IdleFunctionStatus(int interval_seconds, IdleFunction func)
            : interval_seconds(interval_seconds),
              next_timepoint(std::time(nullptr) + interval_seconds), func(func)
        {}

        int interval_seconds;
        std::time_t next_timepoint;
        IdleFunction func;
    };

    IdleFunctionStatus _detect_templates_status;
    std::list<IdleFunctionStatus> _idle_functions;

private:
    static int call_idle_function_if_timeout(std::time_t now, IdleFunctionStatus& status);
};

}

#endif // DAQI_SERVER_HPP


text:
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE "test_mad"

#include <boost/test/unit_test.hpp>
#include "nanocv/tensor.h"
#include "nanocv/math/mad.hpp"
#include "nanocv/math/abs.hpp"
#include "nanocv/math/epsilon.hpp"
#include "nanocv/tensor/mad.hpp"

namespace test
{
        using namespace ncv;

        template
        <
                typename top,
                typename tvector,
                typename tscalar = typename tvector::Scalar
        >
        tscalar test_mad(top op, const tvector& vec1, const tvector& vec2, tscalar wei)
        {
                vector_t cvec1 = vec1;
                vector_t cvec2 = vec2;

                op(cvec1.data(), wei, cvec1.size(), cvec2.data());

                return cvec2.sum();
        }

        void test_mad(size_t size)
        {
                vector_t vec1(size), vec2(size);
                vec1.setRandom();
                vec2.setRandom();

                scalar_t wei = vec1(0) + vec2(3);

                const scalar_t mad    = test_mad(ncv::math::mad<scalar_t>, vec1, vec2, wei);
                const scalar_t madul2 = test_mad(ncv::math::mad_unroll<scalar_t, 2>, vec1, vec2, wei);
                const scalar_t madul3 = test_mad(ncv::math::mad_unroll<scalar_t, 3>, vec1, vec2, wei);
                const scalar_t madul4 = test_mad(ncv::math::mad_unroll<scalar_t, 4>, vec1, vec2, wei);
                const scalar_t madul5 = test_mad(ncv::math::mad_unroll<scalar_t, 5>, vec1, vec2, wei);
                const scalar_t madul6 = test_mad(ncv::math::mad_unroll<scalar_t, 6>, vec1, vec2, wei);
                const scalar_t madul7 = test_mad(ncv::math::mad_unroll<scalar_t, 7>, vec1, vec2, wei);
                const scalar_t madul8 = test_mad(ncv::math::mad_unroll<scalar_t, 8>, vec1, vec2, wei);
                const scalar_t madeig = test_mad(ncv::tensor::mad<scalar_t>, vec1, vec2, wei);

                const scalar_t epsilon = math::epsilon1<scalar_t>();

                BOOST_CHECK_LE(math::abs(mad - mad), epsilon);
                BOOST_CHECK_LE(math::abs(mad - madul2), epsilon);
                BOOST_CHECK_LE(math::abs(mad - madul3), epsilon);
                BOOST_CHECK_LE(math::abs(mad - madul4), epsilon);
                BOOST_CHECK_LE(math::abs(mad - madul5), epsilon);
                BOOST_CHECK_LE(math::abs(mad - madul6), epsilon);
                BOOST_CHECK_LE(math::abs(mad - madul7), epsilon);
                BOOST_CHECK_LE(math::abs(mad - madul8), epsilon);
                BOOST_CHECK_LE(math::abs(mad - madeig), epsilon);
        }
}

BOOST_AUTO_TEST_CASE(test_mad)
{
        using namespace ncv;

        static const size_t min_size = 32 * 1024;
        static const size_t max_size = 4 * 1024 * 1024;

        for (size_t size = min_size; size <= max_size; size *= 2)
        {
                test::test_mad(size);
        }
}


text:
#include <beast.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <thread>
#include <functional>
#include <unordered_map>
#include <set>
#include <string>
#include <fstream>
#include <shared_mutex>
#include <nlohmann/json.hpp>
#include <server_helper.hpp>

namespace http = beast::http;
namespace net = boost::asio;
using tcp = boost::asio::ip::tcp;
using nlohmann::json;

std::shared_mutex mutex_;
std::unordered_map<std::string, std::set<result>> suggestions;  // id -> set of results

template<class Body, class Allocator, class Send>
void handle_request(http::request<Body, http::basic_fields<Allocator>>&& req,
    Send&& send) {

  // Returns a bad request response
  auto const bad_request = [&req](beast::string_view why) {
    http::response<http::string_body> res{http::status::bad_request,
                                          req.version};
    res.set(http::field::server, BEAST_VERSION_STRING);
    res.set(http::field::content_type, "text/html");
    res.keep_alive(false);
    res.body = std::string(why);
    res.prepare_payload();
    return res;
  };

  // Make sure we can handle the method
  if (req.method() != http::verb::post)
    return send(bad_request("Unknown HTTP-method"));

  // Request path must be absolute and not contain "..".
  if (req.target().empty() || req.target()[0] != '/' ||
      req.target().find("..") != beast::string_view::npos) {
    return send(bad_request("Illegal request-target"));
  }

  if (req.target() != "/v1/api/suggest"){
    return send(bad_request("Not Found"));
  }
  json result_data;
  {
    std::shared_lock lock(mutex_);
    json input = json::parse(req.body);
    std::string id;
    input.at("input").get_to(id);
    auto res = suggestions[id];
    json json_suggests = json::array();
    auto count = 0;
    for (auto r : res){
      json o;
      if (r.position == -1){
        r.position = count;
      }
      o = r;
      json_suggests.push_back(o);
      count++;
    }
    result_data["suggestions"] = json_suggests;
  }

  // Respond to POST request
  http::response<http::string_body> res{http::status::ok, req.version};
  res.set(http::field::server, BEAST_VERSION_STRING);
  res.set(http::field::content_type, "application/json");
  res.body = result_data.dump();
  res.keep_alive(false);
  return send(std::move(res));
}

// This is the C++11 equivalent of a generic lambda.
// The function object is used to send an HTTP message.

void fail(beast::error_code ec, char const* what)
{
  std::cerr << what << ": " << ec.message() << "\n";
}

void do_session(tcp::socket& socket)
{
  bool close = false;
  beast::error_code ec;

  // This buffer is required to persist across reads
  beast::flat_buffer buffer;

  // This lambda is used to send messages
  send_lambda<tcp::socket> lambda{socket, close, ec};

    // Read a request
  http::request<http::string_body> req;
  http::read(socket, buffer, req, ec);

  if(ec == http::error::end_of_stream) {
    socket.shutdown(tcp::socket::shutdown_send, ec);
  }
  if(ec) {
    return fail(ec, "read");
  }

    // Send the response
  handle_request(std::move(req), lambda);

  // Send a TCP shutdown
  socket.shutdown(tcp::socket::shutdown_send, ec);

  // At this point the connection is closed gracefully
}

void update_suggestions(const std::string path){
      for(;;){
        {
          std::unique_lock lock(mutex_);
          std::ifstream file(path);
          json data;
          file >> data;
          std::unordered_map<std::string, std::set<result>> new_suggestions;
          for (const auto& s :data){
              auto sug = s.get<suggest>();
              new_suggestions[sug.id].insert(result{sug.name, sug.cost});
          }
          suggestions = std::move(new_suggestions);
        }
        std::this_thread::sleep_for(std::chrono::minutes(15));
      }
}

int main(int argc, char* argv[])
{
  try
  {
    // Check command line arguments.
    if (argc != 4)
    {
      throw std::runtime_error("Incorrect number of args");
    }
    auto const address = net::ip::address::from_string(argv[1]);
    auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
    auto const doc_root = std::string(argv[3]); // path to suggestions.json
    std::string path_to_data;
    if (doc_root == "/") {
      path_to_data = "suggestions.json";
    } else{
      path_to_data = doc_root + "suggestions.json";
    }
    std::ifstream f(path_to_data);

    if (!f.good()){
      throw std::runtime_error("Incorrect directory with json data file");
    }

    std::thread(&update_suggestions, path_to_data).detach();

    // The io_context is required for all I/O
    net::io_service ioc{1};

    // The acceptor receives incoming connections
    tcp::acceptor acceptor{ioc, {address, port}};
    for(;;)
    {
      // This will receive the new connection
      tcp::socket socket{ioc};

      // Block until we get a connection
      acceptor.accept(socket);

      // Launch the session, transferring ownership of the socket
      std::thread{std::bind(&do_session,
          std::move(socket))}.detach();
    }
  }
  catch (const std::exception& e)
  {
    std::cerr << "Error: " << e.what() << std::endl;
    throw e;
  }
}


text: #include <boost/iterator/transform_iterator.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
// Copyright Stephan T. Lavavej, http://nuwen.net .
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://boost.org/LICENSE_1_0.txt .

#ifndef PHAM_SERIAL_HH
#define PHAM_SERIAL_HH

#include "compiler.hh"

#ifdef NUWEN_PLATFORM_MSVC
    #pragma once
#endif

#include "gluon.hh"
#include "typedef.hh"
#include "vector.hh"

#include "external_begin.hh"
    #include <deque>
    #include <list>
    #include <map>
    #include <set>
    #include <stdexcept>
    #include <string>
    #include <utility>
    #include <vector>
    #include <boost/type_traits/remove_const.hpp>
    #include <boost/utility.hpp>
#include "external_end.hh"

namespace nuwen {
    namespace ser {
        class serial : public boost::noncopyable {
        public:
            inline serial();

            template <typename T> explicit serial(const T& t);

            inline vuc_t vuc() const;

            template <typename T> serial& operator<<(const T& t);

            inline serial& operator<<(bool b);
            inline serial& operator<<(uc_t n);
            inline serial& operator<<(sc_t n);
            inline serial& operator<<(us_t n);
            inline serial& operator<<(ss_t n);
            inline serial& operator<<(ul_t n);
            inline serial& operator<<(sl_t n);
            inline serial& operator<<(ull_t n);
            inline serial& operator<<(sll_t n);
            inline serial& operator<<(const std::string& s);

            template <typename T> serial& operator<<(const std::vector<T>& v);
            template <typename T> serial& operator<<(const std::deque<T>& d);
            template <typename T> serial& operator<<(const std::list<T>& l);

            template <typename A, typename B> serial& operator<<(const std::pair<A, B>& p);
            template <typename T, typename L> serial& operator<<(const std::set<T, L>& s);
            template <typename T, typename L> serial& operator<<(const std::multiset<T, L>& ms);

            template <typename K, typename V, typename L> serial& operator<<(const std::map<K, V, L>& m);
            template <typename K, typename V, typename L> serial& operator<<(const std::multimap<K, V, L>& mm);

        private:
            template <typename C> serial& serialize_container(const C& c);

            vuc_t m_v;
        };
    }

    namespace des {
        class deserial : public boost::noncopyable {
        public:
            inline explicit deserial(const vuc_t& v);

            template <typename T> T get();

            inline vuc_ci_t curr() const;
            inline vuc_ci_t end() const;

            inline ull_t size() const;
            inline void consume(ull_t n);

        private:
            vuc_ci_t m_curr;
            vuc_ci_t m_end;
        };
    }
}

namespace pham {
    template <typename T> T deserialize_integer(nuwen::des::deserial& d) {
        if (d.size() < sizeof(T)) {
            throw std::runtime_error("RUNTIME ERROR: pham::deserialize_integer() - Not enough data.");
        }

        const T ret = t_from_vuc_unchecked<T>(d.curr());
        d.consume(sizeof(T));
        return ret;
    }

    template <typename S> S deserialize_sequence(nuwen::des::deserial& d) {
        S ret;

        const nuwen::ull_t n = d.get<nuwen::ull_t>();

        for (nuwen::ull_t i = 0; i < n; ++i) {
            ret.push_back(d.get<typename S::value_type>());
        }

        return ret;
    }

    template <typename U> U deserialize_uniq(nuwen::des::deserial& d) {
        U ret;

        const nuwen::ull_t n = d.get<nuwen::ull_t>();

        for (nuwen::ull_t i = 0; i < n; ++i) {
            if (!ret.insert(d.get<typename U::value_type>()).second) {
                throw std::runtime_error("RUNTIME ERROR: pham::deserialize_uniq() - Non-unique key encountered.");
            }
        }

        return ret;
    }

    template <typename E> E deserialize_eq(nuwen::des::deserial& d) {
        E ret;

        const nuwen::ull_t n = d.get<nuwen::ull_t>();

        for (nuwen::ull_t i = 0; i < n; ++i) {
            ret.insert(d.get<typename E::value_type>());
        }

        return ret;
    }

    template <typename T> struct des_helper {
        static T fxn(nuwen::des::deserial& d) { return T(d); }
    };

    template <typename T> struct des_helper<const T> {
        static const T fxn(nuwen::des::deserial& d) { return d.get<T>(); }
    };

    template <> struct des_helper<bool> {
        static bool fxn(nuwen::des::deserial& d) {
            const nuwen::uc_t n = d.get<nuwen::uc_t>();

            if (n > 1) {
                throw std::runtime_error("RUNTIME ERROR: pham::des_helper<bool>::fxn() - Invalid data.");
            }

            return n != 0;
        }
    };

    template <> struct des_helper<nuwen::uc_t> {
        static nuwen::uc_t fxn(nuwen::des::deserial& d) { return deserialize_integer<nuwen::uc_t>(d); }
    };

    template <> struct des_helper<nuwen::sc_t> {
        static nuwen::sc_t fxn(nuwen::des::deserial& d) { return nuwen::sc_from_uc(d.get<nuwen::uc_t>()); }
    };

    template <> struct des_helper<nuwen::us_t> {
        static nuwen::us_t fxn(nuwen::des::deserial& d) { return deserialize_integer<nuwen::us_t>(d); }
    };

    template <> struct des_helper<nuwen::ss_t> {
        static nuwen::ss_t fxn(nuwen::des::deserial& d) { return nuwen::ss_from_us(d.get<nuwen::us_t>()); }
    };

    template <> struct des_helper<nuwen::ul_t> {
        static nuwen::ul_t fxn(nuwen::des::deserial& d) { return deserialize_integer<nuwen::ul_t>(d); }
    };

    template <> struct des_helper<nuwen::sl_t> {
        static nuwen::sl_t fxn(nuwen::des::deserial& d) { return nuwen::sl_from_ul(d.get<nuwen::ul_t>()); }
    };

    template <> struct des_helper<nuwen::ull_t> {
        static nuwen::ull_t fxn(nuwen::des::deserial& d) { return deserialize_integer<nuwen::ull_t>(d); }
    };

    template <> struct des_helper<nuwen::sll_t> {
        static nuwen::sll_t fxn(nuwen::des::deserial& d) { return nuwen::sll_from_ull(d.get<nuwen::ull_t>()); }
    };

    template <> struct des_helper<std::string> {
        static std::string fxn(nuwen::des::deserial& d) { return nuwen::string_cast<std::string>(d.get<nuwen::vuc_t>()); }
    };

    template <typename T> struct des_helper<std::vector<T> > {
        static std::vector<T> fxn(nuwen::des::deserial& d) { return deserialize_sequence<std::vector<T> >(d); }
    };

    template <typename T> struct des_helper<std::deque<T> > {
        static std::deque<T> fxn(nuwen::des::deserial& d) { return deserialize_sequence<std::deque<T> >(d); }
    };

    template <typename T> struct des_helper<std::list<T> > {
        static std::list<T> fxn(nuwen::des::deserial& d) { return deserialize_sequence<std::list<T> >(d); }
    };

    template <typename A, typename B> struct des_helper<std::pair<A, B> > {
        static std::pair<A, B> fxn(nuwen::des::deserial& d) {
            const A a(d.get<typename boost::remove_const<A>::type>());
            const B b(d.get<typename boost::remove_const<B>::type>());

            return std::make_pair(a, b);
        }
    };

    template <typename T, typename L> struct des_helper<std::set<T, L> > {
        static std::set<T, L> fxn(nuwen::des::deserial& d) { return deserialize_uniq<std::set<T, L> >(d); }
    };

    template <typename T, typename L> struct des_helper<std::multiset<T, L> > {
        static std::multiset<T, L> fxn(nuwen::des::deserial& d) { return deserialize_eq<std::multiset<T, L> >(d); }
    };

    template <typename K, typename V, typename L> struct des_helper<std::map<K, V, L> > {
        static std::map<K, V, L> fxn(nuwen::des::deserial& d) { return deserialize_uniq<std::map<K, V, L> >(d); }
    };

    template <typename K, typename V, typename L> struct des_helper<std::multimap<K, V, L> > {
        static std::multimap<K, V, L> fxn(nuwen::des::deserial& d) { return deserialize_eq<std::multimap<K, V, L> >(d); }
    };
}

inline nuwen::ser::serial::serial() { }

template <typename T> nuwen::ser::serial::serial(const T& t) {
    *this << t;
}

inline nuwen::vuc_t nuwen::ser::serial::vuc() const {
    return m_v;
}

template <typename T> nuwen::ser::serial& nuwen::ser::serial::operator<<(const T& t) {
    return t.serialize(*this);
}

inline nuwen::ser::serial& nuwen::ser::serial::operator<<(const bool b) {
    return *this << static_cast<uc_t>(b);
}

inline nuwen::ser::serial& nuwen::ser::serial::operator<<(const uc_t n) {
    m_v.push_back(n);
    return *this;
}

inline nuwen::ser::serial& nuwen::ser::serial::operator<<(const sc_t n) {
    return *this << uc_from_sc(n);
}

inline nuwen::ser::serial& nuwen::ser::serial::operator<<(const us_t n) {
    m_v += cat(vuc_from_us(n));
    return *this;
}

inline nuwen::ser::serial& nuwen::ser::serial::operator<<(const ss_t n) {
    return *this << us_from_ss(n);
}

inline nuwen::ser::serial& nuwen::ser::serial::operator<<(const ul_t n) {
    m_v += cat(vuc_from_ul(n));
    return *this;
}

inline nuwen::ser::serial& nuwen::ser::serial::operator<<(const sl_t n) {
    return *this << ul_from_sl(n);
}

inline nuwen::ser::serial& nuwen::ser::serial::operator<<(const ull_t n) {
    m_v += cat(vuc_from_ull(n));
    return *this;
}

inline nuwen::ser::serial& nuwen::ser::serial::operator<<(const sll_t n) {
    return *this << ull_from_sll(n);
}

inline nuwen::ser::serial& nuwen::ser::serial::operator<<(const std::string& s) {
    return *this << string_cast<vuc_t>(s);
}

template <typename T> nuwen::ser::serial& nuwen::ser::serial::operator<<(const std::vector<T>& v) {
    return serialize_container(v);
}

template <typename T> nuwen::ser::serial& nuwen::ser::serial::operator<<(const std::deque<T>& d) {
    return serialize_container(d);
}

template <typename T> nuwen::ser::serial& nuwen::ser::serial::operator<<(const std::list<T>& l) {
    return serialize_container(l);
}

template <typename A, typename B> nuwen::ser::serial& nuwen::ser::serial::operator<<(const std::pair<A, B>& p) {
    return *this << p.first << p.second;
}

template <typename T, typename L> nuwen::ser::serial& nuwen::ser::serial::operator<<(const std::set<T, L>& s) {
    return serialize_container(s);
}

template <typename T, typename L> nuwen::ser::serial& nuwen::ser::serial::operator<<(const std::multiset<T, L>& ms) {
    return serialize_container(ms);
}

template <typename K, typename V, typename L> nuwen::ser::serial& nuwen::ser::serial::operator<<(const std::map<K, V, L>& m) {
    return serialize_container(m);
}

template <typename K, typename V, typename L> nuwen::ser::serial& nuwen::ser::serial::operator<<(const std::multimap<K, V, L>& mm) {
    return serialize_container(mm);
}

template <typename C> nuwen::ser::serial& nuwen::ser::serial::serialize_container(const C& c) {
    *this << static_cast<ull_t>(c.size());

    for (typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
        *this << *i;
    }

    return *this;
}

inline nuwen::des::deserial::deserial(const vuc_t& v) : m_curr(v.begin()), m_end(v.end()) { }

template <typename T> T nuwen::des::deserial::get() {
    return pham::des_helper<T>::fxn(*this);
}

inline nuwen::vuc_ci_t nuwen::des::deserial::curr() const { return m_curr; }

inline nuwen::vuc_ci_t nuwen::des::deserial::end() const { return m_end; }

inline nuwen::ull_t nuwen::des::deserial::size() const { return static_cast<ull_t>(m_end - m_curr); }

inline void nuwen::des::deserial::consume(const ull_t n) {
    if (n > size()) {
        throw std::logic_error("LOGIC ERROR: nuwen::des::deserial::consume() - Invalid n.");
    }

    m_curr += static_cast<vuc_d_t>(n);
}

#endif // Idempotency

ext: hh

max_stars_repo_name: nurettin/libnuwen

max_issues_repo_name: nurettin/libnuwen

max_forks_repo_name: nurettin/libnuwen


text:
// Copyright 2019 <maus74>
#include "BrokerResolver.h"

#include <boost/lexical_cast.hpp>

std::string BrokerFile::directoriesToString() const
{
    std::string result;
    for (const std::string &dir : directories) {
        result += dir + " ";
    }
    return result.substr(0, result.size() - 1);
}

void BrokerResolver::saveFileIfCorrect(const boost::filesystem::path &path)
{
    std::string filename = path.filename().string();
    boost::smatch result;
    if (filename.find(".old") != std::string::npos
        || !boost::regex_match(filename, result, filenameChecker)) {
        return;
    }

    fileCollection.emplace_front(BrokerFile{path.filename().string(),
                                            currentDirectories});

    std::string broker = fileCollection.front().directoriesToString();
    auto account = boost::lexical_cast<size_t>(result[2]);
    std::string date = result[3];

    auto iterator = dataCollection.find(BrokerData::Pair{broker, account});
    if (iterator != dataCollection.cend()) {
        iterator->second.files++;
        setIfMore(iterator->second.lastDate, date);
    } else {
        dataCollection[{broker, account}] = {1, date};
    }
}

void BrokerResolver::resolve(const boost::filesystem::path &path)
{
    for (const boost::filesystem::directory_entry &entry :
            boost::filesystem::directory_iterator{path}) {
        boost::filesystem::path resolved =
                boost::filesystem::canonical(entry);

        if (boost::filesystem::is_directory(resolved)) {
            currentDirectories.push_back(
                    boost::filesystem::path{entry}.stem().string());
            resolve(resolved);
        } else if (boost::filesystem::is_regular_file(resolved)) {
            saveFileIfCorrect(entry);
        }
    }

    if (!currentDirectories.empty()) {
        currentDirectories.pop_back();
    }
}

boost::regex BrokerResolver::filenameChecker{
        R"((\w+)_(\d{8})_([12]\d{3}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])).txt)"
};


text:
/*=============================================================================
    Copyright (c) 2004 Angus Leeming

    Distributed under the Boost Software License, Version 1.0.
    (See accompanying file LICENSE_1_0.txt or copy at
    http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/

#include <boost/spirit/core.hpp>

#include <iostream>
#include <string>

///////////////////////////////////////////////////////////////////////////////
//
// Spirit implementation of the grammar described in
// ../doc/grammar_overview.html
//
// The code does nothing more than flag whether the input data conforms to
// the grammar.
//
///////////////////////////////////////////////////////////////////////////////

namespace spirit = boost::spirit;

using std::string;
using std::cin;
using std::cout;
using std::cerr;
using std::endl;

struct skip_grammar : spirit::grammar<skip_grammar>
{
    template <typename ScannerT>
    struct definition {
        definition(skip_grammar const &)
        {
            using spirit::space_p;
            using spirit::anychar_p;

            skip
                = whitespace
                | '\\' >> *whitespace >> '\n'
                | '#' >> *(anychar_p - '\n');

            whitespace
                = space_p - '\n';
        }

        typedef typename spirit::rule<ScannerT> rule_t;

        rule_t const & start() const { return skip; }

    private:
        rule_t skip, whitespace;
    };
};

struct expression_grammar : public spirit::grammar<expression_grammar>
{
    template <typename ScannerT>
    struct definition
    {
        definition(expression_grammar const &)
        {
            using spirit::alpha_p;
            using spirit::alnum_p;
            using spirit::ch_p;
            using spirit::real_p;
            using spirit::str_p;

            expr
                = logical_expr >> !conditional_expr_helper;
            conditional_expr_helper
                = ch_p('?') >> expr >> ':' >> expr >> !conditional_expr_helper;
            logical_expr
                = bitwise_expr >> *((str_p("&&") | "||") >> bitwise_expr);
            bitwise_expr
                = equality_expr >> *((ch_p('&') | '|' | '^') >> equality_expr);
            equality_expr
                = compare_expr >> *((str_p("==") | "!=") >> compare_expr);
            compare_expr
                = shift_expr >> *((ch_p('<') | '>' | "<=" | ">=") >> shift_expr);
            shift_expr
                = add_expr >> *((str_p("<<") | ">>") >> add_expr);
            add_expr
                = mult_expr >> *((ch_p('+') | '-') >> mult_expr);
            mult_expr
                = expr_atom >> *((ch_p('*') | '/' | '%') >> expr_atom);
            expr_atom
                = function
                | number
                | ch_p('(') >> expr >> ')'
                | (ch_p('+') | '-' | '!') >> expr_atom;
            number
                = real_p
                | local_vars
                | global_vars;
            local_vars
                = name;
            global_vars
                = name;
            function
                = name >> '(' >> !arg_list >> ')';
            arg_list
                = expr >> *(ch_p(',') >> expr);
            name
                = (alpha_p | '_') >> *(alnum_p | '_');
        }

        typedef typename spirit::rule<ScannerT> rule_t;

        rule_t const & start() const { return expr; }

    private:
        rule_t add_expr, arg_list, bitwise_expr, compare_expr,
            conditional_expr_helper, equality_expr, expr, expr_atom,
            function, global_vars, local_vars, logical_expr, mult_expr,
            name, number, shift_expr;
    };
};

struct yac_grammar : public spirit::grammar<yac_grammar>
{
    template <typename ScannerT>
    struct definition
    {
        definition(yac_grammar const &)
        {
            using spirit::alpha_p;
            using spirit::alnum_p;
            using spirit::ch_p;

            statement_list
                = *(statement >> +(ch_p('\n') | ';'));
            statement
                = var_assignment
                | function_definition
                | "print " >> expression_list;
            expression_list
                = expression >> *(',' >> expression);
            var_assignment
                = name >> '=' >> expression;
            function_definition
                = name >> '(' >> !name_list >> ')' >> '=' >> expression;
            name_list
                = name >> *(',' >> name);
            name
                = (alpha_p | '_') >> *(alnum_p | '_');
        }

        typedef typename spirit::rule<ScannerT> rule_t;

        rule_t const & start() const { return statement_list; }

    private:
        rule_t expression_list, function_definition, name, name_list,
            statement, statement_list, var_assignment;
        expression_grammar expression;
    };
};

namespace {

char const * prompt()
{
    return "yac> ";
}

} // namespace anon

int main()
{
    typedef spirit::parse_info<string::const_iterator> parse_info_t;

    yac_grammar calculator;
    skip_grammar skipper;

    cout << "/////////////////////////////////////////////////////////\n\n"
         << "\t\tYet Another Calculator...\n\n"
         << "/////////////////////////////////////////////////////////\n\n"
         << "Type an expression...or [q or Q] to quit\n\n";

    string data;
    string buffer;
    cout << prompt();
    while (getline(cin, buffer)) {
        // getline strips the final '\n', so add it back.
        buffer += '\n';

        // Quit?
        // Find the first non-whitespace character.
        parse_info_t info
            = spirit::parse(buffer.begin(), buffer.end(), *spirit::space_p);

        if (info.full) {
            // Nothing but whitespace
            if (data.empty())
                cout << prompt();
            continue;
        } else {
            string::size_type const first = info.stop - buffer.begin();
            if (buffer[first] == 'q' || buffer[first] == 'Q')
                break;
        }

        // Continuation?
        // Find the last non-whitespace character.
        string const rbuffer = string(buffer.rbegin(), buffer.rend());
        // Cannot fail because we're testing the same data as above.
        info = spirit::parse(rbuffer.begin(), rbuffer.end(), *spirit::space_p);
        string::size_type const last = rbuffer.end() - info.stop - 1;

        data += buffer;
        if (buffer[last] == '\\')
            continue;

        // The data has been generated, so now get on and parse it properly.
        info = spirit::parse(data.begin(), data.end(), calculator, skipper);

        if (info.full) {
            cout << "-------------------------\n"
                 << "Parsing succeeded\n"
                 << "-------------------------\n";
        } else {
            cerr << "-------------------------\n"
                 << "Parsing failed\n"
                 << "-------------------------\n";
        }

        data.clear();
        cout << prompt();
    }

    return 0;
}

max_stars_repo_name: Devaraj-G/volna

max_issues_repo_name: Devaraj-G/volna

max_forks_repo_name: Devaraj-G/volna