<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_pm_utils.C $         */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file p9_pm_utils.C
/// @brief Utility functions for PM FAPIs
///

// *HWP HWP Owner       : Amit Kumar <akumar3@us.ibm.com>
// *HWP Backup HWP Owner: Greg Still <stillgs@us.ibm.com>
// *HWP FW Owner        : Bilicon Patil <bilpatil@in.ibm.com>
// *HWP Team            : PM
// *HWP Level           : 1
// *HWP Consumed by     : HS

// ----------------------------------------------------------------------
// Includes
// ----------------------------------------------------------------------
#include <p9_pm.H>
#include <p9_pm_utils.H>
#include <p9_const_common.H>

/// Byte-reverse a 16-bit integer if on a little-endian machine

uint16_t
revle16(const uint16_t i_x)
{
    uint16_t rx;

#ifndef _BIG_ENDIAN
    uint8_t* pix = (uint8_t*)(&i_x);
    uint8_t* prx = (uint8_t*)(&rx);

    prx[0] = pix[1];
    prx[1] = pix[0];
#else
    rx = i_x;
#endif

    return rx;
}

/// Byte-reverse a 32-bit integer if on a little-endian machine

uint32_t
revle32(const uint32_t i_x)
{
    uint32_t rx;

#ifndef _BIG_ENDIAN
    uint8_t* pix = (uint8_t*)(&i_x);
    uint8_t* prx = (uint8_t*)(&rx);

    prx[0] = pix[3];
    prx[1] = pix[2];
    prx[2] = pix[1];
    prx[3] = pix[0];
#else
    rx = i_x;
#endif

    return rx;
}

/// Byte-reverse a 64-bit integer if on a little-endian machine

uint64_t
revle64(const uint64_t i_x)
{
    uint64_t rx;

#ifndef _BIG_ENDIAN
    uint8_t* pix = (uint8_t*)(&i_x);
    uint8_t* prx = (uint8_t*)(&rx);

    prx[0] = pix[7];
    prx[1] = pix[6];
    prx[2] = pix[5];
    prx[3] = pix[4];
    prx[4] = pix[3];
    prx[5] = pix[2];
    prx[6] = pix[1];
    prx[7] = pix[0];
#else
    rx = i_x;
#endif

    return rx;
}

fapi2::ReturnCode p9_pm_glob_fir_trace(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const char* i_msg)
{
    FAPI_INF("p9_pm_glob_fir_trace Enter");

#if 0 // The CONST_UINT64_T definition in P9 const_common.H takes 4 arguments -
    // CONST_UINT64_T(name, expr, unit, meth). Need to figure out the values
    // for "unit" and "meth" for the below declarations.
    CONST_UINT64_T( GLOB_XSTOP_FIR_0x01040000, ULL(0x01040000) );
    CONST_UINT64_T( GLOB_RECOV_FIR_0x01040001, ULL(0x01040001) );
    CONST_UINT64_T( TP_LFIR_0x0104000A, ULL(0x0104000A) );
#endif

    //  Note: i_msg is put on on each record to allow for trace "greps"
    //  so as to see the "big picture" across when

    uint8_t l_traceEnFlag = false;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
    fapi2::buffer<uint64_t> l_data64;

#if 0 // Uncomment when attribute ATTR_PM_GLOBAL_FIR_TRACE_EN is ready
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PM_GLOBAL_FIR_TRACE_EN,
                           FAPI_SYSTEM,
                           l_traceEnFlag),
             "FAPI_ATTR_GET for attribute ATTR_PM_GLOBAL_FIR_TRACE_EN");
#endif

    // Continue if trace is enabled.
    if (false == l_traceEnFlag)
    {
        goto fapi_try_exit;
    }

    //  ******************************************************************
    //  Check for xstops and recoverables and put in the trace
    //  ******************************************************************
    {
#if 0 // Uncomment when the scom address is defined
        FAPI_TRY(fapi2::getScom(i_target,
                                READ_GLOBAL_XSTOP_FIR_0x570F001B,
                                l_data64));
#endif

        if(l_data64)
        {
            FAPI_INF("Xstop is **ACTIVE** %s", i_msg);
        }
    }

    {
#if 0 // Uncomment when the scom address is defined
        FAPI_TRY(fapi2::getScom(i_target,
                                READ_GLOBAL_RECOV_FIR_0x570F001C,
                                l_data64));
#endif

        if(l_data64)
        {
            FAPI_INF("Recoverable attention is **ACTIVE** %s", i_msg);
        }
    }

    {
#if 0 // Uncomment when the scom address is defined
        FAPI_TRY(fapi2::getScom(i_target,
                                GLOB_XSTOP_FIR_0x01040000,
                                l_data64));
#endif

        if(l_data64)
        {
            FAPI_INF("Glob Xstop FIR is **ACTIVE** %s", i_msg);
        }
    }

    {
#if 0 // Uncomment when the scom address is defined
        FAPI_TRY(fapi2::getScom(i_target,
                                GLOB_RECOV_FIR_0x01040001,
                                l_data64));
#endif

        if(l_data64)
        {
            FAPI_INF("Glob Recov FIR is **ACTIVE** %s", i_msg);
        }
    }

    {
#if 0 // Uncomment when the scom address is defined
        FAPI_TRY(fapi2::getScom(i_target,
                                TP_LFIR_0x0104000A,
                                l_data64));
#endif

        if(l_data64)
        {
            FAPI_INF("TP LFIR is **ACTIVE** %s", i_msg);
        }
    }

fapi_try_exit:
    return fapi2::current_err;
}

fapi2::ReturnCode special_wakeup_all(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const bool i_enable)
{
    FAPI_INF("special_wakeup_all Enter");

    fapi2::ReturnCode l_rc;
    auto l_exChiplets = i_target.getChildren<fapi2::TARGET_TYPE_EX>
                        (fapi2::TARGET_STATE_FUNCTIONAL);

    // For each EX target
    for (auto l_ex_chplt : l_exChiplets)
    {
        FAPI_DBG("Running special wakeup on ex chiplet 0x%08X ", l_ex_chplt);

        FAPI_TRY( fapi2::specialWakeup( l_ex_chplt, i_enable ) );
    }

fapi_try_exit:
    return fapi2::current_err;
}
<commit_msg>PM: p9_pm_init, p9_pm_utils clean-up<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_pm_utils.C $         */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file p9_pm_utils.C
/// @brief Utility functions for PM FAPIs
///

// *HWP HWP Owner       : Amit Kumar <akumar3@us.ibm.com>
// *HWP Backup HWP Owner: Greg Still <stillgs@us.ibm.com>
// *HWP FW Owner        : Bilicon Patil <bilpatil@in.ibm.com>
// *HWP Team            : PM
// *HWP Level           : 1
// *HWP Consumed by     : HS

// ----------------------------------------------------------------------
// Includes
// ----------------------------------------------------------------------
#include <p9_pm.H>
#include <p9_pm_utils.H>
#include <p9_const_common.H>
#include <p9_perv_scom_addresses.H>

/// Byte-reverse a 16-bit integer if on a little-endian machine

uint16_t
revle16(const uint16_t i_x)
{
    uint16_t rx;

#ifndef _BIG_ENDIAN
    uint8_t* pix = (uint8_t*)(&i_x);
    uint8_t* prx = (uint8_t*)(&rx);

    prx[0] = pix[1];
    prx[1] = pix[0];
#else
    rx = i_x;
#endif

    return rx;
}

/// Byte-reverse a 32-bit integer if on a little-endian machine

uint32_t
revle32(const uint32_t i_x)
{
    uint32_t rx;

#ifndef _BIG_ENDIAN
    uint8_t* pix = (uint8_t*)(&i_x);
    uint8_t* prx = (uint8_t*)(&rx);

    prx[0] = pix[3];
    prx[1] = pix[2];
    prx[2] = pix[1];
    prx[3] = pix[0];
#else
    rx = i_x;
#endif

    return rx;
}

/// Byte-reverse a 64-bit integer if on a little-endian machine

uint64_t
revle64(const uint64_t i_x)
{
    uint64_t rx;

#ifndef _BIG_ENDIAN
    uint8_t* pix = (uint8_t*)(&i_x);
    uint8_t* prx = (uint8_t*)(&rx);

    prx[0] = pix[7];
    prx[1] = pix[6];
    prx[2] = pix[5];
    prx[3] = pix[4];
    prx[4] = pix[3];
    prx[5] = pix[2];
    prx[6] = pix[1];
    prx[7] = pix[0];
#else
    rx = i_x;
#endif

    return rx;
}

fapi2::ReturnCode p9_pm_glob_fir_trace(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const char* i_msg)
{
    FAPI_DBG(">> p9_pm_glob_fir_trace");

    // Multicast read addresses
    const uint64_t READ_GLOB_XSTOP_FIR_MC =  RULL(0x570F001C);
    const uint64_t READ_GLOB_RECOV_FIR_MC =  RULL(0x570F001B);

    //  Note: i_msg is put on on each record to allow for trace "greps"
    //  so as to see the "big picture" across when
    uint8_t l_traceEnFlag = false;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
    fapi2::buffer<uint64_t> l_data64;

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PM_GLOBAL_FIR_TRACE_EN,
                           FAPI_SYSTEM,
                           l_traceEnFlag),
             "FAPI_ATTR_GET for attribute ATTR_PM_GLOBAL_FIR_TRACE_EN");

    // Continue if trace is enabled.
    if (!l_traceEnFlag)
    {
        goto fapi_try_exit;
    }

    //  ******************************************************************
    //  Check for xstops and recoverables and put in the trace
    //  ******************************************************************
    {
        FAPI_TRY(fapi2::getScom(i_target,
                                READ_GLOB_XSTOP_FIR_MC,
                                l_data64));

        if(l_data64)
        {
            FAPI_INF("Xstop is **ACTIVE** %s", i_msg);
        }
    }

    {
        FAPI_TRY(fapi2::getScom(i_target,
                                READ_GLOB_RECOV_FIR_MC,
                                l_data64));

        if(l_data64)
        {
            FAPI_INF("Recoverable attention is **ACTIVE** %s", i_msg);
        }
    }

    {
        FAPI_TRY(fapi2::getScom(i_target,
                                PERV_TP_XFIR,
                                l_data64));

        if(l_data64)
        {
            FAPI_INF("Glob Xstop FIR is **ACTIVE** %s", i_msg);
        }
    }

    {
        FAPI_TRY(fapi2::getScom(i_target,
                                PERV_TP_RFIR,
                                l_data64));

        if(l_data64)
        {
            FAPI_INF("Glob Recov FIR is **ACTIVE** %s", i_msg);
        }
    }

    {
        FAPI_TRY(fapi2::getScom(i_target,
                                PERV_TP_LOCAL_FIR,
                                l_data64));

        if(l_data64)
        {
            FAPI_INF("TP LFIR is **ACTIVE** %s", i_msg);
        }
    }

fapi_try_exit:
    FAPI_DBG("<< p9_pm_glob_fir_trace");
    return fapi2::current_err;
}

fapi2::ReturnCode special_wakeup_all(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const bool i_enable)
{
    FAPI_DBG(">> special_wakeup_all");

    fapi2::ReturnCode l_rc;
    auto l_exChiplets = i_target.getChildren<fapi2::TARGET_TYPE_EX>
                        (fapi2::TARGET_STATE_FUNCTIONAL);

    // For each EX target
    for (auto l_ex_chplt : l_exChiplets)
    {
        fapi2::ATTR_CHIP_UNIT_POS_Type l_ex_num;
        FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS,
                                l_ex_chplt,
                                l_ex_num));
        FAPI_DBG("Running special wakeup on ex chiplet 0x%08X ", l_ex_num);

        FAPI_TRY( fapi2::specialWakeup( l_ex_chplt, i_enable ) );
    }

fapi_try_exit:
    FAPI_DBG("<< special_wakeup_all");
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>//// License: Apache 2.0. See LICENSE file in root directory.
//// Copyright(c) 2020 Intel Corporation. All Rights Reserved.

#include "depth-to-rgb-calibration.h"
#include <librealsense2/rs.hpp>
#include "core/streaming.h"
#include "calibrated-sensor.h"
#include "context.h"
#include "api.h"  // VALIDATE_INTERFACE_NO_THROW
#include "algo/depth-to-rgb-calibration/debug.h"
#include "l500/l500-device.h"
#include "l500/l500-color.h"
#include "algo/depth-to-rgb-calibration/utils.h"

using namespace librealsense;
namespace impl = librealsense::algo::depth_to_rgb_calibration;
namespace thermal = librealsense::algo::thermal_loop;

#define CHECK_IF_NEEDS_TO_STOP() if (_should_continue) _should_continue()

