<commit_before>/* Picasso - a vector graphics library
 *
 * Copyright (C) 2014 Zhang Ji Peng
 * Contact: onecoolx@gmail.com
 */

#include "common.h"

#include "gfx_math.h"
#include "gfx_gradient_adapter.h"
#include "gfx_line_generator.h"

namespace gfx {

// gradient functions

// gradient_x
class gradient_x
{
public:
    void init(scalar, scalar, scalar) { }
    static int calculate(int x, int, int) { return x; }
};

// gradient_conic
class gradient_conic
{
public:
    void init(scalar, scalar, scalar) { }
    static int calculate(int x, int y, int d)
    {
        return uround(Fabs(Atan2(INT_TO_SCALAR(y), INT_TO_SCALAR(x))) * INT_TO_SCALAR(d) * _1divPI);
    }
};

class gradient_conic_vg
{
public:
    void init(scalar, scalar, scalar) { }
    static int calculate(int x, int y, int d)
    {
        scalar a = Atan2(INT_TO_SCALAR(y), INT_TO_SCALAR(x));
        if (a < 0) a = _2PI + a;
        return round(a * INT_TO_SCALAR(d) * _1div2PI);
    }
};

// gradient_radial
class gradient_radial
{
public:
    void init(scalar, scalar, scalar) { }
    static int calculate(int x, int y, int d)
    {
        return (int)fast_sqrt(x*x + y*y);
    }
};

// gradient_radial_focus
class gradient_radial_focus
{
public:
    gradient_radial_focus()
        : m_r(100 * gradient_subpixel_scale)
        , m_fx(0)
        , m_fy(0)
    {
        update_values();
    }

    void init(scalar r, scalar fx, scalar fy)
    {
        m_r = iround(r * gradient_subpixel_scale);
        m_fx = iround(fx * gradient_subpixel_scale);
        m_fy = iround(fy * gradient_subpixel_scale);
        update_values();
    }

    int calculate(int x, int y, int) const
    {
        scalar dx = INT_TO_SCALAR(x - m_fx);
        scalar dy = INT_TO_SCALAR(y - m_fy);
        scalar d2 = dx * m_fy - dy * m_fx;
        scalar d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2;
        return iround((dx * m_fx + dy * m_fy + Sqrt(Fabs(d3))) * m_mul);
    }

private:
    void update_values(void)
    {
        // Calculate the invariant values. In case the focal center
        // lies exactly on the gradient circle the divisor degenerates
        // into zero. In this case we just move the focal center by
        // one subpixel unit possibly in the direction to the origin (0,0)
        // and calculate the values again.

        m_r2 = INT_TO_SCALAR(m_r) * INT_TO_SCALAR(m_r);
        m_fx2 = INT_TO_SCALAR(m_fx) * INT_TO_SCALAR(m_fx);
        m_fy2 = INT_TO_SCALAR(m_fy) * INT_TO_SCALAR(m_fy);
        scalar d = (m_r2 - (m_fx2 + m_fy2));
        if (d == INT_TO_SCALAR(0)) {
            if (m_fx) {
                if (m_fx < 0)
                    ++m_fx;
                else
                    --m_fx;
            }

            if (m_fy) {
                if (m_fy < 0)
                    ++m_fy;
                else
                    --m_fy;
            }

            m_fx2 = INT_TO_SCALAR(m_fx) * INT_TO_SCALAR(m_fx);
            m_fy2 = INT_TO_SCALAR(m_fy) * INT_TO_SCALAR(m_fy);
            d = (m_r2 - (m_fx2 + m_fy2));
        }
        m_mul = m_r / d;
    }

private:
    int m_r;
    int m_fx;
    int m_fy;
    scalar m_r2;
    scalar m_fx2;
    scalar m_fy2;
    scalar m_mul;
};

// gradient adaptors

// gradient once adaptor
template <typename GradientFunc>
class gradient_pad_adaptor
{
public:
    gradient_pad_adaptor(const GradientFunc& gradient)
        : m_gradient(&gradient)
    {
    }

    int calculate(int x, int y, int d) const
    {
        int ret = m_gradient->calculate(x, y, d);
        if (ret < 0) ret = 0;
        if (ret > d) ret = d;
        return ret;
    }

private:
    const GradientFunc* m_gradient;
};

// gradient repeat adaptor
template <typename GradientFunc>
class gradient_repeat_adaptor
{
public:
    gradient_repeat_adaptor(const GradientFunc& gradient)
        : m_gradient(&gradient)
    {
    }

    int calculate(int x, int y, int d) const
    {
        int ret = m_gradient->calculate(x, y, d) % d;
        if (ret < 0) ret += d;
        return ret;
    }

private:
    const GradientFunc* m_gradient;
};

// gradient reflect adaptor
template <typename GradientFunc>
class gradient_reflect_adaptor
{
public:
    gradient_reflect_adaptor(const GradientFunc& gradient)
        : m_gradient(&gradient)
    {
    }

    int calculate(int x, int y, int d) const
    {
        int d2 = d << 1;
        int ret = m_gradient->calculate(x, y, d) % d2;
        if (ret < 0) ret += d2;
        if (ret >= d) ret = d2 - ret;
        return ret;
    }

private:
    const GradientFunc* m_gradient;
};

// gradient wrapper implements
template <typename GradientFunc, typename Adaptor>
class gfx_gradient : public gfx_gradient_wrapper
{
public:
    gfx_gradient()
        : m_gradient()
        , m_adaptor(m_gradient)
    {
    }

    virtual void init(scalar r, scalar x, scalar y)
    {
        m_gradient.init(r, x, y);
    }

    virtual int calculate(int x, int y, int d) const
    {
        return m_adaptor.calculate(x, y, d);
    }

private:
    GradientFunc m_gradient;
    Adaptor m_adaptor;
};

// gfx gradient table

// rgba8 color interpolator
struct color_interpolator
{
public:
    typedef rgba8 color_type;

    color_interpolator(const color_type& c1, const color_type& c2, unsigned len)
        : r(c1.r, c2.r, len)
        , g(c1.g, c2.g, len)
        , b(c1.b, c2.b, len)
        , a(c1.a, c2.a, len)
    {
    }

    void operator ++ ()
    {
        ++r; ++g; ++b; ++a;
    }

    color_type color(void) const
    {
        return color_type(r.y(), g.y(), b.y(), a.y());
    }

private:
    gfx_dda_line_interpolator<14> r;
    gfx_dda_line_interpolator<14> g;
    gfx_dda_line_interpolator<14> b;
    gfx_dda_line_interpolator<14> a;
};

void gfx_gradient_table::build_table(void)
{
    quick_sort(m_color_profile, offset_less);
    m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal));

    if (m_color_profile.size() >= 2) {
        unsigned int i;
        unsigned int start = uround(m_color_profile[0].offset * color_table_size);
        unsigned int end = 0;
        color_type c = m_color_profile[0].color;

        for (i = 0; i < start; i++) {
            m_color_table[i] = c;
        }

        for (i = 1; i < m_color_profile.size(); i++) {
            end  = uround(m_color_profile[i].offset * color_table_size);
            color_interpolator ci(m_color_profile[i-1].color,
                                  m_color_profile[i].color, end - start + 1);
            while (start < end) {
                m_color_table[start] = ci.color();
                ++ci;
                ++start;
            }
        }

        c = m_color_profile.last().color;

        for (; end < m_color_table.size(); end++) {
            m_color_table[end] = c;
        }
    }
}

// gfx gradient adapter
void gfx_gradient_adapter::init_linear(int spread, scalar x1, scalar y1, scalar x2, scalar y2)
{
    if (!m_wrapper) {
        switch (spread) {
            case SPREAD_PAD:
                m_wrapper = new gfx_gradient<gradient_x, gradient_pad_adaptor<gradient_x> >;
                break;
            case SPREAD_REPEAT:
                m_wrapper = new gfx_gradient<gradient_x, gradient_repeat_adaptor<gradient_x> >;
                break;
            case SPREAD_REFLECT:
                m_wrapper = new gfx_gradient<gradient_x, gradient_reflect_adaptor<gradient_x> >;
                break;
        };

        if (!m_wrapper)
            return;

        scalar len = calc_distance(x1, y1, x2, y2);

        gfx_trans_affine mtx;
        if (len) {
            if (x2 < x1)
                mtx.rotate(PI - Asin((y2 - y1) / len));
            else
                mtx.rotate(Asin((y2 - y1) / len));
        } else
            len = FLT_TO_SCALAR(2.0f); // len can not be zero

        mtx.translate(x1, y1);

        m_start = FLT_TO_SCALAR(0.0f);
        m_length = len;
        m_matrix = mtx;
    }
}

void gfx_gradient_adapter::init_radial(int spread, scalar x1, scalar y1, scalar radius1,
                                           scalar x2, scalar y2, scalar radius2)
{
    if (!m_wrapper) {
        if ((x1 == x2) && (y1 == y2)) {
            switch (spread) {
                case SPREAD_PAD:
                    m_wrapper = new gfx_gradient<gradient_radial,
                                             gradient_pad_adaptor<gradient_radial> >;
                    break;
                case SPREAD_REPEAT:
                    m_wrapper = new gfx_gradient<gradient_radial,
                                             gradient_repeat_adaptor<gradient_radial> >;
                    break;
                case SPREAD_REFLECT:
                    m_wrapper = new gfx_gradient<gradient_radial,
                                             gradient_reflect_adaptor<gradient_radial> >;
                    break;
            }
        } else {
            switch (spread) {
                case SPREAD_PAD:
                    m_wrapper = new gfx_gradient<gradient_radial_focus,
                                             gradient_pad_adaptor<gradient_radial_focus> >;
                    break;
                case SPREAD_REPEAT:
                    m_wrapper = new gfx_gradient<gradient_radial_focus,
                                             gradient_repeat_adaptor<gradient_radial_focus> >;
                    break;
                case SPREAD_REFLECT:
                    m_wrapper = new gfx_gradient<gradient_radial_focus,
                                             gradient_reflect_adaptor<gradient_radial_focus> >;
                    break;
            }

        }

        if (!m_wrapper)
            return;

        scalar len = Fabs(radius2);
        scalar fx = x1 - x2;
        scalar fy = y1 - y2;

        m_wrapper->init(len, fx, fy);

        if (!len)
            len = FLT_TO_SCALAR(2.0f); // len can not be zero

        gfx_trans_affine mtx;
        mtx.translate(x1 - fx, y1 - fy);

        m_start = Fabs(radius1);
        m_length = len;
        m_matrix = mtx;
    }
}

