<commit_before>/*
 * Copyright 2008 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkMathPriv.h"
#include "SkPointPriv.h"

#if 0
void SkIPoint::rotateCW(SkIPoint* dst) const {
    SkASSERT(dst);

    // use a tmp in case this == dst
    int32_t tmp = fX;
    dst->fX = -fY;
    dst->fY = tmp;
}

void SkIPoint::rotateCCW(SkIPoint* dst) const {
    SkASSERT(dst);

    // use a tmp in case this == dst
    int32_t tmp = fX;
    dst->fX = fY;
    dst->fY = -tmp;
}
#endif

///////////////////////////////////////////////////////////////////////////////

void SkPoint::scale(SkScalar scale, SkPoint* dst) const {
    SkASSERT(dst);
    dst->set(fX * scale, fY * scale);
}

bool SkPoint::normalize() {
    return this->setLength(fX, fY, SK_Scalar1);
}

bool SkPoint::setNormalize(SkScalar x, SkScalar y) {
    return this->setLength(x, y, SK_Scalar1);
}

bool SkPoint::setLength(SkScalar length) {
    return this->setLength(fX, fY, length);
}

// Returns the square of the Euclidian distance to (dx,dy).
static inline float getLengthSquared(float dx, float dy) {
    return dx * dx + dy * dy;
}

// Calculates the square of the Euclidian distance to (dx,dy) and stores it in
// *lengthSquared.  Returns true if the distance is judged to be "nearly zero".
//
// This logic is encapsulated in a helper method to make it explicit that we
// always perform this check in the same manner, to avoid inconsistencies
// (see http://code.google.com/p/skia/issues/detail?id=560 ).
static inline bool is_length_nearly_zero(float dx, float dy,
                                         float *lengthSquared) {
    *lengthSquared = getLengthSquared(dx, dy);
    return *lengthSquared <= (SK_ScalarNearlyZero * SK_ScalarNearlyZero);
}

/*
 *  We have to worry about 2 tricky conditions:
 *  1. underflow of mag2 (compared against nearlyzero^2)
 *  2. overflow of mag2 (compared w/ isfinite)
 *
 *  If we underflow, we return false. If we overflow, we compute again using
 *  doubles, which is much slower (3x in a desktop test) but will not overflow.
 */
template <bool use_rsqrt> bool set_point_length(SkPoint* pt, float x, float y, float length,
                                                float* orig_length = nullptr) {
    SkASSERT(!use_rsqrt || (orig_length == nullptr));

    float mag = 0;
    float mag2;
    if (is_length_nearly_zero(x, y, &mag2)) {
        pt->set(0, 0);
        return false;
    }

    if (sk_float_isfinite(mag2)) {
        float scale;
        if (use_rsqrt) {
            scale = length * sk_float_rsqrt(mag2);
        } else {
            mag = sk_float_sqrt(mag2);
            scale = length / mag;
        }
        x *= scale;
        y *= scale;
    } else {
        // our mag2 step overflowed to infinity, so use doubles instead.
        // much slower, but needed when x or y are very large, other wise we
        // divide by inf. and return (0,0) vector.
        double xx = x;
        double yy = y;
        double dmag = sqrt(xx * xx + yy * yy);
        double dscale = length / dmag;
        x *= dscale;
        y *= dscale;
        // check if we're not finite, or we're zero-length
        if (!sk_float_isfinite(x) || !sk_float_isfinite(y) || (x == 0 && y == 0)) {
            pt->set(0, 0);
            return false;
        }
        if (orig_length) {
            mag = sk_double_to_float(dmag);
        }
    }
    pt->set(x, y);
    if (orig_length) {
        *orig_length = mag;
    }
    return true;
}

SkScalar SkPoint::Normalize(SkPoint* pt) {
    float mag;
    if (set_point_length<false>(pt, pt->fX, pt->fY, 1.0f, &mag)) {
        return mag;
    }
    return 0;
}

SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
    float mag2 = dx * dx + dy * dy;
    if (SkScalarIsFinite(mag2)) {
        return sk_float_sqrt(mag2);
    } else {
        double xx = dx;
        double yy = dy;
        return sk_double_to_float(sqrt(xx * xx + yy * yy));
    }
}

bool SkPoint::setLength(float x, float y, float length) {
    return set_point_length<false>(this, x, y, length);
}

bool SkPointPriv::SetLengthFast(SkPoint* pt, float length) {
    return set_point_length<true>(pt, pt->fX, pt->fY, length);
}

///////////////////////////////////////////////////////////////////////////////

SkScalar SkPointPriv::DistanceToLineBetweenSqd(const SkPoint& pt, const SkPoint& a,
                                               const SkPoint& b,
                                               Side* side) {

    SkVector u = b - a;
    SkVector v = pt - a;

    SkScalar uLengthSqd = LengthSqd(u);
    // Degenerate line, return distancesqd to point A
    if (uLengthSqd < SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
        return LengthSqd(v);
    }
    SkScalar det = u.cross(v);
    if (side) {
        SkASSERT(-1 == kLeft_Side &&
                  0 == kOn_Side &&
                  1 == kRight_Side);
        *side = (Side) SkScalarSignAsInt(det);
    }
    SkScalar temp = det / uLengthSqd;
    temp *= det;
    return temp;
}

SkScalar SkPointPriv::DistanceToLineSegmentBetweenSqd(const SkPoint& pt, const SkPoint& a,
                                                      const SkPoint& b) {
    // See comments to distanceToLineBetweenSqd. If the projection of c onto
    // u is between a and b then this returns the same result as that
    // function. Otherwise, it returns the distance to the closer of a and
    // b. Let the projection of v onto u be v'.  There are three cases:
    //    1. v' points opposite to u. c is not between a and b and is closer
    //       to a than b.
    //    2. v' points along u and has magnitude less than y. c is between
    //       a and b and the distance to the segment is the same as distance
    //       to the line ab.
    //    3. v' points along u and has greater magnitude than u. c is not
    //       not between a and b and is closer to b than a.
    // v' = (u dot v) * u / |u|. So if (u dot v)/|u| is less than zero we're
    // in case 1. If (u dot v)/|u| is > |u| we are in case 3. Otherwise
    // we're in case 2. We actually compare (u dot v) to 0 and |u|^2 to
    // avoid a sqrt to compute |u|.

    SkVector u = b - a;
    SkVector v = pt - a;

    SkScalar uLengthSqd = LengthSqd(u);
    SkScalar uDotV = SkPoint::DotProduct(u, v);

    // closest point is point A or segment is degenerate so use point A
    if (uDotV <= 0 || uLengthSqd < SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
        return LengthSqd(v);
    // closest point is point B
    } else if (uDotV > uLengthSqd) {
        return DistanceToSqd(b, pt);
    // closest point is inside segment
    } else {
        SkScalar det = u.cross(v);
        SkScalar temp = det / uLengthSqd;
        temp *= det;
        return temp;
    }
}
<commit_msg>Make line distance more robust<commit_after>/*
 * Copyright 2008 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkMathPriv.h"
#include "SkPointPriv.h"

#if 0
void SkIPoint::rotateCW(SkIPoint* dst) const {
    SkASSERT(dst);

    // use a tmp in case this == dst
    int32_t tmp = fX;
    dst->fX = -fY;
    dst->fY = tmp;
}

void SkIPoint::rotateCCW(SkIPoint* dst) const {
    SkASSERT(dst);

    // use a tmp in case this == dst
    int32_t tmp = fX;
    dst->fX = fY;
    dst->fY = -tmp;
}
#endif

///////////////////////////////////////////////////////////////////////////////

void SkPoint::scale(SkScalar scale, SkPoint* dst) const {
    SkASSERT(dst);
    dst->set(fX * scale, fY * scale);
}

bool SkPoint::normalize() {
    return this->setLength(fX, fY, SK_Scalar1);
}

bool SkPoint::setNormalize(SkScalar x, SkScalar y) {
    return this->setLength(x, y, SK_Scalar1);
}

bool SkPoint::setLength(SkScalar length) {
    return this->setLength(fX, fY, length);
}

// Returns the square of the Euclidian distance to (dx,dy).
static inline float getLengthSquared(float dx, float dy) {
    return dx * dx + dy * dy;
}

// Calculates the square of the Euclidian distance to (dx,dy) and stores it in
// *lengthSquared.  Returns true if the distance is judged to be "nearly zero".
//
// This logic is encapsulated in a helper method to make it explicit that we
// always perform this check in the same manner, to avoid inconsistencies
// (see http://code.google.com/p/skia/issues/detail?id=560 ).
static inline bool is_length_nearly_zero(float dx, float dy,
                                         float *lengthSquared) {
    *lengthSquared = getLengthSquared(dx, dy);
    return *lengthSquared <= (SK_ScalarNearlyZero * SK_ScalarNearlyZero);
}

/*
 *  We have to worry about 2 tricky conditions:
 *  1. underflow of mag2 (compared against nearlyzero^2)
 *  2. overflow of mag2 (compared w/ isfinite)
 *
 *  If we underflow, we return false. If we overflow, we compute again using
 *  doubles, which is much slower (3x in a desktop test) but will not overflow.
 */
template <bool use_rsqrt> bool set_point_length(SkPoint* pt, float x, float y, float length,
                                                float* orig_length = nullptr) {
    SkASSERT(!use_rsqrt || (orig_length == nullptr));

    float mag = 0;
    float mag2;
    if (is_length_nearly_zero(x, y, &mag2)) {
        pt->set(0, 0);
        return false;
    }

    if (sk_float_isfinite(mag2)) {
        float scale;
        if (use_rsqrt) {
            scale = length * sk_float_rsqrt(mag2);
        } else {
            mag = sk_float_sqrt(mag2);
            scale = length / mag;
        }
        x *= scale;
        y *= scale;
    } else {
        // our mag2 step overflowed to infinity, so use doubles instead.
        // much slower, but needed when x or y are very large, other wise we
        // divide by inf. and return (0,0) vector.
        double xx = x;
        double yy = y;
        double dmag = sqrt(xx * xx + yy * yy);
        double dscale = length / dmag;
        x *= dscale;
        y *= dscale;
        // check if we're not finite, or we're zero-length
        if (!sk_float_isfinite(x) || !sk_float_isfinite(y) || (x == 0 && y == 0)) {
            pt->set(0, 0);
            return false;
        }
        if (orig_length) {
            mag = sk_double_to_float(dmag);
        }
    }
    pt->set(x, y);
    if (orig_length) {
        *orig_length = mag;
    }
    return true;
}

SkScalar SkPoint::Normalize(SkPoint* pt) {
    float mag;
    if (set_point_length<false>(pt, pt->fX, pt->fY, 1.0f, &mag)) {
        return mag;
    }
    return 0;
}

SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
    float mag2 = dx * dx + dy * dy;
    if (SkScalarIsFinite(mag2)) {
        return sk_float_sqrt(mag2);
    } else {
        double xx = dx;
        double yy = dy;
        return sk_double_to_float(sqrt(xx * xx + yy * yy));
    }
}

bool SkPoint::setLength(float x, float y, float length) {
    return set_point_length<false>(this, x, y, length);
}

bool SkPointPriv::SetLengthFast(SkPoint* pt, float length) {
    return set_point_length<true>(pt, pt->fX, pt->fY, length);
}

///////////////////////////////////////////////////////////////////////////////

SkScalar SkPointPriv::DistanceToLineBetweenSqd(const SkPoint& pt, const SkPoint& a,
                                               const SkPoint& b,
                                               Side* side) {

    SkVector u = b - a;
    SkVector v = pt - a;

    SkScalar uLengthSqd = LengthSqd(u);
    SkScalar det = u.cross(v);
    if (side) {
        SkASSERT(-1 == kLeft_Side &&
                  0 == kOn_Side &&
                  1 == kRight_Side);
        *side = (Side) SkScalarSignAsInt(det);
    }
    SkScalar temp = sk_ieee_float_divide(det, uLengthSqd);
    temp *= det;
    // It's possible we have a degenerate line vector, or we're so far away it looks degenerate
    // In this case, return squared distance to point A.
    if (!SkScalarIsFinite(temp)) {
        return LengthSqd(v);
    }
    return temp;
}