depth_to_rgb_calibration::depth_to_rgb_calibration(
    impl::optimizer::settings const & settings,
    rs2::frame depth,
    rs2::frame ir,
    rs2::frame yuy,
    rs2::frame prev_yuy,
    std::vector< impl::yuy_t > const & last_yuy_data,
    impl::algo_calibration_info const & cal_info,
    impl::algo_calibration_registers const & cal_regs,
    rs2_intrinsics yuy_intrinsics,
    thermal::thermal_calibration_table_interface const & thermal_table,
    std::function<void()> should_continue
)
    : _algo( settings )
    , _raw_intr( yuy_intrinsics )
    , _thermal_intr( _raw_intr )
    , _extr(to_raw_extrinsics( depth.get_profile().get_extrinsics_to( yuy.get_profile() )))
    , _from( depth.get_profile().get()->profile )
    , _to( yuy.get_profile().get()->profile )
    , _should_continue( should_continue )
    , _thermal_table( thermal_table )
{
    AC_LOG( DEBUG, "Setting YUY data" );
    auto color_profile = yuy.get_profile().as< rs2::video_stream_profile >();
    auto yuy_data = (impl::yuy_t const *) yuy.get_data();
    auto prev_yuy_data = (impl::yuy_t const *) prev_yuy.get_data();
    if( last_yuy_data.size() == yuy.get_data_size() / sizeof( impl::yuy_t ) )
        _last_successful_frame_data = last_yuy_data;  // copy -- will be moved to algo
    else if( ! last_yuy_data.empty() )
        AC_LOG( DEBUG, "Not using last successfully-calibrated scene: it's of a different resolution" );

    auto scale = thermal_table.get_thermal_scale( settings.hum_temp );
    AC_LOG( DEBUG, "    scaling K_rgb by " << scale );
    _thermal_intr.fx = float( _thermal_intr.fx * scale );
    _thermal_intr.fy = float( _thermal_intr.fy * scale );

    impl::calib calibration( _thermal_intr, _extr );

    CHECK_IF_NEEDS_TO_STOP();

    _algo.set_yuy_data(
        std::vector< impl::yuy_t >( yuy_data, yuy_data + yuy.get_data_size() / sizeof( impl::yuy_t )),
        std::vector< impl::yuy_t >( prev_yuy_data, prev_yuy_data + yuy.get_data_size() / sizeof( impl::yuy_t ) ),
        std::move( _last_successful_frame_data ),
        calibration
    );

    AC_LOG( DEBUG, "Setting IR data" );
    auto ir_profile = ir.get_profile().as< rs2::video_stream_profile >();
    auto ir_data = (impl::ir_t const *) ir.get_data();

    CHECK_IF_NEEDS_TO_STOP();

    _algo.set_ir_data(
        std::vector< impl::ir_t >( ir_data, ir_data + ir.get_data_size() / sizeof( impl::ir_t )),
        ir_profile.width(), ir_profile.height()
    );

    CHECK_IF_NEEDS_TO_STOP();

    auto si = ((frame_interface *) depth.get() )->get_sensor();
    auto cs = VALIDATE_INTERFACE_NO_THROW( si, librealsense::calibrated_sensor );
    if( !cs )
    {
        // We can only calibrate depth sensors that supply this interface!
        throw librealsense::not_implemented_exception( "the depth frame supplied is not from a calibrated_sensor" );
    }
    _dsm_params = cs->get_dsm_params();

    AC_LOG( DEBUG, "Setting Z data" );
    auto z_profile = depth.get_profile().as< rs2::video_stream_profile >();
    auto z_data = (impl::z_t const *) depth.get_data();

    CHECK_IF_NEEDS_TO_STOP();

    _algo.set_z_data(
        std::vector< impl::z_t >( z_data, z_data + depth.get_data_size() / sizeof( impl::z_t ) ),
        z_profile.get_intrinsics(), _dsm_params, cal_info, cal_regs,
        depth.as< rs2::depth_frame >().get_units() * 1000.f   // same scaling as for extrinsics!
    );

    debug_calibration( "old" );
}

void depth_to_rgb_calibration::write_data_to( std::string const & dir )
{
    _algo.write_data_to( dir );

    impl::write_to_file( &_raw_intr, sizeof( _raw_intr ), dir, "raw_rgb.intrinsics" );

    impl::write_vector_to_file( _thermal_table.build_raw_data(), dir, "rgb_thermal_table" );
}

rs2_calibration_status depth_to_rgb_calibration::optimize(
    std::function<void( rs2_calibration_status )> call_back
)
{
#define DISABLE_RS2_CALIBRATION_CHECKS "RS2_AC_DISABLE_RETRIES"

    try
    {
        AC_LOG( DEBUG, "Checking scene validity" );
        if( !_algo.is_scene_valid() )
        {
            //AC_LOG( ERROR, "Calibration scene was found invalid!" );
            call_back( RS2_CALIBRATION_SCENE_INVALID );
            if( !getenv( DISABLE_RS2_CALIBRATION_CHECKS ) )
            {
                // Default behavior is to stop AC and trigger a retry
                return RS2_CALIBRATION_RETRY;
            }
            if( getenv( "RS2_AC_INVALID_SCENE_FAIL" ) )
            {
                // Here we don't want a retry, but we also do not want the calibration
                // to possibly be successful -- fail it
                AC_LOG( DEBUG, DISABLE_RS2_CALIBRATION_CHECKS << " is on but so is RS2_AC_INVALID_SCENE_FAIL: fail!" );
                return RS2_CALIBRATION_FAILED;
            }
            AC_LOG( DEBUG, DISABLE_RS2_CALIBRATION_CHECKS << " is on; continuing" );
        }

        CHECK_IF_NEEDS_TO_STOP();

        AC_LOG( DEBUG, "Optimizing" );

        _algo.optimize(
            [&]( impl::data_collect const & data ) { CHECK_IF_NEEDS_TO_STOP(); }
        );

        AC_LOG( DEBUG, "Checking result validity" );
        if( !_algo.is_valid_results() )
        {
            // Error would have printed inside
            call_back( RS2_CALIBRATION_BAD_RESULT );
            if( !getenv( DISABLE_RS2_CALIBRATION_CHECKS ) )
            {
                // Default behavior is to stop and trigger a retry
                AC_LOG( DEBUG, DISABLE_RS2_CALIBRATION_CHECKS << " is off; will retry if possible" );
                return RS2_CALIBRATION_RETRY;
            }
            if( !getenv( "RS2_AC_FORCE_BAD_RESULT" ) )
            {
                // This is mostly for validation use, where we don't want the retries and instead want
                // to fail on bad results (we don't want to write bad results to the camera!)
                AC_LOG( DEBUG, DISABLE_RS2_CALIBRATION_CHECKS << " is on; no retries" );
                return RS2_CALIBRATION_FAILED;
            }
            // Allow forcing of results... be careful! This may damage the camera in AC2!
            AC_LOG( DEBUG, DISABLE_RS2_CALIBRATION_CHECKS << " is on but so is RS2_AC_FORCE_BAD_RESULT: results will be used!" );
        }

        // AC_LOG( INFO, "Calibration finished; original cost= " << original_cost << "  optimized
        // cost= " << params_curr.cost );

        AC_LOG( DEBUG, "Optimization successful!" );
        _thermal_intr = _algo.get_calibration().get_intrinsics();
        _thermal_intr.model = RS2_DISTORTION_INVERSE_BROWN_CONRADY;  // restore LRS model

        // Override everything in the raw intrinsics except the focal length (fx and fy)
        // TODO: AC is not "supposed" to change focal length, but we shouldn't assume this! The
        // proper way to do the following is not by restoring the original, but rather by DEscaling
        // the results from AC.
        auto original_fx = _raw_intr.fx, original_fy = _raw_intr.fy;
        _raw_intr = _thermal_intr;
        _raw_intr.fx = original_fx;
        _raw_intr.fy = original_fy;

        _extr = from_raw_extrinsics( _algo.get_calibration().get_extrinsics() );
        _dsm_params = _algo.get_dsm_params();
        _last_successful_frame_data = _algo.get_yuy_data().orig_frame;  // copy -- will be moved to ac_trigger
        debug_calibration( "new" );
        return RS2_CALIBRATION_SUCCESSFUL;
    }
    catch( std::exception const & e )
    {
        AC_LOG( ERROR, "Calibration threw error: " << e.what() );
        return RS2_CALIBRATION_FAILED;
    }
}

void depth_to_rgb_calibration::debug_calibration( char const * prefix )
{
    AC_LOG( INFO, AC_F_PREC << "    " << prefix << "   th" << _thermal_intr );
    AC_LOG( INFO, AC_F_PREC << "    " << prefix << "  raw" << _raw_intr );
    AC_LOG( INFO, AC_F_PREC << "    " << prefix << " extr" << _extr );
    AC_LOG( INFO, AC_F_PREC << "    " << prefix << "  dsm" << _dsm_params );
}

<commit_msg>minor fix in kth debug messages<commit_after>//// License: Apache 2.0. See LICENSE file in root directory.
//// Copyright(c) 2020 Intel Corporation. All Rights Reserved.

#include "depth-to-rgb-calibration.h"
#include <librealsense2/rs.hpp>
#include "core/streaming.h"
#include "calibrated-sensor.h"
#include "context.h"
#include "api.h"  // VALIDATE_INTERFACE_NO_THROW
#include "algo/depth-to-rgb-calibration/debug.h"
#include "l500/l500-device.h"
#include "l500/l500-color.h"
#include "algo/depth-to-rgb-calibration/utils.h"

using namespace librealsense;
namespace impl = librealsense::algo::depth_to_rgb_calibration;
namespace thermal = librealsense::algo::thermal_loop;

#define CHECK_IF_NEEDS_TO_STOP() if (_should_continue) _should_continue()

depth_to_rgb_calibration::depth_to_rgb_calibration(
    impl::optimizer::settings const & settings,
    rs2::frame depth,
    rs2::frame ir,
    rs2::frame yuy,
    rs2::frame prev_yuy,
    std::vector< impl::yuy_t > const & last_yuy_data,
    impl::algo_calibration_info const & cal_info,
    impl::algo_calibration_registers const & cal_regs,
    rs2_intrinsics yuy_intrinsics,
    thermal::thermal_calibration_table_interface const & thermal_table,
    std::function<void()> should_continue
)
    : _algo( settings )
    , _raw_intr( yuy_intrinsics )
    , _thermal_intr( _raw_intr )
    , _extr(to_raw_extrinsics( depth.get_profile().get_extrinsics_to( yuy.get_profile() )))
    , _from( depth.get_profile().get()->profile )
    , _to( yuy.get_profile().get()->profile )
    , _should_continue( should_continue )
    , _thermal_table( thermal_table )
{
    AC_LOG( DEBUG, "Setting YUY data" );
    auto color_profile = yuy.get_profile().as< rs2::video_stream_profile >();
    auto yuy_data = (impl::yuy_t const *) yuy.get_data();
    auto prev_yuy_data = (impl::yuy_t const *) prev_yuy.get_data();
    if( last_yuy_data.size() == yuy.get_data_size() / sizeof( impl::yuy_t ) )
        _last_successful_frame_data = last_yuy_data;  // copy -- will be moved to algo
    else if( ! last_yuy_data.empty() )
        AC_LOG( DEBUG, "Not using last successfully-calibrated scene: it's of a different resolution" );

    auto scale = thermal_table.get_thermal_scale( settings.hum_temp );
    AC_LOG( DEBUG, "    scaling K_rgb by " << scale );
    _thermal_intr.fx = float( _thermal_intr.fx * scale );
    _thermal_intr.fy = float( _thermal_intr.fy * scale );

    impl::calib calibration( _thermal_intr, _extr );

    CHECK_IF_NEEDS_TO_STOP();

    _algo.set_yuy_data(
        std::vector< impl::yuy_t >( yuy_data, yuy_data + yuy.get_data_size() / sizeof( impl::yuy_t )),
        std::vector< impl::yuy_t >( prev_yuy_data, prev_yuy_data + yuy.get_data_size() / sizeof( impl::yuy_t ) ),
        std::move( _last_successful_frame_data ),
        calibration
    );

    AC_LOG( DEBUG, "Setting IR data" );
    auto ir_profile = ir.get_profile().as< rs2::video_stream_profile >();
    auto ir_data = (impl::ir_t const *) ir.get_data();

    CHECK_IF_NEEDS_TO_STOP();

    _algo.set_ir_data(
        std::vector< impl::ir_t >( ir_data, ir_data + ir.get_data_size() / sizeof( impl::ir_t )),
        ir_profile.width(), ir_profile.height()
    );

    CHECK_IF_NEEDS_TO_STOP();

    auto si = ((frame_interface *) depth.get() )->get_sensor();
    auto cs = VALIDATE_INTERFACE_NO_THROW( si, librealsense::calibrated_sensor );
    if( !cs )
    {
        // We can only calibrate depth sensors that supply this interface!
        throw librealsense::not_implemented_exception( "the depth frame supplied is not from a calibrated_sensor" );
    }
    _dsm_params = cs->get_dsm_params();

    AC_LOG( DEBUG, "Setting Z data" );
    auto z_profile = depth.get_profile().as< rs2::video_stream_profile >();
    auto z_data = (impl::z_t const *) depth.get_data();

    CHECK_IF_NEEDS_TO_STOP();

    _algo.set_z_data(
        std::vector< impl::z_t >( z_data, z_data + depth.get_data_size() / sizeof( impl::z_t ) ),
        z_profile.get_intrinsics(), _dsm_params, cal_info, cal_regs,
        depth.as< rs2::depth_frame >().get_units() * 1000.f   // same scaling as for extrinsics!
    );

    debug_calibration( "old" );
}

