text:
/*
Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.

The MySQL Connector/C++ is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
MySQL Connectors. There are special exceptions to the terms and
conditions of the GPLv2 as it is applied to this software, see the
FLOSS License Exception
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; version 2 of the License.

This program 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 General Public License
for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sstream>
#include <boost/scoped_array.hpp>

#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/warning.h>
#include "mysql_util.h"
#include "mysql_ps_resultset.h"
#include "mysql_resultset.h"
#include "mysql_prepared_statement.h"
#include "mysql_ps_resultset_metadata.h"
#include "mysql_resultbind.h"

#include "nativeapi/native_statement_wrapper.h"
#include "nativeapi/native_resultset_wrapper.h"

#include "mysql_debug.h"

namespace sql
{
namespace mysql
{

/* {{{ my_l_to_a() -I- */
static inline char * my_l_to_a(char * buf, size_t buf_size, int64_t a)
{
	snprintf(buf, buf_size, "%lld", (long long) a);
	return buf;
}
/* }}} */

/* {{{ my_ul_to_a() -I- */
static inline char * my_ul_to_a(char * buf, size_t buf_size, uint64_t a)
{
	snprintf(buf, buf_size, "%llu", (unsigned long long) a);
	return buf;
}
/* }}} */

/* {{{ my_f_to_a() -I- */
static inline char * my_f_to_a(char * buf, size_t buf_size, double a)
{
	snprintf(buf, buf_size, "%f", a);
	return buf;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::MySQL_Prepared_ResultSet() -I- */
MySQL_Prepared_ResultSet::MySQL_Prepared_ResultSet(
			boost::shared_ptr< NativeAPI::NativeStatementWrapper > & s,
			boost::shared_ptr< MySQL_ResultBind > & r_bind,
			sql::ResultSet::enum_type rset_type,
			MySQL_Prepared_Statement * par,
			boost::shared_ptr< MySQL_DebugLogger > & l
		)
	: row(NULL), proxy(s), row_position(0), parent(par), is_valid(true),
		logger(l), result_bind(r_bind), resultset_type(rset_type)
{
	CPP_ENTER("MySQL_Prepared_ResultSet::MySQL_Prepared_ResultSet");

	result_bind->bindResult();

	boost::scoped_ptr< NativeAPI::NativeResultsetWrapper > result_meta( proxy->result_metadata() );
	num_fields = proxy->field_count();
	num_rows = proxy->num_rows();

	CPP_INFO_FMT("num_fields=%u num_rows=%u", num_fields, num_rows);
	for (unsigned int i = 0; i < num_fields; ++i) {
		boost::scoped_array< char > upstring(sql::mysql::util::utf8_strup(result_meta->fetch_field()->name, 0));
		field_name_to_index_map[sql::SQLString(upstring.get())] = i;
	}

	rs_meta.reset(new MySQL_PreparedResultSetMetaData(proxy, logger));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::~MySQL_Prepared_ResultSet() -I- */
MySQL_Prepared_ResultSet::~MySQL_Prepared_ResultSet()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::~MySQL_Prepared_ResultSet");
	closeIntern();
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::absolute() -I- */
bool
MySQL_Prepared_ResultSet::absolute(const int new_pos)
{
	CPP_ENTER("MySQL_Prepared_ResultSet::absolute");
	checkValid();
	checkScrollable();
	if (new_pos > 0) {
		if (new_pos > (int) num_rows) {
			row_position = num_rows + 1; /* after last row */
		} else {
			row_position = new_pos;
			seek();
			return true;
		}
	} else if (new_pos < 0) {
		if ((-new_pos) > (int) num_rows) {
			row_position = 0; /* before first new_pos */
		} else {
			row_position = num_rows - (-new_pos) + 1;
			seek();
			return true;
		}
	} else {
		/* According to the JDBC book, absolute(0) means before the result set */
		row_position = 0;
		/* no seek() here, as we are not on data*/
		beforeFirst();
	}
	return (row_position > 0 && row_position < (num_rows + 1));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::afterLast() -I- */
void
MySQL_Prepared_ResultSet::afterLast()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::afterLast");
	checkValid();
	checkScrollable();
	row_position = num_rows + 1;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::beforeFirst() -I- */
void
MySQL_Prepared_ResultSet::beforeFirst()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::beforeFirst");
	checkValid();
	checkScrollable();
	proxy->data_seek(0);
	row_position = 0;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::cancelRowUpdates() -U- */
void
MySQL_Prepared_ResultSet::cancelRowUpdates()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::cancelRowUpdates");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::cancelRowUpdates()");
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::checkValid() -I- */
void
MySQL_Prepared_ResultSet::checkValid() const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::checkValid");
	CPP_INFO_FMT("this=%p", this);
	if (isClosed()) {
		throw sql::InvalidInstanceException("Statement has been closed");
	}
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::checkScrollable() -I- */
void
MySQL_Prepared_ResultSet::checkScrollable() const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::checkScrollable");
	CPP_INFO_FMT("this=%p", this);
	if (resultset_type == sql::ResultSet::TYPE_FORWARD_ONLY) {
		throw sql::NonScrollableException("Nonscrollable result set");
	}
}
/* }}} */

/* {{{ MySQL_ResultSet::isScrollable() -I- */
bool
MySQL_Prepared_ResultSet::isScrollable() const
{
	CPP_ENTER("MySQL_ResultSet::isScrollable");
	CPP_INFO_FMT("this=%p", this);
	return (resultset_type != sql::ResultSet::TYPE_FORWARD_ONLY);
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::clearWarnings() -U- */
void
MySQL_Prepared_ResultSet::clearWarnings()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::clearWarnings");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::clearWarnings()");
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::close() -I- */
void
MySQL_Prepared_ResultSet::close()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::close");
	checkValid();
	closeIntern();
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::closeIntern() -I- */
void
MySQL_Prepared_ResultSet::closeIntern()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::closeIntern");
	is_valid = false;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::findColumn() -I- */
uint32_t
MySQL_Prepared_ResultSet::findColumn(const sql::SQLString& columnLabel) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::findColumn");
	checkValid();
	boost::scoped_array< char > upstring(sql::mysql::util::utf8_strup(columnLabel.c_str(), 0));
	FieldNameIndexMap::const_iterator iter= field_name_to_index_map.find(upstring.get());

	if (iter == field_name_to_index_map.end()) {
		return 0;
	}
	/* findColumn returns 1-based indexes */
	return iter->second + 1;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::first() -I- */
bool
MySQL_Prepared_ResultSet::first()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::first");
	checkValid();
	checkScrollable();
	if (num_rows) {
		row_position = 1;
		seek();
	}
	return num_rows? true:false;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getBlob() -I- */
std::istream *
MySQL_Prepared_ResultSet::getBlob(const uint32_t columnIndex) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getBlob(int)");
	CPP_INFO_FMT("column=%u", columnIndex);
	/* isBeforeFirst checks for validity */
	if (isBeforeFirstOrAfterLast()) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getBlob: can't fetch because not on result set");
	}
	return new std::istringstream(getString(columnIndex));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getBlob() -I- */
std::istream *
MySQL_Prepared_ResultSet::getBlob(const sql::SQLString& columnLabel) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getBlob(string)");
	/* isBeforeFirst checks for validity */
	if (isBeforeFirstOrAfterLast()) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getBlob: can't fetch because not on result set");
	}
	return new std::istringstream(getString(columnLabel));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getBoolean() -I- */
bool
MySQL_Prepared_ResultSet::getBoolean(const uint32_t columnIndex) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getBoolean(int)");
	CPP_INFO_FMT("column=%u", columnIndex);
	/* isBeforeFirst checks for validity */
	if (isBeforeFirstOrAfterLast()) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getBoolean: can't fetch because not on result set");
	}
	return getInt(columnIndex)? true:false;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getBoolean() -I- */
bool
MySQL_Prepared_ResultSet::getBoolean(const sql::SQLString& columnLabel) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getBoolean(string)");
	/* isBeforeFirst checks for validity */
	if (isBeforeFirstOrAfterLast()) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getBoolean: can't fetch because not on result set");
	}
	return getInt(columnLabel)? true:false;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getConcurrency() -U- */
int
MySQL_Prepared_ResultSet::getConcurrency()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getConcurrency");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::getConcurrency()");
	return 0; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getCursorName() -U- */
SQLString
MySQL_Prepared_ResultSet::getCursorName()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getCursorName");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::getCursorName()");
	return ""; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getDouble() -I- */
long double
MySQL_Prepared_ResultSet::getDouble(const uint32_t columnIndex) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getDouble(int)");
	CPP_INFO_FMT("column=%u", columnIndex);

	/* isBeforeFirst checks for validity */
	if (isBeforeFirstOrAfterLast()) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getDouble: can't fetch because not on result set");
	}

	if (columnIndex == 0 || columnIndex > num_fields) {
		throw sql::InvalidArgumentException("MySQLPreparedResultSet::getDouble: invalid 'columnIndex'");
	}

	last_queried_column = columnIndex;

	if (*result_bind->rbind[columnIndex - 1].is_null) {
		return 0.0;
	}

	switch (rs_meta->getColumnType(columnIndex)) {
		case sql::DataType::BIT:
		case sql::DataType::YEAR:	// fetched as a SMALLINT
		case sql::DataType::TINYINT:
		case sql::DataType::SMALLINT:
		case sql::DataType::MEDIUMINT:
		case sql::DataType::INTEGER:
		case sql::DataType::BIGINT:
		{
			long double ret;
			bool is_it_unsigned = result_bind->rbind[columnIndex - 1].is_unsigned != 0;
			CPP_INFO_FMT("It's an int : %ssigned", is_it_unsigned? "un":"");
			if (is_it_unsigned) {
				uint64_t ival = getUInt64_intern(columnIndex, false);
				CPP_INFO_FMT("value=%llu", ival);
				ret = static_cast<long double>(ival);
			} else {
				int64_t ival = getInt64_intern(columnIndex, false);
				CPP_INFO_FMT("value=%lld", ival);
				ret = static_cast<long double>(ival);
			}
			CPP_INFO_FMT("value=%10.10f", (double) ret);
			return ret;
		}
		case sql::DataType::NUMERIC:
		case sql::DataType::DECIMAL:
		case sql::DataType::TIMESTAMP:
		case sql::DataType::DATE:
		case sql::DataType::TIME:
		case sql::DataType::CHAR:
		case sql::DataType::BINARY:
		case sql::DataType::VARCHAR:
		case sql::DataType::VARBINARY:
		case sql::DataType::LONGVARCHAR:
		case sql::DataType::LONGVARBINARY:
		case sql::DataType::SET:
		case sql::DataType::ENUM:
		{
			CPP_INFO("It's a string");
			long double ret = sql::mysql::util::strtold(getString(columnIndex).c_str(), NULL);
			CPP_INFO_FMT("value=%10.10f", ret);
			return ret;
		}
		case sql::DataType::REAL:
		{
			long double ret = !*result_bind->rbind[columnIndex - 1].is_null? *reinterpret_cast<float *>(result_bind->rbind[columnIndex - 1].buffer):0.;
			CPP_INFO_FMT("value=%10.10f", ret);
			return ret;
		}
		case sql::DataType::DOUBLE:
		{
			long double ret = !*result_bind->rbind[columnIndex - 1].is_null? *reinterpret_cast<double *>(result_bind->rbind[columnIndex - 1].buffer):0.;
			CPP_INFO_FMT("value=%10.10f", ret);
			return ret;
		}

		// ToDo : Geometry? default ?
	}
	CPP_ERR("MySQL_Prepared_ResultSet::getDouble: unhandled type. Please, report");
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::getDouble: unhandled type. Please, report");
	return .0; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getDouble() -I- */
long double
MySQL_Prepared_ResultSet::getDouble(const sql::SQLString& columnLabel) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getDouble(string)");
	return getDouble(findColumn(columnLabel));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getFetchDirection() -U- */
int
MySQL_Prepared_ResultSet::getFetchDirection()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getFetchDirection");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::getFetchDirection()");
	return 0; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getFetchSize() -U- */
size_t
MySQL_Prepared_ResultSet::getFetchSize()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getFetchSize");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::getFetchSize()");
	return 0; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getHoldability() -U- */
int
MySQL_Prepared_ResultSet::getHoldability()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getHoldability");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::getHoldability()");
	return 0; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getInt() -I- */
