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

#include <nvtt/nvtt.h>
#include <nvimage/Image.h>
#include <nvimage/ImageIO.h>
#include <nvimage/BlockDXT.h>
#include <nvimage/ColorBlock.h>
#include <nvcore/Ptr.h>
#include <nvcore/Debug.h>
#include <nvcore/StrLib.h>
#include <nvcore/StdStream.h>
#include <nvcore/TextWriter.h>

#include <stdlib.h> // free
#include <string.h> // memcpy
#include <time.h> // clock

using namespace nv;

static const char * s_fileNames[] = {
	// Kodak image set
	"kodim01.png",
	"kodim02.png",
	"kodim03.png",
	"kodim04.png",
	"kodim05.png",
	"kodim06.png",
	"kodim07.png",
	"kodim08.png",
	"kodim09.png",
	"kodim10.png",
	"kodim11.png",
	"kodim12.png",
	"kodim13.png",
	"kodim14.png",
	"kodim15.png",
	"kodim16.png",
	"kodim17.png",
	"kodim18.png",
	"kodim19.png",
	"kodim20.png",
	"kodim21.png",
	"kodim22.png",
	"kodim23.png",
	"kodim24.png",
	// Waterloo image set
	"clegg.png",
	"frymire.png",
	"lena.png",
	"monarch.png",
	"peppers.png",
	"sail.png",
	"serrano.png",
	"tulips.png",
	// Epic image set
	"Bradley1.png",
	"Gradient.png",
	"MoreRocks.png",
	"Wall.png",
	"Rainbow.png",
	"Text.png",
};
const int s_fileCount = sizeof(s_fileNames)/sizeof(s_fileNames[0]);

struct MyOutputHandler : public nvtt::OutputHandler
{
	MyOutputHandler() : m_data(NULL), m_ptr(NULL) {}
	~MyOutputHandler()
	{
		free(m_data);
	}

	virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel)
	{
		m_size = size;
		m_width = width;
		m_height = height;
		free(m_data);
		m_data = (unsigned char *)malloc(size);
		m_ptr = m_data;
	}

	virtual bool writeData(const void * data, int size)
	{
		memcpy(m_ptr, data, size);
		m_ptr += size;
		return true;
	}

	Image * decompress(nvtt::Format format)
	{
		int bw = (m_width + 3) / 4;
		int bh = (m_height + 3) / 4;

		AutoPtr<Image> img( new Image() );
		img->allocate(m_width, m_height);

		if (format == nvtt::Format_BC1)
		{
			BlockDXT1 * block = (BlockDXT1 *)m_data;

			for (int y = 0; y < bh; y++)
			{
				for (int x = 0; x < bw; x++)
				{
					ColorBlock colors;
					block->decodeBlock(&colors);

					for (int yy = 0; yy < 4; yy++)
					{
						for (int xx = 0; xx < 4; xx++)
						{
							Color32 c = colors.color(xx, yy);

							if (x * 4 + xx < m_width && y * 4 + yy < m_height)
							{
								img->pixel(x * 4 + xx, y * 4 + yy) = c;
							}
						}
					}

					block++;
				}
			}
		}

		return img.release();
	}

	int m_size;
	int m_width;
	int m_height;
	unsigned char * m_data;
	unsigned char * m_ptr;
};

float rmsError(const Image * a, const Image * b)
{
	nvCheck(a != NULL);
	nvCheck(b != NULL);
	nvCheck(a->width() == b->width());
	nvCheck(a->height() == b->height());

	float mse = 0;

	const uint count = a->width() * a->height();

	for (uint i = 0; i < count; i++)
	{
		Color32 c0 = a->pixel(i);
		Color32 c1 = b->pixel(i);

		int r = c0.r - c1.r;
		int g = c0.g - c1.g;
		int b = c0.b - c1.b;
		//int a = c0.a - c1.a;

		mse += r * r;
		mse += g * g;
		mse += b * b;
	}

	mse /= count;

	return sqrtf(mse);
}