void gfx_gradient_adapter::init_conic(int spread, scalar x, scalar y, scalar angle)
{
    if (!m_wrapper) {
        if (spread == SPREAD_REFLECT) {
            m_wrapper = new gfx_gradient<gradient_conic, gradient_reflect_adaptor<gradient_conic> >;
        } else {
            m_wrapper = new gfx_gradient<gradient_conic_vg, gradient_pad_adaptor<gradient_conic_vg> >;
        }

        if (!m_wrapper)
            return;

        gfx_trans_affine mtx;
        mtx.translate(x, y);
        mtx.translate(-x, -y);
        mtx.rotate(angle);
        mtx.translate(x, y);

        m_start = INT_TO_SCALAR(0);
        m_length = INT_TO_SCALAR(128);
        m_matrix = mtx;
    }
}

}
<commit_msg>fix win32 gyp build<commit_after>/* Picasso - a vector graphics library
 *
 * Copyright (C) 2014 Zhang Ji Peng
 * Contact: onecoolx@gmail.com
 */

#include "common.h"

#include "gfx_math.h"
#include "gfx_gradient_adapter.h"
#include "gfx_line_generator.h"

namespace gfx {

// gradient functions

// gradient_x
class gradient_x
{
public:
    void init(scalar, scalar, scalar) { }
    static int calculate(int x, int, int) { return x; }
};

// gradient_conic
class gradient_conic
{
public:
    void init(scalar, scalar, scalar) { }
    static int calculate(int x, int y, int d)
    {
        return uround(Fabs(Atan2(INT_TO_SCALAR(y), INT_TO_SCALAR(x))) * INT_TO_SCALAR(d) * _1divPI);
    }
};

class gradient_conic_vg
{
public:
    void init(scalar, scalar, scalar) { }
    static int calculate(int x, int y, int d)
    {
        scalar a = Atan2(INT_TO_SCALAR(y), INT_TO_SCALAR(x));
        if (a < 0) a = _2PI + a;
        return iround(a * INT_TO_SCALAR(d) * _1div2PI);
    }
};

// gradient_radial
class gradient_radial
{
public:
    void init(scalar, scalar, scalar) { }
    static int calculate(int x, int y, int d)
    {
        return (int)fast_sqrt(x*x + y*y);
    }
};

// gradient_radial_focus
class gradient_radial_focus
{
public:
    gradient_radial_focus()
        : m_r(100 * gradient_subpixel_scale)
        , m_fx(0)
        , m_fy(0)
    {
        update_values();
    }

    void init(scalar r, scalar fx, scalar fy)
    {
        m_r = iround(r * gradient_subpixel_scale);
        m_fx = iround(fx * gradient_subpixel_scale);
        m_fy = iround(fy * gradient_subpixel_scale);
        update_values();
    }

    int calculate(int x, int y, int) const
    {
        scalar dx = INT_TO_SCALAR(x - m_fx);
        scalar dy = INT_TO_SCALAR(y - m_fy);
        scalar d2 = dx * m_fy - dy * m_fx;
        scalar d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2;
        return iround((dx * m_fx + dy * m_fy + Sqrt(Fabs(d3))) * m_mul);
    }

private:
    void update_values(void)
    {
        // Calculate the invariant values. In case the focal center
        // lies exactly on the gradient circle the divisor degenerates
        // into zero. In this case we just move the focal center by
        // one subpixel unit possibly in the direction to the origin (0,0)
        // and calculate the values again.

        m_r2 = INT_TO_SCALAR(m_r) * INT_TO_SCALAR(m_r);
        m_fx2 = INT_TO_SCALAR(m_fx) * INT_TO_SCALAR(m_fx);
        m_fy2 = INT_TO_SCALAR(m_fy) * INT_TO_SCALAR(m_fy);
        scalar d = (m_r2 - (m_fx2 + m_fy2));
        if (d == INT_TO_SCALAR(0)) {
            if (m_fx) {
                if (m_fx < 0)
                    ++m_fx;
                else
                    --m_fx;
            }

            if (m_fy) {
                if (m_fy < 0)
                    ++m_fy;
                else
                    --m_fy;
            }

            m_fx2 = INT_TO_SCALAR(m_fx) * INT_TO_SCALAR(m_fx);
            m_fy2 = INT_TO_SCALAR(m_fy) * INT_TO_SCALAR(m_fy);
            d = (m_r2 - (m_fx2 + m_fy2));
        }
        m_mul = m_r / d;
    }

private:
    int m_r;
    int m_fx;
    int m_fy;
    scalar m_r2;
    scalar m_fx2;
    scalar m_fy2;
    scalar m_mul;
};

// gradient adaptors

// gradient once adaptor
template <typename GradientFunc>
class gradient_pad_adaptor
{
public:
    gradient_pad_adaptor(const GradientFunc& gradient)
        : m_gradient(&gradient)
    {
    }

    int calculate(int x, int y, int d) const
    {
        int ret = m_gradient->calculate(x, y, d);
        if (ret < 0) ret = 0;
        if (ret > d) ret = d;
        return ret;
    }

private:
    const GradientFunc* m_gradient;
};

// gradient repeat adaptor
template <typename GradientFunc>
class gradient_repeat_adaptor
{
public:
    gradient_repeat_adaptor(const GradientFunc& gradient)
        : m_gradient(&gradient)
    {
    }

    int calculate(int x, int y, int d) const
    {
        int ret = m_gradient->calculate(x, y, d) % d;
        if (ret < 0) ret += d;
        return ret;
    }

private:
    const GradientFunc* m_gradient;
};

// gradient reflect adaptor
template <typename GradientFunc>
class gradient_reflect_adaptor
{
public:
    gradient_reflect_adaptor(const GradientFunc& gradient)
        : m_gradient(&gradient)
    {
    }

    int calculate(int x, int y, int d) const
    {
        int d2 = d << 1;
        int ret = m_gradient->calculate(x, y, d) % d2;
        if (ret < 0) ret += d2;
        if (ret >= d) ret = d2 - ret;
        return ret;
    }

private:
    const GradientFunc* m_gradient;
};

// gradient wrapper implements
template <typename GradientFunc, typename Adaptor>
class gfx_gradient : public gfx_gradient_wrapper
{
public:
    gfx_gradient()
        : m_gradient()
        , m_adaptor(m_gradient)
    {
    }

    virtual void init(scalar r, scalar x, scalar y)
    {
        m_gradient.init(r, x, y);
    }

    virtual int calculate(int x, int y, int d) const
    {
        return m_adaptor.calculate(x, y, d);
    }

private:
    GradientFunc m_gradient;
    Adaptor m_adaptor;
};

// gfx gradient table

// rgba8 color interpolator
struct color_interpolator
{
public:
    typedef rgba8 color_type;

    color_interpolator(const color_type& c1, const color_type& c2, unsigned len)
        : r(c1.r, c2.r, len)
        , g(c1.g, c2.g, len)
        , b(c1.b, c2.b, len)
        , a(c1.a, c2.a, len)
    {
    }

    void operator ++ ()
    {
        ++r; ++g; ++b; ++a;
    }

    color_type color(void) const
    {
        return color_type(r.y(), g.y(), b.y(), a.y());
    }

private:
    gfx_dda_line_interpolator<14> r;
    gfx_dda_line_interpolator<14> g;
    gfx_dda_line_interpolator<14> b;
    gfx_dda_line_interpolator<14> a;
};

void gfx_gradient_table::build_table(void)
{
    quick_sort(m_color_profile, offset_less);
    m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal));

    if (m_color_profile.size() >= 2) {
        unsigned int i;
        unsigned int start = uround(m_color_profile[0].offset * color_table_size);
        unsigned int end = 0;
        color_type c = m_color_profile[0].color;

        for (i = 0; i < start; i++) {
            m_color_table[i] = c;
        }

        for (i = 1; i < m_color_profile.size(); i++) {
            end  = uround(m_color_profile[i].offset * color_table_size);
            color_interpolator ci(m_color_profile[i-1].color,
                                  m_color_profile[i].color, end - start + 1);
            while (start < end) {
                m_color_table[start] = ci.color();
                ++ci;
                ++start;
            }
        }

        c = m_color_profile.last().color;

        for (; end < m_color_table.size(); end++) {
            m_color_table[end] = c;
        }
    }
}

// gfx gradient adapter
void gfx_gradient_adapter::init_linear(int spread, scalar x1, scalar y1, scalar x2, scalar y2)
{
    if (!m_wrapper) {
        switch (spread) {
            case SPREAD_PAD:
                m_wrapper = new gfx_gradient<gradient_x, gradient_pad_adaptor<gradient_x> >;
                break;
            case SPREAD_REPEAT:
                m_wrapper = new gfx_gradient<gradient_x, gradient_repeat_adaptor<gradient_x> >;
                break;
            case SPREAD_REFLECT:
                m_wrapper = new gfx_gradient<gradient_x, gradient_reflect_adaptor<gradient_x> >;
                break;
        };

        if (!m_wrapper)
            return;

        scalar len = calc_distance(x1, y1, x2, y2);

        gfx_trans_affine mtx;
        if (len) {
            if (x2 < x1)
                mtx.rotate(PI - Asin((y2 - y1) / len));
            else
                mtx.rotate(Asin((y2 - y1) / len));
        } else
            len = FLT_TO_SCALAR(2.0f); // len can not be zero

        mtx.translate(x1, y1);

        m_start = FLT_TO_SCALAR(0.0f);
        m_length = len;
        m_matrix = mtx;
    }
}

void gfx_gradient_adapter::init_radial(int spread, scalar x1, scalar y1, scalar radius1,
                                           scalar x2, scalar y2, scalar radius2)
{
    if (!m_wrapper) {
        if ((x1 == x2) && (y1 == y2)) {
            switch (spread) {
                case SPREAD_PAD:
                    m_wrapper = new gfx_gradient<gradient_radial,
                                             gradient_pad_adaptor<gradient_radial> >;
                    break;
                case SPREAD_REPEAT:
                    m_wrapper = new gfx_gradient<gradient_radial,
                                             gradient_repeat_adaptor<gradient_radial> >;
                    break;
                case SPREAD_REFLECT:
                    m_wrapper = new gfx_gradient<gradient_radial,
                                             gradient_reflect_adaptor<gradient_radial> >;
                    break;
            }
        } else {
            switch (spread) {
                case SPREAD_PAD:
                    m_wrapper = new gfx_gradient<gradient_radial_focus,
                                             gradient_pad_adaptor<gradient_radial_focus> >;
                    break;
                case SPREAD_REPEAT:
                    m_wrapper = new gfx_gradient<gradient_radial_focus,
                                             gradient_repeat_adaptor<gradient_radial_focus> >;
                    break;
                case SPREAD_REFLECT:
                    m_wrapper = new gfx_gradient<gradient_radial_focus,
                                             gradient_reflect_adaptor<gradient_radial_focus> >;
                    break;
            }

        }

        if (!m_wrapper)
            return;

        scalar len = Fabs(radius2);
        scalar fx = x1 - x2;
        scalar fy = y1 - y2;

        m_wrapper->init(len, fx, fy);

        if (!len)
            len = FLT_TO_SCALAR(2.0f); // len can not be zero

        gfx_trans_affine mtx;
        mtx.translate(x1 - fx, y1 - fy);

        m_start = Fabs(radius1);
        m_length = len;
        m_matrix = mtx;
    }
}