int32_t
MySQL_Prepared_ResultSet::getInt(const uint32_t columnIndex) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getInt(int)");
	CPP_INFO_FMT("column=%u", columnIndex);
	/* isBeforeFirst checks for validity */
	if (isBeforeFirstOrAfterLast()) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getInt: can't fetch because not on result set");
	}
	if (columnIndex == 0 || columnIndex > num_fields) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getInt: invalid value of 'columnIndex'");
	}

	last_queried_column = columnIndex;

	if (*result_bind->rbind[columnIndex - 1].is_null) {
		return 0;
	}

	return static_cast<int32_t>(getInt64_intern(columnIndex, true));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getInt() -I- */
int32_t
MySQL_Prepared_ResultSet::getInt(const sql::SQLString& columnLabel) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getInt(string)");
	return getInt(findColumn(columnLabel));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getUInt() -I- */
uint32_t
MySQL_Prepared_ResultSet::getUInt(const uint32_t columnIndex) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getUInt(int)");
	CPP_INFO_FMT("column=%u", columnIndex);
	/* isBeforeFirst checks for validity */
	if (isBeforeFirstOrAfterLast()) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getUInt: can't fetch because not on result set");
	}
	if (columnIndex == 0 || columnIndex > num_fields) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getUInt: invalid value of 'columnIndex'");
	}

	last_queried_column = columnIndex;

	if (*result_bind->rbind[columnIndex - 1].is_null) {
		return 0;
	}
	return static_cast<uint32_t>(getUInt64_intern(columnIndex, true));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getUInt() -I- */
uint32_t
MySQL_Prepared_ResultSet::getUInt(const sql::SQLString& columnLabel) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getUInt(string)");
	return getUInt(findColumn(columnLabel));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getInt64_intern() -I- */
int64_t
MySQL_Prepared_ResultSet::getInt64_intern(const uint32_t columnIndex, bool /* cutTooBig */) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getInt64_intern");
	CPP_INFO_FMT("column=%u", columnIndex);

	switch (rs_meta->getColumnType(columnIndex)) {
		case sql::DataType::REAL:
		case sql::DataType::DOUBLE:
			CPP_INFO("It's a double");
			return static_cast<int64_t>(getDouble(columnIndex));
		case sql::DataType::NUMERIC:
		case sql::DataType::DECIMAL:
		case sql::DataType::TIMESTAMP:
		case sql::DataType::DATE:
		case sql::DataType::TIME:
		case sql::DataType::CHAR:
		case sql::DataType::BINARY:
		case sql::DataType::VARCHAR:
		case sql::DataType::VARBINARY:
		case sql::DataType::LONGVARCHAR:
		case sql::DataType::LONGVARBINARY:
		case sql::DataType::SET:
		case sql::DataType::ENUM:
			CPP_INFO("It's a string");
			return strtoll(getString(columnIndex).c_str(), NULL, 10);
		case sql::DataType::BIT:
		{
			int64_t uval = 0;
			/* This length is in bytes, on the contrary to what can be seen in mysql_resultset.cpp where the Meta is used */
			switch (*result_bind->rbind[columnIndex - 1].length) {
				case 8:uval = (int64_t) bit_uint8korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 7:uval = (int64_t) bit_uint7korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 6:uval = (int64_t) bit_uint6korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 5:uval = (int64_t) bit_uint5korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 4:uval = (int64_t) bit_uint4korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 3:uval = (int64_t) bit_uint3korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 2:uval = (int64_t) bit_uint2korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 1:uval = (int64_t) bit_uint1korr(result_bind->rbind[columnIndex - 1].buffer);break;
			}
			return uval;
		}
		case sql::DataType::YEAR:	// fetched as a SMALLINT
		case sql::DataType::TINYINT:
		case sql::DataType::SMALLINT:
		case sql::DataType::MEDIUMINT:
		case sql::DataType::INTEGER:
		case sql::DataType::BIGINT: {
			// sql::DataType::YEAR is fetched as a SMALLINT, thus should not be in the switch
			int64_t ret;
			bool is_it_null = *result_bind->rbind[columnIndex - 1].is_null != 0;
			bool is_it_unsigned = result_bind->rbind[columnIndex - 1].is_unsigned != 0;

			CPP_INFO_FMT("%d byte, %ssigned, null=%d", result_bind->rbind[columnIndex - 1].buffer_length, is_it_unsigned? "un":"", is_it_null);
			switch (result_bind->rbind[columnIndex - 1].buffer_length) {
				case 1:
					if (is_it_unsigned) {
						// ToDo: Really reinterpret_case or static_cast
						ret = !is_it_null? *reinterpret_cast<uint8_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					} else {
						// ToDo: Really reinterpret_case or static_cast
						ret = !is_it_null? *reinterpret_cast<int8_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					}
					break;
				case 2:
					if (is_it_unsigned) {
						ret = !is_it_null? *reinterpret_cast<uint16_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					} else {
						ret = !is_it_null? *reinterpret_cast<int16_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					}
					break;
				case 4:
					if (is_it_unsigned) {
						ret =  !is_it_null? *reinterpret_cast<uint32_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					} else {
						ret =  !is_it_null? *reinterpret_cast<int32_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					}
					break;
				case 8:
					if (is_it_unsigned) {
						ret =  !is_it_null? *reinterpret_cast<uint64_t *>(result_bind->rbind[columnIndex - 1].buffer):0;

#if WE_WANT_TO_SEE_MORE_FAILURES_IN_UNIT_RESULTSET
						if (cutTooBig &&
							ret &&
							*reinterpret_cast<uint64_t *>(result_bind->rbind[columnIndex - 1].buffer) > UL64(9223372036854775807))
						{
							ret = UL64(9223372036854775807);
						}
#endif
					} else {
						ret =  !is_it_null? *reinterpret_cast<int64_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					}
					break;
				default:
					throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getInt64_intern: invalid type");
			}
			CPP_INFO_FMT("value=%lld", ret);
			return ret;
		}
		default:
			break;
		// ToDo : Geometry? default ?
	}
	CPP_ERR("MySQL_Prepared_ResultSet::getInt64_intern: unhandled type. Please, report");
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::getInt64_intern: unhandled type. Please, report");
	return 0; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getInt64() -I- */
int64_t
MySQL_Prepared_ResultSet::getInt64(const uint32_t columnIndex) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getInt64(int)");
	CPP_INFO_FMT("column=%u", columnIndex);

	/* isBeforeFirst checks for validity */
	if (isBeforeFirstOrAfterLast()) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getInt64: can't fetch because not on result set");
	}
	if (columnIndex == 0 || columnIndex > num_fields) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getInt64: invalid value of 'columnIndex'");
	}

	last_queried_column = columnIndex;

	if (*result_bind->rbind[columnIndex - 1].is_null) {
		return 0;
	}
	return getInt64_intern(columnIndex, true);
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getInt64() -I- */
int64_t
MySQL_Prepared_ResultSet::getInt64(const sql::SQLString& columnLabel) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getInt64(string)");
	return getInt64(findColumn(columnLabel));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getUInt64_intern() -I- */
uint64_t
MySQL_Prepared_ResultSet::getUInt64_intern(const uint32_t columnIndex, bool /* cutTooBig */) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getUInt64_intern");
	CPP_INFO_FMT("column=%u", columnIndex);

	switch (rs_meta->getColumnType(columnIndex)) {
		case sql::DataType::REAL:
		case sql::DataType::DOUBLE:
			CPP_INFO("It's a double");
			return static_cast<uint64_t>(getDouble(columnIndex));
		case sql::DataType::NUMERIC:
		case sql::DataType::DECIMAL:
		case sql::DataType::TIMESTAMP:
		case sql::DataType::DATE:
		case sql::DataType::TIME:
		case sql::DataType::CHAR:
		case sql::DataType::BINARY:
		case sql::DataType::VARCHAR:
		case sql::DataType::VARBINARY:
		case sql::DataType::LONGVARCHAR:
		case sql::DataType::LONGVARBINARY:
		case sql::DataType::SET:
		case sql::DataType::ENUM:
			CPP_INFO("It's a string");
			return strtoull(getString(columnIndex).c_str(), NULL, 10);
		case sql::DataType::BIT:
		{
			uint64_t uval = 0;
			/* This length is in bytes, on the contrary to what can be seen in mysql_resultset.cpp where the Meta is used */
			switch (*result_bind->rbind[columnIndex - 1].length) {
				case 8:uval = (uint64_t) bit_uint8korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 7:uval = (uint64_t) bit_uint7korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 6:uval = (uint64_t) bit_uint6korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 5:uval = (uint64_t) bit_uint5korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 4:uval = (uint64_t) bit_uint4korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 3:uval = (uint64_t) bit_uint3korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 2:uval = (uint64_t) bit_uint2korr(result_bind->rbind[columnIndex - 1].buffer);break;
				case 1:uval = (uint64_t) bit_uint1korr(result_bind->rbind[columnIndex - 1].buffer);break;
			}
			return uval;
		}
		case sql::DataType::YEAR:	// fetched as a SMALLINT
		case sql::DataType::TINYINT:
		case sql::DataType::SMALLINT:
		case sql::DataType::MEDIUMINT:
		case sql::DataType::INTEGER:
		case sql::DataType::BIGINT:
		{
			// sql::DataType::YEAR is fetched as a SMALLINT, thus should not be in the switch

			uint64_t ret;
			bool is_it_null = *result_bind->rbind[columnIndex - 1].is_null != 0;
			bool is_it_unsigned = result_bind->rbind[columnIndex - 1].is_unsigned != 0;

			CPP_INFO_FMT("%d byte, %ssigned, null=%d", result_bind->rbind[columnIndex - 1].buffer_length, is_it_unsigned? "un":"", is_it_null);
			switch (result_bind->rbind[columnIndex - 1].buffer_length) {
				case 1:
					if (is_it_unsigned) {
						// ToDo: Really reinterpret_case or static_cast
						ret = !is_it_null? *reinterpret_cast<uint8_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					} else {
						// ToDo: Really reinterpret_case or static_cast
						ret = !is_it_null? *reinterpret_cast<int8_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					}
					break;
				case 2:
					if (is_it_unsigned) {
						ret = !is_it_null? *reinterpret_cast<uint16_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					} else {
						ret = !is_it_null? *reinterpret_cast<int16_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					}
					break;
				case 4:
					if (is_it_unsigned) {
						ret =  !is_it_null? *reinterpret_cast<uint32_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					} else {
						ret =  !is_it_null? *reinterpret_cast<int32_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					}
					break;
				case 8:
					if (is_it_unsigned) {
						ret =  !is_it_null? *reinterpret_cast<uint64_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
					} else {
						ret =  !is_it_null? *reinterpret_cast<int64_t *>(result_bind->rbind[columnIndex - 1].buffer):0;
#if WE_WANT_TO_SEE_MORE_FAILURES_IN_UNIT_RESULTSET
						if (is_it_null) {
							if (cutTooBig && *reinterpret_cast<int64_t *>(result_bind->rbind[columnIndex - 1].buffer) < 0) {
								ret =  *reinterpret_cast<uint64_t *>(result_bind->rbind[columnIndex - 1].buffer);
							} else {
								ret =  *reinterpret_cast<int64_t *>(result_bind->rbind[columnIndex - 1].buffer);
							}
						} else {
							ret = 0;
						}
#endif
					}
					break;
				default:
					throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getInt64_intern: invalid type");
			}
			CPP_INFO_FMT("value=%lld", ret);
			return ret;
		}
		default:
			break;
		// ToDo : Geometry? default ?
	}
	CPP_ERR("MySQL_Prepared_ResultSet::getUInt64_intern: unhandled type. Please, report");
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::getUInt64_intern: unhandled type. Please, report");
	return 0; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getUInt64() -I- */
uint64_t
MySQL_Prepared_ResultSet::getUInt64(const uint32_t columnIndex) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getUInt64(int)");
	CPP_INFO_FMT("column=%u", columnIndex);

	/* isBeforeFirst checks for validity */
	if (isBeforeFirstOrAfterLast()) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getUInt64: can't fetch because not on result set");
	}
	if (columnIndex == 0 || columnIndex > num_fields) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getUInt64: invalid value of 'columnIndex'");
	}

	last_queried_column = columnIndex;

	if (*result_bind->rbind[columnIndex - 1].is_null) {
		return 0;
	}
	return getUInt64_intern(columnIndex, true);
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getUInt64() -I- */
uint64_t
MySQL_Prepared_ResultSet::getUInt64(const sql::SQLString& columnLabel) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getUInt64(string)");
	return getUInt64(findColumn(columnLabel));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getMetaData() -I- */