int main(int argc, char *argv[])
{
	const uint version = nvtt::version();
	const uint major = version / 100;
	const uint minor = version % 100;

	printf("NVIDIA Texture Tools %u.%u - Copyright NVIDIA Corporation 2007 - 2008\n\n", major, minor);

	bool fast = false;
	bool nocuda = false;
	bool showHelp = false;
	const char * outPath = "output";
	const char * regressPath = NULL;

	// Parse arguments.
	for (int i = 1; i < argc; i++)
	{
		if (strcmp("-fast", argv[i]) == 0)
		{
			fast = true;
		}
		else if (strcmp("-nocuda", argv[i]) == 0)
		{
			nocuda = true;
		}
		else if (strcmp("-help", argv[i]) == 0)
		{
			showHelp = true;
		}
		else if (strcmp("-out", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') outPath = argv[i+1];
		}
		else if (strcmp("-regress", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') regressPath = argv[i+1];
		}
	}

	if (showHelp)
	{
		printf("usage: nvtestsuite [options]\n\n");

		printf("Input options:\n");
		printf("  -regress <path>\tRegression directory.\n");

		printf("Compression options:\n");
		printf("  -fast          \tFast compression.\n");
		printf("  -nocuda        \tDo not use cuda compressor.\n");

		printf("Output options:\n");
		printf("  -out <path>    \tOutput directory.\n");

		return 1;
	}

	nvtt::InputOptions inputOptions;
	inputOptions.setMipmapGeneration(false);

	nvtt::CompressionOptions compressionOptions;
	compressionOptions.setFormat(nvtt::Format_BC1);
	if (fast)
	{
		compressionOptions.setQuality(nvtt::Quality_Fastest);
	}
	else
	{
		compressionOptions.setQuality(nvtt::Quality_Production);
	}

	nvtt::OutputOptions outputOptions;
	outputOptions.setOutputHeader(false);

	MyOutputHandler outputHandler;
	outputOptions.setOutputHandler(&outputHandler);

	nvtt::Compressor compressor;
	compressor.enableCudaAcceleration(!nocuda);

    // @@ Create outPath.

	Path csvFileName("%s/result.csv", outPath);
	StdOutputStream csvStream(csvFileName);
	TextWriter csvWriter(&csvStream);

	float totalTime = 0;
	float totalRMS = 0;
	int failedTests = 0;
	float totalDiff = 0;

	for (int i = 0; i < s_fileCount; i++)
	{
		AutoPtr<Image> img( new Image() );

		if (!img->load(s_fileNames[i]))
		{
			printf("Input image '%s' not found.\n", s_fileNames[i]);
			return EXIT_FAILURE;
		}

		inputOptions.setTextureLayout(nvtt::TextureType_2D, img->width(), img->height());
		inputOptions.setMipmapData(img->pixels(), img->width(), img->height());

		printf("Compressing: \t'%s'\n", s_fileNames[i]);

		clock_t start = clock();

		compressor.process(inputOptions, compressionOptions, outputOptions);

		clock_t end = clock();
		printf("  Time: \t%.3f sec\n", float(end-start) / CLOCKS_PER_SEC);
		totalTime += float(end-start);

		AutoPtr<Image> img_out( outputHandler.decompress(nvtt::Format_BC1) );

		Path outputFileName("%s/%s", outPath, s_fileNames[i]);
		outputFileName.stripExtension();
		outputFileName.append(".tga");
		if (!ImageIO::save(outputFileName, img_out.ptr()))
		{
			printf("Error saving file '%s'.\n", outputFileName.str());
		}

		float rms = rmsError(img.ptr(), img_out.ptr());
		totalRMS += rms;

		printf("  RMS:  \t%.4f\n", rms);

		// Output csv file
		csvWriter << "\"" << s_fileNames[i] << "\"," << rms << "\n";

		if (regressPath != NULL)
		{
			Path regressFileName("%s/%s", regressPath, s_fileNames[i]);
			regressFileName.stripExtension();
			regressFileName.append(".tga");

			AutoPtr<Image> img_reg( new Image() );
			if (!img_reg->load(regressFileName.str()))
			{
				printf("Regression image '%s' not found.\n", regressFileName.str());
				return EXIT_FAILURE;
			}

			float rms_reg = rmsError(img.ptr(), img_reg.ptr());

			float diff = rms_reg - rms;
			totalDiff += diff;

			const char * text = "PASSED";
			if (equal(diff, 0)) text = "PASSED";
			else if (diff < 0) {
				text = "FAILED";
				failedTests++;
			}

			printf("  Diff: \t%.4f (%s)\n", diff, text);
		}

        fflush(stdout);
	}

	totalRMS /= s_fileCount;
	totalDiff /= s_fileCount;

	printf("Total Results:\n");
	printf("  Total Time: \t%.3f sec\n", totalTime / CLOCKS_PER_SEC);
	printf("  Average RMS:\t%.4f\n", totalRMS);

	if (regressPath != NULL)
	{
		printf("Regression Results:\n");
		printf("  Diff: %.4f\n", totalDiff);
		printf("  %d/%d tests failed.\n", failedTests, s_fileCount);
	}

	return EXIT_SUCCESS;
}

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

#include <nvtt/nvtt.h>
#include <nvimage/Image.h>
#include <nvimage/ImageIO.h>
#include <nvimage/BlockDXT.h>
#include <nvimage/ColorBlock.h>
#include <nvcore/Ptr.h>
#include <nvcore/Debug.h>
#include <nvcore/StrLib.h>
#include <nvcore/StdStream.h>
#include <nvcore/TextWriter.h>
#include <nvcore/FileSystem.h>

#include <stdlib.h> // free
#include <string.h> // memcpy
#include <time.h> // clock

using namespace nv;

static const char * s_fileNames[] = {
	// Kodak image set
	"kodim01.png",
	"kodim02.png",
	"kodim03.png",
	"kodim04.png",
	"kodim05.png",
	"kodim06.png",
	"kodim07.png",
	"kodim08.png",
	"kodim09.png",
	"kodim10.png",
	"kodim11.png",
	"kodim12.png",
	"kodim13.png",
	"kodim14.png",
	"kodim15.png",
	"kodim16.png",
	"kodim17.png",
	"kodim18.png",
	"kodim19.png",
	"kodim20.png",
	"kodim21.png",
	"kodim22.png",
	"kodim23.png",
	"kodim24.png",
	// Waterloo image set
	"clegg.png",
	"frymire.png",
	"lena.png",
	"monarch.png",
	"peppers.png",
	"sail.png",
	"serrano.png",
	"tulips.png",
	// Epic image set
	"Bradley1.png",
	"Gradient.png",
	"MoreRocks.png",
	"Wall.png",
	"Rainbow.png",
	"Text.png",
};
const int s_fileCount = sizeof(s_fileNames)/sizeof(s_fileNames[0]);

struct MyOutputHandler : public nvtt::OutputHandler
{
	MyOutputHandler() : m_data(NULL), m_ptr(NULL) {}
	~MyOutputHandler()
	{
		free(m_data);
	}

	virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel)
	{
		m_size = size;
		m_width = width;
		m_height = height;
		free(m_data);
		m_data = (unsigned char *)malloc(size);
		m_ptr = m_data;
	}

	virtual bool writeData(const void * data, int size)
	{
		memcpy(m_ptr, data, size);
		m_ptr += size;
		return true;
	}

	Image * decompress(nvtt::Format format)
	{
		int bw = (m_width + 3) / 4;
		int bh = (m_height + 3) / 4;

		AutoPtr<Image> img( new Image() );
		img->allocate(m_width, m_height);

		if (format == nvtt::Format_BC1)
		{
			BlockDXT1 * block = (BlockDXT1 *)m_data;

			for (int y = 0; y < bh; y++)
			{
				for (int x = 0; x < bw; x++)
				{
					ColorBlock colors;
					block->decodeBlock(&colors);

					for (int yy = 0; yy < 4; yy++)
					{
						for (int xx = 0; xx < 4; xx++)
						{
							Color32 c = colors.color(xx, yy);

							if (x * 4 + xx < m_width && y * 4 + yy < m_height)
							{
								img->pixel(x * 4 + xx, y * 4 + yy) = c;
							}
						}
					}

					block++;
				}
			}
		}

		return img.release();
	}

	int m_size;
	int m_width;
	int m_height;
	unsigned char * m_data;
	unsigned char * m_ptr;
};

float rmsError(const Image * a, const Image * b)
{
	nvCheck(a != NULL);
	nvCheck(b != NULL);
	nvCheck(a->width() == b->width());
	nvCheck(a->height() == b->height());

	float mse = 0;

	const uint count = a->width() * a->height();

	for (uint i = 0; i < count; i++)
	{
		Color32 c0 = a->pixel(i);
		Color32 c1 = b->pixel(i);

		int r = c0.r - c1.r;
		int g = c0.g - c1.g;
		int b = c0.b - c1.b;
		//int a = c0.a - c1.a;

		mse += r * r;
		mse += g * g;
		mse += b * b;
	}

	mse /= count;

	return sqrtf(mse);
}

int main(int argc, char *argv[])
{
	const uint version = nvtt::version();
	const uint major = version / 100;
	const uint minor = version % 100;

	printf("NVIDIA Texture Tools %u.%u - Copyright NVIDIA Corporation 2007 - 2008\n\n", major, minor);

	bool fast = false;
	bool nocuda = false;
	bool showHelp = false;
	const char * outPath = "output";
	const char * regressPath = NULL;

	// Parse arguments.
	for (int i = 1; i < argc; i++)
	{
		if (strcmp("-fast", argv[i]) == 0)
		{
			fast = true;
		}
		else if (strcmp("-nocuda", argv[i]) == 0)
		{
			nocuda = true;
		}
		else if (strcmp("-help", argv[i]) == 0)
		{
			showHelp = true;
		}
		else if (strcmp("-out", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') outPath = argv[i+1];
		}
		else if (strcmp("-regress", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') regressPath = argv[i+1];
		}
	}

	if (showHelp)
	{
		printf("usage: nvtestsuite [options]\n\n");

		printf("Input options:\n");
		printf("  -regress <path>\tRegression directory.\n");

		printf("Compression options:\n");
		printf("  -fast          \tFast compression.\n");
		printf("  -nocuda        \tDo not use cuda compressor.\n");

		printf("Output options:\n");
		printf("  -out <path>    \tOutput directory.\n");

		return 1;
	}

	nvtt::InputOptions inputOptions;
	inputOptions.setMipmapGeneration(false);

	nvtt::CompressionOptions compressionOptions;
	compressionOptions.setFormat(nvtt::Format_BC1);
	if (fast)
	{
		compressionOptions.setQuality(nvtt::Quality_Fastest);
	}
	else
	{
		compressionOptions.setQuality(nvtt::Quality_Production);
	}

	nvtt::OutputOptions outputOptions;
	outputOptions.setOutputHeader(false);

	MyOutputHandler outputHandler;
	outputOptions.setOutputHandler(&outputHandler);

	nvtt::Compressor compressor;
	compressor.enableCudaAcceleration(!nocuda);

	FileSystem::createDirectory(outPath);

	Path csvFileName("%s/result.csv", outPath);
	StdOutputStream csvStream(csvFileName);
	TextWriter csvWriter(&csvStream);

	float totalTime = 0;
	float totalRMS = 0;
	int failedTests = 0;
	float totalDiff = 0;

	for (int i = 0; i < s_fileCount; i++)
	{
		AutoPtr<Image> img( new Image() );

		if (!img->load(s_fileNames[i]))
		{
			printf("Input image '%s' not found.\n", s_fileNames[i]);
			return EXIT_FAILURE;
		}

		inputOptions.setTextureLayout(nvtt::TextureType_2D, img->width(), img->height());
		inputOptions.setMipmapData(img->pixels(), img->width(), img->height());

		printf("Compressing: \t'%s'\n", s_fileNames[i]);

		clock_t start = clock();

		compressor.process(inputOptions, compressionOptions, outputOptions);

		clock_t end = clock();
		printf("  Time: \t%.3f sec\n", float(end-start) / CLOCKS_PER_SEC);
		totalTime += float(end-start);

		AutoPtr<Image> img_out( outputHandler.decompress(nvtt::Format_BC1) );

		Path outputFileName("%s/%s", outPath, s_fileNames[i]);
		outputFileName.stripExtension();
		outputFileName.append(".tga");
		if (!ImageIO::save(outputFileName, img_out.ptr()))
		{
			printf("Error saving file '%s'.\n", outputFileName.str());
		}

		float rms = rmsError(img.ptr(), img_out.ptr());
		totalRMS += rms;

		printf("  RMS:  \t%.4f\n", rms);

		// Output csv file
		csvWriter << "\"" << s_fileNames[i] << "\"," << rms << "\n";

		if (regressPath != NULL)
		{
			Path regressFileName("%s/%s", regressPath, s_fileNames[i]);
			regressFileName.stripExtension();
			regressFileName.append(".tga");

			AutoPtr<Image> img_reg( new Image() );
			if (!img_reg->load(regressFileName.str()))
			{
				printf("Regression image '%s' not found.\n", regressFileName.str());
				return EXIT_FAILURE;
			}

			float rms_reg = rmsError(img.ptr(), img_reg.ptr());

			float diff = rms_reg - rms;
			totalDiff += diff;

			const char * text = "PASSED";
			if (equal(diff, 0)) text = "PASSED";
			else if (diff < 0) {
				text = "FAILED";
				failedTests++;
			}

			printf("  Diff: \t%.4f (%s)\n", diff, text);
		}

		fflush(stdout);
	}

	totalRMS /= s_fileCount;
	totalDiff /= s_fileCount;

	printf("Total Results:\n");
	printf("  Total Time: \t%.3f sec\n", totalTime / CLOCKS_PER_SEC);
	printf("  Average RMS:\t%.4f\n", totalRMS);

	if (regressPath != NULL)
	{
		printf("Regression Results:\n");
		printf("  Diff: %.4f\n", totalDiff);
		printf("  %d/%d tests failed.\n", failedTests, s_fileCount);
	}

	return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/// \file uparser.cc

#include <sdk/config.h> // YYDEBUG.

//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>

#include <cassert>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <string>

#include <libport/foreach.hh>

#include <ast/nary.hh>
#include <ast/print.hh>

#include <parser/parser-impl.hh>
#include <parser/parser-utils.hh>
#include <parser/tweast.hh>
#include <parser/utoken.hh>

#include <kernel/server-timer.hh>

namespace parser
{

  /*-------------.
  | ParserImpl.  |
  `-------------*/

  ParserImpl::ParserImpl()
    : tweast_(0),
      loc_(),
      synclines_(),
      result_(0),
      debug_(!!getenv("YYDEBUG"))
  {
  }

  void
  ParserImpl::parse_(std::istream& source)
  {
    TIMER_PUSH("parse");
    // Set up result_.
    passert(*result_, !result_.get());
    result_.reset(new ParseResult);

    // Set up scanner.
    yyFlexLexer scanner;
    scanner.switch_streams(&source, 0);

    // Set up parser.
    parser_type p(*this, scanner);
#if defined YYDEBUG && YYDEBUG
    p.set_debug_level(debug_);
#endif

    // Parse.
    if (debug_)
      LIBPORT_ECHO("====================== Parse begin");
    result_->status = p.parse();
    if (debug_)
      LIBPORT_ECHO("====================== Parse end:" << std::endl
                   << *result_);
    TIMER_POP("parse");
  }

  parse_result_type
  ParserImpl::parse(const std::string& s)
  {
    if (debug_)
      LIBPORT_ECHO("Parsing: " << s);
    std::istringstream is(s);
    parse_(is);
    if (debug_)
      LIBPORT_ECHO("Result: " << *result_);
    return result_;
  }

  parse_result_type
  ParserImpl::parse(Tweast& t)
  {
    // Recursive calls are forbidden.  If we want to relax this
    // constraint, note that we also need to save and restore other
    // member changed during the parsing, such as warnings_ and
    // errors_.  But it is simpler to recurse with the standalone
    // parse functions.
    passert(tweast_, !tweast_);
    tweast_ = &t;
    std::istringstream is(t.input_get());
    parse_(is);
    tweast_ = 0;
    return result_;
  }

  parse_result_type
  ParserImpl::parse_file(const std::string& fn)
  {
    std::ifstream f(fn.c_str());
    if (!f.good())
    {
      // Return an error instead of creating a valid empty ast.
      result_.reset(new ParseResult);
      result_->status = 1;
    }
    else
    {
      // A location pointing to it.
      location_type loc;
      loc.initialize(new libport::Symbol(fn));

      // Exchange with the current location so that we can restore it
      // afterwards (when reading the input flow, we want to be able to
      // restore the cursor after having handled a load command).
      std::swap(loc, loc_);
      ECHO("Parsing file: " << fn);
      parse_(f);
      std::swap(loc, loc_);
    }
    return result_;
  }

  void
  ParserImpl::error(const location_type& l, const std::string& msg)
  {
    result_->error(l, msg);
  }

  void
  ParserImpl::warn(const location_type& l, const std::string& msg)
  {
    result_->warn(l, msg);
  }

}
<commit_msg>Do not use passert if the evaluation of the subject triggers abortion.<commit_after>/// \file uparser.cc

#include <sdk/config.h> // YYDEBUG.

//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>

#include <cassert>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <string>

#include <libport/foreach.hh>

#include <ast/nary.hh>
#include <ast/print.hh>

#include <parser/parser-impl.hh>
#include <parser/parser-utils.hh>
#include <parser/tweast.hh>
#include <parser/utoken.hh>

#include <kernel/server-timer.hh>

namespace parser
{

  /*-------------.
  | ParserImpl.  |
  `-------------*/

  ParserImpl::ParserImpl()
    : tweast_(0),
      loc_(),
      synclines_(),
      result_(0),
      debug_(!!getenv("YYDEBUG"))
  {
  }

  void
  ParserImpl::parse_(std::istream& source)
  {
    TIMER_PUSH("parse");
    // Set up result_.

    // FIXME: This check will evaluate (void)*result_ in NDEBUG,
    // entailing an abortion since result_ == 0. Passert should
    // probably be fixed.
    // passert(*result_, !result_.get());

    result_.reset(new ParseResult);

    // Set up scanner.
    yyFlexLexer scanner;
    scanner.switch_streams(&source, 0);

    // Set up parser.
    parser_type p(*this, scanner);
#if defined YYDEBUG && YYDEBUG
    p.set_debug_level(debug_);
#endif

    // Parse.
    if (debug_)
      LIBPORT_ECHO("====================== Parse begin");
    result_->status = p.parse();
    if (debug_)
      LIBPORT_ECHO("====================== Parse end:" << std::endl
                   << *result_);
    TIMER_POP("parse");
  }

  parse_result_type
  ParserImpl::parse(const std::string& s)
  {
    if (debug_)
      LIBPORT_ECHO("Parsing: " << s);
    std::istringstream is(s);
    parse_(is);
    if (debug_)
      LIBPORT_ECHO("Result: " << *result_);
    return result_;
  }

  parse_result_type
  ParserImpl::parse(Tweast& t)
  {
    // Recursive calls are forbidden.  If we want to relax this
    // constraint, note that we also need to save and restore other
    // member changed during the parsing, such as warnings_ and
    // errors_.  But it is simpler to recurse with the standalone
    // parse functions.
    passert(tweast_, !tweast_);
    tweast_ = &t;
    std::istringstream is(t.input_get());
    parse_(is);
    tweast_ = 0;
    return result_;
  }

  parse_result_type
  ParserImpl::parse_file(const std::string& fn)
  {
    std::ifstream f(fn.c_str());
    if (!f.good())
    {
      // Return an error instead of creating a valid empty ast.
      result_.reset(new ParseResult);
      result_->status = 1;
    }
    else
    {
      // A location pointing to it.
      location_type loc;
      loc.initialize(new libport::Symbol(fn));

      // Exchange with the current location so that we can restore it
      // afterwards (when reading the input flow, we want to be able to
      // restore the cursor after having handled a load command).
      std::swap(loc, loc_);
      ECHO("Parsing file: " << fn);
      parse_(f);
      std::swap(loc, loc_);
    }
    return result_;
  }

  void
  ParserImpl::error(const location_type& l, const std::string& msg)
  {
    result_->error(l, msg);
  }

  void
  ParserImpl::warn(const location_type& l, const std::string& msg)
  {
    result_->warn(l, msg);
  }

}
<|endoftext|>


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

#include "common.h"

#ifdef HAVE_SDL
#include <stdlib.h>
#include <string>
#include "SDLMedia.h"
#include "ErrorHandler.h"

#ifdef HALF_RATE_AUDIO
static const int defaultAudioRate=11025;
#else
static const int defaultAudioRate=22050;
#endif

//
// SDLMedia
//

SDLMedia::SDLMedia() : BzfMedia()
{
  cmdFill       = 0;
  audioReady    = false;
}

double			SDLMedia::stopwatch(bool start)
{
  Uint32 currentTick = SDL_GetTicks(); //msec

  if (start) {
    stopwatchTime = currentTick;
    return 0.0;
  }
  if (currentTick >= stopwatchTime)
    return (double) (currentTick - stopwatchTime) * 0.001; // sec
  else
    //Clock is wrapped : happens after 49 days
    //Should be "wrap value" - stopwatchtime. Now approx.
    return (double) currentTick * 0.001;
}

bool			SDLMedia::openAudio()
{
  // don't re-initialize
  if (audioReady) return false;

  if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) {
    printFatalError("Could not initialize SDL-Audio: %s.\n", SDL_GetError());
    exit(-1);
  };

  static SDL_AudioSpec desired;

  // what the frequency?
  audioOutputRate = defaultAudioRate;

  // how big a fragment to use?  we want to hold at around 1/10th of
  // a second.
  // probably SDL is using multiple buffering, make it a 3rd
  int fragmentSize = (int)(0.03f * (float)audioOutputRate);
  int n;

  n = 0;
  while ((1 << n) < fragmentSize)
    ++n;

  // samples are two bytes each so double the size
  audioBufferSize = 1 << (n + 1);

  desired.freq       = audioOutputRate;
  desired.format     = AUDIO_S16SYS;
  desired.channels   = 2;
  desired.samples    = audioBufferSize >> 1; // In stereo samples
  desired.callback   = &fillAudioWrapper;
  desired.userdata   = (void *) this;	// To handle Wrap of func

  /* Open the audio device, forcing the desired format */
  if (SDL_OpenAudio(&desired, NULL) < 0) {
    fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
    return false;
  }

  // make an output buffer
  outputBuffer  = new short[audioBufferSize];

  // ready to go
  audioReady = true;

  return true;
}

void			SDLMedia::closeAudio()
{
  // Stop Audio to avoid callback
  SDL_PauseAudio(1);

  SDL_CloseAudio();
  delete [] outputBuffer;
  outputBuffer  = 0;
  SDL_QuitSubSystem(SDL_INIT_AUDIO);
  audioReady    = false;
}

void			SDLMedia::startAudioCallback(bool (*proc)(void))
{
  userCallback = proc;

  // Stop sending silence and start calling audio callback
  SDL_PauseAudio(0);
}

void			SDLMedia::writeSoundCommand(const void* cmd, int len)
{
  if (!audioReady) return;

  SDL_LockAudio();

  // Discard command if full
  if ((cmdFill + len) < 2048) {
    memcpy(&cmdQueue[cmdFill], cmd, len);
    // We should awake audioSleep - but game become unplayable
    // using here an SDL_CondSignal(wakeCond)
    cmdFill += len;
  }

  SDL_UnlockAudio();
}

bool			SDLMedia::readSoundCommand(void* cmd, int len)
{
  bool result = false;

  if (cmdFill >= len) {
    memcpy(cmd, cmdQueue, len);
    // repack list of command waiting to be processed
    memmove(cmdQueue, &cmdQueue[len], cmdFill - len);
    cmdFill -= len;
    result = true;
  }
  return result;
}

int			SDLMedia::getAudioOutputRate() const
{
  return audioOutputRate;
}

int			SDLMedia::getAudioBufferSize() const
{
  return audioBufferSize;
}

int			SDLMedia::getAudioBufferChunkSize() const
{
  return audioBufferSize>>1;
}

void SDLMedia::fillAudio (Uint8 * stream, int len)
{
  userCallback();
  Uint8* soundBuffer	= stream;

  int transferSize = (audioBufferSize - sampleToSend) * 2;
  if (transferSize > len)
    transferSize   = len;
  // just copying into the soundBuffer is enough, SDL is looking for
  // something different from silence sample
  memcpy(soundBuffer,
	 (Uint8 *) &outputBuffer[sampleToSend],
	 transferSize);
  sampleToSend    += transferSize / 2;
  soundBuffer     += transferSize;
  len	     -= transferSize;

}

void SDLMedia::fillAudioWrapper (void * userdata, Uint8 * stream, int len)
{
  SDLMedia * me = (SDLMedia *) userdata;
  me->fillAudio(stream, len);
};

void			SDLMedia::writeAudioFrames(
				const float* samples, int numFrames)
{
  int numSamples = 2 * numFrames;
  int limit;

  while (numSamples > 0) {
    if (numSamples>audioBufferSize)
      limit=audioBufferSize;
    else
      limit=numSamples;
    for (int j = 0; j < limit; j++) {
      if (samples[j] < -32767.0)
	outputBuffer[j] = -32767;
      else
	if (samples[j] > 32767.0)
	  outputBuffer[j] = 32767;
	else
	  outputBuffer[j] = short(samples[j]);
    }

    // fill out the chunk (we never write a partial chunk)
    if (limit < audioBufferSize) {
      for (int j = limit; j < audioBufferSize; ++j)
	outputBuffer[j] = 0;
    }

    sampleToSend = 0;

    samples    += audioBufferSize;
    numSamples -= audioBufferSize;
  }
}

// Setting Audio Driver
void	SDLMedia::setDriver(std::string driverName) {
  static char envAssign[256];
  std::string envVar = "SDL_AUDIODRIVER=" + driverName;
  strncpy(envAssign, envVar.c_str(), 255);
  envAssign[255]     = '\0';
  putenv(envAssign);
};

// Setting Audio Device
void	SDLMedia::setDevice(std::string deviceName) {
  static char envAssign[256];
  std::string envVar = "SDL_PATH_DSP=" + deviceName;
  strncpy(envAssign, envVar.c_str(), 255);
  envAssign[255]     = '\0';
  putenv(envAssign);
};

float*	    SDLMedia::doReadSound(const std::string &filename, int &numFrames,
				  int &rate) const
{
  SDL_AudioSpec wav_spec;
  Uint32	wav_length;
  Uint8	*wav_buffer;
  int	   ret;
  SDL_AudioCVT  wav_cvt;
  int16_t      *cvt16;
  int	   i;

  float	*data = NULL;
  rate	= defaultAudioRate;
  if (SDL_LoadWAV(filename.c_str(), &wav_spec, &wav_buffer, &wav_length)) {
    /* Build AudioCVT */
    ret = SDL_BuildAudioCVT(&wav_cvt,
			    wav_spec.format, wav_spec.channels, wav_spec.freq,
			    AUDIO_S16SYS, 2, defaultAudioRate);
    /* Check that the convert was built */
    if (ret == -1) {
      printFatalError("Could not build converter for Wav file %s: %s.\n",
		      filename.c_str(), SDL_GetError());
    } else {
      /* Setup for conversion */
      wav_cvt.buf = (Uint8*)malloc(wav_length * wav_cvt.len_mult);
      wav_cvt.len = wav_length;
      memcpy(wav_cvt.buf, wav_buffer, wav_length);
      /* And now we're ready to convert */
      SDL_ConvertAudio(&wav_cvt);
      numFrames = (int)(wav_length * wav_cvt.len_ratio / 4);
      cvt16     = (int16_t *)wav_cvt.buf;
      data      = new float[numFrames * 2];
      for (i = 0; i < numFrames * 2; i++)
	data[i] = cvt16[i];
      free(wav_cvt.buf);
    }
    SDL_FreeWAV(wav_buffer);
  }
  return data;
}

void SDLMedia::audioDriver(std::string& driverName)
{
  char driver[128] = "SDL: audio not available";
  char *result = SDL_AudioDriverName(driver, sizeof(driver));
  if (result)
    driverName = driver;
  else
    driverName = "SDL: audio not available";
}

#endif //HAVE_SDL
// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

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

#include "common.h"

#ifdef HAVE_SDL
#include <stdlib.h>
#include <string>
#include "SDLMedia.h"
#include "ErrorHandler.h"

#ifdef HALF_RATE_AUDIO
static const int defaultAudioRate=11025;
#else
static const int defaultAudioRate=22050;
#endif

//
// SDLMedia
//

SDLMedia::SDLMedia() : BzfMedia()
{
  cmdFill       = 0;
  audioReady    = false;
}

double			SDLMedia::stopwatch(bool start)
{
  Uint32 currentTick = SDL_GetTicks(); //msec

  if (start) {
    stopwatchTime = currentTick;
    return 0.0;
  }
  if (currentTick >= stopwatchTime)
    return (double) (currentTick - stopwatchTime) * 0.001; // sec
  else
    //Clock is wrapped : happens after 49 days
    //Should be "wrap value" - stopwatchtime. Now approx.
    return (double) currentTick * 0.001;
}

bool			SDLMedia::openAudio()
{
  // don't re-initialize
  if (audioReady) return false;

  if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) {
    printFatalError("Could not initialize SDL-Audio: %s.\n", SDL_GetError());
    exit(-1);
  };

  static SDL_AudioSpec desired;

  // what the frequency?
  audioOutputRate = defaultAudioRate;

  // how big a fragment to use?  we want to hold at around 1/10th of
  // a second.
  // probably SDL is using multiple buffering, make it a 3rd
  int fragmentSize = (int)(0.03f * (float)audioOutputRate);
  int n;

  n = 0;
  while ((1 << n) < fragmentSize)
    ++n;

  // samples are two bytes each so double the size
  audioBufferSize = 1 << (n + 1);

  desired.freq       = audioOutputRate;
  desired.format     = AUDIO_S16SYS;
  desired.channels   = 2;
  desired.samples    = audioBufferSize >> 1; // In stereo samples
  desired.callback   = &fillAudioWrapper;
  desired.userdata   = (void *) this;	// To handle Wrap of func

  /* Open the audio device, forcing the desired format */
  if (SDL_OpenAudio(&desired, NULL) < 0) {
    fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
    return false;
  }

  // make an output buffer
  outputBuffer  = new short[audioBufferSize];

  // ready to go
  audioReady = true;

  return true;
}

void			SDLMedia::closeAudio()
{
  // Stop Audio to avoid callback
  SDL_PauseAudio(1);

  SDL_CloseAudio();
  delete [] outputBuffer;
  outputBuffer  = 0;
  SDL_QuitSubSystem(SDL_INIT_AUDIO);
  audioReady    = false;
}

void			SDLMedia::startAudioCallback(bool (*proc)(void))
{
  userCallback = proc;

  // Stop sending silence and start calling audio callback
  SDL_PauseAudio(0);
}

void			SDLMedia::writeSoundCommand(const void* cmd, int len)
{
  if (!audioReady) return;

  SDL_LockAudio();

  // Discard command if full
  if ((cmdFill + len) < 2048) {
    memcpy(&cmdQueue[cmdFill], cmd, len);
    // We should awake audioSleep - but game become unplayable
    // using here an SDL_CondSignal(wakeCond)
    cmdFill += len;
  }

  SDL_UnlockAudio();
}

bool			SDLMedia::readSoundCommand(void* cmd, int len)
{
  bool result = false;

  if (cmdFill >= len) {
    memcpy(cmd, cmdQueue, len);
    // repack list of command waiting to be processed
    memmove(cmdQueue, &cmdQueue[len], cmdFill - len);
    cmdFill -= len;
    result = true;
  }
  return result;
}

int			SDLMedia::getAudioOutputRate() const
{
  return audioOutputRate;
}

int			SDLMedia::getAudioBufferSize() const
{
  return audioBufferSize;
}

int			SDLMedia::getAudioBufferChunkSize() const
{
  return audioBufferSize>>1;
}

void SDLMedia::fillAudio (Uint8 * stream, int len)
{
  userCallback();
  Uint8* soundBuffer	= stream;

  int transferSize = (audioBufferSize - sampleToSend) * 2;
  if (transferSize > len)
    transferSize   = len;
  // just copying into the soundBuffer is enough, SDL is looking for
  // something different from silence sample
  memcpy(soundBuffer,
	 (Uint8 *) &outputBuffer[sampleToSend],
	 transferSize);
  sampleToSend    += transferSize / 2;
  soundBuffer     += transferSize;
  len	     -= transferSize;

}

void SDLMedia::fillAudioWrapper (void * userdata, Uint8 * stream, int len)
{
  SDLMedia * me = (SDLMedia *) userdata;
  me->fillAudio(stream, len);
};

void			SDLMedia::writeAudioFrames(
				const float* samples, int numFrames)
{
  int numSamples = 2 * numFrames;
  int limit;

  while (numSamples > 0) {
    if (numSamples>audioBufferSize)
      limit=audioBufferSize;
    else
      limit=numSamples;
    for (int j = 0; j < limit; j++) {
      if (samples[j] < -32767.0)
	outputBuffer[j] = -32767;
      else
	if (samples[j] > 32767.0)
	  outputBuffer[j] = 32767;
	else
	  outputBuffer[j] = short(samples[j]);
    }

    // fill out the chunk (we never write a partial chunk)
    if (limit < audioBufferSize) {
      for (int j = limit; j < audioBufferSize; ++j)
	outputBuffer[j] = 0;
    }

    sampleToSend = 0;

    samples    += audioBufferSize;
    numSamples -= audioBufferSize;
  }
}

// Setting Audio Driver
void	SDLMedia::setDriver(std::string driverName) {
  static char envAssign[256];
  std::string envVar = "SDL_AUDIODRIVER=" + driverName;
  strncpy(envAssign, envVar.c_str(), 255);
  envAssign[255]     = '\0';
  putenv(envAssign);
};

// Setting Audio Device
void	SDLMedia::setDevice(std::string deviceName) {
  static char envAssign[256];
  std::string envVar = "AUDIODEV=" + deviceName;
  strncpy(envAssign, envVar.c_str(), 255);
  envAssign[255]     = '\0';
  putenv(envAssign);
};

float*	    SDLMedia::doReadSound(const std::string &filename, int &numFrames,
				  int &rate) const
{
  SDL_AudioSpec wav_spec;
  Uint32	wav_length;
  Uint8	*wav_buffer;
  int	   ret;
  SDL_AudioCVT  wav_cvt;
  int16_t      *cvt16;
  int	   i;

  float	*data = NULL;
  rate	= defaultAudioRate;
  if (SDL_LoadWAV(filename.c_str(), &wav_spec, &wav_buffer, &wav_length)) {
    /* Build AudioCVT */
    ret = SDL_BuildAudioCVT(&wav_cvt,
			    wav_spec.format, wav_spec.channels, wav_spec.freq,
			    AUDIO_S16SYS, 2, defaultAudioRate);
    /* Check that the convert was built */
    if (ret == -1) {
      printFatalError("Could not build converter for Wav file %s: %s.\n",
		      filename.c_str(), SDL_GetError());
    } else {
      /* Setup for conversion */
      wav_cvt.buf = (Uint8*)malloc(wav_length * wav_cvt.len_mult);
      wav_cvt.len = wav_length;
      memcpy(wav_cvt.buf, wav_buffer, wav_length);
      /* And now we're ready to convert */
      SDL_ConvertAudio(&wav_cvt);
      numFrames = (int)(wav_length * wav_cvt.len_ratio / 4);
      cvt16     = (int16_t *)wav_cvt.buf;
      data      = new float[numFrames * 2];
      for (i = 0; i < numFrames * 2; i++)
	data[i] = cvt16[i];
      free(wav_cvt.buf);
    }
    SDL_FreeWAV(wav_buffer);
  }
  return data;
}

void SDLMedia::audioDriver(std::string& driverName)
{
  char driver[128];
  char *result = SDL_AudioDriverName(driver, sizeof(driver));
  if (result)
    driverName = driver;
  else
    driverName = "audio not available";
}

#endif //HAVE_SDL
// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2011 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "TextEngine.h"

#include "../base/Logger.h"
#include "../base/OSHelper.h"
#include "../base/Exception.h"
#include "../base/FileHelper.h"
#include "../base/StringHelper.h"

#include <algorithm>

namespace avg {

using namespace std;

static void
text_subst_func_hint(FcPattern *pattern, gpointer data)
{
    FcPatternAddBool(pattern, FC_HINTING, true);
    FcPatternAddInteger(pattern, FC_HINT_STYLE, FC_HINT_MEDIUM);
    FcPatternAddInteger(pattern, FC_RGBA, FC_RGBA_NONE);
    FcPatternAddBool(pattern, FC_ANTIALIAS, true);
}

static void
text_subst_func_nohint(FcPattern *pattern, gpointer data)
{
    FcPatternAddBool(pattern, FC_HINTING, false);
    FcPatternAddBool(pattern, FC_AUTOHINT, false);
    FcPatternAddInteger(pattern, FC_HINT_STYLE, FC_HINT_NONE);
    FcPatternAddInteger(pattern, FC_RGBA, FC_RGBA_NONE);
    FcPatternAddBool(pattern, FC_ANTIALIAS, true);
}

TextEngine& TextEngine::get(bool bHint)
{
    if (bHint) {
        static TextEngine s_Instance(true);
        return s_Instance;
    } else {
        static TextEngine s_Instance(false);
        return s_Instance;
    }
}

TextEngine::TextEngine(bool bHint)
    : m_bHint(bHint)
{
    m_sFontDirs.push_back("fonts/");
    init();
}

TextEngine::~TextEngine()
{
    deinit();
}

void TextEngine::init()
{
    m_pFontMap = PANGO_FT2_FONT_MAP(pango_ft2_font_map_new());
    pango_ft2_font_map_set_resolution(m_pFontMap, 72, 72);
    if (m_bHint) {
        pango_ft2_font_map_set_default_substitute(m_pFontMap, text_subst_func_hint,
                0, 0);
    } else {
        pango_ft2_font_map_set_default_substitute(m_pFontMap, text_subst_func_nohint,
                0, 0);
    }
    m_pPangoContext = pango_ft2_font_map_create_context(m_pFontMap);

    pango_context_set_language(m_pPangoContext,
            pango_language_from_string ("en_US"));
    pango_context_set_base_dir(m_pPangoContext, PANGO_DIRECTION_LTR);

    initFonts();

    string sOldLang = "";
    getEnv("LC_CTYPE", sOldLang);
    setEnv("LC_CTYPE", "en-us");
    pango_font_map_list_families(PANGO_FONT_MAP(m_pFontMap), &m_ppFontFamilies,
            &m_NumFontFamilies);
    setEnv("LC_CTYPE", sOldLang);
    for (int i = 0; i < m_NumFontFamilies; ++i) {
        m_sFonts.push_back(pango_font_family_get_name(m_ppFontFamilies[i]));
    }
    sort(m_sFonts.begin(), m_sFonts.end());
}

void TextEngine::deinit()
{
    g_object_unref(m_pFontMap);
    g_free(m_ppFontFamilies);
    g_object_unref(m_pPangoContext);
    m_sFonts.clear();
}

void TextEngine::addFontDir(const std::string& sDir)
{
    deinit();
    m_sFontDirs.push_back(sDir);
    init();
}

PangoContext * TextEngine::getPangoContext()
{
    return m_pPangoContext;
}

const vector<string>& TextEngine::getFontFamilies()
{
    return m_sFonts;
}

const vector<string>& TextEngine::getFontVariants(const string& sFontName)
{
    PangoFontFamily * pCurFamily = getFontFamily(sFontName);
    PangoFontFace ** ppFaces;
    int numFaces;
    pango_font_family_list_faces (pCurFamily, &ppFaces, &numFaces);
    static vector<string> sVariants;
    for (int i = 0; i < numFaces; ++i) {
        sVariants.push_back(pango_font_face_get_face_name(ppFaces[i]));
    }
    g_free(ppFaces);
    return sVariants;
}

PangoFontDescription * TextEngine::getFontDescription(const string& sFamily,
        const string& sVariant)
{
    PangoFontDescription* pDescription;
    FontDescriptionCache::iterator it;
    it = m_FontDescriptionCache.find(pair<string, string>(sFamily, sVariant));
    if (it == m_FontDescriptionCache.end()) {
        PangoFontFamily * pFamily;
        bool bFamilyFound = true;
        try {
            pFamily = getFontFamily(sFamily);
        } catch (Exception&) {
            if (m_sFontsNotFound.find(sFamily) == m_sFontsNotFound.end()) {
                AVG_TRACE(Logger::WARNING, "Could not find font face " << sFamily <<
                        ". Using sans instead.");
                m_sFontsNotFound.insert(sFamily);
            }
            bFamilyFound = false;
            pFamily = getFontFamily("sans");
        }
        PangoFontFace ** ppFaces;
        int numFaces;
        pango_font_family_list_faces(pFamily, &ppFaces, &numFaces);
        PangoFontFace * pFace = 0;
        if (sVariant == "") {
            pFace = ppFaces[0];
        } else {
            for (int i = 0; i < numFaces; ++i) {
                if (equalIgnoreCase(pango_font_face_get_face_name(ppFaces[i]), sVariant)) {
                    pFace = ppFaces[i];
                }
            }
        }
        if (!pFace) {
            pFace = ppFaces[0];
            if (bFamilyFound) {
                pair<string, string> variant(sFamily, sVariant);
                if (m_VariantsNotFound.find(variant) == m_VariantsNotFound.end()) {
                    m_VariantsNotFound.insert(variant);
                    AVG_TRACE(Logger::WARNING, "Could not find font variant "
                            << sFamily << ":" << sVariant << ". Using " <<
                            pango_font_face_get_face_name(pFace) << " instead.");
                }
            }
        }
        g_free(ppFaces);
        pDescription = pango_font_face_describe(pFace);
        m_FontDescriptionCache[pair<string, string>(sFamily, sVariant)] =
                pDescription;
    } else {
        pDescription = it->second;
    }
    return pango_font_description_copy(pDescription);
}

void GLibLogFunc(const gchar *log_domain, GLogLevelFlags log_level,
        const gchar *message, gpointer unused_data)
{
#ifndef WIN32
    string s = "Pango ";
    if (log_level & G_LOG_LEVEL_ERROR) {
        s += "error: ";
    } else if (log_level & G_LOG_LEVEL_CRITICAL) {
        s += string("critical: ")+message;
        AVG_TRACE(Logger::ERROR, s);
        AVG_ASSERT(false);
    } else if (log_level & G_LOG_LEVEL_WARNING) {
        s += "warning: ";
    } else if (log_level & G_LOG_LEVEL_MESSAGE) {
        s += "message: ";
    } else if (log_level & G_LOG_LEVEL_INFO) {
        s += "info: ";
    } else if (log_level & G_LOG_LEVEL_DEBUG) {
        s += "debug: ";
    }
    s += message;
    AVG_TRACE(Logger::WARNING, s);
#endif
}

void TextEngine::initFonts()
{
    std::vector<std::string> fontConfPathPrefixList;
#ifndef WIN32
    fontConfPathPrefixList.push_back("/");
    fontConfPathPrefixList.push_back("/usr/local/");
    fontConfPathPrefixList.push_back("/opt/local/");
#endif
    fontConfPathPrefixList.push_back(getAvgLibPath());

    std::string sFontConfPath;
    for (size_t i = 0; i < fontConfPathPrefixList.size(); ++i) {
        sFontConfPath = fontConfPathPrefixList[i] + "etc/fonts/fonts.conf";
        if (fileExists(sFontConfPath)) {
            break;
        }
    }

    FcConfig * pConfig = FcConfigCreate();
    int ok = (int)FcConfigParseAndLoad(pConfig,
            (const FcChar8 *)(sFontConfPath.c_str()), true);
    checkFontError(ok, string("Font error: could not load config file ")+sFontConfPath);
    ok = (int)FcConfigBuildFonts(pConfig);
    checkFontError(ok, string("Font error: FcConfigBuildFonts failed."));
    ok = (int)FcConfigSetCurrent(pConfig);
    checkFontError(ok, string("Font error: FcConfigSetCurrent failed."));
    for(std::vector<std::string>::const_iterator it = m_sFontDirs.begin();
            it != m_sFontDirs.end(); ++it)
    {
        ok = (int)FcConfigAppFontAddDir(pConfig, (const FcChar8 *)it->c_str());
        checkFontError(ok, string("Font error: FcConfigAppFontAddDir("
                    + *it + ") failed."));
    }
    /*
       FcStrList * pCacheDirs = FcConfigGetCacheDirs(pConfig);
       FcChar8 * pDir;
       do {
       pDir = FcStrListNext(pCacheDirs);
       if (pDir) {
       cerr << pDir << endl;
       }
       } while (pDir);
     */
    g_log_set_default_handler(GLibLogFunc, 0);
}

PangoFontFamily * TextEngine::getFontFamily(const string& sFamily)
{
    PangoFontFamily * pFamily = 0;
    AVG_ASSERT(m_NumFontFamilies != 0);
    for (int i=0; i<m_NumFontFamilies; ++i) {
        if (equalIgnoreCase(pango_font_family_get_name(m_ppFontFamilies[i]), sFamily)) {
            pFamily = m_ppFontFamilies[i];
        }
    }
    if (!pFamily) {
        throw(Exception(AVG_ERR_INVALID_ARGS,
                "getFontFamily: Font family "+sFamily+" not found."));
    }
    return pFamily;
}

void TextEngine::checkFontError(int ok, const string& sMsg)
{
    if (ok == 0) {
        throw Exception(AVG_ERR_FONT_INIT_FAILED, sMsg);
    }
}

}
<commit_msg>Fixed Pango deprecation warnings.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2011 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "TextEngine.h"

#include "../base/Logger.h"
#include "../base/OSHelper.h"
#include "../base/Exception.h"
#include "../base/FileHelper.h"
#include "../base/StringHelper.h"

#include <algorithm>

namespace avg {

using namespace std;

static void
text_subst_func_hint(FcPattern *pattern, gpointer data)
{
    FcPatternAddBool(pattern, FC_HINTING, true);
    FcPatternAddInteger(pattern, FC_HINT_STYLE, FC_HINT_MEDIUM);
    FcPatternAddInteger(pattern, FC_RGBA, FC_RGBA_NONE);
    FcPatternAddBool(pattern, FC_ANTIALIAS, true);
}

static void
text_subst_func_nohint(FcPattern *pattern, gpointer data)
{
    FcPatternAddBool(pattern, FC_HINTING, false);
    FcPatternAddBool(pattern, FC_AUTOHINT, false);
    FcPatternAddInteger(pattern, FC_HINT_STYLE, FC_HINT_NONE);
    FcPatternAddInteger(pattern, FC_RGBA, FC_RGBA_NONE);
    FcPatternAddBool(pattern, FC_ANTIALIAS, true);
}

TextEngine& TextEngine::get(bool bHint)
{
    if (bHint) {
        static TextEngine s_Instance(true);
        return s_Instance;
    } else {
        static TextEngine s_Instance(false);
        return s_Instance;
    }
}

TextEngine::TextEngine(bool bHint)
    : m_bHint(bHint)
{
    m_sFontDirs.push_back("fonts/");
    init();
}

TextEngine::~TextEngine()
{
    deinit();
}

void TextEngine::init()
{
    m_pFontMap = PANGO_FT2_FONT_MAP(pango_ft2_font_map_new());
    pango_ft2_font_map_set_resolution(m_pFontMap, 72, 72);
    if (m_bHint) {
        pango_ft2_font_map_set_default_substitute(m_pFontMap, text_subst_func_hint,
                0, 0);
    } else {
        pango_ft2_font_map_set_default_substitute(m_pFontMap, text_subst_func_nohint,
                0, 0);
    }
#if PANGO_VERSION > PANGO_VERSION_ENCODE(1,22,0)
    m_pPangoContext = pango_font_map_create_context(PANGO_FONT_MAP(m_pFontMap));
#else
    m_pPangoContext = pango_ft2_font_map_create_context(m_pFontMap);
#endif

    pango_context_set_language(m_pPangoContext,
            pango_language_from_string ("en_US"));
    pango_context_set_base_dir(m_pPangoContext, PANGO_DIRECTION_LTR);

    initFonts();

    string sOldLang = "";
    getEnv("LC_CTYPE", sOldLang);
    setEnv("LC_CTYPE", "en-us");
    pango_font_map_list_families(PANGO_FONT_MAP(m_pFontMap), &m_ppFontFamilies,
            &m_NumFontFamilies);
    setEnv("LC_CTYPE", sOldLang);
    for (int i = 0; i < m_NumFontFamilies; ++i) {
        m_sFonts.push_back(pango_font_family_get_name(m_ppFontFamilies[i]));
    }
    sort(m_sFonts.begin(), m_sFonts.end());
}

void TextEngine::deinit()
{
    g_object_unref(m_pFontMap);
    g_free(m_ppFontFamilies);
    g_object_unref(m_pPangoContext);
    m_sFonts.clear();
}

void TextEngine::addFontDir(const std::string& sDir)
{
    deinit();
    m_sFontDirs.push_back(sDir);
    init();
}

PangoContext * TextEngine::getPangoContext()
{
    return m_pPangoContext;
}

const vector<string>& TextEngine::getFontFamilies()
{
    return m_sFonts;
}

const vector<string>& TextEngine::getFontVariants(const string& sFontName)
{
    PangoFontFamily * pCurFamily = getFontFamily(sFontName);
    PangoFontFace ** ppFaces;
    int numFaces;
    pango_font_family_list_faces (pCurFamily, &ppFaces, &numFaces);
    static vector<string> sVariants;
    for (int i = 0; i < numFaces; ++i) {
        sVariants.push_back(pango_font_face_get_face_name(ppFaces[i]));
    }
    g_free(ppFaces);
    return sVariants;
}

PangoFontDescription * TextEngine::getFontDescription(const string& sFamily,
        const string& sVariant)
{
    PangoFontDescription* pDescription;
    FontDescriptionCache::iterator it;
    it = m_FontDescriptionCache.find(pair<string, string>(sFamily, sVariant));
    if (it == m_FontDescriptionCache.end()) {
        PangoFontFamily * pFamily;
        bool bFamilyFound = true;
        try {
            pFamily = getFontFamily(sFamily);
        } catch (Exception&) {
            if (m_sFontsNotFound.find(sFamily) == m_sFontsNotFound.end()) {
                AVG_TRACE(Logger::WARNING, "Could not find font face " << sFamily <<
                        ". Using sans instead.");
                m_sFontsNotFound.insert(sFamily);
            }
            bFamilyFound = false;
            pFamily = getFontFamily("sans");
        }
        PangoFontFace ** ppFaces;
        int numFaces;
        pango_font_family_list_faces(pFamily, &ppFaces, &numFaces);
        PangoFontFace * pFace = 0;
        if (sVariant == "") {
            pFace = ppFaces[0];
        } else {
            for (int i = 0; i < numFaces; ++i) {
                if (equalIgnoreCase(pango_font_face_get_face_name(ppFaces[i]), sVariant)) {
                    pFace = ppFaces[i];
                }
            }
        }
        if (!pFace) {
            pFace = ppFaces[0];
            if (bFamilyFound) {
                pair<string, string> variant(sFamily, sVariant);
                if (m_VariantsNotFound.find(variant) == m_VariantsNotFound.end()) {
                    m_VariantsNotFound.insert(variant);
                    AVG_TRACE(Logger::WARNING, "Could not find font variant "
                            << sFamily << ":" << sVariant << ". Using " <<
                            pango_font_face_get_face_name(pFace) << " instead.");
                }
            }
        }
        g_free(ppFaces);
        pDescription = pango_font_face_describe(pFace);
        m_FontDescriptionCache[pair<string, string>(sFamily, sVariant)] =
                pDescription;
    } else {
        pDescription = it->second;
    }
    return pango_font_description_copy(pDescription);
}

void GLibLogFunc(const gchar *log_domain, GLogLevelFlags log_level,
        const gchar *message, gpointer unused_data)
{
#ifndef WIN32
    string s = "Pango ";
    if (log_level & G_LOG_LEVEL_ERROR) {
        s += "error: ";
    } else if (log_level & G_LOG_LEVEL_CRITICAL) {
        s += string("critical: ")+message;
        AVG_TRACE(Logger::ERROR, s);
        AVG_ASSERT(false);
    } else if (log_level & G_LOG_LEVEL_WARNING) {
        s += "warning: ";
    } else if (log_level & G_LOG_LEVEL_MESSAGE) {
        s += "message: ";
    } else if (log_level & G_LOG_LEVEL_INFO) {
        s += "info: ";
    } else if (log_level & G_LOG_LEVEL_DEBUG) {
        s += "debug: ";
    }
    s += message;
    AVG_TRACE(Logger::WARNING, s);
#endif
}

void TextEngine::initFonts()
{
    std::vector<std::string> fontConfPathPrefixList;
#ifndef WIN32
    fontConfPathPrefixList.push_back("/");
    fontConfPathPrefixList.push_back("/usr/local/");
    fontConfPathPrefixList.push_back("/opt/local/");
#endif
    fontConfPathPrefixList.push_back(getAvgLibPath());

    std::string sFontConfPath;
    for (size_t i = 0; i < fontConfPathPrefixList.size(); ++i) {
        sFontConfPath = fontConfPathPrefixList[i] + "etc/fonts/fonts.conf";
        if (fileExists(sFontConfPath)) {
            break;
        }
    }

    FcConfig * pConfig = FcConfigCreate();
    int ok = (int)FcConfigParseAndLoad(pConfig,
            (const FcChar8 *)(sFontConfPath.c_str()), true);
    checkFontError(ok, string("Font error: could not load config file ")+sFontConfPath);
    ok = (int)FcConfigBuildFonts(pConfig);
    checkFontError(ok, string("Font error: FcConfigBuildFonts failed."));
    ok = (int)FcConfigSetCurrent(pConfig);
    checkFontError(ok, string("Font error: FcConfigSetCurrent failed."));
    for(std::vector<std::string>::const_iterator it = m_sFontDirs.begin();
            it != m_sFontDirs.end(); ++it)
    {
        ok = (int)FcConfigAppFontAddDir(pConfig, (const FcChar8 *)it->c_str());
        checkFontError(ok, string("Font error: FcConfigAppFontAddDir("
                    + *it + ") failed."));
    }
    /*
       FcStrList * pCacheDirs = FcConfigGetCacheDirs(pConfig);
       FcChar8 * pDir;
       do {
       pDir = FcStrListNext(pCacheDirs);
       if (pDir) {
       cerr << pDir << endl;
       }
       } while (pDir);
     */
    g_log_set_default_handler(GLibLogFunc, 0);
}

PangoFontFamily * TextEngine::getFontFamily(const string& sFamily)
{
    PangoFontFamily * pFamily = 0;
    AVG_ASSERT(m_NumFontFamilies != 0);
    for (int i=0; i<m_NumFontFamilies; ++i) {
        if (equalIgnoreCase(pango_font_family_get_name(m_ppFontFamilies[i]), sFamily)) {
            pFamily = m_ppFontFamilies[i];
        }
    }
    if (!pFamily) {
        throw(Exception(AVG_ERR_INVALID_ARGS,
                "getFontFamily: Font family "+sFamily+" not found."));
    }
    return pFamily;
}

void TextEngine::checkFontError(int ok, const string& sMsg)
{
    if (ok == 0) {
        throw Exception(AVG_ERR_FONT_INIT_FAILED, sMsg);
    }
}

}
<|endoftext|>


<commit_before>// -*- mode:c++;coding:utf-8; -*- vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:enc=utf-8:
/*
The MIT License

Copyright (c) 2008, 2009 Flusspferd contributors (see "CONTRIBUTORS" or
                                       http://flusspferd.org/contributors.txt)

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

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

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

#include "flusspferd/create.hpp"
#include "flusspferd/tracer.hpp"
#include "flusspferd/modules.hpp"
#include "flusspferd/security.hpp"
#include "flusspferd/class_description.hpp"

#include <sstream>
#include <curl/curl.h>

using namespace flusspferd;

namespace {
  long global_init(long flags) {
    return curl_global_init(flags);
  }

  FLUSSPFERD_CLASS_DESCRIPTION
  (
   Easy,
   (constructor_name, "Easy")
   (full_name, "cURL.Easy")
   (methods,
    ("cleanup",  bind, cleanup)
    ("perform",  bind, perform)
    ("reset",    bind, reset)
    ("escape",   bind, escape)
    ("unescape", bind, unescape)
    ("setopt",   bind, setopt)
    ("valid",    bind, valid))
   )
  {
    CURL *handle;

		object writecallback;
		static size_t writefunction(void *ptr, size_t size, size_t nmemb, void *stream) {
			assert(stream);
			Easy &self = *reinterpret_cast<Easy*>(stream);
			//			self.writecallback.call();
			// TODO ...
			return size * nmemb;
		}
	protected:
		void trace(flusspferd::tracer &trc) {
			trc("writecallback", writecallback);
		}

  public:
    CURL *data() { return handle; }
    bool valid() { return handle; }
    CURL *get() {
      if(!handle) {
        throw flusspferd::exception("CURL handle not valid!");
      }
      return handle;
    }

    Easy(flusspferd::object const &self, flusspferd::call_context&)
      : base_type(self), handle(curl_easy_init())
    {
      if(!handle) {
        throw flusspferd::exception("curl_easy_init");
      }
    }

    Easy(flusspferd::object const &self, CURL *hnd)
      : base_type(self), handle(hnd)
    {
      assert(handle);
    }

    void cleanup() {
      if(handle) {
        curl_easy_cleanup(handle);
        handle = 0x0;
      }
    }
    ~Easy() { cleanup(); }

    int perform() {
      return curl_easy_perform(get());
    }

    void reset() {
      curl_easy_reset(get());
    }

    std::string unescape(char const *input) {
      int len;
      char *uesc = curl_easy_unescape(get(), input, 0, &len);
      if(!uesc) {
        throw flusspferd::exception("curl_easy_escape");
      }
      std::string ret(uesc, len);
      curl_free(uesc);
      return ret;
    }

    std::string escape(char const *input) {
      char *esc = curl_easy_escape(get(), input, 0);
      if(!esc) {
        throw flusspferd::exception("curl_easy_escape");
      }
      std::string ret(esc);
      curl_free(esc);
      return ret;
    }

#define OPT_NUMBER(what)                                                \
    case what :                                                         \
      if(x.arg.size() != 2) {                                           \
        std::stringstream ss;                                           \
        ss << "curl_easy_setopt: Expected two arguments. Got (" << x.arg.size() << ')'; \
        throw flusspferd::exception(ss.str());                          \
      }                                                                 \
      int res = curl_easy_setopt(get(), what , x.arg[1].to_number());		\
			if(res != 0) {																										\
				throw flusspferd::exception(std::string("curl_easy_setopt: ") +	\
																		curl_easy_strerror(res));						\
			}																																	\
      break;                                                            \
      /**/

#define OPT_FUNCTION(what, data, callback, func)

    void setopt(flusspferd::call_context &x) {
      int what = x.arg.front().to_number();
      switch(what) {
        //OPT_NUMBER(CURLOPT_HEADER)
      case CURLOPT_WRITEFUNCTION: {
				// TODO reset to default function (0x0 parameter!)
				if(!x.arg[1].is_object()) {
					throw flusspferd::exception("curl_easy_setopt: expected a function as second parameter!");
				}
				writecallback = x.arg[1].to_object();
        int res = curl_easy_setopt(get(), CURLOPT_WRITEDATA, this);
        if(res != 0) {
          throw flusspferd::exception(std::string("curl_easy_setopt: ") +
																			curl_easy_strerror((CURLcode)res));
        }
				res = curl_easy_setopt(get(), CURLOPT_WRITEFUNCTION, writefunction);
				if(res != 0) {
					throw flusspferd::exception(std::string("curl_easy_setopt: ") +
																			curl_easy_strerror((CURLcode)res));
				}
			}
      default: {
        std::stringstream ss;
        ss << "curl_easy_setopt unkown or unsupported option (" << what << ')';
        throw flusspferd::exception(ss.str());
      }
      };
    }

#undef OPT_FUNCTION
#undef OPT_NUMBER

    static Easy &create(CURL *hnd) {
      return flusspferd::create_native_object<Easy>(object(), hnd);
    }
  };

  Easy &wrap(CURL *hnd) {
    return Easy::create(hnd);
  }
  CURL *unwrap(Easy &c) {
    return c.data();
  }

  FLUSSPFERD_LOADER_SIMPLE(cURL) {
    local_root_scope scope;

    cURL.define_property("GLOBAL_ALL", value(CURL_GLOBAL_ALL),
                         read_only_property | permanent_property);
    cURL.define_property("GLOBAL_SSL", value(CURL_GLOBAL_SSL),
                         read_only_property | permanent_property);
    cURL.define_property("GLOBAL_WIN32", value(CURL_GLOBAL_WIN32),
                         read_only_property | permanent_property);
    cURL.define_property("GLOBAL_NOTHING", value(CURL_GLOBAL_NOTHING),
                         read_only_property | permanent_property);
    create_native_function(cURL, "globalInit", &global_init);
    cURL.define_property("version", value(curl_version()),
                         read_only_property | permanent_property);

    load_class<Easy>(cURL);
    cURL.define_property("OPT_HEADER", value((int)CURLOPT_HEADER),
                         read_only_property | permanent_property);
		cURL.define_property("OPT_WRITEFUNCTION", value((int)CURLOPT_WRITEFUNCTION),
                         read_only_property | permanent_property);
  }
}
<commit_msg>curl: global_init now throws an exception instead of returning the error code<commit_after>// -*- mode:c++;coding:utf-8; -*- vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:enc=utf-8:
/*
The MIT License

Copyright (c) 2008, 2009 Flusspferd contributors (see "CONTRIBUTORS" or
                                       http://flusspferd.org/contributors.txt)

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

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

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

#include "flusspferd/create.hpp"
#include "flusspferd/tracer.hpp"
#include "flusspferd/modules.hpp"
#include "flusspferd/security.hpp"
#include "flusspferd/class_description.hpp"

#include <sstream>
#include <curl/curl.h>

using namespace flusspferd;

namespace {
  void global_init(long flags) {
    CURLcode ret = curl_global_init(flags);
		if(ret != 0) {
			throw flusspferd::exception(std::string("curl_global_init: ") +
																	curl_easy_strerror(ret));
		}
  }

  FLUSSPFERD_CLASS_DESCRIPTION
  (
   Easy,
   (constructor_name, "Easy")
   (full_name, "cURL.Easy")
   (methods,
    ("cleanup",  bind, cleanup)
    ("perform",  bind, perform)
    ("reset",    bind, reset)
    ("escape",   bind, escape)
    ("unescape", bind, unescape)
    ("setopt",   bind, setopt)
    ("valid",    bind, valid))
   )
  {
    CURL *handle;

		object writecallback;
		static size_t writefunction(void *ptr, size_t size, size_t nmemb, void *stream) {
			assert(stream);
			Easy &self = *reinterpret_cast<Easy*>(stream);
			//			self.writecallback.call();
			// TODO ...
			return size * nmemb;
		}
	protected:
		void trace(flusspferd::tracer &trc) {
			trc("writecallback", writecallback);
		}

  public:
    CURL *data() { return handle; }
    bool valid() { return handle; }
    CURL *get() {
      if(!handle) {
        throw flusspferd::exception("CURL handle not valid!");
      }
      return handle;
    }

    Easy(flusspferd::object const &self, flusspferd::call_context&)
      : base_type(self), handle(curl_easy_init())
    {
      if(!handle) {
        throw flusspferd::exception("curl_easy_init");
      }
    }

    Easy(flusspferd::object const &self, CURL *hnd)
      : base_type(self), handle(hnd)
    {
      assert(handle);
    }

    void cleanup() {
      if(handle) {
        curl_easy_cleanup(handle);
        handle = 0x0;
      }
    }
    ~Easy() { cleanup(); }

    int perform() {
      return curl_easy_perform(get());
    }

    void reset() {
      curl_easy_reset(get());
    }

    std::string unescape(char const *input) {
      int len;
      char *uesc = curl_easy_unescape(get(), input, 0, &len);
      if(!uesc) {
        throw flusspferd::exception("curl_easy_escape");
      }
      std::string ret(uesc, len);
      curl_free(uesc);
      return ret;
    }

    std::string escape(char const *input) {
      char *esc = curl_easy_escape(get(), input, 0);
      if(!esc) {
        throw flusspferd::exception("curl_easy_escape");
      }
      std::string ret(esc);
      curl_free(esc);
      return ret;
    }

#define OPT_NUMBER(what)                                                \
    case what :                                                         \
      if(x.arg.size() != 2) {                                           \
        std::stringstream ss;                                           \
        ss << "curl_easy_setopt: Expected two arguments. Got (" << x.arg.size() << ')'; \
        throw flusspferd::exception(ss.str());                          \
      }                                                                 \
      int res = curl_easy_setopt(get(), what , x.arg[1].to_number());		\
			if(res != 0) {																										\
				throw flusspferd::exception(std::string("curl_easy_setopt: ") +	\
																		curl_easy_strerror(res));						\
			}																																	\
      break;                                                            \
      /**/

