<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkExceptionObjectTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

//
//  TO COMPILE:
//  $(CC) -I ../../../Code/Common -LANG:std -o itkExceptionObjectTest
//     itkExceptionObjectTest.cxx $../../../Code/Common/itkExceptionObject.cxx
//

#include "itkExceptionObject.h"
#include <iostream>

class mammal
 { public:  virtual int GetType()=0;  virtual bool operator== (mammal &); };
class human : public mammal {  public: int GetType() { return 32; }};
class naked_mole_rat : public mammal{ public:  int GetType() { return 2; }};

bool mammal::operator== (mammal &o)
{
  if ( this->GetType() != o.GetType() )
    {
    itk::IncompatibleOperandsError e(__FILE__, __LINE__);
    e.SetLocation("bool mammal::operator==(mammal&, mammal&)");
    e.SetDescription("Cannot compare mammals of unequal type");
    throw e;
    }
  else
    {
    if ( /* blah blah blah */ 1)
      {
      return true;
      }
    else
      {
      return false;
      }
    }
}

int lookup(const int& i)
{
  static int table[5] = { 23,42,42,32,12 };
  if ( ! ( 0 <= i && i < 5 ) )
    {
    itk::RangeError e(__FILE__, __LINE__);
    e.SetLocation("int lookup(const int& )");
    e.SetDescription("Attempted to access out-of-bounds array element");
    throw e;
    }
  return table[i];
}

int itkExceptionObjectTest(int, char* [] )
{
  // SOME BASIC TESTS OF THE itk::ExceptionObject 's

  itk::RangeError E;
  E.SetLocation("itkExceptionObjectTest(int, char**)");
  E.SetDescription("E");
  std::cout << E << std::endl;
  itk::RangeError F(E);
  std::cout << F << std::endl;
  itk::RangeError G;
  G.SetLocation("itkExceptionObjectTest(int, char**)");
  G.SetDescription("G");
  std::cout << "F==G? " << (F==G) << std::endl;
  E = F = G;
  std::cout << F << std::endl;
  std::cout << "F==G? " << (F==G) << std::endl;

  itk::RangeError *Ep  = new itk::RangeError;
  Ep->SetLocation("itkExceptionObjectTest(int, char**)");
  Ep->SetDescription("Ep");
  itk::RangeError *Fp = new itk::RangeError;
  *Fp = *Ep;
  delete Ep;
  std::cout << *Fp << std::endl;

  // ** BE SURE TO CATCH BY REFERENCE TO AVOID SLICING **
  try {
    lookup(4);  // OK
    lookup(12); // ERROR
    }
  catch (itk::ExceptionObject &e)
    {
    std::cout << e << std::endl;
    }

  try
    {
    human john, jane;
    naked_mole_rat hal;
    john == john;  // OK
    jane == john;  // OK
    hal == john;   // ERROR
    }
  catch (itk::IncompatibleOperandsError &e)
    {
    std::cout << e << std::endl;
    }

  /*
  // SAMPLE ERROR STUFF
  itk::SampleError Se;
  Se.SetLocation("SE LOCATION");
  Se.SetDescription("SE DESCRIPTION");
  itk::SampleError Sf(Se);
  itk::SampleError Sg;
  Sg = Sf;
  std::cout << Sg << std::endl;

  try
  {
    itk::SampleError E;
    E.SetLocation("djibouti");
    E.SetDescription("sample error");
    throw E;
  }
  catch (itk::ExceptionObject &e) { std::cout << e << std::endl; }
  */

  delete Fp;

  return 0;

}
<commit_msg>COMP: Removing warning for lack of virtual destructor.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkExceptionObjectTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkExceptionObject.h"
#include <iostream>

class mammal
 {
 public:
   virtual int GetType()=0;
   virtual bool operator== (mammal &);
   mammal() {};
   virtual ~mammal() {};
 };

class human : public mammal
{
  public:
    int GetType()
    {
      return 32;
    }
};

class naked_mole_rat : public mammal
{
  public:
    int GetType()
    {
      return 2;
    }
};

bool mammal::operator== (mammal &o)
{
  if ( this->GetType() != o.GetType() )
    {
    itk::IncompatibleOperandsError e(__FILE__, __LINE__);
    e.SetLocation("bool mammal::operator==(mammal&, mammal&)");
    e.SetDescription("Cannot compare mammals of unequal type");
    throw e;
    }
  else
    {
    if ( /* blah blah blah */ 1)
      {
      return true;
      }
    else
      {
      return false;
      }
    }
}

int lookup(const int& i)
{
  static int table[5] = { 23,42,42,32,12 };
  if ( ! ( 0 <= i && i < 5 ) )
    {
    itk::RangeError e(__FILE__, __LINE__);
    e.SetLocation("int lookup(const int& )");
    e.SetDescription("Attempted to access out-of-bounds array element");
    throw e;
    }
  return table[i];
}

int itkExceptionObjectTest(int, char* [] )
{
  // SOME BASIC TESTS OF THE itk::ExceptionObject 's

  itk::RangeError E;
  E.SetLocation("itkExceptionObjectTest(int, char**)");
  E.SetDescription("E");
  std::cout << E << std::endl;
  itk::RangeError F(E);
  std::cout << F << std::endl;
  itk::RangeError G;
  G.SetLocation("itkExceptionObjectTest(int, char**)");
  G.SetDescription("G");
  std::cout << "F==G? " << (F==G) << std::endl;
  E = F = G;
  std::cout << F << std::endl;
  std::cout << "F==G? " << (F==G) << std::endl;

  itk::RangeError *Ep  = new itk::RangeError;
  Ep->SetLocation("itkExceptionObjectTest(int, char**)");
  Ep->SetDescription("Ep");
  itk::RangeError *Fp = new itk::RangeError;
  *Fp = *Ep;
  delete Ep;
  std::cout << *Fp << std::endl;

  // ** BE SURE TO CATCH BY REFERENCE TO AVOID SLICING **
  try {
    lookup(4);  // OK
    lookup(12); // ERROR
    }
  catch (itk::ExceptionObject &e)
    {
    std::cout << e << std::endl;
    }

  try
    {
    human john, jane;
    naked_mole_rat hal;
    john == john;  // OK
    jane == john;  // OK
    hal == john;   // ERROR
    }
  catch (itk::IncompatibleOperandsError &e)
    {
    std::cout << e << std::endl;
    }

  /*
  // SAMPLE ERROR STUFF
  itk::SampleError Se;
  Se.SetLocation("SE LOCATION");
  Se.SetDescription("SE DESCRIPTION");
  itk::SampleError Sf(Se);
  itk::SampleError Sg;
  Sg = Sf;
  std::cout << Sg << std::endl;

  try
  {
    itk::SampleError E;
    E.SetLocation("djibouti");
    E.SetDescription("sample error");
    throw E;
  }
  catch (itk::ExceptionObject &e) { std::cout << e << std::endl; }
  */

  delete Fp;

  return 0;

}
<|endoftext|>


<commit_before>#include <osgGA/StateSetManipulator>

using namespace osg;
using namespace osgGA;

StateSetManipulator::StateSetManipulator(): _drawState(NULL)
{
}

StateSetManipulator::~StateSetManipulator()
{
}

void StateSetManipulator::setStateSet(StateSet *drawState)
{
    _drawState=drawState;
    if(!_drawState.valid()) return;
    _backface = (_drawState->getMode(GL_CULL_FACE)&osg::StateAttribute::ON);
    _lighting =(_drawState->getMode(GL_LIGHTING)&osg::StateAttribute::ON);
    _texture =(_drawState->getTextureMode(0,GL_TEXTURE_2D)&osg::StateAttribute::ON);
}

StateSet *StateSetManipulator::getStateSet()
{
    return _drawState.get();
}

const StateSet *StateSetManipulator::getStateSet() const
{
    return _drawState.get();
}

bool StateSetManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& aa)
{
    if(!_drawState.valid()) return false;

    if(ea.getEventType()==GUIEventAdapter::KEYDOWN){

        switch( ea.getKey() ){

            case 'b' :
                _backface = !_backface;
                if( _backface ) _drawState->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
                else _drawState->setMode(GL_CULL_FACE,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
                aa.requestRedraw();
                return true;
                break;

            case 'l' :
                _lighting = !_lighting ;
                if( _lighting ) _drawState->setMode(GL_LIGHTING,osg::StateAttribute::ON);
                else _drawState->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
                aa.requestRedraw();
                return true;
                break;

            case 't' :
                _texture = !_texture;
                if (_texture) _drawState->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::INHERIT);
                else _drawState->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
                aa.requestRedraw();
                return true;
                break;

        }
    }
    return false;
}

void StateSetManipulator::getUsage(osg::ApplicationUsage& usage) const
{
    usage.addKeyboardMouseBinding("b","Toggle backface culling");
    usage.addKeyboardMouseBinding("l","Toggle lighting");
    usage.addKeyboardMouseBinding("t","Toggle texturing");
}

void StateSetManipulator::accept(GUIEventHandlerVisitor& gehv)
{
    gehv.visit(*this);
}
<commit_msg>Added 'w' toggle to StateSetManipulator to toggle between filled, line and point polygon drawing modes.<commit_after>#include <osgGA/StateSetManipulator>

#include <osg/PolygonMode>

using namespace osg;
using namespace osgGA;

StateSetManipulator::StateSetManipulator(): _drawState(NULL)
{
}

StateSetManipulator::~StateSetManipulator()
{
}

void StateSetManipulator::setStateSet(StateSet *drawState)
{
    _drawState=drawState;
    if(!_drawState.valid()) return;
    _backface = (_drawState->getMode(GL_CULL_FACE)&osg::StateAttribute::ON);
    _lighting =(_drawState->getMode(GL_LIGHTING)&osg::StateAttribute::ON);
    _texture =(_drawState->getTextureMode(0,GL_TEXTURE_2D)&osg::StateAttribute::ON);
}

StateSet *StateSetManipulator::getStateSet()
{
    return _drawState.get();
}

const StateSet *StateSetManipulator::getStateSet() const
{
    return _drawState.get();
}

bool StateSetManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& aa)
{
    if(!_drawState.valid()) return false;

    if(ea.getEventType()==GUIEventAdapter::KEYDOWN){

        switch( ea.getKey() ){

            case 'b' :
                _backface = !_backface;
                if( _backface ) _drawState->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
                else _drawState->setMode(GL_CULL_FACE,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
                aa.requestRedraw();
                return true;
                break;

            case 'l' :
                _lighting = !_lighting ;
                if( _lighting ) _drawState->setMode(GL_LIGHTING,osg::StateAttribute::ON);
                else _drawState->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
                aa.requestRedraw();
                return true;
                break;

            case 't' :
                _texture = !_texture;
                if (_texture) _drawState->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::INHERIT);
                else _drawState->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
                aa.requestRedraw();
                return true;
                break;

        case 'w' :
            {
                osg::PolygonMode* polyModeObj = dynamic_cast<osg::PolygonMode*>(_drawState->getAttribute(osg::StateAttribute::POLYGONMODE));
                if (!polyModeObj)
                {
                    polyModeObj = new osg::PolygonMode;
                    _drawState->setAttribute(polyModeObj);
                }

                // cycle through the available modes.
                switch(polyModeObj->getMode(osg::PolygonMode::FRONT_AND_BACK))
                {
                    case osg::PolygonMode::FILL : polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE); break;
                    case osg::PolygonMode::LINE : polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::POINT); break;
                    case osg::PolygonMode::POINT : polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::FILL); break;
                }
            }
            break;
        }
    }
    return false;
}

void StateSetManipulator::getUsage(osg::ApplicationUsage& usage) const
{
    usage.addKeyboardMouseBinding("b","Toggle backface culling");
    usage.addKeyboardMouseBinding("l","Toggle lighting");
    usage.addKeyboardMouseBinding("t","Toggle texturing");
    usage.addKeyboardMouseBinding("w","Toggle polygon fill mode between fill, line (wire frame) and points");
}

void StateSetManipulator::accept(GUIEventHandlerVisitor& gehv)
{
    gehv.visit(*this);
}
<|endoftext|>


<commit_before>/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *
 *    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.
 */