sql::ResultSetMetaData *
MySQL_Prepared_ResultSet::getMetaData() const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getMetaData");
	checkValid();
	return rs_meta.get();
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getRow() -I- */
size_t
MySQL_Prepared_ResultSet::getRow() const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getRow");
	checkValid();
	/* row_position is 0 based */
	return static_cast<size_t> (row_position);
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getRowId() -U- */
sql::RowID *
MySQL_Prepared_ResultSet::getRowId(uint32_t)
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getRowId");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::getRowId()");
	return NULL; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getRowId() -U- */
sql::RowID *
MySQL_Prepared_ResultSet::getRowId(const sql::SQLString &)
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getRowId");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::getRowId()");
	return NULL; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getStatement() -I- */
const sql::Statement *
MySQL_Prepared_ResultSet::getStatement() const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getStatement");
	return parent;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getString() -I- */
SQLString
MySQL_Prepared_ResultSet::getString(const uint32_t columnIndex) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getString(int)");
	CPP_INFO_FMT("column=%u", columnIndex);

	/* isBeforeFirst checks for validity */
	if (isBeforeFirstOrAfterLast()) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::getString: can't fetch because not on result set");
	}

	if (columnIndex == 0 || columnIndex > num_fields) {
		throw sql::InvalidArgumentException("MySQLPreparedResultSet::getString: invalid 'columnIndex'");
	}

	last_queried_column = columnIndex;
	if (*result_bind->rbind[columnIndex - 1].is_null) {
		return sql::SQLString("");
	}

	switch (rs_meta->getColumnType(columnIndex)) {
		case sql::DataType::TIMESTAMP:
		{
			char buf[22];
			MYSQL_TIME * t = static_cast<MYSQL_TIME *>(result_bind->rbind[columnIndex - 1].buffer);
			snprintf(buf, sizeof(buf) - 1, "%04d-%02d-%02d %02d:%02d:%02d", t->year, t->month, t->day, t->hour, t->minute, t->second);
			CPP_INFO_FMT("It's a datetime/timestamp %s", buf);
			return sql::SQLString(buf);
		}
		case sql::DataType::DATE:
		{
			char buf[12];
			MYSQL_TIME * t = static_cast<MYSQL_TIME *>(result_bind->rbind[columnIndex - 1].buffer);
			snprintf(buf, sizeof(buf) - 1, "%02d-%02d-%02d", t->year, t->month, t->day);
			CPP_INFO_FMT("It's a date %s", buf);
			return sql::SQLString(buf);
		}
		case sql::DataType::TIME:
		{
			char buf[12];
			MYSQL_TIME * t = static_cast<MYSQL_TIME *>(result_bind->rbind[columnIndex - 1].buffer);
			snprintf(buf, sizeof(buf) - 1, "%s%02d:%02d:%02d", t->neg? "-":"", t->hour, t->minute, t->second);
			CPP_INFO_FMT("It's a time %s", buf);
			return sql::SQLString(buf);
		}
		case sql::DataType::BIT:
		case sql::DataType::YEAR:	// fetched as a SMALLINT
		case sql::DataType::TINYINT:
		case sql::DataType::SMALLINT:
		case sql::DataType::MEDIUMINT:
		case sql::DataType::INTEGER:
		case sql::DataType::BIGINT:
		{
			char buf[30];
			CPP_INFO("It's an int");
			if (result_bind->rbind[columnIndex - 1].is_unsigned) {
				my_ul_to_a(buf, sizeof(buf) - 1, getUInt64_intern(columnIndex, false));
			} else {
				my_l_to_a(buf, sizeof(buf) - 1, getInt64_intern(columnIndex, false));
			}
			return sql::SQLString(buf);
		}
		case sql::DataType::REAL:
		case sql::DataType::DOUBLE:
		{
			char buf[50];
			CPP_INFO("It's a double");
			my_f_to_a(buf, sizeof(buf) - 1, getDouble(columnIndex));
			return sql::SQLString(buf);
		}
		case sql::DataType::NUMERIC:
		case sql::DataType::DECIMAL:
		case sql::DataType::CHAR:
		case sql::DataType::BINARY:
		case sql::DataType::VARCHAR:
		case sql::DataType::VARBINARY:
		case sql::DataType::LONGVARCHAR:
		case sql::DataType::LONGVARBINARY:
		case sql::DataType::SET:
		case sql::DataType::ENUM:
			CPP_INFO("It's a string");
			return  sql::SQLString(static_cast<char *>(result_bind->rbind[columnIndex - 1].buffer), *result_bind->rbind[columnIndex - 1].length);
		default:
			break;
		// ToDo : Geometry? default ?
	}

	CPP_ERR("MySQL_Prepared_ResultSet::getString: unhandled type. Please, report");
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::getString: unhandled type. Please, report");
	return 0; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getString() -I- */
SQLString
MySQL_Prepared_ResultSet::getString(const sql::SQLString& columnLabel) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getString(string)");
	return getString(findColumn(columnLabel));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getType() -I- */
sql::ResultSet::enum_type
MySQL_Prepared_ResultSet::getType() const
{
	CPP_ENTER("MySQL_ResultSet::getType");
	checkValid();
	return resultset_type;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::getWarnings() -U- */
void
MySQL_Prepared_ResultSet::getWarnings()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::getWarnings");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::getWarnings()");
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::isAfterLast() -I- */
bool
MySQL_Prepared_ResultSet::isAfterLast() const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::beforeFirst");
	checkValid();
	checkScrollable();
	return (row_position == num_rows + 1);
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::isBeforeFirst() -I- */
bool
MySQL_Prepared_ResultSet::isBeforeFirst() const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::beforeFirst");
	checkValid();
	return (row_position == 0);
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::isClosed() -I- */
bool
MySQL_Prepared_ResultSet::isClosed() const
{
	return !is_valid;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::insertRow() -U- */
void
MySQL_Prepared_ResultSet::insertRow()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::beforeFirst");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::insertRow()");
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::isFirst() -I- */
bool
MySQL_Prepared_ResultSet::isFirst() const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::beforeFirst");
	checkValid();
	return (row_position == 1);
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::isLast() -I- */
bool
MySQL_Prepared_ResultSet::isLast() const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::isLast");
	checkValid();
	checkScrollable();
	return (row_position == num_rows);
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::isNull() -I- */
bool
MySQL_Prepared_ResultSet::isNull(const uint32_t columnIndex) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::isNull(int)");
	checkValid();
	if (columnIndex == 0 || columnIndex > num_fields) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::isNull: invalid value of 'columnIndex'");
	}
	/* isBeforeFirst checks for validity */
	if (isBeforeFirstOrAfterLast()) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::isNull: can't fetch because not on result set");
	}
	return *result_bind->rbind[columnIndex - 1].is_null != 0;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::isNull() -I- */
bool
MySQL_Prepared_ResultSet::isNull(const sql::SQLString& columnLabel) const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::isNull(string)");
	uint32_t col_idx = findColumn(columnLabel);
	if (col_idx == 0) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::isNull: invalid value of 'columnLabel'");
	}
	return isNull(col_idx);
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::last() -I- */
bool
MySQL_Prepared_ResultSet::last()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::last");
	checkValid();
	checkScrollable();
	if (num_rows) {
		row_position = num_rows;
		seek();
	}
	return num_rows? true:false;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::moveToCurrentRow() -U- */
void
MySQL_Prepared_ResultSet::moveToCurrentRow()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::moveToCurrentRow");
	checkValid();
	checkScrollable();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::moveToCurrentRow()");
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::moveToInsertRow() -U- */
void
MySQL_Prepared_ResultSet::moveToInsertRow()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::moveToInsertRow");
	checkValid();
	checkScrollable();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::moveToInsertRow()");
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::next() -I- */
bool
MySQL_Prepared_ResultSet::next()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::next");
	CPP_INFO_FMT("row_position=%llu num_rows=%llu", row_position, num_rows);
	checkValid();
	bool ret = false;
	if (isScrollable()) {
		/* isBeforeFirst checks for validity */
		if (isLast()) {
			++row_position;
			ret = false;
		} else if (row_position < num_rows + 1) {

			if (row_position == 0) {
				proxy->data_seek(row_position);
			} else {
				/*
				NOTE: Buffered only optimization.

				If our position is anything else but beforeFirst/afterLast, then the last
				cursor operation ended with a mysql_stmt_fetch call, which by definition (?)
				moves the cursor to the next row after the fetched one. So, we do not need
				any positioning here.
				*/
			}

			int result = proxy->fetch();
			if (!result || result == MYSQL_DATA_TRUNCATED) {
				ret = true;
			}
			if (result == MYSQL_NO_DATA) {
				ret = false;
			}
			++row_position;
		}
		CPP_INFO_FMT("new_row_position=%llu ret=%d", row_position, ret);
	} else {
		int result = proxy->fetch();
		if (!result || result == MYSQL_DATA_TRUNCATED) {
			ret = true;
		}
		if (result == MYSQL_NO_DATA) {
			ret = false;
		}
		++row_position;
	}
	return ret;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::previous() -I- */
bool
MySQL_Prepared_ResultSet::previous()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::previous");
	/* isBeforeFirst checks for validity */
	if (isBeforeFirst()) {
		return false;
	} else if (isFirst()) {
		beforeFirst();
		return false;
	} else if (row_position > 1) {
		--row_position;
		proxy->data_seek(row_position - 1);
		int result = proxy->fetch();
		if (!result || result == MYSQL_DATA_TRUNCATED) {
			return true;
		}
		if (result == MYSQL_NO_DATA) {
			return false;
		}
		throw sql::SQLException("Error during mysql_stmt_fetch");
	}
	throw sql::SQLException("Impossible");
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::refreshRow() -U- */
void
MySQL_Prepared_ResultSet::refreshRow()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::refreshRow");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::refreshRow()");
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::relative() -I- */
bool
MySQL_Prepared_ResultSet::relative(const int rows)
{
	CPP_ENTER("MySQL_Prepared_ResultSet::relative");
	checkValid();
	checkScrollable();
	if (rows != 0) {
		if (row_position + rows > num_rows || row_position + rows < 1) {
			row_position = rows > 0? num_rows + 1 : 0; /* after last or before first */
		} else {
			row_position += rows;
			proxy->data_seek(row_position - 1);
		}
	}

	return (row_position > 0 && row_position <= num_rows);
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::rowDeleted() -U- */
bool
MySQL_Prepared_ResultSet::rowDeleted()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::rowDeleted");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::rowDeleted()");
	return false; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::rowInserted() -U- */
bool
MySQL_Prepared_ResultSet::rowInserted()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::rowInserted");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::rowInserted()");
	return false; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::rowUpdated() -U- */
bool
MySQL_Prepared_ResultSet::rowUpdated()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::rowUpdated");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::rowUpdated()");
	return false; // fool compilers
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::rowsCount() -I- */
size_t
MySQL_Prepared_ResultSet::rowsCount() const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::rowsCount");
	checkValid();
	checkScrollable();
	return static_cast<size_t>(proxy->num_rows());
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::setFetchSize() -U- */
void
MySQL_Prepared_ResultSet::setFetchSize(size_t /* rows */)
{
	CPP_ENTER("MySQL_Prepared_ResultSet::setFetchSize");
	checkValid();
	throw sql::MethodNotImplementedException("MySQL_Prepared_ResultSet::setFetchSize()");
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::wasNull() -I- */
bool
MySQL_Prepared_ResultSet::wasNull() const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::wasNull");
	checkValid();
	/* isBeforeFirst checks for validity */
	if (isBeforeFirstOrAfterLast()) {
		throw sql::InvalidArgumentException("MySQL_Prepared_ResultSet::wasNull: can't fetch because not on result set");
	}
	return *result_bind->rbind[last_queried_column - 1].is_null != 0;
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::isBeforeFirstOrAfterLast() -I- */
bool
MySQL_Prepared_ResultSet::isBeforeFirstOrAfterLast() const
{
	CPP_ENTER("MySQL_Prepared_ResultSet::isBeforeFirstOrAfterLast");
	checkValid();
	return (row_position == 0) || (isScrollable() && (row_position == num_rows + 1));
}
/* }}} */

/* {{{ MySQL_Prepared_ResultSet::seek() -I- */
void
MySQL_Prepared_ResultSet::seek()
{
	CPP_ENTER("MySQL_Prepared_ResultSet::seek");
	proxy->data_seek(row_position - 1);
	proxy->fetch();
}
/* }}} */

} /* namespace mysql */
} /* namespace sql */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */

max_stars_repo_name: vkardon/dbstream

max_issues_repo_name: vkardon/dbstream

max_forks_repo_name: vkardon/dbstream


text:
/*
* Copyright (C) 2014-2017 Rhonda Software.
* All rights reserved.
*/

#include "StdInc.h"
#include "ApiStorage.h"
#include "SAXHandlers.h"
#include <boost/stacktrace.hpp>
#include <xercesc/parsers/SAXParser.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/XMLString.hpp>

//////////////////////////////////////////////////////////////////////////
// sorted array of used nodes
const std::vector<std::string> ApiStorage::nodeNames =
{
    "Argument",
    "ArrayType",
    "CvQualifiedType",
    "Ellipsis",
    "EnumValue",
    "Enumeration",
    "Field",
    "File",
    "Function",
    "FunctionType",
    "FundamentalType",
    "GCC_XML",
    "Namespace",
    "PointerType",
    "Struct",
    "Typedef",
    "Union",
    "Variable"
};

//////////////////////////////////////////////////////////////////////////
void RPCAPI GeneratorPrintStackTrace(std::ostream& stream)
{
    stream << boost::stacktrace::stacktrace() << std::endl;
}

//////////////////////////////////////////////////////////////////////////
ApiStoragePtr ApiStorageInterface::Create(const StorageParameters& params)
{
    std::unique_ptr<ApiStorage> aPtr(new ApiStorage(params));
    if (!aPtr)
    {
        STG_EXCEPTION_ERROR("Cannot create ApiStorage instance");
    }

    aPtr->LoadXmlData();
    return ApiStoragePtr(aPtr.release());
}

//////////////////////////////////////////////////////////////////////////
ApiStorage::ApiStorage(const StorageParameters& params)
    : m_params(params)
{
}

//////////////////////////////////////////////////////////////////////////
ApiStorage::~ApiStorage()
{
}

//////////////////////////////////////////////////////////////////////////
void ApiStorage::LoadXmlData()
{
    try
    {
        XMLPlatformUtils::Initialize();
    }
    catch (const XMLException& toCatch)
    {
        char* message = XMLString::transcode(toCatch.getMessage());
        std::string errMsg = "Error during XERCEC-C initialization!: ";
        errMsg += message;
        XMLString::release(&message);
        STG_EXCEPTION_ERROR(errMsg);
    }

    try
    {
        std::unique_ptr<xercesc::SAXParser> parser(new SAXParser());
        std::unique_ptr<xercesc::DocumentHandler> docHandler(new SAXHandlers(*this));
        parser->setDocumentHandler(docHandler.get());
        parser->setErrorHandler(dynamic_cast<xercesc::ErrorHandler*>(docHandler.get()));

        parser->parse(m_params.apiXmlName.c_str());
    }
    catch (const XMLException& e)
    {
        char* message = XMLString::transcode(e.getMessage());
        std::string errMsg = "XMLException message is: ";
        errMsg += message;
        XMLString::release(&message);
        STG_EXCEPTION_ERROR(errMsg);
    }
    catch (const SAXParseException& e)
    {
        char* message = XMLString::transcode(e.getMessage());
        std::string errMsg = "SAXParseException message is: ";
        errMsg += message;
        XMLString::release(&message);
        STG_EXCEPTION_ERROR(errMsg);
    }
    catch (std::exception& e)
    {
        STG_EXCEPTION_ERROR(GMSG << "Exception message is: " << e.what());
    }
    catch (...)
    {
        STG_EXCEPTION_ERROR("Unexpected Exception");
    }
}

//////////////////////////////////////////////////////////////////////////
bool ApiStorage::IsHandleTag(const std::string& tagName) const
{
    return std::binary_search(std::begin(nodeNames), std::end(nodeNames), tagName);
}

//////////////////////////////////////////////////////////////////////////
EItemTag ApiStorage::TagName2TagValue(const std::string& tagName)
{
    EItemTag tag = EItemTag::enNone;
    auto it = std::lower_bound(std::begin(nodeNames), std::end(nodeNames), tagName);
    if (it != std::end(nodeNames))
    {
        tag = static_cast<EItemTag>(std::distance(std::begin(nodeNames), it) + 1);
    }
    return tag;
}

void ApiStorage::AddNode(const std::string& tagName, const std::map<std::string, std::string>& attrMap)
{
    EItemTag tag = TagName2TagValue(tagName);
    // TODO: implement
}

ext: cpp

max_stars_repo_name: dshadrin/RpcWrappersGenerator

max_issues_repo_name: dshadrin/RpcWrappersGenerator

max_forks_repo_name: dshadrin/RpcWrappersGenerator


text:
#pragma once
#include <hive/chain/hive_fwd.hpp>
#include <appbase/application.hpp>

#include <boost/config.hpp>

#define HIVE_STATSD_PLUGIN_NAME "statsd"

namespace hive { namespace plugins { namespace statsd {

using namespace appbase;

namespace detail
{
  class statsd_plugin_impl;
}

class statsd_plugin : public appbase::plugin< statsd_plugin >
{
  public:
    APPBASE_PLUGIN_REQUIRES()

    statsd_plugin();
    virtual ~statsd_plugin();

    virtual void set_program_options( options_description&, options_description& ) override;

    static const std::string& name() { static std::string name = HIVE_STATSD_PLUGIN_NAME; return name; }

    virtual void plugin_initialize( const variables_map& options ) override;
    virtual void plugin_startup() override;
    virtual void plugin_shutdown() override;

    // Starts statsd logging early, potentially before plugin_startup
    void start_logging();

    void increment( const std::string& ns, const std::string& stat, const std::string& key,                       const float frequency = 1.0f ) const noexcept;
    void decrement( const std::string& ns, const std::string& stat, const std::string& key,                       const float frequency = 1.0f ) const noexcept;
    void count(     const std::string& ns, const std::string& stat, const std::string& key, const int64_t delta,  const float frequency = 1.0f ) const noexcept;
    void gauge(     const std::string& ns, const std::string& stat, const std::string& key, const uint64_t value, const float frequency = 1.0f ) const noexcept;
    void timing(    const std::string& ns, const std::string& stat, const std::string& key, const uint32_t ms,    const float frequency = 1.0f ) const noexcept;

  private:
    std::unique_ptr< detail::statsd_plugin_impl > my;
};

} } } // hive::plugins::statsd

ext: hpp


text:
#include <typeinfo>
#include <boost/any.hpp>
#include <boost/chrono.hpp>
#include <windows.h>

#include "YDJAPI.h"
#include "BuiltinJAPI.h"

namespace NYDWE
{

struct STimePoint
{
	boost::any anyTimePoint;
};

static STimePoint *__cdecl JAPITimeGet(INT method)
{
	STimePoint *result = new STimePoint;

	switch (method)
	{
	case 1:
		result->anyTimePoint = boost::chrono::system_clock::now();
		break;
	case 2:
		result->anyTimePoint = boost::chrono::high_resolution_clock::now();
		break;
	default:
		result->anyTimePoint = boost::chrono::process_cpu_clock::now();
		break;
	}

	return result;
}

static INT __cdecl JAPITimeDiff(STimePoint *pBegin, STimePoint *pEnd)
{
	FLOAT result = 0;

	if (pBegin && pEnd && pBegin->anyTimePoint.type() == pEnd->anyTimePoint.type())
	{
		const std::type_info &typeInfo = pBegin->anyTimePoint.type();
		if (typeInfo == typeid(boost::chrono::system_clock::time_point))
		{
			boost::chrono::duration<float> dur = boost::any_cast<boost::chrono::system_clock::time_point>(pEnd->anyTimePoint)
				- boost::any_cast<boost::chrono::system_clock::time_point>(pBegin->anyTimePoint);
			result = dur.count();
		}
		else if (typeInfo == typeid(boost::chrono::high_resolution_clock::time_point))
		{
			boost::chrono::duration<float> dur = boost::any_cast<boost::chrono::high_resolution_clock::time_point>(pEnd->anyTimePoint)
				- boost::any_cast<boost::chrono::high_resolution_clock::time_point>(pBegin->anyTimePoint);
			result = dur.count();
		}
		else if (typeInfo == typeid(boost::chrono::process_cpu_clock::time_point))
		{
			boost::chrono::duration<float> dur = boost::any_cast<boost::chrono::process_cpu_clock::time_point>(pEnd->anyTimePoint)
				- boost::any_cast<boost::chrono::process_cpu_clock::time_point>(pBegin->anyTimePoint);
			result = dur.count();
		}
	}

	return (INT &)result;
}

static VOID __cdecl JAPITimeDelete(STimePoint *pTimePoint)
{
	delete pTimePoint;
}

void RegisterBuiltinJAPI()
{
	RegisterJAPINative(JAPITimeGet, "JAPITimeGet", "(I)I");
	RegisterJAPINative(JAPITimeDelete, "JAPITimeDelete", "(I)V");
	RegisterJAPINative(JAPITimeDiff, "JAPITimeDiff", "(II)R");
}

} // namespace NYDWE

max_stars_repo_name: luciouskami/XYWE

max_issues_repo_name: shawwwn/YDWE

max_forks_repo_name: shawwwn/YDWE


text:
/* Copyright © 2017 Apple Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-3-clause license that can
 * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
 */
#ifndef TC_DISABLE_REMOTEFS

#ifndef _WIN32
#include <arpa/inet.h>
#else
#include <ws2tcpip.h>
#endif
#include <memory>
#include <fstream>
#include <string>
#include <thread>
#include <future>
#include <regex>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/tokenizer.hpp>
#include <core/logging/logger.hpp>
#include <core/logging/assertions.hpp>
#include <core/storage/fileio/s3_api.hpp>
#include <core/storage/fileio/fs_utils.hpp>
#include <core/storage/fileio/general_fstream.hpp>
#include <core/storage/fileio/get_s3_endpoint.hpp>
#include <core/system/cppipc/server/cancel_ops.hpp>

/* aws */
#include <aws/core/Aws.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/ListObjectsV2Request.h>
#include <aws/s3/model/ListObjectsV2Result.h>
#include <aws/s3/model/DeleteObjectRequest.h>
#include <aws/s3/model/DeleteObjectsRequest.h>
#include <aws/s3/model/Delete.h>
#include <aws/core/auth/AWSCredentialsProvider.h>

using namespace Aws;
using namespace Aws::S3;
using namespace turi::fileio;