void gfx_gradient_adapter::init_conic(int spread, scalar x, scalar y, scalar angle)
{
    if (!m_wrapper) {
        if (spread == SPREAD_REFLECT) {
            m_wrapper = new gfx_gradient<gradient_conic, gradient_reflect_adaptor<gradient_conic> >;
        } else {
            m_wrapper = new gfx_gradient<gradient_conic_vg, gradient_pad_adaptor<gradient_conic_vg> >;
        }

        if (!m_wrapper)
            return;

        gfx_trans_affine mtx;
        mtx.translate(x, y);
        mtx.translate(-x, -y);
        mtx.rotate(angle);
        mtx.translate(x, y);

        m_start = INT_TO_SCALAR(0);
        m_length = INT_TO_SCALAR(128);
        m_matrix = mtx;
    }
}

}
<|endoftext|>


<commit_before>#include "csv_exporter.h"

/*
 *
 * Class doc can be found in csv_exporter.h
 */
CSV_Exporter::CSV_Exporter()
{
    /* EMPTY - NO NEED */
}

/**
 * @brief   This method will generate the CSV file (Targeting google calendar import)
 *          it will create a full Semester calendar based on the users input (@param cal)
 *          and the @calSched wich holdes all the courses in "this" semester.
 * @param calSched  - Holdes all the Courses and there info
 * @param cal       - The Calendar dialog witch holdes the starting date and the eand date.
 * @return          - True if *all* went well, false if something on the way went wrong.
 */
bool CSV_Exporter::exportCalendar(calendarSchedule *calSched, CalendarDialog *cal, calendarExam *exams)
{
    if ((cal == NULL) || (calSched == NULL)) //pointers checking!
        return false;

    if (calSched->getCourses().isEmpty())
        return false;

    qDebug() << Q_FUNC_INFO << "Getting path for csv file from user...";

    QString filePath = getFileFath();
    if(filePath == NULL) //User canceled from the file explorer popup
    {
        qDebug() << Q_FUNC_INFO << "CSV : User pressed Cancel... returning false";
        return false;
    }
    qDebug() << Q_FUNC_INFO << "CSV : User Chose: " << filePath;
    qDebug() << Q_FUNC_INFO << "CSV : Atempting to export the Schedule...";

    QFile file(filePath);
    if(!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) //Incase unable to open the file (binary mode - \n will not be converted on "Windows")
    {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Critical);
        msgBox.setText(QObject::tr("Unable to open or create the file.\nExporting Failed"));
        msgBox.exec();
        qCritical() << Q_FUNC_INFO << "unable to open/create the file... maybe permissions error.";
        return false;
    }

    QTextStream out(&file); //The output streem.
    out.setCodec("UTF-8"); //Unicode 8

    out << CSV_CALENDAR_HEADER << "\n"; // macro in header file

    for (calendarCourse *coursePtr: (calSched->getCourses())) //main loop - running though all courses
    {
        // Getting course info - store in vars for easy access
        int day = coursePtr->getDay();
        int startH = coursePtr->getHourBegin();
        int startM = coursePtr->getMinutesBegin();
        int endH = coursePtr->getHourEnd();
        int endM = coursePtr->getMinutesEnd();
        QString lecturer = coursePtr->getLecturer();
        QString type = coursePtr->getType();
        QString name = coursePtr->getName();
        QString room = coursePtr->getRoom();

        QDate currentDate = cal->getStartDate(); // currentDate will iterate throuh the semester
        int firstDayOfSemester = currentDate.dayOfWeek(); //Returns the weekday (1 = Monday to 7 = Sunday) for this date.

        changeDayNumberFromQtToNormal(&firstDayOfSemester); //Get sync with our day numbers.

        /*
         * these 6 lines will get the right day for the starting poin in a
         * semester for eatch course.
         */
        if(day > firstDayOfSemester)
            currentDate = currentDate.addDays(day-firstDayOfSemester); //add the gap
        else if(day < firstDayOfSemester)
            currentDate = currentDate.addDays(6); //move a week nius one day
        else// ==
            currentDate = currentDate; //just for clearaty

        /*
         * secondary loop - We have course info and starting day.
         * evrey loop enterence we add the course and moving one week forward.
         */
        for(;currentDate <= cal->getEndDate(); currentDate = currentDate.addDays(7))
        {
            QString line = makeLine(name, &currentDate, startH, startM, endH, endM, lecturer, room, type);
            if(line != NULL)
                out << line << char(0x0A);
            else
                qWarning() << Q_FUNC_INFO << "CSV : Got A NULL in Line! in function: " << Q_FUNC_INFO;
        }
        out.flush();
    }

    if(cal->isExams()) //Export Exams as well
    {
        qDebug() << "Exporting Exams!";
        for(calendarExamCourse* exam:exams->getExams())
        {
            QTime startH = exam->getFirstHourbegin();
            QTime endH = startH.addSecs(60*60*3);//add 3 hours
            QString type = "מבחן א";
            QString name = exam->getName();
            QDate date = exam->getFirstDate();
            QString line = makeLine(name, &date, startH.hour(), startH.minute(), endH.hour(), endH.minute(), "", "", type);
            if(line != NULL)
                out << line << char(0x0A);
            else
                qWarning() << Q_FUNC_INFO << "CSV : Got A NULL in Line! in function: " << Q_FUNC_INFO;
            //===============
            // Second Date
            //===============
            startH = exam->getSecondHourbegin();
            endH = startH.addSecs(60*60*3);//add 3 hours
            date = exam->getSecondDate();
            type = "מבחן ב";
            line = makeLine(name, &date, startH.hour(), startH.minute(), endH.hour(), endH.minute(), "", "", type);
            if(line != NULL)
                out << line << char(0x0A);
            else
                qWarning() << Q_FUNC_INFO << "CSV : Got A NULL in Line! in function: " << Q_FUNC_INFO;
        }
        out.flush();
    }

    file.close();
    qDebug() << Q_FUNC_INFO << "CSV : Exported Successfully";
    return true;

}

/**
 * @brief Get the file path according to user via a file explorer dialog
 * @return - QString: the file path.
 */
QString CSV_Exporter::getFileFath()
{
    QString fileName = QFileDialog::getSaveFileName(NULL,
                                                    QObject::tr("JceManager Save Schedule Dialog"), "",
                                                    QObject::tr("CSV Files (*.csv);;All Files (*)"));
    if (fileName == "")
        return NULL;

    //IMPORTENT! ADD CSV EXTENTION
    if(!fileName.contains(".csv") && !fileName.contains(".CSV"))
        fileName.append(".csv");
    return fileName;
}

/**
 * @brief Returning a CSV formated ling in QString.
 * @param name
 * @param date
 * @param startH
 * @param startM - Not used at the moment.
 * @param endH
 * @param endM
 * @param lecturer
 * @param room
 * @param type
 * @return a CSV formated ling in QString.
 */
QString CSV_Exporter::makeLine(QString name, QDate *date, int startH, int startM, int endH, int endM, QString lecturer, QString room, QString type)
{
    //Creating a CSV text line for Google Calendar/iCal/Outlook

    QString CSV_line = "";
    QString subject = "\"";
    subject.append(name);
    subject.append(" - ");
    subject.append(type);
    subject.append("\"");

    QString dateStr = date->toString("MM/dd/yyyy");

    QString start;
    start.append(QString::number(startH));
    if(startM != 0)
    {
        start.append(":");
        start.append(QString::number(startM));
    }
    else
        start.append(":00");
    start.append(":00");

    QString end;
    end.append(QString::number(endH));
    if(endM != 0)
    {
        end.append(":");
        end.append(QString::number(endM));
    }
    else
        end.append(":00");
    end.append(":00");

    QString description = "\"מרצה ";

    if (lecturer == LECTURER_DEFAULT_STRING)
        description.append("טרם נקבע מרצה או מתרגל");
    else if(lecturer == "")
        description = "";
    else
        description.append(lecturer);

    description.append("\n");

    if (room == ROOM_DEFAULT_STRING)
        description.append("טרם נקבע מיקום");
    else
    {
        description.append(" ב");
        description.append(room);
    }

    if(room == "")
        description = "\"\Good Luck!\n";

    description.append("\n Created with JCE Manager.\"");

    //Create the Fucking Line
    //Header: Subject,Start Date,Start Time,End Date,End Time,Description,Location
    CSV_line.append(subject);
    CSV_line.append(",");

    CSV_line.append(dateStr);
    CSV_line.append(",");

    CSV_line.append(start);
    CSV_line.append(",");

    CSV_line.append(dateStr);
    CSV_line.append(",");

    CSV_line.append(end);
    CSV_line.append(",");

    CSV_line.append(description);
    CSV_line.append(",");

    CSV_line.append("\"JCE Jerusalem\"");

    return CSV_line;
}

/**
 * @brief The QDate.dayOfWeek() returns an integer as follows (Sunday = 7, monday = 1... Friday = 5)
 * This method will make that return integer more uderstandble and easy to use with the Calander classes of
 * JCE Manager. so Sunday = 1, Monday = 2 and so on...
 *
 * @param QtDay - A  Qt dayOfWeek integer pointer. it will cange his value.
 */
void CSV_Exporter::changeDayNumberFromQtToNormal(int *QtDay)
{
    switch(*QtDay){
    case 7:
        *QtDay = SUNDAY;
        break;
    case 1:
        *QtDay = MONDAY;
        break;
    case 2:
        *QtDay = TUESDAY;
        break;
    case 3:
        *QtDay = WENDSDAY;
        break;
    case 4:
        *QtDay = THURSDAY;
        break;
    case 5:
        *QtDay = FRIDAY;
        break;
    default:
        *QtDay = 7;
        break;
    }
    return; //Done.
}

<commit_msg>Changed the type of exams in exporter<commit_after>#include "csv_exporter.h"

/*
 *
 * Class doc can be found in csv_exporter.h
 */