/**
 *    @file
 *      The implementation of the Setup Payload. Currently only needed to
 *      verify the validity of a Setup Payload
 */

#include "SetupPayload.h"

#include <core/CHIPCore.h>
#include <core/CHIPTLV.h>
#include <core/CHIPTLVData.hpp>
#include <core/CHIPTLVUtilities.hpp>
#include <support/CodeUtils.h>
#include <support/RandUtils.h>
#include <utility>

using namespace chip;
using namespace std;
using namespace chip::TLV;

namespace chip {

bool IsCHIPTag(uint8_t tag)
{
    return tag >= (1 << kRawVendorTagLengthInBits);
}

bool IsVendorTag(uint8_t tag)
{
    return tag < (1 << kRawVendorTagLengthInBits);
}

// Check the Setup Payload for validity
//
// `vendor_id` and `product_id` are allowed all of uint16_t
// `requiresCustomFlow` is not checked since it is a bool
bool SetupPayload::isValidQRCodePayload()
{
    if (version >= 1 << kVersionFieldLengthInBits)
    {
        return false;
    }

    if (rendezvousInformation > RendezvousInformationFlags::kAllMask)
    {
        return false;
    }

    if (discriminator >= 1 << kPayloadDiscriminatorFieldLengthInBits)
    {
        return false;
    }

    if (setUpPINCode >= 1 << kSetupPINCodeFieldLengthInBits)
    {
        return false;
    }

    if (version == 0 && rendezvousInformation == RendezvousInformationFlags::kNone && discriminator == 0 && setUpPINCode == 0)
    {
        return false;
    }

    return true;
}

bool SetupPayload::isValidManualCode()
{
    if (discriminator >= 1 << kManualSetupDiscriminatorFieldLengthInBits)
    {
        return false;
    }
    if (setUpPINCode >= 1 << kSetupPINCodeFieldLengthInBits)
    {
        return false;
    }

    if (setUpPINCode == 0)
    {
        return false;
    }

    return true;
}

CHIP_ERROR SetupPayload::addOptionalVendorData(uint8_t tag, string data)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    OptionalQRCodeInfo info;
    info.tag  = tag;
    info.type = optionalQRCodeInfoTypeString;
    info.data = std::move(data);

    err = addOptionalVendorData(info);
    SuccessOrExit(err);

exit:
    return err;
}

CHIP_ERROR SetupPayload::addOptionalVendorData(uint8_t tag, int32_t data)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    OptionalQRCodeInfo info;
    info.tag   = tag;
    info.type  = optionalQRCodeInfoTypeInt32;
    info.int32 = data;

    err = addOptionalVendorData(info);
    SuccessOrExit(err);

exit:
    return err;
}

vector<OptionalQRCodeInfo> SetupPayload::getAllOptionalVendorData()
{
    vector<OptionalQRCodeInfo> returnedOptionalInfo;
    for (auto & entry : optionalVendorData)
    {
        returnedOptionalInfo.push_back(entry.second);
    }
    return returnedOptionalInfo;
}

CHIP_ERROR SetupPayload::removeOptionalVendorData(uint8_t tag)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    VerifyOrExit(optionalVendorData.find(tag) != optionalVendorData.end(), err = CHIP_ERROR_KEY_NOT_FOUND);
    optionalVendorData.erase(tag);

exit:
    return err;
}

CHIP_ERROR SetupPayload::addSerialNumber(string serialNumber)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    OptionalQRCodeInfoExtension info;
    info.tag  = kSerialNumberTag;
    info.type = optionalQRCodeInfoTypeString;
    info.data = std::move(serialNumber);

    err = addOptionalExtensionData(info);
    SuccessOrExit(err);

exit:
    return err;
}

CHIP_ERROR SetupPayload::addSerialNumber(uint32_t serialNumber)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    OptionalQRCodeInfoExtension info;
    info.tag    = kSerialNumberTag;
    info.type   = optionalQRCodeInfoTypeUInt32;
    info.uint32 = serialNumber;

    err = addOptionalExtensionData(info);
    SuccessOrExit(err);

exit:
    return err;
}

CHIP_ERROR SetupPayload::getSerialNumber(string & outSerialNumber)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    OptionalQRCodeInfoExtension info;
    err = getOptionalExtensionData(kSerialNumberTag, info);
    SuccessOrExit(err);

    switch (info.type)
    {
    case (optionalQRCodeInfoTypeString):
        outSerialNumber = info.data;
        break;
    case (optionalQRCodeInfoTypeUInt32):
        outSerialNumber = to_string(info.uint32);
        break;
    default:
        err = CHIP_ERROR_INVALID_ARGUMENT;
    }

exit:
    return err;
}

CHIP_ERROR SetupPayload::removeSerialNumber()
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    VerifyOrExit(optionalExtensionData.find(kSerialNumberTag) != optionalExtensionData.end(), err = CHIP_ERROR_KEY_NOT_FOUND);
    optionalExtensionData.erase(kSerialNumberTag);

exit:
    return err;
}

CHIP_ERROR SetupPayload::addOptionalVendorData(const OptionalQRCodeInfo & info)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    VerifyOrExit(IsVendorTag(info.tag), err = CHIP_ERROR_INVALID_ARGUMENT);
    optionalVendorData[info.tag] = info;

exit:
    return err;
}

CHIP_ERROR SetupPayload::addOptionalExtensionData(const OptionalQRCodeInfoExtension & info)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    VerifyOrExit(IsCHIPTag(info.tag), err = CHIP_ERROR_INVALID_ARGUMENT);
    optionalExtensionData[info.tag] = info;

exit:
    return err;
}

CHIP_ERROR SetupPayload::getOptionalVendorData(uint8_t tag, OptionalQRCodeInfo & info)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    VerifyOrExit(optionalVendorData.find(tag) != optionalVendorData.end(), err = CHIP_ERROR_KEY_NOT_FOUND);
    info = optionalVendorData[tag];

exit:
    return err;
}

CHIP_ERROR SetupPayload::getOptionalExtensionData(uint8_t tag, OptionalQRCodeInfoExtension & info)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    VerifyOrExit(optionalExtensionData.find(tag) != optionalExtensionData.end(), err = CHIP_ERROR_KEY_NOT_FOUND);
    info = optionalExtensionData[tag];

exit:
    return err;
}

optionalQRCodeInfoType SetupPayload::getNumericTypeFor(uint8_t tag)
{
    optionalQRCodeInfoType elemType = optionalQRCodeInfoTypeUnknown;

    if (IsVendorTag(tag))
    {
        elemType = optionalQRCodeInfoTypeInt32;
    }
    else if (tag == kSerialNumberTag)
    {
        elemType = optionalQRCodeInfoTypeUInt32;
    }

    return elemType;
}

vector<OptionalQRCodeInfoExtension> SetupPayload::getAllOptionalExtensionData()
{
    vector<OptionalQRCodeInfoExtension> returnedOptionalInfo;
    for (auto & entry : optionalExtensionData)
    {
        returnedOptionalInfo.push_back(entry.second);
    }
    return returnedOptionalInfo;
}

bool SetupPayload::operator==(SetupPayload & input)
{
    bool isIdentical = true;
    vector<OptionalQRCodeInfo> inputOptionalVendorData;
    vector<OptionalQRCodeInfoExtension> inputOptionalExtensionData;

    VerifyOrExit(this->version == input.version && this->vendorID == input.vendorID && this->productID == input.productID &&
                     this->requiresCustomFlow == input.requiresCustomFlow &&
                     this->rendezvousInformation == input.rendezvousInformation && this->discriminator == input.discriminator &&
                     this->setUpPINCode == input.setUpPINCode,
                 isIdentical = false);

    inputOptionalVendorData = input.getAllOptionalVendorData();
    VerifyOrExit(optionalVendorData.size() == inputOptionalVendorData.size(), isIdentical = false);

    for (OptionalQRCodeInfo inputInfo : inputOptionalVendorData)
    {
        OptionalQRCodeInfo info;
        CHIP_ERROR err = getOptionalVendorData(inputInfo.tag, info);
        VerifyOrExit(err == CHIP_NO_ERROR, isIdentical = false);
        VerifyOrExit(inputInfo.type == info.type, isIdentical = false);
        VerifyOrExit(inputInfo.data == info.data, isIdentical = false);
        VerifyOrExit(inputInfo.int32 == info.int32, isIdentical = false);
    }

    inputOptionalExtensionData = input.getAllOptionalExtensionData();
    VerifyOrExit(optionalExtensionData.size() == inputOptionalExtensionData.size(), isIdentical = false);

    for (OptionalQRCodeInfoExtension inputInfo : inputOptionalExtensionData)
    {
        OptionalQRCodeInfoExtension info;
        CHIP_ERROR err = getOptionalExtensionData(inputInfo.tag, info);
        VerifyOrExit(err == CHIP_NO_ERROR, isIdentical = false);
        VerifyOrExit(inputInfo.type == info.type, isIdentical = false);
        VerifyOrExit(inputInfo.data == info.data, isIdentical = false);
        VerifyOrExit(inputInfo.int32 == info.int32, isIdentical = false);
        VerifyOrExit(inputInfo.int64 == info.int64, isIdentical = false);
        VerifyOrExit(inputInfo.uint32 == info.uint32, isIdentical = false);
        VerifyOrExit(inputInfo.uint64 == info.uint64, isIdentical = false);
    }

exit:
    return isIdentical;
}

} // namespace chip
<commit_msg>clang-tidy: Apply fixes "performance-for-range-copy" (#3040)<commit_after>/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *
 *    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.
 */

/**
 *    @file
 *      The implementation of the Setup Payload. Currently only needed to
 *      verify the validity of a Setup Payload
 */

#include "SetupPayload.h"

#include <core/CHIPCore.h>
#include <core/CHIPTLV.h>
#include <core/CHIPTLVData.hpp>
#include <core/CHIPTLVUtilities.hpp>
#include <support/CodeUtils.h>
#include <support/RandUtils.h>
#include <utility>

using namespace chip;
using namespace std;
using namespace chip::TLV;

namespace chip {

bool IsCHIPTag(uint8_t tag)
{
    return tag >= (1 << kRawVendorTagLengthInBits);
}

bool IsVendorTag(uint8_t tag)
{
    return tag < (1 << kRawVendorTagLengthInBits);
}

// Check the Setup Payload for validity
//
// `vendor_id` and `product_id` are allowed all of uint16_t
// `requiresCustomFlow` is not checked since it is a bool
bool SetupPayload::isValidQRCodePayload()
{
    if (version >= 1 << kVersionFieldLengthInBits)
    {
        return false;
    }

    if (rendezvousInformation > RendezvousInformationFlags::kAllMask)
    {
        return false;
    }

    if (discriminator >= 1 << kPayloadDiscriminatorFieldLengthInBits)
    {
        return false;
    }

    if (setUpPINCode >= 1 << kSetupPINCodeFieldLengthInBits)
    {
        return false;
    }

    if (version == 0 && rendezvousInformation == RendezvousInformationFlags::kNone && discriminator == 0 && setUpPINCode == 0)
    {
        return false;
    }

    return true;
}

bool SetupPayload::isValidManualCode()
{
    if (discriminator >= 1 << kManualSetupDiscriminatorFieldLengthInBits)
    {
        return false;
    }
    if (setUpPINCode >= 1 << kSetupPINCodeFieldLengthInBits)
    {
        return false;
    }

    if (setUpPINCode == 0)
    {
        return false;
    }

    return true;
}

CHIP_ERROR SetupPayload::addOptionalVendorData(uint8_t tag, string data)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    OptionalQRCodeInfo info;
    info.tag  = tag;
    info.type = optionalQRCodeInfoTypeString;
    info.data = std::move(data);

    err = addOptionalVendorData(info);
    SuccessOrExit(err);

exit:
    return err;
}

CHIP_ERROR SetupPayload::addOptionalVendorData(uint8_t tag, int32_t data)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    OptionalQRCodeInfo info;
    info.tag   = tag;
    info.type  = optionalQRCodeInfoTypeInt32;
    info.int32 = data;

    err = addOptionalVendorData(info);
    SuccessOrExit(err);

exit:
    return err;
}

