<commit_before>#include "Float16.h"
#include "Error.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/Support/ErrorHandling.h"

using namespace Halide;

// These helper functions are not members of float16_t because
// it would expose the implementation
namespace {
llvm::APFloat::roundingMode
getLLVMAPFRoundingMode(Halide::RoundingMode mode) {
    switch (mode) {
    case RoundingMode::TowardZero:
        return llvm::APFloat::roundingMode::rmTowardZero;
    case RoundingMode::ToNearestTiesToEven:
        return llvm::APFloat::roundingMode::rmNearestTiesToEven;
    case RoundingMode::ToNearestTiesToAway:
        return llvm::APFloat::roundingMode::rmNearestTiesToAway;
    case RoundingMode::TowardPositiveInfinity:
        return llvm::APFloat::roundingMode::rmTowardPositive;
    case RoundingMode::TowardNegativeInfinity:
        return llvm::APFloat::roundingMode::rmTowardNegative;
    default:
        internal_error << "Invalid rounding mode :" << (int)mode << "\n";
    }
    llvm_unreachable("Could not get LLVM rounding mode");
}

float16_t toFP16(llvm::APFloat v) {
    uint64_t bits = v.bitcastToAPInt().getZExtValue();
    internal_assert(bits <= 0xFFFF) << "Invalid bits for float16_t\n";
    return float16_t::make_from_bits(bits);
}

llvm::APFloat toLLVMAPF(float16_t v) {
    llvm::APInt bitRepr(16, (uint64_t)v.to_bits(), /*isSigned=*/false);
    llvm::APFloat repr(llvm::APFloat::IEEEhalf, bitRepr);
    // use assert to avoid cost of conversion in release builds
    assert(v.to_bits() == toFP16(repr).to_bits() && "Converting to APFloat and back failed");
    return repr;
}

template <typename T>
void checkConversion(llvm::APFloat::opStatus status,
                     T value,
                     const char *typeName,
                     llvm::APFloat result) {
    // Check the exceptions
    internal_assert(!(status & llvm::APFloat::opStatus::opInvalidOp)) << "Unexpected invalid op\n";
    internal_assert(!(status & llvm::APFloat::opStatus::opDivByZero)) << "Unexpected div by zero\n";
    if (status & llvm::APFloat::opStatus::opOverflow) {
        user_error << "Converting " << value << " of type " << typeName <<
                   " to float16_t results in overflow (Result \"" << toFP16(result).to_decimal_string() << "\")\n";
    }
    if (status & llvm::APFloat::opStatus::opUnderflow) {
        internal_assert(status & llvm::APFloat::opStatus::opInexact) << "Underflow was flagged but inexact was not\n";
        // We don't emit a warning here because we will emit another warning
        // when handling ``opInexact``. APFloat mimics the default
        // exception handling behaviour for underflow in IEEE754 (7.5 Underflow)
        // where a flag is only raised if the result is inexact.
    }

    if (status & llvm::APFloat::opStatus::opInexact) {
        user_warning << "Converting " << value << " of type " << typeName <<
                     " to float16_t cannot be done exactly (Result \"" <<
                     toFP16(result).to_hex_string() <<
                     "\" which is approximately \"" <<
                     toFP16(result).to_decimal_string() << "\" in decimal)\n";
    }
}

template <typename T>
uint16_t getBitsFrom(T value, RoundingMode roundingMode, const char *typeName) {
    llvm::APFloat convertedValue(value);
    bool losesInfo = false;
    llvm::APFloat::opStatus status = convertedValue.convert(
        llvm::APFloat::IEEEhalf,
        getLLVMAPFRoundingMode(roundingMode),
        &losesInfo);
    checkConversion(status, value, typeName, convertedValue);
    return toFP16(convertedValue).to_bits();
}

template <>
uint16_t getBitsFrom(const char *value, RoundingMode roundingMode, const char *typeName) {
    llvm::APFloat convertedValue(llvm::APFloat::IEEEhalf);
    // TODO: Sanitize value
    llvm::APFloat::opStatus status = convertedValue.convertFromString(value,
        getLLVMAPFRoundingMode(roundingMode));

    checkConversion(status, value, typeName, convertedValue);
    return toFP16(convertedValue).to_bits();
}

template <>
uint16_t getBitsFrom(int64_t value, RoundingMode roundingMode, const char *typeName) {
    llvm::APFloat convertedValue(llvm::APFloat::IEEEhalf);
    llvm::integerPart asIP = value;
    llvm::APFloat::opStatus status = convertedValue.convertFromSignExtendedInteger(
        &asIP,
        /*srcCount=*/1, // All bits are contained within a single int64_t
        /*isSigned=*/true,
        getLLVMAPFRoundingMode(roundingMode));
    checkConversion(status, value, typeName, convertedValue);
    return toFP16(convertedValue).to_bits();
}

}  //end anonymous namespace
// End helper functions

namespace Halide {
// The static_asserts checking the size is to make sure
// float16_t can be used as a 16-bits wide POD type.
float16_t::float16_t(float value, RoundingMode roundingMode) {
    static_assert(sizeof(float16_t) == 2, "float16_t is wrong size");
    this->data = getBitsFrom(value, roundingMode, "float");
}

float16_t::float16_t(double value, RoundingMode roundingMode) {
    static_assert(sizeof(float16_t) == 2, "float16_t is wrong size");
    this->data = getBitsFrom(value, roundingMode, "double");
}

float16_t::float16_t(const char *stringRepr, RoundingMode roundingMode) {
    static_assert(sizeof(float16_t) == 2, "float16_t is wrong size");
    this->data = getBitsFrom(stringRepr, roundingMode, "string");
}

float16_t::float16_t() {
    static_assert(sizeof(float16_t) == 2, "float16_t is wrong size");
    this->data = 0;
}

float16_t float16_t::make_from_signed_int(int64_t value, RoundingMode roundingMode) {
    static_assert(sizeof(float16_t) == 2, "float16_t is wrong size");
    float16_t val;
    val.data = getBitsFrom(value, roundingMode, "int64_t");
    return val;
}

float16_t float16_t::make_from_bits(uint16_t rawBits) {
    static_assert(sizeof(float16_t) == 2, "float16_t is wrong size");
    float16_t val;
    val.data = rawBits;
    return val;
}

float16_t::operator float() const {
    llvm::APFloat convertedValue = toLLVMAPF(*this);
    bool losesInfo = false;
    // Converting to a more precise type so the rounding mode does not matter, so
    // just pick any.
    convertedValue.convert(llvm::APFloat::IEEEsingle, llvm::APFloat::rmNearestTiesToEven, &losesInfo);
    internal_assert(!losesInfo) << "Unexpected information loss\n";
    return convertedValue.convertToFloat();
}

float16_t::operator double() const {
    llvm::APFloat convertedValue = toLLVMAPF(*this);
    bool losesInfo = false;
    // Converting to a more precise type so the rounding mode does not matter, so
    // just pick any.
    convertedValue.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven, &losesInfo);
    internal_assert(!losesInfo) << "Unexpected information loss\n";
    return convertedValue.convertToDouble();
}

float16_t float16_t::make_zero(bool positive) {
    llvm::APFloat zero = llvm::APFloat::getZero(llvm::APFloat::IEEEhalf, !positive);
    return toFP16(zero);
}

float16_t float16_t::make_infinity(bool positive) {
    llvm::APFloat inf = llvm::APFloat::getInf(llvm::APFloat::IEEEhalf, !positive);
    return toFP16(inf);
}

float16_t float16_t::make_nan() {
    llvm::APFloat nan = llvm::APFloat::getNaN(llvm::APFloat::IEEEhalf);
    return toFP16(nan);
}

float16_t float16_t::add(float16_t rhs, RoundingMode roundingMode) const {
    llvm::APFloat result = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    // FIXME: Ignoring possible exceptions
    result.add(rhsAPF, getLLVMAPFRoundingMode(roundingMode));
    return toFP16(result);
}

float16_t float16_t::subtract(float16_t rhs, RoundingMode roundingMode) const {
    llvm::APFloat result = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    // FIXME: Ignoring possible exceptions
    result.subtract(rhsAPF, getLLVMAPFRoundingMode(roundingMode));
    return toFP16(result);
}

float16_t float16_t::multiply(float16_t rhs, RoundingMode roundingMode) const {
    llvm::APFloat result = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    // FIXME: Ignoring possible exceptions
    result.multiply(rhsAPF, getLLVMAPFRoundingMode(roundingMode));
    return toFP16(result);
}

float16_t float16_t::divide(float16_t denominator, RoundingMode roundingMode) const {
    llvm::APFloat result = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(denominator);
    // FIXME: Ignoring possible exceptions
    result.divide(rhsAPF, getLLVMAPFRoundingMode(roundingMode));
    return toFP16(result);
}

float16_t float16_t::remainder(float16_t denominator) const {
    llvm::APFloat result = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(denominator);
    // FIXME: Ignoring possible exceptions
    result.remainder(rhsAPF);
    return toFP16(result);
}

float16_t float16_t::mod(float16_t denominator, RoundingMode roundingMode) const {
    llvm::APFloat result = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(denominator);
    // FIXME: Ignoring possible exceptions
    result.mod(rhsAPF, getLLVMAPFRoundingMode(roundingMode));
    return toFP16(result);
}

float16_t float16_t::operator-() const {
    llvm::APFloat result = toLLVMAPF(*this);
    result.changeSign();
    return toFP16(result);
}

float16_t float16_t::operator+(float16_t rhs) const {
    return this->add(rhs, RoundingMode::ToNearestTiesToEven);
}

float16_t float16_t::operator-(float16_t rhs) const {
    return this->subtract(rhs, RoundingMode::ToNearestTiesToEven);
}

float16_t float16_t::operator*(float16_t rhs) const {
    return this->multiply(rhs, RoundingMode::ToNearestTiesToEven);
}

float16_t float16_t::operator/(float16_t rhs) const {
    return this->divide(rhs, RoundingMode::ToNearestTiesToEven);
}

bool float16_t::operator==(float16_t rhs) const {
    llvm::APFloat lhsAPF = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    return lhsAPF.compare(rhsAPF) == llvm::APFloat::cmpEqual;
}

std::string float16_t::to_hex_string() const {
    // Expected format of result: [-]0xh.hhhp[+-]dd
    // at most 12 characters are needed for half precision
    // + 1 for null terminator
    char buffer[13];
    llvm::APFloat repr = toLLVMAPF(*this);
    // The rounding mode does not matter here when we set hexDigits to 0 which
    // will give the precise representation. So any rounding mode will do.
    unsigned count = repr.convertToHexString(buffer,
                                             /*hexDigits=*/0,
                                             /*upperCase=*/false,
                                             llvm::APFloat::rmNearestTiesToEven);
    internal_assert(count < sizeof(buffer) / sizeof(char)) << "Incorrect buffer size\n";
    std::string result(buffer);
    return result;
}