void depth_to_rgb_calibration::write_data_to( std::string const & dir )
{
    _algo.write_data_to( dir );

    impl::write_to_file( &_raw_intr, sizeof( _raw_intr ), dir, "raw_rgb.intrinsics" );

    impl::write_vector_to_file( _thermal_table.build_raw_data(), dir, "rgb_thermal_table" );
}

rs2_calibration_status depth_to_rgb_calibration::optimize(
    std::function<void( rs2_calibration_status )> call_back
)
{
#define DISABLE_RS2_CALIBRATION_CHECKS "RS2_AC_DISABLE_RETRIES"

    try
    {
        AC_LOG( DEBUG, "Checking scene validity" );
        if( !_algo.is_scene_valid() )
        {
            //AC_LOG( ERROR, "Calibration scene was found invalid!" );
            call_back( RS2_CALIBRATION_SCENE_INVALID );
            if( !getenv( DISABLE_RS2_CALIBRATION_CHECKS ) )
            {
                // Default behavior is to stop AC and trigger a retry
                return RS2_CALIBRATION_RETRY;
            }
            if( getenv( "RS2_AC_INVALID_SCENE_FAIL" ) )
            {
                // Here we don't want a retry, but we also do not want the calibration
                // to possibly be successful -- fail it
                AC_LOG( DEBUG, DISABLE_RS2_CALIBRATION_CHECKS << " is on but so is RS2_AC_INVALID_SCENE_FAIL: fail!" );
                return RS2_CALIBRATION_FAILED;
            }
            AC_LOG( DEBUG, DISABLE_RS2_CALIBRATION_CHECKS << " is on; continuing" );
        }

        CHECK_IF_NEEDS_TO_STOP();

        AC_LOG( DEBUG, "Optimizing" );

        _algo.optimize(
            [&]( impl::data_collect const & data ) { CHECK_IF_NEEDS_TO_STOP(); }
        );

        AC_LOG( DEBUG, "Checking result validity" );
        if( !_algo.is_valid_results() )
        {
            // Error would have printed inside
            call_back( RS2_CALIBRATION_BAD_RESULT );
            if( !getenv( DISABLE_RS2_CALIBRATION_CHECKS ) )
            {
                // Default behavior is to stop and trigger a retry
                AC_LOG( DEBUG, DISABLE_RS2_CALIBRATION_CHECKS << " is off; will retry if possible" );
                return RS2_CALIBRATION_RETRY;
            }
            if( !getenv( "RS2_AC_FORCE_BAD_RESULT" ) )
            {
                // This is mostly for validation use, where we don't want the retries and instead want
                // to fail on bad results (we don't want to write bad results to the camera!)
                AC_LOG( DEBUG, DISABLE_RS2_CALIBRATION_CHECKS << " is on; no retries" );
                return RS2_CALIBRATION_FAILED;
            }
            // Allow forcing of results... be careful! This may damage the camera in AC2!
            AC_LOG( DEBUG, DISABLE_RS2_CALIBRATION_CHECKS << " is on but so is RS2_AC_FORCE_BAD_RESULT: results will be used!" );
        }

        // AC_LOG( INFO, "Calibration finished; original cost= " << original_cost << "  optimized
        // cost= " << params_curr.cost );

        AC_LOG( DEBUG, "Optimization successful!" );
        _thermal_intr = _algo.get_calibration().get_intrinsics();
        _thermal_intr.model = RS2_DISTORTION_INVERSE_BROWN_CONRADY;  // restore LRS model

        // Override everything in the raw intrinsics except the focal length (fx and fy)
        // TODO: AC is not "supposed" to change focal length, but we shouldn't assume this! The
        // proper way to do the following is not by restoring the original, but rather by DEscaling
        // the results from AC.
        auto original_fx = _raw_intr.fx, original_fy = _raw_intr.fy;
        _raw_intr = _thermal_intr;
        _raw_intr.fx = original_fx;
        _raw_intr.fy = original_fy;

        _extr = from_raw_extrinsics( _algo.get_calibration().get_extrinsics() );
        _dsm_params = _algo.get_dsm_params();
        _last_successful_frame_data = _algo.get_yuy_data().orig_frame;  // copy -- will be moved to ac_trigger
        debug_calibration( "new" );
        return RS2_CALIBRATION_SUCCESSFUL;
    }
    catch( std::exception const & e )
    {
        AC_LOG( ERROR, "Calibration threw error: " << e.what() );
        return RS2_CALIBRATION_FAILED;
    }
}

void depth_to_rgb_calibration::debug_calibration( char const * prefix )
{
    AC_LOG( DEBUG, AC_F_PREC << "    " << prefix << "   th" << _thermal_intr );
    AC_LOG( DEBUG, AC_F_PREC << "    " << prefix << "  raw" << _raw_intr );
    AC_LOG( DEBUG, AC_F_PREC << "    " << prefix << " extr" << _extr );
    AC_LOG( DEBUG, AC_F_PREC << "    " << prefix << "  dsm" << _dsm_params );
}

<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"
#include "obj_pool.h"
#include "liquids.h"

void TPool::overFlow()
{
  int index=getDrinkIndex(), total=0, amt=0;
  TRoom *rp=NULL;
  TPool *pool;
  bool valid;

  // should make a structure for this but I'm in a hurry
  vector<TRoom *>rooms;
  vector<dirTypeT>roomdirs;
  vector<int>roomamts;

  if(!roomp)
    return;

  if(index>=9){
    // check every exit
    for(dirTypeT dir=MIN_DIR;dir<MAX_DIR;dir++){
      // liquid doesn't flow up
      if(dir==DIR_UP)
	continue;

      // eligible exit
      if(exitDir(dir) && real_roomp(exitDir(dir)->to_room) &&
	 !(exitDir(dir)->condition & EX_CLOSED) &&
	 (rp = real_roomp(roomp->exitDir(dir)->to_room))){
	// check each item
	valid=true;
	amt=0;
	for(TThing *t=rp->getStuff();t;t=t->nextThing){
	  // check pools that are the same type and less than half my size
	  if((pool=dynamic_cast<TPool *>(t)) &&
	     pool->getDrinkType()==getDrinkType()){
	    if(pool->getDrinkUnits() >= (getDrinkUnits()/2)){
	      valid=false;
	    } else {
	      total+=pool->getDrinkUnits();
	      amt=pool->getDrinkUnits();
	    }
	  }
	}
	if(valid){
	  rooms.push_back(rp);
	  roomdirs.push_back(dir);
	  roomamts.push_back(amt);
	}
      }
    }

    // no rooms to flow into, we're the smallest pool
    if(!rooms.size())
      return;

    total+=(int)((float)getDrinkUnits() * 0.60);
    setDrinkUnits((int)((float)getDrinkUnits() * 0.40));

    total/=rooms.size();

    sendrpf(COLOR_BASIC, roomp,
	    "Some %s flows outward into surrounding rooms.\n\r",
	    liquidInfo[getDrinkType()]->name);

    for(unsigned int i=0;i<rooms.size();++i){
      rooms[i]->dropPool(total-roomamts[i], getDrinkType());
      sendrpf(COLOR_BASIC, rooms[i],
	      "Some %s flows in from the %s.\n\r",
	      liquidInfo[getDrinkType()]->name,
	      dirs[rev_dir[roomdirs[i]]]);
    }

    roomp->saveItems("");
    rp->saveItems("");
  }
}

void TPool::doMerge()
{
  TPool *pool;
  TThing *t, *t2;

  if(!roomp)
    return;

  for(t=roomp->getStuff();t;t=t2){
    t2=t->nextThing;

    if((pool=dynamic_cast<TPool *>(t)) && pool != this &&
       pool->getDrinkType()==getDrinkType()){
      // merge!
      addToDrinkUnits(pool->getDrinkUnits());
      --(*pool);
      delete pool;
    }
  }
}

void TPool::setDrinkUnits(int n)
{
  setMaxDrinkUnits(n);
  TBaseCup::setDrinkUnits(n);
  setVolume((int)(getVolume() + (getDrinkUnits() * SIP_VOLUME)));
  weightChangeObject(0);
  updateDesc();
  obj_flags.decay_time=getDrinkUnits();
}

void TPool::addToDrinkUnits(int n)
{
  addToMaxDrinkUnits(n);
  TBaseCup::addToDrinkUnits(n);
  setVolume((int)(getVolume() + (getDrinkUnits() * SIP_VOLUME)));
  weightChangeObject(0);
  updateDesc();
  obj_flags.decay_time=getDrinkUnits();
}

void TPool::setDrinkType(liqTypeT n)
{
  TBaseCup::setDrinkType(n);
  updateDesc();
}

// the best way to do this would be to explicitly set the proper weight in the
// accessors, rather than using weightChangeObject.  It is prone to float
// rounding errors and some functions don't even bother to use it (ie, pour,
// which I fixed).  But instead of recoding everything, I'll just put this here
// so that pools don't generate errors in weightChangeObject.
void TPool::weightChangeObject(float fWeight)
{
  setWeight(obj_index[getItemIndex()].weight);
  TBaseCup::weightChangeObject(getDrinkUnits() * SIP_WEIGHT);
}

int TPool::getDrinkIndex() const
{
  int drinkunits=getDrinkUnits();

  if(drinkunits<=0){
    return 0;
  } else if(drinkunits<=5){
    return 1;
  } else if(drinkunits<=10){
    return 2;
  } else if(drinkunits<=25){
    return 3;
  } else if(drinkunits<=50){
    return 4;
  } else if(drinkunits<=100){
    return 5;
  } else if(drinkunits<=250){
    return 6;
  } else if(drinkunits<=1000){
    return 7;
  } else if(drinkunits<=10000){
    return 8;
  } else if(drinkunits<=25000){
    return 9;
  } else {
    return 10;
  }
}

void TPool::updateDesc()
{
  int drinkindex=getDrinkIndex();
  char buf[256];
  const char *liqname=liquidInfo[getDrinkType()]->name;
  sstring buf2;

  const char *poolname [] =
  {
    "a few drops of %s",
    "a tiny puddle of %s",
    "a small puddle of %s",
    "a puddle of %s",
    "a fair sized puddle of %s",
    "a big pool of %s",
    "a large pool of %s",
    "a huge pool of %s",
    "a massive pool of %s",
    "a tremendously huge pool of %s",
    "a veritable ocean of %s"
  };

  const char *pooldesc [] =
  {
    "A few drops of %s sprinkle the $g here and are fading fast.",
    "A tiny puddle of %s has gathered on the $g here.",
    "A small puddle of %s is on the $g here.",
    "A puddle of %s is here on the $g.",
    "A fair sized puddle of %s is here on the $g.",
    "A big pool of %s is on the $g here.",
    "A large pool of %s is here on the $g.",
    "A huge pool of %s is on the $g here.",
    "A massive pool of %s is on the $g here.",
    "A tremendously huge pool of %s dominates the area.",
    "A veritable ocean of %s covers the area."
  };

  if (isObjStat(ITEM_STRUNG)) {
    delete [] shortDescr;
    delete [] descr;
    delete [] name;

    extraDescription *exd;
    while ((exd = ex_description)) {
      ex_description = exd->next;
      delete exd;
    }
    ex_description = NULL;
    delete [] action_description;
    action_description = NULL;
  } else {
    addObjStat(ITEM_STRUNG);
    ex_description = NULL;
    action_description = NULL;
  }

  if(isDrinkConFlag(DRINK_FROZEN)){
    buf2 = fmt("chunk frozen %s %s") %
      stripColorCodes(liquidInfo[getDrinkType()]->name) %
      stripColorCodes(liquidInfo[getDrinkType()]->color);
    name = mud_str_dup(buf2);

    sprintf(buf, "a <C>frozen<1> chunk of %s", liqname);
    shortDescr = mud_str_dup(buf);

    sprintf(buf, "A chunk of <C>frozen<1> %s is here.", liqname);
    setDescr(mud_str_dup(buf));

    SET_BIT(obj_flags.wear_flags, ITEM_TAKE);
  } else {
    buf2 = fmt("pool puddle %s %s") %
      stripColorCodes(liquidInfo[getDrinkType()]->name) %
      stripColorCodes(liquidInfo[getDrinkType()]->color);
    name = mud_str_dup(buf2);

    sprintf(buf, poolname[drinkindex], liqname);
    shortDescr = mud_str_dup(buf);

    sprintf(buf, pooldesc[drinkindex], liqname);
    setDescr(mud_str_dup(buf));

    REMOVE_BIT(obj_flags.wear_flags, ITEM_TAKE);
  }
}

bool TPool::isPluralItem() const
{
  // a few drops of blood
  if (getDrinkIndex() == 0)
    return TRUE;

  // otherwise, make recursive
  return TBaseCup::isPluralItem();
}