vector<OptionalQRCodeInfo> SetupPayload::getAllOptionalVendorData()
{
    vector<OptionalQRCodeInfo> returnedOptionalInfo;
    for (auto & entry : optionalVendorData)
    {
        returnedOptionalInfo.push_back(entry.second);
    }
    return returnedOptionalInfo;
}

CHIP_ERROR SetupPayload::removeOptionalVendorData(uint8_t tag)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    VerifyOrExit(optionalVendorData.find(tag) != optionalVendorData.end(), err = CHIP_ERROR_KEY_NOT_FOUND);
    optionalVendorData.erase(tag);

exit:
    return err;
}

CHIP_ERROR SetupPayload::addSerialNumber(string serialNumber)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    OptionalQRCodeInfoExtension info;
    info.tag  = kSerialNumberTag;
    info.type = optionalQRCodeInfoTypeString;
    info.data = std::move(serialNumber);

    err = addOptionalExtensionData(info);
    SuccessOrExit(err);

exit:
    return err;
}

CHIP_ERROR SetupPayload::addSerialNumber(uint32_t serialNumber)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    OptionalQRCodeInfoExtension info;
    info.tag    = kSerialNumberTag;
    info.type   = optionalQRCodeInfoTypeUInt32;
    info.uint32 = serialNumber;

    err = addOptionalExtensionData(info);
    SuccessOrExit(err);

exit:
    return err;
}

CHIP_ERROR SetupPayload::getSerialNumber(string & outSerialNumber)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    OptionalQRCodeInfoExtension info;
    err = getOptionalExtensionData(kSerialNumberTag, info);
    SuccessOrExit(err);

    switch (info.type)
    {
    case (optionalQRCodeInfoTypeString):
        outSerialNumber = info.data;
        break;
    case (optionalQRCodeInfoTypeUInt32):
        outSerialNumber = to_string(info.uint32);
        break;
    default:
        err = CHIP_ERROR_INVALID_ARGUMENT;
    }

exit:
    return err;
}

CHIP_ERROR SetupPayload::removeSerialNumber()
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    VerifyOrExit(optionalExtensionData.find(kSerialNumberTag) != optionalExtensionData.end(), err = CHIP_ERROR_KEY_NOT_FOUND);
    optionalExtensionData.erase(kSerialNumberTag);

exit:
    return err;
}

CHIP_ERROR SetupPayload::addOptionalVendorData(const OptionalQRCodeInfo & info)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    VerifyOrExit(IsVendorTag(info.tag), err = CHIP_ERROR_INVALID_ARGUMENT);
    optionalVendorData[info.tag] = info;

exit:
    return err;
}

CHIP_ERROR SetupPayload::addOptionalExtensionData(const OptionalQRCodeInfoExtension & info)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    VerifyOrExit(IsCHIPTag(info.tag), err = CHIP_ERROR_INVALID_ARGUMENT);
    optionalExtensionData[info.tag] = info;

exit:
    return err;
}

CHIP_ERROR SetupPayload::getOptionalVendorData(uint8_t tag, OptionalQRCodeInfo & info)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    VerifyOrExit(optionalVendorData.find(tag) != optionalVendorData.end(), err = CHIP_ERROR_KEY_NOT_FOUND);
    info = optionalVendorData[tag];

exit:
    return err;
}

CHIP_ERROR SetupPayload::getOptionalExtensionData(uint8_t tag, OptionalQRCodeInfoExtension & info)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    VerifyOrExit(optionalExtensionData.find(tag) != optionalExtensionData.end(), err = CHIP_ERROR_KEY_NOT_FOUND);
    info = optionalExtensionData[tag];

exit:
    return err;
}

optionalQRCodeInfoType SetupPayload::getNumericTypeFor(uint8_t tag)
{
    optionalQRCodeInfoType elemType = optionalQRCodeInfoTypeUnknown;

    if (IsVendorTag(tag))
    {
        elemType = optionalQRCodeInfoTypeInt32;
    }
    else if (tag == kSerialNumberTag)
    {
        elemType = optionalQRCodeInfoTypeUInt32;
    }

    return elemType;
}

vector<OptionalQRCodeInfoExtension> SetupPayload::getAllOptionalExtensionData()
{
    vector<OptionalQRCodeInfoExtension> returnedOptionalInfo;
    for (auto & entry : optionalExtensionData)
    {
        returnedOptionalInfo.push_back(entry.second);
    }
    return returnedOptionalInfo;
}

bool SetupPayload::operator==(SetupPayload & input)
{
    bool isIdentical = true;
    vector<OptionalQRCodeInfo> inputOptionalVendorData;
    vector<OptionalQRCodeInfoExtension> inputOptionalExtensionData;

    VerifyOrExit(this->version == input.version && this->vendorID == input.vendorID && this->productID == input.productID &&
                     this->requiresCustomFlow == input.requiresCustomFlow &&
                     this->rendezvousInformation == input.rendezvousInformation && this->discriminator == input.discriminator &&
                     this->setUpPINCode == input.setUpPINCode,
                 isIdentical = false);

    inputOptionalVendorData = input.getAllOptionalVendorData();
    VerifyOrExit(optionalVendorData.size() == inputOptionalVendorData.size(), isIdentical = false);

    for (const OptionalQRCodeInfo & inputInfo : inputOptionalVendorData)
    {
        OptionalQRCodeInfo info;
        CHIP_ERROR err = getOptionalVendorData(inputInfo.tag, info);
        VerifyOrExit(err == CHIP_NO_ERROR, isIdentical = false);
        VerifyOrExit(inputInfo.type == info.type, isIdentical = false);
        VerifyOrExit(inputInfo.data == info.data, isIdentical = false);
        VerifyOrExit(inputInfo.int32 == info.int32, isIdentical = false);
    }

    inputOptionalExtensionData = input.getAllOptionalExtensionData();
    VerifyOrExit(optionalExtensionData.size() == inputOptionalExtensionData.size(), isIdentical = false);

    for (const OptionalQRCodeInfoExtension & inputInfo : inputOptionalExtensionData)
    {
        OptionalQRCodeInfoExtension info;
        CHIP_ERROR err = getOptionalExtensionData(inputInfo.tag, info);
        VerifyOrExit(err == CHIP_NO_ERROR, isIdentical = false);
        VerifyOrExit(inputInfo.type == info.type, isIdentical = false);
        VerifyOrExit(inputInfo.data == info.data, isIdentical = false);
        VerifyOrExit(inputInfo.int32 == info.int32, isIdentical = false);
        VerifyOrExit(inputInfo.int64 == info.int64, isIdentical = false);
        VerifyOrExit(inputInfo.uint32 == info.uint32, isIdentical = false);
        VerifyOrExit(inputInfo.uint64 == info.uint64, isIdentical = false);
    }

exit:
    return isIdentical;
}

} // namespace chip
<|endoftext|>


<commit_before>#include <sailboat.h>
#include "buoy.h"
#include <stdio.h>
#include <stdlib.h>

Buoy::Buoy(int nb, double xb, double yb, double zb, double ub, double dt)
{

    this->dt = dt;

    // id
    n = nb;

    // Position
    x = xb;
    y = yb;
    z = zb;

    Xdot[0] = 0;
    Xdot[1] = 0;
    Xdot[2] = 0;

    Xdot2[0] = 0;
    Xdot2[1] = 0;
    Xdot2[2] = 0;

    // Command
    //volBal = BUOY_CONTROL;
    volBal = 0;
    S = 1;

    // Caracteristiques physiques
    m = 100;
    vol = 100;
    rho_w=1.025;
    mvol = m/(vol-volBal); //kg/m³

    // Lorentz variables
    sigma = 10.0;
    beta = 8.0/3.0;
    rho = 28;
    k = 0.0;
    delta = mvol/rho_w; //delta = rapport de la masse volumique de l'eau sur celui de la bouee
    mu = 1.0; //coefficient de resistance de Stokes
    theta = 10;

    phi_i = 1.0;
    Ri = 100.0;

    int i =0;
    //TODO : tourne a linfini
    /*
    while (Xi[i]=!NULL)
    {
        double r = rand() % 200;
        double ang = rand() % 200;
        printf("rayon : %f angle : %f\n", r, ang);
        Xi[i] = r*cos(314*ang);
        Yi[i] = r*sin(314*ang);
        i++;
        printf("valeur de i :%i\n", i);
    }
    */
   printf("appel dans le constructeur :%f\n", Xi[0]);
    Xi[0] = 100;
    Xi[1] = 100;
    Xi[2] = -100;
    Xi[3] = -100;

    Yi[0] = 100;
    Yi[1] = -100;
    Yi[2] = -100;
    Yi[3] = 100;

}

void Buoy::lorenz(void)
{
    Xdot[0] = sigma*(y-x)*dt;
    Xdot[1] = (x*(rho-z)-y)*dt;
    Xdot[2] = (k*(x*y-beta*z)+u);
}

void Buoy::sinLine(double simuTime)
{
    double depth = 40; // m
    double freq = 0.05; // Hz
    double speed = 10;  // m/s
    Xdot[0] = 0;      //X
    Xdot[1] = 0;      //Y
    Xdot[2] = speed*sin(2*M_PI*simuTime*freq); //Z
}

void Buoy::pendulum(void)
{
    Xdot[0] = y;
    Xdot[1] = -sin(x);
    Xdot[2] = u;
}

void Buoy::stateEq(void)
{
    Xdot[0] = sin(0.001*(y+0.9*z));
    Xdot[1] = -sin(0.001*(x+z));
    Xdot[2] = u;

}

void Buoy::setCommand(double ub)
{
    u = ub;
}

int Buoy::getNumber(void)
{
    return n;
}

double* Buoy::getPos(void)
{
    double* xd = new double[4];
    xd[0] = sqrt(pow(Xdot[0],2.0)+pow(Xdot[1],2.0)+pow(Xdot[2],2.0));
    xd[1] = x;
    xd[2] = y;
    xd[3] = z;
    return xd;
}

void Buoy::eqParticuleSimple(void)
{
    vx = -2*sin(y);
    vy = 2*sin(x);

    Dx = -4*sin(x)*cos(y);
    Dy = 4*sin(y)*cos(x);
}

void Buoy::eqParticule(void)
{
    double d2;
    double dvxx, dvyx, dvxy, dvyy;
    vx = 0;
    vy = 0;
    dvxx = 0;
    dvyx = 0;
    dvxy = 0;
    dvyy = 0;

    for (int i=0;i<4;i++)
    {
        d2 = (x-Xi[i])*(x-Xi[i])+(y-Yi[i])*(y-Yi[i]);

        vx   += phi_i*2*y*(y-Yi[i])*exp(-1*d2/(Ri*Ri))/(Ri*Ri);
        vy   -= phi_i*2*x*(x-Xi[i])*exp(-1*d2/(Ri*Ri))/(Ri*Ri);

        dvxx -= phi_i*4*y*(y-Yi[i])*(x-Xi[i])*exp(-1*d2/(Ri*Ri))/(Ri*Ri*Ri*Ri);
        dvxy += 2*phi_i*exp(-1*d2/(Ri*Ri))/(Ri*Ri)*((2*y-Yi[i])-2*y*(y-Yi[i])*(y-Yi[i]));
        dvyx -= 2*phi_i*exp(-1*d2/(Ri*Ri))/(Ri*Ri)*((2*x-Xi[i])-2*x*(x-Xi[i])*(x-Xi[i]));
        dvyy += phi_i*4*x*(y-Yi[i])*(x-Xi[i])*exp(-1*d2/(Ri*Ri))/(Ri*Ri*Ri*Ri);
    }

    Dx = vx*dvxx+vy*dvxy;
    Dy = vx*dvyx+vy*dvyy;
}

void Buoy::vortex(void)
{
    //Dx = vy*0.5*(1+sin(theta*z))*2*cos(y);
    //Dy = vx*0.5*(1+sin(theta*z))*2*cos(x);
    eqParticule();
    mvol = m/(vol-volBal);
    delta = mvol/rho_w;
    Xdot2[0] = delta * Dx - mu * (Xdot[0] - vx);
    Xdot2[1] = Dy - mu * (Xdot[1] - vy);
    Xdot2[2] = (m-(vol-volBal)*rho_w)*9.81-mu*Xdot[2];
    printf("Buoy  mass : %f : vol : %f, volbal : %f, accel : %f \n",m,vol,volBal,Xdot2[2]);

}