SkScalar SkPointPriv::DistanceToLineSegmentBetweenSqd(const SkPoint& pt, const SkPoint& a,
                                                      const SkPoint& b) {
    // See comments to distanceToLineBetweenSqd. If the projection of c onto
    // u is between a and b then this returns the same result as that
    // function. Otherwise, it returns the distance to the closer of a and
    // b. Let the projection of v onto u be v'.  There are three cases:
    //    1. v' points opposite to u. c is not between a and b and is closer
    //       to a than b.
    //    2. v' points along u and has magnitude less than y. c is between
    //       a and b and the distance to the segment is the same as distance
    //       to the line ab.
    //    3. v' points along u and has greater magnitude than u. c is not
    //       not between a and b and is closer to b than a.
    // v' = (u dot v) * u / |u|. So if (u dot v)/|u| is less than zero we're
    // in case 1. If (u dot v)/|u| is > |u| we are in case 3. Otherwise
    // we're in case 2. We actually compare (u dot v) to 0 and |u|^2 to
    // avoid a sqrt to compute |u|.

    SkVector u = b - a;
    SkVector v = pt - a;

    SkScalar uLengthSqd = LengthSqd(u);
    SkScalar uDotV = SkPoint::DotProduct(u, v);

    // closest point is point A
    if (uDotV <= 0) {
        return LengthSqd(v);
    // closest point is point B
    } else if (uDotV > uLengthSqd) {
        return DistanceToSqd(b, pt);
    // closest point is inside segment
    } else {
        SkScalar det = u.cross(v);
        SkScalar temp = sk_ieee_float_divide(det, uLengthSqd);
        temp *= det;
        // It's possible we have a degenerate segment, or we're so far away it looks degenerate
        // In this case, return squared distance to point A.
        if (!SkScalarIsFinite(temp)) {
            return LengthSqd(v);
        }
        return temp;
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkRRect.h"

///////////////////////////////////////////////////////////////////////////////

void SkRRect::setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
    if (rect.isEmpty()) {
        this->setEmpty();
        return;
    }

    if (xRad <= 0 || yRad <= 0) {
        // all corners are square in this case
        this->setRect(rect);
        return;
    }

    if (rect.width() < xRad+xRad || rect.height() < yRad+yRad) {
        SkScalar scale = SkMinScalar(SkScalarDiv(rect.width(), xRad + xRad),
                                     SkScalarDiv(rect.height(), yRad + yRad));
        SkASSERT(scale < SK_Scalar1);
        xRad = SkScalarMul(xRad, scale);
        yRad = SkScalarMul(yRad, scale);
    }

    fRect = rect;
    for (int i = 0; i < 4; ++i) {
        fRadii[i].set(xRad, yRad);
    }
    fType = kSimple_Type;
    if (xRad >= SkScalarHalf(fRect.width()) && yRad >= SkScalarHalf(fRect.height())) {
        fType = kOval_Type;
        // TODO: try asserting they are already W/2 & H/2 already
        xRad = SkScalarHalf(fRect.width());
        yRad = SkScalarHalf(fRect.height());
    }

    SkDEBUGCODE(this->validate();)
}

void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) {
    if (rect.isEmpty()) {
        this->setEmpty();
        return;
    }

    fRect = rect;
    memcpy(fRadii, radii, sizeof(fRadii));

    bool allCornersSquare = true;

    // Clamp negative radii to zero
    for (int i = 0; i < 4; ++i) {
        if (fRadii[i].fX <= 0 || fRadii[i].fY <= 0) {
            // In this case we are being a little fast & loose. Since one of
            // the radii is 0 the corner is square. However, the other radii
            // could still be non-zero and play in the global scale factor
            // computation.
            fRadii[i].fX = 0;
            fRadii[i].fY = 0;
        } else {
            allCornersSquare = false;
        }
    }

    if (allCornersSquare) {
        this->setRect(rect);
        return;
    }

    // Proportionally scale down all radii to fit. Find the minimum ratio
    // of a side and the radii on that side (for all four sides) and use
    // that to scale down _all_ the radii. This algorithm is from the
    // W3 spec (http://www.w3.org/TR/css3-background/) section 5.5 - Overlapping
    // Curves:
    // "Let f = min(Li/Si), where i is one of { top, right, bottom, left },
    //   Si is the sum of the two corresponding radii of the corners on side i,
    //   and Ltop = Lbottom = the width of the box,
    //   and Lleft = Lright = the height of the box.
    // If f < 1, then all corner radii are reduced by multiplying them by f."
    SkScalar scale = SK_Scalar1;

    if (fRadii[0].fX + fRadii[1].fX > rect.width()) {
        scale = SkMinScalar(scale,
                            SkScalarDiv(rect.width(), fRadii[0].fX + fRadii[1].fX));
    }
    if (fRadii[1].fY + fRadii[2].fY > rect.height()) {
        scale = SkMinScalar(scale,
                            SkScalarDiv(rect.height(), fRadii[1].fY + fRadii[2].fY));
    }
    if (fRadii[2].fX + fRadii[3].fX > rect.width()) {
        scale = SkMinScalar(scale,
                            SkScalarDiv(rect.width(), fRadii[2].fX + fRadii[3].fX));
    }
    if (fRadii[3].fY + fRadii[0].fY > rect.height()) {
        scale = SkMinScalar(scale,
                            SkScalarDiv(rect.height(), fRadii[3].fY + fRadii[0].fY));
    }

    if (scale < SK_Scalar1) {
        for (int i = 0; i < 4; ++i) {
            fRadii[i].fX = SkScalarMul(fRadii[i].fX, scale);
            fRadii[i].fY = SkScalarMul(fRadii[i].fY, scale);
        }
    }

    // At this point we're either oval, simple, or complex (not empty or rect)
    // but we lazily resolve the type to avoid the work if the information
    // isn't required.
    fType = (SkRRect::Type) kUnknown_Type;

    SkDEBUGCODE(this->validate();)
}

bool SkRRect::contains(SkScalar x, SkScalar y) const {
    SkDEBUGCODE(this->validate();)

    if (kEmpty_Type == this->type()) {
        return false;
    }

    if (!fRect.contains(x, y)) {
        return false;
    }

    if (kRect_Type == this->type()) {
        // the 'fRect' test above was sufficient
        return true;
    }

    // We know the point is inside the RR's bounds. The only way it can
    // be out is if it outside one of the corners
    SkPoint canonicalPt; // (x,y) translated to one of the quadrants
    int index;

    if (kOval_Type == this->type()) {
        canonicalPt.set(x - fRect.centerX(), y - fRect.centerY());
        index = kUpperLeft_Corner;  // any corner will do in this case
    } else {
        if (x < fRect.fLeft + fRadii[kUpperLeft_Corner].fX &&
            y < fRect.fTop + fRadii[kUpperLeft_Corner].fY) {
            // UL corner
            index = kUpperLeft_Corner;
            canonicalPt.set(x - (fRect.fLeft + fRadii[kUpperLeft_Corner].fX),
                            y - (fRect.fTop + fRadii[kUpperLeft_Corner].fY));
            SkASSERT(canonicalPt.fX < 0 && canonicalPt.fY < 0);
        } else if (x < fRect.fLeft + fRadii[kLowerLeft_Corner].fX &&
                   y > fRect.fBottom - fRadii[kLowerLeft_Corner].fY) {
            // LL corner
            index = kLowerLeft_Corner;
            canonicalPt.set(x - (fRect.fLeft + fRadii[kLowerLeft_Corner].fX),
                            y - (fRect.fBottom - fRadii[kLowerLeft_Corner].fY));
            SkASSERT(canonicalPt.fX < 0 && canonicalPt.fY > 0);
        } else if (x > fRect.fRight - fRadii[kUpperRight_Corner].fX &&
                   y < fRect.fTop + fRadii[kUpperRight_Corner].fY) {
            // UR corner
            index = kUpperRight_Corner;
            canonicalPt.set(x - (fRect.fRight - fRadii[kUpperRight_Corner].fX),
                            y - (fRect.fTop + fRadii[kUpperRight_Corner].fY));
            SkASSERT(canonicalPt.fX > 0 && canonicalPt.fY < 0);
        } else if (x > fRect.fRight - fRadii[kLowerRight_Corner].fX &&
                   y > fRect.fBottom - fRadii[kLowerRight_Corner].fY) {
            // LR corner
            index = kLowerRight_Corner;
            canonicalPt.set(x - (fRect.fRight - fRadii[kLowerRight_Corner].fX),
                            y - (fRect.fBottom - fRadii[kLowerRight_Corner].fY));
            SkASSERT(canonicalPt.fX > 0 && canonicalPt.fY > 0);
        } else {
            // not in any of the corners
            return true;
        }
    }

    // A point is in an ellipse (in standard position) if:
    //      x^2     y^2
    //     ----- + ----- <= 1
    //      a^2     b^2
    SkScalar dist =  SkScalarDiv(SkScalarSquare(canonicalPt.fX), SkScalarSquare(fRadii[index].fX)) +
                     SkScalarDiv(SkScalarSquare(canonicalPt.fY), SkScalarSquare(fRadii[index].fY));
    return dist <= SK_Scalar1;
}

// There is a simplified version of this method in setRectXY
void SkRRect::computeType() const {
    SkDEBUGCODE(this->validate();)

    if (fRect.isEmpty()) {
        fType = kEmpty_Type;
        return;
    }

    bool allRadiiEqual = true; // are all x radii equal and all y radii?
    bool allCornersSquare = 0 == fRadii[0].fX || 0 == fRadii[0].fY;

    for (int i = 1; i < 4; ++i) {
        if (0 != fRadii[i].fX && 0 != fRadii[i].fY) {
            // if either radius is zero the corner is square so both have to
            // be non-zero to have a rounded corner
            allCornersSquare = false;
        }
        if (fRadii[i].fX != fRadii[i-1].fX || fRadii[i].fY != fRadii[i-1].fY) {
            allRadiiEqual = false;
        }
    }

    if (allCornersSquare) {
        fType = kRect_Type;
        return;
    }

    if (allRadiiEqual) {
        if (fRadii[0].fX >= SkScalarHalf(fRect.width()) &&
            fRadii[0].fY >= SkScalarHalf(fRect.height())) {
            fType = kOval_Type;
        } else {
            fType = kSimple_Type;
        }
        return;
    }

    fType = kComplex_Type;
}

#ifdef SK_DEBUG
void SkRRect::validate() const {
    bool allRadiiZero = (0 == fRadii[0].fX && 0 == fRadii[0].fY);
    bool allCornersSquare = (0 == fRadii[0].fX || 0 == fRadii[0].fY);
    bool allRadiiSame = true;

    for (int i = 1; i < 4; ++i) {
        if (0 != fRadii[i].fX || 0 != fRadii[i].fY) {
            allRadiiZero = false;
        }

        if (fRadii[i].fX != fRadii[i-1].fX || fRadii[i].fY != fRadii[i-1].fY) {
            allRadiiSame = false;
        }

        if (0 != fRadii[i].fX && 0 != fRadii[i].fY) {
            allCornersSquare = false;
        }
    }

    switch (fType) {
        case kEmpty_Type:
            SkASSERT(fRect.isEmpty());
            SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare);

            SkASSERT(0 == fRect.fLeft && 0 == fRect.fTop &&
                     0 == fRect.fRight && 0 == fRect.fBottom);
            break;
        case kRect_Type:
            SkASSERT(!fRect.isEmpty());
            SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare);
            break;
        case kOval_Type:
            SkASSERT(!fRect.isEmpty());
            SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare);

            for (int i = 0; i < 4; ++i) {
                SkASSERT(SkScalarNearlyEqual(fRadii[i].fX, SkScalarHalf(fRect.width())));
                SkASSERT(SkScalarNearlyEqual(fRadii[i].fY, SkScalarHalf(fRect.height())));
            }
            break;
        case kSimple_Type:
            SkASSERT(!fRect.isEmpty());
            SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare);
            break;
        case kComplex_Type:
            SkASSERT(!fRect.isEmpty());
            SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare);
            break;
        case kUnknown_Type:
            // no limits on this
            break;
    }
}
#endif // SK_DEBUG