#define OPT_FUNCTION(what, data, callback, func)

    void setopt(flusspferd::call_context &x) {
      int what = x.arg.front().to_number();
      switch(what) {
        //OPT_NUMBER(CURLOPT_HEADER)
      case CURLOPT_WRITEFUNCTION: {
				// TODO reset to default function (0x0 parameter!)
				if(!x.arg[1].is_object()) {
					throw flusspferd::exception("curl_easy_setopt: expected a function as second parameter!");
				}
				writecallback = x.arg[1].to_object();
        int res = curl_easy_setopt(get(), CURLOPT_WRITEDATA, this);
        if(res != 0) {
          throw flusspferd::exception(std::string("curl_easy_setopt: ") +
																			curl_easy_strerror((CURLcode)res));
        }
				res = curl_easy_setopt(get(), CURLOPT_WRITEFUNCTION, writefunction);
				if(res != 0) {
					throw flusspferd::exception(std::string("curl_easy_setopt: ") +
																			curl_easy_strerror((CURLcode)res));
				}
			}
      default: {
        std::stringstream ss;
        ss << "curl_easy_setopt unkown or unsupported option (" << what << ')';
        throw flusspferd::exception(ss.str());
      }
      };
    }

#undef OPT_FUNCTION
#undef OPT_NUMBER

    static Easy &create(CURL *hnd) {
      return flusspferd::create_native_object<Easy>(object(), hnd);
    }
  };

  Easy &wrap(CURL *hnd) {
    return Easy::create(hnd);
  }
  CURL *unwrap(Easy &c) {
    return c.data();
  }

  FLUSSPFERD_LOADER_SIMPLE(cURL) {
    local_root_scope scope;

    cURL.define_property("GLOBAL_ALL", value(CURL_GLOBAL_ALL),
                         read_only_property | permanent_property);
    cURL.define_property("GLOBAL_SSL", value(CURL_GLOBAL_SSL),
                         read_only_property | permanent_property);
    cURL.define_property("GLOBAL_WIN32", value(CURL_GLOBAL_WIN32),
                         read_only_property | permanent_property);
    cURL.define_property("GLOBAL_NOTHING", value(CURL_GLOBAL_NOTHING),
                         read_only_property | permanent_property);
    create_native_function(cURL, "globalInit", &global_init);
    cURL.define_property("version", value(curl_version()),
                         read_only_property | permanent_property);

    load_class<Easy>(cURL);
    cURL.define_property("OPT_HEADER", value((int)CURLOPT_HEADER),
                         read_only_property | permanent_property);
		cURL.define_property("OPT_WRITEFUNCTION", value((int)CURLOPT_WRITEFUNCTION),
                         read_only_property | permanent_property);
  }
}
<|endoftext|>