void Buoy::rotation(void)
{
    double xd;
    double yd;
    xd = cos(theta*z)*vx-sin(theta*z)*vy;
    yd = cos(theta*z)*vy+sin(theta*z)*vx;
    vx = xd;
    vy = yd;
}

void Buoy::clock(void)  // The model is described in "L. Jaulin Modélisation et commande d'un bateau à voile, CIFA2004, Douz (Tunisie)"
{
    // On met à jour la position de la bouee
    // On travaille en dynamique donc pfd m*a = Somme(Forces)
    vortex();
    rotation();
    Xdot[0] = Xdot[0]+dt*Xdot2[0];
    Xdot[1] = Xdot[1]+dt*Xdot2[1];
    Xdot[2] = Xdot[2]+dt*Xdot2[2];
    x = x+dt*Xdot[0];
    y = y+dt*Xdot[1];
    z = z+dt*Xdot[2];
    if (z<0)
    {
        z = 0;
        Xdot[2] = 0;
    }
    //TODO : mettre un min et un max
    volBal = volBal+u*S*dt;
    if(volBal<0){volBal = 0;}
    else if(volBal>vol){volBal = vol;}
    printf("Buoy State %d : x : %f, y : %f, z : %f \n",n,x,y,z);
    fflush(stdout);
}

<commit_msg>Modification de la taille du ballast (plus petit)<commit_after>#include <sailboat.h>
#include "buoy.h"
#include <stdio.h>
#include <stdlib.h>

Buoy::Buoy(int nb, double xb, double yb, double zb, double ub, double dt)
{

    this->dt = dt;

    // id
    n = nb;

    // Position
    x = xb;
    y = yb;
    z = zb;

    Xdot[0] = 0;
    Xdot[1] = 0;
    Xdot[2] = 0;

    Xdot2[0] = 0;
    Xdot2[1] = 0;
    Xdot2[2] = 0;

    // Command
    //volBal = BUOY_CONTROL;
    volBal = 0;
    S = 1;

    // Caracteristiques physiques
    m = 100;
    vol = 100;
    rho_w=1.025;
    mvol = m/(vol-volBal); //kg/m³

    // Lorentz variables
    sigma = 10.0;
    beta = 8.0/3.0;
    rho = 28;
    k = 0.0;
    delta = mvol/rho_w; //delta = rapport de la masse volumique de l'eau sur celui de la bouee
    mu = 1.0; //coefficient de resistance de Stokes
    theta = 10;

    phi_i = 1.0;
    Ri = 100.0;

    int i =0;
    //TODO : tourne a linfini
    /*
    while (Xi[i]=!NULL)
    {
        double r = rand() % 200;
        double ang = rand() % 200;
        printf("rayon : %f angle : %f\n", r, ang);
        Xi[i] = r*cos(314*ang);
        Yi[i] = r*sin(314*ang);
        i++;
        printf("valeur de i :%i\n", i);
    }
    */
   printf("appel dans le constructeur :%f\n", Xi[0]);
    Xi[0] = 100;
    Xi[1] = 100;
    Xi[2] = -100;
    Xi[3] = -100;

    Yi[0] = 100;
    Yi[1] = -100;
    Yi[2] = -100;
    Yi[3] = 100;

}

void Buoy::lorenz(void)
{
    Xdot[0] = sigma*(y-x)*dt;
    Xdot[1] = (x*(rho-z)-y)*dt;
    Xdot[2] = (k*(x*y-beta*z)+u);
}

void Buoy::sinLine(double simuTime)
{
    double depth = 40; // m
    double freq = 0.05; // Hz
    double speed = 10;  // m/s
    Xdot[0] = 0;      //X
    Xdot[1] = 0;      //Y
    Xdot[2] = speed*sin(2*M_PI*simuTime*freq); //Z
}

void Buoy::pendulum(void)
{
    Xdot[0] = y;
    Xdot[1] = -sin(x);
    Xdot[2] = u;
}

void Buoy::stateEq(void)
{
    Xdot[0] = sin(0.001*(y+0.9*z));
    Xdot[1] = -sin(0.001*(x+z));
    Xdot[2] = u;

}

void Buoy::setCommand(double ub)
{
    u = ub;
}

int Buoy::getNumber(void)
{
    return n;
}

double* Buoy::getPos(void)
{
    double* xd = new double[4];
    xd[0] = sqrt(pow(Xdot[0],2.0)+pow(Xdot[1],2.0)+pow(Xdot[2],2.0));
    xd[1] = x;
    xd[2] = y;
    xd[3] = z;
    return xd;
}

void Buoy::eqParticuleSimple(void)
{
    vx = -2*sin(y);
    vy = 2*sin(x);

    Dx = -4*sin(x)*cos(y);
    Dy = 4*sin(y)*cos(x);
}

void Buoy::eqParticule(void)
{
    double d2;
    double dvxx, dvyx, dvxy, dvyy;
    vx = 0;
    vy = 0;
    dvxx = 0;
    dvyx = 0;
    dvxy = 0;
    dvyy = 0;

    for (int i=0;i<4;i++)
    {
        d2 = (x-Xi[i])*(x-Xi[i])+(y-Yi[i])*(y-Yi[i]);

        vx   += phi_i*2*y*(y-Yi[i])*exp(-1*d2/(Ri*Ri))/(Ri*Ri);
        vy   -= phi_i*2*x*(x-Xi[i])*exp(-1*d2/(Ri*Ri))/(Ri*Ri);

        dvxx -= phi_i*4*y*(y-Yi[i])*(x-Xi[i])*exp(-1*d2/(Ri*Ri))/(Ri*Ri*Ri*Ri);
        dvxy += 2*phi_i*exp(-1*d2/(Ri*Ri))/(Ri*Ri)*((2*y-Yi[i])-2*y*(y-Yi[i])*(y-Yi[i]));
        dvyx -= 2*phi_i*exp(-1*d2/(Ri*Ri))/(Ri*Ri)*((2*x-Xi[i])-2*x*(x-Xi[i])*(x-Xi[i]));
        dvyy += phi_i*4*x*(y-Yi[i])*(x-Xi[i])*exp(-1*d2/(Ri*Ri))/(Ri*Ri*Ri*Ri);
    }

    Dx = vx*dvxx+vy*dvxy;
    Dy = vx*dvyx+vy*dvyy;
}

void Buoy::vortex(void)
{
    //Dx = vy*0.5*(1+sin(theta*z))*2*cos(y);
    //Dy = vx*0.5*(1+sin(theta*z))*2*cos(x);
    eqParticule();
    mvol = m/(vol-volBal);
    delta = mvol/rho_w;
    Xdot2[0] = delta * Dx - mu * (Xdot[0] - vx);
    Xdot2[1] = Dy - mu * (Xdot[1] - vy);
    Xdot2[2] = (m - (vol - volBal) * rho_w) * 9.81 - mu * Xdot[2];
    printf("Buoy  mass : %f : vol : %f, volbal : %f, accel : %f \n",m,vol,volBal,Xdot2[2]);

}

void Buoy::rotation(void)
{
    double xd;
    double yd;
    xd = cos(theta*z)*vx-sin(theta*z)*vy;
    yd = cos(theta*z)*vy+sin(theta*z)*vx;
    vx = xd;
    vy = yd;
}

void Buoy::clock(void)  // The model is described in "L. Jaulin Modélisation et commande d'un bateau à voile, CIFA2004, Douz (Tunisie)"
{
    // On met à jour la position de la bouee
    // On travaille en dynamique donc pfd m*a = Somme(Forces)
    vortex();
    rotation();
    Xdot[0] = Xdot[0]+dt*Xdot2[0];
    Xdot[1] = Xdot[1]+dt*Xdot2[1];
    Xdot[2] = Xdot[2]+dt*Xdot2[2];
    x = x+dt*Xdot[0];
    y = y+dt*Xdot[1];
    z = z+dt*Xdot[2];
    if (z<0)
    {
        z = 0;
        Xdot[2] = 0;
    }
    //TODO : mettre un min et un max
    volBal = volBal+u*S*dt;
    if(volBal<0){volBal = 0;}
    else if(volBal>50){volBal = 50;}
    printf("Buoy State %d : x : %f, y : %f, z : %f \n",n,x,y,z);
    fflush(stdout);
}

<|endoftext|>


<commit_before>#include <shogun/labels/DenseLabels.h>
#include <shogun/labels/BinaryLabels.h>

using namespace shogun;

CBinaryLabels::CBinaryLabels() : CDenseLabels()
{
}

CBinaryLabels::CBinaryLabels(int32_t num_labels) : CDenseLabels(num_labels)
{
}

CBinaryLabels::CBinaryLabels(SGVector<float64_t> src, float64_t threshold) : CDenseLabels()
{
	SGVector<float64_t> labels(src.vlen);
	for (int32_t i=0; i<labels.vlen; i++)
		labels[i] = src[i]+threshold>=0 ? +1.0 : -1.0;
	set_labels(labels);
	set_confidences(src);
}

CBinaryLabels::CBinaryLabels(CFile* loader) : CDenseLabels(loader)
{
}

CBinaryLabels* CBinaryLabels::obtain_from_generic(CLabels* base_labels)
{
	if ( base_labels->get_label_type() == LT_BINARY )
		return (CBinaryLabels*) base_labels;
	else
		SG_SERROR("base_labels must be of dynamic type CBinaryLabels");

	return NULL;
}

void CBinaryLabels::ensure_valid(const char* context)
{
    CDenseLabels::ensure_valid(context);
    bool found_plus_one=false;
    bool found_minus_one=false;

    int32_t subset_size=get_num_labels();
    for (int32_t i=0; i<subset_size; i++)
    {
        int32_t real_i=m_subset_stack->subset_idx_conversion(i);
        if (m_labels[real_i]==+1.0)
            found_plus_one=true;
        else if (m_labels[real_i]==-1.0)
            found_minus_one=true;
        else
        {
            SG_ERROR("%s%sNot a two class labeling label[%d]=%f (only +1/-1 "
                    "allowed)\n", context?context:"", context?": ":"", i, m_labels[real_i]);
        }
    }

    if (!found_plus_one)
    {
        SG_ERROR("%s%sNot a two class labeling - no positively labeled examples found\n",
                context?context:"", context?": ":"");
    }

    if (!found_minus_one)
    {
        SG_ERROR("%s%sNot a two class labeling - no negatively labeled examples found\n",
                context?context:"", context?": ":"");
    }
}

ELabelType CBinaryLabels::get_label_type()
{
	return LT_BINARY;
}