CSV_Exporter::CSV_Exporter()
{
    /* EMPTY - NO NEED */
}

/**
 * @brief   This method will generate the CSV file (Targeting google calendar import)
 *          it will create a full Semester calendar based on the users input (@param cal)
 *          and the @calSched wich holdes all the courses in "this" semester.
 * @param calSched  - Holdes all the Courses and there info
 * @param cal       - The Calendar dialog witch holdes the starting date and the eand date.
 * @return          - True if *all* went well, false if something on the way went wrong.
 */
bool CSV_Exporter::exportCalendar(calendarSchedule *calSched, CalendarDialog *cal, calendarExam *exams)
{
    if ((cal == NULL) || (calSched == NULL)) //pointers checking!
        return false;

    if (calSched->getCourses().isEmpty())
        return false;

    qDebug() << Q_FUNC_INFO << "Getting path for csv file from user...";

    QString filePath = getFileFath();
    if(filePath == NULL) //User canceled from the file explorer popup
    {
        qDebug() << Q_FUNC_INFO << "CSV : User pressed Cancel... returning false";
        return false;
    }
    qDebug() << Q_FUNC_INFO << "CSV : User Chose: " << filePath;
    qDebug() << Q_FUNC_INFO << "CSV : Atempting to export the Schedule...";

    QFile file(filePath);
    if(!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) //Incase unable to open the file (binary mode - \n will not be converted on "Windows")
    {
        QMessageBox msgBox;
        msgBox.setIcon(QMessageBox::Critical);
        msgBox.setText(QObject::tr("Unable to open or create the file.\nExporting Failed"));
        msgBox.exec();
        qCritical() << Q_FUNC_INFO << "unable to open/create the file... maybe permissions error.";
        return false;
    }

    QTextStream out(&file); //The output streem.
    out.setCodec("UTF-8"); //Unicode 8

    out << CSV_CALENDAR_HEADER << "\n"; // macro in header file

    for (calendarCourse *coursePtr: (calSched->getCourses())) //main loop - running though all courses
    {
        // Getting course info - store in vars for easy access
        int day = coursePtr->getDay();
        int startH = coursePtr->getHourBegin();
        int startM = coursePtr->getMinutesBegin();
        int endH = coursePtr->getHourEnd();
        int endM = coursePtr->getMinutesEnd();
        QString lecturer = coursePtr->getLecturer();
        QString type = coursePtr->getType();
        QString name = coursePtr->getName();
        QString room = coursePtr->getRoom();

        QDate currentDate = cal->getStartDate(); // currentDate will iterate throuh the semester
        int firstDayOfSemester = currentDate.dayOfWeek(); //Returns the weekday (1 = Monday to 7 = Sunday) for this date.

        changeDayNumberFromQtToNormal(&firstDayOfSemester); //Get sync with our day numbers.

        /*
         * these 6 lines will get the right day for the starting poin in a
         * semester for eatch course.
         */
        if(day > firstDayOfSemester)
            currentDate = currentDate.addDays(day-firstDayOfSemester); //add the gap
        else if(day < firstDayOfSemester)
            currentDate = currentDate.addDays(6); //move a week nius one day
        else// ==
            currentDate = currentDate; //just for clearaty

        /*
         * secondary loop - We have course info and starting day.
         * evrey loop enterence we add the course and moving one week forward.
         */
        for(;currentDate <= cal->getEndDate(); currentDate = currentDate.addDays(7))
        {
            QString line = makeLine(name, &currentDate, startH, startM, endH, endM, lecturer, room, type);
            if(line != NULL)
                out << line << char(0x0A);
            else
                qWarning() << Q_FUNC_INFO << "CSV : Got A NULL in Line! in function: " << Q_FUNC_INFO;
        }
        out.flush();
    }

    if(cal->isExams()) //Export Exams as well
    {
        qDebug() << "Exporting Exams!";
        for(calendarExamCourse* exam:exams->getExams())
        {
            QTime startH = exam->getFirstHourbegin();
            QTime endH = startH.addSecs(60*60*3);//add 3 hours
            QString type = "מועד א";
            QString name = exam->getName();
            QDate date = exam->getFirstDate();
            QString line = makeLine(name, &date, startH.hour(), startH.minute(), endH.hour(), endH.minute(), "", "", type);
            if(line != NULL)
                out << line << char(0x0A);
            else
                qWarning() << Q_FUNC_INFO << "CSV : Got A NULL in Line! in function: " << Q_FUNC_INFO;
            //===============
            // Second Date
            //===============
            startH = exam->getSecondHourbegin();
            endH = startH.addSecs(60*60*3);//add 3 hours
            date = exam->getSecondDate();
            type = "מועד ב";
            line = makeLine(name, &date, startH.hour(), startH.minute(), endH.hour(), endH.minute(), "", "", type);
            if(line != NULL)
                out << line << char(0x0A);
            else
                qWarning() << Q_FUNC_INFO << "CSV : Got A NULL in Line! in function: " << Q_FUNC_INFO;
        }
        out.flush();
    }

    file.close();
    qDebug() << Q_FUNC_INFO << "CSV : Exported Successfully";
    return true;

}

/**
 * @brief Get the file path according to user via a file explorer dialog
 * @return - QString: the file path.
 */
QString CSV_Exporter::getFileFath()
{
    QString fileName = QFileDialog::getSaveFileName(NULL,
                                                    QObject::tr("JceManager Save Schedule Dialog"), "",
                                                    QObject::tr("CSV Files (*.csv);;All Files (*)"));
    if (fileName == "")
        return NULL;

    //IMPORTENT! ADD CSV EXTENTION
    if(!fileName.contains(".csv") && !fileName.contains(".CSV"))
        fileName.append(".csv");
    return fileName;
}

/**
 * @brief Returning a CSV formated ling in QString.
 * @param name
 * @param date
 * @param startH
 * @param startM
 * @param endH
 * @param endM
 * @param lecturer
 * @param room
 * @param type
 * @return a CSV formated ling in QString.
 */
QString CSV_Exporter::makeLine(QString name, QDate *date, int startH, int startM, int endH, int endM, QString lecturer, QString room, QString type)
{
    //Creating a CSV text line for Google Calendar/iCal/Outlook

    QString CSV_line = "";
    QString subject = "\"";
    subject.append(name);
    subject.append(" - ");
    subject.append(type);
    subject.append("\"");

    QString dateStr = date->toString("MM/dd/yyyy");

    QString start;
    start.append(QString::number(startH));
    if(startM != 0)
    {
        start.append(":");
        start.append(QString::number(startM));
    }
    else
        start.append(":00");
    start.append(":00");

    QString end;
    end.append(QString::number(endH));
    if(endM != 0)
    {
        end.append(":");
        end.append(QString::number(endM));
    }
    else
        end.append(":00");
    end.append(":00");

    QString description = "\"מרצה ";

    if (lecturer == LECTURER_DEFAULT_STRING)
        description.append("טרם נקבע מרצה או מתרגל");
    else if(lecturer == "")
        description = "";
    else
        description.append(lecturer);

    description.append("\n");

    if (room == ROOM_DEFAULT_STRING)
        description.append("טרם נקבע מיקום");
    else
    {
        description.append(" ב");
        description.append(room);
    }

    if(room == "")
        description = "\"\Good Luck!\n";

    description.append("\n Created with JCE Manager.\"");

    //Create the Fucking Line
    //Header: Subject,Start Date,Start Time,End Date,End Time,Description,Location
    CSV_line.append(subject);
    CSV_line.append(",");

    CSV_line.append(dateStr);
    CSV_line.append(",");

    CSV_line.append(start);
    CSV_line.append(",");

    CSV_line.append(dateStr);
    CSV_line.append(",");

    CSV_line.append(end);
    CSV_line.append(",");

    CSV_line.append(description);
    CSV_line.append(",");

    CSV_line.append("\"JCE Jerusalem\"");

    return CSV_line;
}

/**
 * @brief The QDate.dayOfWeek() returns an integer as follows (Sunday = 7, monday = 1... Friday = 5)
 * This method will make that return integer more uderstandble and easy to use with the Calander classes of
 * JCE Manager. so Sunday = 1, Monday = 2 and so on...
 *
 * @param QtDay - A  Qt dayOfWeek integer pointer. it will cange his value.
 */
void CSV_Exporter::changeDayNumberFromQtToNormal(int *QtDay)
{
    switch(*QtDay){
    case 7:
        *QtDay = SUNDAY;
        break;
    case 1:
        *QtDay = MONDAY;
        break;
    case 2:
        *QtDay = TUESDAY;
        break;
    case 3:
        *QtDay = WENDSDAY;
        break;
    case 4:
        *QtDay = THURSDAY;
        break;
    case 5:
        *QtDay = FRIDAY;
        break;
    default:
        *QtDay = 7;
        break;
    }
    return; //Done.
}

<|endoftext|>


<commit_before>#include "joedb/Readonly_Journal.h"
#include "joedb/Generic_File.h"
#include "joedb/Exception.h"

#include <vector>
#include <sstream>

const uint32_t joedb::Readonly_Journal::version_number = 0x00000004;
const uint32_t joedb::Readonly_Journal::compatible_version = 0x00000004;
const int64_t joedb::Readonly_Journal::header_size = 41;

#define FORMAT_EXCEPTION(x)\
 do {if (!ignore_errors) throw Exception(x);} while(false)

/////////////////////////////////////////////////////////////////////////////
joedb::Readonly_Journal::Readonly_Journal
/////////////////////////////////////////////////////////////////////////////
(
 Generic_File &file,
 bool ignore_errors
):
 file(file),
 checkpoint_index(0),
 checkpoint_position(0),
 table_of_last_operation(0),
 record_of_last_operation(0),
 field_of_last_update(0)
{
 //
 // Check the format of an existing joedb file
 //
 if (file.get_mode() != Open_Mode::create_new)
 {
  //
  // First, check for initial "joedb"
  //
  if (file.read<uint8_t>() != 'j' ||
      file.read<uint8_t>() != 'o' ||
      file.read<uint8_t>() != 'e' ||
      file.read<uint8_t>() != 'd' ||
      file.read<uint8_t>() != 'b')
  {
   FORMAT_EXCEPTION("File does not start by 'joedb'");
  }
  else
  {
   //
   // Check version number
   //
   const uint32_t version = file.read<uint32_t>();
   if (version < compatible_version || version > version_number)
    FORMAT_EXCEPTION("Unsupported format version");

   //
   // Find the most recent checkpoint
   //
   int64_t pos[4];
   for (int i = 0; i < 4; i++)
    pos[i] = file.read<int64_t>();

   if (pos[0] != pos[1] || pos[2] != pos[3])
    FORMAT_EXCEPTION("Checkpoint mismatch");

   checkpoint_position = 0;

   for (unsigned i = 0; i < 2; i++)
    if (pos[2 * i] == pos[2 * i + 1] && pos[2 * i] > checkpoint_position)
    {
     if (int64_t(size_t(pos[2 * i])) != pos[2 * i])
      throw Exception("size_t is too small for this file");
     checkpoint_position = pos[2 * i];
     checkpoint_index = i;
    }

   if (checkpoint_position < header_size)
    FORMAT_EXCEPTION("Checkpoint too small");

   //
   // Compare to file size (if available)
   //
   int64_t file_size = file.get_size();

   if (file_size > 0 && file_size != checkpoint_position)
    FORMAT_EXCEPTION("Checkpoint different from file size");

   if (ignore_errors)
    checkpoint_position = file_size;
  }
 }
}