<commit_before>/***************************************************************************
            dump.c  -  Skeleton of backends to access the Key Database
                             -------------------
    begin                : Mon May  3 15:22:44 CEST 2010
    copyright            : by Markus Raab
    email                : elektra@markus-raab.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the BSD License (revised).                      *
 *                                                                         *
 ***************************************************************************/

#include "dump.hpp"

using namespace ckdb;

#include <kdberrors.h>

namespace dump
{

int serialize(std::ostream &os, ckdb::Key *, ckdb::KeySet *ks)
{
	ckdb::Key *cur;

	os << "kdbOpen 1" << std::endl;

	os << "ksNew " << ckdb::ksGetSize(ks) << std::endl;

	ckdb::KeySet *metacopies = ckdb::ksNew(0);

	ksRewind(ks);
	while ((cur = ksNext(ks)) != 0)
	{
		size_t namesize = ckdb::keyGetNameSize(cur);
		size_t valuesize = ckdb::keyGetValueSize(cur);
		os << "keyNew " << namesize
		   << " " << valuesize << std::endl;
		os.write(ckdb::keyName(cur), namesize);
		os.write(static_cast<const char*>(ckdb::keyValue(cur)), valuesize);
		os << std::endl;

		const ckdb::Key *meta;
		ckdb::keyRewindMeta(cur);
		while ((meta = ckdb::keyNextMeta(cur)) != 0)
		{
			std::stringstream ss;
			ss << "user/" << meta; // use the address of pointer as name

			ckdb::Key *search = ckdb::keyNew(
					ss.str().c_str(),
					KEY_END);
			ckdb::Key *ret = ksLookup(metacopies, search, 0);

			if (!ret)
			{
				/* This meta key was not serialized up to now */
				size_t metanamesize = ckdb::keyGetNameSize(meta);
				size_t metavaluesize = ckdb::keyGetValueSize(meta);

				os << "keyMeta " << metanamesize
				   << " " << metavaluesize << std::endl;
				os.write (ckdb::keyName(meta), metanamesize);
				os.write (static_cast<const char*>(ckdb::keyValue(meta)), metavaluesize);
				os << std::endl;

				std::stringstream ssv;
				ssv << namesize << " " << metanamesize << std::endl;
				ssv.write(ckdb::keyName(cur), namesize);
				ssv.write (ckdb::keyName(meta), metanamesize);
				ckdb::keySetRaw(search, ssv.str().c_str(), ssv.str().size());

				ksAppendKey(metacopies, search);
			} else {
				/* Meta key already serialized, write out a reference to it */
				keyDel (search);

				os << "keyCopyMeta ";
				os.write(static_cast<const char*>(ckdb::keyValue(ret)), ckdb::keyGetValueSize(ret));
				os << std::endl;
			}
		}
		os << "keyEnd" << std::endl;
	}
	os << "ksEnd" << std::endl;

	ksDel (metacopies);

	return 1;
}

int unserialize(std::istream &is, ckdb::Key *errorKey, ckdb::KeySet *ks)
{
	ckdb::Key *cur = 0;

	std::vector<char> namebuffer(4048);
	std::vector<char> valuebuffer(4048);
	std::string line;
	std::string command;
	size_t nrKeys;
	size_t namesize;
	size_t valuesize;

	while(std::getline (is, line))
	{
		std::stringstream ss (line);
		ss >> command;

		if (command == "kdbOpen")
		{
			std::string version;
			ss >> version;
			if (version != "1")
			{
				ELEKTRA_SET_ERROR (50, errorKey, version.c_str());
				return -1;
			}
		}
		else if (command == "ksNew")
		{
			ss >> nrKeys;

			ksClear(ks);
		}
		else if (command == "keyNew")
		{
			cur = ckdb::keyNew(0);

			ss >> namesize;
			ss >> valuesize;

			if (namesize > namebuffer.size()) namebuffer.resize(namesize);
			is.read(&namebuffer[0], namesize);
			namebuffer[namesize] = 0;
			ckdb::keySetName(cur, &namebuffer[0]);

			if (valuesize > valuebuffer.size()) valuebuffer.resize(valuesize);
			is.read(&valuebuffer[0], valuesize);
			ckdb::keySetRaw (cur, &valuebuffer[0], valuesize);
			std::getline (is, line);
		}
		else if (command == "keyMeta")
		{
			ss >> namesize;
			ss >> valuesize;

			if (namesize > namebuffer.size()) namebuffer.resize(namesize);
			is.read(&namebuffer[0], namesize);
			namebuffer[namesize] = 0;

			if (valuesize > valuebuffer.size()) valuebuffer.resize(valuesize);
			is.read(&valuebuffer[0], valuesize);

			keySetMeta (cur, &namebuffer[0], &valuebuffer[0]);
			std::getline (is, line);
		}
		else if (command == "keyCopyMeta")
		{
			ss >> namesize;
			ss >> valuesize;

			if (namesize > namebuffer.size()) namebuffer.resize(namesize);
			is.read(&namebuffer[0], namesize);
			namebuffer[namesize] = 0;

			if (valuesize > valuebuffer.size()) valuebuffer.resize(valuesize);
			is.read(&valuebuffer[0], valuesize);

			ckdb::Key * search = ckdb::ksLookupByName(ks, &namebuffer[0], 0);
			ckdb::keyCopyMeta(cur, search, &valuebuffer[0]);
			std::getline (is, line);
		}
		else if (command == "keyEnd")
		{
			ckdb::ksAppendKey(ks, cur);
			cur = 0;
		}
		else if (command == "ksEnd")
		{
			break;
		} else {
			ELEKTRA_SET_ERROR (49, errorKey, command.c_str());
			return -1;
		}
	}
	return 1;
}

} // namespace dump