///////////////////////////////////////////////////////////////////////////////
<commit_msg>Fix for roll-blocking compiler error in SkRRect.cpp<commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkRRect.h"

///////////////////////////////////////////////////////////////////////////////

void SkRRect::setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
    if (rect.isEmpty()) {
        this->setEmpty();
        return;
    }

    if (xRad <= 0 || yRad <= 0) {
        // all corners are square in this case
        this->setRect(rect);
        return;
    }

    if (rect.width() < xRad+xRad || rect.height() < yRad+yRad) {
        SkScalar scale = SkMinScalar(SkScalarDiv(rect.width(), xRad + xRad),
                                     SkScalarDiv(rect.height(), yRad + yRad));
        SkASSERT(scale < SK_Scalar1);
        xRad = SkScalarMul(xRad, scale);
        yRad = SkScalarMul(yRad, scale);
    }

    fRect = rect;
    for (int i = 0; i < 4; ++i) {
        fRadii[i].set(xRad, yRad);
    }
    fType = kSimple_Type;
    if (xRad >= SkScalarHalf(fRect.width()) && yRad >= SkScalarHalf(fRect.height())) {
        fType = kOval_Type;
        // TODO: try asserting they are already W/2 & H/2 already
        xRad = SkScalarHalf(fRect.width());
        yRad = SkScalarHalf(fRect.height());
    }

    SkDEBUGCODE(this->validate();)
}

void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) {
    if (rect.isEmpty()) {
        this->setEmpty();
        return;
    }

    fRect = rect;
    memcpy(fRadii, radii, sizeof(fRadii));

    bool allCornersSquare = true;

    // Clamp negative radii to zero
    for (int i = 0; i < 4; ++i) {
        if (fRadii[i].fX <= 0 || fRadii[i].fY <= 0) {
            // In this case we are being a little fast & loose. Since one of
            // the radii is 0 the corner is square. However, the other radii
            // could still be non-zero and play in the global scale factor
            // computation.
            fRadii[i].fX = 0;
            fRadii[i].fY = 0;
        } else {
            allCornersSquare = false;
        }
    }

    if (allCornersSquare) {
        this->setRect(rect);
        return;
    }

    // Proportionally scale down all radii to fit. Find the minimum ratio
    // of a side and the radii on that side (for all four sides) and use
    // that to scale down _all_ the radii. This algorithm is from the
    // W3 spec (http://www.w3.org/TR/css3-background/) section 5.5 - Overlapping
    // Curves:
    // "Let f = min(Li/Si), where i is one of { top, right, bottom, left },
    //   Si is the sum of the two corresponding radii of the corners on side i,
    //   and Ltop = Lbottom = the width of the box,
    //   and Lleft = Lright = the height of the box.
    // If f < 1, then all corner radii are reduced by multiplying them by f."
    SkScalar scale = SK_Scalar1;

    if (fRadii[0].fX + fRadii[1].fX > rect.width()) {
        scale = SkMinScalar(scale,
                            SkScalarDiv(rect.width(), fRadii[0].fX + fRadii[1].fX));
    }
    if (fRadii[1].fY + fRadii[2].fY > rect.height()) {
        scale = SkMinScalar(scale,
                            SkScalarDiv(rect.height(), fRadii[1].fY + fRadii[2].fY));
    }
    if (fRadii[2].fX + fRadii[3].fX > rect.width()) {
        scale = SkMinScalar(scale,
                            SkScalarDiv(rect.width(), fRadii[2].fX + fRadii[3].fX));
    }
    if (fRadii[3].fY + fRadii[0].fY > rect.height()) {
        scale = SkMinScalar(scale,
                            SkScalarDiv(rect.height(), fRadii[3].fY + fRadii[0].fY));
    }

    if (scale < SK_Scalar1) {
        for (int i = 0; i < 4; ++i) {
            fRadii[i].fX = SkScalarMul(fRadii[i].fX, scale);
            fRadii[i].fY = SkScalarMul(fRadii[i].fY, scale);
        }
    }

    // At this point we're either oval, simple, or complex (not empty or rect)
    // but we lazily resolve the type to avoid the work if the information
    // isn't required.
    fType = (SkRRect::Type) kUnknown_Type;

    SkDEBUGCODE(this->validate();)
}

bool SkRRect::contains(SkScalar x, SkScalar y) const {
    SkDEBUGCODE(this->validate();)

    if (kEmpty_Type == this->type()) {
        return false;
    }

    if (!fRect.contains(x, y)) {
        return false;
    }

    if (kRect_Type == this->type()) {
        // the 'fRect' test above was sufficient
        return true;
    }

    // We know the point is inside the RR's bounds. The only way it can
    // be out is if it outside one of the corners
    SkPoint canonicalPt; // (x,y) translated to one of the quadrants
    int index;

    if (kOval_Type == this->type()) {
        canonicalPt.set(x - fRect.centerX(), y - fRect.centerY());
        index = kUpperLeft_Corner;  // any corner will do in this case
    } else {
        if (x < fRect.fLeft + fRadii[kUpperLeft_Corner].fX &&
            y < fRect.fTop + fRadii[kUpperLeft_Corner].fY) {
            // UL corner
            index = kUpperLeft_Corner;
            canonicalPt.set(x - (fRect.fLeft + fRadii[kUpperLeft_Corner].fX),
                            y - (fRect.fTop + fRadii[kUpperLeft_Corner].fY));
            SkASSERT(canonicalPt.fX < 0 && canonicalPt.fY < 0);
        } else if (x < fRect.fLeft + fRadii[kLowerLeft_Corner].fX &&
                   y > fRect.fBottom - fRadii[kLowerLeft_Corner].fY) {
            // LL corner
            index = kLowerLeft_Corner;
            canonicalPt.set(x - (fRect.fLeft + fRadii[kLowerLeft_Corner].fX),
                            y - (fRect.fBottom - fRadii[kLowerLeft_Corner].fY));
            SkASSERT(canonicalPt.fX < 0 && canonicalPt.fY > 0);
        } else if (x > fRect.fRight - fRadii[kUpperRight_Corner].fX &&
                   y < fRect.fTop + fRadii[kUpperRight_Corner].fY) {
            // UR corner
            index = kUpperRight_Corner;
            canonicalPt.set(x - (fRect.fRight - fRadii[kUpperRight_Corner].fX),
                            y - (fRect.fTop + fRadii[kUpperRight_Corner].fY));
            SkASSERT(canonicalPt.fX > 0 && canonicalPt.fY < 0);
        } else if (x > fRect.fRight - fRadii[kLowerRight_Corner].fX &&
                   y > fRect.fBottom - fRadii[kLowerRight_Corner].fY) {
            // LR corner
            index = kLowerRight_Corner;
            canonicalPt.set(x - (fRect.fRight - fRadii[kLowerRight_Corner].fX),
                            y - (fRect.fBottom - fRadii[kLowerRight_Corner].fY));
            SkASSERT(canonicalPt.fX > 0 && canonicalPt.fY > 0);
        } else {
            // not in any of the corners
            return true;
        }
    }

    // A point is in an ellipse (in standard position) if:
    //      x^2     y^2
    //     ----- + ----- <= 1
    //      a^2     b^2
    SkScalar dist =  SkScalarDiv(SkScalarSquare(canonicalPt.fX), SkScalarSquare(fRadii[index].fX)) +
                     SkScalarDiv(SkScalarSquare(canonicalPt.fY), SkScalarSquare(fRadii[index].fY));
    return dist <= SK_Scalar1;
}

// There is a simplified version of this method in setRectXY
void SkRRect::computeType() const {
    SkDEBUGCODE(this->validate();)

    if (fRect.isEmpty()) {
        fType = kEmpty_Type;
        return;
    }

    bool allRadiiEqual = true; // are all x radii equal and all y radii?
    bool allCornersSquare = 0 == fRadii[0].fX || 0 == fRadii[0].fY;

    for (int i = 1; i < 4; ++i) {
        if (0 != fRadii[i].fX && 0 != fRadii[i].fY) {
            // if either radius is zero the corner is square so both have to
            // be non-zero to have a rounded corner
            allCornersSquare = false;
        }
        if (fRadii[i].fX != fRadii[i-1].fX || fRadii[i].fY != fRadii[i-1].fY) {
            allRadiiEqual = false;
        }
    }

    if (allCornersSquare) {
        fType = kRect_Type;
        return;
    }

    if (allRadiiEqual) {
        if (fRadii[0].fX >= SkScalarHalf(fRect.width()) &&
            fRadii[0].fY >= SkScalarHalf(fRect.height())) {
            fType = kOval_Type;
        } else {
            fType = kSimple_Type;
        }
        return;
    }

    fType = kComplex_Type;
}

#ifdef SK_DEBUG
void SkRRect::validate() const {
    bool allRadiiZero = (0 == fRadii[0].fX && 0 == fRadii[0].fY);
    bool allCornersSquare = (0 == fRadii[0].fX || 0 == fRadii[0].fY);
    bool allRadiiSame = true;

    for (int i = 1; i < 4; ++i) {
        if (0 != fRadii[i].fX || 0 != fRadii[i].fY) {
            allRadiiZero = false;
        }

        if (fRadii[i].fX != fRadii[i-1].fX || fRadii[i].fY != fRadii[i-1].fY) {
            allRadiiSame = false;
        }

        if (0 != fRadii[i].fX && 0 != fRadii[i].fY) {
            allCornersSquare = false;
        }
    }

    switch (fType) {
        case kEmpty_Type:
            SkASSERT(fRect.isEmpty());
            SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare);

            SkASSERT(0 == fRect.fLeft && 0 == fRect.fTop &&
                     0 == fRect.fRight && 0 == fRect.fBottom);
            break;
        case kRect_Type:
            SkASSERT(!fRect.isEmpty());
            SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare);
            break;
        case kOval_Type:
            SkASSERT(!fRect.isEmpty());
            SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare);

            for (int i = 0; i < 4; ++i) {
                SkASSERT(SkScalarNearlyEqual(fRadii[i].fX, SkScalarHalf(fRect.width())));
                SkASSERT(SkScalarNearlyEqual(fRadii[i].fY, SkScalarHalf(fRect.height())));
            }
            break;
        case kSimple_Type:
            SkASSERT(!fRect.isEmpty());
            SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare);
            break;
        case kComplex_Type:
            SkASSERT(!fRect.isEmpty());
            SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare);
            break;
#if 0
        // error: case value not in enumerated type 'SkRRect::Type
        case kUnknown_Type:
            // no limits on this
            break;
#endif
    }
}
#endif // SK_DEBUG

///////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>#include "StorageLogSegment.h"
#include "System/FileSystem.h"
#include "System/IO/IOProcessor.h"
#include "System/Stopwatch.h"
#include "System/Compress/Compressor.h"

StorageLogSegment::StorageLogSegment()
{
    prev = next = this;
    logSegmentID = 0;
    fd = INVALID_FD;
    logCommandID = 1;
    prevContextID = 0;
    prevShardID = 0;
    writeShardID = true;
    asyncCommit = false;
}

#define Log_DebugLong(sw, ...)  \
    if (sw.Elapsed() > 1000)    \
    do {                        \
        Log_Debug(__VA_ARGS__); \
        sw.Reset();             \
    } while (0)

bool StorageLogSegment::Open(Buffer& filename_, uint64_t logSegmentID_)
{
    unsigned    length;
    Stopwatch   sw;

    sw.Start();

    filename.Write(filename_);
    filename.NullTerminate();
    fd = FS_Open(filename.GetBuffer(), FS_CREATE | FS_WRITEONLY | FS_APPEND);
    if (fd == INVALID_FD)
        return false;

    sw.Stop();

    Log_DebugLong(sw, "log segment Open() took %U msec", (uint64_t) sw.Elapsed());

    logSegmentID = logSegmentID_;
    offset = 0;

    sw.Start();
    writeBuffer.AppendLittle64(logSegmentID);
    length = writeBuffer.GetLength();

    if (FS_FileWrite(fd, writeBuffer.GetBuffer(), length) != length)
    {
        FS_FileClose(fd);
        fd = INVALID_FD;
        return false;
    }
    offset += length;

    sw.Stop();

    Log_DebugLong(sw, "log segment Open() took %U msec, length = %u", (uint64_t) sw.Elapsed(), length);

    sw.Start();
    FS_Sync(fd);
    sw.Stop();

    Log_DebugLong(sw, "log segment Open() took %U msec", (uint64_t) sw.Elapsed());

    NewRound();

    Log_Debug("Opening log segment %U", logSegmentID);

    return true;
}