#undef FORMAT_EXCEPTION

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::replay_log(Writable &writable)
/////////////////////////////////////////////////////////////////////////////
{
 rewind();
 play_until_checkpoint(writable);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::rewind()
/////////////////////////////////////////////////////////////////////////////
{
 file.set_position(header_size);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::seek(int64_t position)
/////////////////////////////////////////////////////////////////////////////
{
 file.set_position(position);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::play_until(Writable &writable, int64_t end)
/////////////////////////////////////////////////////////////////////////////
{
 while(file.get_position() < end)
  one_step(writable);
 file.set_position(file.get_position()); // get ready for writing
}

/////////////////////////////////////////////////////////////////////////////
bool joedb::Readonly_Journal::at_end_of_file() const
/////////////////////////////////////////////////////////////////////////////
{
 return file.get_position() >= checkpoint_position;
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::one_step(Writable &writable)
/////////////////////////////////////////////////////////////////////////////
{
 switch(file.read<operation_t>())
 {
  case operation_t::end_of_file:
   if (file.get_position() != checkpoint_position)
    throw Exception("Unexpected end of file");
  break;

  case operation_t::create_table:
  {
   std::string name = safe_read_string();
   writable.create_table(name);
  }
  break;

  case operation_t::drop_table:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   writable.drop_table(table_id);
  }
  break;

  case operation_t::rename_table:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   std::string name = safe_read_string();
   writable.rename_table(table_id, name);
  }
  break;

  case operation_t::add_field:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   std::string name = safe_read_string();
   Type type = read_type();
   writable.add_field(table_id, name, type);
  }
  break;

  case operation_t::drop_field:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Field_Id field_id = file.compact_read<Field_Id>();
   writable.drop_field(table_id, field_id);
  }
  break;

  case operation_t::rename_field:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Field_Id field_id = file.compact_read<Field_Id>();
   std::string name = safe_read_string();
   writable.rename_field(table_id, field_id, name);
  }
  break;

  case operation_t::insert_into:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Record_Id record_id = file.compact_read<Record_Id>();
   writable.insert_into(table_id, record_id);
   table_of_last_operation = table_id;
   record_of_last_operation = record_id;
  }
  break;

  case operation_t::insert_vector:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Record_Id record_id = file.compact_read<Record_Id>();
   Record_Id size = file.compact_read<Record_Id>();
   writable.insert_vector(table_id, record_id, size);
   table_of_last_operation = table_id;
   record_of_last_operation = record_id;
  }
  break;

  case operation_t::append:
   writable.insert_into(table_of_last_operation,
                         ++record_of_last_operation);
  break;

  case operation_t::delete_from:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Record_Id record_id = file.compact_read<Record_Id>();
   writable.delete_from(table_id, record_id);
  }
  break;

  #define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
  case operation_t::update_##type_id:\
   table_of_last_operation = file.compact_read<Table_Id>();\
   record_of_last_operation = file.compact_read<Record_Id>();\
   field_of_last_update = file.compact_read<Field_Id>();\
  goto lbl_perform_update_##type_id;\
\
  case operation_t::update_last_##type_id:\
   field_of_last_update = file.compact_read<Field_Id>();\
  goto lbl_perform_update_##type_id;\
\
  case operation_t::update_next_##type_id:\
   record_of_last_operation++;\
  goto lbl_perform_update_##type_id;\
\
  lbl_perform_update_##type_id:\
  {\
   cpp_type value = read_method();\
   writable.update_##type_id\
   (\
    table_of_last_operation,\
    record_of_last_operation,\
    field_of_last_update,\
    value\
   );\
  }\
  break;\
\
  case operation_t::update_vector_##type_id:\
  {\
   table_of_last_operation = file.compact_read<Table_Id>();\
   record_of_last_operation = file.compact_read<Record_Id>();\
   field_of_last_update = file.compact_read<Field_Id>();\
   Record_Id size = file.compact_read<Record_Id>();\
   if (int64_t(size) > checkpoint_position || size < 0)\
    throw Exception("update_vector too big");\
   std::vector<cpp_type> buffer(size);\
   for (size_t i = 0; i < size; i++)\
    buffer[i] = read_method();\
   writable.update_vector_##type_id\
   (\
    table_of_last_operation,\
    record_of_last_operation,\
    field_of_last_update,\
    size,\
    &buffer[0]\
   );\
  }\
  break;
  #include "joedb/TYPE_MACRO.h"
  #undef TYPE_MACRO

  case operation_t::custom:
  {
   std::string name = safe_read_string();
   writable.custom(name);
  }
  break;

  case operation_t::comment:
  {
   std::string comment = safe_read_string();
   writable.comment(comment);
  }
  break;

  case operation_t::timestamp:
  {
   int64_t timestamp = file.read<int64_t>();
   writable.timestamp(timestamp);
  }
  break;

  case operation_t::valid_data:
   writable.valid_data();
  break;

  default:
  {
   std::ostringstream error;
   error << "Unexpected operation: file.get_position() = ";
   error << file.get_position();
   throw Exception(error.str());
  }
 }
}

/////////////////////////////////////////////////////////////////////////////
joedb::Type joedb::Readonly_Journal::read_type()
/////////////////////////////////////////////////////////////////////////////
{
 Type::Type_Id type_id = Type::Type_Id(file.read<Type_Id_Storage>());
 if (type_id == Type::Type_Id::reference)
  return Type::reference(file.compact_read<Table_Id>());
 else
  return Type(type_id);
}

/////////////////////////////////////////////////////////////////////////////
std::string joedb::Readonly_Journal::safe_read_string()
/////////////////////////////////////////////////////////////////////////////
{
 return file.safe_read_string(size_t(checkpoint_position));
}
<commit_msg>replace ugly macro by lambda<commit_after>#include "joedb/Readonly_Journal.h"
#include "joedb/Generic_File.h"
#include "joedb/Exception.h"

#include <vector>
#include <sstream>

const uint32_t joedb::Readonly_Journal::version_number = 0x00000004;
const uint32_t joedb::Readonly_Journal::compatible_version = 0x00000004;
const int64_t joedb::Readonly_Journal::header_size = 41;

/////////////////////////////////////////////////////////////////////////////
joedb::Readonly_Journal::Readonly_Journal
/////////////////////////////////////////////////////////////////////////////
(
 Generic_File &file,
 bool ignore_errors
):
 file(file),
 checkpoint_index(0),
 checkpoint_position(0),
 table_of_last_operation(0),
 record_of_last_operation(0),
 field_of_last_update(0)
{
 auto format_exception = [ignore_errors](const char *message)
 {
  if (!ignore_errors)
   throw Exception(message);
 };

 //
 // Check the format of an existing joedb file
 //
 if (file.get_mode() != Open_Mode::create_new)
 {
  //
  // First, check for initial "joedb"
  //
  if (file.read<uint8_t>() != 'j' ||
      file.read<uint8_t>() != 'o' ||
      file.read<uint8_t>() != 'e' ||
      file.read<uint8_t>() != 'd' ||
      file.read<uint8_t>() != 'b')
  {
   format_exception("File does not start by 'joedb'");
  }
  else
  {
   //
   // Check version number
   //
   const uint32_t version = file.read<uint32_t>();
   if (version < compatible_version || version > version_number)
    format_exception("Unsupported format version");

   //
   // Find the most recent checkpoint
   //
   int64_t pos[4];
   for (int i = 0; i < 4; i++)
    pos[i] = file.read<int64_t>();

   if (pos[0] != pos[1] || pos[2] != pos[3])
    format_exception("Checkpoint mismatch");

   checkpoint_position = 0;

   for (unsigned i = 0; i < 2; i++)
    if (pos[2 * i] == pos[2 * i + 1] && pos[2 * i] > checkpoint_position)
    {
     if (int64_t(size_t(pos[2 * i])) != pos[2 * i])
      throw Exception("size_t is too small for this file");
     checkpoint_position = pos[2 * i];
     checkpoint_index = i;
    }

   if (checkpoint_position < header_size)
    format_exception("Checkpoint too small");

   //
   // Compare to file size (if available)
   //
   int64_t file_size = file.get_size();

   if (file_size > 0 && file_size != checkpoint_position)
    format_exception("Checkpoint different from file size");

   if (ignore_errors)
    checkpoint_position = file_size;
  }
 }
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::replay_log(Writable &writable)
/////////////////////////////////////////////////////////////////////////////
{
 rewind();
 play_until_checkpoint(writable);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::rewind()
/////////////////////////////////////////////////////////////////////////////
{
 file.set_position(header_size);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::seek(int64_t position)
/////////////////////////////////////////////////////////////////////////////
{
 file.set_position(position);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::play_until(Writable &writable, int64_t end)
/////////////////////////////////////////////////////////////////////////////
{
 while(file.get_position() < end)
  one_step(writable);
 file.set_position(file.get_position()); // get ready for writing
}

/////////////////////////////////////////////////////////////////////////////
bool joedb::Readonly_Journal::at_end_of_file() const
/////////////////////////////////////////////////////////////////////////////
{
 return file.get_position() >= checkpoint_position;
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::one_step(Writable &writable)
/////////////////////////////////////////////////////////////////////////////
{
 switch(file.read<operation_t>())
 {
  case operation_t::end_of_file:
   if (file.get_position() != checkpoint_position)
    throw Exception("Unexpected end of file");
  break;

  case operation_t::create_table:
  {
   std::string name = safe_read_string();
   writable.create_table(name);
  }
  break;

  case operation_t::drop_table:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   writable.drop_table(table_id);
  }
  break;

  case operation_t::rename_table:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   std::string name = safe_read_string();
   writable.rename_table(table_id, name);
  }
  break;

  case operation_t::add_field:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   std::string name = safe_read_string();
   Type type = read_type();
   writable.add_field(table_id, name, type);
  }
  break;

  case operation_t::drop_field:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Field_Id field_id = file.compact_read<Field_Id>();
   writable.drop_field(table_id, field_id);
  }
  break;

  case operation_t::rename_field:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Field_Id field_id = file.compact_read<Field_Id>();
   std::string name = safe_read_string();
   writable.rename_field(table_id, field_id, name);
  }
  break;

  case operation_t::insert_into:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Record_Id record_id = file.compact_read<Record_Id>();
   writable.insert_into(table_id, record_id);
   table_of_last_operation = table_id;
   record_of_last_operation = record_id;
  }
  break;

  case operation_t::insert_vector:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Record_Id record_id = file.compact_read<Record_Id>();
   Record_Id size = file.compact_read<Record_Id>();
   writable.insert_vector(table_id, record_id, size);
   table_of_last_operation = table_id;
   record_of_last_operation = record_id;
  }
  break;

  case operation_t::append:
   writable.insert_into(table_of_last_operation,
                         ++record_of_last_operation);
  break;

  case operation_t::delete_from:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Record_Id record_id = file.compact_read<Record_Id>();
   writable.delete_from(table_id, record_id);
  }
  break;

  #define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
  case operation_t::update_##type_id:\
   table_of_last_operation = file.compact_read<Table_Id>();\
   record_of_last_operation = file.compact_read<Record_Id>();\
   field_of_last_update = file.compact_read<Field_Id>();\
  goto lbl_perform_update_##type_id;\