namespace turi {
namespace {

/**
 * Check the string is a valid s3 bucket name using the following criteria from
 * http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html:
 *
 * 1 Bucket names must be at least 3 and no more than 63 characters long.
 * 2 Bucket names must be a series of one or more labels.
 * 3 Adjacent labels are separated by a single period (.).
 * 4 Bucket names can contain lowercase letters, numbers, and hyphens.
 * 5 Each label must start and end with a lowercase letter or a number.
 * 6 Bucket names must not be formatted as an IP address (e.g., 192.168.5.4).
 *
 * Amendment 1:
 *   Uppercase letters are in fact fine... And it is in fact case sensitive.
 *   Our test bucket Turi-Datasets breaks a couple of the rules above.
 *   Tweaked to accept capital letters.
 *
 * Amendment 2:
 *   underscores are fine too
 */
bool bucket_name_valid(const std::string& bucket_name) {
  // rule 1
  if (bucket_name.size() < 3 || bucket_name.size() > 63) {
    return false;
  }

  // rule 2, 3
  typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
  boost::char_separator<char> sep(".");
  tokenizer labels(bucket_name, sep);
  tokenizer::iterator iter = labels.begin();
  if (iter == labels.end()) {
    return false;
  }

  // rule 4, 5
  auto label_valid = [](const std::string& label) {
    if (label.empty()) return false;
    using namespace std::regex_constants;

    auto alnum = [=](char x) { return (x <= 'Z' && x >= 'A') || (x <= 'z' && x >= 'a') || (x <= '9' && x >= '0'); };
    auto alnum_underscore_or_hypen = [=](char x) { return x == '-' || x == '_' || alnum(x); };

    // begin
    if (!alnum(*label.begin())) return false;
    // end
    if (!alnum(*(label.end()-1))) return false;
    // everything in between
    for (size_t i = 1; i < label.size() - 1; ++i) {
      if (!alnum_underscore_or_hypen(label[i])) return false;
    }
    return true;
  };
  while (iter != labels.end()) {
    if (!label_valid(*iter)) return false;
    ++iter;
  }

  // rule 6, to validate, let's try creating an ip address from the bucket name.
  struct sockaddr_in sa;
  int result = inet_pton(AF_INET, bucket_name.c_str(), &(sa.sin_addr));
  if (result != 0) return false;

  return true;
}

std::string string_from_s3url(const s3url& parsed_url) {
  std::string ret = "s3://" + parsed_url.access_key_id + ":"
      + parsed_url.secret_key + ":";
  if (!parsed_url.endpoint.empty()) {
    ret += parsed_url.endpoint + "/";
  }
  ret += parsed_url.bucket;
  if (!parsed_url.object_name.empty()) {
    ret += "/" + parsed_url.object_name;
  }
  return ret;
}

} // anonymous namespace

const std::vector<std::string> S3Operation::_enum_to_str = {
    "DeleteObjects", "ListObjects", "HeadObjects"};

/**
 * This splits a URL of the form
 * s3://[access_key_id]:[secret_key]:[endpoint/][bucket]/[object_name]
 * into several pieces.
 *
 * Returns true on success, false on failure.
 */
bool parse_s3url(std::string url, s3url& ret, std::string& err_msg) {
  // must begin with s3://
  if (fileio::get_protocol(url) != "s3") {
    err_msg = url + " doesn't start with 's3://'";
    return false;
  }
  // strip the s3://
  url = url.substr(5);
  err_msg.clear();

  // Extract the access key ID and secret key
  std::stringstream ss;
  size_t splitpos = url.find(':');
  if (splitpos == std::string::npos) {
    ss << "Cannot find AWS_ACCESS_KEY_ID in the s3 url." << __FILE__ << " at "
       << __LINE__;
    err_msg = ss.str();
    logstream(LOG_WARNING) << err_msg << std::endl;
    return false;
  } else {
    ret.access_key_id = url.substr(0, splitpos);
    url = url.substr(splitpos + 1);
  }
  // Extract the secret key
  splitpos = url.find(':');
  if (splitpos == std::string::npos) {
    ss << "Cannot find SECRET_AWS_ACCESS_KEY in the s3 url." << __LINE__
       << " at " << __FILE__;
    err_msg = ss.str();
    logstream(LOG_WARNING) << err_msg << std::endl;
    return false;
  } else {
    ret.secret_key = url.substr(0, splitpos);
    url = url.substr(splitpos + 1);
  }

  // The rest is parsed using boost::tokenizer
  typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
  boost::char_separator<char> sep("/");
  tokenizer tokens(url, sep);
  tokenizer::iterator iter = tokens.begin();
  if (iter == tokens.end()) {
    ss << "missing endpoint or bucket or object key in " << url << __FILE__
       << "at" << __LINE__;
    err_msg = ss.str();
    return false;
  }

  auto original_url = sanitize_url(url);
  // Parse endpoints; since we support private cloud settings
  // url can be tricky; region (.*)com is not sufficient
  if (std::regex_match(*iter, std::regex("(.*)\\.(com|net)"))) {
    ret.endpoint = *iter;
    ++iter;
  }

  // Parse bucket name
  if (iter == tokens.end()) {
    ss << "missing bucket name in " << '\'' << original_url << '\'' << " in "
       << __FILE__ << " at " << __LINE__;
    err_msg = ss.str();
    return false;
  }
  if (!bucket_name_valid(*iter)) {
    ss << '\'' << original_url << '\'' << " has invalid bucket name: " << *iter;
    err_msg = ss.str();
    logstream(LOG_WARNING) << err_msg << std::endl;
    return false;
  }
  ret.bucket = *iter;
  ++iter;

  // The rest part is the object key
  if (iter == tokens.end()) {
    // no object key
    return true;
  }

  ret.object_name = *iter;
  ++iter;
  while (iter != tokens.end()) {
    ret.object_name += "/" + *iter;
    ++iter;
  }

  // std::cout << "Access Key: " << ret.access_key_id << "\n"
  //           << "Secret Key: " << ret.secret_key<< "\n"
  //           << "Bucket: " << ret.bucket<< "\n"
  //           << "Object: " << ret.object_name<< "\n"
  //           << "Endpoint: " << ret.endpoint << "\n";
  return true;
}

// The options we pass to aws cli for s3 commands
// "us-east-1" is the us-standard and it works with buckets from all regions
// "acl" grants the bucket owner full permission regardless of the uploader's account
static const std::string S3_COMMAND_OPTION = "--region us-east-1 --acl bucket-owner-full-control";

std::string validate_input_file(const std::string& local_file) {
  // Try to open the input file
  std::shared_ptr<turi::general_ifstream> fin(
      new turi::general_ifstream(local_file.c_str(),
                                     false)); // gzip_compressed.
                                             // We avoid decompressing the file
                                             // on transfer. i.e. if the file is
                                             // compressed/uncompressed to begin
                                             // with, lets  keep it that way.

  // file cannot be opened
  if (!fin->good()) {
    return std::string("File ") + local_file + " cannot be opened.";
  }

  // get the file size. Return failure on failure.
  size_t file_size = fin->file_size();
  if (file_size == (size_t)(-1)) {
    return std::string("Size of file ") + local_file + " cannot be obtained.";
  }
  return "";
}

std::string validate_output_file(const std::string& local_file) {
  // Try to open the output file
  std::shared_ptr<turi::general_ofstream> fout(
      new turi::general_ofstream(local_file.c_str(),
                                     false));// gzip_compressed.
                                             // We avoid recompressing the file
                                             // on transfer. i.e. if the file is
                                             // compressed/uncompressed to begin
                                             // with, lets  keep it that way.
  // file cannot be opened
  if (!fout->good()) {
    // return a failure immediately.
    return std::string("File ") + local_file + " cannot be opened.";
  }
  return "";
}

/**
 * Adding single quote around the path, and escape all single quotes inside the path.
 */
std::string quote_and_escape_path(const std::string& path) {
  // s3 keys are at most 1024 bytes,
  // we make the buffer three times bigger
  // and it should be enough to conver the length of escaped path s3://bucket_name/key
  const size_t BUF_SIZE = 1024 * 3;
  char* buf = new char[BUF_SIZE];
  size_t current_pos = 0;
  buf[current_pos++] = '\"'; // begin quote
  for (const auto& c : path) {
    if (c == '\'') {
      buf[current_pos++] = '\\'; // escape quote
      if (current_pos >= BUF_SIZE) {
        delete[] buf;
        throw("Invalid path: exceed length limit");
      }
    }
    buf[current_pos++] = c;
    if (current_pos >= BUF_SIZE) {
      delete[] buf;
      throw("Invalid path: exceed length limit");
    }
  }
  buf[current_pos++] = '\"'; // end quote
  std::string ret(buf, current_pos);
  delete[] buf;
  return ret;
}

list_objects_response list_objects_impl(s3url parsed_url,
                                        std::string proxy,
                                        std::string endpoint)
{
    // initialization
    Aws::SDKOptions options;
    options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Info;
    Aws::InitAPI(options);

    // credentials
    Aws::Auth::AWSCredentials credentials(parsed_url.access_key_id.c_str(), parsed_url.secret_key.c_str());

    // s3 client config
    Aws::Client::ClientConfiguration clientConfiguration;
    if (turi::fileio::insecure_ssl_cert_checks()) {
      clientConfiguration.verifySSL = false;
    }
    if (parsed_url.endpoint.empty()) {
      clientConfiguration.endpointOverride = endpoint.c_str();
    } else {
      clientConfiguration.endpointOverride = parsed_url.endpoint.c_str();
    }
    clientConfiguration.proxyHost = proxy.c_str();
    clientConfiguration.requestTimeoutMs = 5 * 60000;
    clientConfiguration.connectTimeoutMs = 20000;
    std::string region = fileio::get_region_name_from_endpoint(clientConfiguration.endpointOverride.c_str());
    clientConfiguration.region = region.c_str();

    S3Client client(credentials, clientConfiguration);

    list_objects_response ret;

    Aws::S3::Model::ListObjectsV2Request request;
    request.WithBucket(parsed_url.bucket.c_str());
    request.WithPrefix(parsed_url.object_name.c_str());
    request.WithDelimiter("/"); // seperate objects from directories

    bool moreResults = false;
    do
    {
        auto outcome = client.ListObjectsV2(request);
        if(outcome.IsSuccess())
        {
            auto result = outcome.GetResult();

            // now iterate through found objects - these are files
            Aws::Vector<Aws::S3::Model::Object> objects;
            objects = result.GetContents();
            for (auto const& o : objects)
            {
                // std::cout << "object: " << objects[i].GetKey() << ", size: " << objects[i].GetSize() << ", last_modified: " << objects[i].GetLastModified().Millis() << std::endl;
                ret.objects.push_back(std::string(o.GetKey().c_str()));
                std::stringstream stream;
                stream << o.GetLastModified().Millis();
                ret.objects_last_modified.push_back(stream.str());
            }

            // now iterate through common prefixes - these are directories
            Aws::Vector<Aws::S3::Model::CommonPrefix> prefixes;
            prefixes = result.GetCommonPrefixes();
            for (auto const& p : prefixes)
            {
                // std::cout << "directory: " << prefixes[i].GetPrefix() << std::endl;
                std::string key = std::string(p.GetPrefix().c_str());
                // strip the ending "/" on a directory
                if (boost::ends_with(key, "/")) key = key.substr(0, key.length() - 1);
                ret.directories.push_back(key);
            }

            // more results to retrieve
            moreResults = result.GetIsTruncated();
            if (moreResults)
            {
                // add to the request object with continuation token
                request.WithContinuationToken(result.GetContinuationToken());
            }

        }
        else
        {
            std::stringstream ss;
            reportS3ErrorDetailed(ss, parsed_url, S3Operation::List,
                                  clientConfiguration, outcome)
                << std::endl;
            ret.error = ss.str();
        }

    } while (moreResults);

    Aws::ShutdownAPI(options);
    for (auto& dir : ret.directories) {
      s3url dirurl = parsed_url;
      dirurl.object_name = dir;
      dir = string_from_s3url(dirurl);
    }
    for (auto& object: ret.objects) {
      s3url objurl = parsed_url;
      objurl.object_name = object;
      object = string_from_s3url(objurl);
    }
    return ret;
}

/// returns an error string on failure. Empty string on success
std::string delete_object_impl(s3url parsed_url,
                               std::string proxy,
                               std::string endpoint) {
    std::string ret;

    // initialization
    Aws::SDKOptions options;
    options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Info;
    Aws::InitAPI(options);

    // credentials
    Aws::Auth::AWSCredentials credentials(parsed_url.access_key_id.c_str(), parsed_url.secret_key.c_str());

    // s3 client config
    Aws::Client::ClientConfiguration clientConfiguration;
    if (turi::fileio::insecure_ssl_cert_checks()) {
      clientConfiguration.verifySSL = false;
    }

    if (parsed_url.endpoint.empty()) {
      clientConfiguration.endpointOverride = endpoint.c_str();
    } else {
      clientConfiguration.endpointOverride = parsed_url.endpoint.c_str();
    }

    clientConfiguration.proxyHost = proxy.c_str();
    clientConfiguration.requestTimeoutMs = 5 * 60000;
    clientConfiguration.connectTimeoutMs = 20000;
    std::string region = fileio::get_region_name_from_endpoint(clientConfiguration.endpointOverride.c_str());
    clientConfiguration.region = region.c_str();

    S3Client client(credentials, clientConfiguration);

    Aws::S3::Model::DeleteObjectRequest request;
    request.WithBucket(parsed_url.bucket.c_str());
    request.WithKey(parsed_url.object_name.c_str());

    auto outcome = client.DeleteObject(request);
    if(!outcome.IsSuccess())
    {
      std::stringstream ss;
      reportS3ErrorDetailed(ss, parsed_url, S3Operation::Delete,
                            clientConfiguration, outcome) << std::endl;
      ret = ss.str();
    }

    Aws::ShutdownAPI(options);
    return ret;
}

/// returns an error string on failure. Empty string on success
std::string delete_prefix_impl(s3url parsed_url,
                               std::string proxy,
                               std::string endpoint) {

    // List objects and then create a DeleteObjects request from the resulting list

    std::string ret;

    // initialization
    Aws::SDKOptions options;
    options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Info;
    Aws::InitAPI(options);

    // credentials
    Aws::Auth::AWSCredentials credentials(parsed_url.access_key_id.c_str(), parsed_url.secret_key.c_str());

    // s3 client config
    Aws::Client::ClientConfiguration clientConfiguration;
    if (turi::fileio::insecure_ssl_cert_checks()) {
      clientConfiguration.verifySSL = false;
    }

    if (parsed_url.endpoint.empty()) {
      clientConfiguration.endpointOverride = endpoint.c_str();
    } else {
      clientConfiguration.endpointOverride = parsed_url.endpoint.c_str();
    }

    clientConfiguration.proxyHost = proxy.c_str();
    clientConfiguration.requestTimeoutMs = 5 * 60000;
    clientConfiguration.connectTimeoutMs = 20000;
    std::string region = fileio::get_region_name_from_endpoint(clientConfiguration.endpointOverride.c_str());
    clientConfiguration.region = region.c_str();

    S3Client client(credentials, clientConfiguration);

    Aws::S3::Model::ListObjectsV2Request request;
    request.WithBucket(parsed_url.bucket.c_str());
    request.WithPrefix(parsed_url.object_name.c_str());

    // keep retrieving objects until no more objects match query
    bool moreResults = false;
    Aws::S3::Model::Delete deleteObjects;
    do
    {
        auto outcome = client.ListObjectsV2(request);
        if(outcome.IsSuccess())
        {
            auto result = outcome.GetResult();

            // now iterate through found objects and construct DeleteObjects request with them
            auto objects = result.GetContents();
            for (auto const& o : objects)
            {
                Aws::S3::Model::ObjectIdentifier key;
                deleteObjects.AddObjects(key.WithKey(o.GetKey()));
            }

            // more results to retrieve
            moreResults = result.GetIsTruncated();
            if (moreResults)
            {
                // add to the request object with continuation token
                request.WithContinuationToken(result.GetContinuationToken());
            }

        }
        else
        {
            std::stringstream ss;
            reportS3ErrorDetailed(ss, parsed_url, S3Operation::List,
                                  clientConfiguration, outcome)
                << std::endl;
            ret = ss.str();
        }

    } while (moreResults);

    if (deleteObjects.GetObjects().size() > 0)
    {
        Aws::S3::Model::DeleteObjectsRequest delRequest;
        delRequest.WithBucket(parsed_url.bucket.c_str());
        delRequest.WithDelete(deleteObjects);

        auto outcome = client.DeleteObjects(delRequest);
        if (!outcome.IsSuccess())
        {
          std::stringstream ss;
          reportS3ErrorDetailed(ss, parsed_url, S3Operation::Delete,
                                clientConfiguration, outcome)
              << std::endl;
          ret = ss.str();
        }
    }

    Aws::ShutdownAPI(options);
    return ret;
}

list_objects_response list_objects(std::string url,
                                   std::string proxy) {
  s3url parsed_url;
  list_objects_response ret;
  std::string err_msg;
  bool success = parse_s3url(url, parsed_url, err_msg);
  if (!success) {
    ret.error = err_msg;
    return ret;
  }

  size_t current_endpoint = 0;
  // try all endpoints
  auto endpoints = get_s3_endpoints();
  do {
    ret = list_objects_impl(parsed_url, proxy, endpoints[current_endpoint]);
    ++current_endpoint;
  } while (boost::algorithm::icontains(ret.error, "PermanentRedirect") &&
         current_endpoint < endpoints.size());

  return ret;
}

std::pair<file_status, list_objects_response>
is_directory(std::string url, std::string proxy) {
  s3url parsed_url;
  list_objects_response ret;
  std::string err_msg;
  bool success = parse_s3url(url, parsed_url, err_msg);
  if (!success) {
    ret.error = std::move(err_msg);
    return {file_status::MISSING, ret};
  }
  // if there are no "/"'s it is just a top level bucket

  list_objects_response response = list_objects(url, proxy);
  // an error occured
  if (!response.error.empty()) {
    return {file_status::MISSING, response};
  }

  // its a top level bucket name
  if (parsed_url.object_name.empty()) {
    return {file_status::DIRECTORY, response};
  }

  // is a directory
  for (auto dir: response.directories) {
    if (dir == url) {
      return {file_status::DIRECTORY, response};
    }
  }

  // is an object
  for (auto object: response.objects) {
    if (object == url) {
      return {file_status::REGULAR_FILE, response};
    }
  }

  // is not found
  return {file_status::MISSING, response};
}

list_objects_response list_directory(std::string url, std::string proxy) {
  s3url parsed_url;
  list_objects_response ret;
  std::string err_msg;
  bool success = parse_s3url(url, parsed_url, err_msg);
  if (!success) {
    ret.error = err_msg;
    return ret;
  }
  // normalize the URL so it doesn't matter if you put strange "/"s at the end
  url = string_from_s3url(parsed_url);
  auto isdir = is_directory(url, proxy);
  // if not found.
  if (isdir.first == file_status::MISSING) return isdir.second;
  // if its a directory
  if (isdir.first == file_status::DIRECTORY) {
    // if there are no "/"'s it is a top level bucket and we don't need
    // to mess with prefixes to get the contents
    if (!parsed_url.object_name.empty()) {
      parsed_url.object_name = parsed_url.object_name + "/";
    }
    size_t current_endpoint = 0;

    // try all endpoints
    auto endpoints = get_s3_endpoints();
    do {
      ret = list_objects_impl(parsed_url, proxy, endpoints[current_endpoint]);
      ++current_endpoint;
    } while (boost::algorithm::icontains(ret.error, "PermanentRedirect") &&
           current_endpoint < endpoints.size());
  } else {
    ret.objects.push_back(url);
  }

  return ret;
}

std::string delete_object(std::string url,
                          std::string proxy) {
  s3url parsed_url;
  std::string err_msg;

  bool success = parse_s3url(url, parsed_url, err_msg);
  if (!success) {
    return err_msg;
  }
  // try all endpoints
  size_t current_endpoint = 0;
  auto endpoints = get_s3_endpoints();
  do {
    err_msg = delete_object_impl(parsed_url, proxy, endpoints[current_endpoint]);
    ++current_endpoint;
  } while (boost::algorithm::icontains(err_msg , "PermanentRedirect") &&
         current_endpoint < endpoints.size());

  return err_msg;
}

std::string delete_prefix(std::string url,
                          std::string proxy) {
  s3url parsed_url;
  std::string err_msg;
  bool success = parse_s3url(url, parsed_url, err_msg);
  if (!success) {
    return err_msg;
  }
  // try all endpoints
  size_t current_endpoint = 0;
  auto endpoints = get_s3_endpoints();
  do {
    err_msg = delete_prefix_impl(parsed_url, proxy, endpoints[current_endpoint]);
    ++current_endpoint;
  } while (boost::algorithm::icontains(err_msg, "PermanentRedirect") &&
         current_endpoint < endpoints.size());

  return err_msg;
}

std::string sanitize_s3_url_aggressive(std::string url) {
  // must begin with s3://
  if (fileio::get_protocol(url) != "s3") {
    return url;
  }
  // strip the s3://
  url = url.substr(5);

  // strip the secret key and the access key following the usual rules.
  size_t splitpos = url.find(':');
  if (splitpos != std::string::npos) url = url.substr(splitpos + 1);
  splitpos = url.find(':');
  if (splitpos != std::string::npos) url = url.substr(splitpos + 1);

  // now, a user error is possible where ":" shows up inside the
  // secret key / access key thus leaking part of a key in the logs.
  // so we also perform a more aggressive truncation.
  // find the first "/" and delete everything up to the last ":"
  // before the first "/"
  size_t bucketend = url.find('/');
  if (bucketend == std::string::npos) bucketend = url.length();
  size_t last_colon = url.find_last_of(':', bucketend);
  if (last_colon != std::string::npos) url = url.substr(last_colon + 1);
  return "s3://" + url;
}

std::string sanitize_s3_url(const std::string& url) {
  s3url parsed_url;
  std::string err_msg;
  auto ret = parse_s3url(url, parsed_url, err_msg);
  DASSERT_EQ(ret, err_msg.empty());
  if (ret) {
    if (parsed_url.endpoint.empty())
      return "s3://" + parsed_url.bucket + "/" + parsed_url.object_name;
    else
      return "s3://" + parsed_url.endpoint + "/" + parsed_url.bucket + "/" + parsed_url.object_name;
  } else {
    return sanitize_s3_url_aggressive(url);
  };
}

std::string get_s3_error_code(const std::string& msg) {
  static const std::vector<std::string> errorcodes {
    "AccessDenied", "NoSuchBucket", "InvalidAccessKeyId",
    "InvalidBucketName", "KeyTooLong", "NoSuchKey", "RequestTimeout"
  };

  // User friendly error codes, return immediately.
  for (const auto& ec : errorcodes) {
    if (boost::algorithm::icontains(msg, ec)) {
      return msg;
    }
  }

  // Error code that may need some explanation.
  // Add messages for error code below:
  // ...
  // best guess for 403 error
  if (boost::algorithm::icontains(msg, "forbidden")) {
    return "403 Forbidden. Please check your AWS credentials and permission to the file.";
  }

  return msg;
}

std::string get_s3_file_last_modified(const std::string& url){
  list_objects_response response = list_objects(url);
  if (response.error.empty() && response.objects_last_modified.size() == 1) {
    return response.objects_last_modified[0];
  } else if (!response.error.empty()) {
    logstream(LOG_WARNING) << "List object error: " << response.error << " " << __FILE__ << " at " << __LINE__ << std::endl;
    throw(response.error);
  }
  return "";
}

}