bool float16_t::operator>(float16_t rhs) const {
    internal_assert(!this->are_unordered(rhs)) << "Cannot compare unorderable values\n";
    llvm::APFloat lhsAPF = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    return lhsAPF.compare(rhsAPF) == llvm::APFloat::cmpGreaterThan;
}

bool float16_t::operator<(float16_t rhs) const {
    internal_assert(!this->are_unordered(rhs)) << "Cannot compare unorderable values\n";
    llvm::APFloat lhsAPF = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    return lhsAPF.compare(rhsAPF) == llvm::APFloat::cmpLessThan;
}

bool float16_t::are_unordered(float16_t rhs) const {
    llvm::APFloat lhsAPF = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    return lhsAPF.compare(rhsAPF) == llvm::APFloat::cmpUnordered;
}

std::string float16_t::to_decimal_string(unsigned int significantDigits) const {
    llvm::APFloat repr = toLLVMAPF(*this);
    llvm::SmallVector<char, 16> result;
    repr.toString(result, /*FormatPrecision=*/significantDigits, /*FormatMaxPadding=*/0);
    return std::string(result.begin(), result.end());
}

bool float16_t::is_nan() const {
    llvm::APFloat repr = toLLVMAPF(*this);
    return repr.isNaN();
}

bool float16_t::is_infinity() const {
    llvm::APFloat repr = toLLVMAPF(*this);
    return repr.isInfinity();
}

bool float16_t::is_negative() const {
    llvm::APFloat repr = toLLVMAPF(*this);
    return repr.isNegative();
}

bool float16_t::is_zero() const {
    llvm::APFloat repr = toLLVMAPF(*this);
    return repr.isZero();
}

uint16_t float16_t::to_bits() const {
    return this->data;
}

}  // namespace halide
<commit_msg>Track llvm removing rounding mode from mod operator in APFloat.h.<commit_after>#include "Float16.h"
#include "Error.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/Support/ErrorHandling.h"

using namespace Halide;

// These helper functions are not members of float16_t because
// it would expose the implementation
namespace {
llvm::APFloat::roundingMode
getLLVMAPFRoundingMode(Halide::RoundingMode mode) {
    switch (mode) {
    case RoundingMode::TowardZero:
        return llvm::APFloat::roundingMode::rmTowardZero;
    case RoundingMode::ToNearestTiesToEven:
        return llvm::APFloat::roundingMode::rmNearestTiesToEven;
    case RoundingMode::ToNearestTiesToAway:
        return llvm::APFloat::roundingMode::rmNearestTiesToAway;
    case RoundingMode::TowardPositiveInfinity:
        return llvm::APFloat::roundingMode::rmTowardPositive;
    case RoundingMode::TowardNegativeInfinity:
        return llvm::APFloat::roundingMode::rmTowardNegative;
    default:
        internal_error << "Invalid rounding mode :" << (int)mode << "\n";
    }
    llvm_unreachable("Could not get LLVM rounding mode");
}

float16_t toFP16(llvm::APFloat v) {
    uint64_t bits = v.bitcastToAPInt().getZExtValue();
    internal_assert(bits <= 0xFFFF) << "Invalid bits for float16_t\n";
    return float16_t::make_from_bits(bits);
}

llvm::APFloat toLLVMAPF(float16_t v) {
    llvm::APInt bitRepr(16, (uint64_t)v.to_bits(), /*isSigned=*/false);
    llvm::APFloat repr(llvm::APFloat::IEEEhalf, bitRepr);
    // use assert to avoid cost of conversion in release builds
    assert(v.to_bits() == toFP16(repr).to_bits() && "Converting to APFloat and back failed");
    return repr;
}

template <typename T>
void checkConversion(llvm::APFloat::opStatus status,
                     T value,
                     const char *typeName,
                     llvm::APFloat result) {
    // Check the exceptions
    internal_assert(!(status & llvm::APFloat::opStatus::opInvalidOp)) << "Unexpected invalid op\n";
    internal_assert(!(status & llvm::APFloat::opStatus::opDivByZero)) << "Unexpected div by zero\n";
    if (status & llvm::APFloat::opStatus::opOverflow) {
        user_error << "Converting " << value << " of type " << typeName <<
                   " to float16_t results in overflow (Result \"" << toFP16(result).to_decimal_string() << "\")\n";
    }
    if (status & llvm::APFloat::opStatus::opUnderflow) {
        internal_assert(status & llvm::APFloat::opStatus::opInexact) << "Underflow was flagged but inexact was not\n";
        // We don't emit a warning here because we will emit another warning
        // when handling ``opInexact``. APFloat mimics the default
        // exception handling behaviour for underflow in IEEE754 (7.5 Underflow)
        // where a flag is only raised if the result is inexact.
    }

    if (status & llvm::APFloat::opStatus::opInexact) {
        user_warning << "Converting " << value << " of type " << typeName <<
                     " to float16_t cannot be done exactly (Result \"" <<
                     toFP16(result).to_hex_string() <<
                     "\" which is approximately \"" <<
                     toFP16(result).to_decimal_string() << "\" in decimal)\n";
    }
}

template <typename T>
uint16_t getBitsFrom(T value, RoundingMode roundingMode, const char *typeName) {
    llvm::APFloat convertedValue(value);
    bool losesInfo = false;
    llvm::APFloat::opStatus status = convertedValue.convert(
        llvm::APFloat::IEEEhalf,
        getLLVMAPFRoundingMode(roundingMode),
        &losesInfo);
    checkConversion(status, value, typeName, convertedValue);
    return toFP16(convertedValue).to_bits();
}

template <>
uint16_t getBitsFrom(const char *value, RoundingMode roundingMode, const char *typeName) {
    llvm::APFloat convertedValue(llvm::APFloat::IEEEhalf);
    // TODO: Sanitize value
    llvm::APFloat::opStatus status = convertedValue.convertFromString(value,
        getLLVMAPFRoundingMode(roundingMode));

    checkConversion(status, value, typeName, convertedValue);
    return toFP16(convertedValue).to_bits();
}

template <>
uint16_t getBitsFrom(int64_t value, RoundingMode roundingMode, const char *typeName) {
    llvm::APFloat convertedValue(llvm::APFloat::IEEEhalf);
    llvm::integerPart asIP = value;
    llvm::APFloat::opStatus status = convertedValue.convertFromSignExtendedInteger(
        &asIP,
        /*srcCount=*/1, // All bits are contained within a single int64_t
        /*isSigned=*/true,
        getLLVMAPFRoundingMode(roundingMode));
    checkConversion(status, value, typeName, convertedValue);
    return toFP16(convertedValue).to_bits();
}

}  //end anonymous namespace
// End helper functions

namespace Halide {
// The static_asserts checking the size is to make sure
// float16_t can be used as a 16-bits wide POD type.
float16_t::float16_t(float value, RoundingMode roundingMode) {
    static_assert(sizeof(float16_t) == 2, "float16_t is wrong size");
    this->data = getBitsFrom(value, roundingMode, "float");
}

float16_t::float16_t(double value, RoundingMode roundingMode) {
    static_assert(sizeof(float16_t) == 2, "float16_t is wrong size");
    this->data = getBitsFrom(value, roundingMode, "double");
}

float16_t::float16_t(const char *stringRepr, RoundingMode roundingMode) {
    static_assert(sizeof(float16_t) == 2, "float16_t is wrong size");
    this->data = getBitsFrom(stringRepr, roundingMode, "string");
}

float16_t::float16_t() {
    static_assert(sizeof(float16_t) == 2, "float16_t is wrong size");
    this->data = 0;
}

float16_t float16_t::make_from_signed_int(int64_t value, RoundingMode roundingMode) {
    static_assert(sizeof(float16_t) == 2, "float16_t is wrong size");
    float16_t val;
    val.data = getBitsFrom(value, roundingMode, "int64_t");
    return val;
}

float16_t float16_t::make_from_bits(uint16_t rawBits) {
    static_assert(sizeof(float16_t) == 2, "float16_t is wrong size");
    float16_t val;
    val.data = rawBits;
    return val;
}

float16_t::operator float() const {
    llvm::APFloat convertedValue = toLLVMAPF(*this);
    bool losesInfo = false;
    // Converting to a more precise type so the rounding mode does not matter, so
    // just pick any.
    convertedValue.convert(llvm::APFloat::IEEEsingle, llvm::APFloat::rmNearestTiesToEven, &losesInfo);
    internal_assert(!losesInfo) << "Unexpected information loss\n";
    return convertedValue.convertToFloat();
}

float16_t::operator double() const {
    llvm::APFloat convertedValue = toLLVMAPF(*this);
    bool losesInfo = false;
    // Converting to a more precise type so the rounding mode does not matter, so
    // just pick any.
    convertedValue.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven, &losesInfo);
    internal_assert(!losesInfo) << "Unexpected information loss\n";
    return convertedValue.convertToDouble();
}

float16_t float16_t::make_zero(bool positive) {
    llvm::APFloat zero = llvm::APFloat::getZero(llvm::APFloat::IEEEhalf, !positive);
    return toFP16(zero);
}

float16_t float16_t::make_infinity(bool positive) {
    llvm::APFloat inf = llvm::APFloat::getInf(llvm::APFloat::IEEEhalf, !positive);
    return toFP16(inf);
}

float16_t float16_t::make_nan() {
    llvm::APFloat nan = llvm::APFloat::getNaN(llvm::APFloat::IEEEhalf);
    return toFP16(nan);
}

float16_t float16_t::add(float16_t rhs, RoundingMode roundingMode) const {
    llvm::APFloat result = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    // FIXME: Ignoring possible exceptions
    result.add(rhsAPF, getLLVMAPFRoundingMode(roundingMode));
    return toFP16(result);
}

float16_t float16_t::subtract(float16_t rhs, RoundingMode roundingMode) const {
    llvm::APFloat result = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    // FIXME: Ignoring possible exceptions
    result.subtract(rhsAPF, getLLVMAPFRoundingMode(roundingMode));
    return toFP16(result);
}

float16_t float16_t::multiply(float16_t rhs, RoundingMode roundingMode) const {
    llvm::APFloat result = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    // FIXME: Ignoring possible exceptions
    result.multiply(rhsAPF, getLLVMAPFRoundingMode(roundingMode));
    return toFP16(result);
}

float16_t float16_t::divide(float16_t denominator, RoundingMode roundingMode) const {
    llvm::APFloat result = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(denominator);
    // FIXME: Ignoring possible exceptions
    result.divide(rhsAPF, getLLVMAPFRoundingMode(roundingMode));
    return toFP16(result);
}

float16_t float16_t::remainder(float16_t denominator) const {
    llvm::APFloat result = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(denominator);
    // FIXME: Ignoring possible exceptions
    result.remainder(rhsAPF);
    return toFP16(result);
}