void CBinaryLabels::scores_to_probabilities()
{
	SG_DEBUG("entering CBinaryLabels::scores_to_probabilities()\n");

	REQUIRE(m_confidences.vector, "%s::scores_to_probabilities() requires "
			"confidences vector!\n", get_name());

	/* count prior0 and prior1 if needed */
	int32_t prior0=0;
	int32_t prior1=0;
	SG_DEBUG("counting number of positive and negative labels\n");
	{
		for (index_t i=0; i<m_confidences.vlen; ++i)
		{
			if (m_confidences[i]>0)
				prior1++;
			else
				prior0++;
		}
	}
	SG_DEBUG("%d pos; %d neg\n", prior1, prior0);

	/* parameter setting */
	/* maximum number of iterations */
	index_t maxiter=100;

	/* minimum step taken in line search */
	float64_t minstep=1E-10;

	/* for numerically strict pd of hessian */
	float64_t sigma=1E-12;
	float64_t eps=1E-5;

	/* construct target support */
	float64_t hiTarget=(prior1+1.0)/(prior1+2.0);
	float64_t loTarget=1/(prior0+2.0);
	index_t length=prior1+prior0;

	SGVector<float64_t> t(length);
	for (index_t i=0; i<length; ++i)
	{
		if (m_confidences[i]>0)
			t[i]=hiTarget;
		else
			t[i]=loTarget;
	}

	/* initial Point and Initial Fun Value */
	/* result parameters of sigmoid */
	float64_t a=0;
	float64_t b=CMath::log((prior0+1.0)/(prior1+1.0));
	float64_t fval=0.0;

	for (index_t i=0; i<length; ++i)
	{
		float64_t fApB=m_confidences[i]*a+b;
		if (fApB>=0)
			fval+=t[i]*fApB+CMath::log(1+CMath::exp(-fApB));
		else
			fval+=(t[i]-1)*fApB+CMath::log(1+CMath::exp(fApB));
	}

	index_t it;
	float64_t g1;
	float64_t g2;
	for (it=0; it<maxiter; ++it)
	{
		SG_DEBUG("Iteration %d, a=%f, b=%f, fval=%f\n", it, a, b, fval);

		/* Update Gradient and Hessian (use H' = H + sigma I) */
		float64_t h11=sigma; //Numerically ensures strict PD
		float64_t h22=h11;
		float64_t h21=0;
		g1=0;
		g2=0;

		for (index_t i=0; i<length; ++i)
		{
			float64_t fApB=m_confidences[i]*a+b;
			float64_t p;
			float64_t q;
			if (fApB>=0)
			{
				p=CMath::exp(-fApB)/(1.0+CMath::exp(-fApB));
				q=1.0/(1.0+CMath::exp(-fApB));
			}
			else
			{
				p=1.0/(1.0+CMath::exp(fApB));
				q=CMath::exp(fApB)/(1.0+CMath::exp(fApB));
			}

			float64_t d2=p*q;
			h11+=m_confidences[i]*m_confidences[i]*d2;
			h22+=d2;
			h21+=m_confidences[i]*d2;
			float64_t d1=t[i]-p;
			g1+=m_confidences[i]*d1;
			g2+=d1;
		}

		/* Stopping Criteria */
		if (CMath::abs(g1)<eps && CMath::abs(g2)<eps)
			break;

		/* Finding Newton direction: -inv(H') * g */
		float64_t det=h11*h22-h21*h21;
		float64_t dA=-(h22*g1-h21*g2)/det;
		float64_t dB=-(-h21*g1+h11*g2)/det;
		float64_t gd=g1*dA+g2*dB;

		/* Line Search */
		float64_t stepsize=1;

		while (stepsize>=minstep)
		{
			float64_t newA=a+stepsize*dA;
			float64_t newB=b+stepsize*dB;

			/* New function value */
			float64_t newf=0.0;
			for (index_t i=0; i<length; ++i)
			{
				float64_t fApB=m_confidences[i]*newA+newB;
				if (fApB>=0)
					newf+=t[i]*fApB+CMath::log(1+CMath::exp(-fApB));
				else
					newf+=(t[i]-1)*fApB+CMath::log(1+CMath::exp(fApB));
			}

			/* Check sufficient decrease */
			if (newf<fval+0.0001*stepsize*gd)
			{
				a=newA;
				b=newB;
				fval=newf;
				break;
			}
			else
				stepsize=stepsize/2.0;
		}

		if (stepsize<minstep)
		{
			SG_WARNING("%s::scores_to_probabilities(): line search fails, A=%f, "
					"B=%f, g1=%f, g2=%f, dA=%f, dB=%f, gd=%f\n",
					a, b, g1, g2, dA, dB, gd);
		}
	}

	if (it>=maxiter-1)
	{
		SG_WARNING("%s::scores_to_probabilities(): reaching maximal iterations,"
				" g1=%f, g2=%f\n", g1, g2);
	}

	SG_DEBUG("fitted sigmoid: a=%f, b=%f\n", a, b);

	/* now the sigmoid is fitted, convert all confidences to probabilities */
	for (index_t i=0; i<m_confidences.vlen; ++i)
	{
		float64_t fApB=m_confidences[i]*a+b;
		m_confidences[i]=fApB>=0 ? CMath::exp(-fApB)/(1.0+exp(-fApB)) :
				1.0/(1+CMath::exp(fApB));
	}

	SG_DEBUG("leaving CBinaryLabels::scores_to_probabilities()\n");
}
<commit_msg>bugfix<commit_after>#include <shogun/labels/DenseLabels.h>
#include <shogun/labels/BinaryLabels.h>

using namespace shogun;

CBinaryLabels::CBinaryLabels() : CDenseLabels()
{
}

CBinaryLabels::CBinaryLabels(int32_t num_labels) : CDenseLabels(num_labels)
{
}

CBinaryLabels::CBinaryLabels(SGVector<float64_t> src, float64_t threshold) : CDenseLabels()
{
	SGVector<float64_t> labels(src.vlen);
	for (int32_t i=0; i<labels.vlen; i++)
		labels[i] = src[i]+threshold>=0 ? +1.0 : -1.0;
	set_labels(labels);
	set_confidences(src);
}

CBinaryLabels::CBinaryLabels(CFile* loader) : CDenseLabels(loader)
{
}

CBinaryLabels* CBinaryLabels::obtain_from_generic(CLabels* base_labels)
{
	if ( base_labels->get_label_type() == LT_BINARY )
		return (CBinaryLabels*) base_labels;
	else
		SG_SERROR("base_labels must be of dynamic type CBinaryLabels");

	return NULL;
}

void CBinaryLabels::ensure_valid(const char* context)
{
    CDenseLabels::ensure_valid(context);
    bool found_plus_one=false;
    bool found_minus_one=false;

    int32_t subset_size=get_num_labels();
    for (int32_t i=0; i<subset_size; i++)
    {
        int32_t real_i=m_subset_stack->subset_idx_conversion(i);
        if (m_labels[real_i]==+1.0)
            found_plus_one=true;
        else if (m_labels[real_i]==-1.0)
            found_minus_one=true;
        else
        {
            SG_ERROR("%s%sNot a two class labeling label[%d]=%f (only +1/-1 "
                    "allowed)\n", context?context:"", context?": ":"", i, m_labels[real_i]);
        }
    }

    if (!found_plus_one)
    {
        SG_ERROR("%s%sNot a two class labeling - no positively labeled examples found\n",
                context?context:"", context?": ":"");
    }

    if (!found_minus_one)
    {
        SG_ERROR("%s%sNot a two class labeling - no negatively labeled examples found\n",
                context?context:"", context?": ":"");
    }
}

ELabelType CBinaryLabels::get_label_type()
{
	return LT_BINARY;
}

void CBinaryLabels::scores_to_probabilities()
{
	SG_DEBUG("entering CBinaryLabels::scores_to_probabilities()\n");

	REQUIRE(m_confidences.vector, "%s::scores_to_probabilities() requires "
			"confidences vector!\n", get_name());

	/* count prior0 and prior1 if needed */
	int32_t prior0=0;
	int32_t prior1=0;
	SG_DEBUG("counting number of positive and negative labels\n");
	{
		for (index_t i=0; i<m_confidences.vlen; ++i)
		{
			if (m_confidences[i]>0)
				prior1++;
			else
				prior0++;
		}
	}
	SG_DEBUG("%d pos; %d neg\n", prior1, prior0);

	/* parameter setting */
	/* maximum number of iterations */
	index_t maxiter=100;

	/* minimum step taken in line search */
	float64_t minstep=1E-10;

	/* for numerically strict pd of hessian */
	float64_t sigma=1E-12;
	float64_t eps=1E-5;

	/* construct target support */
	float64_t hiTarget=(prior1+1.0)/(prior1+2.0);
	float64_t loTarget=1/(prior0+2.0);
	index_t length=prior1+prior0;

	SGVector<float64_t> t(length);
	for (index_t i=0; i<length; ++i)
	{
		if (m_confidences[i]>0)
			t[i]=hiTarget;
		else
			t[i]=loTarget;
	}

	/* initial Point and Initial Fun Value */
	/* result parameters of sigmoid */
	float64_t a=0;
	float64_t b=CMath::log((prior0+1.0)/(prior1+1.0));
	float64_t fval=0.0;

	for (index_t i=0; i<length; ++i)
	{
		float64_t fApB=m_confidences[i]*a+b;
		if (fApB>=0)
			fval+=t[i]*fApB+CMath::log(1+CMath::exp(-fApB));
		else
			fval+=(t[i]-1)*fApB+CMath::log(1+CMath::exp(fApB));
	}

	index_t it;
	float64_t g1;
	float64_t g2;
	for (it=0; it<maxiter; ++it)
	{
		SG_DEBUG("Iteration %d, a=%f, b=%f, fval=%f\n", it, a, b, fval);

		/* Update Gradient and Hessian (use H' = H + sigma I) */
		float64_t h11=sigma; //Numerically ensures strict PD
		float64_t h22=h11;
		float64_t h21=0;
		g1=0;
		g2=0;

		for (index_t i=0; i<length; ++i)
		{
			float64_t fApB=m_confidences[i]*a+b;
			float64_t p;
			float64_t q;
			if (fApB>=0)
			{
				p=CMath::exp(-fApB)/(1.0+CMath::exp(-fApB));
				q=1.0/(1.0+CMath::exp(-fApB));
			}
			else
			{
				p=1.0/(1.0+CMath::exp(fApB));
				q=CMath::exp(fApB)/(1.0+CMath::exp(fApB));
			}

			float64_t d2=p*q;
			h11+=m_confidences[i]*m_confidences[i]*d2;
			h22+=d2;
			h21+=m_confidences[i]*d2;
			float64_t d1=t[i]-p;
			g1+=m_confidences[i]*d1;
			g2+=d1;
		}

		/* Stopping Criteria */
		if (CMath::abs(g1)<eps && CMath::abs(g2)<eps)
			break;

		/* Finding Newton direction: -inv(H') * g */
		float64_t det=h11*h22-h21*h21;
		float64_t dA=-(h22*g1-h21*g2)/det;
		float64_t dB=-(-h21*g1+h11*g2)/det;
		float64_t gd=g1*dA+g2*dB;

		/* Line Search */
		float64_t stepsize=1;

		while (stepsize>=minstep)
		{
			float64_t newA=a+stepsize*dA;
			float64_t newB=b+stepsize*dB;

			/* New function value */
			float64_t newf=0.0;
			for (index_t i=0; i<length; ++i)
			{
				float64_t fApB=m_confidences[i]*newA+newB;
				if (fApB>=0)
					newf+=t[i]*fApB+CMath::log(1+CMath::exp(-fApB));
				else
					newf+=(t[i]-1)*fApB+CMath::log(1+CMath::exp(fApB));
			}

			/* Check sufficient decrease */
			if (newf<fval+0.0001*stepsize*gd)
			{
				a=newA;
				b=newB;
				fval=newf;
				break;
			}
			else
				stepsize=stepsize/2.0;
		}

		if (stepsize<minstep)
		{
			SG_WARNING("%s::scores_to_probabilities(): line search fails, A=%f, "
					"B=%f, g1=%f, g2=%f, dA=%f, dB=%f, gd=%f\n",
					get_name(), a, b, g1, g2, dA, dB, gd);
		}
	}

	if (it>=maxiter-1)
	{
		SG_WARNING("%s::scores_to_probabilities(): reaching maximal iterations,"
				" g1=%f, g2=%f\n", get_name(), g1, g2);
	}

	SG_DEBUG("fitted sigmoid: a=%f, b=%f\n", a, b);

	/* now the sigmoid is fitted, convert all confidences to probabilities */
	for (index_t i=0; i<m_confidences.vlen; ++i)
	{
		float64_t fApB=m_confidences[i]*a+b;
		m_confidences[i]=fApB>=0 ? CMath::exp(-fApB)/(1.0+exp(-fApB)) :
				1.0/(1+CMath::exp(fApB));
	}

	SG_DEBUG("leaving CBinaryLabels::scores_to_probabilities()\n");
}
<|endoftext|>


<commit_before>#include <cstring>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
 #include <arpa/inet.h>
#include <unistd.h>
#include "../address.h"

#include "../exceptions.h"

#include "../stringview.h"
#include "socketObject.h"
#include "localAddr.h"
#include "../realpath.h"

using ondra_shared::StringView;

namespace simpleServer {

class AddressAddrInfo: public INetworkAddress {
public:
	AddressAddrInfo(struct addrinfo *addr):addr(addr) {}

	virtual std::string toString(bool resolve = false) const override;
	virtual BinaryView toSockAddr() const override;
	virtual RefCntPtr<INetworkAddress> getNextAddr() const override;

	virtual SocketObject connect() const override;
	virtual SocketObject listen() const override;