extern "C" {

int elektraDumpGet(ckdb::Plugin *, ckdb::KeySet *returned, ckdb::Key *parentKey)
{
	Key *root = ckdb::keyNew("system/elektra/modules/dump", KEY_END);
	if (keyRel(root, parentKey) >= 0)
	{
		keyDel (root);
		void (*get) (void) = (void (*) (void)) elektraDumpGet;
		void (*set) (void) = (void (*) (void)) elektraDumpSet;
		void (*serialize) (void) = (void (*) (void)) dump::serialize;
		void (*unserialize) (void) = (void (*) (void)) dump::unserialize;
		KeySet *n = ksNew(50,
			keyNew ("system/elektra/modules/dump",
				KEY_VALUE, "dump plugin waits for your orders", KEY_END),
			keyNew ("system/elektra/modules/dump/exports", KEY_END),
			keyNew ("system/elektra/modules/dump/exports/get",
				KEY_SIZE, sizeof (get),
				KEY_BINARY,
				KEY_VALUE, &get, KEY_END),
			keyNew ("system/elektra/modules/dump/exports/set",
				KEY_SIZE, sizeof (set),
				KEY_BINARY,
				KEY_VALUE, &set, KEY_END),
			keyNew ("system/elektra/modules/dump/exports/serialize",
				KEY_SIZE, sizeof (serialize),
				KEY_BINARY,
				KEY_VALUE, &serialize, KEY_END),
			keyNew ("system/elektra/modules/dump/exports/unserialize",
				KEY_SIZE, sizeof (unserialize),
				KEY_BINARY,
				KEY_VALUE, &unserialize, KEY_END),
			keyNew ("system/elektra/modules/dump/infos",
				KEY_VALUE, "All information you want to know", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/author",
				KEY_VALUE, "Markus Raab <elektra@markus-raab.org>", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/licence",
				KEY_VALUE, "BSD", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/description",
				KEY_VALUE, "Dumps complete Elektra Semantics", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/provides",
				KEY_VALUE, "storage", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/placements",
				KEY_VALUE, "getstorage setstorage", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/needs",
				KEY_VALUE, "", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/version",
				KEY_VALUE, PLUGINVERSION, KEY_END),
			KS_END);
		ksAppend(returned, n);
		ksDel (n);
		return 1;
	}
	keyDel (root);
	std::ifstream ofs(keyString(parentKey), std::ios::binary);
	if (!ofs.is_open()) return 0;

	return dump::unserialize (ofs, parentKey, returned);
}

int elektraDumpSet(ckdb::Plugin *, ckdb::KeySet *returned, ckdb::Key *parentKey)
{
	std::ofstream ofs(keyString(parentKey), std::ios::binary);
	if (!ofs.is_open())
	{
		ELEKTRA_SET_ERROR (9, parentKey, "file is not open in dump");
		return -1;
	}

	return dump::serialize (ofs, parentKey, returned);
}

ckdb::Plugin *ELEKTRA_PLUGIN_EXPORT(dump)
{
	return elektraPluginExport("dump",
		ELEKTRA_PLUGIN_GET,		&elektraDumpGet,
		ELEKTRA_PLUGIN_SET,		&elektraDumpSet,
		ELEKTRA_PLUGIN_END);
}

} // extern C