int TRoom::dropPool(int amt, liqTypeT liq)
{
  TPool *pool=NULL;
  TThing *t;
  TObj *obj;

  if(amt==0)
    return FALSE;

  /* look for preexisting pool */
  for(t=getStuff();t;t=t->nextThing){
    TPool *tp = dynamic_cast<TPool *>(t);
    if (tp && (tp->getDrinkType() == liq)){
      pool=tp;
      break;
    }
  }

  if(!pool){
    // create new pool
#if 1
// builder port uses stripped down database which was causing problems
// hence this setup instead.
    int robj = real_object(GENERIC_POOL);
    if (robj < 0 || robj >= (signed int) obj_index.size()) {
      vlogf(LOG_BUG, fmt("dropPool(): No object (%d) in database!") %  GENERIC_POOL);
      return false;
    }

    obj = read_object(robj, REAL);
#else
    obj = read_object(GENERIC_POOL, VIRTUAL);
#endif
    pool = dynamic_cast<TPool *>(obj);
    if (!pool)
      return false;
    pool->initPool(amt, liq);

    *this += *pool;
  } else {
    pool->fillMeAmount(amt, liq);
  }

  return TRUE;

}

int TBeing::dropPool(int amt, liqTypeT liq)
{
  TPool *pool=NULL;
  TThing *t;
  TObj *obj;

  if(amt==0)
    return FALSE;

  /* look for preexisting pool */
  for(t=roomp->getStuff();t;t=t->nextThing){
    TPool *tp = dynamic_cast<TPool *>(t);
    if (tp && (tp->getDrinkType() == liq)){
      pool=tp;
      break;
    }
  }

  if(!pool){
    // create new pool
#if 1
// builder port uses stripped down database which was causing problems
// hence this setup instead.
    int robj = real_object(GENERIC_POOL);
    if (robj < 0 || robj >= (signed int) obj_index.size()) {
      vlogf(LOG_BUG, fmt("dropPool(): No object (%d) in database!") %  GENERIC_POOL);
      return false;
    }

    obj = read_object(robj, REAL);
#else
    obj = read_object(GENERIC_POOL, VIRTUAL);
#endif
    pool = dynamic_cast<TPool *>(obj);
    if (!pool)
      return false;
    pool->initPool(amt, liq);

    *roomp += *pool;
  } else {
    pool->fillMeAmount(amt, liq);
  }

  return TRUE;
}

void TPool::decayMe()
{
  int drinkunits=getDrinkUnits();

  // check for non-decaying pools
  if (isDrinkConFlag(DRINK_PERM))
    return;

  if(drinkunits<=0)
    setDrinkUnits(0);
  else if(drinkunits<25)
    addToDrinkUnits(-1);
  else // large pools evaporate faster
    addToDrinkUnits(-(drinkunits/25));
}

void TPool::initPool(int amt, liqTypeT liq)
{
  swapToStrung();
  REMOVE_BIT(obj_flags.wear_flags, ITEM_TAKE);
  setDrinkType(liq);
  canBeSeen = 1;
  setMaterial(MAT_WATER);

  fillMeAmount(amt, liq);
}

TPool::TPool() :
  TBaseCup()
{
}

TPool::TPool(const TPool &a) :
  TBaseCup(a)
{
}

TPool & TPool::operator=(const TPool &a)
{
  if (this == &a) return *this;
  TBaseCup::operator=(a);
  return *this;
}

TPool::~TPool()
{
}

void TPool::fillMeAmount(int amt, liqTypeT liq)
{
  setDrinkType(liq);
  addToDrinkUnits(amt);

  weightChangeObject(amt * SIP_WEIGHT);
}

<commit_msg>lowered pool size for overflow<commit_after>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"
#include "obj_pool.h"
#include "liquids.h"

void TPool::overFlow()
{
  int index=getDrinkIndex(), total=0, amt=0;
  TRoom *rp=NULL;
  TPool *pool;
  bool valid;

  // should make a structure for this but I'm in a hurry
  vector<TRoom *>rooms;
  vector<dirTypeT>roomdirs;
  vector<int>roomamts;

  if(!roomp)
    return;

  if(index>=8){
    // check every exit
    for(dirTypeT dir=MIN_DIR;dir<MAX_DIR;dir++){
      // liquid doesn't flow up
      if(dir==DIR_UP)
	continue;

      // eligible exit
      if(exitDir(dir) && real_roomp(exitDir(dir)->to_room) &&
	 !(exitDir(dir)->condition & EX_CLOSED) &&
	 (rp = real_roomp(roomp->exitDir(dir)->to_room))){
	// check each item
	valid=true;
	amt=0;
	for(TThing *t=rp->getStuff();t;t=t->nextThing){
	  // check pools that are the same type and less than half my size
	  if((pool=dynamic_cast<TPool *>(t)) &&
	     pool->getDrinkType()==getDrinkType()){
	    if(pool->getDrinkUnits() >= (getDrinkUnits()/2)){
	      valid=false;
	    } else {
	      total+=pool->getDrinkUnits();
	      amt=pool->getDrinkUnits();
	    }
	  }
	}
	if(valid){
	  rooms.push_back(rp);
	  roomdirs.push_back(dir);
	  roomamts.push_back(amt);
	}
      }
    }

    // no rooms to flow into, we're the smallest pool
    if(!rooms.size())
      return;

    total+=(int)((float)getDrinkUnits() * 0.60);
    setDrinkUnits((int)((float)getDrinkUnits() * 0.40));

    total/=rooms.size();

    sendrpf(COLOR_BASIC, roomp,
	    "Some %s flows outward into surrounding rooms.\n\r",
	    liquidInfo[getDrinkType()]->name);

    for(unsigned int i=0;i<rooms.size();++i){
      rooms[i]->dropPool(total-roomamts[i], getDrinkType());
      sendrpf(COLOR_BASIC, rooms[i],
	      "Some %s flows in from the %s.\n\r",
	      liquidInfo[getDrinkType()]->name,
	      dirs[rev_dir[roomdirs[i]]]);
    }

    roomp->saveItems("");
    rp->saveItems("");
  }
}

void TPool::doMerge()
{
  TPool *pool;
  TThing *t, *t2;

  if(!roomp)
    return;

  for(t=roomp->getStuff();t;t=t2){
    t2=t->nextThing;

    if((pool=dynamic_cast<TPool *>(t)) && pool != this &&
       pool->getDrinkType()==getDrinkType()){
      // merge!
      addToDrinkUnits(pool->getDrinkUnits());
      --(*pool);
      delete pool;
    }
  }
}

void TPool::setDrinkUnits(int n)
{
  setMaxDrinkUnits(n);
  TBaseCup::setDrinkUnits(n);
  setVolume((int)(getVolume() + (getDrinkUnits() * SIP_VOLUME)));
  weightChangeObject(0);
  updateDesc();
  obj_flags.decay_time=getDrinkUnits();
}

void TPool::addToDrinkUnits(int n)
{
  addToMaxDrinkUnits(n);
  TBaseCup::addToDrinkUnits(n);
  setVolume((int)(getVolume() + (getDrinkUnits() * SIP_VOLUME)));
  weightChangeObject(0);
  updateDesc();
  obj_flags.decay_time=getDrinkUnits();
}

void TPool::setDrinkType(liqTypeT n)
{
  TBaseCup::setDrinkType(n);
  updateDesc();
}

// the best way to do this would be to explicitly set the proper weight in the
// accessors, rather than using weightChangeObject.  It is prone to float
// rounding errors and some functions don't even bother to use it (ie, pour,
// which I fixed).  But instead of recoding everything, I'll just put this here
// so that pools don't generate errors in weightChangeObject.
void TPool::weightChangeObject(float fWeight)
{
  setWeight(obj_index[getItemIndex()].weight);
  TBaseCup::weightChangeObject(getDrinkUnits() * SIP_WEIGHT);
}

int TPool::getDrinkIndex() const
{
  int drinkunits=getDrinkUnits();

  if(drinkunits<=0){
    return 0;
  } else if(drinkunits<=5){
    return 1;
  } else if(drinkunits<=10){
    return 2;
  } else if(drinkunits<=25){
    return 3;
  } else if(drinkunits<=50){
    return 4;
  } else if(drinkunits<=100){
    return 5;
  } else if(drinkunits<=250){
    return 6;
  } else if(drinkunits<=1000){
    return 7;
  } else if(drinkunits<=10000){
    return 8;
  } else if(drinkunits<=25000){
    return 9;
  } else {
    return 10;
  }
}

void TPool::updateDesc()
{
  int drinkindex=getDrinkIndex();
  char buf[256];
  const char *liqname=liquidInfo[getDrinkType()]->name;
  sstring buf2;

  const char *poolname [] =
  {
    "a few drops of %s",
    "a tiny puddle of %s",
    "a small puddle of %s",
    "a puddle of %s",
    "a fair sized puddle of %s",
    "a big pool of %s",
    "a large pool of %s",
    "a huge pool of %s",
    "a massive pool of %s",
    "a tremendously huge pool of %s",
    "a veritable ocean of %s"
  };

  const char *pooldesc [] =
  {
    "A few drops of %s sprinkle the $g here and are fading fast.",
    "A tiny puddle of %s has gathered on the $g here.",
    "A small puddle of %s is on the $g here.",
    "A puddle of %s is here on the $g.",
    "A fair sized puddle of %s is here on the $g.",
    "A big pool of %s is on the $g here.",
    "A large pool of %s is here on the $g.",
    "A huge pool of %s is on the $g here.",
    "A massive pool of %s is on the $g here.",
    "A tremendously huge pool of %s dominates the area.",
    "A veritable ocean of %s covers the area."
  };

  if (isObjStat(ITEM_STRUNG)) {
    delete [] shortDescr;
    delete [] descr;
    delete [] name;

    extraDescription *exd;
    while ((exd = ex_description)) {
      ex_description = exd->next;
      delete exd;
    }
    ex_description = NULL;
    delete [] action_description;
    action_description = NULL;
  } else {
    addObjStat(ITEM_STRUNG);
    ex_description = NULL;
    action_description = NULL;
  }

  if(isDrinkConFlag(DRINK_FROZEN)){
    buf2 = fmt("chunk frozen %s %s") %
      stripColorCodes(liquidInfo[getDrinkType()]->name) %
      stripColorCodes(liquidInfo[getDrinkType()]->color);
    name = mud_str_dup(buf2);

    sprintf(buf, "a <C>frozen<1> chunk of %s", liqname);
    shortDescr = mud_str_dup(buf);

    sprintf(buf, "A chunk of <C>frozen<1> %s is here.", liqname);
    setDescr(mud_str_dup(buf));

    SET_BIT(obj_flags.wear_flags, ITEM_TAKE);
  } else {
    buf2 = fmt("pool puddle %s %s") %
      stripColorCodes(liquidInfo[getDrinkType()]->name) %
      stripColorCodes(liquidInfo[getDrinkType()]->color);
    name = mud_str_dup(buf2);

    sprintf(buf, poolname[drinkindex], liqname);
    shortDescr = mud_str_dup(buf);

    sprintf(buf, pooldesc[drinkindex], liqname);
    setDescr(mud_str_dup(buf));

    REMOVE_BIT(obj_flags.wear_flags, ITEM_TAKE);
  }
}

bool TPool::isPluralItem() const
{
  // a few drops of blood
  if (getDrinkIndex() == 0)
    return TRUE;

  // otherwise, make recursive
  return TBaseCup::isPluralItem();
}

int TRoom::dropPool(int amt, liqTypeT liq)
{
  TPool *pool=NULL;
  TThing *t;
  TObj *obj;

  if(amt==0)
    return FALSE;

  /* look for preexisting pool */
  for(t=getStuff();t;t=t->nextThing){
    TPool *tp = dynamic_cast<TPool *>(t);
    if (tp && (tp->getDrinkType() == liq)){
      pool=tp;
      break;
    }
  }

  if(!pool){
    // create new pool
#if 1
// builder port uses stripped down database which was causing problems
// hence this setup instead.
    int robj = real_object(GENERIC_POOL);
    if (robj < 0 || robj >= (signed int) obj_index.size()) {
      vlogf(LOG_BUG, fmt("dropPool(): No object (%d) in database!") %  GENERIC_POOL);
      return false;
    }

    obj = read_object(robj, REAL);
#else
    obj = read_object(GENERIC_POOL, VIRTUAL);
#endif
    pool = dynamic_cast<TPool *>(obj);
    if (!pool)
      return false;
    pool->initPool(amt, liq);

    *this += *pool;
  } else {
    pool->fillMeAmount(amt, liq);
  }

  return TRUE;

}