	~AddressAddrInfo() {
		if (addr) freeaddrinfo(addr);
	}

	virtual const INetworkAddress &unproxy() const override {return *this;}

protected:

	struct addrinfo *addr;

};

class AddressAddrInfoSlave: public AddressAddrInfo {
public:
	AddressAddrInfoSlave(struct addrinfo *addr, RefCntPtr<AddressAddrInfo> master)
		:AddressAddrInfo(addr),master(master) {}

	~AddressAddrInfoSlave() noexcept {
		addr = nullptr;
	}

	virtual const INetworkAddress &unproxy() const {return *this;}
protected:
//	template<typename T> friend class RefCntPtr;

	RefCntPtr<AddressAddrInfo> master;

};

RefCntPtr<INetworkAddress> AddressAddrInfo::getNextAddr() const
{
	if (addr->ai_next) return new AddressAddrInfoSlave(addr->ai_next, const_cast<AddressAddrInfo *>(this));
	else return nullptr;
}

SocketObject AddressAddrInfo::connect() const {
	SocketObject s(socket(addr->ai_family, SOCK_STREAM, addr->ai_protocol));
	if (!s) throw SystemException(errno,"Failed to create socket");
	int nblock = 1;ioctl(s, FIONBIO, &nblock);
	::connect(s, reinterpret_cast<const struct sockaddr *>(addr->ai_addr),addr->ai_addrlen);
	return s;
}
SocketObject AddressAddrInfo::listen() const {
	SocketObject s(socket(addr->ai_family, SOCK_STREAM, addr->ai_protocol));
	if (!s) throw SystemException(errno,"Failed to create socket");
	int enable = 1;
	(void)setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
	if (addr->ai_family == AF_INET6)
		(void)setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(int));
	(void)ioctl(s, FIONBIO, &enable);
	if (::bind(s, reinterpret_cast<const struct sockaddr *>(addr->ai_addr),addr->ai_addrlen) == -1) {
		int e = errno;
		throw SystemException(e,"Cannot bind socket to port:" + this->toString(false));
	}
	if (::listen(s,SOMAXCONN) == -1) {
		int e = errno;
		throw SystemException(e,"Cannot activate listen mode on the socket:" + this->toString(false));
	}
	return s;
}

class AddressSockAddr: public AddressAddrInfo {
public:

	static addrinfo *convert_to_addrinfo(AddressSockAddr *me, const struct sockaddr *sa, int len, int protocol) {
		me->addr.ai_addr = reinterpret_cast<sockaddr *>(me->data);
		me->addr.ai_addrlen = len;
		me->addr.ai_canonname = 0;
		me->addr.ai_family = sa->sa_family;
		me->addr.ai_flags = 0;
		me->addr.ai_next = 0;
		me->addr.ai_protocol = protocol;
		me->addr.ai_socktype= SOCK_STREAM;
		std::memcpy(me->data, sa, len);
		return &me->addr;
	}

	AddressSockAddr(const struct sockaddr *sa, int len, int protocol)
		:AddressAddrInfo(convert_to_addrinfo(this,sa,len,protocol)) {}

	~AddressSockAddr() {
		AddressAddrInfo::addr = nullptr;
	}

	void *operator new(std::size_t sz, const int &salen) {
		std::size_t totalsz = sz-16+salen;
		return ::operator new(totalsz);
	}

	void operator delete(void *ptr, const int &) {
		::operator delete(ptr);
	}

	void operator delete(void *ptr, std::size_t ) {
		::operator delete(ptr);
	}

protected:
	addrinfo addr;
	char data[16];

};

std::string AddressAddrInfo::toString(bool ) const {
	if (addr->ai_canonname == 0) {
		char addrbuff[256];
		char portbuff[256];
		switch (addr->ai_family) {
		case AF_INET:
			inet_ntop(addr->ai_family,
					&reinterpret_cast<const sockaddr_in *>(addr->ai_addr)->sin_addr,
					addrbuff,sizeof(addrbuff));
			snprintf(portbuff, sizeof(portbuff), "%d", htons(reinterpret_cast<const sockaddr_in *>(addr->ai_addr)->sin_port));
			return std::string(addrbuff)+":"+portbuff;
		case AF_INET6:
			inet_ntop(addr->ai_family,
					&reinterpret_cast<const sockaddr_in6 *>(addr->ai_addr)->sin6_addr,
					addrbuff,sizeof(addrbuff));
			snprintf(portbuff, sizeof(portbuff), "%d", htons(reinterpret_cast<const sockaddr_in6 *>(addr->ai_addr)->sin6_port));
			return std::string("[")+addrbuff+"]:"+portbuff;
		case AF_UNIX:
			return std::string("unix://")+reinterpret_cast<const sockaddr_un *>(addr->ai_addr)->sun_path;
		default:
			return "<unknown address>";
		}
	} else {
		return addr->ai_canonname;
	}
}

BinaryView AddressAddrInfo::toSockAddr() const {
	return BinaryView(reinterpret_cast<const unsigned char *>(addr->ai_addr), addr->ai_addrlen);
}

std::string NetAddr::toString(bool resolve) const {
	return addr->toString(resolve);
}

BinaryView NetAddr::toSockAddr() const {
	return addr->toSockAddr();
}

static char *copyString(void *abuff, StrViewA str) {
	char *buff = reinterpret_cast<char *>(abuff);
	std::memcpy(buff, str.data, str.length);
	buff[str.length] = 0;
	return buff;
}

static char *copyNumberToStr2(char *buff, unsigned int number) {
	if (number) {
		char *c = copyNumberToStr2(buff, number/10);
		*c = number % 10 + '0';
		return c+1;
	} else {
		return buff;
	}
}

static char *copyNumberToStr(void *abuff, unsigned int number) {
	char *buff = reinterpret_cast<char *>(abuff);
	if (number == 0) strcpy(buff,"0");
	else *copyNumberToStr2(buff, number) = 0;
	return buff;
}

class GaiError: public SystemException {
public:
	GaiError(int e):SystemException(e) {}
	std::string getMessage() const {
		return gai_strerror(this->err);
	}
};

static NetAddr createUnixAddress(StrViewA file) {
	unsigned int perms = 0;
	auto seppos = file.indexOf(":");
	if (seppos != file.npos) {
		perms = 0;
		if (file.length - seppos < 4) {
			throw SystemException(EINVAL,std::string("Permission must have 3 octal numbers:")+std::string(file));
		}
		for (unsigned int i = 0; i < 3; i++) {
			unsigned int v = file[seppos+i+1]-'0';
			if (v > 7) {
				throw SystemException(EINVAL,std::string("Permission must be octal number:")+std::string(file));
			}
			perms = perms * 8 + v;
		}
		file = file.substr(0,seppos);
	}

	return NetAddr(new NetAddrSocket(realpath(file),perms));
}

NetAddr NetAddr::create(StrViewA addr, unsigned int defaultPort, AddressType type) {

	if (addr.indexOf(",") != addr.npos) {
		auto spl = addr.split(",");
		StrViewA a = spl();
		a = a.trim(isspace);
		NetAddr addr = create(a, defaultPort, type);
		while (spl) {
			a = spl();
			a = a.trim(isspace);
			NetAddr b = create(a, defaultPort, type);
			addr = addr + b;
		}
		return addr;
	}

	if (addr.substr(0,7) == "unix://" && addr.length>8) {
		return createUnixAddress(addr.substr(6+(addr[7]=='.'?1:0)));
	}
	if (addr.substr(0,5) == "unix:" && addr.length>5) {
		return createUnixAddress(addr.substr(5));
	}

	struct addrinfo req, *result;
	std::memset(&req,0,sizeof(req));
	req.ai_socktype = SOCK_STREAM;

	StrViewA prepNode;
	StrViewA prepPort;

	const char *node = 0;
	const char *svc = 0;

	switch (type) {
		default:
		case IPvAll: 	req.ai_family = AF_UNSPEC;break;
		case IPv4: 		req.ai_family = AF_INET;break;
		case IPv6: 		req.ai_family = AF_INET6;break;
	}

	req.ai_flags |=  AI_CANONIDN;

	if (addr.empty()) {
		req.ai_flags |=  AI_PASSIVE;
		node = nullptr;
	} else {
		if (addr[0] == '[') {

			std::size_t sep = addr.lastIndexOf("]:");
			if (sep == addr.npos) {
				if (addr[addr.length-1] == ']') {
					prepNode = addr.substr(1, addr.length-2);
				} else {
					sep = addr.lastIndexOf(":");
					if (sep == addr.npos) {
						prepNode = addr;
					} else {
						prepNode = addr.substr(0,sep);
						prepPort = addr.substr(sep+1);
					}
				}
			} else {
				prepNode = addr.substr(0,sep);
				prepPort = addr.substr(sep+2);
			}
		} else {
			std::size_t sep = addr.lastIndexOf(":");
			if (sep == addr.npos) {
				prepNode = addr;
			} else {
				prepNode = addr.substr(0,sep);
				prepPort = addr.substr(sep+1);
			}
		}
		node = copyString(alloca(prepNode.length+1),prepNode);

	}

	if (prepPort.empty()) {
		svc = copyNumberToStr(alloca(30), defaultPort);
	} else {
		svc = copyString(alloca(prepPort.length+1), prepPort);
	}

	int e = getaddrinfo(node,svc, &req, &result);
	if (e) {
		if (e == EAI_SYSTEM) throw SystemException(errno);
		else throw GaiError(e);
	}

	//HACK: Some OS returns duplicated records. Perform deduplication
	{
		struct addrinfo *tmp = nullptr, *x = result;
		while (x) {
			auto z = x->ai_next;
			x->ai_next = tmp;
			auto p = tmp;
			while (p) {
				if (p->ai_addrlen == x->ai_addrlen
						&& p->ai_family == x->ai_family
						&& memcmp(p->ai_addr,x->ai_addr,x->ai_addrlen) == 0)
					break;
				p = p->ai_next;
			}
			if (p == nullptr) {
				tmp = x;
			}
			x = z;
		}

		result = 0;
		while (tmp) {
			auto x = tmp;
			tmp = tmp->ai_next;
			x->ai_next = result;
			result = x;
		}
	}

	return PNetworkAddress::staticCast(RefCntPtr<AddressAddrInfo>(new AddressAddrInfo(result)));
}

NetAddr NetAddr::create(const BinaryView &addr, int protocol) {
	return  PNetworkAddress::staticCast(RefCntPtr<AddressSockAddr>(
			new(addr.length) AddressSockAddr(reinterpret_cast<const struct sockaddr *>(addr.data),addr.length, protocol)));
}

class ChainedNetworkAddr: public INetworkAddress {
public:

	ChainedNetworkAddr(NetAddr master, NetAddr slave, NetAddr next):master(master),slave(slave),next(next) {}

	virtual std::string toString(bool resolve = false) const override {
		return slave.toString(resolve);
	}
	virtual BinaryView toSockAddr() const override {
		return slave.toSockAddr();
	}

	virtual RefCntPtr<INetworkAddress> getNextAddr() const override {
		auto ret = slave.getNextAddr();
		if (ret == nullptr) return next.getHandle();
		else {
			return new ChainedNetworkAddr(master, ret, next);
		}
	};

	~ChainedNetworkAddr() noexcept {}

	virtual const INetworkAddress &unproxy() const override {return (slave.getHandle())->unproxy();}

	virtual SocketObject connect() const override  {return slave.connect();}
	virtual SocketObject listen() const override {return slave.listen();}

protected:
	NetAddr master, slave, next;

//	template<typename T> friend class RefCntPtr;

};

NetAddr NetAddr::operator +(const NetAddr& other) const {
	return NetAddr(new ChainedNetworkAddr(*this,*this, other));
}

RefCntPtr<INetworkAddress> NetAddr::getNextAddr() const {
	return addr->getNextAddr();
}

SocketObject NetAddr::connect() const {
	return addr->connect();
}

SocketObject NetAddr::listen() const {
	return addr->listen();
}

int invalidSocketValue = -1;

}
<commit_msg>use * in address to specify listening on all interfaces<commit_after>#include <cstring>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
 #include <arpa/inet.h>
#include <unistd.h>
#include "../address.h"

#include "../exceptions.h"