<commit_msg>improve dump contract's docu<commit_after>/***************************************************************************
            dump.c  -  Skeleton of backends to access the Key Database
                             -------------------
    begin                : Mon May  3 15:22:44 CEST 2010
    copyright            : by Markus Raab
    email                : elektra@markus-raab.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the BSD License (revised).                      *
 *                                                                         *
 ***************************************************************************/

#include "dump.hpp"

using namespace ckdb;

#include <kdberrors.h>

namespace dump
{

int serialize(std::ostream &os, ckdb::Key *, ckdb::KeySet *ks)
{
	ckdb::Key *cur;

	os << "kdbOpen 1" << std::endl;

	os << "ksNew " << ckdb::ksGetSize(ks) << std::endl;

	ckdb::KeySet *metacopies = ckdb::ksNew(0);

	ksRewind(ks);
	while ((cur = ksNext(ks)) != 0)
	{
		size_t namesize = ckdb::keyGetNameSize(cur);
		size_t valuesize = ckdb::keyGetValueSize(cur);
		os << "keyNew " << namesize
		   << " " << valuesize << std::endl;
		os.write(ckdb::keyName(cur), namesize);
		os.write(static_cast<const char*>(ckdb::keyValue(cur)), valuesize);
		os << std::endl;

		const ckdb::Key *meta;
		ckdb::keyRewindMeta(cur);
		while ((meta = ckdb::keyNextMeta(cur)) != 0)
		{
			std::stringstream ss;
			ss << "user/" << meta; // use the address of pointer as name

			ckdb::Key *search = ckdb::keyNew(
					ss.str().c_str(),
					KEY_END);
			ckdb::Key *ret = ksLookup(metacopies, search, 0);

			if (!ret)
			{
				/* This meta key was not serialized up to now */
				size_t metanamesize = ckdb::keyGetNameSize(meta);
				size_t metavaluesize = ckdb::keyGetValueSize(meta);

				os << "keyMeta " << metanamesize
				   << " " << metavaluesize << std::endl;
				os.write (ckdb::keyName(meta), metanamesize);
				os.write (static_cast<const char*>(ckdb::keyValue(meta)), metavaluesize);
				os << std::endl;

				std::stringstream ssv;
				ssv << namesize << " " << metanamesize << std::endl;
				ssv.write(ckdb::keyName(cur), namesize);
				ssv.write (ckdb::keyName(meta), metanamesize);
				ckdb::keySetRaw(search, ssv.str().c_str(), ssv.str().size());

				ksAppendKey(metacopies, search);
			} else {
				/* Meta key already serialized, write out a reference to it */
				keyDel (search);

				os << "keyCopyMeta ";
				os.write(static_cast<const char*>(ckdb::keyValue(ret)), ckdb::keyGetValueSize(ret));
				os << std::endl;
			}
		}
		os << "keyEnd" << std::endl;
	}
	os << "ksEnd" << std::endl;

	ksDel (metacopies);

	return 1;
}

int unserialize(std::istream &is, ckdb::Key *errorKey, ckdb::KeySet *ks)
{
	ckdb::Key *cur = 0;

	std::vector<char> namebuffer(4048);
	std::vector<char> valuebuffer(4048);
	std::string line;
	std::string command;
	size_t nrKeys;
	size_t namesize;
	size_t valuesize;

	while(std::getline (is, line))
	{
		std::stringstream ss (line);
		ss >> command;

		if (command == "kdbOpen")
		{
			std::string version;
			ss >> version;
			if (version != "1")
			{
				ELEKTRA_SET_ERROR (50, errorKey, version.c_str());
				return -1;
			}
		}
		else if (command == "ksNew")
		{
			ss >> nrKeys;

			ksClear(ks);
		}
		else if (command == "keyNew")
		{
			cur = ckdb::keyNew(0);

			ss >> namesize;
			ss >> valuesize;

			if (namesize > namebuffer.size()) namebuffer.resize(namesize);
			is.read(&namebuffer[0], namesize);
			namebuffer[namesize] = 0;
			ckdb::keySetName(cur, &namebuffer[0]);

			if (valuesize > valuebuffer.size()) valuebuffer.resize(valuesize);
			is.read(&valuebuffer[0], valuesize);
			ckdb::keySetRaw (cur, &valuebuffer[0], valuesize);
			std::getline (is, line);
		}
		else if (command == "keyMeta")
		{
			ss >> namesize;
			ss >> valuesize;

			if (namesize > namebuffer.size()) namebuffer.resize(namesize);
			is.read(&namebuffer[0], namesize);
			namebuffer[namesize] = 0;

			if (valuesize > valuebuffer.size()) valuebuffer.resize(valuesize);
			is.read(&valuebuffer[0], valuesize);

			keySetMeta (cur, &namebuffer[0], &valuebuffer[0]);
			std::getline (is, line);
		}
		else if (command == "keyCopyMeta")
		{
			ss >> namesize;
			ss >> valuesize;

			if (namesize > namebuffer.size()) namebuffer.resize(namesize);
			is.read(&namebuffer[0], namesize);
			namebuffer[namesize] = 0;

			if (valuesize > valuebuffer.size()) valuebuffer.resize(valuesize);
			is.read(&valuebuffer[0], valuesize);

			ckdb::Key * search = ckdb::ksLookupByName(ks, &namebuffer[0], 0);
			ckdb::keyCopyMeta(cur, search, &valuebuffer[0]);
			std::getline (is, line);
		}
		else if (command == "keyEnd")
		{
			ckdb::ksAppendKey(ks, cur);
			cur = 0;
		}
		else if (command == "ksEnd")
		{
			break;
		} else {
			ELEKTRA_SET_ERROR (49, errorKey, command.c_str());
			return -1;
		}
	}
	return 1;
}

} // namespace dump