void StorageLogSegment::Close()
{
    FS_FileClose(fd);
    fd = INVALID_FD;
    writeBuffer.Reset();
}

void StorageLogSegment::DeleteFile()
{
    FS_Delete(filename.GetBuffer());
}

uint64_t StorageLogSegment::GetLogSegmentID()
{
    return logSegmentID;
}

uint32_t StorageLogSegment::GetLogCommandID()
{
    return logCommandID;
}

void StorageLogSegment::SetOnCommit(Callable* onCommit_)
{
    onCommit = onCommit_;
    asyncCommit = true;
}

int32_t StorageLogSegment::AppendSet(uint16_t contextID, uint64_t shardID,
 ReadBuffer& key, ReadBuffer& value)
{
    assert(fd != INVALID_FD);

    prevLength = writeBuffer.GetLength();

    writeBuffer.Appendf("%c", STORAGE_LOGSEGMENT_COMMAND_SET);
    if (!writeShardID && contextID == prevContextID && shardID == prevShardID)
    {
        writeBuffer.Appendf("%b", true); // use previous shardID
    }
    else
    {
        writeBuffer.Appendf("%b", false);
        writeBuffer.AppendLittle16(contextID);
        writeBuffer.AppendLittle64(shardID);
    }
    writeBuffer.AppendLittle16(key.GetLength());
    writeBuffer.Append(key);
    writeBuffer.AppendLittle32(value.GetLength());
    writeBuffer.Append(value);

    writeShardID = false;
    prevContextID = contextID;
    prevShardID = shardID;
    return logCommandID++;
}

int32_t StorageLogSegment::AppendDelete(uint16_t contextID, uint64_t shardID, ReadBuffer& key)
{
    assert(fd != INVALID_FD);

    prevLength = writeBuffer.GetLength();

    writeBuffer.Appendf("%c", STORAGE_LOGSEGMENT_COMMAND_DELETE);

    if (!writeShardID && contextID == prevContextID && shardID == prevShardID)
    {
        writeBuffer.Appendf("%b", true); // use previous shardID
    }
    else
    {
        writeBuffer.Appendf("%b", false);
        writeBuffer.AppendLittle16(contextID);
        writeBuffer.AppendLittle64(shardID);
    }
    writeBuffer.AppendLittle16(key.GetLength());
    writeBuffer.Append(key);

    writeShardID = false;
    prevContextID = contextID;
    prevShardID = shardID;
    return logCommandID++;
}

void StorageLogSegment::Undo()
{
    writeBuffer.SetLength(prevLength);
    logCommandID--;
    writeShardID = true;
}

void StorageLogSegment::Commit()
{
    uint32_t    length;
    uint32_t    checksum;
    ReadBuffer  dataPart;
    Buffer      compressed;
    Compressor  compressor;

    commitStatus = true;

    assert(fd != INVALID_FD);

    length = writeBuffer.GetLength();

    assert(length >= STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);

    if (length == STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE)
        return; // empty round

    dataPart.SetBuffer(writeBuffer.GetBuffer() + STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);
    dataPart.SetLength(length - STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);
//    checksum = dataPart.GetChecksum();
    checksum = 0;

    assert(compressor.Compress(dataPart, compressed));

//    Log_Debug("uncompressed = %s, compressed = %s", HUMAN_BYTES(dataPart.GetLength()),
//     HUMAN_BYTES(compressed.GetLength()));

    length = STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE + compressed.GetLength();

    writeBuffer.SetLength(0);
    writeBuffer.AppendLittle32(length);
    writeBuffer.AppendLittle32(dataPart.GetLength());
    writeBuffer.AppendLittle32(checksum);
    writeBuffer.SetLength(STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);
    writeBuffer.Append(compressed);

//    Log_Debug("Commit");

    sw.Start();
/*
    if (FS_FileWrite(fd, writeBuffer.GetBuffer(), length) != length)
    {
        FS_FileClose(fd);
        fd = INVALID_FD;
        commitStatus = false;
        return;
    }
*/
  // TEST CODE
    #define WRITE_SIZE 64*1024
    unsigned ws;
    for (unsigned ofs = 0; ofs < length; ofs += ws)
    {
        ws = MIN(WRITE_SIZE, length - ofs);
        if (FS_FileWrite(fd, writeBuffer.GetBuffer() + ofs, ws) != ws)
        {
            FS_FileClose(fd);
            fd = INVALID_FD;
            commitStatus = false;
            return;
        }
        FS_Sync(fd);
    }
    // TEST CODE END

    offset += length;

    sw.Stop();
    Log_DebugLong(sw, "log segment Commit took %U msec, length: %u", (uint64_t) sw.Elapsed(), length);

    FS_Sync(fd);

    Log_DebugLong(sw, "log segment Sync took %U msec", (uint64_t) sw.Elapsed());

    NewRound();

    if (asyncCommit)
        IOProcessor::Complete(onCommit);
}

bool StorageLogSegment::GetCommitStatus()
{
    return commitStatus;
}

bool StorageLogSegment::HasUncommitted()
{
    return (writeBuffer.GetLength() > STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);
}

uint64_t StorageLogSegment::GetOffset()
{
    return offset;
}

void StorageLogSegment::NewRound()
{
    // reserve:
    // 4 bytes for size
    // 4 bytes for uncompressedLength
    // 4 bytes for CRC
    writeBuffer.Allocate(STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);
    writeBuffer.Zero();
    writeBuffer.SetLength(STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);

    prevLength = writeBuffer.GetLength();
}
<commit_msg>Fixed build bug.<commit_after>#include "StorageLogSegment.h"
#include "System/FileSystem.h"
#include "System/IO/IOProcessor.h"
#include "System/Stopwatch.h"
#include "System/Compress/Compressor.h"

StorageLogSegment::StorageLogSegment()
{
    prev = next = this;
    logSegmentID = 0;
    fd = INVALID_FD;
    logCommandID = 1;
    prevContextID = 0;
    prevShardID = 0;
    writeShardID = true;
    asyncCommit = false;
}

#define Log_DebugLong(sw, ...)  \
    if (sw.Elapsed() > 1000)    \
    do {                        \
        Log_Debug(__VA_ARGS__); \
        sw.Reset();             \
    } while (0)

bool StorageLogSegment::Open(Buffer& filename_, uint64_t logSegmentID_)
{
    unsigned    length;
    Stopwatch   sw;

    sw.Start();

    filename.Write(filename_);
    filename.NullTerminate();
    fd = FS_Open(filename.GetBuffer(), FS_CREATE | FS_WRITEONLY | FS_APPEND);
    if (fd == INVALID_FD)
        return false;

    sw.Stop();

    Log_DebugLong(sw, "log segment Open() took %U msec", (uint64_t) sw.Elapsed());

    logSegmentID = logSegmentID_;
    offset = 0;

    sw.Start();
    writeBuffer.AppendLittle64(logSegmentID);
    length = writeBuffer.GetLength();

    if (FS_FileWrite(fd, writeBuffer.GetBuffer(), length) != length)
    {
        FS_FileClose(fd);
        fd = INVALID_FD;
        return false;
    }
    offset += length;

    sw.Stop();

    Log_DebugLong(sw, "log segment Open() took %U msec, length = %u", (uint64_t) sw.Elapsed(), length);

    sw.Start();
    FS_Sync(fd);
    sw.Stop();

    Log_DebugLong(sw, "log segment Open() took %U msec", (uint64_t) sw.Elapsed());

    NewRound();

    Log_Debug("Opening log segment %U", logSegmentID);

    return true;
}

void StorageLogSegment::Close()
{
    FS_FileClose(fd);
    fd = INVALID_FD;
    writeBuffer.Reset();
}

void StorageLogSegment::DeleteFile()
{
    FS_Delete(filename.GetBuffer());
}

uint64_t StorageLogSegment::GetLogSegmentID()
{
    return logSegmentID;
}

uint32_t StorageLogSegment::GetLogCommandID()
{
    return logCommandID;
}

void StorageLogSegment::SetOnCommit(Callable* onCommit_)
{
    onCommit = onCommit_;
    asyncCommit = true;
}

int32_t StorageLogSegment::AppendSet(uint16_t contextID, uint64_t shardID,
 ReadBuffer& key, ReadBuffer& value)
{
    assert(fd != INVALID_FD);

    prevLength = writeBuffer.GetLength();

    writeBuffer.Appendf("%c", STORAGE_LOGSEGMENT_COMMAND_SET);
    if (!writeShardID && contextID == prevContextID && shardID == prevShardID)
    {
        writeBuffer.Appendf("%b", true); // use previous shardID
    }
    else
    {
        writeBuffer.Appendf("%b", false);
        writeBuffer.AppendLittle16(contextID);
        writeBuffer.AppendLittle64(shardID);
    }
    writeBuffer.AppendLittle16(key.GetLength());
    writeBuffer.Append(key);
    writeBuffer.AppendLittle32(value.GetLength());
    writeBuffer.Append(value);

    writeShardID = false;
    prevContextID = contextID;
    prevShardID = shardID;
    return logCommandID++;
}

int32_t StorageLogSegment::AppendDelete(uint16_t contextID, uint64_t shardID, ReadBuffer& key)
{
    assert(fd != INVALID_FD);

    prevLength = writeBuffer.GetLength();

    writeBuffer.Appendf("%c", STORAGE_LOGSEGMENT_COMMAND_DELETE);

    if (!writeShardID && contextID == prevContextID && shardID == prevShardID)
    {
        writeBuffer.Appendf("%b", true); // use previous shardID
    }
    else
    {
        writeBuffer.Appendf("%b", false);
        writeBuffer.AppendLittle16(contextID);
        writeBuffer.AppendLittle64(shardID);
    }
    writeBuffer.AppendLittle16(key.GetLength());
    writeBuffer.Append(key);

    writeShardID = false;
    prevContextID = contextID;
    prevShardID = shardID;
    return logCommandID++;
}

void StorageLogSegment::Undo()
{
    writeBuffer.SetLength(prevLength);
    logCommandID--;
    writeShardID = true;
}

void StorageLogSegment::Commit()
{
    uint32_t    length;
    uint32_t    checksum;
    ReadBuffer  dataPart;
    Buffer      compressed;
    Compressor  compressor;

    commitStatus = true;

    assert(fd != INVALID_FD);

    length = writeBuffer.GetLength();

    assert(length >= STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);

    if (length == STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE)
        return; // empty round

    dataPart.SetBuffer(writeBuffer.GetBuffer() + STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);
    dataPart.SetLength(length - STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);
//    checksum = dataPart.GetChecksum();
    checksum = 0;

    assert(compressor.Compress(dataPart, compressed));

//    Log_Debug("uncompressed = %s, compressed = %s", HUMAN_BYTES(dataPart.GetLength()),
//     HUMAN_BYTES(compressed.GetLength()));

    length = STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE + compressed.GetLength();

    writeBuffer.SetLength(0);
    writeBuffer.AppendLittle32(length);
    writeBuffer.AppendLittle32(dataPart.GetLength());
    writeBuffer.AppendLittle32(checksum);
    writeBuffer.SetLength(STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);
    writeBuffer.Append(compressed);

//    Log_Debug("Commit");

/*
    if (FS_FileWrite(fd, writeBuffer.GetBuffer(), length) != length)
    {
        FS_FileClose(fd);
        fd = INVALID_FD;
        commitStatus = false;
        return;
    }
*/
  // TEST CODE
    #define WRITE_SIZE 64*1024
    unsigned ws;
    for (unsigned ofs = 0; ofs < length; ofs += ws)
    {
        ws = MIN(WRITE_SIZE, length - ofs);
        if (FS_FileWrite(fd, writeBuffer.GetBuffer() + ofs, ws) != ws)
        {
            FS_FileClose(fd);
            fd = INVALID_FD;
            commitStatus = false;
            return;
        }
        FS_Sync(fd);
    }
    // TEST CODE END

    offset += length;

    FS_Sync(fd);

    NewRound();

    if (asyncCommit)
        IOProcessor::Complete(onCommit);
}