int TBeing::dropPool(int amt, liqTypeT liq)
{
  TPool *pool=NULL;
  TThing *t;
  TObj *obj;

  if(amt==0)
    return FALSE;

  /* look for preexisting pool */
  for(t=roomp->getStuff();t;t=t->nextThing){
    TPool *tp = dynamic_cast<TPool *>(t);
    if (tp && (tp->getDrinkType() == liq)){
      pool=tp;
      break;
    }
  }

  if(!pool){
    // create new pool
#if 1
// builder port uses stripped down database which was causing problems
// hence this setup instead.
    int robj = real_object(GENERIC_POOL);
    if (robj < 0 || robj >= (signed int) obj_index.size()) {
      vlogf(LOG_BUG, fmt("dropPool(): No object (%d) in database!") %  GENERIC_POOL);
      return false;
    }

    obj = read_object(robj, REAL);
#else
    obj = read_object(GENERIC_POOL, VIRTUAL);
#endif
    pool = dynamic_cast<TPool *>(obj);
    if (!pool)
      return false;
    pool->initPool(amt, liq);

    *roomp += *pool;
  } else {
    pool->fillMeAmount(amt, liq);
  }

  return TRUE;
}

void TPool::decayMe()
{
  int drinkunits=getDrinkUnits();

  // check for non-decaying pools
  if (isDrinkConFlag(DRINK_PERM))
    return;

  if(drinkunits<=0)
    setDrinkUnits(0);
  else if(drinkunits<25)
    addToDrinkUnits(-1);
  else // large pools evaporate faster
    addToDrinkUnits(-(drinkunits/25));
}

void TPool::initPool(int amt, liqTypeT liq)
{
  swapToStrung();
  REMOVE_BIT(obj_flags.wear_flags, ITEM_TAKE);
  setDrinkType(liq);
  canBeSeen = 1;
  setMaterial(MAT_WATER);

  fillMeAmount(amt, liq);
}

TPool::TPool() :
  TBaseCup()
{
}

TPool::TPool(const TPool &a) :
  TBaseCup(a)
{
}

TPool & TPool::operator=(const TPool &a)
{
  if (this == &a) return *this;
  TBaseCup::operator=(a);
  return *this;
}

TPool::~TPool()
{
}

void TPool::fillMeAmount(int amt, liqTypeT liq)
{
  setDrinkType(liq);
  addToDrinkUnits(amt);

  weightChangeObject(amt * SIP_WEIGHT);
}

<|endoftext|>


<commit_before>/*
 * This file is part of accounts-ui
 *
 * Copyright (C) 2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include "provider-plugin-proxy.h"
#include "provider-plugin-proxy-priv.h"

#include <QProcess>
#include <QDebug>
#include <QLocalServer>
#include <QLocalSocket>

using namespace Accounts;
using namespace AccountsUI;

ProviderPluginProxyPrivate::~ProviderPluginProxyPrivate()
{
    qDebug() << Q_FUNC_INFO;
    if (process) {
        stopProcess();
        delete process;
    }
}

void ProviderPluginProxyPrivate::startProcess(Provider *provider,
                                              AccountId accountId,
                                              const QString &serviceType)
{
    Q_Q(ProviderPluginProxy);

    PWATCHER_RESTART(pwatcher);
    const char pluginNamePattern[] = "%1plugin";

    /*
     * TODO: specify dir path by some variable
     * */
    QDir pluginDir(QString::fromLatin1("/usr/libexec/AccountsUI"));
    QDomElement root(provider->domDocument().documentElement());
    QString pluginTypeName(root.
                           firstChildElement(QString::fromLatin1("plugin")).
                           text());

    QString pluginFileName(QString::fromLatin1(pluginNamePattern)
                           .arg(pluginTypeName));
    QFileInfo pluginFileInfo(pluginDir, pluginFileName);

    QString providerId(root.attribute(QLatin1String("id")));

    //fallback use id as a plugin name
    if (!pluginFileInfo.exists()) {
        pluginFileName = QString::fromLatin1(pluginNamePattern).arg(providerId);
        pluginFileInfo.setFile(pluginDir, pluginFileName);

        if (!pluginFileInfo.exists()) {
            pluginFileName = QString::fromLatin1(pluginNamePattern).
                                      arg(QLatin1String("generic"));
            pluginFileInfo.setFile(pluginDir, pluginFileName);
        }
    }

    if (!pluginFileInfo.exists()) {
        emit q->failed();
        return;
    }

    QString processArguments;
    Qt::HANDLE windowId = MApplication::instance()->activeWindow()->winId();

    if (accountId != 0) {
        processArguments = QString::fromLatin1("%1 --edit %2 --windowId %3")
            .arg(pluginFileInfo.canonicalFilePath())
            .arg(accountId)
            .arg(windowId);

        newAccountCreation = false;
    } else {
        processArguments = QString::fromLatin1("%1 --create %2 --windowId %3")
            .arg(pluginFileInfo.canonicalFilePath())
            .arg(providerId)
            .arg(windowId);

        newAccountCreation = true;
    }

    if (!serviceType.isEmpty())
        processArguments.append(QString::fromLatin1(" --serviceType %1")
                                .arg(serviceType));

#ifndef QT_NO_DEBUG_OUTPUT
    processArguments.append(QString::fromLatin1(" -output-level debug"));
#endif

    if (!process &&
        !(process = new QProcess())) {
        emit q->failed();
        return;
    }

    pluginName = pluginFileName;
    serverName = providerId;

    qDebug() << __TIME__ <<__FILE__ << __func__ << processArguments;

    connect(process, SIGNAL(readyReadStandardError()),
            this, SLOT(onReadStandardError()));
    connect(process, SIGNAL(error(QProcess::ProcessError)),
            this, SLOT(onError(QProcess::ProcessError)));
    connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
            this, SLOT(onFinished(int, QProcess::ExitStatus)));
    connect(process, SIGNAL(started()), this, SLOT(setCommunicationChannel()));

    process->start(processArguments);
    PWATCHER_TRACE(pwatcher);
}

void ProviderPluginProxyPrivate::setCommunicationChannel()
{
    QLocalServer *server  = new QLocalServer();
    QLocalServer::removeServer(serverName);
    if (!server->listen(serverName))
        qDebug()<<"Server not up";
    else
        connect(server, SIGNAL(newConnection()), this, SLOT(readDataSent()));
}

void ProviderPluginProxyPrivate::readDataSent()
{
    QLocalServer *server = qobject_cast<QLocalServer*>(sender());
    QLocalSocket *socket = server->nextPendingConnection();
    if(!socket->waitForConnected())
        return;
    if(!socket->waitForReadyRead())
        return;
    QByteArray ba = socket->readAll();
    QString data(ba);
    accountInfo = data;
    socket->close();
}

bool ProviderPluginProxyPrivate::stopProcess()
{
    if (process == 0)
        return false;
    process->disconnect();
    process->close();
    return process->waitForFinished();
}

void ProviderPluginProxyPrivate::onReadStandardError()
{
    qDebug() << QString::fromLatin1(process->readAllStandardError());
}

void ProviderPluginProxyPrivate::onError(QProcess::ProcessError err)
{
    Q_Q(ProviderPluginProxy);

    PWATCHER_TRACE(pwatcher);
    if (err == QProcess::FailedToStart) {
        pluginName.clear();

        emit q->failed();
        if (process) {
            process->deleteLater();
            process = NULL;
        }
    }

    qDebug() << "Error: " << err;
}

void ProviderPluginProxyPrivate::onFinished(int exitCode,
                                            QProcess::ExitStatus exitStatus)
{
    Q_Q(ProviderPluginProxy);
    Q_UNUSED(exitCode);
    PWATCHER_TRACE(pwatcher) << exitCode;

    if (exitStatus == QProcess::CrashExit) {
        emit q->failed();
        process->deleteLater();
        process = NULL;
        return;
    }

    if (newAccountCreation) {
        QString value;
        if (!accountInfo.isEmpty())
            value = accountInfo;
        else {
            char buffer[16];
            process->readLine(buffer, sizeof(buffer));
            value = QString::fromAscii(buffer);
        }
        if (!value.isEmpty()) {
            QStringList resultList = value.split(" ");
            result = resultList.at(0).toInt();
            if (resultList.count() > 1)
                returnToApp = resultList.at(1).toInt();
            /* TODO: do we need the returnToApp value?
             * - if not, remove it completely (and from ProviderPluginProcess
             * - if yes, consider exposing it as an additional method
             */
            Q_UNUSED(returnToApp);
        }

        qDebug() << "Plugin output: " << result;

        emit q->created(result);
    } else
        emit q->edited();

    pluginName.clear();

    if (process) {
        process->deleteLater();
        process = NULL;
    }
}

ProviderPluginProxy::ProviderPluginProxy(QObject *parent):
    QObject(parent),
    d_ptr(new ProviderPluginProxyPrivate())
{
    Q_D(ProviderPluginProxy);

    d->q_ptr = this;
}

ProviderPluginProxy::~ProviderPluginProxy()
{
    Q_D(ProviderPluginProxy);
    delete d;
}

void ProviderPluginProxy::createAccount(Provider *provider,
                                        const QString &serviceType)
{
    Q_D(ProviderPluginProxy);
    PWATCHER_TRACE(pwatcher);

    if (!provider) {
        qCritical() << " NULL pointer to provider";
        emit failed();
        return;
    }

    d->startProcess(provider, 0, serviceType);
}

void ProviderPluginProxy::editAccount(Account *account,
                                      const QString &serviceType)
{
    Q_D(ProviderPluginProxy);
    PWATCHER_TRACE(pwatcher);

    if (!account) {
        qCritical() << " NULL pointer to account";
        emit failed();
        return;
    }

    Manager *manager = account->manager();
    Provider *provider = manager->provider(account->providerName());
    d->startProcess(provider, account->id(), serviceType);
}

void ProviderPluginProxy::stopProcess()
{
    Q_D(ProviderPluginProxy);
    d->stopProcess();
}

bool ProviderPluginProxy::isPluginRunning()
{
    Q_D(ProviderPluginProxy);
    return d->process != NULL;
}

QString ProviderPluginProxy::pluginName()
{
    if (!isPluginRunning())
        return QString();

    Q_D(ProviderPluginProxy);
    return d->pluginName;
}

<commit_msg>Fixes 210679-Accounts-ui crashes while going back from Login view to Provider list view<commit_after>/*
 * This file is part of accounts-ui
 *
 * Copyright (C) 2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include "provider-plugin-proxy.h"
#include "provider-plugin-proxy-priv.h"

#include <QProcess>
#include <QDebug>
#include <QLocalServer>
#include <QLocalSocket>

using namespace Accounts;
using namespace AccountsUI;

ProviderPluginProxyPrivate::~ProviderPluginProxyPrivate()
{
    qDebug() << Q_FUNC_INFO;
    if (process) {
        stopProcess();
        delete process;
    }
}

void ProviderPluginProxyPrivate::startProcess(Provider *provider,
                                              AccountId accountId,
                                              const QString &serviceType)
{
    Q_Q(ProviderPluginProxy);

    PWATCHER_RESTART(pwatcher);
    const char pluginNamePattern[] = "%1plugin";

    /*
     * TODO: specify dir path by some variable
     * */
    QDir pluginDir(QString::fromLatin1("/usr/libexec/AccountsUI"));
    QDomElement root(provider->domDocument().documentElement());
    QString pluginTypeName(root.
                           firstChildElement(QString::fromLatin1("plugin")).
                           text());

    QString pluginFileName(QString::fromLatin1(pluginNamePattern)
                           .arg(pluginTypeName));
    QFileInfo pluginFileInfo(pluginDir, pluginFileName);

    QString providerId(root.attribute(QLatin1String("id")));

    //fallback use id as a plugin name
    if (!pluginFileInfo.exists()) {
        pluginFileName = QString::fromLatin1(pluginNamePattern).arg(providerId);
        pluginFileInfo.setFile(pluginDir, pluginFileName);

        if (!pluginFileInfo.exists()) {
            pluginFileName = QString::fromLatin1(pluginNamePattern).
                                      arg(QLatin1String("generic"));
            pluginFileInfo.setFile(pluginDir, pluginFileName);
        }
    }

    if (!pluginFileInfo.exists()) {
        emit q->failed();
        return;
    }

    QString processArguments;
    Qt::HANDLE windowId = MApplication::instance()->activeWindow()->winId();

    if (accountId != 0) {
        processArguments = QString::fromLatin1("%1 --edit %2 --windowId %3")
            .arg(pluginFileInfo.canonicalFilePath())
            .arg(accountId)
            .arg(windowId);

        newAccountCreation = false;
    } else {
        processArguments = QString::fromLatin1("%1 --create %2 --windowId %3")
            .arg(pluginFileInfo.canonicalFilePath())
            .arg(providerId)
            .arg(windowId);

        newAccountCreation = true;
    }

    if (!serviceType.isEmpty())
        processArguments.append(QString::fromLatin1(" --serviceType %1")
                                .arg(serviceType));

#ifndef QT_NO_DEBUG_OUTPUT
    processArguments.append(QString::fromLatin1(" -output-level debug"));