extern "C" {

int elektraDumpGet(ckdb::Plugin *, ckdb::KeySet *returned, ckdb::Key *parentKey)
{
	Key *root = ckdb::keyNew("system/elektra/modules/dump", KEY_END);
	if (keyRel(root, parentKey) >= 0)
	{
		keyDel (root);
		void (*get) (void) = (void (*) (void)) elektraDumpGet;
		void (*set) (void) = (void (*) (void)) elektraDumpSet;
		void (*serialize) (void) = (void (*) (void)) dump::serialize;
		void (*unserialize) (void) = (void (*) (void)) dump::unserialize;
		KeySet *n = ksNew(50,
			keyNew ("system/elektra/modules/dump",
				KEY_VALUE, "dump plugin waits for your orders", KEY_END),
			keyNew ("system/elektra/modules/dump/exports", KEY_END),
			keyNew ("system/elektra/modules/dump/exports/get",
				KEY_SIZE, sizeof (get),
				KEY_BINARY,
				KEY_VALUE, &get, KEY_END),
			keyNew ("system/elektra/modules/dump/exports/set",
				KEY_SIZE, sizeof (set),
				KEY_BINARY,
				KEY_VALUE, &set, KEY_END),
			keyNew ("system/elektra/modules/dump/exports/serialize",
				KEY_SIZE, sizeof (serialize),
				KEY_BINARY,
				KEY_VALUE, &serialize, KEY_END),
			keyNew ("system/elektra/modules/dump/exports/unserialize",
				KEY_SIZE, sizeof (unserialize),
				KEY_BINARY,
				KEY_VALUE, &unserialize, KEY_END),
			keyNew ("system/elektra/modules/dump/infos",
				KEY_VALUE, "Dumps into a format tailored to KeySet semantics", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/author",
				KEY_VALUE, "Markus Raab <elektra@markus-raab.org>", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/licence",
				KEY_VALUE, "BSD", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/description",
				KEY_VALUE, "Dumps complete KeySet Semantics", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/provides",
				KEY_VALUE, "storage", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/placements",
				KEY_VALUE, "getstorage setstorage", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/needs",
				KEY_VALUE, "", KEY_END),
			keyNew ("system/elektra/modules/dump/infos/version",
				KEY_VALUE, PLUGINVERSION, KEY_END),
			KS_END);
		ksAppend(returned, n);
		ksDel (n);
		return 1;
	}
	keyDel (root);
	std::ifstream ofs(keyString(parentKey), std::ios::binary);
	if (!ofs.is_open()) return 0;

	return dump::unserialize (ofs, parentKey, returned);
}

int elektraDumpSet(ckdb::Plugin *, ckdb::KeySet *returned, ckdb::Key *parentKey)
{
	std::ofstream ofs(keyString(parentKey), std::ios::binary);
	if (!ofs.is_open())
	{
		ELEKTRA_SET_ERROR (9, parentKey, "file is not open in dump");
		return -1;
	}

	return dump::serialize (ofs, parentKey, returned);
}

ckdb::Plugin *ELEKTRA_PLUGIN_EXPORT(dump)
{
	return elektraPluginExport("dump",
		ELEKTRA_PLUGIN_GET,		&elektraDumpGet,
		ELEKTRA_PLUGIN_SET,		&elektraDumpSet,
		ELEKTRA_PLUGIN_END);
}

} // extern C