#endif

max_stars_repo_name: syoutsey/turicreate

max_issues_repo_name: lukereichold/turicreate

max_forks_repo_name: syoutsey/turicreate


text:
////////////////////////////////////////////////////////////////////////////////////////////////////
// apply.hpp
// Treat the first argument as a callable and the others as arguments to the
// callable
//
//  Copyright 2012 Eric Niebler. Distributed under the Boost
//  Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_PROTO_V5_ACTION_APPLY_HPP_INCLUDED
#define BOOST_PROTO_V5_ACTION_APPLY_HPP_INCLUDED

#include <boost/proto/v5/proto_fwd.hpp>
#include <boost/proto/v5/utility.hpp>
#include <boost/proto/v5/action/basic_action.hpp>
#include <boost/proto/v5/action/call.hpp>
#include <boost/proto/v5/utility.hpp>

namespace boost
{
    namespace proto
    {
        inline namespace v5
        {
            namespace detail
            {
                template<typename Fun, typename ...Actions>
                struct _apply
                  : basic_action<_apply<Fun, Actions...>>
                {
                    template<typename ...Args>
                    constexpr auto operator()(Args &&... args) const
                    BOOST_PROTO_AUTO_RETURN(
                        BOOST_PROTO_TRY_CALL(detail::call_1_<true, Actions...>())(
                            call_action_<Fun>()(static_cast<Args &&>(args)...)
                          , static_cast<Args &&>(args)...
                        )
                    )
                };
            }

            struct apply
            {};

            namespace extension
            {
                template<typename Fun, typename ...Actions>
                struct action_impl<apply(Fun, Actions...)>
                  : detail::_apply<Fun, Actions...>
                {};
            }
        }
    }
}

#endif


text:
#include <NTL/xdouble.h>
#include <NTL/RR.h>

NTL_START_IMPL

NTL_CHEAP_THREAD_LOCAL
long xdouble::oprec = 10;

void xdouble::SetOutputPrecision(long p)
{
   if (p < 1) p = 1;

   if (NTL_OVERFLOW(p, 1, 0))
      ResourceError("xdouble: output precision too big");

   oprec = p;
}