\
  case operation_t::update_last_##type_id:\
   field_of_last_update = file.compact_read<Field_Id>();\
  goto lbl_perform_update_##type_id;\
\
  case operation_t::update_next_##type_id:\
   record_of_last_operation++;\
  goto lbl_perform_update_##type_id;\
\
  lbl_perform_update_##type_id:\
  {\
   cpp_type value = read_method();\
   writable.update_##type_id\
   (\
    table_of_last_operation,\
    record_of_last_operation,\
    field_of_last_update,\
    value\
   );\
  }\
  break;\
\
  case operation_t::update_vector_##type_id:\
  {\
   table_of_last_operation = file.compact_read<Table_Id>();\
   record_of_last_operation = file.compact_read<Record_Id>();\
   field_of_last_update = file.compact_read<Field_Id>();\
   Record_Id size = file.compact_read<Record_Id>();\
   if (int64_t(size) > checkpoint_position || size < 0)\
    throw Exception("update_vector too big");\
   std::vector<cpp_type> buffer(size);\
   for (size_t i = 0; i < size; i++)\
    buffer[i] = read_method();\
   writable.update_vector_##type_id\
   (\
    table_of_last_operation,\
    record_of_last_operation,\
    field_of_last_update,\
    size,\
    &buffer[0]\
   );\
  }\
  break;
  #include "joedb/TYPE_MACRO.h"
  #undef TYPE_MACRO

  case operation_t::custom:
  {
   std::string name = safe_read_string();
   writable.custom(name);
  }
  break;

  case operation_t::comment:
  {
   std::string comment = safe_read_string();
   writable.comment(comment);
  }
  break;

  case operation_t::timestamp:
  {
   int64_t timestamp = file.read<int64_t>();
   writable.timestamp(timestamp);
  }
  break;

  case operation_t::valid_data:
   writable.valid_data();
  break;

  default:
  {
   std::ostringstream error;
   error << "Unexpected operation: file.get_position() = ";
   error << file.get_position();
   throw Exception(error.str());
  }
 }
}

/////////////////////////////////////////////////////////////////////////////
joedb::Type joedb::Readonly_Journal::read_type()
/////////////////////////////////////////////////////////////////////////////
{
 Type::Type_Id type_id = Type::Type_Id(file.read<Type_Id_Storage>());
 if (type_id == Type::Type_Id::reference)
  return Type::reference(file.compact_read<Table_Id>());
 else
  return Type(type_id);
}