float16_t float16_t::mod(float16_t denominator, RoundingMode roundingMode) const {
    llvm::APFloat result = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(denominator);
    // FIXME: Ignoring possible exceptions
    // LLVM removed the rounding mode as the operation is always exact.
    // TODO: change float16_t::mod to no take a rounding mode.
    #if LLVM_VERSION < 38
    result.mod(rhsAPF, getLLVMAPFRoundingMode(roundingMode));
    #else
    result.mod(rhsAPF);
    #endif
    return toFP16(result);
}

float16_t float16_t::operator-() const {
    llvm::APFloat result = toLLVMAPF(*this);
    result.changeSign();
    return toFP16(result);
}

float16_t float16_t::operator+(float16_t rhs) const {
    return this->add(rhs, RoundingMode::ToNearestTiesToEven);
}

float16_t float16_t::operator-(float16_t rhs) const {
    return this->subtract(rhs, RoundingMode::ToNearestTiesToEven);
}

float16_t float16_t::operator*(float16_t rhs) const {
    return this->multiply(rhs, RoundingMode::ToNearestTiesToEven);
}

float16_t float16_t::operator/(float16_t rhs) const {
    return this->divide(rhs, RoundingMode::ToNearestTiesToEven);
}

bool float16_t::operator==(float16_t rhs) const {
    llvm::APFloat lhsAPF = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    return lhsAPF.compare(rhsAPF) == llvm::APFloat::cmpEqual;
}

std::string float16_t::to_hex_string() const {
    // Expected format of result: [-]0xh.hhhp[+-]dd
    // at most 12 characters are needed for half precision
    // + 1 for null terminator
    char buffer[13];
    llvm::APFloat repr = toLLVMAPF(*this);
    // The rounding mode does not matter here when we set hexDigits to 0 which
    // will give the precise representation. So any rounding mode will do.
    unsigned count = repr.convertToHexString(buffer,
                                             /*hexDigits=*/0,
                                             /*upperCase=*/false,
                                             llvm::APFloat::rmNearestTiesToEven);
    internal_assert(count < sizeof(buffer) / sizeof(char)) << "Incorrect buffer size\n";
    std::string result(buffer);
    return result;
}

bool float16_t::operator>(float16_t rhs) const {
    internal_assert(!this->are_unordered(rhs)) << "Cannot compare unorderable values\n";
    llvm::APFloat lhsAPF = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    return lhsAPF.compare(rhsAPF) == llvm::APFloat::cmpGreaterThan;
}

bool float16_t::operator<(float16_t rhs) const {
    internal_assert(!this->are_unordered(rhs)) << "Cannot compare unorderable values\n";
    llvm::APFloat lhsAPF = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    return lhsAPF.compare(rhsAPF) == llvm::APFloat::cmpLessThan;
}

bool float16_t::are_unordered(float16_t rhs) const {
    llvm::APFloat lhsAPF = toLLVMAPF(*this);
    llvm::APFloat rhsAPF = toLLVMAPF(rhs);
    return lhsAPF.compare(rhsAPF) == llvm::APFloat::cmpUnordered;
}

std::string float16_t::to_decimal_string(unsigned int significantDigits) const {
    llvm::APFloat repr = toLLVMAPF(*this);
    llvm::SmallVector<char, 16> result;
    repr.toString(result, /*FormatPrecision=*/significantDigits, /*FormatMaxPadding=*/0);
    return std::string(result.begin(), result.end());
}

bool float16_t::is_nan() const {
    llvm::APFloat repr = toLLVMAPF(*this);
    return repr.isNaN();
}

bool float16_t::is_infinity() const {
    llvm::APFloat repr = toLLVMAPF(*this);
    return repr.isInfinity();
}

bool float16_t::is_negative() const {
    llvm::APFloat repr = toLLVMAPF(*this);
    return repr.isNegative();
}

bool float16_t::is_zero() const {
    llvm::APFloat repr = toLLVMAPF(*this);
    return repr.isZero();
}

uint16_t float16_t::to_bits() const {
    return this->data;
}

}  // namespace halide
<|endoftext|>


<commit_before>#include <stan/math/prim.hpp>
#include <gtest/gtest.h>
#include <vector>

TEST(MathFunctionsPoissonBinomialLogProbs, check_scalar_y) {
  using stan::math::poisson_binomial_log_probs;
  using vec = Eigen::Matrix<double, Eigen::Dynamic, 1>;

  vec p(3, 1);
  p << 0.5, 0.2, 0.7;
  std::vector<double> vals{-2.12026, -0.84397, -0.967584, -2.65926};

  for (int i = 0; i < 4; i++) {
    auto x = poisson_binomial_log_probs(i, p);
    EXPECT_TRUE(x.rows() == i + 1);
    EXPECT_TRUE(x.cols() == 1);
    for (int j = 0; j <= i; ++j) {
      EXPECT_NEAR(vals[j], x(j), 0.001);
    }
  }
}

TEST(MathFunctionsPoissonBinomialLogProbs, check_vectorial_y) {
  using stan::math::poisson_binomial_log_probs;
  using vec = Eigen::Matrix<double, Eigen::Dynamic, 1>;

  vec p(3, 1);
  p << 0.5, 0.2, 0.7;
  std::vector<int> y{0, 1};
  auto x = poisson_binomial_log_probs(y, p);

  EXPECT_TRUE(x.size() == 2);
  EXPECT_TRUE(x[0].rows() == 1);
  EXPECT_TRUE(x[0].cols() == 1);
  EXPECT_TRUE(x[1].rows() == 2);
  EXPECT_TRUE(x[1].cols() == 1);
}

TEST(MathFunctionsPoissonBinomialLogProbs, check_vectorial_y_vectorial_theta) {
  using stan::math::poisson_binomial_log_probs;
  using vec = Eigen::Matrix<double, Eigen::Dynamic, 1>;

  vec p(3, 1);
  p << 0.5, 0.2, 0.7;
  std::vector<int> y{0, 1};
  std::vector<vec> ps{p, p};
  auto x = poisson_binomial_log_probs(y, ps);

  EXPECT_TRUE(x.size() == 2);
  EXPECT_TRUE(x[0].rows() == 1);
  EXPECT_TRUE(x[0].cols() == 1);
  EXPECT_TRUE(x[1].rows() == 2);
  EXPECT_TRUE(x[1].cols() == 1);
}<commit_msg>Cppling of log_prob tests<commit_after>#include <stan/math/prim.hpp>
#include <gtest/gtest.h>
#include <vector>

TEST(MathFunctionsPoissonBinomialLogProbs, check_scalar_y) {
  using stan::math::poisson_binomial_log_probs;
  using vec = Eigen::Matrix<double, Eigen::Dynamic, 1>;

  vec p(3, 1);
  p << 0.5, 0.2, 0.7;
  std::vector<double> vals{-2.12026, -0.84397, -0.967584, -2.65926};

  for (int i = 0; i < 4; i++) {
    auto x = poisson_binomial_log_probs(i, p);
    EXPECT_EQ(x.rows(), i + 1);
    EXPECT_EQ(x.cols(), 1);
    for (int j = 0; j <= i; ++j) {
      EXPECT_NEAR(vals[j], x(j), 0.001);
    }
  }
}

TEST(MathFunctionsPoissonBinomialLogProbs, check_vectorial_y) {
  using stan::math::poisson_binomial_log_probs;
  using vec = Eigen::Matrix<double, Eigen::Dynamic, 1>;

  vec p(3, 1);
  p << 0.5, 0.2, 0.7;
  std::vector<int> y{0, 1};
  auto x = poisson_binomial_log_probs(y, p);

  EXPECT_EQ(x.size(), 2);
  EXPECT_EQ(x[0].rows(), 1);
  EXPECT_EQ(x[0].cols(), 1);
  EXPECT_EQ(x[1].rows(), 2);
  EXPECT_EQ(x[1].cols(), 1);
}

TEST(MathFunctionsPoissonBinomialLogProbs, check_vectorial_y_vectorial_theta) {
  using stan::math::poisson_binomial_log_probs;
  using vec = Eigen::Matrix<double, Eigen::Dynamic, 1>;

  vec p(3, 1);
  p << 0.5, 0.2, 0.7;
  std::vector<int> y{0, 1};
  std::vector<vec> ps{p, p};
  auto x = poisson_binomial_log_probs(y, ps);

  EXPECT_EQ(x.size(), 2);
  EXPECT_EQ(x[0].rows(), 1);
  EXPECT_EQ(x[0].cols(), 1);
  EXPECT_EQ(x[1].rows(), 2);
  EXPECT_EQ(x[1].cols(), 1);
}<|endoftext|>


<commit_before>#include <wx/wxprec.h>
#ifndef WX_PRECOMP
    #include <wx/wx.h>
    #include <wx/display.h>
    #include <wx/filefn.h>
    #include <wx/dir.h>
#endif
#include <string>

#include "MainFrame.hpp"
#include "GUI.hpp"
#include "misc_ui.hpp"
#include "Settings.hpp"
#include "Preset.hpp"

// Logging mechanism
#include "Log.hpp"