<|endoftext|>


<commit_before>/*******************************************************************************

Copyright The University of Auckland

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*******************************************************************************/

//==============================================================================
// Preferences window
//==============================================================================

#include "mainwindow.h"
#include "preferenceswindow.h"

//==============================================================================

#include "ui_preferenceswindow.h"

//==============================================================================

namespace OpenCOR {

//==============================================================================

PreferencesWindow::PreferencesWindow(QWidget *pParent) :
    QDialog(pParent),
    mGui(new Ui::PreferencesWindow)
{
    // Set up the GUI

    mGui->setupUi(this);
}

//==============================================================================

PreferencesWindow::~PreferencesWindow()
{
    // Delete the GUI

    delete mGui;
}

//==============================================================================

}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Some minor cleaning up [ci skip].<commit_after>/*******************************************************************************

Copyright The University of Auckland

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*******************************************************************************/

//==============================================================================
// Preferences window
//==============================================================================

#include "preferenceswindow.h"

//==============================================================================

#include "ui_preferenceswindow.h"

//==============================================================================

namespace OpenCOR {

//==============================================================================

PreferencesWindow::PreferencesWindow(QWidget *pParent) :
    QDialog(pParent),
    mGui(new Ui::PreferencesWindow)
{
    // Set up the GUI

    mGui->setupUi(this);
}

//==============================================================================

PreferencesWindow::~PreferencesWindow()
{
    // Delete the GUI

    delete mGui;
}

//==============================================================================

}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>/*
 * Action.cpp
 *
 */

#include "Action.h"

Action::Action() {
	// TODO Auto-generated constructor stub

}
Action::Action(Packet pkt, Database* db, Socket* sock){
	if(pkt.m_MsgType < 0){
		std::cout << "[E] No Information in Packet" << std::endl;
	}
	else{
		m_db = db;
		m_GivenPkt = pkt;
		m_sock = sock;
		TakeAction();
	}
}
Action::Action(Database* db) {
	m_db = db;
	while(1) {
		std::cout << "[D] Check Heartbeat" << std::endl;
		CheckHeartbeat();
		sleep(10);
	}
}

Action::~Action() {
	// TODO Auto-generated destructor stub
}

// Get Packet and command
// If the parameter is string parse it.
void Action::GivePacket(Packet pkt){
	if(pkt.m_MsgType < 0){
		std::cout << "[E] No Information in Packet" << std::endl;
	}
	else{
		m_GivenPkt = pkt;
		TakeAction();
	}
}

// Decide proper action and perform the job.
void Action::TakeAction(){
	// Do action following message type
	Packet pkt;
	std::string result;
	std::string temp;

	switch(m_GivenPkt.m_MsgType){

	case AP_REGISTRATION_REQUEST:
		InsertDatabase();
		SendResponseMessage(AP_REGISTRATION_RESPONSE, pkt);
		break;

	//case AP_REGISTRATION_RESPONSE:
		//break;

	case AP_STATE_UPDATE_REQUEST:
		UpdateDatabase();
		SendResponseMessage(AP_STATE_UPDATE_RESPONSE, pkt);
		break;

	//case AP_STATE_UPDATE_RESPONSE:
		//break;

	case AP_LIST_REQUEST:
		result = m_db->GetResult("select ID, IP, SSID from AP_Information;");

		//Parse the result by '|' mark
		//and make pkt context
		while(true)
		{
			temp = result.substr(0,result.find('|'));
			result.erase(0,result.find('|')+1);
			pkt.AddValue(AP_ID, temp);

			temp = result.substr(0,result.find('|'));
			result.erase(0,result.find('|')+1);
			pkt.AddValue(AP_IP, temp);

			temp = result.substr(0,result.find('|'));
			result.erase(0,result.find('|')+1);
			pkt.AddValue(AP_SSID, temp);

			if(result.length() < 1) break;
		}
		SendResponseMessage(AP_LIST_RESPONSE, pkt);
		break;

	default:
		break;
	}
}

//Add AP information on DB
void Action::InsertDatabase(){
	std::string query;
	query.assign("INSERT INTO AP_Information (");

	for(int i=0; i<m_GivenPkt.m_paramNo; i++){
		query.append(ValueTypeToString(m_GivenPkt.m_ValueType[i]));
		query.append(",");
	}
	query.erase(query.length()-1);
	query.append(") VALUES ('");

	for(int i=0; i<m_GivenPkt.m_paramNo; i++){
			query.append(m_GivenPkt.m_Value[i]);
			query.append("','");
	}
	query.erase(query.length()-2);
	query.append(");");

	m_db->SendQuery(query);
}

//Update AP Information on DB
void Action::UpdateDatabase(){
	std::string query;
	query.assign("UPDATE AP_Information SET ");

	for(int i=1; i<m_GivenPkt.m_paramNo; i++){
		query.append(ValueTypeToString(m_GivenPkt.m_ValueType[i]));
		query.append("='");
		query.append(m_GivenPkt.m_Value[i]);
		query.append("',");
	}
	query.erase(query.length()-1);
	query.append(", time=CURRENT_TIMESTAMP");
	query.append(" WHERE ");
	query.append(ValueTypeToString(m_GivenPkt.m_ValueType[0]));
	query.append("='");
	query.append(m_GivenPkt.m_Value[0]);
	query.append("';");

	m_db->SendQuery(query);
}

void Action::CheckHeartbeat() {

	std::string query;
	query.assign("DELETE FROM AP_Information WHERE (time - CURRENT_TIMESTAMP) < - 30;");
	m_db->SendQuery(query);

}

//Send response to AP
void Action::SendResponseMessage(int messageType, Packet pkt){
	pkt.DecideMessageType(messageType);
	m_sock->send(pkt.CreateMessage());
	std::cout << "[S] (" << pkt.m_MsgType << ") ";
	std::cout << pkt.CreateMessage() << std::endl;
}
<commit_msg>solved db's bug and add heartbeat<commit_after>/*
 * Action.cpp
 *
 */

#include "Action.h"

Action::Action() {
	// TODO Auto-generated constructor stub

}
Action::Action(Packet pkt, Database* db, Socket* sock){
	if(pkt.m_MsgType < 0){
		std::cout << "[E] No Information in Packet" << std::endl;
	}
	else{
		m_db = db;
		m_GivenPkt = pkt;
		m_sock = sock;
		TakeAction();
	}
}
Action::Action(Database* db) {
	m_db = db;
	while(1) {
		std::cout << "[D] Check Heartbeat" << std::endl;
		CheckHeartbeat();
		sleep(10);
	}
}

Action::~Action() {
	// TODO Auto-generated destructor stub
}

// Get Packet and command
// If the parameter is string parse it.
void Action::GivePacket(Packet pkt){
	if(pkt.m_MsgType < 0){
		std::cout << "[E] No Information in Packet" << std::endl;
	}
	else{
		m_GivenPkt = pkt;
		TakeAction();
	}
}

// Decide proper action and perform the job.
void Action::TakeAction(){
	// Do action following message type
	Packet pkt;
	std::string result;
	std::string temp;

	switch(m_GivenPkt.m_MsgType){

	case AP_REGISTRATION_REQUEST:
		InsertDatabase();
		SendResponseMessage(AP_REGISTRATION_RESPONSE, pkt);
		break;

	//case AP_REGISTRATION_RESPONSE:
		//break;

	case AP_STATE_UPDATE_REQUEST:
		UpdateDatabase();
		SendResponseMessage(AP_STATE_UPDATE_RESPONSE, pkt);
		break;

	//case AP_STATE_UPDATE_RESPONSE:
		//break;

	case AP_LIST_REQUEST:
		result = m_db->GetResult("select ID, IP, SSID from AP_Information;");

		//Parse the result by '|' mark
		//and make pkt context
		while(true)
		{
			temp = result.substr(0,result.find('|'));
			result.erase(0,result.find('|')+1);
			pkt.AddValue(AP_ID, temp);

			temp = result.substr(0,result.find('|'));
			result.erase(0,result.find('|')+1);
			pkt.AddValue(AP_IP, temp);

			temp = result.substr(0,result.find('|'));
			result.erase(0,result.find('|')+1);
			pkt.AddValue(AP_SSID, temp);

			if(result.length() < 1) break;
		}
		SendResponseMessage(AP_LIST_RESPONSE, pkt);
		break;

	default:
		break;
	}
}

//Add AP information on DB
void Action::InsertDatabase(){
	std::string query;
	query.assign("INSERT INTO AP_Information (");

	for(int i=0; i<m_GivenPkt.m_paramNo; i++){
		query.append(ValueTypeToString(m_GivenPkt.m_ValueType[i]));
		query.append(",");
	}
	query.erase(query.length()-1);
	query.append(") VALUES ('");

	for(int i=0; i<m_GivenPkt.m_paramNo; i++){
			query.append(m_GivenPkt.m_Value[i]);
			query.append("','");
	}
	query.erase(query.length()-2);
	query.append(");");

	m_db->SendQuery(query);
}

//Update AP Information on DB
void Action::UpdateDatabase(){
	std::string query;

	query.assign("INSERT INTO AP_Information (");

	for(int i=0; i<m_GivenPkt.m_paramNo; i++){
		query.append(ValueTypeToString(m_GivenPkt.m_ValueType[i]));
		query.append(",");
	}
	//query.erase(query.length()-1);
	query.append("time");
	query.append(") VALUES ('");

	for(int i=0; i<m_GivenPkt.m_paramNo; i++){
			query.append(m_GivenPkt.m_Value[i]);
			query.append("','");
	}
	query.erase(query.length()-1);
	query.append("CURRENT_TIMESTAMP");
	//query.erase(query.length()-2);
	query.append(") ON DUPLICATE KEY ");

	//m_db->SendQuery(query);

	//query.assign("UPDATE AP_Information SET ");
	query.append("UPDATE ");

	for(int i=1; i<m_GivenPkt.m_paramNo; i++){
		query.append(ValueTypeToString(m_GivenPkt.m_ValueType[i]));
		query.append("='");
		query.append(m_GivenPkt.m_Value[i]);
		query.append("',");
	}
	query.erase(query.length()-1);
	query.append(", time=CURRENT_TIMESTAMP;");
	/*
	query.append(" WHERE ");
	query.append(ValueTypeToString(m_GivenPkt.m_ValueType[0]));
	query.append("='");
	query.append(m_GivenPkt.m_Value[0]);
	query.append("';");
	*/
	//std::cout << query << std::endl;

	m_db->SendQuery(query);
}

void Action::CheckHeartbeat() {

	std::string query;
	query.assign("DELETE FROM AP_Information WHERE (time - CURRENT_TIMESTAMP) <= - 30;");
	m_db->SendQuery(query);

}

//Send response to AP
void Action::SendResponseMessage(int messageType, Packet pkt){
	pkt.DecideMessageType(messageType);
	m_sock->send(pkt.CreateMessage());
	std::cout << "[S] (" << pkt.m_MsgType << ") ";
	std::cout << pkt.CreateMessage() << std::endl;
}
<|endoftext|>