#include "../stringview.h"
#include "socketObject.h"
#include "localAddr.h"
#include "../realpath.h"

using ondra_shared::StringView;

namespace simpleServer {

class AddressAddrInfo: public INetworkAddress {
public:
	AddressAddrInfo(struct addrinfo *addr):addr(addr) {}

	virtual std::string toString(bool resolve = false) const override;
	virtual BinaryView toSockAddr() const override;
	virtual RefCntPtr<INetworkAddress> getNextAddr() const override;

	virtual SocketObject connect() const override;
	virtual SocketObject listen() const override;

	~AddressAddrInfo() {
		if (addr) freeaddrinfo(addr);
	}

	virtual const INetworkAddress &unproxy() const override {return *this;}

protected:

	struct addrinfo *addr;

};

class AddressAddrInfoSlave: public AddressAddrInfo {
public:
	AddressAddrInfoSlave(struct addrinfo *addr, RefCntPtr<AddressAddrInfo> master)
		:AddressAddrInfo(addr),master(master) {}

	~AddressAddrInfoSlave() noexcept {
		addr = nullptr;
	}

	virtual const INetworkAddress &unproxy() const {return *this;}
protected:
//	template<typename T> friend class RefCntPtr;

	RefCntPtr<AddressAddrInfo> master;

};

RefCntPtr<INetworkAddress> AddressAddrInfo::getNextAddr() const
{
	if (addr->ai_next) return new AddressAddrInfoSlave(addr->ai_next, const_cast<AddressAddrInfo *>(this));
	else return nullptr;
}

SocketObject AddressAddrInfo::connect() const {
	SocketObject s(socket(addr->ai_family, SOCK_STREAM, addr->ai_protocol));
	if (!s) throw SystemException(errno,"Failed to create socket");
	int nblock = 1;ioctl(s, FIONBIO, &nblock);
	::connect(s, reinterpret_cast<const struct sockaddr *>(addr->ai_addr),addr->ai_addrlen);
	return s;
}
SocketObject AddressAddrInfo::listen() const {
	SocketObject s(socket(addr->ai_family, SOCK_STREAM, addr->ai_protocol));
	if (!s) throw SystemException(errno,"Failed to create socket");
	int enable = 1;
	(void)setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
	if (addr->ai_family == AF_INET6)
		(void)setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(int));
	(void)ioctl(s, FIONBIO, &enable);
	if (::bind(s, reinterpret_cast<const struct sockaddr *>(addr->ai_addr),addr->ai_addrlen) == -1) {
		int e = errno;
		throw SystemException(e,"Cannot bind socket to port:" + this->toString(false));
	}
	if (::listen(s,SOMAXCONN) == -1) {
		int e = errno;
		throw SystemException(e,"Cannot activate listen mode on the socket:" + this->toString(false));
	}
	return s;
}

class AddressSockAddr: public AddressAddrInfo {
public:

	static addrinfo *convert_to_addrinfo(AddressSockAddr *me, const struct sockaddr *sa, int len, int protocol) {
		me->addr.ai_addr = reinterpret_cast<sockaddr *>(me->data);
		me->addr.ai_addrlen = len;
		me->addr.ai_canonname = 0;
		me->addr.ai_family = sa->sa_family;
		me->addr.ai_flags = 0;
		me->addr.ai_next = 0;
		me->addr.ai_protocol = protocol;
		me->addr.ai_socktype= SOCK_STREAM;
		std::memcpy(me->data, sa, len);
		return &me->addr;
	}

	AddressSockAddr(const struct sockaddr *sa, int len, int protocol)
		:AddressAddrInfo(convert_to_addrinfo(this,sa,len,protocol)) {}

	~AddressSockAddr() {
		AddressAddrInfo::addr = nullptr;
	}

	void *operator new(std::size_t sz, const int &salen) {
		std::size_t totalsz = sz-16+salen;
		return ::operator new(totalsz);
	}

	void operator delete(void *ptr, const int &) {
		::operator delete(ptr);
	}

	void operator delete(void *ptr, std::size_t ) {
		::operator delete(ptr);
	}

protected:
	addrinfo addr;
	char data[16];

};

std::string AddressAddrInfo::toString(bool ) const {
	if (addr->ai_canonname == 0) {
		char addrbuff[256];
		char portbuff[256];
		switch (addr->ai_family) {
		case AF_INET:
			inet_ntop(addr->ai_family,
					&reinterpret_cast<const sockaddr_in *>(addr->ai_addr)->sin_addr,
					addrbuff,sizeof(addrbuff));
			snprintf(portbuff, sizeof(portbuff), "%d", htons(reinterpret_cast<const sockaddr_in *>(addr->ai_addr)->sin_port));
			return std::string(addrbuff)+":"+portbuff;
		case AF_INET6:
			inet_ntop(addr->ai_family,
					&reinterpret_cast<const sockaddr_in6 *>(addr->ai_addr)->sin6_addr,
					addrbuff,sizeof(addrbuff));
			snprintf(portbuff, sizeof(portbuff), "%d", htons(reinterpret_cast<const sockaddr_in6 *>(addr->ai_addr)->sin6_port));
			return std::string("[")+addrbuff+"]:"+portbuff;
		case AF_UNIX:
			return std::string("unix://")+reinterpret_cast<const sockaddr_un *>(addr->ai_addr)->sun_path;
		default:
			return "<unknown address>";
		}
	} else {
		return addr->ai_canonname;
	}
}

BinaryView AddressAddrInfo::toSockAddr() const {
	return BinaryView(reinterpret_cast<const unsigned char *>(addr->ai_addr), addr->ai_addrlen);
}

std::string NetAddr::toString(bool resolve) const {
	return addr->toString(resolve);
}

BinaryView NetAddr::toSockAddr() const {
	return addr->toSockAddr();
}

static char *copyString(void *abuff, StrViewA str) {
	char *buff = reinterpret_cast<char *>(abuff);
	std::memcpy(buff, str.data, str.length);
	buff[str.length] = 0;
	return buff;
}

static char *copyNumberToStr2(char *buff, unsigned int number) {
	if (number) {
		char *c = copyNumberToStr2(buff, number/10);
		*c = number % 10 + '0';
		return c+1;
	} else {
		return buff;
	}
}

static char *copyNumberToStr(void *abuff, unsigned int number) {
	char *buff = reinterpret_cast<char *>(abuff);
	if (number == 0) strcpy(buff,"0");
	else *copyNumberToStr2(buff, number) = 0;
	return buff;
}

class GaiError: public SystemException {
public:
	GaiError(int e):SystemException(e) {}
	std::string getMessage() const {
		return gai_strerror(this->err);
	}
};

static NetAddr createUnixAddress(StrViewA file) {
	unsigned int perms = 0;
	auto seppos = file.indexOf(":");
	if (seppos != file.npos) {
		perms = 0;
		if (file.length - seppos < 4) {
			throw SystemException(EINVAL,std::string("Permission must have 3 octal numbers:")+std::string(file));
		}
		for (unsigned int i = 0; i < 3; i++) {
			unsigned int v = file[seppos+i+1]-'0';
			if (v > 7) {
				throw SystemException(EINVAL,std::string("Permission must be octal number:")+std::string(file));
			}
			perms = perms * 8 + v;
		}
		file = file.substr(0,seppos);
	}

	return NetAddr(new NetAddrSocket(realpath(file),perms));
}

NetAddr NetAddr::create(StrViewA addr, unsigned int defaultPort, AddressType type) {

	if (addr.indexOf(",") != addr.npos) {
		auto spl = addr.split(",");
		StrViewA a = spl();
		a = a.trim(isspace);
		NetAddr addr = create(a, defaultPort, type);
		while (spl) {
			a = spl();
			a = a.trim(isspace);
			NetAddr b = create(a, defaultPort, type);
			addr = addr + b;
		}
		return addr;
	}

	if (addr.substr(0,7) == "unix://" && addr.length>8) {
		return createUnixAddress(addr.substr(6+(addr[7]=='.'?1:0)));
	}
	if (addr.substr(0,5) == "unix:" && addr.length>5) {
		return createUnixAddress(addr.substr(5));
	}

	struct addrinfo req, *result;
	std::memset(&req,0,sizeof(req));
	req.ai_socktype = SOCK_STREAM;

	StrViewA prepNode;
	StrViewA prepPort;

	const char *node = 0;
	const char *svc = 0;

	switch (type) {
		default:
		case IPvAll: 	req.ai_family = AF_UNSPEC;break;
		case IPv4: 		req.ai_family = AF_INET;break;
		case IPv6: 		req.ai_family = AF_INET6;break;
	}

	req.ai_flags |=  AI_CANONIDN;

	if (addr.empty()) {
		req.ai_flags |=  AI_PASSIVE;
		node = nullptr;
	} else {
		if (addr[0] == '[') {

			std::size_t sep = addr.lastIndexOf("]:");
			if (sep == addr.npos) {
				if (addr[addr.length-1] == ']') {
					prepNode = addr.substr(1, addr.length-2);
				} else {
					sep = addr.lastIndexOf(":");
					if (sep == addr.npos) {
						prepNode = addr;
					} else {
						prepNode = addr.substr(0,sep);
						prepPort = addr.substr(sep+1);
					}
				}
			} else {
				prepNode = addr.substr(0,sep);
				prepPort = addr.substr(sep+2);
			}
		} else {
			std::size_t sep = addr.lastIndexOf(":");
			if (sep == addr.npos) {
				prepNode = addr;
			} else {
				prepNode = addr.substr(0,sep);
				prepPort = addr.substr(sep+1);
			}
		}
		if (prepNode.empty() || prepNode=="*") {
			req.ai_flags |=  AI_PASSIVE;
			node = nullptr;
		} else {
			node = copyString(alloca(prepNode.length+1),prepNode);
		}

	}

	if (prepPort.empty()) {
		svc = copyNumberToStr(alloca(30), defaultPort);
	} else {
		svc = copyString(alloca(prepPort.length+1), prepPort);
	}

	int e = getaddrinfo(node,svc, &req, &result);
	if (e) {
		if (e == EAI_SYSTEM) throw SystemException(errno);
		else throw GaiError(e);
	}

	//HACK: Some OS returns duplicated records. Perform deduplication
	{
		struct addrinfo *tmp = nullptr, *x = result;
		while (x) {
			auto z = x->ai_next;
			x->ai_next = tmp;
			auto p = tmp;
			while (p) {
				if (p->ai_addrlen == x->ai_addrlen
						&& p->ai_family == x->ai_family
						&& memcmp(p->ai_addr,x->ai_addr,x->ai_addrlen) == 0)
					break;
				p = p->ai_next;
			}
			if (p == nullptr) {
				tmp = x;
			}
			x = z;
		}

		result = 0;
		while (tmp) {
			auto x = tmp;
			tmp = tmp->ai_next;
			x->ai_next = result;
			result = x;
		}
	}

	return PNetworkAddress::staticCast(RefCntPtr<AddressAddrInfo>(new AddressAddrInfo(result)));
}

NetAddr NetAddr::create(const BinaryView &addr, int protocol) {
	return  PNetworkAddress::staticCast(RefCntPtr<AddressSockAddr>(
			new(addr.length) AddressSockAddr(reinterpret_cast<const struct sockaddr *>(addr.data),addr.length, protocol)));
}

class ChainedNetworkAddr: public INetworkAddress {
public:

	ChainedNetworkAddr(NetAddr master, NetAddr slave, NetAddr next):master(master),slave(slave),next(next) {}

	virtual std::string toString(bool resolve = false) const override {
		return slave.toString(resolve);
	}
	virtual BinaryView toSockAddr() const override {
		return slave.toSockAddr();
	}

	virtual RefCntPtr<INetworkAddress> getNextAddr() const override {
		auto ret = slave.getNextAddr();
		if (ret == nullptr) return next.getHandle();
		else {
			return new ChainedNetworkAddr(master, ret, next);
		}
	};

	~ChainedNetworkAddr() noexcept {}

	virtual const INetworkAddress &unproxy() const override {return (slave.getHandle())->unproxy();}

	virtual SocketObject connect() const override  {return slave.connect();}
	virtual SocketObject listen() const override {return slave.listen();}

protected:
	NetAddr master, slave, next;

//	template<typename T> friend class RefCntPtr;

};