namespace Slic3r { namespace GUI {

/// Primary initialization and point of entry into the GUI application.
/// Calls MainFrame and handles preset loading, etc.
bool App::OnInit()
{
    this->SetAppName("Slic3r");
    this->notifier = std::unique_ptr<Notifier>();

    datadir = decode_path(wxStandardPaths::Get().GetUserDataDir());
    wxString enc_datadir = encode_path(datadir);

    const wxString& slic3r_ini  {datadir + "/slic3r.ini"};
    this->preset_ini[static_cast<int>(preset_t::Print)] = {datadir + "/print"};
    this->preset_ini[static_cast<int>(preset_t::Printer)] = {datadir + "/printer"};
    this->preset_ini[static_cast<int>(preset_t::Material)] = {datadir + "/filament"};
    const wxString& print_ini = this->preset_ini[static_cast<int>(preset_t::Print)];
    const wxString& printer_ini = this->preset_ini[static_cast<int>(preset_t::Printer)];
    const wxString& material_ini = this->preset_ini[static_cast<int>(preset_t::Material)];

    // if we don't have a datadir or a slic3r.ini, prompt for wizard.
    bool run_wizard = (wxDirExists(datadir) && wxFileExists(slic3r_ini));

    /* Check to make sure if datadir exists */
    for (auto& dir : std::vector<wxString> { enc_datadir, print_ini, printer_ini, material_ini }) {
        if (wxDirExists(dir)) continue;
        if (!wxMkdir(dir)) {
            Slic3r::Log::fatal_error(LogChannel, (_("Slic3r was unable to create its data directory at ")+ dir).ToStdWstring());
        }
    }

    Slic3r::Log::info(LogChannel, (_("Data dir: ") + datadir).ToStdWstring());

    ui_settings = Settings::init_settings();

    // Load gui settings from slic3r.ini
    if (wxFileExists(slic3r_ini)) {
    /*
        my $ini = eval { Slic3r::Config->read_ini("$datadir/slic3r.ini") };
        if ($ini) {
            $last_version = $ini->{_}{version};
            $ini->{_}{$_} = $Settings->{_}{$_}
                for grep !exists $ini->{_}{$_}, keys %{$Settings->{_}};
            $Settings = $ini;
        }
        delete $Settings->{_}{mode};  # handle legacy
    */
    }

    ui_settings->save_settings();

    // Load presets
    this->load_presets();

    wxImage::AddHandler(new wxPNGHandler());
    MainFrame *frame = new MainFrame( "Slic3r", wxDefaultPosition, wxDefaultSize);
    this->SetTopWindow(frame);

    // Load init bundle
    //

    // Run the wizard if we don't have an initial config
    /*
    $self->check_version
        if $self->have_version_check
            && ($Settings->{_}{version_check} // 1)
            && (!$Settings->{_}{last_version_check} || (time - $Settings->{_}{last_version_check}) >= 86400);
    */

    // run callback functions during idle on the main frame
    this->Bind(wxEVT_IDLE,
        [this](wxIdleEvent& e) {
            std::function<void()> func {nullptr}; //
            // try to get the mutex. If we can't, just skip this idle event and get the next one.
            if (!this->callback_register.try_lock()) return;
            // pop callback
            if (cb.size() >= 1) {
                func = cb.top();
                cb.pop();
            }
            // unlock mutex
            this->callback_register.unlock();
            try { // call the function if it's not nullptr;
                if (func != nullptr) func();
            } catch (std::exception& e) { Slic3r::Log::error(LogChannel, LOG_WSTRING("Exception thrown: " <<  e.what())); }
        });
    /*
    EVT_IDLE($frame, sub {
        while (my $cb = shift @cb) {
            $cb->();
        }
    });
    */

    // Handle custom version check event
    /*
    EVT_COMMAND($self, -1, $VERSION_CHECK_EVENT, sub {
        my ($self, $event) = @_;
        my ($success, $response, $manual_check) = @{$event->GetData};

        if ($success) {
            if ($response =~ /^obsolete ?= ?([a-z0-9.-]+,)*\Q$Slic3r::VERSION\E(?:,|$)/) {
                my $res = Wx::MessageDialog->new(undef, "A new version is available. Do you want to open the Slic3r website now?",
                    'Update', wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_INFORMATION | wxICON_ERROR)->ShowModal;
                Wx::LaunchDefaultBrowser('http://slic3r.org/') if $res == wxID_YES;
            } else {
                Slic3r::GUI::show_info(undef, "You're using the latest version. No updates are available.") if $manual_check;
            }
            $Settings->{_}{last_version_check} = time();
            $self->save_settings;
        } else {
            Slic3r::GUI::show_error(undef, "Failed to check for updates. Try later.") if $manual_check;
        }
    });
    */

    return true;
}

void App::save_window_pos(const wxTopLevelWindow* window, const wxString& name ) {
    ui_settings->window_pos[name] =
        std::make_tuple<wxPoint, wxSize, bool>(
            window->GetScreenPosition(),
            window->GetSize(),
            window->IsMaximized());

    ui_settings->save_settings();
}

void App::restore_window_pos(wxTopLevelWindow* window, const wxString& name ) {
    try {
        auto tmp = ui_settings->window_pos[name];
        const auto& size = std::get<1>(tmp);
        const auto& pos = std::get<0>(tmp);
        window->SetSize(size);

        auto display = wxDisplay().GetClientArea();
        if (((pos.x + size.x / 2) < display.GetRight()) && (pos.y + size.y/2 < display.GetBottom()))
            window->Move(pos);

        window->Maximize(std::get<2>(tmp));
    }
    catch (std::out_of_range& e) {
        // config was empty
    }
}

void App::load_presets() {
    for (size_t group = 0; group < preset_types; ++group) {
        Presets& preset_list = this->presets.at(group);
        wxString& ini = this->preset_ini.at(group);
        // keep external or dirty presets
        preset_list.erase(std::remove_if(preset_list.begin(), preset_list.end(),
                    [](const Preset& t) -> bool { return (t.external && t.file_exists()) || t.dirty(); }),
                preset_list.end());
        if (wxDirExists(ini)) {
            auto sink { wxDirTraverserSimple() };
            sink.file_cb = ([&preset_list, group] (const wxString& filename) {

                    // skip if we already have it
                    if (std::find_if(preset_list.begin(), preset_list.end(),
                            [filename] (const Preset& t)
                                { return filename.ToStdString() == t.name; }) != preset_list.end()) return;
                    wxString path, name, ext;
                    wxFileName::SplitPath(filename, &path, &name, &ext);

                    preset_list.push_back(Preset(path.ToStdString(), (name + ext).ToStdString(), static_cast<preset_t>(group)));
                    });

            wxDir dir(ini);
            dir.Traverse(sink, "*.ini");

            // Sort the list by name
            std::sort(preset_list.begin(), preset_list.end(), [] (const Preset& x, const Preset& y) -> bool { return x.name < y.name; });

            // Prepend default Preset
            preset_list.emplace(preset_list.begin(), Preset(true, "- default -"s, static_cast<preset_t>(group)));
        }

    }
}

void App::CallAfter(std::function<void()> cb_function) {
    // set mutex
    this->callback_register.lock();
    // push function onto stack
    this->cb.emplace(cb_function);
    // unset mutex
    this->callback_register.unlock();
}

void App::OnUnhandledException() {
    try { throw; }
    catch (std::exception &e) {
        Slic3r::Log::fatal_error(LogChannel, LOG_WSTRING("Exception Caught: " << e.what()));
    }
}

}} // namespace Slic3r::GUI
<commit_msg>Fix adding presets to master preset list.<commit_after>#include <wx/wxprec.h>
#ifndef WX_PRECOMP
    #include <wx/wx.h>
    #include <wx/display.h>
    #include <wx/filefn.h>
    #include <wx/dir.h>
#endif
#include <string>

#include "MainFrame.hpp"
#include "GUI.hpp"
#include "misc_ui.hpp"
#include "Settings.hpp"
#include "Preset.hpp"

// Logging mechanism
#include "Log.hpp"

namespace Slic3r { namespace GUI {

/// Primary initialization and point of entry into the GUI application.
/// Calls MainFrame and handles preset loading, etc.
bool App::OnInit()
{
    this->SetAppName("Slic3r");
    this->notifier = std::unique_ptr<Notifier>();

    datadir = decode_path(wxStandardPaths::Get().GetUserDataDir());
    wxString enc_datadir = encode_path(datadir);

    const wxString& slic3r_ini  {datadir + "/slic3r.ini"};
    this->preset_ini[static_cast<int>(preset_t::Print)] = {datadir + "/print"};
    this->preset_ini[static_cast<int>(preset_t::Printer)] = {datadir + "/printer"};
    this->preset_ini[static_cast<int>(preset_t::Material)] = {datadir + "/filament"};
    const wxString& print_ini = this->preset_ini[static_cast<int>(preset_t::Print)];
    const wxString& printer_ini = this->preset_ini[static_cast<int>(preset_t::Printer)];
    const wxString& material_ini = this->preset_ini[static_cast<int>(preset_t::Material)];

    // if we don't have a datadir or a slic3r.ini, prompt for wizard.
    bool run_wizard = (wxDirExists(datadir) && wxFileExists(slic3r_ini));

    /* Check to make sure if datadir exists */
    for (auto& dir : std::vector<wxString> { enc_datadir, print_ini, printer_ini, material_ini }) {
        if (wxDirExists(dir)) continue;
        if (!wxMkdir(dir)) {
            Slic3r::Log::fatal_error(LogChannel, (_("Slic3r was unable to create its data directory at ")+ dir).ToStdWstring());
        }
    }

    Slic3r::Log::info(LogChannel, (_("Data dir: ") + datadir).ToStdWstring());

    ui_settings = Settings::init_settings();

    // Load gui settings from slic3r.ini
    if (wxFileExists(slic3r_ini)) {
    /*
        my $ini = eval { Slic3r::Config->read_ini("$datadir/slic3r.ini") };
        if ($ini) {
            $last_version = $ini->{_}{version};
            $ini->{_}{$_} = $Settings->{_}{$_}
                for grep !exists $ini->{_}{$_}, keys %{$Settings->{_}};
            $Settings = $ini;
        }
        delete $Settings->{_}{mode};  # handle legacy
    */
    }

    ui_settings->save_settings();

    // Load presets
    this->load_presets();

    wxImage::AddHandler(new wxPNGHandler());
    MainFrame *frame = new MainFrame( "Slic3r", wxDefaultPosition, wxDefaultSize);
    this->SetTopWindow(frame);

    // Load init bundle
    //

    // Run the wizard if we don't have an initial config
    /*
    $self->check_version
        if $self->have_version_check
            && ($Settings->{_}{version_check} // 1)
            && (!$Settings->{_}{last_version_check} || (time - $Settings->{_}{last_version_check}) >= 86400);
    */

    // run callback functions during idle on the main frame
    this->Bind(wxEVT_IDLE,
        [this](wxIdleEvent& e) {
            std::function<void()> func {nullptr}; //
            // try to get the mutex. If we can't, just skip this idle event and get the next one.
            if (!this->callback_register.try_lock()) return;
            // pop callback
            if (cb.size() >= 1) {
                func = cb.top();
                cb.pop();
            }
            // unlock mutex
            this->callback_register.unlock();
            try { // call the function if it's not nullptr;
                if (func != nullptr) func();
            } catch (std::exception& e) { Slic3r::Log::error(LogChannel, LOG_WSTRING("Exception thrown: " <<  e.what())); }
        });
    /*
    EVT_IDLE($frame, sub {
        while (my $cb = shift @cb) {
            $cb->();
        }
    });
    */

    // Handle custom version check event
    /*
    EVT_COMMAND($self, -1, $VERSION_CHECK_EVENT, sub {
        my ($self, $event) = @_;
        my ($success, $response, $manual_check) = @{$event->GetData};

        if ($success) {
            if ($response =~ /^obsolete ?= ?([a-z0-9.-]+,)*\Q$Slic3r::VERSION\E(?:,|$)/) {
                my $res = Wx::MessageDialog->new(undef, "A new version is available. Do you want to open the Slic3r website now?",
                    'Update', wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_INFORMATION | wxICON_ERROR)->ShowModal;
                Wx::LaunchDefaultBrowser('http://slic3r.org/') if $res == wxID_YES;
            } else {
                Slic3r::GUI::show_info(undef, "You're using the latest version. No updates are available.") if $manual_check;
            }
            $Settings->{_}{last_version_check} = time();
            $self->save_settings;
        } else {
            Slic3r::GUI::show_error(undef, "Failed to check for updates. Try later.") if $manual_check;
        }
    });
    */

    return true;
}

void App::save_window_pos(const wxTopLevelWindow* window, const wxString& name ) {
    ui_settings->window_pos[name] =
        std::make_tuple<wxPoint, wxSize, bool>(
            window->GetScreenPosition(),
            window->GetSize(),
            window->IsMaximized());

    ui_settings->save_settings();
}

void App::restore_window_pos(wxTopLevelWindow* window, const wxString& name ) {
    try {
        auto tmp = ui_settings->window_pos[name];
        const auto& size = std::get<1>(tmp);
        const auto& pos = std::get<0>(tmp);
        window->SetSize(size);

        auto display = wxDisplay().GetClientArea();
        if (((pos.x + size.x / 2) < display.GetRight()) && (pos.y + size.y/2 < display.GetBottom()))
            window->Move(pos);

        window->Maximize(std::get<2>(tmp));
    }
    catch (std::out_of_range& e) {
        // config was empty
    }
}

void App::load_presets() {
    for (size_t group = 0; group < preset_types; ++group) {
        Presets& preset_list = this->presets.at(group);
        wxString& ini = this->preset_ini.at(group);
        // keep external or dirty presets
        preset_list.erase(std::remove_if(preset_list.begin(), preset_list.end(),
                    [](const Preset& t) -> bool { return (t.external && t.file_exists()) || t.dirty(); }),
                preset_list.end());
        if (wxDirExists(ini)) {
            auto sink { wxDirTraverserSimple() };
            sink.file_cb = ([&preset_list, group] (const wxString& filename) {

                    // skip if we already have it
                    if (std::find_if(preset_list.begin(), preset_list.end(),
                            [filename] (const Preset& t)
                                { return filename.ToStdString() == t.name; }) != preset_list.end()) return;
                    wxString path, name, ext;
                    wxFileName::SplitPath(filename, &path, &name, &ext);

                    preset_list.push_back(Preset(path.ToStdString(), (name + wxString(".") + ext).ToStdString(), static_cast<preset_t>(group)));
                    });

            wxDir dir(ini);
            dir.Traverse(sink, "*.ini");

            // Sort the list by name
            std::sort(preset_list.begin(), preset_list.end(), [] (const Preset& x, const Preset& y) -> bool { return x.name < y.name; });

            // Prepend default Preset
            preset_list.emplace(preset_list.begin(), Preset(true, "- default -"s, static_cast<preset_t>(group)));
        }

    }
}

void App::CallAfter(std::function<void()> cb_function) {
    // set mutex
    this->callback_register.lock();
    // push function onto stack
    this->cb.emplace(cb_function);
    // unset mutex
    this->callback_register.unlock();
}

void App::OnUnhandledException() {
    try { throw; }
    catch (std::exception &e) {
        Slic3r::Log::fatal_error(LogChannel, LOG_WSTRING("Exception Caught: " << e.what()));
    }
}

}} // namespace Slic3r::GUI
<|endoftext|>