#endif

    if (!process &&
        !(process = new QProcess())) {
        emit q->failed();
        return;
    }

    pluginName = pluginFileName;
    serverName = providerId;

    qDebug() << __TIME__ <<__FILE__ << __func__ << processArguments;

    connect(process, SIGNAL(readyReadStandardError()),
            this, SLOT(onReadStandardError()));
    connect(process, SIGNAL(error(QProcess::ProcessError)),
            this, SLOT(onError(QProcess::ProcessError)));
    connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
            this, SLOT(onFinished(int, QProcess::ExitStatus)));
    connect(process, SIGNAL(started()), this, SLOT(setCommunicationChannel()));

    process->start(processArguments);
    PWATCHER_TRACE(pwatcher);
}

void ProviderPluginProxyPrivate::setCommunicationChannel()
{
    QLocalServer *server  = new QLocalServer();
    QLocalServer::removeServer(serverName);
    if (!server->listen(serverName))
        qDebug()<<"Server not up";
    else
        connect(server, SIGNAL(newConnection()), this, SLOT(readDataSent()));
}

void ProviderPluginProxyPrivate::readDataSent()
{
    QLocalServer *server = qobject_cast<QLocalServer*>(sender());
    QLocalSocket *socket = server->nextPendingConnection();
    if(!socket->waitForConnected())
        return;
    if(!socket->waitForReadyRead())
        return;
    QByteArray ba = socket->readAll();
    QString data(ba);
    accountInfo = data;
    socket->close();
}

bool ProviderPluginProxyPrivate::stopProcess()
{
    if (process == 0)
        return false;
    process->disconnect();
    process->close();
    return process->waitForFinished();
}

void ProviderPluginProxyPrivate::onReadStandardError()
{
    qDebug() << QString::fromLatin1(process->readAllStandardError());
}

void ProviderPluginProxyPrivate::onError(QProcess::ProcessError err)
{
    Q_Q(ProviderPluginProxy);

    PWATCHER_TRACE(pwatcher);
    if (err == QProcess::FailedToStart) {
        pluginName.clear();

        emit q->failed();
        if (process) {
            process->deleteLater();
            process = NULL;
        }
    }

    qDebug() << "Error: " << err;
}

void ProviderPluginProxyPrivate::onFinished(int exitCode,
                                            QProcess::ExitStatus exitStatus)
{
    Q_Q(ProviderPluginProxy);
    Q_UNUSED(exitCode);
    PWATCHER_TRACE(pwatcher) << exitCode;
    int returnToApp = 0;
    int result = 0;

    if (exitStatus == QProcess::CrashExit) {
        emit q->failed();
        process->deleteLater();
        process = NULL;
        return;
    }

    if (newAccountCreation) {
        QString value;
        if (!accountInfo.isEmpty())
            value = accountInfo;
        else {
            char buffer[16];
            process->readLine(buffer, sizeof(buffer));
            value = QString::fromAscii(buffer);
        }
        if (!value.isEmpty()) {
            QStringList resultList = value.split(" ");
            result = resultList.at(0).toInt();
            if (resultList.count() > 1)
                returnToApp = resultList.at(1).toInt();
            /* TODO: do we need the returnToApp value?
             * - if not, remove it completely (and from ProviderPluginProcess
             * - if yes, consider exposing it as an additional method
             */
            Q_UNUSED(returnToApp);
        }

        qDebug() << "Plugin output: " << result;

        emit q->created(result);
    } else
        emit q->edited();

    pluginName.clear();

    if (process) {
        process->deleteLater();
        process = NULL;
    }
}

ProviderPluginProxy::ProviderPluginProxy(QObject *parent):
    QObject(parent),
    d_ptr(new ProviderPluginProxyPrivate())
{
    Q_D(ProviderPluginProxy);

    d->q_ptr = this;
}

ProviderPluginProxy::~ProviderPluginProxy()
{
    Q_D(ProviderPluginProxy);
    delete d;
}

void ProviderPluginProxy::createAccount(Provider *provider,
                                        const QString &serviceType)
{
    Q_D(ProviderPluginProxy);
    PWATCHER_TRACE(pwatcher);

    if (!provider) {
        qCritical() << " NULL pointer to provider";
        emit failed();
        return;
    }

    d->startProcess(provider, 0, serviceType);
}

void ProviderPluginProxy::editAccount(Account *account,
                                      const QString &serviceType)
{
    Q_D(ProviderPluginProxy);
    PWATCHER_TRACE(pwatcher);

    if (!account) {
        qCritical() << " NULL pointer to account";
        emit failed();
        return;
    }

    Manager *manager = account->manager();
    Provider *provider = manager->provider(account->providerName());
    d->startProcess(provider, account->id(), serviceType);
}

void ProviderPluginProxy::stopProcess()
{
    Q_D(ProviderPluginProxy);
    d->stopProcess();
}

bool ProviderPluginProxy::isPluginRunning()
{
    Q_D(ProviderPluginProxy);
    return d->process != NULL;
}

QString ProviderPluginProxy::pluginName()
{
    if (!isPluginRunning())
        return QString();

    Q_D(ProviderPluginProxy);
    return d->pluginName;
}

<|endoftext|>


<commit_before>/**************************************************************
COSC 501
Elliott Plack
14 NOV 2013                            Due date: 30 NOV 2013

Problem:
	Write a program that plays the game of HANGMAN(guessing a
	mystery word).  Read a word to be guessed from a file into
	successive elements of the array WORD. The player must
	guess the letters belonging to WORD. A single guessing
	session should be terminated when either all letters have
	been guessed correctly (player wins) or a specified number
	of incorrect guesses have been made (computer wins). A run
	must consist of at least two sessions: one player wins and
	one computer wins. The player decides whether or not to
	start a new session.

***************************************************************/

#include <iomanip>
#include <iostream>
#include <fstream>
#include <string>
#include <time.h> // for random
using namespace std;

ifstream inFile;     // define ifstream to inFile command
ofstream outFile;    // define outfile2

void readString();
void initialize(unsigned long); // function to initalize everything
void guess();

// global variables
//char guess; // guess from user
string word; // word to be read from file (the solution)
string solution; // solution (guessed by user)
unsigned long wordLength; // length of word

// functions

int main() // reads in the file and sets the functions in motion
{
	readString();
	initialize(wordLength); // sends length of word to initialize function
	guess();

	return 0;
}

void readString()
{
	int random20 = 0; // random number
	string dictionary[20]; // 20 words to load from file

	inFile.open("Words4Hangman.txt"); // open input file

	while (inFile.good())
	{
		for (int i = 0; i < 20; i++)
		{
			inFile >> dictionary[i]; // load file and fill dict
		}
	}

	inFile.close(); // close the file

	srand((int)time(NULL)); // initialize random seed
	random20 = (rand() % 20); // set random to 20 +-

	word = dictionary[rand() % 20]; // set word = to a random letter in the dictionary
	cout << word << endl; // cheater! (testing)
	wordLength = word.size(); // size (length) of the string
}

void initialize(unsigned long wordLength)
{
	solution.assign(wordLength, '*');

	cout << "Solution: " << solution << endl; // test
}

void guess()
{
	string guessWord;
	cout << "Guess a word\n";
	cin >> guessWord;

	if (guessWord.compare(word) == 0)
	{
		cout << "success";
	}
	else
	{
		cout << "fail";
	}
}<commit_msg>progress<commit_after>/**************************************************************
COSC 501
Elliott Plack
14 NOV 2013                            Due date: 30 NOV 2013

Problem:
	Write a program that plays the game of HANGMAN(guessing a
	mystery word).  Read a word to be guessed from a file into
	successive elements of the array WORD. The player must
	guess the letters belonging to WORD. A single guessing
	session should be terminated when either all letters have
	been guessed correctly (player wins) or a specified number
	of incorrect guesses have been made (computer wins). A run
	must consist of at least two sessions: one player wins and
	one computer wins. The player decides whether or not to
	start a new session.

***************************************************************/

#include <iomanip>
#include <iostream>
#include <fstream>
#include <string>
#include <time.h> // for random
using namespace std;

ifstream inFile;     // define ifstream to inFile command
ofstream outFile;    // define outfile2

void readString();
void initialize(unsigned long); // function to initalize everything
void guess();

// global variables
//char guess; // guess from user
string word; // word to be read from file (the solution)
string solution; // solution (guessed by user)
unsigned long wordLength; // length of word

// functions

int main() // reads in the file and sets the functions in motion
{
	readString();
	initialize(wordLength); // sends length of word to initialize function
	cout << "Let's play hangman!\n";
	guess();

	return 0;
}

void readString()
{
	int random20 = 0; // random number
	string dictionary[20]; // 20 words to load from file

	inFile.open("Words4Hangman.txt"); // open input file

	while (inFile.good())
	{
		for (int i = 0; i < 20; i++)
		{
			inFile >> dictionary[i]; // load file and fill dict
		}
	}

	inFile.close(); // close the file

	srand((int)time(NULL)); // initialize random seed
	random20 = (rand() % 20); // set random to 20 +-

	word = dictionary[rand() % 20]; // set word = to a random letter in the dictionary
	cout << word << endl; // cheater! (testing)
	wordLength = word.size(); // size (length) of the string
}

void initialize(unsigned long wordLength)
{
	solution.assign(wordLength, '*');

	cout << "Solution: " << solution << endl; // test
}

void guess()
{
	char guessLetter = ' '; // letter to guess
	cout << solution << endl; // output solution
	cout << "Guess a letter\n";
	cin >> guessLetter;

	for (unsigned long i = 0; i < wordLength; i++)
	{
		if (guessLetter == word[i])
		{
			cout << "char " << i << " is " << guessLetter << endl;
		}
		cout << guessLetter << "is not in the word";
	}

}<|endoftext|>


<commit_before>// PbniHash.cpp : PBNI class
#define _CRT_SECURE_NO_DEPRECATE

#include "PbniHash.h"

#ifdef _DEBUG
#define	VERSION_STR	_T(" (Debug version - ") _T(__DATE__) _T(" ") _T(__TIME__) _T(")")
#else
#define	VERSION_STR	_T(" (Release version - ") _T(__DATE__) _T(" ") _T(__TIME__) _T(")")
#endif

// default constructor
PbniHash::PbniHash()
{
}

PbniHash::PbniHash( IPB_Session * pSession )
:m_pSession( pSession )
{
	struct hi_init_set hi_set;

	m_lastError = HI_ERR_SUCCESS;
	hi_set_zero(&hi_set);
	hi_set_bucket_size(&hi_set, TABLE_SIZE);
	hi_set_hash_alg(&hi_set, HI_HASH_DEFAULT);
	hi_set_coll_eng(&hi_set, COLL_ENG_LIST);
	//hi_set_key_cmp_func(&hi_set, hi_cmp_int32);
	hi_set_key_cmp_func(&hi_set, hi_cmp_str);

	hi_create(&m_hi_handle, &hi_set);	//todo: check error
}

// destructor
PbniHash::~PbniHash()
{
	DoPurge();
	hi_fini(m_hi_handle);
}

// method called by PowerBuilder to invoke PBNI class methods
PBXRESULT PbniHash::Invoke
(
	IPB_Session * session,
	pbobject obj,
	pbmethodID mid,
	PBCallInfo * ci
)
{
   PBXRESULT pbxr = PBX_OK;

	switch ( mid )
	{
		case mid_Hello:
			pbxr = this->Hello( ci );
         break;

		case mid_Add:
			pbxr = this->Add(ci);
			break;
		case mid_Get:
			pbxr = this->Get(ci);
			break;
		case mid_Remove:
			pbxr = this->Remove(ci);
			break;
		case mid_Count:
			pbxr = this->Count(ci);
			break;
		case mid_GetKeys:
			pbxr = this ->GetKeys(ci);
			break;
		case mid_GetLastError:
			pbxr = this ->GetLastErr(ci);
			break;
		case mid_GetLastErrMsg:
			pbxr = this ->GetLastErrMsg(ci);
			break;
		/*case mid_UseStrCompare:
			pbxr = this ->GetKeys(ci);//!!!!
			break;*/
		case mid_Purge:
			pbxr = this->Purge(ci);
			break;
		case mid_Set:
			pbxr = this->Set(ci);
			break;
		default:
			pbxr = PBX_E_INVOKE_METHOD_AMBIGUOUS;
	}

	return pbxr;
}

void PbniHash::Destroy()
{
   delete this;
}

// Method callable from PowerBuilder
PBXRESULT PbniHash::Hello( PBCallInfo * ci )
{
	PBXRESULT	pbxr = PBX_OK;

	// return value
	ci->returnValue->SetString( _T("Hello from PbniHash") VERSION_STR );

	return pbxr;
}