/////////////////////////////////////////////////////////////////////////////
std::string joedb::Readonly_Journal::safe_read_string()
/////////////////////////////////////////////////////////////////////////////
{
 return file.safe_read_string(size_t(checkpoint_position));
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "kudu/master/master_runner.h"

#include <iostream>
#include <string>

#include <gflags/gflags.h>
#include <glog/logging.h>

#include "kudu/gutil/strings/substitute.h"
#include "kudu/master/master.h"
#include "kudu/util/flags.h"
#include "kudu/util/monotime.h"
#include "kudu/util/version_info.h"

using kudu::master::Master;
using std::string;

DECLARE_bool(evict_failed_followers);

namespace kudu {
namespace master {

void SetMasterFlagDefaults() {
  // Reset some default values before parsing gflags.
  CHECK_NE("", google::SetCommandLineOptionWithMode("rpc_bind_addresses",
                                                    strings::Substitute(
                                                        "0.0.0.0:$0",
                                                        Master::kDefaultPort).c_str(),
                                                    google::FlagSettingMode::SET_FLAGS_DEFAULT));
  CHECK_NE("", google::SetCommandLineOptionWithMode("webserver_port",
                                                    std::to_string(
                                                        Master::kDefaultWebPort).c_str(),
                                                    google::FlagSettingMode::SET_FLAGS_DEFAULT));

  // Setting the default value of the 'force_block_cache_capacity' flag to
  // 'false' makes the corresponding group validator enforce proper settings
  // for the memory limit and the cfile cache capacity.
  CHECK_NE("", SetCommandLineOptionWithMode("force_block_cache_capacity",
                                            "false",
                                            gflags::SET_FLAGS_DEFAULT));

  // A multi-node Master leader should not evict failed Master followers
  // because there is no-one to assign replacement servers in order to maintain
  // the desired replication factor. (It's not turtles all the way down!)
  CHECK_NE("", SetCommandLineOptionWithMode("evict_failed_followers",
                                            "false",
                                            gflags::SET_FLAGS_DEFAULT));
  // SET_FLAGS_DEFAULT won't reset the flag value if it has previously been
  // set, instead it will only change the default. Because we want to ensure
  // evict_failed_followers is always false, we explicitly set the flag.
  FLAGS_evict_failed_followers = false;
}

Status RunMasterServer() {
  string nondefault_flags = GetNonDefaultFlags();
  LOG(INFO) << "Master server non-default flags:\n"
            << nondefault_flags << '\n'
            << "Master server version:\n"
            << VersionInfo::GetAllVersionInfo();

  Master server({});
  RETURN_NOT_OK(server.Init());
  RETURN_NOT_OK(server.Start());

  while (true) {
    SleepFor(MonoDelta::FromSeconds(60));
  }
}

} // namespace master
} // namespace kudu
<commit_msg>[master] Replace hive_metastore_sasl_enabled validator<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "kudu/master/master_runner.h"

#include <iostream>
#include <string>

#include <gflags/gflags.h>
#include <glog/logging.h>

#include "kudu/gutil/strings/substitute.h"
#include "kudu/master/master.h"
#include "kudu/util/flags.h"
#include "kudu/util/monotime.h"
#include "kudu/util/version_info.h"

using kudu::master::Master;
using std::string;

DECLARE_bool(evict_failed_followers);

DECLARE_bool(hive_metastore_sasl_enabled);
DECLARE_string(keytab_file);

namespace kudu {
namespace master {

// Validates that if the HMS is configured with SASL enabled, the server has a
// keytab available. This doesn't use a GROUP_FLAG_VALIDATOR because this check
// only needs to be run on a server. E.g. tools that run with the HMS don't need
// to pass in a keytab.
static Status ValidateHiveMetastoreSaslEnabled() {
    if (FLAGS_hive_metastore_sasl_enabled &&
        FLAGS_keytab_file.empty()) {
        return Status::ConfigurationError("When the Hive Metastore has SASL enabled "
                                          "(--hive_metastore_sasl_enabled), Kudu must be "
                                          "configured with a keytab (--keytab_file).");
    }
    return Status::OK();
}

void SetMasterFlagDefaults() {
  // Reset some default values before parsing gflags.
  CHECK_NE("", google::SetCommandLineOptionWithMode("rpc_bind_addresses",
                                                    strings::Substitute(
                                                        "0.0.0.0:$0",
                                                        Master::kDefaultPort).c_str(),
                                                    google::FlagSettingMode::SET_FLAGS_DEFAULT));
  CHECK_NE("", google::SetCommandLineOptionWithMode("webserver_port",
                                                    std::to_string(
                                                        Master::kDefaultWebPort).c_str(),
                                                    google::FlagSettingMode::SET_FLAGS_DEFAULT));

  // Setting the default value of the 'force_block_cache_capacity' flag to
  // 'false' makes the corresponding group validator enforce proper settings
  // for the memory limit and the cfile cache capacity.
  CHECK_NE("", SetCommandLineOptionWithMode("force_block_cache_capacity",
                                            "false",
                                            gflags::SET_FLAGS_DEFAULT));

  // A multi-node Master leader should not evict failed Master followers
  // because there is no-one to assign replacement servers in order to maintain
  // the desired replication factor. (It's not turtles all the way down!)
  CHECK_NE("", SetCommandLineOptionWithMode("evict_failed_followers",
                                            "false",
                                            gflags::SET_FLAGS_DEFAULT));
  // SET_FLAGS_DEFAULT won't reset the flag value if it has previously been
  // set, instead it will only change the default. Because we want to ensure
  // evict_failed_followers is always false, we explicitly set the flag.
  FLAGS_evict_failed_followers = false;
}

Status RunMasterServer() {
  string nondefault_flags = GetNonDefaultFlags();
  LOG(INFO) << "Master server non-default flags:\n"
            << nondefault_flags << '\n'
            << "Master server version:\n"
            << VersionInfo::GetAllVersionInfo();

  RETURN_NOT_OK(ValidateHiveMetastoreSaslEnabled());

  Master server({});
  RETURN_NOT_OK(server.Init());
  RETURN_NOT_OK(server.Start());

  while (true) {
    SleepFor(MonoDelta::FromSeconds(60));
  }
}

} // namespace master
} // namespace kudu
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of the Qt Build Suite
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file.
** Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**************************************************************************/

#include "oldsourceproject.h"

#include <buildgraph/buildgraph.h>
#include <buildgraph/executor.h>
#include <language/loader.h>
#include <tools/runenvironment.h>
#include <tools/fileinfo.h>
#include <tools/persistence.h>
#include <tools/logger.h>
#include <tools/scannerpluginmanager.h>
#include <tools/scripttools.h>
#include <tools/platform.h>

#include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QtCore/QSettings>
#include <QtCore/QScopedPointer>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QElapsedTimer>

namespace qbs {

SourceProject::SourceProject(qbs::Settings::Ptr settings)
    : m_settings(settings)
{
}

void SourceProject::setSearchPaths(const QStringList &searchPaths)
{
    m_searchPaths = searchPaths;
}

void SourceProject::loadPlugins(const QStringList &pluginPaths)
{
    static bool alreadyCalled = false;
    if (alreadyCalled) {
        qbsWarning("qbs::SourceProject::loadPlugins was called more than once.");
    }

    alreadyCalled = true;

    foreach (const QString &pluginPath, pluginPaths)
        QCoreApplication::addLibraryPath(pluginPath);

    qbs::ScannerPluginManager::instance()->loadPlugins(pluginPaths);
}

void SourceProject::loadProject(QFutureInterface<bool> &futureInterface, QString projectFileName, QList<QVariantMap> buildConfigs)
{
    QHash<QString, qbs::Platform::Ptr > platforms = Platform::platforms();
    if (platforms.isEmpty()) {
        qbsFatal("no platforms configured. maybe you want to run 'qbs platforms probe' first.");
        futureInterface.reportResult(false);
        return;
    }
    if (buildConfigs.isEmpty()) {
        qbsFatal("SourceProject::loadProject: no build configuration given.");
        futureInterface.reportResult(false);
        return;
    }
    QList<qbs::Configuration::Ptr> configurations;
    foreach (QVariantMap buildCfg, buildConfigs) {
        if (!buildCfg.value("platform").isValid()) {
            if (!m_settings->value("defaults/platform").isValid()) {
                qbsFatal("SourceProject::loadProject: no platform given and no default set.");
                continue;
            }
            buildCfg.insert("platform", m_settings->value("defaults/platform").toString());
        }
        Platform::Ptr platform = platforms.value(buildCfg.value("platform").toString());
        if (platform.isNull()) {
            qbsFatal("SourceProject::loadProject: unknown platform: %s", qPrintable(buildCfg.value("platform").toString()));
            continue;
        }
        foreach (const QString &key, platform->settings.allKeys()) {
            buildCfg.insert(QString(key).replace('/','.'),
                    platform->settings.value(key));
        }

        if (!buildCfg.value("buildVariant").isValid()) {
            qbsFatal("SourceProject::loadProject: property 'buildVariant' missing in build configuration.");
            continue;
        }
        qbs::Configuration::Ptr configure(new qbs::Configuration);
        configurations.append(configure);

        foreach (const QString &property, buildCfg.keys()) {
            QStringList nameElements = property.split('.');
            if (nameElements.count() == 1)
                nameElements.prepend("qbs");
            QVariantMap configValue = configure->value();
            qbs::setConfigProperty(configValue, nameElements, buildCfg.value(property));
            configure->setValue(configValue);
        }
    }

    qbs::Loader loader;
    loader.setSearchPaths(m_searchPaths);
    m_buildGraph = QSharedPointer<qbs::BuildGraph>(new qbs::BuildGraph);
    m_buildGraph->setOutputDirectoryRoot(QDir::currentPath());
    const QString buildDirectoryRoot = m_buildGraph->buildDirectoryRoot();

    try {
        foreach (const qbs::Configuration::Ptr &configure, configurations) {
            qbs::BuildProject::Ptr bProject;
            const qbs::FileTime projectFileTimeStamp = qbs::FileInfo(projectFileName).lastModified();
            bProject = qbs::BuildProject::load(m_buildGraph.data(), projectFileTimeStamp, configure, m_searchPaths);
            if (!bProject) {
                QElapsedTimer timer;
                timer.start();
                if (!loader.hasLoaded())
                    loader.loadProject(projectFileName);
                qbs::ResolvedProject::Ptr rProject = loader.resolveProject(buildDirectoryRoot, configure, futureInterface);
                if (rProject->products.isEmpty())
                    throw qbs::Error(QString("'%1' does not contain products.").arg(projectFileName));
                qDebug() << "loading project took: " << timer.elapsed() << "ms";
                timer.start();
                bProject = m_buildGraph->resolveProject(rProject, futureInterface);
                qDebug() << "build graph took: " << timer.elapsed() << "ms";
            }

            m_buildProjects.append(bProject);

            printf("for %s:\n", qPrintable(bProject->resolvedProject()->id));
            foreach (qbs::ResolvedProduct::Ptr p, bProject->resolvedProject()->products) {
                printf("  - [%s] %s as %s\n"
                        ,qPrintable(p->fileTags.join(", "))
                        ,qPrintable(p->name)
                        ,qPrintable(p->project->id)
                      );
            }
            printf("\n");
        }

    } catch (qbs::Error &e) {
        m_errors.append(e);
        futureInterface.reportResult(false);
        return;
    }

    futureInterface.reportResult(true);
}

QList<BuildProject::Ptr> SourceProject::buildProjects() const
{
    return m_buildProjects;
}

QList<Error> SourceProject::errors() const
{
    return m_errors;
}

} // namespace qbs

<commit_msg>support submodule syntax in platform config files<commit_after>/**************************************************************************
**
** This file is part of the Qt Build Suite
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file.
** Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**************************************************************************/

#include "oldsourceproject.h"

#include <buildgraph/buildgraph.h>
#include <buildgraph/executor.h>
#include <language/loader.h>
#include <tools/runenvironment.h>
#include <tools/fileinfo.h>
#include <tools/persistence.h>
#include <tools/logger.h>
#include <tools/scannerpluginmanager.h>
#include <tools/scripttools.h>
#include <tools/platform.h>

#include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QtCore/QSettings>
#include <QtCore/QScopedPointer>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QElapsedTimer>

namespace qbs {

SourceProject::SourceProject(qbs::Settings::Ptr settings)
    : m_settings(settings)
{
}

void SourceProject::setSearchPaths(const QStringList &searchPaths)
{
    m_searchPaths = searchPaths;
}

void SourceProject::loadPlugins(const QStringList &pluginPaths)
{
    static bool alreadyCalled = false;
    if (alreadyCalled) {
        qbsWarning("qbs::SourceProject::loadPlugins was called more than once.");
    }

    alreadyCalled = true;

    foreach (const QString &pluginPath, pluginPaths)
        QCoreApplication::addLibraryPath(pluginPath);

    qbs::ScannerPluginManager::instance()->loadPlugins(pluginPaths);
}

void SourceProject::loadProject(QFutureInterface<bool> &futureInterface, QString projectFileName, QList<QVariantMap> buildConfigs)
{
    QHash<QString, qbs::Platform::Ptr > platforms = Platform::platforms();
    if (platforms.isEmpty()) {
        qbsFatal("no platforms configured. maybe you want to run 'qbs platforms probe' first.");
        futureInterface.reportResult(false);
        return;
    }
    if (buildConfigs.isEmpty()) {
        qbsFatal("SourceProject::loadProject: no build configuration given.");
        futureInterface.reportResult(false);
        return;
    }
    QList<qbs::Configuration::Ptr> configurations;
    foreach (QVariantMap buildCfg, buildConfigs) {
        if (!buildCfg.value("platform").isValid()) {
            if (!m_settings->value("defaults/platform").isValid()) {
                qbsFatal("SourceProject::loadProject: no platform given and no default set.");
                continue;
            }
            buildCfg.insert("platform", m_settings->value("defaults/platform").toString());
        }
        Platform::Ptr platform = platforms.value(buildCfg.value("platform").toString());
        if (platform.isNull()) {
            qbsFatal("SourceProject::loadProject: unknown platform: %s", qPrintable(buildCfg.value("platform").toString()));
            continue;
        }
        foreach (const QString &key, platform->settings.allKeys()) {
            QString fixedKey = key;
            int idx = fixedKey.lastIndexOf(QChar('/'));
            if (idx > 0)
                fixedKey[idx] = QChar('.');
            buildCfg.insert(fixedKey, platform->settings.value(key));
        }

        if (!buildCfg.value("buildVariant").isValid()) {
            qbsFatal("SourceProject::loadProject: property 'buildVariant' missing in build configuration.");
            continue;
        }
        qbs::Configuration::Ptr configure(new qbs::Configuration);
        configurations.append(configure);

        foreach (const QString &property, buildCfg.keys()) {
            QStringList nameElements = property.split('.');
            if (nameElements.count() == 1)
                nameElements.prepend("qbs");
            QVariantMap configValue = configure->value();
            qbs::setConfigProperty(configValue, nameElements, buildCfg.value(property));
            configure->setValue(configValue);
        }
    }

    qbs::Loader loader;
    loader.setSearchPaths(m_searchPaths);
    m_buildGraph = QSharedPointer<qbs::BuildGraph>(new qbs::BuildGraph);
    m_buildGraph->setOutputDirectoryRoot(QDir::currentPath());
    const QString buildDirectoryRoot = m_buildGraph->buildDirectoryRoot();

    try {
        foreach (const qbs::Configuration::Ptr &configure, configurations) {
            qbs::BuildProject::Ptr bProject;
            const qbs::FileTime projectFileTimeStamp = qbs::FileInfo(projectFileName).lastModified();
            bProject = qbs::BuildProject::load(m_buildGraph.data(), projectFileTimeStamp, configure, m_searchPaths);
            if (!bProject) {
                QElapsedTimer timer;
                timer.start();
                if (!loader.hasLoaded())
                    loader.loadProject(projectFileName);
                qbs::ResolvedProject::Ptr rProject = loader.resolveProject(buildDirectoryRoot, configure, futureInterface);
                if (rProject->products.isEmpty())
                    throw qbs::Error(QString("'%1' does not contain products.").arg(projectFileName));
                qDebug() << "loading project took: " << timer.elapsed() << "ms";
                timer.start();
                bProject = m_buildGraph->resolveProject(rProject, futureInterface);
                qDebug() << "build graph took: " << timer.elapsed() << "ms";
            }

            m_buildProjects.append(bProject);

            printf("for %s:\n", qPrintable(bProject->resolvedProject()->id));
            foreach (qbs::ResolvedProduct::Ptr p, bProject->resolvedProject()->products) {
                printf("  - [%s] %s as %s\n"
                        ,qPrintable(p->fileTags.join(", "))
                        ,qPrintable(p->name)
                        ,qPrintable(p->project->id)
                      );
            }
            printf("\n");
        }

    } catch (qbs::Error &e) {
        m_errors.append(e);
        futureInterface.reportResult(false);
        return;
    }

    futureInterface.reportResult(true);
}

QList<BuildProject::Ptr> SourceProject::buildProjects() const
{
    return m_buildProjects;
}

QList<Error> SourceProject::errors() const
{
    return m_errors;
}

} // namespace qbs

<|endoftext|>


<commit_before>/*
* BigInt Encoding/Decoding
* (C) 1999-2010,2012 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/bigint.h>
#include <botan/divide.h>
#include <botan/charset.h>
#include <botan/hex.h>

namespace Botan {

std::string BigInt::to_dec_string() const
   {
   BigInt copy = *this;
   copy.set_sign(Positive);

   BigInt remainder;
   std::vector<uint8_t> digits;

   while(copy > 0)
      {
      divide(copy, 10, copy, remainder);
      digits.push_back(static_cast<uint8_t>(remainder.word_at(0)));
      }

   std::string s;

   for(auto i = digits.rbegin(); i != digits.rend(); ++i)
      {
      s.push_back(Charset::digit2char(*i));
      }

   return s;
   }

std::string BigInt::to_hex_string() const
   {
   return hex_encode(BigInt::encode(*this));
   }

/*
* Encode a BigInt
*/
void BigInt::encode(uint8_t output[], const BigInt& n, Base base)
   {
   if(base == Binary)
      {
      n.binary_encode(output);
      }
   else if(base == Hexadecimal)
      {
      secure_vector<uint8_t> binary(n.encoded_size(Binary));
      n.binary_encode(binary.data());

      hex_encode(cast_uint8_ptr_to_char(output),
                 binary.data(), binary.size());
      }
   else if(base == Decimal)
      {
      BigInt copy = n;
      BigInt remainder;
      copy.set_sign(Positive);
      const size_t output_size = n.encoded_size(Decimal);
      for(size_t j = 0; j != output_size; ++j)
         {
         divide(copy, 10, copy, remainder);
         output[output_size - 1 - j] =
            Charset::digit2char(static_cast<uint8_t>(remainder.word_at(0)));
         if(copy.is_zero())
            break;
         }
      }
   else
      throw Invalid_Argument("Unknown BigInt encoding method");
   }

/*
* Encode a BigInt
*/
std::vector<uint8_t> BigInt::encode(const BigInt& n, Base base)
   {
   if(base == Binary)
      return BigInt::encode(n);

   std::vector<uint8_t> output(n.encoded_size(base));
   encode(output.data(), n, base);
   for(size_t j = 0; j != output.size(); ++j)
      if(output[j] == 0)
         output[j] = '0';

   return output;
   }

/*
* Encode a BigInt
*/
secure_vector<uint8_t> BigInt::encode_locked(const BigInt& n, Base base)
   {
   if(base == Binary)
      return BigInt::encode_locked(n);

   secure_vector<uint8_t> output(n.encoded_size(base));
   encode(output.data(), n, base);
   for(size_t j = 0; j != output.size(); ++j)
      if(output[j] == 0)
         output[j] = '0';

   return output;
   }

/*
* Encode a BigInt, with leading 0s if needed
*/
secure_vector<uint8_t> BigInt::encode_1363(const BigInt& n, size_t bytes)
   {
   secure_vector<uint8_t> output(bytes);
   BigInt::encode_1363(output.data(), output.size(), n);
   return output;
   }

//static
void BigInt::encode_1363(uint8_t output[], size_t bytes, const BigInt& n)
   {
   const size_t n_bytes = n.bytes();
   if(n_bytes > bytes)
      throw Encoding_Error("encode_1363: n is too large to encode properly");

   const size_t leading_0s = bytes - n_bytes;
   encode(&output[leading_0s], n, Binary);
   }

/*
* Encode two BigInt, with leading 0s if needed, and concatenate
*/
secure_vector<uint8_t> BigInt::encode_fixed_length_int_pair(const BigInt& n1, const BigInt& n2, size_t bytes)
   {
   secure_vector<uint8_t> output(2 * bytes);
   BigInt::encode_1363(output.data(), bytes, n1);
   BigInt::encode_1363(output.data() + bytes, bytes, n2);
   return output;
   }

/*
* Decode a BigInt
*/
BigInt BigInt::decode(const uint8_t buf[], size_t length, Base base)
   {
   BigInt r;
   if(base == Binary)
      r.binary_decode(buf, length);
   else if(base == Hexadecimal)
      {
      secure_vector<uint8_t> binary;

      if(length % 2)
         {
         // Handle lack of leading 0
         const char buf0_with_leading_0[2] =
            { '0', static_cast<char>(buf[0]) };

         binary = hex_decode_locked(buf0_with_leading_0, 2);

         binary += hex_decode_locked(cast_uint8_ptr_to_char(&buf[1]),
                                     length - 1,
                                     false);
         }
      else
         binary = hex_decode_locked(cast_uint8_ptr_to_char(buf),
                                    length, false);

      r.binary_decode(binary.data(), binary.size());
      }
   else if(base == Decimal)
      {
      for(size_t i = 0; i != length; ++i)
         {
         if(Charset::is_space(buf[i]))
            continue;

         if(!Charset::is_digit(buf[i]))
            throw Invalid_Argument("BigInt::decode: "
                                   "Invalid character in decimal input");

         const uint8_t x = Charset::char2digit(buf[i]);

         if(x >= 10)
            throw Invalid_Argument("BigInt: Invalid decimal string");

         r *= 10;
         r += x;
         }
      }
   else
      throw Invalid_Argument("Unknown BigInt decoding method");
   return r;
   }

}
<commit_msg>Fix BigInt::to_{dec,hex}_string for zero<commit_after>/*
* BigInt Encoding/Decoding
* (C) 1999-2010,2012 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/bigint.h>
#include <botan/divide.h>
#include <botan/charset.h>
#include <botan/hex.h>

namespace Botan {

std::string BigInt::to_dec_string() const
   {
   BigInt copy = *this;
   copy.set_sign(Positive);

   BigInt remainder;
   std::vector<uint8_t> digits;

   while(copy > 0)
      {
      divide(copy, 10, copy, remainder);
      digits.push_back(static_cast<uint8_t>(remainder.word_at(0)));
      }

   std::string s;

   for(auto i = digits.rbegin(); i != digits.rend(); ++i)
      {
      s.push_back(Charset::digit2char(*i));
      }

   if(s.empty())
      s += "0";

   return s;
   }

std::string BigInt::to_hex_string() const
   {
   const std::vector<uint8_t> bits = BigInt::encode(*this);
   if(bits.empty())
      return "00";
   else
      return hex_encode(bits);
   }

/*
* Encode a BigInt
*/
void BigInt::encode(uint8_t output[], const BigInt& n, Base base)
   {
   if(base == Binary)
      {
      n.binary_encode(output);
      }
   else if(base == Hexadecimal)
      {
      secure_vector<uint8_t> binary(n.encoded_size(Binary));
      n.binary_encode(binary.data());

      hex_encode(cast_uint8_ptr_to_char(output),
                 binary.data(), binary.size());
      }
   else if(base == Decimal)
      {
      BigInt copy = n;
      BigInt remainder;
      copy.set_sign(Positive);
      const size_t output_size = n.encoded_size(Decimal);
      for(size_t j = 0; j != output_size; ++j)
         {
         divide(copy, 10, copy, remainder);
         output[output_size - 1 - j] =
            Charset::digit2char(static_cast<uint8_t>(remainder.word_at(0)));
         if(copy.is_zero())
            break;
         }
      }
   else
      throw Invalid_Argument("Unknown BigInt encoding method");
   }

