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

#include <stdlib.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h> /* for TCP_NODELAY */
#include <sys/socket.h>

#include "utils.h"
#include "config.h"
#include "server.h"

#include "xapiand.h"

int bind_http(int http_port)
{
	int backlog = -1;
	int error;
	int optval = 1;
	struct sockaddr_in addr;
	struct linger ling = {0, 0};

	int http_sock = socket(PF_INET, SOCK_STREAM, 0);

	setsockopt(http_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval));
	error = setsockopt(http_sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&optval, sizeof(optval));
	if (error != 0)
		LOG_CONN((void *)NULL, "ERROR: setsockopt (sock=%d): %s\n", http_sock, strerror(errno));

	error = setsockopt(http_sock, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
	if (error != 0)
		LOG_CONN((void *)NULL, "ERROR: setsockopt (sock=%d): %s\n", http_sock, strerror(errno));

	error = setsockopt(http_sock, IPPROTO_TCP, TCP_NODELAY, (void *)&optval, sizeof(optval));
	if (error != 0)
		LOG_CONN((void *)NULL, "ERROR: setsockopt (sock=%d): %s\n", http_sock, strerror(errno));

	addr.sin_family = AF_INET;
	addr.sin_port = htons(http_port);
	addr.sin_addr.s_addr = INADDR_ANY;

	if (bind(http_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
		LOG_ERR((void *)NULL, "ERROR: http bind error (sock=%d): %s\n", http_sock, strerror(errno));
		close(http_sock);
		http_sock = -1;
	} else {
		fcntl(http_sock, F_SETFL, fcntl(http_sock, F_GETFL, 0) | O_NONBLOCK);

		listen(http_sock, backlog);
	}

	return http_sock;
}

int bind_binary(int binary_port)
{
	int backlog = -1;
	int error;
	int optval = 1;
	struct sockaddr_in addr;
	struct linger ling = {0, 0};

	int binary_sock = socket(PF_INET, SOCK_STREAM, 0);

	setsockopt(binary_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval));
	error = setsockopt(binary_sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&optval, sizeof(optval));
	if (error != 0)
		LOG_CONN((void *)NULL, "ERROR: setsockopt (sock=%d): %s\n", binary_sock, strerror(errno));

	error = setsockopt(binary_sock, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
	if (error != 0)
		LOG_CONN((void *)NULL, "ERROR: setsockopt (sock=%d): %s\n", binary_sock, strerror(errno));

	error = setsockopt(binary_sock, IPPROTO_TCP, TCP_NODELAY, (void *)&optval, sizeof(optval));
	if (error != 0)
		LOG_CONN((void *)NULL, "ERROR: setsockopt (sock=%d): %s\n", binary_sock, strerror(errno));

	addr.sin_family = AF_INET;
	addr.sin_port = htons(binary_port);
	addr.sin_addr.s_addr = INADDR_ANY;

	if (bind(binary_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
		LOG_ERR((void *)NULL, "ERROR: binary bind error (sock=%d): %s\n", binary_sock, strerror(errno));
		close(binary_sock);
		binary_sock = -1;
	} else {
		fcntl(binary_sock, F_SETFL, fcntl(binary_sock, F_GETFL, 0) | O_NONBLOCK);

		listen(binary_sock, backlog);
	}

	return binary_sock;
}

int main(int argc, char **argv)
{
	int http_port = XAPIAND_HTTP_SERVERPORT;
	int binary_port = XAPIAND_BINARY_SERVERPORT;

	if (argc > 2) {
		http_port = atoi(argv[1]);
		binary_port = atoi(argv[2]);
	}

	LOG((void *)NULL, "Starting %s (%s).\n", PACKAGE_STRING, PACKAGE_BUGREPORT);

	int http_sock = bind_http(http_port);
	int binary_sock = bind_binary(binary_port);

	int tasks = 0;

	if (http_sock != -1 && binary_sock != -1) {
		LOG((void *)NULL, "Listening on %d (http), %d (xapian)...\n", http_port, binary_port);

		ev::default_loop loop;
		if (tasks) {
			ThreadPool *thread_pool = new ThreadPool(tasks);

			for (int i = 0; i < tasks; i++) {
				XapiandServer * server = new XapiandServer(NULL, http_sock, binary_sock);
				thread_pool->addTask(server);
			}

			loop.run();

			LOG_OBJ((void *)NULL, "Waiting for threads...\n");

			thread_pool->finish();
			thread_pool->join();

			delete thread_pool;
		} else {
			XapiandServer * server = new XapiandServer(&loop, http_sock, binary_sock);
			server->run();
			delete server;
		}
	}

	if (http_sock != -1) {
		close(http_sock);
	}

	if (binary_sock != -1) {
		close(binary_sock);
	}

	LOG((void *)NULL, "Done with all work!\n");

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

#include <stdlib.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h> /* for TCP_NODELAY */
#include <sys/socket.h>

#include "utils.h"
#include "config.h"
#include "server.h"

#include "xapiand.h"

int bind_http(int http_port)
{
	int tcp_backlog = XAPIAND_TCP_BACKLOG;
	int error;
	int optval = 1;
	struct sockaddr_in addr;
	struct linger ling = {0, 0};

	int http_sock = socket(PF_INET, SOCK_STREAM, 0);

	setsockopt(http_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval));
	error = setsockopt(http_sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&optval, sizeof(optval));
	if (error != 0)
		LOG_CONN((void *)NULL, "ERROR: setsockopt (sock=%d): %s\n", http_sock, strerror(errno));

	error = setsockopt(http_sock, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
	if (error != 0)
		LOG_CONN((void *)NULL, "ERROR: setsockopt (sock=%d): %s\n", http_sock, strerror(errno));

	error = setsockopt(http_sock, IPPROTO_TCP, TCP_NODELAY, (void *)&optval, sizeof(optval));
	if (error != 0)
		LOG_CONN((void *)NULL, "ERROR: setsockopt (sock=%d): %s\n", http_sock, strerror(errno));

	addr.sin_family = AF_INET;
	addr.sin_port = htons(http_port);
	addr.sin_addr.s_addr = INADDR_ANY;

	if (bind(http_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
		LOG_ERR((void *)NULL, "ERROR: http bind error (sock=%d): %s\n", http_sock, strerror(errno));
		close(http_sock);
		http_sock = -1;
	} else {
		fcntl(http_sock, F_SETFL, fcntl(http_sock, F_GETFL, 0) | O_NONBLOCK);

		listen(http_sock, tcp_backlog);
	}

	return http_sock;
}

int bind_binary(int binary_port)
{
	int tcp_backlog = XAPIAND_TCP_BACKLOG;
	int error;
	int optval = 1;
	struct sockaddr_in addr;
	struct linger ling = {0, 0};

	int binary_sock = socket(PF_INET, SOCK_STREAM, 0);

	setsockopt(binary_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval));
	error = setsockopt(binary_sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&optval, sizeof(optval));
	if (error != 0)
		LOG_CONN((void *)NULL, "ERROR: setsockopt (sock=%d): %s\n", binary_sock, strerror(errno));

	error = setsockopt(binary_sock, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
	if (error != 0)
		LOG_CONN((void *)NULL, "ERROR: setsockopt (sock=%d): %s\n", binary_sock, strerror(errno));

	error = setsockopt(binary_sock, IPPROTO_TCP, TCP_NODELAY, (void *)&optval, sizeof(optval));
	if (error != 0)
		LOG_CONN((void *)NULL, "ERROR: setsockopt (sock=%d): %s\n", binary_sock, strerror(errno));

	addr.sin_family = AF_INET;
	addr.sin_port = htons(binary_port);
	addr.sin_addr.s_addr = INADDR_ANY;

	if (bind(binary_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
		LOG_ERR((void *)NULL, "ERROR: binary bind error (sock=%d): %s\n", binary_sock, strerror(errno));
		close(binary_sock);
		binary_sock = -1;
	} else {
		fcntl(binary_sock, F_SETFL, fcntl(binary_sock, F_GETFL, 0) | O_NONBLOCK);

		listen(binary_sock, tcp_backlog);
	}

	return binary_sock;
}

int main(int argc, char **argv)
{
	int http_port = XAPIAND_HTTP_SERVERPORT;
	int binary_port = XAPIAND_BINARY_SERVERPORT;

	if (argc > 2) {
		http_port = atoi(argv[1]);
		binary_port = atoi(argv[2]);
	}

	LOG((void *)NULL, "Starting %s (%s).\n", PACKAGE_STRING, PACKAGE_BUGREPORT);

	int http_sock = bind_http(http_port);
	int binary_sock = bind_binary(binary_port);

	int tasks = 0;

	if (http_sock != -1 && binary_sock != -1) {
		LOG((void *)NULL, "Listening on %d (http), %d (xapian)...\n", http_port, binary_port);

		ev::default_loop loop;
		if (tasks) {
			ThreadPool *thread_pool = new ThreadPool(tasks);

			for (int i = 0; i < tasks; i++) {
				XapiandServer * server = new XapiandServer(NULL, http_sock, binary_sock);
				thread_pool->addTask(server);
			}

			loop.run();

			LOG_OBJ((void *)NULL, "Waiting for threads...\n");

			thread_pool->finish();
			thread_pool->join();

			delete thread_pool;
		} else {
			XapiandServer * server = new XapiandServer(&loop, http_sock, binary_sock);
			server->run();
			delete server;
		}
	}

	if (http_sock != -1) {
		close(http_sock);
	}

	if (binary_sock != -1) {
		close(binary_sock);
	}

	LOG((void *)NULL, "Done with all work!\n");

	return 0;
}
<|endoftext|>


<commit_before>/*
  Copyright (C) 2005 Steven L. Scott

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

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

/*
 *  Mathlib : A C Library of Special Functions
 *  Copyright (C) 1998 Ross Ihaka
 *  Copyright (C) 2000 The R Development Core Team
 *  based on AS91 (C) 1979 Royal Statistical Society
 *
 *  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; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 *  USA.
 *
 *  DESCRIPTION
 *
 *      Compute the quantile function of the gamma distribution.
 *
 *  NOTES
 *
 *      This function is based on the Applied Statistics
 *      Algorithm AS 91 ("ppchi2") and via pgamma(.) AS 239.
 *
 *  REFERENCES
 *
 *      Best, D. J. and D. E. Roberts (1975).
 *      Percentage Points of the Chi-Squared Distribution.
 *      Applied Statistics 24, page 385.  */

#include "nmath.hpp"
#include "dpq.hpp"
namespace Rmath{

double qgamma(double p, double alpha, double scale, int lower_tail, int log_p)
/*                      shape = alpha */
{
#define C7      4.67
#define C8      6.66
#define C9      6.73
#define C10     13.32

#define EPS1 1e-2
#define EPS2 5e-7/* final precision */
#define MAXIT 1000/* was 20 */

#define pMIN 1e-100    /* was 0.000002 = 2e-6 */
#define pMAX (1-1e-12)/* was 0.999998 = 1 - 2e-6 */

    const double
        i420  = 1./ 420.,
        i2520 = 1./ 2520.,
        i5040 = 1./ 5040;

    double p_, a, b, c, ch, g, p1, v;
    double p2, q, s1, s2, s3, s4, s5, s6, t, x;
    int i;

    /* test arguments and initialise */
    // Code below checks errno, so make sure it is in a good state to begin
    // with.
    errno = 0;

#ifdef IEEE_754
    if (ISNAN(p) || ISNAN(alpha) || ISNAN(scale))
        return p + alpha + scale;
#endif
    R_Q_P01_check(p);
    if (alpha <= 0) ML_ERR_return_NAN;

    /* FIXME: This (cutoff to {0, +Inf}) is far from optimal when log_p: */
    p_ = R_DT_qIv(p);/* lower_tail prob (in any case) */
    if (/* 0 <= */ p_ < pMIN) return 0;
    if (/* 1 >= */ p_ > pMAX) return BOOM::infinity();

    v = 2*alpha;

    c = alpha-1;
    g = lgammafn(alpha);/* log Gamma(v/2) */

/*----- Phase I : Starting Approximation */

    if(v < (-1.24)*R_DT_log(p)) {       /* for small chi-squared */
        /* FIXME: Improve this "if (log_p)" :
         *        (A*exp(b)) ^ 1/al */
        ch = pow(p_* alpha*exp(g+alpha*M_LN2), 1/alpha);
        if(ch < EPS2) {/* Corrected according to AS 91; MM, May 25, 1999 */
            goto END;
        }

    } else if(v > 0.32) {       /*  using Wilson and Hilferty estimate */

        x = qnorm(p, 0, 1, lower_tail, log_p);
        p1 = 0.222222/v;
        ch = v*pow(x*sqrt(p1)+1-p1, 3);

        /* starting approximation for p tending to 1 */

        if( ch > 2.2*v + 6 )
            ch = -2*(R_DT_Clog(p) - c*log(0.5*ch) + g);

    } else { /* for v <= 0.32 */

        ch = 0.4;
        a = R_DT_Clog(p) + g + c*M_LN2;
        do {
            q = ch;
            p1 = 1. / (1+ch*(C7+ch));
            p2 = ch*(C9+ch*(C8+ch));
            t = -0.5 +(C7+2*ch)*p1 - (C9+ch*(C10+3*ch))/p2;
            ch -= (1- exp(a+0.5*ch)*p2*p1)/t;
        } while(fabs(q - ch) > EPS1*fabs(ch));
    }

/*----- Phase II: Iteration
 *      Call pgamma() [AS 239]  and calculate seven term taylor series
 */
    for( i=1 ; i <= MAXIT ; i++ ) {
        q = ch;
        p1 = 0.5*ch;
        p2 = p_ - pgamma(p1, alpha, 1, /*lower_tail*/true, /*log_p*/false);
// #ifdef IEEE_754
//         if(!R_FINITE(p2))
// #else
//         if(errno != 0)
// #endif
//                 return std::numeric_limits<double>::quiet_NaN();
        if (errno != 0) {
          std::ostringstream err;
          err << "Math error in qgamma: " << strerror(errno) << std::endl;
          report_error(err.str());
          return std::numeric_limits<double>::quiet_NaN();
        }
        if (!std::finite(p2)) {
          return std::numeric_limits<double>::quiet_NaN();
        }

        t = p2*exp(alpha*M_LN2+g+p1-c*log(ch));
        b = t/ch;
        a = 0.5*t - b*c;
        s1 = (210+a*(140+a*(105+a*(84+a*(70+60*a))))) * i420;
        s2 = (420+a*(735+a*(966+a*(1141+1278*a)))) * i2520;
        s3 = (210+a*(462+a*(707+932*a))) * i2520;
        s4 = (252+a*(672+1182*a)+c*(294+a*(889+1740*a))) * i5040;
        s5 = (84+2264*a+c*(1175+606*a)) * i2520;
        s6 = (120+c*(346+127*c)) * i5040;
        ch += t*(1+0.5*t*s1-b*c*(s1-b*(s2-b*(s3-b*(s4-b*(s5-b*s6))))));
        if(fabs(q - ch) < EPS2*ch)
            goto END;
    }
    ML_ERROR(ME_PRECISION);/* no convergence in MAXIT iterations */
 END:
    return 0.5*scale*ch;
}
}
<commit_msg>Fixed typo std::finite -> std::isfinite.<commit_after>/*
  Copyright (C) 2005 Steven L. Scott

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

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

/*
 *  Mathlib : A C Library of Special Functions
 *  Copyright (C) 1998 Ross Ihaka
 *  Copyright (C) 2000 The R Development Core Team
 *  based on AS91 (C) 1979 Royal Statistical Society
 *
 *  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; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 *  USA.
 *
 *  DESCRIPTION
 *
 *      Compute the quantile function of the gamma distribution.
 *
 *  NOTES
 *
 *      This function is based on the Applied Statistics
 *      Algorithm AS 91 ("ppchi2") and via pgamma(.) AS 239.
 *
 *  REFERENCES
 *
 *      Best, D. J. and D. E. Roberts (1975).
 *      Percentage Points of the Chi-Squared Distribution.
 *      Applied Statistics 24, page 385.  */

#include "nmath.hpp"
#include "dpq.hpp"
namespace Rmath{

double qgamma(double p, double alpha, double scale, int lower_tail, int log_p)
/*                      shape = alpha */
{
#define C7      4.67
#define C8      6.66
#define C9      6.73
#define C10     13.32

#define EPS1 1e-2
#define EPS2 5e-7/* final precision */
#define MAXIT 1000/* was 20 */

#define pMIN 1e-100    /* was 0.000002 = 2e-6 */
#define pMAX (1-1e-12)/* was 0.999998 = 1 - 2e-6 */

    const double
        i420  = 1./ 420.,
        i2520 = 1./ 2520.,
        i5040 = 1./ 5040;

    double p_, a, b, c, ch, g, p1, v;
    double p2, q, s1, s2, s3, s4, s5, s6, t, x;
    int i;

    /* test arguments and initialise */
    // Code below checks errno, so make sure it is in a good state to begin
    // with.
    errno = 0;

#ifdef IEEE_754
    if (ISNAN(p) || ISNAN(alpha) || ISNAN(scale))
        return p + alpha + scale;
#endif
    R_Q_P01_check(p);
    if (alpha <= 0) ML_ERR_return_NAN;

    /* FIXME: This (cutoff to {0, +Inf}) is far from optimal when log_p: */
    p_ = R_DT_qIv(p);/* lower_tail prob (in any case) */
    if (/* 0 <= */ p_ < pMIN) return 0;
    if (/* 1 >= */ p_ > pMAX) return BOOM::infinity();

    v = 2*alpha;

    c = alpha-1;
    g = lgammafn(alpha);/* log Gamma(v/2) */

/*----- Phase I : Starting Approximation */

    if(v < (-1.24)*R_DT_log(p)) {       /* for small chi-squared */
        /* FIXME: Improve this "if (log_p)" :
         *        (A*exp(b)) ^ 1/al */
        ch = pow(p_* alpha*exp(g+alpha*M_LN2), 1/alpha);
        if(ch < EPS2) {/* Corrected according to AS 91; MM, May 25, 1999 */
            goto END;
        }

    } else if(v > 0.32) {       /*  using Wilson and Hilferty estimate */

        x = qnorm(p, 0, 1, lower_tail, log_p);
        p1 = 0.222222/v;
        ch = v*pow(x*sqrt(p1)+1-p1, 3);

        /* starting approximation for p tending to 1 */

        if( ch > 2.2*v + 6 )
            ch = -2*(R_DT_Clog(p) - c*log(0.5*ch) + g);

    } else { /* for v <= 0.32 */

        ch = 0.4;
        a = R_DT_Clog(p) + g + c*M_LN2;
        do {
            q = ch;
            p1 = 1. / (1+ch*(C7+ch));
            p2 = ch*(C9+ch*(C8+ch));
            t = -0.5 +(C7+2*ch)*p1 - (C9+ch*(C10+3*ch))/p2;
            ch -= (1- exp(a+0.5*ch)*p2*p1)/t;
        } while(fabs(q - ch) > EPS1*fabs(ch));
    }

/*----- Phase II: Iteration
 *      Call pgamma() [AS 239]  and calculate seven term taylor series
 */
    for( i=1 ; i <= MAXIT ; i++ ) {
        q = ch;
        p1 = 0.5*ch;
        p2 = p_ - pgamma(p1, alpha, 1, /*lower_tail*/true, /*log_p*/false);
// #ifdef IEEE_754
//         if(!R_FINITE(p2))
// #else
//         if(errno != 0)
// #endif
//                 return std::numeric_limits<double>::quiet_NaN();
        if (errno != 0) {
          std::ostringstream err;
          err << "Math error in qgamma: " << strerror(errno) << std::endl;
          report_error(err.str());
          return std::numeric_limits<double>::quiet_NaN();
        }
        if (!std::isfinite(p2)) {
          return std::numeric_limits<double>::quiet_NaN();
        }

        t = p2*exp(alpha*M_LN2+g+p1-c*log(ch));
        b = t/ch;
        a = 0.5*t - b*c;
        s1 = (210+a*(140+a*(105+a*(84+a*(70+60*a))))) * i420;
        s2 = (420+a*(735+a*(966+a*(1141+1278*a)))) * i2520;
        s3 = (210+a*(462+a*(707+932*a))) * i2520;
        s4 = (252+a*(672+1182*a)+c*(294+a*(889+1740*a))) * i5040;
        s5 = (84+2264*a+c*(1175+606*a)) * i2520;
        s6 = (120+c*(346+127*c)) * i5040;
        ch += t*(1+0.5*t*s1-b*c*(s1-b*(s2-b*(s3-b*(s4-b*(s5-b*s6))))));
        if(fabs(q - ch) < EPS2*ch)
            goto END;
    }
    ML_ERROR(ME_PRECISION);/* no convergence in MAXIT iterations */
 END:
    return 0.5*scale*ch;
}
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2013-2014 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <fstream>
#include <sstream>

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

#include "wishes.hpp"
#include "objectives.hpp"
#include "expenses.hpp"
#include "earnings.hpp"
#include "fortune.hpp"
#include "accounts.hpp"
#include "args.hpp"
#include "data.hpp"
#include "guid.hpp"
#include "config.hpp"
#include "utils.hpp"
#include "console.hpp"
#include "budget_exception.hpp"
#include "compute.hpp"

using namespace budget;

namespace {

static data_handler<wish> wishes;

void list_wishes(){
    if(wishes.data.size() == 0){
        std::cout << "No wishes" << std::endl;
    } else {
        std::vector<std::string> columns = {"ID", "Name", "Amount", "Paid"};
        std::vector<std::vector<std::string>> contents;

        money total;
        money unpaid_total;
        for(auto& wish : wishes.data){
            contents.push_back({to_string(wish.id), wish.name, to_string(wish.amount), wish.paid ? to_string(wish.paid_amount) : "No"});

            total += wish.amount;
            if(!wish.paid){
                unpaid_total += wish.amount;
            }
        }

        contents.push_back({"", "", "", ""});
        contents.push_back({"", "Total", to_string(total), ""});
        contents.push_back({"", "Unpaid Total", to_string(unpaid_total), ""});

        display_table(columns, contents);
    }
}

void status_wishes(){
    auto today = boost::gregorian::day_clock::local_day();

    if(today.day() < 12){
        std::cout << "WARNING: It is early in the month, no one can know what may happen ;)" << std::endl << std::endl;
    }

    std::cout << "Wishes" << std::endl << std::endl;

    size_t width = 0;
    for(auto& wish : wishes.data){
        if(wish.paid){
            continue;
        }

        auto name = wish.name;
        boost::algorithm::trim(name);

        width = std::max(rsize(name), width);
    }

    auto month_status = budget::compute_month_status(today.year(), today.month());
    auto year_status = budget::compute_year_status(today.year(), today.month());

    auto fortune_amount = budget::current_fortune();

    for(auto& wish : wishes.data){
        if(wish.paid){
            continue;
        }

        auto amount = wish.amount;
        auto name = wish.name;

        boost::algorithm::trim(name);

        std::cout << "  ";
        print_minimum(name, width);
        std::cout << "  ";

        size_t monthly_breaks = 0;
        size_t yearly_breaks = 0;

        bool month_objective = true;
        bool year_objective = true;

        for(auto& objective : all_objectives()){
            if(objective.type == "monthly"){
                auto success_before = budget::compute_success(month_status, objective);
                auto success_after = budget::compute_success(month_status.add_expense(amount), objective);

                if(success_before >= 100 && success_after < 100){
                    ++monthly_breaks;
                }

                if(success_after < 100){
                    month_objective = false;
                }
            } else if(objective.type == "yearly"){
                auto success_before = budget::compute_success(year_status, objective);
                auto success_after = budget::compute_success(year_status.add_expense(amount), objective);

                if(success_before >= 100 && success_after < 100){
                    ++yearly_breaks;
                }

                if(success_after < 100){
                    year_objective = false;
                }
            }
        }

        if(fortune_amount < wish.amount){
            std::cout << "Impossible (not enough fortune)";
        } else {
            if(month_status.balance > wish.amount){
                if(!all_objectives().empty()){
                    if(month_objective && year_objective){
                        std::cout << "Perfect (On month balance, all objectives fullfilled)";
                    } else if(month_objective){
                        std::cout << "Good (On month balance, month objectives fullfilled)";
                    } else if(yearly_breaks > 0 || monthly_breaks > 0){
                        std::cout << "OK (On month balance, " << (yearly_breaks + monthly_breaks) << " objectives broken)";
                    } else if(yearly_breaks == 0 && monthly_breaks == 0){
                        std::cout << "Warning (On month balance, objectives not fullfilled)";
                    }
                } else {
                    std::cout << "OK (on month balance)";
                }
            } else if(year_status.balance > wish.amount){
                if(!all_objectives().empty()){
                    if(month_objective && year_objective){
                        std::cout << "Perfect (On year balance, all objectives fullfilled)";
                    } else if(month_objective){
                        std::cout << "Good (On year balance, month objectives fullfilled)";
                    } else if(yearly_breaks > 0 || monthly_breaks > 0){
                        std::cout << "OK (On year balance, " << (yearly_breaks + monthly_breaks) << " objectives broken)";
                    } else if(yearly_breaks == 0 && monthly_breaks == 0){
                        std::cout << "Warning (On year balance, objectives not fullfilled)";
                    }
                } else {
                    std::cout << "OK (on year balance)";
                }
            } else {
                std::cout << "Warning (on fortune only)";
            }
        }

        std::cout << std::endl;
    }
}

void estimate_wishes(){
    std::cout << "Time to buy (with year objectives)" << std::endl;

    size_t width = 0;
    for(auto& wish : wishes.data){
        if(wish.paid){
            continue;
        }

        auto name = wish.name;

        boost::algorithm::trim(name);

        width = std::max(rsize(name), width);
    }

    auto fortune_amount = budget::current_fortune();
    auto today = boost::gregorian::day_clock::local_day();

    for(auto& wish : wishes.data){
        if(wish.paid){
            continue;
        }

        auto name = wish.name;

        boost::algorithm::trim(name);

        std::cout << "  ";
        print_minimum(name, width);
        std::cout << "  ";

        bool ok = false;

        for(std::size_t i = 0; i < 24 && !ok; ++i){
            auto day = today + boost::gregorian::months(i);
            auto month_status = budget::compute_month_status(day.year(), day.month());
            auto year_status = budget::compute_year_status(day.year(), day.month());

            size_t monthly_breaks = 0;
            size_t yearly_breaks = 0;

            bool month_objective = true;
            bool year_objective = true;

            for(auto& objective : all_objectives()){
                if(objective.type == "monthly"){
                    auto success_before = budget::compute_success(month_status, objective);
                    auto success_after = budget::compute_success(month_status.add_expense(wish.amount), objective);

                    if(success_before >= 100 && success_after < 100){
                        ++monthly_breaks;
                    }

                    if(success_after < 100){
                        month_objective = false;
                    }
                } else if(objective.type == "yearly"){
                    auto success_before = budget::compute_success(year_status, objective);
                    auto success_after = budget::compute_success(year_status.add_expense(wish.amount), objective);

                    if(success_before >= 100 && success_after < 100){
                        ++yearly_breaks;
                    }

                    if(success_after < 100){
                        year_objective = false;
                    }
                }
            }

            if(fortune_amount >= wish.amount){
                if(month_objective && year_objective){
                    if(wish.amount >= month_status.budget){
                        if(year_status.balance > wish.amount){
                            std::cout << day.month() << " " << day.year() << std::endl;
                            ok = true;
                        }
                    } else {
                        if(month_status.balance > wish.amount){
                            std::cout << day.month() << " " << day.year() << std::endl;
                            ok = true;
                        }
                    }
                }
            }
        }

        if(!ok){
            std::cout << "You should wait a very long time to buy this" << std::endl;
        }
    }

    std::cout << std::endl << "Time to buy (without year objectives)" << std::endl;

    for(auto& wish : wishes.data){
        if(wish.paid){
            continue;
        }

        auto name = wish.name;

        boost::algorithm::trim(name);

        std::cout << "  ";
        print_minimum(name, width);
        std::cout << "  ";

        bool ok = false;

        for(std::size_t i = 0; i < 24 && !ok; ++i){
            auto day = today + boost::gregorian::months(i);
            auto month_status = budget::compute_month_status(day.year(), day.month());
            auto year_status = budget::compute_year_status(day.year(), day.month());

            size_t monthly_breaks = 0;
            bool month_objective = true;

            for(auto& objective : all_objectives()){
                if(objective.type == "monthly"){
                    auto success_before = budget::compute_success(month_status, objective);
                    auto success_after = budget::compute_success(month_status.add_expense(wish.amount), objective);

                    if(success_before >= 100 && success_after < 100){
                        ++monthly_breaks;
                    }

                    if(success_after < 100){
                        month_objective = false;
                    }
                }
            }

            if(fortune_amount >= wish.amount){
                if(month_objective){
                    if(wish.amount >= month_status.budget){
                        if(year_status.balance > wish.amount){
                            std::cout << day.month() << " " << day.year() << std::endl;
                            ok = true;
                        }
                    } else {
                        if(month_status.balance > wish.amount){
                            std::cout << day.month() << " " << day.year() << std::endl;
                            ok = true;
                        }
                    }
                }
            }
        }

        if(!ok){
            std::cout << "You should wait a very long time to buy this" << std::endl;
        }
    }
}

void edit(budget::wish& wish){
    edit_string(wish.name, "Name", not_empty_checker());
    edit_money(wish.amount, "Amount", not_negative_checker(), not_zero_checker());
}

} //end of anonymous namespace

void budget::wishes_module::load(){
    load_expenses();
    load_earnings();
    load_accounts();
    load_fortunes();
    load_objectives();
    load_wishes();
}

void budget::wishes_module::unload(){
    save_wishes();
}

void budget::wishes_module::handle(const std::vector<std::string>& args){
    if(args.size() == 1){
        status_wishes();
    } else {
        auto& subcommand = args[1];

        if(subcommand == "list"){
            list_wishes();
        } else if(subcommand == "status"){
            status_wishes();
        } else if(subcommand == "estimate"){
            estimate_wishes();
        } else if(subcommand == "add"){
            wish wish;
            wish.guid = generate_guid();
            wish.date = boost::gregorian::day_clock::local_day();

            edit(wish);

            auto id = add_data(wishes, std::move(wish));
            std::cout << "Wish " << id << " has been created" << std::endl;
        } else if(subcommand == "delete"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(wishes, id)){
                throw budget_exception("There are no wish with id " + args[2]);
            }

            remove(wishes, id);

            std::cout << "wish " << id << " has been deleted" << std::endl;
        } else if(subcommand == "edit"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(wishes, id)){
                throw budget_exception("There are no wish with id " + args[2]);
            }

            auto& wish = get(wishes, id);

            edit(wish);

            set_wishes_changed();

            std::cout << "wish " << id << " has been modified" << std::endl;
        } else if(subcommand == "paid"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(wishes, id)){
                throw budget_exception("There are no wish with id " + args[2]);
            }

            auto& wish = get(wishes, id);

            edit_money(wish.paid_amount, "Paid Amount", not_negative_checker(), not_zero_checker());

            wish.paid = true;

            set_wishes_changed();

            std::cout << "wish " << id << " has been marked as paid" << std::endl;
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}

void budget::load_wishes(){
    load_data(wishes, "wishes.data");
}

void budget::save_wishes(){
    save_data(wishes, "wishes.data");
}

void budget::add_wish(budget::wish&& wish){
    add_data(wishes, std::forward<budget::wish>(wish));
}

std::ostream& budget::operator<<(std::ostream& stream, const wish& wish){
    return stream
        << wish.id  << ':'
        << wish.guid << ':'
        << wish.name << ':'
        << wish.amount << ':'
        << to_string(wish.date) << ':'
        << static_cast<size_t>(wish.paid) << ':'
        << wish.paid_amount;
}

void budget::operator>>(const std::vector<std::string>& parts, wish& wish){
    wish.id = to_number<std::size_t>(parts[0]);
    wish.guid = parts[1];
    wish.name = parts[2];
    wish.amount = parse_money(parts[3]);
    wish.date = boost::gregorian::from_string(parts[4]);
    wish.paid = to_number<std::size_t>(parts[5]) == 1;
    wish.paid_amount = parse_money(parts[6]);
}

std::vector<wish>& budget::all_wishes(){
    return wishes.data;
}

void budget::set_wishes_changed(){
    wishes.changed = true;
}

void budget::migrate_wishes_2_to_3(){
    load_data(wishes, "wishes.data", [](const std::vector<std::string>& parts, wish& wish){
        wish.id = to_number<std::size_t>(parts[0]);
        wish.guid = parts[1];
        wish.name = parts[2];
        wish.amount = parse_money(parts[3]);
        wish.date = boost::gregorian::from_string(parts[4]);
        wish.paid = false;
        wish.paid_amount = budget::money(0,0);
        });

    set_wishes_changed();

    save_data(wishes, "wishes.data");

}
<commit_msg>Display amount on wish status<commit_after>//=======================================================================
// Copyright (c) 2013-2014 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <fstream>
#include <sstream>

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

#include "wishes.hpp"
#include "objectives.hpp"
#include "expenses.hpp"
#include "earnings.hpp"
#include "fortune.hpp"
#include "accounts.hpp"
#include "args.hpp"
#include "data.hpp"
#include "guid.hpp"
#include "config.hpp"
#include "utils.hpp"
#include "console.hpp"
#include "budget_exception.hpp"
#include "compute.hpp"

using namespace budget;

namespace {

static data_handler<wish> wishes;

void list_wishes(){
    if(wishes.data.size() == 0){
        std::cout << "No wishes" << std::endl;
    } else {
        std::vector<std::string> columns = {"ID", "Name", "Amount", "Paid"};
        std::vector<std::vector<std::string>> contents;

        money total;
        money unpaid_total;
        for(auto& wish : wishes.data){
            contents.push_back({to_string(wish.id), wish.name, to_string(wish.amount), wish.paid ? to_string(wish.paid_amount) : "No"});

            total += wish.amount;
            if(!wish.paid){
                unpaid_total += wish.amount;
            }
        }

        contents.push_back({"", "", "", ""});
        contents.push_back({"", "Total", to_string(total), ""});
        contents.push_back({"", "Unpaid Total", to_string(unpaid_total), ""});

        display_table(columns, contents);
    }
}

void status_wishes(){
    auto today = boost::gregorian::day_clock::local_day();

    if(today.day() < 12){
        std::cout << "WARNING: It is early in the month, no one can know what may happen ;)" << std::endl << std::endl;
    }

    std::cout << "Wishes" << std::endl << std::endl;

    size_t width = 0;
    for(auto& wish : wishes.data){
        if(wish.paid){
            continue;
        }

        auto name = wish.name + " (" + to_string(wish.amount) + ")";
        boost::algorithm::trim(name);

        width = std::max(rsize(name), width);
    }

    auto month_status = budget::compute_month_status(today.year(), today.month());
    auto year_status = budget::compute_year_status(today.year(), today.month());

    auto fortune_amount = budget::current_fortune();

    for(auto& wish : wishes.data){
        if(wish.paid){
            continue;
        }

        auto amount = wish.amount;
        auto name = wish.name + " (" + to_string(wish.amount) + ")";

        boost::algorithm::trim(name);

        std::cout << "  ";
        print_minimum(name, width);
        std::cout << "  ";

        size_t monthly_breaks = 0;
        size_t yearly_breaks = 0;

        bool month_objective = true;
        bool year_objective = true;

        for(auto& objective : all_objectives()){
            if(objective.type == "monthly"){
                auto success_before = budget::compute_success(month_status, objective);
                auto success_after = budget::compute_success(month_status.add_expense(amount), objective);

                if(success_before >= 100 && success_after < 100){
                    ++monthly_breaks;
                }

                if(success_after < 100){
                    month_objective = false;
                }
            } else if(objective.type == "yearly"){
                auto success_before = budget::compute_success(year_status, objective);
                auto success_after = budget::compute_success(year_status.add_expense(amount), objective);

                if(success_before >= 100 && success_after < 100){
                    ++yearly_breaks;
                }

                if(success_after < 100){
                    year_objective = false;
                }
            }
        }

        if(fortune_amount < wish.amount){
            std::cout << "Impossible (not enough fortune)";
        } else {
            if(month_status.balance > wish.amount){
                if(!all_objectives().empty()){
                    if(month_objective && year_objective){
                        std::cout << "Perfect (On month balance, all objectives fullfilled)";
                    } else if(month_objective){
                        std::cout << "Good (On month balance, month objectives fullfilled)";
                    } else if(yearly_breaks > 0 || monthly_breaks > 0){
                        std::cout << "OK (On month balance, " << (yearly_breaks + monthly_breaks) << " objectives broken)";
                    } else if(yearly_breaks == 0 && monthly_breaks == 0){
                        std::cout << "Warning (On month balance, objectives not fullfilled)";
                    }
                } else {
                    std::cout << "OK (on month balance)";
                }
            } else if(year_status.balance > wish.amount){
                if(!all_objectives().empty()){
                    if(month_objective && year_objective){
                        std::cout << "Perfect (On year balance, all objectives fullfilled)";
                    } else if(month_objective){
                        std::cout << "Good (On year balance, month objectives fullfilled)";
                    } else if(yearly_breaks > 0 || monthly_breaks > 0){
                        std::cout << "OK (On year balance, " << (yearly_breaks + monthly_breaks) << " objectives broken)";
                    } else if(yearly_breaks == 0 && monthly_breaks == 0){
                        std::cout << "Warning (On year balance, objectives not fullfilled)";
                    }
                } else {
                    std::cout << "OK (on year balance)";
                }
            } else {
                std::cout << "Warning (on fortune only)";
            }
        }

        std::cout << std::endl;
    }
}

void estimate_wishes(){
    std::cout << "Time to buy (with year objectives)" << std::endl;

    size_t width = 0;
    for(auto& wish : wishes.data){
        if(wish.paid){
            continue;
        }

        auto name = wish.name;

        boost::algorithm::trim(name);

        width = std::max(rsize(name), width);
    }

    auto fortune_amount = budget::current_fortune();
    auto today = boost::gregorian::day_clock::local_day();

    for(auto& wish : wishes.data){
        if(wish.paid){
            continue;
        }

        auto name = wish.name;

        boost::algorithm::trim(name);

        std::cout << "  ";
        print_minimum(name, width);
        std::cout << "  ";

        bool ok = false;

        for(std::size_t i = 0; i < 24 && !ok; ++i){
            auto day = today + boost::gregorian::months(i);
            auto month_status = budget::compute_month_status(day.year(), day.month());
            auto year_status = budget::compute_year_status(day.year(), day.month());

            size_t monthly_breaks = 0;
            size_t yearly_breaks = 0;

            bool month_objective = true;
            bool year_objective = true;

            for(auto& objective : all_objectives()){
                if(objective.type == "monthly"){
                    auto success_before = budget::compute_success(month_status, objective);
                    auto success_after = budget::compute_success(month_status.add_expense(wish.amount), objective);

                    if(success_before >= 100 && success_after < 100){
                        ++monthly_breaks;
                    }

                    if(success_after < 100){
                        month_objective = false;
                    }
                } else if(objective.type == "yearly"){
                    auto success_before = budget::compute_success(year_status, objective);
                    auto success_after = budget::compute_success(year_status.add_expense(wish.amount), objective);

                    if(success_before >= 100 && success_after < 100){
                        ++yearly_breaks;
                    }

                    if(success_after < 100){
                        year_objective = false;
                    }
                }
            }

            if(fortune_amount >= wish.amount){
                if(month_objective && year_objective){
                    if(wish.amount >= month_status.budget){
                        if(year_status.balance > wish.amount){
                            std::cout << day.month() << " " << day.year() << std::endl;
                            ok = true;
                        }
                    } else {
                        if(month_status.balance > wish.amount){
                            std::cout << day.month() << " " << day.year() << std::endl;
                            ok = true;
                        }
                    }
                }
            }
        }

        if(!ok){
            std::cout << "You should wait a very long time to buy this" << std::endl;
        }
    }

    std::cout << std::endl << "Time to buy (without year objectives)" << std::endl;

    for(auto& wish : wishes.data){
        if(wish.paid){
            continue;
        }

        auto name = wish.name;

        boost::algorithm::trim(name);

        std::cout << "  ";
        print_minimum(name, width);
        std::cout << "  ";

        bool ok = false;

        for(std::size_t i = 0; i < 24 && !ok; ++i){
            auto day = today + boost::gregorian::months(i);
            auto month_status = budget::compute_month_status(day.year(), day.month());
            auto year_status = budget::compute_year_status(day.year(), day.month());

            size_t monthly_breaks = 0;
            bool month_objective = true;

            for(auto& objective : all_objectives()){
                if(objective.type == "monthly"){
                    auto success_before = budget::compute_success(month_status, objective);
                    auto success_after = budget::compute_success(month_status.add_expense(wish.amount), objective);

                    if(success_before >= 100 && success_after < 100){
                        ++monthly_breaks;
                    }

                    if(success_after < 100){
                        month_objective = false;
                    }
                }
            }

            if(fortune_amount >= wish.amount){
                if(month_objective){
                    if(wish.amount >= month_status.budget){
                        if(year_status.balance > wish.amount){
                            std::cout << day.month() << " " << day.year() << std::endl;
                            ok = true;
                        }
                    } else {
                        if(month_status.balance > wish.amount){
                            std::cout << day.month() << " " << day.year() << std::endl;
                            ok = true;
                        }
                    }
                }
            }
        }

        if(!ok){
            std::cout << "You should wait a very long time to buy this" << std::endl;
        }
    }
}

void edit(budget::wish& wish){
    edit_string(wish.name, "Name", not_empty_checker());
    edit_money(wish.amount, "Amount", not_negative_checker(), not_zero_checker());
}

} //end of anonymous namespace

void budget::wishes_module::load(){
    load_expenses();
    load_earnings();
    load_accounts();
    load_fortunes();
    load_objectives();
    load_wishes();
}

void budget::wishes_module::unload(){
    save_wishes();
}

void budget::wishes_module::handle(const std::vector<std::string>& args){
    if(args.size() == 1){
        status_wishes();
    } else {
        auto& subcommand = args[1];

        if(subcommand == "list"){
            list_wishes();
        } else if(subcommand == "status"){
            status_wishes();
        } else if(subcommand == "estimate"){
            estimate_wishes();
        } else if(subcommand == "add"){
            wish wish;
            wish.guid = generate_guid();
            wish.date = boost::gregorian::day_clock::local_day();

            edit(wish);

            auto id = add_data(wishes, std::move(wish));
            std::cout << "Wish " << id << " has been created" << std::endl;
        } else if(subcommand == "delete"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(wishes, id)){
                throw budget_exception("There are no wish with id " + args[2]);
            }

            remove(wishes, id);

            std::cout << "wish " << id << " has been deleted" << std::endl;
        } else if(subcommand == "edit"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(wishes, id)){
                throw budget_exception("There are no wish with id " + args[2]);
            }

            auto& wish = get(wishes, id);

            edit(wish);

            set_wishes_changed();

            std::cout << "wish " << id << " has been modified" << std::endl;
        } else if(subcommand == "paid"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(wishes, id)){
                throw budget_exception("There are no wish with id " + args[2]);
            }

            auto& wish = get(wishes, id);

            edit_money(wish.paid_amount, "Paid Amount", not_negative_checker(), not_zero_checker());

            wish.paid = true;

            set_wishes_changed();

            std::cout << "wish " << id << " has been marked as paid" << std::endl;
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}

void budget::load_wishes(){
    load_data(wishes, "wishes.data");
}

void budget::save_wishes(){
    save_data(wishes, "wishes.data");
}

void budget::add_wish(budget::wish&& wish){
    add_data(wishes, std::forward<budget::wish>(wish));
}

std::ostream& budget::operator<<(std::ostream& stream, const wish& wish){
    return stream
        << wish.id  << ':'
        << wish.guid << ':'
        << wish.name << ':'
        << wish.amount << ':'
        << to_string(wish.date) << ':'
        << static_cast<size_t>(wish.paid) << ':'
        << wish.paid_amount;
}

void budget::operator>>(const std::vector<std::string>& parts, wish& wish){
    wish.id = to_number<std::size_t>(parts[0]);
    wish.guid = parts[1];
    wish.name = parts[2];
    wish.amount = parse_money(parts[3]);
    wish.date = boost::gregorian::from_string(parts[4]);
    wish.paid = to_number<std::size_t>(parts[5]) == 1;
    wish.paid_amount = parse_money(parts[6]);
}

std::vector<wish>& budget::all_wishes(){
    return wishes.data;
}

void budget::set_wishes_changed(){
    wishes.changed = true;
}

void budget::migrate_wishes_2_to_3(){
    load_data(wishes, "wishes.data", [](const std::vector<std::string>& parts, wish& wish){
        wish.id = to_number<std::size_t>(parts[0]);
        wish.guid = parts[1];
        wish.name = parts[2];
        wish.amount = parse_money(parts[3]);
        wish.date = boost::gregorian::from_string(parts[4]);
        wish.paid = false;
        wish.paid_amount = budget::money(0,0);
        });

    set_wishes_changed();

    save_data(wishes, "wishes.data");

}
<|endoftext|>


<commit_before>/*
 * CoverageSequential.cpp
 *
 *  Created on: 14.02.2013
 *      Author: cls
 */

#include "CoverageSequential.h"

namespace EnsembleClustering {

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

}

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

double CoverageSequential::getQuality(const Clustering& zeta, Graph& G) {

	double cov = 0.0; // term $\frac{\sum_{C \in \zeta} \sum_{ e \in E(C) } \omega(e)}{\sum_{e \in E} \omega(e)}$
	double totalEdgeWeight = G.totalEdgeWeight(); // add edge weight
	DEBUG("total edge weight = " << totalEdgeWeight)

	if (totalEdgeWeight == 0.0) {
		throw std::invalid_argument(
				"Coverage is undefined for graphs without edges (including self-loops).");
	}

	IndexMap<cluster, double> intraEdgeWeight(zeta.upperBound(), 0.0); // cluster -> weight of its internal edges

	// compute intra-cluster edge weights per cluster
	G.forWeightedEdges(
			[&](node u, node v, edgeweight ew) {
				assert (u < zeta.numberOfNodes());
				assert (v < zeta.numberOfNodes());
				cluster c = zeta[u];
				cluster d = zeta[v];
				if (c == d) {
#ifdef DEBUG
					if ((c >= zeta.upperBound()) || (c < zeta.lowerBound())) {
						ERROR("c=" << c << " = zeta(" << u << ") is larger than upper bound: " << zeta.upperBound());
						ERROR("zeta: "); zeta.print();
					}
#endif
					assert ((zeta.lowerBound()) <= c && (c < zeta.upperBound()));
					intraEdgeWeight[c] += ew;
				} // else ignore edge
			});

	double intraEdgeWeightSum = 0.0; //!< term $\sum_{C \in \zeta} \sum_{ e \in E(C) } \omega(e)$
	for (cluster c = zeta.lowerBound(); c < zeta.upperBound(); ++c) {
		intraEdgeWeightSum += intraEdgeWeight[c];
	}

	cov = intraEdgeWeightSum / totalEdgeWeight;
	DEBUG("coverage = " << cov);

	assert(cov <= 1.0);
	assert(cov >= 0.0);
	return cov;
}

} /* namespace EnsembleClustering */
<commit_msg>coverage debug statements<commit_after>/*
 * CoverageSequential.cpp
 *
 *  Created on: 14.02.2013
 *      Author: cls
 */

#include "CoverageSequential.h"

namespace EnsembleClustering {

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

}

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

double CoverageSequential::getQuality(const Clustering& zeta, Graph& G) {

	double cov = 0.0; // term $\frac{\sum_{C \in \zeta} \sum_{ e \in E(C) } \omega(e)}{\sum_{e \in E} \omega(e)}$
	double totalEdgeWeight = G.totalEdgeWeight(); // add edge weight
	DEBUG("total edge weight = " << totalEdgeWeight)

	if (totalEdgeWeight == 0.0) {
		throw std::invalid_argument(
				"Coverage is undefined for graphs without edges (including self-loops).");
	}

	IndexMap<cluster, double> intraEdgeWeight(zeta.upperBound(), 0.0); // cluster -> weight of its internal edges

	// TODO: sum only over intra-cluster edges, not over clusters

	// compute intra-cluster edge weights per cluster
	G.forWeightedEdges(
			[&](node u, node v, edgeweight ew) {
				assert (u < zeta.numberOfNodes());
				assert (v < zeta.numberOfNodes());
				cluster c = zeta[u];
				cluster d = zeta[v];
				if (c == d) {
#ifdef DEBUG
					if ((c >= zeta.upperBound()) || (c < zeta.lowerBound())) {
						ERROR("c=" << c << " = zeta(" << u << ") is larger than upper bound: " << zeta.upperBound());
						ERROR("zeta: "); zeta.print();
					}
#endif
					assert ((zeta.lowerBound()) <= c && (c < zeta.upperBound()));
					intraEdgeWeight[c] += ew;
				} // else ignore edge
			});

	double intraEdgeWeightSum = 0.0; //!< term $\sum_{C \in \zeta} \sum_{ e \in E(C) } \omega(e)$
	for (cluster c = zeta.lowerBound(); c < zeta.upperBound(); ++c) {
		intraEdgeWeightSum += intraEdgeWeight[c];
	}
	DEBUG("total intra-cluster edge weight = " << intraEdgeWeightSum);

	cov = intraEdgeWeightSum / totalEdgeWeight;
	DEBUG("coverage = " << cov);

	assert(cov <= 1.0);
	assert(cov >= 0.0);
	return cov;
}

} /* namespace EnsembleClustering */
<|endoftext|>


<commit_before>/*
* This file is part of ATLAS. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this distribution.
* (Also avialable at http://www.apache.org/licenses/LICENSE-2.0.txt)
* You may not use this file except in compliance with the License.
*/
#include <fstream>
#include <iostream>
#include <boost/filesystem/operations.hpp>
#include <boost/program_options.hpp>
#include <boost/exception/all.hpp>
#include "configuration.hpp"

namespace bpo = boost::program_options;

namespace AssimpWorker {

Configuration* Configuration::singletonInstance = NULL;
const char* Configuration::defaultConfigFilename = "assimpworker.conf";

Configuration& Configuration::getInstance() {
	if (singletonInstance == NULL) {
		singletonInstance = new Configuration();
	}
	return *singletonInstance;
}

Configuration::Configuration()
{
	setupOptions();
	parseConfigFile();
}

void Configuration::init(int argc, char **argv) {
	bpo::command_line_parser parser(argc, argv);
	parser.options(description);
	bpo::store(parser.run(),parsedVariables);
	// in case the default file didn't exist
	// and we now know a non-default name:
	parseConfigFile();
	if (parsedVariables.count("help")) {
		std::cout << description << std::endl;
		exit(1);
	}
	// now that we have parsed commandline
	// as well as default and possibly other configfile
	// check for missing stuff:
	try {
		bpo::notify(parsedVariables);
	} catch (std::exception const& e) {
		std::cerr << "Parsing options:" << e.what() << std::endl;
		exit(1);
	}
}

void Configuration::parseConfigFile() {
	const char* configFileName = NULL;
	if (parsedVariables.count("config")) {
		// config file specified
		std::string configFile = parsedVariables["config"].as<std::string>();
		configFileName = configFile.c_str();
	} else if (defaultConfigExists()) {
		configFileName = defaultConfigFilename;
	}
	if (!configFileName){
		return;
	}
	std::ifstream configFile(configFileName);
	if (configFile.good()) {
		bpo::parsed_options parsedConfig = bpo::parse_config_file(configFile,description);
		bpo::store(parsedConfig, parsedVariables);
	}
	// don't notify here, as we may not have parsed commandline yet.
}

bool Configuration::defaultConfigExists() {
	return boost::filesystem::exists(defaultConfigFilename);
}

void Configuration::setupOptions() {
	bpo::options_description basic("Basic options");
	basic.add_options()
		("help,h,?", "show this message")
		("version,v","show version number")
		("config,c", bpo::value<std::string>(), "read configuration from file, overrides options given on command line")
		("decompression-path", bpo::value<std::string>()->default_value("./tmp"), "Path to temporary space for decompressed zip contents")
	;
	bpo::options_description stomp("Stomp options");
	stomp.add_options()
		("stomp-heartbeat-interval-ms", bpo::value<int>()->default_value(10000), "Heartbeat interval in ms")
		("stomp-port", bpo::value<int>()        ->default_value(61613),              "Server port (STOMP protocol)")
		("stomp-host", bpo::value<std::string>()->default_value("localhost"),        "Server address")
		("stomp-user", bpo::value<std::string>()->required(),                        "Username")
		("stomp-pass", bpo::value<std::string>()->required(),                        "Password")
		("work-queue",bpo::value<std::string>()->default_value("atlas.work.import"),"Work queue name")
		("feedback-queue",bpo::value<std::string>()->default_value("atlas.work.feedback"),"Feedback queue name")
	;
	bpo::options_description jcr("Repository options");
	jcr.add_options()
		("jcr-url",
		 bpo::value<std::string>()->default_value("http://localhost:8080/modeshape-rest/atlas/default/"),
		 "Root URL")
		("jcr-user",
		 bpo::value<std::string>()->default_value("admin"),
		 "Username")
		("jcr-pass",
		 bpo::value<std::string>()->default_value("admin"),
		 "Password")
	;

	description.add(basic);
	description.add(stomp);
	description.add(jcr);
}

const bpo::variable_value& Configuration::get(const std::string &entry) const {
	return parsedVariables[entry];
}

const bool Configuration::enabled(const std::string& entry) const
{
	return parsedVariables.count(entry);
}

}

<commit_msg>Configuration: add options pertaining to mesh splitting<commit_after>/*
* This file is part of ATLAS. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this distribution.
* (Also avialable at http://www.apache.org/licenses/LICENSE-2.0.txt)
* You may not use this file except in compliance with the License.
*/
#include <fstream>
#include <iostream>
#include <boost/filesystem/operations.hpp>
#include <boost/program_options.hpp>
#include <boost/exception/all.hpp>
#include "configuration.hpp"

namespace bpo = boost::program_options;

namespace AssimpWorker {

Configuration* Configuration::singletonInstance = NULL;
const char* Configuration::defaultConfigFilename = "assimpworker.conf";

Configuration& Configuration::getInstance() {
	if (singletonInstance == NULL) {
		singletonInstance = new Configuration();
	}
	return *singletonInstance;
}

Configuration::Configuration()
{
	setupOptions();
	parseConfigFile();
}

void Configuration::init(int argc, char **argv) {
	bpo::command_line_parser parser(argc, argv);
	parser.options(description);
	bpo::store(parser.run(),parsedVariables);
	// in case the default file didn't exist
	// and we now know a non-default name:
	parseConfigFile();
	if (parsedVariables.count("help")) {
		std::cout << description << std::endl;
		exit(1);
	}
	// now that we have parsed commandline
	// as well as default and possibly other configfile
	// check for missing stuff:
	try {
		bpo::notify(parsedVariables);
	} catch (std::exception const& e) {
		std::cerr << "Parsing options:" << e.what() << std::endl;
		exit(1);
	}
}

void Configuration::parseConfigFile() {
	const char* configFileName = NULL;
	if (parsedVariables.count("config")) {
		// config file specified
		std::string configFile = parsedVariables["config"].as<std::string>();
		configFileName = configFile.c_str();
	} else if (defaultConfigExists()) {
		configFileName = defaultConfigFilename;
	}
	if (!configFileName){
		return;
	}
	std::ifstream configFile(configFileName);
	if (configFile.good()) {
		bpo::parsed_options parsedConfig = bpo::parse_config_file(configFile,description);
		bpo::store(parsedConfig, parsedVariables);
	}
	// don't notify here, as we may not have parsed commandline yet.
}

bool Configuration::defaultConfigExists() {
	return boost::filesystem::exists(defaultConfigFilename);
}

void Configuration::setupOptions() {
	bpo::options_description basic("Basic options");
	basic.add_options()
		("help,h,?", "show this message")
		("version,v","show version number")
		("config,c", bpo::value<std::string>(), "read configuration from file, overrides options given on command line")
		("decompression-path", bpo::value<std::string>()->default_value("./tmp"), "Path to temporary space for decompressed zip contents")
	;
	bpo::options_description import("Import options");
	import.add_options()
		("mesh-split", "Split meshes larger than a certain number of vertices.")
		("mesh-split-threshold", bpo::value<int>()->default_value(65535), "Number of vertices at which to split.")
	;
	bpo::options_description stomp("Stomp options");
	stomp.add_options()
		("stomp-heartbeat-interval-ms", bpo::value<int>()->default_value(10000), "Heartbeat interval in ms")
		("stomp-port", bpo::value<int>()        ->default_value(61613),              "Server port (STOMP protocol)")
		("stomp-host", bpo::value<std::string>()->default_value("localhost"),        "Server address")
		("stomp-user", bpo::value<std::string>()->required(),                        "Username")
		("stomp-pass", bpo::value<std::string>()->required(),                        "Password")
		("work-queue",bpo::value<std::string>()->default_value("atlas.work.import"),"Work queue name")
		("feedback-queue",bpo::value<std::string>()->default_value("atlas.work.feedback"),"Feedback queue name")
	;
	bpo::options_description jcr("Repository options");
	jcr.add_options()
		("jcr-url",
		 bpo::value<std::string>()->default_value("http://localhost:8080/modeshape-rest/atlas/default/"),
		 "Root URL")
		("jcr-user",
		 bpo::value<std::string>()->default_value("admin"),
		 "Username")
		("jcr-pass",
		 bpo::value<std::string>()->default_value("admin"),
		 "Password")
	;

	description.add(basic);
	description.add(import);
	description.add(stomp);
	description.add(jcr);
}

const bpo::variable_value& Configuration::get(const std::string &entry) const {
	return parsedVariables[entry];
}

const bool Configuration::enabled(const std::string& entry) const
{
	return parsedVariables.count(entry);
}

}

<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2017.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include "../IO/FileAccessException.h"

#include "Exceptions.h"

#include "ErrNoException.h"

using namespace Stroika;
using namespace Stroika::Foundation;

using namespace Characters;
using namespace Execution;

using Debug::TraceContextBumper;

/*
 ********************************************************************************
 ***************************** errno_ErrorException *****************************
 ********************************************************************************
 */
errno_ErrorException::errno_ErrorException (Execution::errno_t e)
    : StringException (SDKString2Wide (LookupMessage (e)))
    , fError (e)
{
}

SDKString errno_ErrorException::LookupMessage (Execution::errno_t e)
{
    SDKString justErrnoNumberMessage;
    {
        SDKChar justNumBuf[2048];
        justNumBuf[0] = '\0';
#if qPlatform_Windows
        (void)::_stprintf_s (justNumBuf, SDKSTR ("errno: %d"), e);
#else
        (void)::snprintf (justNumBuf, NEltsOf (justNumBuf), SDKSTR ("errno: %d"), e);
#endif
        justErrnoNumberMessage = justNumBuf;
    }
    SDKChar buf[2048];
    buf[0] = '\0';
#if qPlatform_Windows
    if (::_tcserror_s (buf, e) == 0) {
        return buf + SDKString (SDKSTR (" (") + justErrnoNumberMessage + SDKSTR (")"));
    }
#elif qPlatform_Linux
	/*
	 * A bit quirky - GNU-specific and POSIX handle this API fairly differently.
	 * https://linux.die.net/man/3/strerror_r - in one case returns int and 0 means worked,
	 * and other case always returns string to use (not in buf)
	 */
#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE
	// The XSI-compliant strerror_r() function returns 0 on success
	if (::strerror_r (e, buf, NEltsOf (buf)) == 0) {
		return buf + SDKString (SDKSTR (" (") + justErrnoNumberMessage + SDKSTR (")"));
	}
#else
	// the GNU-specific strerror_r() functions return the appropriate error description string
	// NOTE - this version MAY or MAY NOT modify buf - it sometimes returns static strings!
	return ::strerror_r (e, buf, NEltsOf (buf)) + SDKString (SDKSTR (" (") + justErrnoNumberMessage + SDKSTR (")"));
#endif
#elif qPlatform_POSIX
	// The XSI-compliant strerror_r() function returns 0 on success
	if (::strerror_r (e, buf, NEltsOf (buf)) == 0) {
		return buf + SDKString (SDKSTR (" (") + justErrnoNumberMessage + SDKSTR (")"));
	}
#else
    AssertNotImplemented ();
#endif
    return justErrnoNumberMessage;
}

[[noreturn]] void errno_ErrorException::Throw (Execution::errno_t error)
{
    //REVIEW EXCPETIONS ANMD MPAPING - THIS IS NOT GOOD - NOT EVEN CLOSE!!! -- LGP 2011-09-29
    switch (error) {
        case ENOMEM: {
            Execution::Throw (bad_alloc (), "errno_ErrorException::Throw (ENOMEM) - throwing bad_alloc");
        }
        case ENOENT: {
            Execution::Throw (IO::FileAccessException ()); // don't know if they were reading or writing at this level..., and don't know file name...
        }
        case EACCES: {
            Execution::Throw (IO::FileAccessException ()); // don't know if they were reading or writing at this level..., and don't know file name...
        }
// If I decide to pursue mapping, this maybe a good place to start
//  http://aplawrence.com/Unixart/errors.html
//      -- LGP 2009-01-02
#if 0
        case    EPERM: {
                // not sure any point in this unification. Maybe if I added my OWN private 'access denied' exception
                // the mapping/unification would make sense.
                //      -- LGP 2009-01-02
                DbgTrace ("errno_ErrorException::Throw (EPERM) - throwing ERROR_ACCESS_DENIED");
                throw Win32Exception (ERROR_ACCESS_DENIED);
            }
#endif
    }
    DbgTrace (L"errno_ErrorException::Throw (%d) - throwing errno_ErrorException '%s'", error, SDKString2Wide (LookupMessage (error)).c_str ());
    throw errno_ErrorException (error);
}
<commit_msg>make format-code<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2017.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include "../IO/FileAccessException.h"

#include "Exceptions.h"

#include "ErrNoException.h"

using namespace Stroika;
using namespace Stroika::Foundation;

using namespace Characters;
using namespace Execution;

using Debug::TraceContextBumper;

/*
 ********************************************************************************
 ***************************** errno_ErrorException *****************************
 ********************************************************************************
 */
errno_ErrorException::errno_ErrorException (Execution::errno_t e)
    : StringException (SDKString2Wide (LookupMessage (e)))
    , fError (e)
{
}

SDKString errno_ErrorException::LookupMessage (Execution::errno_t e)
{
    SDKString justErrnoNumberMessage;
    {
        SDKChar justNumBuf[2048];
        justNumBuf[0] = '\0';
#if qPlatform_Windows
        (void)::_stprintf_s (justNumBuf, SDKSTR ("errno: %d"), e);
#else
        (void)::snprintf (justNumBuf, NEltsOf (justNumBuf), SDKSTR ("errno: %d"), e);
#endif
        justErrnoNumberMessage = justNumBuf;
    }
    SDKChar buf[2048];
    buf[0] = '\0';
#if qPlatform_Windows
    if (::_tcserror_s (buf, e) == 0) {
        return buf + SDKString (SDKSTR (" (") + justErrnoNumberMessage + SDKSTR (")"));
    }
#elif qPlatform_Linux
/*
     * A bit quirky - GNU-specific and POSIX handle this API fairly differently.
     * https://linux.die.net/man/3/strerror_r - in one case returns int and 0 means worked,
     * and other case always returns string to use (not in buf)
     */
#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE
    // The XSI-compliant strerror_r() function returns 0 on success
    if (::strerror_r (e, buf, NEltsOf (buf)) == 0) {
        return buf + SDKString (SDKSTR (" (") + justErrnoNumberMessage + SDKSTR (")"));
    }
#else
    // the GNU-specific strerror_r() functions return the appropriate error description string
    // NOTE - this version MAY or MAY NOT modify buf - it sometimes returns static strings!
    return ::strerror_r (e, buf, NEltsOf (buf)) + SDKString (SDKSTR (" (") + justErrnoNumberMessage + SDKSTR (")"));
#endif
#elif qPlatform_POSIX
    // The XSI-compliant strerror_r() function returns 0 on success
    if (::strerror_r (e, buf, NEltsOf (buf)) == 0) {
        return buf + SDKString (SDKSTR (" (") + justErrnoNumberMessage + SDKSTR (")"));
    }
#else
    AssertNotImplemented ();
#endif
    return justErrnoNumberMessage;
}

[[noreturn]] void errno_ErrorException::Throw (Execution::errno_t error)
{
    //REVIEW EXCPETIONS ANMD MPAPING - THIS IS NOT GOOD - NOT EVEN CLOSE!!! -- LGP 2011-09-29
    switch (error) {
        case ENOMEM: {
            Execution::Throw (bad_alloc (), "errno_ErrorException::Throw (ENOMEM) - throwing bad_alloc");
        }
        case ENOENT: {
            Execution::Throw (IO::FileAccessException ()); // don't know if they were reading or writing at this level..., and don't know file name...
        }
        case EACCES: {
            Execution::Throw (IO::FileAccessException ()); // don't know if they were reading or writing at this level..., and don't know file name...
        }
// If I decide to pursue mapping, this maybe a good place to start
//  http://aplawrence.com/Unixart/errors.html
//      -- LGP 2009-01-02
#if 0
        case    EPERM: {
                // not sure any point in this unification. Maybe if I added my OWN private 'access denied' exception
                // the mapping/unification would make sense.
                //      -- LGP 2009-01-02
                DbgTrace ("errno_ErrorException::Throw (EPERM) - throwing ERROR_ACCESS_DENIED");
                throw Win32Exception (ERROR_ACCESS_DENIED);
            }
#endif
    }
    DbgTrace (L"errno_ErrorException::Throw (%d) - throwing errno_ErrorException '%s'", error, SDKString2Wide (LookupMessage (error)).c_str ());
    throw errno_ErrorException (error);
}
<|endoftext|>


<commit_before>/**
 *  ifaces.cpp
 *  StatusSpec project
 *
 *  Copyright (c) 2014 thesupremecommander
 *  BSD 2-Clause License
 *  http://opensource.org/licenses/BSD-2-Clause
 *
 */

#include "ifaces.h"

IBaseClientDLL *Interfaces::pClientDLL = nullptr;
IClientEntityList *Interfaces::pClientEntityList = nullptr;
CDllDemandLoader *Interfaces::pClientModule = nullptr;
IVEngineClient *Interfaces::pEngineClient = nullptr;
IFileSystem *Interfaces::pFileSystem = nullptr;
IGameEventManager2 *Interfaces::pGameEventManager = nullptr;
IVModelInfoClient *Interfaces::pModelInfoClient = nullptr;
IPlayerInfoManager *Interfaces::pPlayerInfoManager = nullptr;
IVRenderView *Interfaces::pRenderView = nullptr;
CSteamAPIContext *Interfaces::pSteamAPIContext = nullptr;

CBaseEntityList *g_pEntityList;

IClientMode *Interfaces::GetClientMode() {
#if defined _WIN32
	static DWORD pointer = NULL;

	if (!pointer) {
		pointer = SignatureScan("client", CLIENTMODE_SIG, CLIENTMODE_MASK) + CLIENTMODE_OFFSET;

		if (!pointer) {
			throw bad_pointer("IClientMode");
		}
	}

	if (!**(IClientMode***)pointer) {
		throw bad_pointer("IClientMode");
	}

	return **(IClientMode***)(pointer);
#else
	throw bad_pointer("IClientMode");

	return nullptr;
#endif
}

IGameResources *Interfaces::GetGameResources() {
#if defined _WIN32
	static DWORD pointer = NULL;

	if (!pointer) {
		pointer = SignatureScan("client", GAMERESOURCES_SIG, GAMERESOURCES_MASK);

		if (!pointer) {
			throw bad_pointer("IGameResources");
		}
	}

	GGR_t GGR = (GGR_t) pointer;
	IGameResources *gr = GGR();

	if (!gr) {
		throw bad_pointer("IGameResources");
	}

	return gr;
#else
	throw bad_pointer("IGameResources");

	return nullptr;
#endif
}

CGlobalVarsBase *Interfaces::GetGlobalVars() {
#if defined _WIN32
	static DWORD pointer = NULL;

	if (!pointer) {
		pointer = SignatureScan("client", GPGLOBALS_SIG, GPGLOBALS_MASK) + GPGLOBALS_OFFSET;

		if (!pointer) {
			throw bad_pointer("CGlobalVarsBase");
		}
	}

	if (!**(CGlobalVarsBase***)pointer) {
		throw bad_pointer("CGlobalVarsBase");
	}

	return **(CGlobalVarsBase***)(pointer);
#else
	throw bad_pointer("CGlobalVarsBase");

	return nullptr;
#endif
}

C_HLTVCamera *Interfaces::GetHLTVCamera() {
#if defined _WIN32
	static DWORD pointer = NULL;

	if (!pointer) {
		pointer = SignatureScan("client", HLTVCAMERA_SIG, HLTVCAMERA_MASK) + HLTVCAMERA_OFFSET;

		if (!pointer) {
			throw bad_pointer("C_HLTVCamera");
		}
	}

	if (!*(C_HLTVCamera**)pointer) {
		throw bad_pointer("C_HLTVCamera");
	}

	return *(C_HLTVCamera**)(pointer);
#else
	throw bad_pointer("C_HLTVCamera");

	return nullptr;
#endif
}

void Interfaces::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory) {
	ConnectTier1Libraries(&interfaceFactory, 1);
	ConnectTier2Libraries(&interfaceFactory, 1);
	ConnectTier3Libraries(&interfaceFactory, 1);

	vgui::VGui_InitInterfacesList("statusspec", &interfaceFactory, 1);

	pEngineClient = (IVEngineClient *)interfaceFactory(VENGINE_CLIENT_INTERFACE_VERSION, nullptr);
	pGameEventManager = (IGameEventManager2 *)interfaceFactory(INTERFACEVERSION_GAMEEVENTSMANAGER2, nullptr);
	pModelInfoClient = (IVModelInfoClient *)interfaceFactory(VMODELINFO_CLIENT_INTERFACE_VERSION, nullptr);
	pPlayerInfoManager = (IPlayerInfoManager *)gameServerFactory(INTERFACEVERSION_PLAYERINFOMANAGER, nullptr);
	pRenderView = (IVRenderView *)interfaceFactory(VENGINE_RENDERVIEW_INTERFACE_VERSION, nullptr);

	pClientModule = new CDllDemandLoader(CLIENT_MODULE_FILE);

	CreateInterfaceFn gameClientFactory = pClientModule->GetFactory();

	pClientDLL = (IBaseClientDLL*)gameClientFactory(CLIENT_DLL_INTERFACE_VERSION, nullptr);
	pClientEntityList = (IClientEntityList*)gameClientFactory(VCLIENTENTITYLIST_INTERFACE_VERSION, nullptr);

	pSteamAPIContext = new CSteamAPIContext();
	steamLibrariesAvailable = SteamAPI_InitSafe() && pSteamAPIContext->Init();

	g_pEntityList = dynamic_cast<CBaseEntityList *>(Interfaces::pClientEntityList);

	char dll[MAX_PATH];
	bool steam;
	if (FileSystem_GetFileSystemDLLName(dll, sizeof(dll), steam) == FS_OK) {
		CFSLoadModuleInfo fsLoadModuleInfo;
		fsLoadModuleInfo.m_bSteam = steam;
		fsLoadModuleInfo.m_pFileSystemDLLName = dll;
		fsLoadModuleInfo.m_ConnectFactory = interfaceFactory;

		if (FileSystem_LoadFileSystemModule(fsLoadModuleInfo) == FS_OK) {
			CFSMountContentInfo fsMountContentInfo;
			fsMountContentInfo.m_bToolsMode = fsLoadModuleInfo.m_bToolsMode;
			fsMountContentInfo.m_pDirectoryName = fsLoadModuleInfo.m_GameInfoPath;
			fsMountContentInfo.m_pFileSystem = fsLoadModuleInfo.m_pFileSystem;

			if (FileSystem_MountContent(fsMountContentInfo) == FS_OK) {
				CFSSearchPathsInit fsSearchPathsInit;
				fsSearchPathsInit.m_pDirectoryName = fsLoadModuleInfo.m_GameInfoPath;
				fsSearchPathsInit.m_pFileSystem = fsLoadModuleInfo.m_pFileSystem;

				if (FileSystem_LoadSearchPaths(fsSearchPathsInit) == FS_OK) {
					Interfaces::pFileSystem = fsLoadModuleInfo.m_pFileSystem;
				}
			}
		}
	}
}

void Interfaces::Unload() {
	DisconnectTier3Libraries();
	DisconnectTier2Libraries();
	DisconnectTier1Libraries();

	pSteamAPIContext->Clear();

	pClientModule->Unload();
	pClientModule = nullptr;

	pClientDLL = nullptr;
	pClientEntityList = nullptr;
	pEngineClient = nullptr;
	pFileSystem = nullptr;
	pGameEventManager = nullptr;
	pRenderView = nullptr;
}<commit_msg>Add definition for steam library availability.<commit_after>/**
 *  ifaces.cpp
 *  StatusSpec project
 *
 *  Copyright (c) 2014 thesupremecommander
 *  BSD 2-Clause License
 *  http://opensource.org/licenses/BSD-2-Clause
 *
 */

#include "ifaces.h"

IBaseClientDLL *Interfaces::pClientDLL = nullptr;
IClientEntityList *Interfaces::pClientEntityList = nullptr;
CDllDemandLoader *Interfaces::pClientModule = nullptr;
IVEngineClient *Interfaces::pEngineClient = nullptr;
IFileSystem *Interfaces::pFileSystem = nullptr;
IGameEventManager2 *Interfaces::pGameEventManager = nullptr;
IVModelInfoClient *Interfaces::pModelInfoClient = nullptr;
IPlayerInfoManager *Interfaces::pPlayerInfoManager = nullptr;
IVRenderView *Interfaces::pRenderView = nullptr;
CSteamAPIContext *Interfaces::pSteamAPIContext = nullptr;

bool Interfaces::steamLibrariesAvailable = false;

CBaseEntityList *g_pEntityList;

IClientMode *Interfaces::GetClientMode() {
#if defined _WIN32
	static DWORD pointer = NULL;

	if (!pointer) {
		pointer = SignatureScan("client", CLIENTMODE_SIG, CLIENTMODE_MASK) + CLIENTMODE_OFFSET;

		if (!pointer) {
			throw bad_pointer("IClientMode");
		}
	}

	if (!**(IClientMode***)pointer) {
		throw bad_pointer("IClientMode");
	}

	return **(IClientMode***)(pointer);
#else
	throw bad_pointer("IClientMode");

	return nullptr;
#endif
}

IGameResources *Interfaces::GetGameResources() {
#if defined _WIN32
	static DWORD pointer = NULL;

	if (!pointer) {
		pointer = SignatureScan("client", GAMERESOURCES_SIG, GAMERESOURCES_MASK);

		if (!pointer) {
			throw bad_pointer("IGameResources");
		}
	}

	GGR_t GGR = (GGR_t) pointer;
	IGameResources *gr = GGR();

	if (!gr) {
		throw bad_pointer("IGameResources");
	}

	return gr;
#else
	throw bad_pointer("IGameResources");

	return nullptr;
#endif
}

CGlobalVarsBase *Interfaces::GetGlobalVars() {
#if defined _WIN32
	static DWORD pointer = NULL;

	if (!pointer) {
		pointer = SignatureScan("client", GPGLOBALS_SIG, GPGLOBALS_MASK) + GPGLOBALS_OFFSET;

		if (!pointer) {
			throw bad_pointer("CGlobalVarsBase");
		}
	}

	if (!**(CGlobalVarsBase***)pointer) {
		throw bad_pointer("CGlobalVarsBase");
	}

	return **(CGlobalVarsBase***)(pointer);
#else
	throw bad_pointer("CGlobalVarsBase");

	return nullptr;
#endif
}

C_HLTVCamera *Interfaces::GetHLTVCamera() {
#if defined _WIN32
	static DWORD pointer = NULL;

	if (!pointer) {
		pointer = SignatureScan("client", HLTVCAMERA_SIG, HLTVCAMERA_MASK) + HLTVCAMERA_OFFSET;

		if (!pointer) {
			throw bad_pointer("C_HLTVCamera");
		}
	}

	if (!*(C_HLTVCamera**)pointer) {
		throw bad_pointer("C_HLTVCamera");
	}

	return *(C_HLTVCamera**)(pointer);
#else
	throw bad_pointer("C_HLTVCamera");

	return nullptr;
#endif
}

void Interfaces::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory) {
	ConnectTier1Libraries(&interfaceFactory, 1);
	ConnectTier2Libraries(&interfaceFactory, 1);
	ConnectTier3Libraries(&interfaceFactory, 1);

	vgui::VGui_InitInterfacesList("statusspec", &interfaceFactory, 1);

	pEngineClient = (IVEngineClient *)interfaceFactory(VENGINE_CLIENT_INTERFACE_VERSION, nullptr);
	pGameEventManager = (IGameEventManager2 *)interfaceFactory(INTERFACEVERSION_GAMEEVENTSMANAGER2, nullptr);
	pModelInfoClient = (IVModelInfoClient *)interfaceFactory(VMODELINFO_CLIENT_INTERFACE_VERSION, nullptr);
	pPlayerInfoManager = (IPlayerInfoManager *)gameServerFactory(INTERFACEVERSION_PLAYERINFOMANAGER, nullptr);
	pRenderView = (IVRenderView *)interfaceFactory(VENGINE_RENDERVIEW_INTERFACE_VERSION, nullptr);

	pClientModule = new CDllDemandLoader(CLIENT_MODULE_FILE);

	CreateInterfaceFn gameClientFactory = pClientModule->GetFactory();

	pClientDLL = (IBaseClientDLL*)gameClientFactory(CLIENT_DLL_INTERFACE_VERSION, nullptr);
	pClientEntityList = (IClientEntityList*)gameClientFactory(VCLIENTENTITYLIST_INTERFACE_VERSION, nullptr);

	pSteamAPIContext = new CSteamAPIContext();
	steamLibrariesAvailable = SteamAPI_InitSafe() && pSteamAPIContext->Init();

	g_pEntityList = dynamic_cast<CBaseEntityList *>(Interfaces::pClientEntityList);

	char dll[MAX_PATH];
	bool steam;
	if (FileSystem_GetFileSystemDLLName(dll, sizeof(dll), steam) == FS_OK) {
		CFSLoadModuleInfo fsLoadModuleInfo;
		fsLoadModuleInfo.m_bSteam = steam;
		fsLoadModuleInfo.m_pFileSystemDLLName = dll;
		fsLoadModuleInfo.m_ConnectFactory = interfaceFactory;

		if (FileSystem_LoadFileSystemModule(fsLoadModuleInfo) == FS_OK) {
			CFSMountContentInfo fsMountContentInfo;
			fsMountContentInfo.m_bToolsMode = fsLoadModuleInfo.m_bToolsMode;
			fsMountContentInfo.m_pDirectoryName = fsLoadModuleInfo.m_GameInfoPath;
			fsMountContentInfo.m_pFileSystem = fsLoadModuleInfo.m_pFileSystem;

			if (FileSystem_MountContent(fsMountContentInfo) == FS_OK) {
				CFSSearchPathsInit fsSearchPathsInit;
				fsSearchPathsInit.m_pDirectoryName = fsLoadModuleInfo.m_GameInfoPath;
				fsSearchPathsInit.m_pFileSystem = fsLoadModuleInfo.m_pFileSystem;

				if (FileSystem_LoadSearchPaths(fsSearchPathsInit) == FS_OK) {
					Interfaces::pFileSystem = fsLoadModuleInfo.m_pFileSystem;
				}
			}
		}
	}
}

void Interfaces::Unload() {
	DisconnectTier3Libraries();
	DisconnectTier2Libraries();
	DisconnectTier1Libraries();

	pSteamAPIContext->Clear();

	pClientModule->Unload();
	pClientModule = nullptr;

	pClientDLL = nullptr;
	pClientEntityList = nullptr;
	pEngineClient = nullptr;
	pFileSystem = nullptr;
	pGameEventManager = nullptr;
	pRenderView = nullptr;
}<|endoftext|>