PBXRESULT PbniHash::Add( PBCallInfo * ci )
{
	PBXRESULT	pbxr = PBX_OK;
	int hi_res;
	int keyLen;

	// check arguments
	if ( ci->pArgs->GetAt(0)->IsNull() || ci->pArgs->GetAt(1)->IsNull() )
	{
		// if any of the passed arguments is null, return the null value
		ci->returnValue->SetToNull();
	}
	else
	{
		pbstring key = ci->pArgs->GetAt(0)->GetString();
		LPCTSTR tszKey = m_pSession->GetString(key);

		//ce qui suit est identique a faire un AcquireValue sur la key...
		//wchar_t *localKey = (wchar_t *)malloc((wcslen(tszKey) + 1) * sizeof(wchar_t));
		//wcscpy(localKey, tszKey);
		keyLen = wcstombs(NULL, (LPWSTR)tszKey, 0) + 2;
		char *localKey = (char*)malloc(keyLen);
		wcstombs(localKey, (LPWSTR)tszKey, keyLen);

		IPB_Value *data = m_pSession->AcquireValue(ci->pArgs->GetAt(1));

		PPBDATAREC dataRecord = (PPBDATAREC)malloc(sizeof(PBDATAREC));
		dataRecord->key = localKey;
		dataRecord->data = data;

		hi_res = hi_insert(m_hi_handle, (void*)dataRecord->key, strlen(localKey), dataRecord /*tszData*/);
		if (HI_SUCCESS == hi_res)
			ci->returnValue->SetBool(true);
		else
			ci->returnValue->SetBool(false);
		//TODO: need to tell if HI_ERR_DUPKEY
		m_lastError = hi_res;
	}
	return pbxr;
}

PBXRESULT PbniHash::Get(PBCallInfo *ci)
{
	PBXRESULT	pbxr = PBX_OK;
	int iRet;
	PPBDATAREC data_ptr;

	if ( ci->pArgs->GetAt(0)->IsNull())
	{
		// if any of the passed arguments is null, return the null value
		ci->returnValue->SetToNull();
	}
	else
	{
		pbstring key = ci->pArgs->GetAt(0)->GetString();
		LPCTSTR tszKey = m_pSession->GetString(key);
		int keyLen = wcstombs(NULL, (LPWSTR)tszKey, 0) + 2;
		char *localKey = (char*)malloc(keyLen);
		wcstombs(localKey, (LPWSTR)tszKey, keyLen);

		//search the key
		iRet = hi_get(m_hi_handle, (void*)localKey, strlen(localKey), (void**)&data_ptr);
		if (HI_SUCCESS == iRet)
			m_pSession->SetValue(ci->returnValue, (IPB_Value*)data_ptr->data);
		else
			ci->returnValue->SetToNull();
		free(localKey);
		m_lastError = iRet;
	}
	return pbxr;
}

PBXRESULT PbniHash::Set(PBCallInfo *ci)
{
	PBXRESULT	pbxr = PBX_OK;
	int iRet;
	PPBDATAREC data_ptr;

	if ( ci->pArgs->GetAt(0)->IsNull() || ci->pArgs->GetAt(1)->IsNull() )
	{
		// if any of the passed arguments is null, return the null value
		ci->returnValue->SetToNull();
	}
	else
	{
		pbstring key = ci->pArgs->GetAt(0)->GetString();
		LPCTSTR tszKey = m_pSession->GetString(key);
		int keyLen = wcstombs(NULL, (LPWSTR)tszKey, 0) + 2;
		char *localKey = (char*)malloc(keyLen);
		wcstombs(localKey, (LPWSTR)tszKey, keyLen);

		//search the key
		iRet = hi_get(m_hi_handle, (void*)localKey, strlen(localKey), (void**)&data_ptr);
		if (HI_SUCCESS == iRet)
		{
			//exists, so we can free the existing data and replace by our new one
			m_pSession->ReleaseValue((IPB_Value*)data_ptr->data);
			IPB_Value *data = m_pSession->AcquireValue(ci->pArgs->GetAt(1));
			data_ptr->data = data;
			ci->returnValue->SetBool(true);
			free(localKey);
		}
		else
		{
			IPB_Value *data = m_pSession->AcquireValue(ci->pArgs->GetAt(1));
			PPBDATAREC dataRecord = (PPBDATAREC)malloc(sizeof(PBDATAREC));
			dataRecord->key = localKey;
			dataRecord->data = data;
			iRet = hi_insert(m_hi_handle, (void*)dataRecord->key, strlen(localKey), dataRecord /*tszData*/);
			if (HI_SUCCESS == iRet)
				ci->returnValue->SetBool(true);
			else
				ci->returnValue->SetBool(false);
		}
		m_lastError = iRet;
	}
	return pbxr;
}

PBXRESULT PbniHash::Remove(PBCallInfo *ci)
{
	PBXRESULT	pbxr = PBX_OK;
	int iRet;
	PPBDATAREC data_ptr;

	if ( ci->pArgs->GetAt(0)->IsNull())
	{
		// if any of the passed arguments is null, return the null value
		ci->returnValue->SetToNull();
	}
	else
	{
		pbstring key = ci->pArgs->GetAt(0)->GetString();
		LPCTSTR tszKey = m_pSession->GetString(key);
		int keyLen = wcstombs(NULL, (LPWSTR)tszKey, 0) + 2;
		char *localKey = (char*)malloc(keyLen);
		wcstombs(localKey, (LPWSTR)tszKey, keyLen);

		//search the key
		iRet = hi_remove(m_hi_handle, (void*)localKey, strlen(localKey),(void**)&data_ptr);
		if (HI_SUCCESS == iRet)
		{
			free(data_ptr->key);
			m_pSession->ReleaseValue((IPB_Value*)data_ptr->data);
			free(data_ptr);
			ci->returnValue->SetBool(true);
		}
		else
			ci->returnValue->SetBool(false);
		free(localKey);
		m_lastError = iRet;
	}
	return pbxr;
}

PBXRESULT PbniHash::Count(PBCallInfo *ci)
{
	PBXRESULT	pbxr = PBX_OK;
	pbulong ulRet = m_hi_handle->no_objects;
	ci->returnValue->SetUlong(ulRet);

	return pbxr;
}

PBXRESULT PbniHash::GetLastErr(PBCallInfo *ci)
{
	PBXRESULT	pbxr = PBX_OK;
	//pblong lRet = m_lastError;
	ci->returnValue->SetLong(m_lastError);

	return pbxr;
}

PBXRESULT PbniHash::GetLastErrMsg(PBCallInfo *ci)
{
	PBXRESULT	pbxr = PBX_OK;
	const char *msg;

	msg = hi_strerror(m_lastError);
	int msgLen = mbstowcs(NULL, msg, strlen(msg)+1);
	LPWSTR wmsg = (LPWSTR)malloc((msgLen+1) * sizeof(wchar_t));
	mbstowcs(wmsg, msg, strlen(msg)+1);
	ci->returnValue->SetString(wmsg);
	free(wmsg);
	return pbxr;
}

PBXRESULT PbniHash::GetKeys(PBCallInfo *ci)
{
	PBXRESULT pbxr = PBX_OK;

	if(ci->pArgs->GetAt(0)->IsNull() || !ci->pArgs->GetAt(0)->IsArray() || !ci->pArgs->GetAt(0)->IsByRef())
	{
		//there must be one reference to an array
		ci->returnValue->SetBool(false);
	}
	else
	{
		pblong dim[1] = {1};						//on peut avoir des tableaux avec plusieurs dimensions
													//ici on utilise un tableau  1 dimension, et on commence  1
		pbarray keys;
		void *key, *data;
		unsigned long keylen;

		hi_iterator_t *iter;

		if(HI_SUCCESS == hi_iterator_create(m_hi_handle, &iter))
		{
			keys = m_pSession->NewUnboundedSimpleArray(pbvalue_string);
			while(HI_SUCCESS == hi_iterator_getnext(iter, &data, &key, &keylen))
			{
				int keyLen = mbstowcs(NULL, (const char*)key, 0);
				LPWSTR wstr = (LPWSTR)malloc((keyLen+1) * sizeof(wchar_t));
				mbstowcs(wstr, (const char*)key, keyLen + 1);
#ifdef _DEBUG
				OutputDebugString(wstr);
#endif
				m_pSession->SetStringArrayItem(keys, dim, wstr);
				dim[0]++;		//prochain index
				free(wstr);
			}
			hi_iterator_fini(iter);
			ci->pArgs->GetAt(0)->SetArray(keys);
			ci->returnValue->SetBool(true);
		}
	}

	return pbxr;
}

PBXRESULT PbniHash::Purge(PBCallInfo *ci)
{
	PBXRESULT pbxr = PBX_OK;

	DoPurge();
	return pbxr;
}

void PbniHash::DoPurge()
{
	void *key, *data;
	unsigned long keylen;
	int iRet;
	PPBDATAREC data_ptr;
	hi_iterator_t *iter;

	if(HI_SUCCESS == hi_iterator_create(m_hi_handle, &iter))
	{
		while(HI_SUCCESS == hi_iterator_getnext(iter, &data, &key, &keylen))
		{
#ifdef _DEBUG
			OutputDebugStringA((char*)key);
#endif
			iRet = hi_remove(m_hi_handle, key, keylen,(void**)&data_ptr);
			if (HI_SUCCESS == iRet)
			{
				free(data_ptr->key);
				m_pSession->ReleaseValue((IPB_Value*)(data_ptr->data));
				free(data_ptr);
			}
		}
		hi_iterator_fini(iter);
	}
}
<commit_msg>Always create and return a new array for GetKeys, even if the hash has no data<commit_after>// PbniHash.cpp : PBNI class
#define _CRT_SECURE_NO_DEPRECATE

#include "PbniHash.h"

#ifdef _DEBUG
#define	VERSION_STR	_T(" (Debug version - ") _T(__DATE__) _T(" ") _T(__TIME__) _T(")")
#else
#define	VERSION_STR	_T(" (Release version - ") _T(__DATE__) _T(" ") _T(__TIME__) _T(")")
#endif

// default constructor
PbniHash::PbniHash()
{
}

PbniHash::PbniHash( IPB_Session * pSession )
:m_pSession( pSession )
{
	struct hi_init_set hi_set;

	m_lastError = HI_ERR_SUCCESS;
	hi_set_zero(&hi_set);
	hi_set_bucket_size(&hi_set, TABLE_SIZE);
	hi_set_hash_alg(&hi_set, HI_HASH_DEFAULT);
	hi_set_coll_eng(&hi_set, COLL_ENG_LIST);
	//hi_set_key_cmp_func(&hi_set, hi_cmp_int32);
	hi_set_key_cmp_func(&hi_set, hi_cmp_str);

	hi_create(&m_hi_handle, &hi_set);	//todo: check error
}

// destructor
PbniHash::~PbniHash()
{
	DoPurge();
	hi_fini(m_hi_handle);
}

// method called by PowerBuilder to invoke PBNI class methods
PBXRESULT PbniHash::Invoke
(
	IPB_Session * session,
	pbobject obj,
	pbmethodID mid,
	PBCallInfo * ci
)
{
   PBXRESULT pbxr = PBX_OK;

	switch ( mid )
	{
		case mid_Hello:
			pbxr = this->Hello( ci );
         break;

		case mid_Add:
			pbxr = this->Add(ci);
			break;
		case mid_Get:
			pbxr = this->Get(ci);
			break;
		case mid_Remove:
			pbxr = this->Remove(ci);
			break;
		case mid_Count:
			pbxr = this->Count(ci);
			break;
		case mid_GetKeys:
			pbxr = this ->GetKeys(ci);
			break;
		case mid_GetLastError:
			pbxr = this ->GetLastErr(ci);
			break;
		case mid_GetLastErrMsg:
			pbxr = this ->GetLastErrMsg(ci);
			break;
		/*case mid_UseStrCompare:
			pbxr = this ->GetKeys(ci);//!!!!
			break;*/
		case mid_Purge:
			pbxr = this->Purge(ci);
			break;
		case mid_Set:
			pbxr = this->Set(ci);
			break;
		default:
			pbxr = PBX_E_INVOKE_METHOD_AMBIGUOUS;
	}

	return pbxr;
}

void PbniHash::Destroy()
{
   delete this;
}

// Method callable from PowerBuilder
PBXRESULT PbniHash::Hello( PBCallInfo * ci )
{
	PBXRESULT	pbxr = PBX_OK;

	// return value
	ci->returnValue->SetString( _T("Hello from PbniHash") VERSION_STR );

	return pbxr;
}

PBXRESULT PbniHash::Add( PBCallInfo * ci )
{
	PBXRESULT	pbxr = PBX_OK;
	int hi_res;
	int keyLen;

	// check arguments
	if ( ci->pArgs->GetAt(0)->IsNull() || ci->pArgs->GetAt(1)->IsNull() )
	{
		// if any of the passed arguments is null, return the null value
		ci->returnValue->SetToNull();
	}
	else
	{
		pbstring key = ci->pArgs->GetAt(0)->GetString();
		LPCTSTR tszKey = m_pSession->GetString(key);

		//ce qui suit est identique a faire un AcquireValue sur la key...
		//wchar_t *localKey = (wchar_t *)malloc((wcslen(tszKey) + 1) * sizeof(wchar_t));
		//wcscpy(localKey, tszKey);
		keyLen = wcstombs(NULL, (LPWSTR)tszKey, 0) + 2;
		char *localKey = (char*)malloc(keyLen);
		wcstombs(localKey, (LPWSTR)tszKey, keyLen);

		IPB_Value *data = m_pSession->AcquireValue(ci->pArgs->GetAt(1));

		PPBDATAREC dataRecord = (PPBDATAREC)malloc(sizeof(PBDATAREC));
		dataRecord->key = localKey;
		dataRecord->data = data;

		hi_res = hi_insert(m_hi_handle, (void*)dataRecord->key, strlen(localKey), dataRecord /*tszData*/);
		if (HI_SUCCESS == hi_res)
			ci->returnValue->SetBool(true);
		else
			ci->returnValue->SetBool(false);
		//TODO: need to tell if HI_ERR_DUPKEY
		m_lastError = hi_res;
	}
	return pbxr;
}