bool StorageLogSegment::GetCommitStatus()
{
    return commitStatus;
}

bool StorageLogSegment::HasUncommitted()
{
    return (writeBuffer.GetLength() > STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);
}

uint64_t StorageLogSegment::GetOffset()
{
    return offset;
}

void StorageLogSegment::NewRound()
{
    // reserve:
    // 4 bytes for size
    // 4 bytes for uncompressedLength
    // 4 bytes for CRC
    writeBuffer.Allocate(STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);
    writeBuffer.Zero();
    writeBuffer.SetLength(STORAGE_LOGSEGMENT_BLOCK_HEAD_SIZE);

    prevLength = writeBuffer.GetLength();
}
<|endoftext|>


<commit_before><commit_msg>Fix issues with POV export -  textures & colors<commit_after><|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cassert>
#include <cstdint>
#include <common>
#include <kprint>
#include <util/crc32.hpp>
#include <kernel/elf.hpp>
#include <kernel/syscalls.hpp>

// NOTE: crc_to MUST NOT be initialized to zero
static uint32_t crc_ro = CRC32_BEGIN();
const auto* LOW_CHECK_SIZE = (volatile int*) 0x200;

// Global constructors
static int gconstr_value = 0;
__attribute__((constructor))
static void self_test_gconstr() {
  gconstr_value = 1;
}

static uint32_t generate_ro_crc() noexcept
{
  extern char _TEXT_START_;
  extern char _TEXT_END_;
  extern char _RODATA_START_;
  extern char _RODATA_END_;
  return crc32_fast(&_TEXT_START_, &_RODATA_END_ - &_TEXT_START_);
}

extern "C"
void __init_sanity_checks() noexcept
{
  // zero low memory
  for (volatile int* lowmem = NULL; lowmem < LOW_CHECK_SIZE; lowmem++)
      *lowmem = 0;
  // generate checksum for read-only portions of kernel
  crc_ro = generate_ro_crc();
}

extern "C"
void kernel_sanity_checks()
{
  // verify checksum of read-only portions of kernel
  uint32_t new_ro = generate_ro_crc();
  if (crc_ro != new_ro) {
    kprintf("CRC mismatch %#x vs %#x\n", crc_ro, new_ro);
    panic("Sanity checks: CRC of kernel read-only area failed");
  }

  // verify that Elf symbols were not overwritten
  bool symbols_verified = Elf::verify_symbols();
  if (!symbols_verified)
    panic("Sanity checks: Consistency of Elf symbols and string areas");

  // global constructor self-test
  if (gconstr_value != 1) {
    kprintf("Sanity checks: Global constructors not working (or modified during run-time)!\n");
    panic("Sanity checks: Global constructors verification failed");
  }

}
<commit_msg>x86: Don't verify RO area with paging enabled<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cassert>
#include <cstdint>
#include <kprint>
#include <util/crc32.hpp>
#include <kernel/elf.hpp>
#include <kernel/syscalls.hpp>

//#define ENABLE_CRC_RO
const auto* LOW_CHECK_SIZE = (volatile int*) 0x200;

// Global constructors
static int gconstr_value = 0;
__attribute__((constructor))
static void self_test_gconstr() {
  gconstr_value = 1;
}

#ifdef ENABLE_CRC_RO
// NOTE: crc_ro MUST NOT be initialized to zero
static uint32_t crc_ro = CRC32_BEGIN();

static uint32_t generate_ro_crc() noexcept
{
  extern char _TEXT_START_;
  extern char _TEXT_END_;
  extern char _RODATA_START_;
  extern char _RODATA_END_;
  return crc32_fast(&_TEXT_START_, &_RODATA_END_ - &_TEXT_START_);
}
#endif

extern "C"
void __init_sanity_checks() noexcept
{
  // zero low memory
  for (volatile int* lowmem = NULL; lowmem < LOW_CHECK_SIZE; lowmem++)
      *lowmem = 0;
#ifdef ENABLE_CRC_RO
  // generate checksum for read-only portions of kernel
  crc_ro = generate_ro_crc();
#endif
}

extern "C"
void kernel_sanity_checks()
{
#ifdef ENABLE_CRC_RO
  // verify checksum of read-only portions of kernel
  uint32_t new_ro = generate_ro_crc();

  if (crc_ro != new_ro) {
    kprintf("CRC mismatch %#x vs %#x\n", crc_ro, new_ro);
    panic("Sanity checks: CRC of kernel read-only area failed");
  }
#endif

  // verify that Elf symbols were not overwritten
  bool symbols_verified = Elf::verify_symbols();
  if (!symbols_verified)
    panic("Sanity checks: Consistency of Elf symbols and string areas");

  // global constructor self-test
  if (gconstr_value != 1) {
    kprintf("Sanity checks: Global constructors not working (or modified during run-time)!\n");
    panic("Sanity checks: Global constructors verification failed");
  }

}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#ifdef AIX
#define _LINUX_SOURCE_COMPAT
#include <sys/timer.h>
#undef _LINUX_SOURCE_COMPAT
#endif

#include <plugins/gtk/gtkobject.hxx>
#include <plugins/gtk/gtkframe.hxx>
#include <plugins/gtk/gtkdata.hxx>
#include <plugins/gtk/gtkinst.hxx>

GtkSalObject::GtkSalObject( GtkSalFrame* pParent, sal_Bool bShow )
        : m_pSocket( NULL ),
          m_pRegion( NULL )
{
    if( pParent )
    {
        // our plug window
        m_pSocket = gtk_drawing_area_new();
        Show( bShow );
        // insert into container
        gtk_fixed_put( pParent->getFixedContainer(),
                       m_pSocket,
                       0, 0 );
        // realize so we can get a window id
        gtk_widget_realize( m_pSocket );

        // make it transparent; some plugins may not insert
        // their own window here but use the socket window itself
        gtk_widget_set_app_paintable( m_pSocket, TRUE );

        //system data
        SalDisplay* pDisp = GetX11SalData()->GetDisplay();
        m_aSystemData.nSize         = sizeof( SystemChildData );
        m_aSystemData.pDisplay      = pDisp->GetDisplay();
        m_aSystemData.aWindow       = GDK_WINDOW_XWINDOW(m_pSocket->window);
        m_aSystemData.pSalFrame     = NULL;
        m_aSystemData.pWidget       = m_pSocket;
        m_aSystemData.pVisual       = pDisp->GetVisual(pParent->getScreenNumber()).GetVisual();
        m_aSystemData.nScreen       = pParent->getScreenNumber();
        m_aSystemData.nDepth        = pDisp->GetVisual(pParent->getScreenNumber()).GetDepth();
        m_aSystemData.aColormap     = pDisp->GetColormap(pParent->getScreenNumber()).GetXColormap();
        m_aSystemData.pAppContext   = NULL;
        m_aSystemData.aShellWindow  = GDK_WINDOW_XWINDOW(GTK_WIDGET(pParent->getWindow())->window);
        m_aSystemData.pShellWidget  = GTK_WIDGET(pParent->getWindow());

        g_signal_connect( G_OBJECT(m_pSocket), "button-press-event", G_CALLBACK(signalButton), this );
        g_signal_connect( G_OBJECT(m_pSocket), "button-release-event", G_CALLBACK(signalButton), this );
        g_signal_connect( G_OBJECT(m_pSocket), "focus-in-event", G_CALLBACK(signalFocus), this );
        g_signal_connect( G_OBJECT(m_pSocket), "focus-out-event", G_CALLBACK(signalFocus), this );
        g_signal_connect( G_OBJECT(m_pSocket), "destroy", G_CALLBACK(signalDestroy), this );

        // #i59255# necessary due to sync effects with java child windows
        pParent->Sync();
    }
}

GtkSalObject::~GtkSalObject()
{
    if( m_pRegion )
        gdk_region_destroy( m_pRegion );
    if( m_pSocket )
    {
        // remove socket from parent frame's fixed container
        gtk_container_remove( GTK_CONTAINER(gtk_widget_get_parent(m_pSocket)),
                              m_pSocket );
        // get rid of the socket
        // actually the gtk_container_remove should let the ref count
        // of the socket sink to 0 and destroy it (see signalDestroy)
        // this is just a sanity check
        if( m_pSocket )
            gtk_widget_destroy( m_pSocket );
    }
}

void GtkSalObject::ResetClipRegion()
{
    if( m_pSocket )
        gdk_window_shape_combine_region( m_pSocket->window, NULL, 0, 0 );
}

sal_uInt16 GtkSalObject::GetClipRegionType()
{
    return SAL_OBJECT_CLIP_INCLUDERECTS;
}

void GtkSalObject::BeginSetClipRegion( sal_uLong )
{
    if( m_pRegion )
        gdk_region_destroy( m_pRegion );
    m_pRegion = gdk_region_new();
}

void GtkSalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
{
    GdkRectangle aRect;
    aRect.x         = nX;
    aRect.y         = nY;
    aRect.width     = nWidth;
    aRect.height    = nHeight;

    gdk_region_union_with_rect( m_pRegion, &aRect );
}

void GtkSalObject::EndSetClipRegion()
{
    if( m_pSocket )
        gdk_window_shape_combine_region( m_pSocket->window, m_pRegion, 0, 0 );
}

void GtkSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
{
    if( m_pSocket )
    {
        GtkFixed* pContainer = GTK_FIXED(gtk_widget_get_parent(m_pSocket));
        gtk_fixed_move( pContainer, m_pSocket, nX, nY );
        gtk_widget_set_size_request( m_pSocket, nWidth, nHeight );
        gtk_container_resize_children( GTK_CONTAINER(pContainer) );
    }
}

void GtkSalObject::Show( sal_Bool bVisible )
{
    if( m_pSocket )
    {
        if( bVisible )
            gtk_widget_show( m_pSocket );
        else
            gtk_widget_hide( m_pSocket );
    }
}

void GtkSalObject::Enable( sal_Bool )
{
}

void GtkSalObject::GrabFocus()
{
}

void GtkSalObject::SetBackground()
{
}

void GtkSalObject::SetBackground( SalColor )
{
}

const SystemEnvData* GtkSalObject::GetSystemData() const
{
    return &m_aSystemData;
}

gboolean GtkSalObject::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer object )
{
    GtkSalObject* pThis = (GtkSalObject*)object;

    if( pEvent->type == GDK_BUTTON_PRESS )
    {
        GTK_YIELD_GRAB();
        pThis->CallCallback( SALOBJ_EVENT_TOTOP, NULL );
    }

    return FALSE;
}

gboolean GtkSalObject::signalFocus( GtkWidget*, GdkEventFocus* pEvent, gpointer object )
{
    GtkSalObject* pThis = (GtkSalObject*)object;

    GTK_YIELD_GRAB();

    pThis->CallCallback( pEvent->in ? SALOBJ_EVENT_GETFOCUS : SALOBJ_EVENT_LOSEFOCUS, NULL );

    return FALSE;
}

void GtkSalObject::signalDestroy( GtkObject* pObj, gpointer object )
{
    GtkSalObject* pThis = (GtkSalObject*)object;
    if( GTK_WIDGET(pObj) == pThis->m_pSocket )
    {
        pThis->m_pSocket = NULL;
    }
}

void GtkSalObject::SetForwardKey( sal_Bool bEnable )
{
    printf ("GtkSalObject::SetForwardKey\n");
    if( bEnable )
        gtk_widget_add_events( GTK_WIDGET( m_pSocket ), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE );
    else
        gtk_widget_set_events( GTK_WIDGET( m_pSocket ), ~(GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE) & gtk_widget_get_events( GTK_WIDGET( m_pSocket ) ) );
}

void GtkSalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ )
{
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>don't bleat about having called GtkSalObject::SetForwardKey<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#ifdef AIX
#define _LINUX_SOURCE_COMPAT
#include <sys/timer.h>
#undef _LINUX_SOURCE_COMPAT
#endif

#include <plugins/gtk/gtkobject.hxx>
#include <plugins/gtk/gtkframe.hxx>
#include <plugins/gtk/gtkdata.hxx>
#include <plugins/gtk/gtkinst.hxx>

GtkSalObject::GtkSalObject( GtkSalFrame* pParent, sal_Bool bShow )
        : m_pSocket( NULL ),
          m_pRegion( NULL )
{
    if( pParent )
    {
        // our plug window
        m_pSocket = gtk_drawing_area_new();
        Show( bShow );
        // insert into container
        gtk_fixed_put( pParent->getFixedContainer(),
                       m_pSocket,
                       0, 0 );
        // realize so we can get a window id
        gtk_widget_realize( m_pSocket );

        // make it transparent; some plugins may not insert
        // their own window here but use the socket window itself
        gtk_widget_set_app_paintable( m_pSocket, TRUE );

        //system data
        SalDisplay* pDisp = GetX11SalData()->GetDisplay();
        m_aSystemData.nSize         = sizeof( SystemChildData );
        m_aSystemData.pDisplay      = pDisp->GetDisplay();
        m_aSystemData.aWindow       = GDK_WINDOW_XWINDOW(m_pSocket->window);
        m_aSystemData.pSalFrame     = NULL;
        m_aSystemData.pWidget       = m_pSocket;
        m_aSystemData.pVisual       = pDisp->GetVisual(pParent->getScreenNumber()).GetVisual();
        m_aSystemData.nScreen       = pParent->getScreenNumber();
        m_aSystemData.nDepth        = pDisp->GetVisual(pParent->getScreenNumber()).GetDepth();
        m_aSystemData.aColormap     = pDisp->GetColormap(pParent->getScreenNumber()).GetXColormap();
        m_aSystemData.pAppContext   = NULL;
        m_aSystemData.aShellWindow  = GDK_WINDOW_XWINDOW(GTK_WIDGET(pParent->getWindow())->window);
        m_aSystemData.pShellWidget  = GTK_WIDGET(pParent->getWindow());

        g_signal_connect( G_OBJECT(m_pSocket), "button-press-event", G_CALLBACK(signalButton), this );
        g_signal_connect( G_OBJECT(m_pSocket), "button-release-event", G_CALLBACK(signalButton), this );
        g_signal_connect( G_OBJECT(m_pSocket), "focus-in-event", G_CALLBACK(signalFocus), this );
        g_signal_connect( G_OBJECT(m_pSocket), "focus-out-event", G_CALLBACK(signalFocus), this );
        g_signal_connect( G_OBJECT(m_pSocket), "destroy", G_CALLBACK(signalDestroy), this );

        // #i59255# necessary due to sync effects with java child windows
        pParent->Sync();
    }
}

GtkSalObject::~GtkSalObject()
{
    if( m_pRegion )
        gdk_region_destroy( m_pRegion );
    if( m_pSocket )
    {
        // remove socket from parent frame's fixed container
        gtk_container_remove( GTK_CONTAINER(gtk_widget_get_parent(m_pSocket)),
                              m_pSocket );
        // get rid of the socket
        // actually the gtk_container_remove should let the ref count
        // of the socket sink to 0 and destroy it (see signalDestroy)
        // this is just a sanity check
        if( m_pSocket )
            gtk_widget_destroy( m_pSocket );
    }
}

void GtkSalObject::ResetClipRegion()
{
    if( m_pSocket )
        gdk_window_shape_combine_region( m_pSocket->window, NULL, 0, 0 );
}

sal_uInt16 GtkSalObject::GetClipRegionType()
{
    return SAL_OBJECT_CLIP_INCLUDERECTS;
}

void GtkSalObject::BeginSetClipRegion( sal_uLong )
{
    if( m_pRegion )
        gdk_region_destroy( m_pRegion );
    m_pRegion = gdk_region_new();
}

void GtkSalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
{
    GdkRectangle aRect;
    aRect.x         = nX;
    aRect.y         = nY;
    aRect.width     = nWidth;
    aRect.height    = nHeight;

    gdk_region_union_with_rect( m_pRegion, &aRect );
}

void GtkSalObject::EndSetClipRegion()
{
    if( m_pSocket )
        gdk_window_shape_combine_region( m_pSocket->window, m_pRegion, 0, 0 );
}

void GtkSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
{
    if( m_pSocket )
    {
        GtkFixed* pContainer = GTK_FIXED(gtk_widget_get_parent(m_pSocket));
        gtk_fixed_move( pContainer, m_pSocket, nX, nY );
        gtk_widget_set_size_request( m_pSocket, nWidth, nHeight );
        gtk_container_resize_children( GTK_CONTAINER(pContainer) );
    }
}

void GtkSalObject::Show( sal_Bool bVisible )
{
    if( m_pSocket )
    {
        if( bVisible )
            gtk_widget_show( m_pSocket );
        else
            gtk_widget_hide( m_pSocket );
    }
}

void GtkSalObject::Enable( sal_Bool )
{
}

void GtkSalObject::GrabFocus()
{
}

void GtkSalObject::SetBackground()
{
}

void GtkSalObject::SetBackground( SalColor )
{
}

const SystemEnvData* GtkSalObject::GetSystemData() const
{
    return &m_aSystemData;
}

gboolean GtkSalObject::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer object )
{
    GtkSalObject* pThis = (GtkSalObject*)object;

    if( pEvent->type == GDK_BUTTON_PRESS )
    {
        GTK_YIELD_GRAB();
        pThis->CallCallback( SALOBJ_EVENT_TOTOP, NULL );
    }

    return FALSE;
}

gboolean GtkSalObject::signalFocus( GtkWidget*, GdkEventFocus* pEvent, gpointer object )
{
    GtkSalObject* pThis = (GtkSalObject*)object;

    GTK_YIELD_GRAB();

    pThis->CallCallback( pEvent->in ? SALOBJ_EVENT_GETFOCUS : SALOBJ_EVENT_LOSEFOCUS, NULL );

    return FALSE;
}

void GtkSalObject::signalDestroy( GtkObject* pObj, gpointer object )
{
    GtkSalObject* pThis = (GtkSalObject*)object;
    if( GTK_WIDGET(pObj) == pThis->m_pSocket )
    {
        pThis->m_pSocket = NULL;
    }
}

void GtkSalObject::SetForwardKey( sal_Bool bEnable )
{
    if( bEnable )
        gtk_widget_add_events( GTK_WIDGET( m_pSocket ), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE );
    else
        gtk_widget_set_events( GTK_WIDGET( m_pSocket ), ~(GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE) & gtk_widget_get_events( GTK_WIDGET( m_pSocket ) ) );
}

void GtkSalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ )
{
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include <iostream>

#include "libaps.h"
#include "constants.h"
#include <thread>

using namespace std;

int main ()
{
  cout << "BBN X6-1000 Test Executable" << endl;

  set_malibu_threading_enable(false);

  int numDevices;
  numDevices = get_numDevices();

  cout << numDevices << " X6 device" << (numDevices > 1 ? "s": "")  << " found" << endl;

  if (numDevices < 1)
  	return 0;

  char s[] = "stdout";
  set_log(s);

  cout << "Attempting to initialize libaps" << endl;

  init();

  char serialBuffer[100];

  for (int cnt; cnt < numDevices; cnt++) {
  	get_deviceSerial(cnt, serialBuffer);
  	cout << "Device " << cnt << " serial #: " << serialBuffer << endl;
  }

  int rc;
  rc = connect_by_ID(0);

  cout << "connect_by_ID(0) returned " << rc << endl;

  cout << "current logic temperature = " << get_logic_temperature(0) << endl;

  cout << "current PLL frequency = " << get_sampleRate(0) << " MHz" << endl;

  cout << "setting trigger source = EXTERNAL" << endl;

  set_trigger_source(0, EXTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "setting trigger source = INTERNAL" << endl;

  set_trigger_source(0, INTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "get channel(0) enable: " << get_channel_enabled(0,0) << endl;

  cout << "set channel(0) enabled = 1" << endl;

  set_channel_enabled(0,0,true);

  cout << "enable ramp output" << endl;

  enable_test_generator(0,0,0.001);

  std::this_thread::sleep_for(std::chrono::seconds(5));

  cout << "enable sine wave output" << endl;

  disable_test_generator(0);
  enable_test_generator(0,1,0.001);

  std::this_thread::sleep_for(std::chrono::seconds(5));

  cout << "disabling channel" << endl;
  disable_test_generator(0);
  set_channel_enabled(0,0,false);

  cout << "get channel(0) enable: " << get_channel_enabled(0,0) << endl;

  rc = disconnect_by_ID(0);

  cout << "disconnect_by_ID(0) returned " << rc << endl;

  return 0;
}<commit_msg>First output through X6_1000 class<commit_after>#include <iostream>

#include "libaps.h"
#include "constants.h"
#include <thread>

using namespace std;

int main ()
{
  cout << "BBN X6-1000 Test Executable" << endl;

  set_malibu_threading_enable(false);

  set_logging_level(5);

  int numDevices;
  numDevices = get_numDevices();

  cout << numDevices << " X6 device" << (numDevices > 1 ? "s": "")  << " found" << endl;

  if (numDevices < 1)
  	return 0;

  char s[] = "stdout";
  set_log(s);

  cout << "Attempting to initialize libaps" << endl;

  init();

  char serialBuffer[100];

  for (int cnt; cnt < numDevices; cnt++) {
  	get_deviceSerial(cnt, serialBuffer);
  	cout << "Device " << cnt << " serial #: " << serialBuffer << endl;
  }

  int rc;
  rc = connect_by_ID(0);

  cout << "connect_by_ID(0) returned " << rc << endl;

  cout << "current logic temperature = " << get_logic_temperature(0) << endl;

  cout << "current PLL frequency = " << get_sampleRate(0) << " MHz" << endl;

  cout << "setting trigger source = EXTERNAL" << endl;

  set_trigger_source(0, EXTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "setting trigger source = INTERNAL" << endl;

  set_trigger_source(0, INTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "get channel(0) enable: " << get_channel_enabled(0,0) << endl;

  cout << "set channel(0) enabled = 1" << endl;

  set_channel_enabled(0,0,true);

  cout << "enable ramp output" << endl;

  enable_test_generator(0,0,0.001);

  std::this_thread::sleep_for(std::chrono::seconds(5));

  cout << "enable sine wave output" << endl;

  disable_test_generator(0);
  enable_test_generator(0,1,0.001);

  std::this_thread::sleep_for(std::chrono::seconds(5));

  cout << "disabling channel" << endl;
  disable_test_generator(0);
  set_channel_enabled(0,0,false);

  cout << "get channel(0) enable: " << get_channel_enabled(0,0) << endl;

  rc = disconnect_by_ID(0);

  cout << "disconnect_by_ID(0) returned " << rc << endl;

  return 0;
}<|endoftext|>


<commit_before>//===-- Process.cpp - Implement OS Process Concept --------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This header file implements the operating system Process concept.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Process.h"
#include "llvm/Config/config.h"

namespace llvm {
using namespace sys;

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
//===          independent code.
//===----------------------------------------------------------------------===//

unsigned llvm::sys::Process::GetRandomNumber() {
#if defined(HAVE_ARC4RANDOM)
  return arc4random();
#else
  static int x = (::srand(::time(NULL)), 0);
  return rand();
#endif
}

}

// Include the platform-specific parts of this class.
#ifdef LLVM_ON_UNIX
#include "Unix/Process.inc"
#endif
#ifdef LLVM_ON_WIN32
#include "Windows/Process.inc"
#endif
<commit_msg>[Support] Add missing include.<commit_after>//===-- Process.cpp - Implement OS Process Concept --------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This header file implements the operating system Process concept.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Process.h"
#include "llvm/Config/config.h"
#include <cstdlib>

namespace llvm {
using namespace sys;

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
//===          independent code.
//===----------------------------------------------------------------------===//

unsigned llvm::sys::Process::GetRandomNumber() {
#if defined(HAVE_ARC4RANDOM)
  return arc4random();
#else
  static int x = (::srand(::time(NULL)), 0);
  return ::rand();
#endif
}

}

// Include the platform-specific parts of this class.
#ifdef LLVM_ON_UNIX
#include "Unix/Process.inc"
#endif
#ifdef LLVM_ON_WIN32
#include "Windows/Process.inc"
#endif
<|endoftext|>


<commit_before>/**
 * Node Native Module for Lib Sodium
 *
 * @Author Pedro Paixao
 * @email paixaop at gmail dot com
 * @License MIT
 */
#include "node_sodium.h"

/* int crypto_pwhash_argon2i(unsigned char * const out,
                          unsigned long long outlen,
                          const char * const passwd,
                          unsigned long long passwdlen,
                          const unsigned char * const salt,
                          unsigned long long opslimit, size_t memlimit,
                          int alg)
*/
NAN_METHOD(bind_crypto_pwhash_argon2i) {
    Nan::EscapableHandleScope scope;

    ARGS(6,"arguments must be: output buffer, password buffer, salt buffer, oLimit, memLimit, algorithm");

    ARG_TO_BUFFER_TYPE(out, unsigned char*);
    ARG_TO_BUFFER_TYPE(passwd, char*);
    ARG_TO_UCHAR_BUFFER_LEN(salt, crypto_pwhash_argon2i_SALTBYTES);
    ARG_TO_NUMBER(oppLimit);
    ARG_TO_NUMBER(memLimit);
    ARG_TO_NUMBER(alg);

    if (crypto_pwhash_argon2i(out, out_size, passwd, passwd_size, salt, oppLimit, memLimit, alg) == 0) {
        return JS_TRUE;
    }

    return JS_NULL;
}

/* int crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES],
                              const char * const passwd,
                              unsigned long long passwdlen,
                              unsigned long long opslimit, size_t memlimit)
*/
NAN_METHOD(bind_crypto_pwhash_argon2i_str) {
    Nan::EscapableHandleScope scope;

    ARGS(3,"arguments must be: password buffer, oLimit, memLimit");

    ARG_TO_BUFFER_TYPE(passwd, char*);
    ARG_TO_NUMBER(oppLimit);
    ARG_TO_NUMBER(memLimit);

    NEW_BUFFER_AND_PTR(buf, crypto_pwhash_argon2i_STRBYTES);

    if (crypto_pwhash_argon2i_str((char*)buf_ptr, passwd, passwd_size, oppLimit, memLimit) == 0) {
        return JS_BUFFER(buf);
    }

    return JS_FALSE;
}

/* int crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYTES],
                                     const char * const passwd,
                                     unsigned long long passwdlen)
*/
NAN_METHOD(bind_crypto_pwhash_argon2i_str_verify) {
    Nan::EscapableHandleScope scope;

    ARGS(2,"arguments must be: pwhash string, password");

    ARG_TO_BUFFER_TYPE(hash, char*);
    ARG_TO_BUFFER_TYPE(passwd, char*);

    if (crypto_pwhash_argon2i_str_verify(hash, passwd, passwd_size) == 0) {
        return JS_TRUE;
    }

    return JS_FALSE;
}

/*
    int crypto_pwhash(unsigned char * const out, unsigned long long outlen,
                  const char * const passwd, unsigned long long passwdlen,
                  const unsigned char * const salt,
                  unsigned long long opslimit, size_t memlimit, int alg)

    Buffer out
    Buffer password
    Buffer salt
    Number oppsLimit
    Number memLimit
    Number algorithm

*/
NAN_METHOD(bind_crypto_pwhash) {
    Nan::EscapableHandleScope scope;

    ARGS(6,"arguments must be: output buffer, password buffer, salt buffer, oLimit, memLimit, algorithm");

    ARG_TO_BUFFER_TYPE(out, unsigned char*);
    ARG_TO_BUFFER_TYPE(passwd, char*);
    ARG_TO_UCHAR_BUFFER_LEN(salt, crypto_pwhash_SALTBYTES);
    ARG_TO_NUMBER(oppLimit);
    ARG_TO_NUMBER(memLimit);
    ARG_TO_NUMBER(alg);

    if (crypto_pwhash(out, out_size, passwd, passwd_size, salt, oppLimit, memLimit, alg) == 0) {
        return JS_TRUE;
    }

    return JS_NULL;
}

/**
 * int crypto_pwhash_str(char out[crypto_pwhash_STRBYTES],
                      const char * const passwd, unsigned long long passwdlen,
                      unsigned long long opslimit, size_t memlimit)

    Buffer out
    Buffer passwd
    Number oppsLimit
    Number memLimit
*/
NAN_METHOD(bind_crypto_pwhash_str) {
    Nan::EscapableHandleScope scope;

    ARGS(3,"arguments must be: password buffer, oLimit, memLimit");

    ARG_TO_BUFFER_TYPE(passwd, char*);
    ARG_TO_NUMBER(oppLimit);
    ARG_TO_NUMBER(memLimit);

    NEW_BUFFER_AND_PTR(out, crypto_pwhash_STRBYTES);

    if (crypto_pwhash_str((char*)out_ptr, passwd, passwd_size, oppLimit, memLimit) == 0) {
        return info.GetReturnValue().Set(out);
    }

    return JS_FALSE;
}

/**
 * int crypto_pwhash_str_verify(const char str[crypto_pwhash_STRBYTES],
                             const char * const passwd,
                             unsigned long long passwdlen)

    Buffer hash String
    Buffer password
 */
NAN_METHOD(bind_crypto_pwhash_str_verify) {
    Nan::EscapableHandleScope scope;

    ARGS(2,"arguments must be: pwhash string, password");

    ARG_TO_UCHAR_BUFFER_LEN(hash, crypto_pwhash_STRBYTES);
    ARG_TO_BUFFER_TYPE(passwd, char*);

    if (crypto_pwhash_str_verify((char*)hash, passwd, passwd_size) == 0) {
        return JS_TRUE;
    }

    return JS_FALSE;
}

/**
 * int crypto_pwhash_scryptsalsa208sha256(unsigned char * const out,
                                       unsigned long long outlen,
                                       const char * const passwd,
                                       unsigned long long passwdlen,
                                       const unsigned char * const salt,
                                       unsigned long long opslimit,
                                       size_t memlimit);

    number out length
    buffer passwd
    buffer salt
    number opslimit
    number memlimit
 */
NAN_METHOD(bind_crypto_pwhash_scryptsalsa208sha256) {
    Nan::EscapableHandleScope scope;

    ARGS(5,"arguments must be: output buffer, password buffer, salt buffer, oLimit, memLimit");

    ARG_TO_BUFFER_TYPE(out, unsigned char*);
    ARG_TO_BUFFER_TYPE(passwd, char*);
    ARG_TO_UCHAR_BUFFER_LEN(salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
    ARG_TO_NUMBER(oppLimit);
    ARG_TO_NUMBER(memLimit);

    if (crypto_pwhash_scryptsalsa208sha256(out, out_size, passwd, passwd_size, salt, oppLimit, memLimit) == 0) {
        return JS_TRUE;
    }

    return JS_FALSE;
}

/**
 * int crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd, size_t passwdlen,
                                          const uint8_t * salt, size_t saltlen,
                                          uint64_t N, uint32_t r, uint32_t p,
                                          uint8_t * buf, size_t buflen);
 * Buffer passwd
 * Buffer salt
 * Number N
 * Number r
 * Number p
 * Buffer scrypt hash output
 */
NAN_METHOD(bind_crypto_pwhash_scryptsalsa208sha256_ll) {
    Nan::EscapableHandleScope scope;

    ARGS(6,"arguments must be: password buffer, salt buffer, N, r, p, output buffer");

    ARG_TO_BUFFER_TYPE(passwd, uint8_t*);
    ARG_TO_BUFFER_TYPE(salt, uint8_t*);
    ARG_TO_NUMBER(N);
    ARG_TO_NUMBER(r);
    ARG_TO_NUMBER(p);
    ARG_TO_BUFFER_TYPE(out, uint8_t*);

    if (crypto_pwhash_scryptsalsa208sha256_ll(passwd, passwd_size, salt, salt_size, N, r, p, out, out_size) == 0) {
        return JS_TRUE;
    }

    return JS_FALSE;
}

/**
  int crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
                                           const char * const passwd,
                                           unsigned long long passwdlen,
                                           unsigned long long opslimit,
                                           size_t memlimit);

 */
NAN_METHOD(bind_crypto_pwhash_scryptsalsa208sha256_str) {
    Nan::EscapableHandleScope scope;

    ARGS(3,"arguments must be: password buffer, oLimit, memLimit");

    ARG_TO_BUFFER_TYPE(passwd, char*);
    ARG_TO_NUMBER(oppLimit);
    ARG_TO_NUMBER(memLimit);

    NEW_BUFFER_AND_PTR(hash, crypto_pwhash_scryptsalsa208sha256_STRBYTES);

    if (crypto_pwhash_scryptsalsa208sha256_str((char*)hash_ptr, passwd, passwd_size, oppLimit, memLimit) == 0) {
        return info.GetReturnValue().Set(hash);
    }

    return JS_NULL;
}

/**
 * int crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
                                                  const char * const passwd,
                                                  unsigned long long passwdlen);
 */
NAN_METHOD(bind_crypto_pwhash_scryptsalsa208sha256_str_verify) {
    Nan::EscapableHandleScope scope;

    ARGS(2,"arguments must be: pwhash string, password");

    ARG_TO_UCHAR_BUFFER_LEN(hash, crypto_pwhash_scryptsalsa208sha256_STRBYTES);
    ARG_TO_BUFFER_TYPE(passwd, char*);

    if (crypto_pwhash_scryptsalsa208sha256_str_verify((char*)hash, passwd, passwd_size) == 0) {
        return JS_TRUE;
    }

    return JS_FALSE;
}

/**
 * Register function calls in node binding
 */
void register_crypto_pwhash(Handle<Object> target) {

    // Methods
    NEW_METHOD(crypto_pwhash);
    NEW_METHOD(crypto_pwhash_str);
    NEW_METHOD(crypto_pwhash_str_verify);
    NEW_METHOD(crypto_pwhash_scryptsalsa208sha256);
    NEW_METHOD(crypto_pwhash_scryptsalsa208sha256_ll);
    NEW_METHOD(crypto_pwhash_scryptsalsa208sha256_str);
    NEW_METHOD(crypto_pwhash_scryptsalsa208sha256_str_verify);
    NEW_METHOD(crypto_pwhash_argon2i);
    NEW_METHOD(crypto_pwhash_argon2i_str);
    NEW_METHOD(crypto_pwhash_argon2i_str_verify);

    // Properties
    NEW_NUMBER_PROP(crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE);
    NEW_NUMBER_PROP(crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
    NEW_NUMBER_PROP(crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE);
    NEW_NUMBER_PROP(crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE);
    NEW_INT_PROP(crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
    NEW_INT_PROP(crypto_pwhash_scryptsalsa208sha256_STRBYTES);
    NEW_STRING_PROP(crypto_pwhash_scryptsalsa208sha256_STRPREFIX);

    NEW_NUMBER_PROP(crypto_pwhash_ALG_DEFAULT);
    NEW_NUMBER_PROP(crypto_pwhash_SALTBYTES);
    NEW_NUMBER_PROP(crypto_pwhash_STRBYTES);
    NEW_STRING_PROP(crypto_pwhash_STRPREFIX);
    NEW_NUMBER_PROP(crypto_pwhash_OPSLIMIT_INTERACTIVE);
    NEW_NUMBER_PROP(crypto_pwhash_MEMLIMIT_INTERACTIVE);
    NEW_NUMBER_PROP(crypto_pwhash_OPSLIMIT_MODERATE);
    NEW_NUMBER_PROP(crypto_pwhash_MEMLIMIT_MODERATE);
    NEW_NUMBER_PROP(crypto_pwhash_OPSLIMIT_SENSITIVE);
    NEW_NUMBER_PROP(crypto_pwhash_MEMLIMIT_SENSITIVE);
    NEW_STRING_PROP(crypto_pwhash_PRIMITIVE);

    NEW_INT_PROP(crypto_pwhash_argon2i_ALG_ARGON2I13);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_SALTBYTES);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_STRBYTES);
    NEW_STRING_PROP(crypto_pwhash_argon2i_STRPREFIX);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_OPSLIMIT_MODERATE);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_MEMLIMIT_MODERATE);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE);
}
<commit_msg>return buffer<commit_after>/**
 * Node Native Module for Lib Sodium
 *
 * @Author Pedro Paixao
 * @email paixaop at gmail dot com
 * @License MIT
 */
#include "node_sodium.h"

/* int crypto_pwhash_argon2i(unsigned char * const out,
                          unsigned long long outlen,
                          const char * const passwd,
                          unsigned long long passwdlen,
                          const unsigned char * const salt,
                          unsigned long long opslimit, size_t memlimit,
                          int alg)
*/
NAN_METHOD(bind_crypto_pwhash_argon2i) {
    Nan::EscapableHandleScope scope;

    ARGS(6,"arguments must be: output buffer, password buffer, salt buffer, oLimit, memLimit, algorithm");

    ARG_TO_BUFFER_TYPE(out, unsigned char*);
    ARG_TO_BUFFER_TYPE(passwd, char*);
    ARG_TO_UCHAR_BUFFER_LEN(salt, crypto_pwhash_argon2i_SALTBYTES);
    ARG_TO_NUMBER(oppLimit);
    ARG_TO_NUMBER(memLimit);
    ARG_TO_NUMBER(alg);

    if (crypto_pwhash_argon2i(out, out_size, passwd, passwd_size, salt, oppLimit, memLimit, alg) == 0) {
        return JS_TRUE;
    }

    return JS_NULL;
}

/* int crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES],
                              const char * const passwd,
                              unsigned long long passwdlen,
                              unsigned long long opslimit, size_t memlimit)
*/
NAN_METHOD(bind_crypto_pwhash_argon2i_str) {
    Nan::EscapableHandleScope scope;

    ARGS(3,"arguments must be: password buffer, oLimit, memLimit");

    ARG_TO_BUFFER_TYPE(passwd, char*);
    ARG_TO_NUMBER(oppLimit);
    ARG_TO_NUMBER(memLimit);

    NEW_BUFFER_AND_PTR(buf, crypto_pwhash_argon2i_STRBYTES);

    if (crypto_pwhash_argon2i_str((char*)buf_ptr, passwd, passwd_size, oppLimit, memLimit) == 0) {
        return JS_BUFFER(buf);
    }

    return JS_FALSE;
}

/* int crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYTES],
                                     const char * const passwd,
                                     unsigned long long passwdlen)
*/
NAN_METHOD(bind_crypto_pwhash_argon2i_str_verify) {
    Nan::EscapableHandleScope scope;

    ARGS(2,"arguments must be: pwhash string, password");

    ARG_TO_BUFFER_TYPE(hash, char*);
    ARG_TO_BUFFER_TYPE(passwd, char*);

    if (crypto_pwhash_argon2i_str_verify(hash, passwd, passwd_size) == 0) {
        return JS_TRUE;
    }

    return JS_FALSE;
}

/*
    int crypto_pwhash(unsigned char * const out, unsigned long long outlen,
                  const char * const passwd, unsigned long long passwdlen,
                  const unsigned char * const salt,
                  unsigned long long opslimit, size_t memlimit, int alg)

    Buffer out
    Buffer password
    Buffer salt
    Number oppsLimit
    Number memLimit
    Number algorithm

*/
NAN_METHOD(bind_crypto_pwhash) {
    Nan::EscapableHandleScope scope;

    ARGS(6,"arguments must be: output buffer, password buffer, salt buffer, oLimit, memLimit, algorithm");

    ARG_TO_BUFFER_TYPE(out, unsigned char*);
    ARG_TO_BUFFER_TYPE(passwd, char*);
    ARG_TO_UCHAR_BUFFER_LEN(salt, crypto_pwhash_SALTBYTES);
    ARG_TO_NUMBER(oppLimit);
    ARG_TO_NUMBER(memLimit);
    ARG_TO_NUMBER(alg);

    if (crypto_pwhash(out, out_size, passwd, passwd_size, salt, oppLimit, memLimit, alg) == 0) {
        return JS_TRUE;
    }

    return JS_NULL;
}

/**
 * int crypto_pwhash_str(char out[crypto_pwhash_STRBYTES],
                      const char * const passwd, unsigned long long passwdlen,
                      unsigned long long opslimit, size_t memlimit)

    Buffer out
    Buffer passwd
    Number oppsLimit
    Number memLimit
*/
NAN_METHOD(bind_crypto_pwhash_str) {
    Nan::EscapableHandleScope scope;

    ARGS(3,"arguments must be: password buffer, oLimit, memLimit");

    ARG_TO_BUFFER_TYPE(passwd, char*);
    ARG_TO_NUMBER(oppLimit);
    ARG_TO_NUMBER(memLimit);

    NEW_BUFFER_AND_PTR(out, crypto_pwhash_STRBYTES);

    if (crypto_pwhash_str((char*)out_ptr, passwd, passwd_size, oppLimit, memLimit) == 0) {
        return info.GetReturnValue().Set(out);
    }

    return JS_FALSE;
}

/**
 * int crypto_pwhash_str_verify(const char str[crypto_pwhash_STRBYTES],
                             const char * const passwd,
                             unsigned long long passwdlen)

    Buffer hash String
    Buffer password
 */
NAN_METHOD(bind_crypto_pwhash_str_verify) {
    Nan::EscapableHandleScope scope;

    ARGS(2,"arguments must be: pwhash string, password");

    ARG_TO_UCHAR_BUFFER_LEN(hash, crypto_pwhash_STRBYTES);
    ARG_TO_BUFFER_TYPE(passwd, char*);

    if (crypto_pwhash_str_verify((char*)hash, passwd, passwd_size) == 0) {
        return JS_TRUE;
    }

    return JS_FALSE;
}

/**
 * int crypto_pwhash_scryptsalsa208sha256(unsigned char * const out,
                                       unsigned long long outlen,
                                       const char * const passwd,
                                       unsigned long long passwdlen,
                                       const unsigned char * const salt,
                                       unsigned long long opslimit,
                                       size_t memlimit);

    number out length
    buffer passwd
    buffer salt
    number opslimit
    number memlimit
 */
NAN_METHOD(bind_crypto_pwhash_scryptsalsa208sha256) {
    Nan::EscapableHandleScope scope;

    ARGS(5,"arguments must be: output buffer, password buffer, salt buffer, oLimit, memLimit");

    ARG_TO_BUFFER_TYPE(out, unsigned char*);
    ARG_TO_BUFFER_TYPE(passwd, char*);
    ARG_TO_UCHAR_BUFFER_LEN(salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
    ARG_TO_NUMBER(oppLimit);
    ARG_TO_NUMBER(memLimit);

    if (crypto_pwhash_scryptsalsa208sha256(out, out_size, passwd, passwd_size, salt, oppLimit, memLimit) == 0) {
        return JS_TRUE;
    }

    return JS_FALSE;
}

/**
 * int crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd, size_t passwdlen,
                                          const uint8_t * salt, size_t saltlen,
                                          uint64_t N, uint32_t r, uint32_t p,
                                          uint8_t * buf, size_t buflen);
 * Buffer passwd
 * Buffer salt
 * Number N
 * Number r
 * Number p
 * Buffer scrypt hash output
 */
NAN_METHOD(bind_crypto_pwhash_scryptsalsa208sha256_ll) {
    Nan::EscapableHandleScope scope;

    ARGS(6,"arguments must be: password buffer, salt buffer, N, r, p, output buffer");

    ARG_TO_BUFFER_TYPE(passwd, uint8_t*);
    ARG_TO_BUFFER_TYPE(salt, uint8_t*);
    ARG_TO_NUMBER(N);
    ARG_TO_NUMBER(r);
    ARG_TO_NUMBER(p);
    ARG_TO_BUFFER_TYPE(out, uint8_t*);

    if (crypto_pwhash_scryptsalsa208sha256_ll(passwd, passwd_size, salt, salt_size, N, r, p, out, out_size) == 0) {
        return JS_TRUE;
    }

    return JS_FALSE;
}

/**
  int crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
                                           const char * const passwd,
                                           unsigned long long passwdlen,
                                           unsigned long long opslimit,
                                           size_t memlimit);

 */
NAN_METHOD(bind_crypto_pwhash_scryptsalsa208sha256_str) {
    Nan::EscapableHandleScope scope;

    ARGS(3,"arguments must be: password buffer, oLimit, memLimit");

    ARG_TO_BUFFER_TYPE(passwd, char*);
    ARG_TO_NUMBER(oppLimit);
    ARG_TO_NUMBER(memLimit);

    NEW_BUFFER_AND_PTR(hash, crypto_pwhash_scryptsalsa208sha256_STRBYTES);

    if (crypto_pwhash_scryptsalsa208sha256_str((char*)hash_ptr, passwd, passwd_size, oppLimit, memLimit) == 0) {
        return JS_BUFFER(hash);
    }

    return JS_NULL;
}

/**
 * int crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
                                                  const char * const passwd,
                                                  unsigned long long passwdlen);
 */
NAN_METHOD(bind_crypto_pwhash_scryptsalsa208sha256_str_verify) {
    Nan::EscapableHandleScope scope;

    ARGS(2,"arguments must be: pwhash string, password");

    ARG_TO_UCHAR_BUFFER_LEN(hash, crypto_pwhash_scryptsalsa208sha256_STRBYTES);
    ARG_TO_BUFFER_TYPE(passwd, char*);

    if (crypto_pwhash_scryptsalsa208sha256_str_verify((char*)hash, passwd, passwd_size) == 0) {
        return JS_TRUE;
    }

    return JS_FALSE;
}

/**
 * Register function calls in node binding
 */
void register_crypto_pwhash(Handle<Object> target) {

    // Methods
    NEW_METHOD(crypto_pwhash);
    NEW_METHOD(crypto_pwhash_str);
    NEW_METHOD(crypto_pwhash_str_verify);
    NEW_METHOD(crypto_pwhash_scryptsalsa208sha256);
    NEW_METHOD(crypto_pwhash_scryptsalsa208sha256_ll);
    NEW_METHOD(crypto_pwhash_scryptsalsa208sha256_str);
    NEW_METHOD(crypto_pwhash_scryptsalsa208sha256_str_verify);
    NEW_METHOD(crypto_pwhash_argon2i);
    NEW_METHOD(crypto_pwhash_argon2i_str);
    NEW_METHOD(crypto_pwhash_argon2i_str_verify);

    // Properties
    NEW_NUMBER_PROP(crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE);
    NEW_NUMBER_PROP(crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
    NEW_NUMBER_PROP(crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE);
    NEW_NUMBER_PROP(crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE);
    NEW_INT_PROP(crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
    NEW_INT_PROP(crypto_pwhash_scryptsalsa208sha256_STRBYTES);
    NEW_STRING_PROP(crypto_pwhash_scryptsalsa208sha256_STRPREFIX);

    NEW_NUMBER_PROP(crypto_pwhash_ALG_DEFAULT);
    NEW_NUMBER_PROP(crypto_pwhash_SALTBYTES);
    NEW_NUMBER_PROP(crypto_pwhash_STRBYTES);
    NEW_STRING_PROP(crypto_pwhash_STRPREFIX);
    NEW_NUMBER_PROP(crypto_pwhash_OPSLIMIT_INTERACTIVE);
    NEW_NUMBER_PROP(crypto_pwhash_MEMLIMIT_INTERACTIVE);
    NEW_NUMBER_PROP(crypto_pwhash_OPSLIMIT_MODERATE);
    NEW_NUMBER_PROP(crypto_pwhash_MEMLIMIT_MODERATE);
    NEW_NUMBER_PROP(crypto_pwhash_OPSLIMIT_SENSITIVE);
    NEW_NUMBER_PROP(crypto_pwhash_MEMLIMIT_SENSITIVE);
    NEW_STRING_PROP(crypto_pwhash_PRIMITIVE);

    NEW_INT_PROP(crypto_pwhash_argon2i_ALG_ARGON2I13);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_SALTBYTES);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_STRBYTES);
    NEW_STRING_PROP(crypto_pwhash_argon2i_STRPREFIX);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_OPSLIMIT_MODERATE);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_MEMLIMIT_MODERATE);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE);
    NEW_NUMBER_PROP(crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE);
}
<|endoftext|>