void xdouble::normalize()
{
   if (x == 0)
      e = 0;
   else if (x > 0) {
      while (x < NTL_XD_HBOUND_INV) { x *= NTL_XD_BOUND; e--; }
      while (x > NTL_XD_HBOUND) { x *= NTL_XD_BOUND_INV; e++; }
   }
   else {
      while (x > -NTL_XD_HBOUND_INV) { x *= NTL_XD_BOUND; e--; }
      while (x < -NTL_XD_HBOUND) { x *= NTL_XD_BOUND_INV; e++; }
   }

   if (e >= NTL_OVFBND)
      ResourceError("xdouble: overflow");

   if (e <= -NTL_OVFBND)
      ResourceError("xdouble: underflow");
}

xdouble to_xdouble(double a)
{
   if (a == 0 || a == 1 || (a > 0 && a >= NTL_XD_HBOUND_INV && a <= NTL_XD_HBOUND)
       || (a < 0 && a <= -NTL_XD_HBOUND_INV && a >= -NTL_XD_HBOUND)) {

      return xdouble(a, 0);

   }

   if (!IsFinite(&a))
      ArithmeticError("double to xdouble conversion: non finite value");

   xdouble z = xdouble(a, 0);
   z.normalize();
   return z;
}

void conv(double& xx, const xdouble& a)
{
   double x;
   long e;

   x = a.x;
   e = a.e;

   while (e > 0) { x *= NTL_XD_BOUND; e--; }
   while (e < 0) { x *= NTL_XD_BOUND_INV; e++; }

   xx = x;
}

xdouble operator+(const xdouble& a, const xdouble& b)
{
   xdouble z;

   if (a.x == 0)
      return b;

   if (b.x == 0)
     return a;

   if (a.e == b.e) {
      z.x = a.x + b.x;
      z.e = a.e;
      z.normalize();
      return z;
   }
   else if (a.e > b.e) {
      if (a.e > b.e+1)
         return a;

      z.x = a.x + b.x*NTL_XD_BOUND_INV;
      z.e = a.e;
      z.normalize();
      return z;
   }
   else {
      if (b.e > a.e+1)
         return b;

      z.x = a.x*NTL_XD_BOUND_INV + b.x;
      z.e = b.e;
      z.normalize();
      return z;
   }
}

xdouble operator-(const xdouble& a, const xdouble& b)
{
   xdouble z;

   if (a.x == 0)
      return -b;

   if (b.x == 0)
      return a;

   if (a.e == b.e) {
      z.x = a.x - b.x;
      z.e = a.e;
      z.normalize();
      return z;
   }
   else if (a.e > b.e) {
      if (a.e > b.e+1)
         return a;

      z.x = a.x - b.x*NTL_XD_BOUND_INV;
      z.e = a.e;
      z.normalize();
      return z;
   }
   else {
      if (b.e > a.e+1)
         return -b;

      z.x = a.x*NTL_XD_BOUND_INV - b.x;
      z.e = b.e;
      z.normalize();
      return z;
   }
}

xdouble operator-(const xdouble& a)
{
   xdouble z;
   z.x = -a.x;
   z.e = a.e;
   return z;
}

xdouble operator*(const xdouble& a, const xdouble& b)
{
   xdouble z;

   z.e = a.e + b.e;
   z.x = a.x * b.x;
   z.normalize();
   return z;
}

xdouble operator/(const xdouble& a, const xdouble& b)
{
   xdouble z;

   if (b.x == 0) ArithmeticError("xdouble division by 0");

   z.e = a.e - b.e;
   z.x = a.x / b.x;
   z.normalize();
   return z;
}

long compare(const xdouble& a, const xdouble& b)
{
   xdouble z = a - b;

   if (z.x < 0)
      return -1;
   else if (z.x == 0)
      return 0;
   else
      return 1;
}

long sign(const xdouble& z)
{
   if (z.x < 0)
      return -1;
   else if (z.x == 0)
      return 0;
   else
      return 1;
}

xdouble trunc(const xdouble& a)
{
   if (a.x >= 0)
      return floor(a);
   else
      return ceil(a);
}

xdouble floor(const xdouble& aa)
{
   xdouble z;

   xdouble a = aa;
   ForceToMem(&a.x);

   if (a.e == 0) {
      z.x = floor(a.x);
      z.e = 0;
      z.normalize();
      return z;
   }
   else if (a.e > 0) {
      return a;
   }
   else {
      if (a.x < 0)
         return to_xdouble(-1);
      else
         return to_xdouble(0);
   }
}

xdouble ceil(const xdouble& aa)
{
   xdouble z;

   xdouble a = aa;
   ForceToMem(&a.x);

   if (a.e == 0) {
      z.x = ceil(a.x);
      z.e = 0;
      z.normalize();
      return z;
   }
   else if (a.e > 0) {
      return a;
   }
   else {
      if (a.x < 0)
         return to_xdouble(0);
      else
         return to_xdouble(1);
   }
}

xdouble to_xdouble(const ZZ& a)
{
   RRPush push;
   RR::SetPrecision(NTL_DOUBLE_PRECISION);

   NTL_TLS_LOCAL(RR, t);
   conv(t, a);

   double x;
   conv(x, t.mantissa());

   xdouble y, z, res;

   conv(y, x);
   power2(z, t.exponent());

   res = y*z;

   return res;
}

void conv(ZZ& x, const xdouble& a)
{
   xdouble b = floor(a);

   RRPush push;
   RR::SetPrecision(NTL_DOUBLE_PRECISION);

   NTL_TLS_LOCAL(RR, t);
   conv(t, b);
   conv(x, t);
}

xdouble fabs(const xdouble& a)
{
   xdouble z;

   z.e = a.e;
   z.x = fabs(a.x);
   return z;
}

xdouble sqrt(const xdouble& a)
{
   if (a == 0)
      return to_xdouble(0);

   if (a < 0)
      ArithmeticError("xdouble: sqrt of negative number");

   xdouble t;

   if (a.e & 1) {
      t.e = (a.e - 1)/2;
      t.x = sqrt(a.x * NTL_XD_BOUND);
   }
   else {
      t.e = a.e/2;
      t.x = sqrt(a.x);
   }

   t.normalize();

   return t;
}

void power(xdouble& z, const xdouble& a, const ZZ& e)
{
   xdouble b, res;

   b = a;

   res = 1;
   long n = NumBits(e);
   long i;

   for (i = n-1; i >= 0; i--) {
      res = res * res;
      if (bit(e, i))
         res = res * b;
   }

   if (sign(e) < 0)
      z = 1/res;
   else
      z = res;
}

void power(xdouble& z, const xdouble& a, long e)
{
   NTL_ZZRegister(E);
   E = e;
   power(z, a, E);
}

void power2(xdouble& z, long e)
{
   long hb = NTL_XD_HBOUND_LOG;
   long b = 2*hb;

   long q, r;

   q = e/b;
   r = e%b;

   while (r >= hb) {
      r -= b;
      q++;
   }

   while (r < -hb) {
      r += b;
      q--;
   }

   if (q >= NTL_OVFBND)
      ResourceError("xdouble: overflow");

   if (q <= -NTL_OVFBND)
      ResourceError("xdouble: underflow");

   double x = _ntl_ldexp(1.0, r);

   z.x = x;
   z.e = q;
}

void MulAdd(xdouble& z, const xdouble& a, const xdouble& b, const xdouble& c)
// z = a + b*c
{
   double x;
   long e;

   e = b.e + c.e;
   x = b.x * c.x;

   if (x == 0) {
      z = a;
      return;
   }

   if (a.x == 0) {
      z.e = e;
      z.x = x;
      z.normalize();
      return;
   }

   if (a.e == e) {
      z.x = a.x + x;
      z.e = e;
      z.normalize();
      return;
   }
   else if (a.e > e) {
      if (a.e > e+1) {
         z = a;
         return;
      }

      z.x = a.x + x*NTL_XD_BOUND_INV;
      z.e = a.e;
      z.normalize();
      return;
   }
   else {
      if (e > a.e+1) {
         z.x = x;
         z.e = e;
         z.normalize();
         return;
      }

      z.x = a.x*NTL_XD_BOUND_INV + x;
      z.e = e;
      z.normalize();
      return;
   }
}

void MulSub(xdouble& z, const xdouble& a, const xdouble& b, const xdouble& c)
// z = a - b*c
{
   double x;
   long e;

   e = b.e + c.e;
   x = b.x * c.x;

   if (x == 0) {
      z = a;
      return;
   }

   if (a.x == 0) {
      z.e = e;
      z.x = -x;
      z.normalize();
      return;
   }

   if (a.e == e) {
      z.x = a.x - x;
      z.e = e;
      z.normalize();
      return;
   }
   else if (a.e > e) {
      if (a.e > e+1) {
         z = a;
         return;
      }

      z.x = a.x - x*NTL_XD_BOUND_INV;
      z.e = a.e;
      z.normalize();
      return;
   }
   else {
      if (e > a.e+1) {
         z.x = -x;
         z.e = e;
         z.normalize();
         return;
      }

      z.x = a.x*NTL_XD_BOUND_INV - x;
      z.e = e;
      z.normalize();
      return;
   }
}

double log(const xdouble& a)
{
   static const double LogBound = log(NTL_XD_BOUND); // GLOBAL (assumes C++11 thread-safe init)
   if (a.x <= 0) {
      ArithmeticError("log(xdouble): argument must be positive");
   }

   return log(a.x) + a.e*LogBound;
}

xdouble xexp(double x)
{
   const double LogBound = log(NTL_XD_BOUND);

   double y = x/LogBound;
   double iy = floor(y+0.5);

   if (iy >= NTL_OVFBND)
      ResourceError("xdouble: overflow");

   if (iy <= -NTL_OVFBND)
      ResourceError("xdouble: underflow");

   double fy = y - iy;

   xdouble res;
   res.e = long(iy);
   res.x = exp(fy*LogBound);
   res.normalize();
   return res;
}

/**************  input / output routines **************/

void ComputeLn2(RR&);
void ComputeLn10(RR&);

long ComputeMax10Power()
{
   RRPush push;
   RR::SetPrecision(NTL_BITS_PER_LONG);

   RR ln2, ln10;
   ComputeLn2(ln2);
   ComputeLn10(ln10);

   long k = to_long( to_RR(NTL_OVFBND/2) * ln2 / ln10 );
   return k;
}

xdouble PowerOf10(const ZZ& e)
{
   static NTL_CHEAP_THREAD_LOCAL long init = 0;
   static NTL_CHEAP_THREAD_LOCAL long k = 0;

   NTL_TLS_LOCAL(xdouble, v10k);

   if (!init) {
      k = ComputeMax10Power();
      RRPush push;
      RR::SetPrecision(NTL_DOUBLE_PRECISION);
      v10k = to_xdouble(power(to_RR(10), k));
      init = 1;
   }

   ZZ e1;
   long neg;

   if (e < 0) {
      e1 = -e;
      neg = 1;
   }
   else {
      e1 = e;
      neg = 0;
   }

   long r;
   ZZ q;

   r = DivRem(q, e1, k);

   RRPush push;
   RR::SetPrecision(NTL_DOUBLE_PRECISION);
   xdouble x1 = to_xdouble(power(to_RR(10), r));

   xdouble x2 = power(v10k, q);
   xdouble x3 = x1*x2;

   if (neg) x3 = 1/x3;

   return x3;
}