PBXRESULT PbniHash::Get(PBCallInfo *ci)
{
	PBXRESULT	pbxr = PBX_OK;
	int iRet;
	PPBDATAREC data_ptr;

	if ( ci->pArgs->GetAt(0)->IsNull())
	{
		// if any of the passed arguments is null, return the null value
		ci->returnValue->SetToNull();
	}
	else
	{
		pbstring key = ci->pArgs->GetAt(0)->GetString();
		LPCTSTR tszKey = m_pSession->GetString(key);
		int keyLen = wcstombs(NULL, (LPWSTR)tszKey, 0) + 2;
		char *localKey = (char*)malloc(keyLen);
		wcstombs(localKey, (LPWSTR)tszKey, keyLen);

		//search the key
		iRet = hi_get(m_hi_handle, (void*)localKey, strlen(localKey), (void**)&data_ptr);
		if (HI_SUCCESS == iRet)
			m_pSession->SetValue(ci->returnValue, (IPB_Value*)data_ptr->data);
		else
			ci->returnValue->SetToNull();
		free(localKey);
		m_lastError = iRet;
	}
	return pbxr;
}

PBXRESULT PbniHash::Set(PBCallInfo *ci)
{
	PBXRESULT	pbxr = PBX_OK;
	int iRet;
	PPBDATAREC data_ptr;

	if ( ci->pArgs->GetAt(0)->IsNull() || ci->pArgs->GetAt(1)->IsNull() )
	{
		// if any of the passed arguments is null, return the null value
		ci->returnValue->SetToNull();
	}
	else
	{
		pbstring key = ci->pArgs->GetAt(0)->GetString();
		LPCTSTR tszKey = m_pSession->GetString(key);
		int keyLen = wcstombs(NULL, (LPWSTR)tszKey, 0) + 2;
		char *localKey = (char*)malloc(keyLen);
		wcstombs(localKey, (LPWSTR)tszKey, keyLen);

		//search the key
		iRet = hi_get(m_hi_handle, (void*)localKey, strlen(localKey), (void**)&data_ptr);
		if (HI_SUCCESS == iRet)
		{
			//exists, so we can free the existing data and replace by our new one
			m_pSession->ReleaseValue((IPB_Value*)data_ptr->data);
			IPB_Value *data = m_pSession->AcquireValue(ci->pArgs->GetAt(1));
			data_ptr->data = data;
			ci->returnValue->SetBool(true);
			free(localKey);
		}
		else
		{
			IPB_Value *data = m_pSession->AcquireValue(ci->pArgs->GetAt(1));
			PPBDATAREC dataRecord = (PPBDATAREC)malloc(sizeof(PBDATAREC));
			dataRecord->key = localKey;
			dataRecord->data = data;
			iRet = hi_insert(m_hi_handle, (void*)dataRecord->key, strlen(localKey), dataRecord /*tszData*/);
			if (HI_SUCCESS == iRet)
				ci->returnValue->SetBool(true);
			else
				ci->returnValue->SetBool(false);
		}
		m_lastError = iRet;
	}
	return pbxr;
}

PBXRESULT PbniHash::Remove(PBCallInfo *ci)
{
	PBXRESULT	pbxr = PBX_OK;
	int iRet;
	PPBDATAREC data_ptr;

	if ( ci->pArgs->GetAt(0)->IsNull())
	{
		// if any of the passed arguments is null, return the null value
		ci->returnValue->SetToNull();
	}
	else
	{
		pbstring key = ci->pArgs->GetAt(0)->GetString();
		LPCTSTR tszKey = m_pSession->GetString(key);
		int keyLen = wcstombs(NULL, (LPWSTR)tszKey, 0) + 2;
		char *localKey = (char*)malloc(keyLen);
		wcstombs(localKey, (LPWSTR)tszKey, keyLen);

		//search the key
		iRet = hi_remove(m_hi_handle, (void*)localKey, strlen(localKey),(void**)&data_ptr);
		if (HI_SUCCESS == iRet)
		{
			free(data_ptr->key);
			m_pSession->ReleaseValue((IPB_Value*)data_ptr->data);
			free(data_ptr);
			ci->returnValue->SetBool(true);
		}
		else
			ci->returnValue->SetBool(false);
		free(localKey);
		m_lastError = iRet;
	}
	return pbxr;
}

PBXRESULT PbniHash::Count(PBCallInfo *ci)
{
	PBXRESULT	pbxr = PBX_OK;
	pbulong ulRet = m_hi_handle->no_objects;
	ci->returnValue->SetUlong(ulRet);

	return pbxr;
}

PBXRESULT PbniHash::GetLastErr(PBCallInfo *ci)
{
	PBXRESULT	pbxr = PBX_OK;
	//pblong lRet = m_lastError;
	ci->returnValue->SetLong(m_lastError);

	return pbxr;
}

PBXRESULT PbniHash::GetLastErrMsg(PBCallInfo *ci)
{
	PBXRESULT	pbxr = PBX_OK;
	const char *msg;

	msg = hi_strerror(m_lastError);
	int msgLen = mbstowcs(NULL, msg, strlen(msg)+1);
	LPWSTR wmsg = (LPWSTR)malloc((msgLen+1) * sizeof(wchar_t));
	mbstowcs(wmsg, msg, strlen(msg)+1);
	ci->returnValue->SetString(wmsg);
	free(wmsg);
	return pbxr;
}

PBXRESULT PbniHash::GetKeys(PBCallInfo *ci)
{
	PBXRESULT pbxr = PBX_OK;

	if(ci->pArgs->GetAt(0)->IsNull() || !ci->pArgs->GetAt(0)->IsArray() || !ci->pArgs->GetAt(0)->IsByRef())
	{
		//there must be one reference to an array
		ci->returnValue->SetBool(false);
	}
	else
	{
		pblong dim[1] = {1};						//on peut avoir des tableaux avec plusieurs dimensions
													//ici on utilise un tableau  1 dimension, et on commence  1
		pbarray keys;
		void *key, *data;
		unsigned long keylen;

		hi_iterator_t *iter;

		// we always return a new array, it may be empty
		keys = m_pSession->NewUnboundedSimpleArray(pbvalue_string);

		if(HI_SUCCESS == hi_iterator_create(m_hi_handle, &iter)) //we can also get HI_ERR_NODATA if empty hash
		{

			while(HI_SUCCESS == hi_iterator_getnext(iter, &data, &key, &keylen))
			{
				int keyLen = mbstowcs(NULL, (const char*)key, 0);
				LPWSTR wstr = (LPWSTR)malloc((keyLen+1) * sizeof(wchar_t));
				mbstowcs(wstr, (const char*)key, keyLen + 1);
#ifdef _DEBUG
				OutputDebugString(wstr);
#endif
				m_pSession->SetStringArrayItem(keys, dim, wstr);
				dim[0]++;		//prochain index
				free(wstr);
			}
			hi_iterator_fini(iter);
		}
		ci->pArgs->GetAt(0)->SetArray(keys);
		ci->returnValue->SetBool(true);
	}

	return pbxr;
}

PBXRESULT PbniHash::Purge(PBCallInfo *ci)
{
	PBXRESULT pbxr = PBX_OK;

	DoPurge();
	return pbxr;
}

void PbniHash::DoPurge()
{
	void *key, *data;
	unsigned long keylen;
	int iRet;
	PPBDATAREC data_ptr;
	hi_iterator_t *iter;

	if(HI_SUCCESS == hi_iterator_create(m_hi_handle, &iter))
	{
		while(HI_SUCCESS == hi_iterator_getnext(iter, &data, &key, &keylen))
		{
#ifdef _DEBUG
			OutputDebugStringA((char*)key);
#endif
			iRet = hi_remove(m_hi_handle, key, keylen,(void**)&data_ptr);
			if (HI_SUCCESS == iRet)
			{
				free(data_ptr->key);
				m_pSession->ReleaseValue((IPB_Value*)(data_ptr->data));
				free(data_ptr);
			}
		}
		hi_iterator_fini(iter);
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ucbprops.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 05:17:11 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _UCBPROPS_HXX
#define _UCBPROPS_HXX

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HPP_
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#endif
#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif
#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#ifndef _UCBHELPER_MACROS_HXX
#include <ucbhelper/macros.hxx>
#endif

//=========================================================================

#define PROPERTIES_MANAGER_SERVICE_NAME "com.sun.star.ucb.PropertiesManager"

//============================================================================
//
// class UcbPropertiesManager.
//
//============================================================================

class UcbPropertiesManager :
                public cppu::OWeakObject,
                public com::sun::star::lang::XTypeProvider,
                public com::sun::star::lang::XServiceInfo,
                public com::sun::star::beans::XPropertySetInfo
{
    com::sun::star::uno::Sequence< com::sun::star::beans::Property >*
                                m_pProps;
    osl::Mutex                  m_aMutex;

private:
    sal_Bool queryProperty( const rtl::OUString& rName,
                            com::sun::star::beans::Property& rProp );

public:
    UcbPropertiesManager( const com::sun::star::uno::Reference<
                            com::sun::star::lang::XMultiServiceFactory >&
                                rxSMgr );
    virtual ~UcbPropertiesManager();

    // XInterface
    XINTERFACE_DECL()

    // XTypeProvider
    XTYPEPROVIDER_DECL()

    // XServiceInfo
    XSERVICEINFO_DECL()

    // XPropertySetInfo
    virtual com::sun::star::uno::Sequence<
                com::sun::star::beans::Property > SAL_CALL
    getProperties()
        throw( com::sun::star::uno::RuntimeException );
    virtual com::sun::star::beans::Property SAL_CALL
    getPropertyByName( const rtl::OUString& aName )
        throw( com::sun::star::beans::UnknownPropertyException,
               com::sun::star::uno::RuntimeException );
    virtual sal_Bool SAL_CALL
    hasPropertyByName( const rtl::OUString& Name )
        throw( com::sun::star::uno::RuntimeException );
};

#endif /* !_UCBPROPS_HXX */

<commit_msg>INTEGRATION: CWS changefileheader (1.3.138); FILE MERGED 2008/04/01 16:02:12 thb 1.3.138.3: #i85898# Stripping all external header guards 2008/04/01 12:58:00 thb 1.3.138.2: #i85898# Stripping all external header guards 2008/03/31 15:30:14 rt 1.3.138.1: #i87441# Change license header to LPGL v3.<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: ucbprops.hxx,v $
 * $Revision: 1.4 $
 *
 * 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.
 *
 ************************************************************************/

#ifndef _UCBPROPS_HXX
#define _UCBPROPS_HXX

#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XTypeProvider.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#include <cppuhelper/weak.hxx>
#include <osl/mutex.hxx>
#include <ucbhelper/macros.hxx>

//=========================================================================

#define PROPERTIES_MANAGER_SERVICE_NAME "com.sun.star.ucb.PropertiesManager"

//============================================================================
//
// class UcbPropertiesManager.
//
//============================================================================

class UcbPropertiesManager :
                public cppu::OWeakObject,
                public com::sun::star::lang::XTypeProvider,
                public com::sun::star::lang::XServiceInfo,
                public com::sun::star::beans::XPropertySetInfo
{
    com::sun::star::uno::Sequence< com::sun::star::beans::Property >*
                                m_pProps;
    osl::Mutex                  m_aMutex;

private:
    sal_Bool queryProperty( const rtl::OUString& rName,
                            com::sun::star::beans::Property& rProp );

public:
    UcbPropertiesManager( const com::sun::star::uno::Reference<
                            com::sun::star::lang::XMultiServiceFactory >&
                                rxSMgr );
    virtual ~UcbPropertiesManager();

    // XInterface
    XINTERFACE_DECL()

    // XTypeProvider
    XTYPEPROVIDER_DECL()

    // XServiceInfo
    XSERVICEINFO_DECL()

    // XPropertySetInfo
    virtual com::sun::star::uno::Sequence<
                com::sun::star::beans::Property > SAL_CALL
    getProperties()
        throw( com::sun::star::uno::RuntimeException );
    virtual com::sun::star::beans::Property SAL_CALL
    getPropertyByName( const rtl::OUString& aName )
        throw( com::sun::star::beans::UnknownPropertyException,
               com::sun::star::uno::RuntimeException );
    virtual sal_Bool SAL_CALL
    hasPropertyByName( const rtl::OUString& Name )
        throw( com::sun::star::uno::RuntimeException );
};

#endif /* !_UCBPROPS_HXX */

<|endoftext|>