<commit_before>/*
 *  Copyright (C) 2011, 2012, 2013 Stephen F. Booth <me@sbooth.org>
 *  All Rights Reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *    - Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    - Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    - Neither the name of Stephen F. Booth nor the names of its
 *      contributors may be used to endorse or promote products derived
 *      from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <memory>

#include <taglib/tfilestream.h>
#include <taglib/itfile.h>
#include <taglib/xmfile.h>
#include <taglib/s3mfile.h>
#include <taglib/modfile.h>

#include "MODMetadata.h"
#include "CFWrapper.h"
#include "CFErrorUtilities.h"
#include "Logger.h"
#include "AddAudioPropertiesToDictionary.h"
#include "AddTagToDictionary.h"

static void RegisterMODMetadata() __attribute__ ((constructor));
static void RegisterMODMetadata()
{
	AudioMetadata::RegisterSubclass<MODMetadata>();
}

#pragma mark Static Methods

CFArrayRef MODMetadata::CreateSupportedFileExtensions()
{
	CFStringRef supportedExtensions [] = { CFSTR("it"), CFSTR("xm"), CFSTR("s3m"), CFSTR("mod") };
	return CFArrayCreate(kCFAllocatorDefault, (const void **)supportedExtensions, 4, &kCFTypeArrayCallBacks);
}

CFArrayRef MODMetadata::CreateSupportedMIMETypes()
{
	CFStringRef supportedMIMETypes [] = { CFSTR("audio/it"), CFSTR("audio/xm"), CFSTR("audio/s3m"), CFSTR("audio/mod"), CFSTR("audio/x-mod") };
	return CFArrayCreate(kCFAllocatorDefault, (const void **)supportedMIMETypes, 5, &kCFTypeArrayCallBacks);
}

bool MODMetadata::HandlesFilesWithExtension(CFStringRef extension)
{
	if(nullptr == extension)
		return false;

	if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("it"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("xm"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("s3m"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("mod"), kCFCompareCaseInsensitive))
		return true;

	return false;
}

bool MODMetadata::HandlesMIMEType(CFStringRef mimeType)
{
	if(nullptr == mimeType)
		return false;

	if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/it"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/xm"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/s3m"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/mod"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/x-mod"), kCFCompareCaseInsensitive))
		return true;

	return false;
}

AudioMetadata * MODMetadata::CreateMetadata(CFURLRef url)
{
	return new MODMetadata(url);
}

#pragma mark Creation and Destruction

MODMetadata::MODMetadata(CFURLRef url)
	: AudioMetadata(url)
{}

MODMetadata::~MODMetadata()
{}

#pragma mark Functionality

bool MODMetadata::ReadMetadata(CFErrorRef *error)
{
	ClearAllMetadata();

	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;

	SFB::CFString pathExtension = CFURLCopyPathExtension(mURL);
	if(!pathExtension)
		return false;

	bool fileIsValid = false;
	if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("it"), kCFCompareCaseInsensitive)) {
		std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf, true));
		if(!stream->isOpen()) {
			if(error) {
				SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), "");
				SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Input/output error"), "");
				SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), "");

				*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			}

			return false;
		}

		TagLib::IT::File file(stream.get());
		if(file.isValid()) {
			fileIsValid = true;
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MOD (Impulse Tracker)"));

			if(file.audioProperties())
				AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());

			if(file.tag())
				AddTagToDictionary(mMetadata, file.tag());
		}
	}
	else if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("xm"), kCFCompareCaseInsensitive)) {
		std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf, true));
		if(!stream->isOpen()) {
			if(error) {
				SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), "");
				SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Input/output error"), "");
				SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), "");

				*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			}

			return false;
		}

		TagLib::XM::File file(stream.get());
		if(file.isValid()) {
			fileIsValid = true;
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MOD (Extended Module)"));

			if(file.audioProperties())
				AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());

			if(file.tag())
				AddTagToDictionary(mMetadata, file.tag());
		}
	}
	else if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("s3m"), kCFCompareCaseInsensitive)) {
		std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf, true));
		if(!stream->isOpen()) {
			if(error) {
				SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), "");
				SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Input/output error"), "");
				SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), "");

				*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			}

			return false;
		}

		TagLib::S3M::File file(stream.get());
		if(file.isValid()) {
			fileIsValid = true;
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MOD (ScreamTracker III)"));

			if(file.audioProperties())
				AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());

			if(file.tag())
				AddTagToDictionary(mMetadata, file.tag());
		}
	}
	else if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("mod"), kCFCompareCaseInsensitive)) {
		std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf, true));
		if(!stream->isOpen()) {
			if(error) {
				SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), "");
				SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Input/output error"), "");
				SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), "");

				*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			}

			return false;
		}

		TagLib::Mod::File file(stream.get());
		if(file.isValid()) {
			fileIsValid = true;
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MOD (Protracker)"));

			if(file.audioProperties())
				AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());

			if(file.tag())
				AddTagToDictionary(mMetadata, file.tag());
		}
	}

	CFRelease(pathExtension), pathExtension = nullptr;

	if(!fileIsValid) {
		if(error) {
			SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MOD file."), "");
			SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Not a MOD file"), "");
			SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "");

			*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
		}

		return false;
	}

	return true;
}

bool MODMetadata::WriteMetadata(CFErrorRef */*error*/)
{
	LOGGER_NOTICE("org.sbooth.AudioEngine.AudioMetadata.MOD", "Writing of MOD metadata is not supported");

	return false;
}
<commit_msg>Don’t release a wrapped CFObject<commit_after>/*
 *  Copyright (C) 2011, 2012, 2013 Stephen F. Booth <me@sbooth.org>
 *  All Rights Reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *    - Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    - Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    - Neither the name of Stephen F. Booth nor the names of its
 *      contributors may be used to endorse or promote products derived
 *      from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <memory>

#include <taglib/tfilestream.h>
#include <taglib/itfile.h>
#include <taglib/xmfile.h>
#include <taglib/s3mfile.h>
#include <taglib/modfile.h>

#include "MODMetadata.h"
#include "CFWrapper.h"
#include "CFErrorUtilities.h"
#include "Logger.h"
#include "AddAudioPropertiesToDictionary.h"
#include "AddTagToDictionary.h"

static void RegisterMODMetadata() __attribute__ ((constructor));
static void RegisterMODMetadata()
{
	AudioMetadata::RegisterSubclass<MODMetadata>();
}

#pragma mark Static Methods

CFArrayRef MODMetadata::CreateSupportedFileExtensions()
{
	CFStringRef supportedExtensions [] = { CFSTR("it"), CFSTR("xm"), CFSTR("s3m"), CFSTR("mod") };
	return CFArrayCreate(kCFAllocatorDefault, (const void **)supportedExtensions, 4, &kCFTypeArrayCallBacks);
}

CFArrayRef MODMetadata::CreateSupportedMIMETypes()
{
	CFStringRef supportedMIMETypes [] = { CFSTR("audio/it"), CFSTR("audio/xm"), CFSTR("audio/s3m"), CFSTR("audio/mod"), CFSTR("audio/x-mod") };
	return CFArrayCreate(kCFAllocatorDefault, (const void **)supportedMIMETypes, 5, &kCFTypeArrayCallBacks);
}

bool MODMetadata::HandlesFilesWithExtension(CFStringRef extension)
{
	if(nullptr == extension)
		return false;

	if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("it"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("xm"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("s3m"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("mod"), kCFCompareCaseInsensitive))
		return true;

	return false;
}

bool MODMetadata::HandlesMIMEType(CFStringRef mimeType)
{
	if(nullptr == mimeType)
		return false;

	if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/it"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/xm"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/s3m"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/mod"), kCFCompareCaseInsensitive))
		return true;
	else if(kCFCompareEqualTo == CFStringCompare(mimeType, CFSTR("audio/x-mod"), kCFCompareCaseInsensitive))
		return true;

	return false;
}

AudioMetadata * MODMetadata::CreateMetadata(CFURLRef url)
{
	return new MODMetadata(url);
}

#pragma mark Creation and Destruction

MODMetadata::MODMetadata(CFURLRef url)
	: AudioMetadata(url)
{}

MODMetadata::~MODMetadata()
{}

#pragma mark Functionality

bool MODMetadata::ReadMetadata(CFErrorRef *error)
{
	ClearAllMetadata();

	UInt8 buf [PATH_MAX];
	if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX))
		return false;

	SFB::CFString pathExtension = CFURLCopyPathExtension(mURL);
	if(!pathExtension)
		return false;

	bool fileIsValid = false;
	if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("it"), kCFCompareCaseInsensitive)) {
		std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf, true));
		if(!stream->isOpen()) {
			if(error) {
				SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), "");
				SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Input/output error"), "");
				SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), "");

				*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			}

			return false;
		}

		TagLib::IT::File file(stream.get());
		if(file.isValid()) {
			fileIsValid = true;
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MOD (Impulse Tracker)"));

			if(file.audioProperties())
				AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());

			if(file.tag())
				AddTagToDictionary(mMetadata, file.tag());
		}
	}
	else if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("xm"), kCFCompareCaseInsensitive)) {
		std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf, true));
		if(!stream->isOpen()) {
			if(error) {
				SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), "");
				SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Input/output error"), "");
				SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), "");

				*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			}

			return false;
		}

		TagLib::XM::File file(stream.get());
		if(file.isValid()) {
			fileIsValid = true;
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MOD (Extended Module)"));

			if(file.audioProperties())
				AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());

			if(file.tag())
				AddTagToDictionary(mMetadata, file.tag());
		}
	}
	else if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("s3m"), kCFCompareCaseInsensitive)) {
		std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf, true));
		if(!stream->isOpen()) {
			if(error) {
				SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), "");
				SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Input/output error"), "");
				SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), "");

				*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			}

			return false;
		}

		TagLib::S3M::File file(stream.get());
		if(file.isValid()) {
			fileIsValid = true;
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MOD (ScreamTracker III)"));

			if(file.audioProperties())
				AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());

			if(file.tag())
				AddTagToDictionary(mMetadata, file.tag());
		}
	}
	else if(kCFCompareEqualTo == CFStringCompare(pathExtension, CFSTR("mod"), kCFCompareCaseInsensitive)) {
		std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf, true));
		if(!stream->isOpen()) {
			if(error) {
				SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), "");
				SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Input/output error"), "");
				SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), "");

				*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
			}

			return false;
		}

		TagLib::Mod::File file(stream.get());
		if(file.isValid()) {
			fileIsValid = true;
			CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MOD (Protracker)"));

			if(file.audioProperties())
				AddAudioPropertiesToDictionary(mMetadata, file.audioProperties());

			if(file.tag())
				AddTagToDictionary(mMetadata, file.tag());
		}
	}

	if(!fileIsValid) {
		if(error) {
			SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MOD file."), "");
			SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Not a MOD file"), "");
			SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "");

			*error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion);
		}

		return false;
	}

	return true;
}

bool MODMetadata::WriteMetadata(CFErrorRef */*error*/)
{
	LOGGER_NOTICE("org.sbooth.AudioEngine.AudioMetadata.MOD", "Writing of MOD metadata is not supported");

	return false;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: rscconst.cxx,v $
 * $Revision: 1.10 $
 *
 * 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_rsc.hxx"
/****************** I N C L U D E S **************************************/

// C and C++ Includes.
#include <cstdlib>
#include <cstdio>
#include <cstring>

// Solar Definitionen
#include <tools/solar.h>

// Programmabhaengige Includes.
#include <rscconst.hxx>
#include <rscall.h>
#include <rschash.hxx>
#include <tools/resid.hxx>

/****************** C O D E **********************************************/
/****************** R s c C o n s t **************************************/
/*************************************************************************
|*
|*    RscConst::RscConst()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.05.91
|*    Letzte Aenderung  MM 03.05.91
|*
*************************************************************************/
RscConst::RscConst( Atom nId, sal_uInt32 nTypeId )
    : RscTop( nId, nTypeId )
{
    pVarArray = NULL;
    nEntries = 0;
}

/*************************************************************************
|*
|*    RscConst::~RscConst()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.05.91
|*    Letzte Aenderung  MM 03.05.91
|*
*************************************************************************/
RscConst::~RscConst()
{
    if( pVarArray )
        rtl_freeMemory( (void *)pVarArray );
}

/*************************************************************************
|*
|*    RscConst::GetClassType()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.05.91
|*    Letzte Aenderung  MM 03.05.91
|*
*************************************************************************/
RSCCLASS_TYPE RscConst::GetClassType() const
{
    return RSCCLASS_CONST;
}

/*************************************************************************
|*
|*    RscConst::SetConstance()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.04.91
|*    Letzte Aenderung  MM 03.04.91
|*
*************************************************************************/
ERRTYPE RscConst::SetConstant( Atom nVarName, INT32 lValue ){
    if( pVarArray )
        pVarArray = (VarEle *)
            rtl_reallocateMemory( (void *)pVarArray,
                ((nEntries +1) * sizeof( VarEle )) );
    else
        pVarArray = (VarEle *)
            rtl_allocateMemory( ((nEntries +1) * sizeof( VarEle )) );
    pVarArray[ nEntries ].nId     = nVarName;
    pVarArray[ nEntries ].lValue  = lValue;
    nEntries++;

    return( ERR_OK );
}

/*************************************************************************
|*
|*    RscConst::GetConstance()
|*
|*    Beschreibung
|*    Ersterstellung    MM 15.05.91
|*    Letzte Aenderung  MM 15.05.91
|*
*************************************************************************/
Atom RscConst::GetConstant( sal_uInt32 nPos ){
     if( nPos < nEntries )
        return pVarArray[ nPos ].nId;
    return( InvalidAtom );
}

/*************************************************************************
|*
|*    RscConst::GetConstValue()
|*
|*    Beschreibung
|*    Ersterstellung    MM 15.05.91
|*    Letzte Aenderung  MM 15.05.91
|*
*************************************************************************/
BOOL RscConst::GetConstValue( Atom nConst, INT32 * pValue ) const
{
    sal_uInt32 i = 0;

    for( i = 0; i < nEntries; i++ )
        if( pVarArray[ i ].nId == nConst )
        {
            *pValue = pVarArray[ i ].lValue;
            return TRUE;
        }
    return FALSE;
}

/*************************************************************************
|*
|*    RscConst::GetValueConst()
|*
|*    Beschreibung
|*    Ersterstellung    MM 15.05.91
|*    Letzte Aenderung  MM 15.05.91
|*
*************************************************************************/
BOOL RscConst::GetValueConst( INT32 lValue, Atom * pConst ) const
{
    sal_uInt32 i = 0;

    for( i = 0; i < nEntries; i++ )
        if( pVarArray[ i ].lValue == lValue )
        {
            *pConst = pVarArray[ i ].nId;
            return TRUE;
        }
    return FALSE;
}

/*************************************************************************
|*
|*    RscConst::GetConstPos()
|*
|*    Beschreibung      Sucht die Position der Konstanten
|*                      Return = nEntries, nicht gefunden
|*                      Return = Position im Feld
|*    Ersterstellung    MM 03.04.91
|*    Letzte Aenderung  MM 03.04.91
|*
*************************************************************************/
sal_uInt32 RscConst::GetConstPos( Atom nConst )
{
    sal_uInt32 i = 0;

    for( i = 0; i < nEntries; i++ )
    {
        if( pVarArray[ i ].nId == nConst )
            return( i );
    }

    return( nEntries );
}

/*************************************************************************
|*
|*    RscEnum::WriteSyntax()
|*
|*    Beschreibung
|*    Ersterstellung    MM 29.05.91
|*    Letzte Aenderung  MM 29.05.91
|*
*************************************************************************/
void RscConst::WriteSyntax( FILE * fOutput, RscTypCont * pTC )
{
    RscTop::WriteSyntax( fOutput, pTC );

    sal_uInt32 i = 0;
    // Wenn eine Variable Maskierung hat, dann Maskenfeld
    fprintf( fOutput, "\t" );
    for( i = 0; i < nEntries; i++ )
    {
        fprintf( fOutput, "%s, ", pHS->getString( pVarArray[ i ].nId ).getStr() );
        if( 3 == (i % 4) && i < sal_uInt32(nEntries -1) )
            fprintf( fOutput, "\n\t" );
    };
    fprintf( fOutput, "\n" );
}

//==================================================================
void RscConst::WriteRcAccess
(
    FILE * fOutput,
    RscTypCont * /*pTC*/,
    const char * pName
)
{
    fprintf( fOutput, "\t\tSet%s( %s( ", pName, pHS->getString( GetId() ).getStr() );
    fprintf( fOutput, "*(short*)(pResData+nOffset) ) );\n" );
    fprintf( fOutput, "\t\tnOffset += sizeof( short );\n" );
}

/****************** R s c E n u m ****************************************/
/*************************************************************************
|*
|*    RscEnum::RscEnum()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.04.91
|*    Letzte Aenderung  MM 03.04.91
|*
*************************************************************************/
RscEnum::RscEnum( Atom nId, sal_uInt32 nTypeId )
            : RscConst( nId, nTypeId )
{
    nSize = ALIGNED_SIZE( sizeof( RscEnumInst ) );
}

/*************************************************************************
|*
|*    RscEnum::SetConst()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.04.91
|*    Letzte Aenderung  MM 03.04.91
|*
*************************************************************************/
ERRTYPE RscEnum::SetConst( const RSCINST & rInst, Atom nConst, INT32 /*nVal*/ )
{
    sal_uInt32 i = 0;

    if( nEntries != (i = GetConstPos( nConst )) )
    {
        ((RscEnumInst *)rInst.pData)->nValue = i;
        ((RscEnumInst *)rInst.pData)->bDflt = FALSE;
        return( ERR_OK );
    };

    return( ERR_RSCENUM );
}

/*************************************************************************
|*
|*    RscEnum::SetNumber()
|*
|*    Beschreibung
|*    Ersterstellung    MM 18.07.91
|*    Letzte Aenderung  MM 18.07.91
|*
*************************************************************************/
ERRTYPE RscEnum::SetNumber( const RSCINST & rInst, INT32 lValue )
{
    sal_uInt32  i = 0;

    for( i = 0; i < nEntries; i++ ){
        if( (INT32)pVarArray[ i ].lValue == lValue )
            return( SetConst( rInst, pVarArray[ i ].nId, lValue ) );
    };

    return( ERR_RSCENUM );
}

/*************************************************************************
|*
|*    RscEnum::GetConst()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.04.91
|*    Letzte Aenderung  MM 03.04.91
|*
*************************************************************************/
ERRTYPE RscEnum::GetConst( const RSCINST & rInst, Atom * pH ){
    *pH = pVarArray[ ((RscEnumInst *)rInst.pData)->nValue ].nId;
    return( ERR_OK );
}

/*************************************************************************
|*
|*    RscEnum::GetNumber()
|*
|*    Beschreibung
|*    Ersterstellung    MM 16.09.91
|*    Letzte Aenderung  MM 16.09.91
|*
*************************************************************************/
ERRTYPE RscEnum::GetNumber( const RSCINST & rInst, INT32 * pNumber ){
    *pNumber = pVarArray[ ((RscEnumInst *)rInst.pData)->nValue ].lValue;
    return( ERR_OK );
}

/*************************************************************************
|*
|*    RscEnum::Create()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.04.91
|*    Letzte Aenderung  MM 03.04.91
|*
*************************************************************************/
RSCINST RscEnum::Create( RSCINST * pInst, const RSCINST & rDflt, BOOL bOwnClass ){
    RSCINST aInst;

    if( !pInst ){
        aInst.pClass = this;
        aInst.pData = (CLASS_DATA)
                      rtl_allocateMemory( sizeof( RscEnumInst ) );
    }
    else
        aInst = *pInst;
    if( !bOwnClass && rDflt.IsInst() )
        bOwnClass = rDflt.pClass->InHierarchy( this );

    if( bOwnClass )
        memmove( aInst.pData, rDflt.pData, Size() );
    else{
        ((RscEnumInst *)aInst.pData)->nValue = 0;
        ((RscEnumInst *)aInst.pData)->bDflt = TRUE;
    }

    return( aInst );
}

/*************************************************************************
|*
|*    RscEnum::IsValueDefault()
|*
|*    Beschreibung
|*    Ersterstellung    MM 15.01.92
|*    Letzte Aenderung  MM 15.01.92
|*
*************************************************************************/
BOOL RscEnum::IsValueDefault( const RSCINST & rInst, CLASS_DATA pDef ){
    if( pDef ){
        if( ((RscEnumInst*)rInst.pData)->nValue ==
          ((RscEnumInst*)pDef)->nValue )
        {
            return TRUE;
        }
    }

    return FALSE;
}

/*************************************************************************
|*
|*    RscEnum::WriteSrc()
|*
|*    Beschreibung
|*    Ersterstellung    MM 08.04.91
|*    Letzte Aenderung  MM 08.04.91
|*
*************************************************************************/
void RscEnum::WriteSrc( const RSCINST & rInst, FILE * fOutput,
                         RscTypCont *, sal_uInt32, const char * )
{
    fprintf( fOutput, "%s", pHS->getString(
             pVarArray[ ((RscEnumInst *)rInst.pData)->nValue ].nId ).getStr() );
}

/*************************************************************************
|*
|*    RscEnum::WriteRc()
|*
|*    Beschreibung
|*    Ersterstellung    MM 15.04.91
|*    Letzte Aenderung  MM 15.04.91
|*
*************************************************************************/
ERRTYPE RscEnum::WriteRc( const RSCINST & rInst, RscWriteRc & aMem,
                          RscTypCont *, sal_uInt32, BOOL )
{
    aMem.Put( (INT32)pVarArray[ ((RscEnumInst *)rInst.pData)->nValue ].lValue );
    return( ERR_OK );
}

RscLangEnum::RscLangEnum()
        : RscEnum( pHS->getID( "LangEnum" ), RSC_NOTYPE ),
          mnLangId( 0x400 )
{
}
<commit_msg>INTEGRATION: CWS hr51 (1.10.4); FILE MERGED 2008/06/06 15:08:09 hr 1.10.4.1: #i88947#: std namespace<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: rscconst.cxx,v $
 * $Revision: 1.11 $
 *
 * 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_rsc.hxx"
/****************** I N C L U D E S **************************************/

// C and C++ Includes.
#include <cstdlib>
#include <cstdio>
#include <cstring>

// Solar Definitionen
#include <tools/solar.h>

// Programmabhaengige Includes.
#include <rscconst.hxx>
#include <rscall.h>
#include <rschash.hxx>
#include <tools/resid.hxx>

/****************** C O D E **********************************************/
/****************** R s c C o n s t **************************************/
/*************************************************************************
|*
|*    RscConst::RscConst()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.05.91
|*    Letzte Aenderung  MM 03.05.91
|*
*************************************************************************/
RscConst::RscConst( Atom nId, sal_uInt32 nTypeId )
    : RscTop( nId, nTypeId )
{
    pVarArray = NULL;
    nEntries = 0;
}

/*************************************************************************
|*
|*    RscConst::~RscConst()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.05.91
|*    Letzte Aenderung  MM 03.05.91
|*
*************************************************************************/
RscConst::~RscConst()
{
    if( pVarArray )
        rtl_freeMemory( (void *)pVarArray );
}

/*************************************************************************
|*
|*    RscConst::GetClassType()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.05.91
|*    Letzte Aenderung  MM 03.05.91
|*
*************************************************************************/
RSCCLASS_TYPE RscConst::GetClassType() const
{
    return RSCCLASS_CONST;
}

/*************************************************************************
|*
|*    RscConst::SetConstance()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.04.91
|*    Letzte Aenderung  MM 03.04.91
|*
*************************************************************************/
ERRTYPE RscConst::SetConstant( Atom nVarName, INT32 lValue ){
    if( pVarArray )
        pVarArray = (VarEle *)
            rtl_reallocateMemory( (void *)pVarArray,
                ((nEntries +1) * sizeof( VarEle )) );
    else
        pVarArray = (VarEle *)
            rtl_allocateMemory( ((nEntries +1) * sizeof( VarEle )) );
    pVarArray[ nEntries ].nId     = nVarName;
    pVarArray[ nEntries ].lValue  = lValue;
    nEntries++;

    return( ERR_OK );
}

/*************************************************************************
|*
|*    RscConst::GetConstance()
|*
|*    Beschreibung
|*    Ersterstellung    MM 15.05.91
|*    Letzte Aenderung  MM 15.05.91
|*
*************************************************************************/
Atom RscConst::GetConstant( sal_uInt32 nPos ){
     if( nPos < nEntries )
        return pVarArray[ nPos ].nId;
    return( InvalidAtom );
}

/*************************************************************************
|*
|*    RscConst::GetConstValue()
|*
|*    Beschreibung
|*    Ersterstellung    MM 15.05.91
|*    Letzte Aenderung  MM 15.05.91
|*
*************************************************************************/
BOOL RscConst::GetConstValue( Atom nConst, INT32 * pValue ) const
{
    sal_uInt32 i = 0;

    for( i = 0; i < nEntries; i++ )
        if( pVarArray[ i ].nId == nConst )
        {
            *pValue = pVarArray[ i ].lValue;
            return TRUE;
        }
    return FALSE;
}

/*************************************************************************
|*
|*    RscConst::GetValueConst()
|*
|*    Beschreibung
|*    Ersterstellung    MM 15.05.91
|*    Letzte Aenderung  MM 15.05.91
|*
*************************************************************************/
BOOL RscConst::GetValueConst( INT32 lValue, Atom * pConst ) const
{
    sal_uInt32 i = 0;

    for( i = 0; i < nEntries; i++ )
        if( pVarArray[ i ].lValue == lValue )
        {
            *pConst = pVarArray[ i ].nId;
            return TRUE;
        }
    return FALSE;
}

/*************************************************************************
|*
|*    RscConst::GetConstPos()
|*
|*    Beschreibung      Sucht die Position der Konstanten
|*                      Return = nEntries, nicht gefunden
|*                      Return = Position im Feld
|*    Ersterstellung    MM 03.04.91
|*    Letzte Aenderung  MM 03.04.91
|*
*************************************************************************/
sal_uInt32 RscConst::GetConstPos( Atom nConst )
{
    sal_uInt32 i = 0;

    for( i = 0; i < nEntries; i++ )
    {
        if( pVarArray[ i ].nId == nConst )
            return( i );
    }

    return( nEntries );
}

/*************************************************************************
|*
|*    RscEnum::WriteSyntax()
|*
|*    Beschreibung
|*    Ersterstellung    MM 29.05.91
|*    Letzte Aenderung  MM 29.05.91
|*
*************************************************************************/
void RscConst::WriteSyntax( FILE * fOutput, RscTypCont * pTC )
{
    RscTop::WriteSyntax( fOutput, pTC );

    sal_uInt32 i = 0;
    // Wenn eine Variable Maskierung hat, dann Maskenfeld
    fprintf( fOutput, "\t" );
    for( i = 0; i < nEntries; i++ )
    {
        fprintf( fOutput, "%s, ", pHS->getString( pVarArray[ i ].nId ).getStr() );
        if( 3 == (i % 4) && i < sal_uInt32(nEntries -1) )
            fprintf( fOutput, "\n\t" );
    };
    fprintf( fOutput, "\n" );
}

//==================================================================
void RscConst::WriteRcAccess
(
    FILE * fOutput,
    RscTypCont * /*pTC*/,
    const char * pName
)
{
    fprintf( fOutput, "\t\tSet%s( %s( ", pName, pHS->getString( GetId() ).getStr() );
    fprintf( fOutput, "*(short*)(pResData+nOffset) ) );\n" );
    fprintf( fOutput, "\t\tnOffset += sizeof( short );\n" );
}

/****************** R s c E n u m ****************************************/
/*************************************************************************
|*
|*    RscEnum::RscEnum()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.04.91
|*    Letzte Aenderung  MM 03.04.91
|*
*************************************************************************/
RscEnum::RscEnum( Atom nId, sal_uInt32 nTypeId )
            : RscConst( nId, nTypeId )
{
    nSize = ALIGNED_SIZE( sizeof( RscEnumInst ) );
}

/*************************************************************************
|*
|*    RscEnum::SetConst()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.04.91
|*    Letzte Aenderung  MM 03.04.91
|*
*************************************************************************/
ERRTYPE RscEnum::SetConst( const RSCINST & rInst, Atom nConst, INT32 /*nVal*/ )
{
    sal_uInt32 i = 0;

    if( nEntries != (i = GetConstPos( nConst )) )
    {
        ((RscEnumInst *)rInst.pData)->nValue = i;
        ((RscEnumInst *)rInst.pData)->bDflt = FALSE;
        return( ERR_OK );
    };

    return( ERR_RSCENUM );
}

/*************************************************************************
|*
|*    RscEnum::SetNumber()
|*
|*    Beschreibung
|*    Ersterstellung    MM 18.07.91
|*    Letzte Aenderung  MM 18.07.91
|*
*************************************************************************/
ERRTYPE RscEnum::SetNumber( const RSCINST & rInst, INT32 lValue )
{
    sal_uInt32  i = 0;

    for( i = 0; i < nEntries; i++ ){
        if( (INT32)pVarArray[ i ].lValue == lValue )
            return( SetConst( rInst, pVarArray[ i ].nId, lValue ) );
    };

    return( ERR_RSCENUM );
}

/*************************************************************************
|*
|*    RscEnum::GetConst()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.04.91
|*    Letzte Aenderung  MM 03.04.91
|*
*************************************************************************/
ERRTYPE RscEnum::GetConst( const RSCINST & rInst, Atom * pH ){
    *pH = pVarArray[ ((RscEnumInst *)rInst.pData)->nValue ].nId;
    return( ERR_OK );
}

/*************************************************************************
|*
|*    RscEnum::GetNumber()
|*
|*    Beschreibung
|*    Ersterstellung    MM 16.09.91
|*    Letzte Aenderung  MM 16.09.91
|*
*************************************************************************/
ERRTYPE RscEnum::GetNumber( const RSCINST & rInst, INT32 * pNumber ){
    *pNumber = pVarArray[ ((RscEnumInst *)rInst.pData)->nValue ].lValue;
    return( ERR_OK );
}

/*************************************************************************
|*
|*    RscEnum::Create()
|*
|*    Beschreibung
|*    Ersterstellung    MM 03.04.91
|*    Letzte Aenderung  MM 03.04.91
|*
*************************************************************************/
RSCINST RscEnum::Create( RSCINST * pInst, const RSCINST & rDflt, BOOL bOwnClass ){
    RSCINST aInst;

    if( !pInst ){
        aInst.pClass = this;
        aInst.pData = (CLASS_DATA)
                      rtl_allocateMemory( sizeof( RscEnumInst ) );
    }
    else
        aInst = *pInst;
    if( !bOwnClass && rDflt.IsInst() )
        bOwnClass = rDflt.pClass->InHierarchy( this );

    if( bOwnClass )
        std::memmove( aInst.pData, rDflt.pData, Size() );
    else{
        ((RscEnumInst *)aInst.pData)->nValue = 0;
        ((RscEnumInst *)aInst.pData)->bDflt = TRUE;
    }

    return( aInst );
}

/*************************************************************************
|*
|*    RscEnum::IsValueDefault()
|*
|*    Beschreibung
|*    Ersterstellung    MM 15.01.92
|*    Letzte Aenderung  MM 15.01.92
|*
*************************************************************************/
BOOL RscEnum::IsValueDefault( const RSCINST & rInst, CLASS_DATA pDef ){
    if( pDef ){
        if( ((RscEnumInst*)rInst.pData)->nValue ==
          ((RscEnumInst*)pDef)->nValue )
        {
            return TRUE;
        }
    }

    return FALSE;
}

/*************************************************************************
|*
|*    RscEnum::WriteSrc()
|*
|*    Beschreibung
|*    Ersterstellung    MM 08.04.91
|*    Letzte Aenderung  MM 08.04.91
|*
*************************************************************************/
void RscEnum::WriteSrc( const RSCINST & rInst, FILE * fOutput,
                         RscTypCont *, sal_uInt32, const char * )
{
    fprintf( fOutput, "%s", pHS->getString(
             pVarArray[ ((RscEnumInst *)rInst.pData)->nValue ].nId ).getStr() );
}

/*************************************************************************
|*
|*    RscEnum::WriteRc()
|*
|*    Beschreibung
|*    Ersterstellung    MM 15.04.91
|*    Letzte Aenderung  MM 15.04.91
|*
*************************************************************************/
ERRTYPE RscEnum::WriteRc( const RSCINST & rInst, RscWriteRc & aMem,
                          RscTypCont *, sal_uInt32, BOOL )
{
    aMem.Put( (INT32)pVarArray[ ((RscEnumInst *)rInst.pData)->nValue ].lValue );
    return( ERR_OK );
}

RscLangEnum::RscLangEnum()
        : RscEnum( pHS->getID( "LangEnum" ), RSC_NOTYPE ),
          mnLangId( 0x400 )
{
}
<|endoftext|>


<commit_before>#include <cerrno>
#include <cstring>
#include <iostream>

#include <pqxx/pqxx>

#include "test_helpers.hxx"

using namespace PGSTD;
using namespace pqxx;

// Mixed-mode, seeking test program for libpqxx's Large Objects interface.
namespace
{
const string Contents = "Large object test contents";

class WriteLargeObject : public transactor<>
{
public:
  explicit WriteLargeObject() :
    transactor<>("WriteLargeObject")
  {
  }

  void operator()(argument_type &T)
  {
    largeobjectaccess A(T);
    cout << "Writing to large object #" << largeobject(A).id() << endl;

    A.write(Contents);

    char Buf[200];
    const size_t Size = sizeof(Buf) - 1;
    PQXX_CHECK_EQUAL(
	A.read(Buf, Size),
	0u,
	"Could read bytes from large object after writing.");

    // Overwrite terminating zero
    largeobjectaccess::size_type Here = A.seek(-1, ios::cur);

    // Redundant typedef to work around bug in Visual C++.NET
    typedef largeobjectaccess::size_type loa_size;
    PQXX_CHECK_EQUAL(
	Here,
	loa_size(Contents.size()-1),
	"Ended up in wrong place after moving back 1 byte.");

    A.write("!", 1);

    // Now check that we really did
    PQXX_CHECK_EQUAL(
	A.seek(-1, ios::cur),
	loa_size(Contents.size()-1),
	"Inconsistent seek.");

    char Check;
    PQXX_CHECK_EQUAL(
	A.read(&Check, 1),
	1,
	"Unexpected result from read().");
    PQXX_CHECK_EQUAL(string(&Check, 1), "!", "Read back wrong character.");

    PQXX_CHECK_EQUAL(
	A.seek(0, ios::beg),
	0,
	"Ended up in wrong place after seeking back to beginning.");

    PQXX_CHECK_EQUAL(
	A.read(&Check, 1),
	1,
	"Unexpected result when trying to read back 1st byte.");

    PQXX_CHECK_EQUAL(
	string(&Check, 1),
	string(Contents, 0, 1),
	"Wrong first character in large object.");

    // Clean up after ourselves
    A.remove(T);
  }

private:
  largeobject m_Object;
};

void test_058(connection_base &C, transaction_base &orgT)
{
  orgT.abort();

  C.perform(WriteLargeObject());
}
} // namespace

PQXX_REGISTER_TEST_T(test_058, nontransaction)
<commit_msg>Test build fix.<commit_after>#include <cerrno>
#include <cstring>
#include <iostream>

#include <pqxx/pqxx>

#include "test_helpers.hxx"

using namespace PGSTD;
using namespace pqxx;

// Mixed-mode, seeking test program for libpqxx's Large Objects interface.
namespace
{
const string Contents = "Large object test contents";

class WriteLargeObject : public transactor<>
{
public:
  explicit WriteLargeObject() :
    transactor<>("WriteLargeObject")
  {
  }

  void operator()(argument_type &T)
  {
    largeobjectaccess A(T);
    cout << "Writing to large object #" << largeobject(A).id() << endl;

    A.write(Contents);

    char Buf[200];
    const size_t Size = sizeof(Buf) - 1;
    PQXX_CHECK_EQUAL(
	A.read(Buf, Size),
	0,
	"Could read bytes from large object after writing.");

    // Overwrite terminating zero
    largeobjectaccess::size_type Here = A.seek(-1, ios::cur);

    // Redundant typedef to work around bug in Visual C++.NET
    typedef largeobjectaccess::size_type loa_size;
    PQXX_CHECK_EQUAL(
	Here,
	loa_size(Contents.size()-1),
	"Ended up in wrong place after moving back 1 byte.");

    A.write("!", 1);

    // Now check that we really did
    PQXX_CHECK_EQUAL(
	A.seek(-1, ios::cur),
	loa_size(Contents.size()-1),
	"Inconsistent seek.");

    char Check;
    PQXX_CHECK_EQUAL(
	A.read(&Check, 1),
	1,
	"Unexpected result from read().");
    PQXX_CHECK_EQUAL(string(&Check, 1), "!", "Read back wrong character.");

    PQXX_CHECK_EQUAL(
	A.seek(0, ios::beg),
	0,
	"Ended up in wrong place after seeking back to beginning.");

    PQXX_CHECK_EQUAL(
	A.read(&Check, 1),
	1,
	"Unexpected result when trying to read back 1st byte.");

    PQXX_CHECK_EQUAL(
	string(&Check, 1),
	string(Contents, 0, 1),
	"Wrong first character in large object.");

    // Clean up after ourselves
    A.remove(T);
  }

private:
  largeobject m_Object;
};

void test_058(connection_base &C, transaction_base &orgT)
{
  orgT.abort();

  C.perform(WriteLargeObject());
}
} // namespace

PQXX_REGISTER_TEST_T(test_058, nontransaction)
<|endoftext|>


<commit_before>/*
Copyright (c) 2009-2012, Intel Corporation
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// written by Roman Dementiev
//

#include "cpucounters.h"
#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <sys/time.h>

using std::cout;
using std::endl;

inline double my_timestamp()
{
    struct timeval tp;
    gettimeofday(&tp, NULL);
    return double(tp.tv_sec) + tp.tv_usec / 1000000.;
}

struct T
{
    int key[1];
    int data[15];

    T() { }
    T(int a) { key[0] = a; }

    bool operator == (const T & k) const
    {
        return k.key[0] == key[0];
    }
};

template <class DS>
void Memory_intensive_task(DS & ds)
{
    std::find(ds.begin(), ds.end(), ds.size());
}

int main(int argc, char * argv[])
{
    std::vector<T> vector;
    int nelements = 13000000;

    int i = 0;
    int delay = atoi(argv[1]);

    cout << "Elements data size: " << sizeof(T) * nelements / 1024 << " KB" << std::endl;

    for ( ; i < nelements; ++i)
    {
        vector.push_back(i);
    }

    double before_ts, after_ts;

    while (1)
    {
        before_ts = my_timestamp();
        cout << "Reading memory for " << delay << " seconds" << std::endl;
        do
        {
            Memory_intensive_task(vector);
            after_ts = my_timestamp();
        } while ((after_ts - before_ts) < delay);

        cout << "Sleeping for " << delay << " seconds" << std::endl;
        sleep(delay);
    }

    return 0;
}
<commit_msg>Replace endl with \n to get rid of many unnecessary flushes<commit_after>/*
Copyright (c) 2009-2012, Intel Corporation
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// written by Roman Dementiev
//

#include "cpucounters.h"
#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <sys/time.h>

using std::cout;

inline double my_timestamp()
{
    struct timeval tp;
    gettimeofday(&tp, NULL);
    return double(tp.tv_sec) + tp.tv_usec / 1000000.;
}

struct T
{
    int key[1];
    int data[15];

    T() { }
    T(int a) { key[0] = a; }

    bool operator == (const T & k) const
    {
        return k.key[0] == key[0];
    }
};

template <class DS>
void Memory_intensive_task(DS & ds)
{
    std::find(ds.begin(), ds.end(), ds.size());
}

int main(int argc, char * argv[])
{
    std::vector<T> vector;
    int nelements = 13000000;

    int i = 0;
    int delay = atoi(argv[1]);

    cout << "Elements data size: " << sizeof(T) * nelements / 1024 << " KB\n";

    for ( ; i < nelements; ++i)
    {
        vector.push_back(i);
    }

    double before_ts, after_ts;

    while (1)
    {
        before_ts = my_timestamp();
        cout << "Reading memory for " << delay << " seconds\n";
        do
        {
            Memory_intensive_task(vector);
            after_ts = my_timestamp();
        } while ((after_ts - before_ts) < delay);

        cout << "Sleeping for " << delay << " seconds\n";
        sleep(delay);
    }

    return 0;
}
<|endoftext|>