ostream& operator<<(ostream& s, const xdouble& a)
{
   if (a == 0) {
      s << "0";
      return s;
   }

   RRPush push;
   long temp_p = long(log(fabs(log(fabs(a))) + 1.0)/log(2.0)) + 10;
   RR::SetPrecision(temp_p);

   RR ln2, ln10, log_2_10;
   ComputeLn2(ln2);
   ComputeLn10(ln10);
   log_2_10 = ln10/ln2;
   ZZ log_10_a = to_ZZ(
  (to_RR(a.e)*to_RR(2*NTL_XD_HBOUND_LOG) + log(fabs(a.x))/log(2.0))/log_2_10);

   xdouble b;
   long neg;

   if (a < 0) {
      b = -a;
      neg = 1;
   }
   else {
      b = a;
      neg = 0;
   }

   ZZ k = xdouble::OutputPrecision() - log_10_a;

   xdouble c, d;

   c = PowerOf10(to_ZZ(xdouble::OutputPrecision()));
   d = PowerOf10(log_10_a);

   b = b / d;
   b = b * c;

   while (b < c) {
      b = b * 10.0;
      k++;
   }

   while (b >= c) {
      b = b / 10.0;
      k--;
   }

   b = b + 0.5;
   k = -k;

   ZZ B;
   conv(B, b);

   long bp_len = xdouble::OutputPrecision()+10;

   UniqueArray<char> bp_store;
   bp_store.SetLength(bp_len);
   char *bp = bp_store.get();

   long len, i;

   len = 0;
   do {
      if (len >= bp_len) LogicError("xdouble output: buffer overflow");
      bp[len] = IntValToChar(DivRem(B, B, 10));
      len++;
   } while (B > 0);

   for (i = 0; i < len/2; i++) {
      char tmp;
      tmp = bp[i];
      bp[i] = bp[len-1-i];
      bp[len-1-i] = tmp;
   }

   i = len-1;
   while (bp[i] == '0') i--;

   k += (len-1-i);
   len = i+1;

   bp[len] = '\0';

   if (k > 3 || k < -len - 3) {
      // use scientific notation

      if (neg) s << "-";
      s << "0." << bp << "e" << (k + len);
   }
   else {
      long kk = to_long(k);

      if (kk >= 0) {
         if (neg) s << "-";
         s << bp;
         for (i = 0; i < kk; i++)
            s << "0";
      }
      else if (kk <= -len) {
         if (neg) s << "-";
         s << "0.";
         for (i = 0; i < -len-kk; i++)
            s << "0";
         s << bp;
      }
      else {
         if (neg) s << "-";
         for (i = 0; i < len+kk; i++)
            s << bp[i];

         s << ".";

         for (i = len+kk; i < len; i++)
            s << bp[i];
      }
   }

   return s;
}

istream& operator>>(istream& s, xdouble& x)
{
   long c;
   long cval;
   long sign;
   ZZ a, b;

   if (!s) NTL_INPUT_ERROR(s, "bad xdouble input");

   c = s.peek();
   while (IsWhiteSpace(c)) {
      s.get();
      c = s.peek();
   }

   if (c == '-') {
      sign = -1;
      s.get();
      c = s.peek();
   }
   else
      sign = 1;

   long got1 = 0;
   long got_dot = 0;
   long got2 = 0;

   a = 0;
   b = 1;

   cval = CharToIntVal(c);

   if (cval >= 0 && cval <= 9) {
      got1 = 1;

      while (cval >= 0 && cval <= 9) {
         mul(a, a, 10);
         add(a, a, cval);
         s.get();
         c = s.peek();
         cval = CharToIntVal(c);
      }
   }

   if (c == '.') {
      got_dot = 1;

      s.get();
      c = s.peek();
      cval = CharToIntVal(c);

      if (cval >= 0 && cval <= 9) {
         got2 = 1;

         while (cval >= 0 && cval <= 9) {
            mul(a, a, 10);
            add(a, a, cval);
            mul(b, b, 10);
            s.get();
            c = s.peek();
            cval = CharToIntVal(c);
         }
      }
   }

   if (got_dot && !got1 && !got2)  NTL_INPUT_ERROR(s, "bad xdouble input");

   ZZ e;

   long got_e = 0;
   long e_sign;

   if (c == 'e' || c == 'E') {
      got_e = 1;

      s.get();
      c = s.peek();

      if (c == '-') {
         e_sign = -1;
         s.get();
         c = s.peek();
      }
      else if (c == '+') {
         e_sign = 1;
         s.get();
         c = s.peek();
      }
      else
         e_sign = 1;

      cval = CharToIntVal(c);

      if (cval < 0 || cval > 9) NTL_INPUT_ERROR(s, "bad xdouble input");

      e = 0;
      while (cval >= 0 && cval <= 9) {
         mul(e, e, 10);
         add(e, e, cval);
         s.get();
         c = s.peek();
         cval = CharToIntVal(c);
      }
   }

   if (!got1 && !got2 && !got_e) NTL_INPUT_ERROR(s, "bad xdouble input");

   xdouble t1, t2, v;

   if (got1 || got2) {
      conv(t1, a);
      conv(t2, b);
      v = t1/t2;
   }
   else
      v = 1;

   if (sign < 0)
      v = -v;

   if (got_e) {
      if (e_sign < 0) negate(e, e);
      t1 = PowerOf10(e);
      v = v * t1;
   }

   x = v;
   return s;
}

NTL_END_IMPL


text:
/*
 * Copyright (C) Alex Nekipelov (alex@nekipelov.net)
 * License: MIT
 */

#ifndef REDISCLIENT_REDISCLIENTIMPL_CPP
#define REDISCLIENT_REDISCLIENTIMPL_CPP

#include <boost/asio/write.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>

#include <algorithm>

#include "redisclientimpl.h"

RedisClientImpl::RedisClientImpl(boost::asio::io_service &ioService)
    : state(NotConnected), strand(ioService), socket(ioService), subscribeSeq(0)
{
}

RedisClientImpl::~RedisClientImpl()
{
    close();
}

void RedisClientImpl::close()
{
    if( state != RedisClientImpl::Closed )
    {
        boost::system::error_code ignored_ec;

        errorHandler = boost::bind(&RedisClientImpl::ignoreErrorHandler, _1);
        socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
        state = RedisClientImpl::Closed;
    }
}

void RedisClientImpl::processMessage()
{
    using boost::system::error_code;

    socket.async_read_some(boost::asio::buffer(buf),
                           boost::bind(&RedisClientImpl::asyncRead,
                                       shared_from_this(), _1, _2));
}

void RedisClientImpl::doProcessMessage(const RedisValue &v)
{
    if( state == RedisClientImpl::Subscribed )
    {
        std::vector<RedisValue> result = v.toArray();

        if( result.size() == 3 )
        {
            const RedisValue &command = result[0];
            const RedisValue &queueName = result[1];
            const RedisValue &value = result[2];

            const std::string &cmd = command.toString();

            if( cmd == "message" )
            {
                SingleShotHandlersMap::iterator it = singleShotMsgHandlers.find(queueName.toString());
                if( it != singleShotMsgHandlers.end() )
                {
                    strand.post(boost::bind(it->second, value.toByteArray()));
                    singleShotMsgHandlers.erase(it);
                }

                std::pair<MsgHandlersMap::iterator, MsgHandlersMap::iterator> pair =
                        msgHandlers.equal_range(queueName.toString());
                for(MsgHandlersMap::iterator handlerIt = pair.first;
                    handlerIt != pair.second; ++handlerIt)
                {
                    strand.post(boost::bind(handlerIt->second.second, value.toByteArray()));
                }
            }
            else if( cmd == "subscribe" && handlers.empty() == false )
            {
                handlers.front()(v);
                handlers.pop();
            }
            else if(cmd == "unsubscribe" && handlers.empty() == false )
            {
                handlers.front()(v);
                handlers.pop();
            }
            else
            {
                std::stringstream ss;

                ss << "[RedisClient] invalid command: "
                   << command.toString();

                errorHandler(ss.str());
                return;
            }
        }
        else
        {
            errorHandler("[RedisClient] Protocol error");
            return;
        }
    }
    else
    {
        if( handlers.empty() == false )
        {
            handlers.front()(v);
            handlers.pop();
        }
        else
        {
            std::stringstream ss;

            ss << "[RedisClient] unexpected message: "
               <<  v.inspect();

            errorHandler(ss.str());
            return;
        }
    }
}

void RedisClientImpl::asyncWrite(const boost::system::error_code &ec, const size_t)
{
    if( ec )
    {
        errorHandler(ec.message());
        return;
    }

    assert(queue.empty() == false);
    queue.pop();

    if( queue.empty() == false )
    {
        const QueueItem &item = queue.front();

        boost::asio::async_write(socket,
                                 boost::asio::buffer(item.buff->data(), item.buff->size()),
                                 boost::bind(&RedisClientImpl::asyncWrite, shared_from_this(), _1, _2));
    }
}

void RedisClientImpl::handleAsyncConnect(const boost::system::error_code &ec,
                                         const boost::function<void(bool, const std::string &)> &handler)
{
    if( !ec )
    {
        socket.set_option(boost::asio::ip::tcp::no_delay(true));
        state = RedisClientImpl::Connected;
        handler(true, std::string());
        processMessage();
    }
    else
    {
        handler(false, ec.message());
    }
}

std::vector<char> RedisClientImpl::makeCommand(const std::vector<RedisBuffer> &items)
{
    static const char crlf[] = {'\r', '\n'};

    std::vector<char> result;

    append(result, '*');
    append(result, boost::lexical_cast<std::string>(items.size()));
    append<>(result, crlf);

    std::vector<RedisBuffer>::const_iterator it = items.begin(), end = items.end();
    for(; it != end; ++it)
    {
        append(result, '$');
        append(result, boost::lexical_cast<std::string>(it->size()));
        append<>(result, crlf);
        append(result, *it);
        append<>(result, crlf);
    }

    return result;
}

RedisValue RedisClientImpl::doSyncCommand(const std::vector<RedisBuffer> &buff)
{
    assert( queue.empty() );

    boost::system::error_code ec;

    {
        std::vector<char> data = makeCommand(buff);
        boost::asio::write(socket, boost::asio::buffer(data), boost::asio::transfer_all(), ec);
    }

    if( ec )
    {
        errorHandler(ec.message());
        return RedisValue();
    }
    else
    {
        boost::array<char, 4096> inbuff;

        for(;;)
        {
            size_t size = socket.read_some(boost::asio::buffer(inbuff));

            for(size_t pos = 0; pos < size;)
            {
                std::pair<size_t, RedisParser::ParseResult> result =
                    redisParser.parse(inbuff.data() + pos, size - pos);

                if( result.second == RedisParser::Completed )
                {
                    return redisParser.result();
                }
                else if( result.second == RedisParser::Incompleted )
                {
                    pos += result.first;
                    continue;
                }
                else
                {
                    errorHandler("[RedisClient] Parser error");
                    return RedisValue();
                }
            }
        }
    }
}

void RedisClientImpl::doAsyncCommand(const std::vector<char> &buff,
                                     const boost::function<void(const RedisValue &)> &handler)
{
    QueueItem item;

    item.buff.reset( new std::vector<char>(buff) );
    item.handler = handler;
    queue.push(item);

    handlers.push( item.handler );

    if( queue.size() == 1 )
    {
        boost::asio::async_write(socket,
                                 boost::asio::buffer(item.buff->data(), item.buff->size()),
                                 boost::bind(&RedisClientImpl::asyncWrite, shared_from_this(), _1, _2));
    }
}

void RedisClientImpl::asyncRead(const boost::system::error_code &ec, const size_t size)
{
    if( ec || size == 0 )
    {
        errorHandler(ec.message());
        return;
    }

    for(size_t pos = 0; pos < size;)
    {
        std::pair<size_t, RedisParser::ParseResult> result = redisParser.parse(buf.data() + pos, size - pos);

        if( result.second == RedisParser::Completed )
        {
            doProcessMessage(redisParser.result());
        }
        else if( result.second == RedisParser::Incompleted )
        {
            processMessage();
            return;
        }
        else
        {
            errorHandler("[RedisClient] Parser error");
            return;
        }

        pos += result.first;
    }

    processMessage();

}

void RedisClientImpl::onRedisError(const RedisValue &v)
{
    std::string message = v.toString();
    errorHandler(message);
}

void RedisClientImpl::defaulErrorHandler(const std::string &s)
{
    throw std::runtime_error(s);
}

void RedisClientImpl::ignoreErrorHandler(const std::string &)
{
    // empty
}

void RedisClientImpl::append(std::vector<char> &vec, const RedisBuffer &buf)
{
    vec.insert(vec.end(), buf.data(), buf.data() + buf.size());
}

void RedisClientImpl::append(std::vector<char> &vec, const std::string &s)
{
    vec.insert(vec.end(), s.begin(), s.end());
}

void RedisClientImpl::append(std::vector<char> &vec, const char *s)
{
    vec.insert(vec.end(), s, s + strlen(s));
}

void RedisClientImpl::append(std::vector<char> &vec, char c)
{
    vec.resize(vec.size() + 1);
    vec[vec.size() - 1] = c;
}

#endif // REDISCLIENT_REDISCLIENTIMPL_CPP

max_stars_repo_name: TheSalarKhan/ssehub

max_issues_repo_name: TheSalarKhan/ssehub

max_forks_repo_name: TheSalarKhan/ssehub