NetAddr NetAddr::operator +(const NetAddr& other) const {
	return NetAddr(new ChainedNetworkAddr(*this,*this, other));
}

RefCntPtr<INetworkAddress> NetAddr::getNextAddr() const {
	return addr->getNextAddr();
}

SocketObject NetAddr::connect() const {
	return addr->connect();
}

SocketObject NetAddr::listen() const {
	return addr->listen();
}

int invalidSocketValue = -1;

}
<|endoftext|>


<commit_before>#include <QCoreApplication>
#include <QsLog.h>
#include <QStringList>
#include <QDBusMessage>
#include <QEventLoop>
#include <QTimer>
#include <unistd.h>
#include <velib/qt/ve_qitem.hpp>
#include <velib/qt/ve_qitems_dbus.hpp>
#include <velib/qt/ve_qitem_dbus_publisher.hpp>
#include "dbus_bridge.h"
#include "ac_sensor.h"
#include "ac_sensor_mediator.h"

bool initDBus(QDBusConnection &dbus)
{
	// Calling GetDefault on /Settings should return -1. It's a simple way
	// to see if localsettings is up without relying on a particular path.
	QDBusMessage m = QDBusMessage::createMethodCall("com.victronenergy.settings",
		"/Settings", "com.victronenergy.BusItem", "GetDefault");

	QLOG_INFO() << "Wait for local settings on DBus... ";

	for (int i=0; i<10; i++) {
		QDBusMessage reply = dbus.call(m);
		if (reply.type() == QDBusMessage::ReplyMessage) {
			QLOG_INFO() << "Local settings found";
			return true;
		}

		QLOG_INFO() << "Waiting...";

		QEventLoop l;
		QTimer::singleShot(2000, &l, SLOT(quit()));
		l.exec();
	}
	return false;
}

void initLogger(QsLogging::Level logLevel)
{
	QsLogging::Logger &logger = QsLogging::Logger::instance();
	QsLogging::DestinationPtr debugDestination(
			QsLogging::DestinationFactory::MakeDebugOutputDestination());
	logger.addDestination(debugDestination);
	logger.setIncludeTimestamp(false);

	QLOG_INFO() << "dbus-cgwacs" << "v" VERSION << "started";
	QLOG_INFO() << "Built with Qt" << QT_VERSION_STR << "running on" << qVersion();
	QLOG_INFO() << "Built on" << __DATE__ << "at" << __TIME__;
	logger.setLoggingLevel(logLevel);
}

extern "C"
{
// This function is called by the serial port API from velib when the device is
// disconnected from the serial port.
void pltExit(int ret)
{
	QCoreApplication::exit(ret);
}
}

int main(int argc, char *argv[])
{
	QCoreApplication app(argc, argv);
	app.setApplicationVersion(VERSION);
	app.setApplicationName(app.arguments()[0]);

	initLogger(QsLogging::InfoLevel);

	bool isZigbee = false;
	QString portName;
	QString dbusAddress = "system";
	int timeout = 250;
	QStringList args = app.arguments();
	args.pop_front();

	while (!args.isEmpty()) {
		QString arg = args.takeFirst();

		if (arg == "-h" || arg == "--help") {
			QLOG_INFO() << app.arguments().first();
			QLOG_INFO() << "\t-h, --help";
			QLOG_INFO() << "\t Show this message.";
			QLOG_INFO() << "\t-V, --version";
			QLOG_INFO() << "\t Show the application version.";
			QLOG_INFO() << "\t-b, --dbus";
			QLOG_INFO() << "\t dbus address or 'session' or 'system'";
			QLOG_INFO() << "\t-d level, --debug level";
			QLOG_INFO() << "\t Set log level";
			QLOG_INFO() << "\t--timeout milliseconds";
			QLOG_INFO() << "\t Timeout in milliseconds for RS485 responses";
			QLOG_INFO() << "\t <Port Name>";
			QLOG_INFO() << "\t Name of communication port (eg. /dev/ttyUSB0)";
			exit(1);
		} else if (arg == "-V" || arg == "--version") {
			QLOG_INFO() << VERSION;
			exit(0);
		} else if (arg == "-d" || arg == "--debug") {
			if (!args.isEmpty()) {
				arg = args.takeFirst();
				QsLogging::Logger &logger = QsLogging::Logger::instance();
				QsLogging::Level logLevel = static_cast<QsLogging::Level>(qBound(
					static_cast<int>(QsLogging::TraceLevel),
					arg.toInt(),
					static_cast<int>(QsLogging::OffLevel)));
				logger.setLoggingLevel(logLevel);
			}
		} else if (arg == "-t" || arg == "--timestamp") {
			QsLogging::Logger &logger = QsLogging::Logger::instance();
			logger.setIncludeTimestamp(true);
		} else if (arg == "--timeout") {
			if (!args.isEmpty())
				timeout = qBound(150, args.takeFirst().toInt(), 10000);
		} else if (arg == "-b" || arg == "--dbus") {
			if (!args.isEmpty())
				dbusAddress = args.takeFirst();
		} else if (arg == "-z" || arg == "--zigbee") {
			timeout = qMax(2000, timeout);
			isZigbee = true;
		} else if (!arg.startsWith('-')) {
			portName = arg;
		}
	}

	if (portName.isEmpty()) {
		QLOG_ERROR() << "No communication port specified on command line";
		exit(2);
	} else {
		QLOG_INFO() << "Connecting to" << portName;
	}

	VeQItemDbusProducer producer(VeQItems::getRoot(), "sub", false, false);
	producer.setListenIndividually(true);
	producer.open(dbusAddress);

	BridgeItemProducer dbusExportProducer(VeQItems::getRoot(), "pub");
	VeQItemDbusPublisher publisher(dbusExportProducer.services());
	publisher.open(dbusAddress);

	qRegisterMetaType<ConnectionState>();

	if (!initDBus(producer.dbusConnection())) {
		return 1; // Not success
	}

	VeQItem *settingsRoot = VeQItems::getRoot()->itemGetOrCreate("sub/com.victronenergy.settings", false);
	AcSensorMediator m(portName, timeout, isZigbee, settingsRoot);

	app.connect(&m, SIGNAL(connectionLost()), &app, SLOT(quit()));
	app.connect(&m, SIGNAL(serialEvent(const char *)), &app, SLOT(quit()));

	return app.exec();
}
<commit_msg>Use a dbus Introspectable/Introspect call to detect localsettings.<commit_after>#include <QCoreApplication>
#include <QsLog.h>
#include <QStringList>
#include <QDBusMessage>
#include <QEventLoop>
#include <QTimer>
#include <unistd.h>
#include <velib/qt/ve_qitem.hpp>
#include <velib/qt/ve_qitems_dbus.hpp>
#include <velib/qt/ve_qitem_dbus_publisher.hpp>
#include "dbus_bridge.h"
#include "ac_sensor.h"
#include "ac_sensor_mediator.h"

bool initDBus(QDBusConnection &dbus)
{
	// Calling GetDefault on /Settings should return -1. It's a simple way
	// to see if localsettings is up without relying on a particular path.
	QDBusMessage m = QDBusMessage::createMethodCall("com.victronenergy.settings",
		"/Settings", "org.freedesktop.DBus.Introspectable", "Introspect");

	QLOG_INFO() << "Wait for local settings on DBus... ";

	for (int i=0; i<10; i++) {
		QDBusMessage reply = dbus.call(m);
		if (reply.type() == QDBusMessage::ReplyMessage) {
			QLOG_INFO() << "Local settings found";
			return true;
		}

		QLOG_INFO() << "Waiting...";

		QEventLoop l;
		QTimer::singleShot(2000, &l, SLOT(quit()));
		l.exec();
	}
	return false;
}

void initLogger(QsLogging::Level logLevel)
{
	QsLogging::Logger &logger = QsLogging::Logger::instance();
	QsLogging::DestinationPtr debugDestination(
			QsLogging::DestinationFactory::MakeDebugOutputDestination());
	logger.addDestination(debugDestination);
	logger.setIncludeTimestamp(false);

	QLOG_INFO() << "dbus-cgwacs" << "v" VERSION << "started";
	QLOG_INFO() << "Built with Qt" << QT_VERSION_STR << "running on" << qVersion();
	QLOG_INFO() << "Built on" << __DATE__ << "at" << __TIME__;
	logger.setLoggingLevel(logLevel);
}

extern "C"
{
// This function is called by the serial port API from velib when the device is
// disconnected from the serial port.
void pltExit(int ret)
{
	QCoreApplication::exit(ret);
}
}

int main(int argc, char *argv[])
{
	QCoreApplication app(argc, argv);
	app.setApplicationVersion(VERSION);
	app.setApplicationName(app.arguments()[0]);

	initLogger(QsLogging::InfoLevel);

	bool isZigbee = false;
	QString portName;
	QString dbusAddress = "system";
	int timeout = 250;
	QStringList args = app.arguments();
	args.pop_front();

	while (!args.isEmpty()) {
		QString arg = args.takeFirst();

		if (arg == "-h" || arg == "--help") {
			QLOG_INFO() << app.arguments().first();
			QLOG_INFO() << "\t-h, --help";
			QLOG_INFO() << "\t Show this message.";
			QLOG_INFO() << "\t-V, --version";
			QLOG_INFO() << "\t Show the application version.";
			QLOG_INFO() << "\t-b, --dbus";
			QLOG_INFO() << "\t dbus address or 'session' or 'system'";
			QLOG_INFO() << "\t-d level, --debug level";
			QLOG_INFO() << "\t Set log level";
			QLOG_INFO() << "\t--timeout milliseconds";
			QLOG_INFO() << "\t Timeout in milliseconds for RS485 responses";
			QLOG_INFO() << "\t <Port Name>";
			QLOG_INFO() << "\t Name of communication port (eg. /dev/ttyUSB0)";
			exit(1);
		} else if (arg == "-V" || arg == "--version") {
			QLOG_INFO() << VERSION;
			exit(0);
		} else if (arg == "-d" || arg == "--debug") {
			if (!args.isEmpty()) {
				arg = args.takeFirst();
				QsLogging::Logger &logger = QsLogging::Logger::instance();
				QsLogging::Level logLevel = static_cast<QsLogging::Level>(qBound(
					static_cast<int>(QsLogging::TraceLevel),
					arg.toInt(),
					static_cast<int>(QsLogging::OffLevel)));
				logger.setLoggingLevel(logLevel);
			}
		} else if (arg == "-t" || arg == "--timestamp") {
			QsLogging::Logger &logger = QsLogging::Logger::instance();
			logger.setIncludeTimestamp(true);
		} else if (arg == "--timeout") {
			if (!args.isEmpty())
				timeout = qBound(150, args.takeFirst().toInt(), 10000);
		} else if (arg == "-b" || arg == "--dbus") {
			if (!args.isEmpty())
				dbusAddress = args.takeFirst();
		} else if (arg == "-z" || arg == "--zigbee") {
			timeout = qMax(2000, timeout);
			isZigbee = true;
		} else if (!arg.startsWith('-')) {
			portName = arg;
		}
	}

	if (portName.isEmpty()) {
		QLOG_ERROR() << "No communication port specified on command line";
		exit(2);
	} else {
		QLOG_INFO() << "Connecting to" << portName;
	}

	VeQItemDbusProducer producer(VeQItems::getRoot(), "sub", false, false);
	producer.setListenIndividually(true);
	producer.open(dbusAddress);

	BridgeItemProducer dbusExportProducer(VeQItems::getRoot(), "pub");
	VeQItemDbusPublisher publisher(dbusExportProducer.services());
	publisher.open(dbusAddress);

	qRegisterMetaType<ConnectionState>();

	if (!initDBus(producer.dbusConnection())) {
		return 1; // Not success
	}

	VeQItem *settingsRoot = VeQItems::getRoot()->itemGetOrCreate("sub/com.victronenergy.settings", false);
	AcSensorMediator m(portName, timeout, isZigbee, settingsRoot);

	app.connect(&m, SIGNAL(connectionLost()), &app, SLOT(quit()));
	app.connect(&m, SIGNAL(serialEvent(const char *)), &app, SLOT(quit()));

	return app.exec();
}
<|endoftext|>