/*
* Encode a BigInt
*/
std::vector<uint8_t> BigInt::encode(const BigInt& n, Base base)
   {
   if(base == Binary)
      return BigInt::encode(n);

   std::vector<uint8_t> output(n.encoded_size(base));
   encode(output.data(), n, base);
   for(size_t j = 0; j != output.size(); ++j)
      if(output[j] == 0)
         output[j] = '0';

   return output;
   }

/*
* Encode a BigInt
*/
secure_vector<uint8_t> BigInt::encode_locked(const BigInt& n, Base base)
   {
   if(base == Binary)
      return BigInt::encode_locked(n);

   secure_vector<uint8_t> output(n.encoded_size(base));
   encode(output.data(), n, base);
   for(size_t j = 0; j != output.size(); ++j)
      if(output[j] == 0)
         output[j] = '0';

   return output;
   }

/*
* Encode a BigInt, with leading 0s if needed
*/
secure_vector<uint8_t> BigInt::encode_1363(const BigInt& n, size_t bytes)
   {
   secure_vector<uint8_t> output(bytes);
   BigInt::encode_1363(output.data(), output.size(), n);
   return output;
   }

//static
void BigInt::encode_1363(uint8_t output[], size_t bytes, const BigInt& n)
   {
   const size_t n_bytes = n.bytes();
   if(n_bytes > bytes)
      throw Encoding_Error("encode_1363: n is too large to encode properly");

   const size_t leading_0s = bytes - n_bytes;
   encode(&output[leading_0s], n, Binary);
   }

/*
* Encode two BigInt, with leading 0s if needed, and concatenate
*/
secure_vector<uint8_t> BigInt::encode_fixed_length_int_pair(const BigInt& n1, const BigInt& n2, size_t bytes)
   {
   secure_vector<uint8_t> output(2 * bytes);
   BigInt::encode_1363(output.data(), bytes, n1);
   BigInt::encode_1363(output.data() + bytes, bytes, n2);
   return output;
   }

/*
* Decode a BigInt
*/
BigInt BigInt::decode(const uint8_t buf[], size_t length, Base base)
   {
   BigInt r;
   if(base == Binary)
      r.binary_decode(buf, length);
   else if(base == Hexadecimal)
      {
      secure_vector<uint8_t> binary;

      if(length % 2)
         {
         // Handle lack of leading 0
         const char buf0_with_leading_0[2] =
            { '0', static_cast<char>(buf[0]) };

         binary = hex_decode_locked(buf0_with_leading_0, 2);

         binary += hex_decode_locked(cast_uint8_ptr_to_char(&buf[1]),
                                     length - 1,
                                     false);
         }
      else
         binary = hex_decode_locked(cast_uint8_ptr_to_char(buf),
                                    length, false);

      r.binary_decode(binary.data(), binary.size());
      }
   else if(base == Decimal)
      {
      for(size_t i = 0; i != length; ++i)
         {
         if(Charset::is_space(buf[i]))
            continue;

         if(!Charset::is_digit(buf[i]))
            throw Invalid_Argument("BigInt::decode: "
                                   "Invalid character in decimal input");

         const uint8_t x = Charset::char2digit(buf[i]);

         if(x >= 10)
            throw Invalid_Argument("BigInt: Invalid decimal string");

         r *= 10;
         r += x;
         }
      }
   else
      throw Invalid_Argument("Unknown BigInt decoding method");
   return r;
   }

}
<|endoftext|>