<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLIndexBibliographyConfigurationContext.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 18:39:55 $
 *
 *  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 _XMLOFF_XMLINDEXBIBLIOGRAPHYCONFIGURATIONCONTEXT_HXX_
#include "XMLIndexBibliographyConfigurationContext.hxx"
#endif

#ifndef _XMLOFF_XMLINDEXBIBLIOGRAPHYENTRYCONTEXT_HXX_
#include "XMLIndexBibliographyEntryContext.hxx"
#endif

#ifndef _XMLOFF_XMLICTXT_HXX
#include "xmlictxt.hxx"
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif

#ifndef _XMLOFF_TEXTIMP_HXX_
#include "txtimp.hxx"
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

using namespace ::com::sun::star::text;
using namespace ::com::sun::star::uno;
using namespace ::xmloff::token;

using ::rtl::OUString;
using ::com::sun::star::xml::sax::XAttributeList;
using ::com::sun::star::beans::PropertyValue;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::lang::XMultiServiceFactory;

const sal_Char sAPI_FieldMaster_Bibliography[] =
                                "com.sun.star.text.FieldMaster.Bibliography";

TYPEINIT1( XMLIndexBibliographyConfigurationContext, SvXMLStyleContext );

XMLIndexBibliographyConfigurationContext::XMLIndexBibliographyConfigurationContext(
    SvXMLImport& rImport,
    sal_uInt16 nPrfx,
    const OUString& rLocalName,
    const Reference<XAttributeList> & xAttrList) :
        SvXMLStyleContext(rImport, nPrfx, rLocalName, xAttrList, XML_STYLE_FAMILY_TEXT_BIBLIOGRAPHYCONFIG),
        sFieldMaster_Bibliography(
            RTL_CONSTASCII_USTRINGPARAM(sAPI_FieldMaster_Bibliography)),
        sBracketBefore(RTL_CONSTASCII_USTRINGPARAM("BracketBefore")),
        sBracketAfter(RTL_CONSTASCII_USTRINGPARAM("BracketAfter")),
        sIsNumberEntries(RTL_CONSTASCII_USTRINGPARAM("IsNumberEntries")),
        sIsSortByPosition(RTL_CONSTASCII_USTRINGPARAM("IsSortByPosition")),
        sSortKeys(RTL_CONSTASCII_USTRINGPARAM("SortKeys")),
        sSortKey(RTL_CONSTASCII_USTRINGPARAM("SortKey")),
        sIsSortAscending(RTL_CONSTASCII_USTRINGPARAM("IsSortAscending")),
        sSortAlgorithm(RTL_CONSTASCII_USTRINGPARAM("SortAlgorithm")),
        sLocale(RTL_CONSTASCII_USTRINGPARAM("Locale")),
        sSuffix(),
        sPrefix(),
        sAlgorithm(),
        aLocale(),
        bNumberedEntries(sal_False),
        bSortByPosition(sal_True)
{
}

XMLIndexBibliographyConfigurationContext::~XMLIndexBibliographyConfigurationContext()
{
}

void XMLIndexBibliographyConfigurationContext::StartElement(
    const Reference<XAttributeList> & xAttrList)
{
    sal_Int16 nLength = xAttrList->getLength();
    for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
    {
        OUString sLocalName;
        sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
            GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
                              &sLocalName );

        ProcessAttribute(nPrefix, sLocalName,
                         xAttrList->getValueByIndex(nAttr));
        // else: ignore
    }
}

void XMLIndexBibliographyConfigurationContext::ProcessAttribute(
    sal_uInt16 nPrefix,
    OUString sLocalName,
    OUString sValue)
{
    if( XML_NAMESPACE_TEXT == nPrefix )
    {
        if( IsXMLToken(sLocalName, XML_PREFIX) )
        {
            sPrefix = sValue;
        }
        else if( IsXMLToken(sLocalName, XML_SUFFIX) )
        {
            sSuffix = sValue;
        }
        else if( IsXMLToken(sLocalName, XML_NUMBERED_ENTRIES) )
        {
            sal_Bool bTmp;
            if( SvXMLUnitConverter::convertBool(bTmp, sValue) )
            {
                bNumberedEntries = bTmp;
            }
        }
        else if( IsXMLToken(sLocalName, XML_SORT_BY_POSITION) )
        {
            sal_Bool bTmp;
            if (SvXMLUnitConverter::convertBool(bTmp, sValue))
            {
                bSortByPosition = bTmp;
            }
        }
        else if( IsXMLToken(sLocalName, XML_SORT_ALGORITHM) )
        {
            sAlgorithm = sValue;
        }
    }
    else if( XML_NAMESPACE_FO == nPrefix )
    {
        if( IsXMLToken(sLocalName, XML_LANGUAGE) )
        {
            aLocale.Language = sValue;
        }
        else if( IsXMLToken(sLocalName, XML_COUNTRY) )
        {
            aLocale.Country = sValue;
        }
    }
}

SvXMLImportContext *XMLIndexBibliographyConfigurationContext::CreateChildContext(
    sal_uInt16 nPrefix,
    const OUString& rLocalName,
    const Reference<XAttributeList> & xAttrList )
{
    OUString sKey;
    sal_Bool bSort(sal_True);

    // process children here and use default context!
    if ( ( nPrefix == XML_NAMESPACE_TEXT ) &&
         IsXMLToken( rLocalName, XML_SORT_KEY ) )
    {
        sal_Int16 nLength = xAttrList->getLength();
        for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
        {
            OUString sLocalName;
            sal_uInt16 nPrfx = GetImport().GetNamespaceMap().
                GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
                                  &sLocalName );

            if (nPrfx == XML_NAMESPACE_TEXT)
            {
                if ( IsXMLToken( sLocalName, XML_KEY ) )
                {
                    sKey = xAttrList->getValueByIndex(nAttr);
                }
                else if ( IsXMLToken( sLocalName, XML_SORT_ASCENDING ) )
                {
                    sal_Bool bTmp;
                    if (SvXMLUnitConverter::convertBool(
                        bTmp, xAttrList->getValueByIndex(nAttr)))
                    {
                        bSort = bTmp;
                    }
                }
            }
        }

        // valid data?
        sal_uInt16 nKey;
        if (SvXMLUnitConverter::convertEnum(nKey, sKey,
                                            aBibliographyDataFieldMap))
        {

            Any aAny;
            Sequence<PropertyValue> aKey(2);

            PropertyValue aNameValue;
            aNameValue.Name = sSortKey;
            aAny <<= (sal_Int16)nKey;
            aNameValue.Value = aAny;
            aKey[0] = aNameValue;

            PropertyValue aSortValue;
            aSortValue.Name = sIsSortAscending;
            aAny.setValue(&bSort, ::getBooleanCppuType());
            aSortValue.Value = aAny;
            aKey[1] = aSortValue;

            aSortKeys.push_back(aKey);
        }
    }

    return SvXMLImportContext::CreateChildContext(nPrefix, rLocalName,
                                                  xAttrList);
}

void XMLIndexBibliographyConfigurationContext::CreateAndInsert(sal_Bool)
{
    // (code almost the same as export...)

    // insert and block mode is handled in insertStyleFamily

    // first: get field master
    // (we'll create one, and get the only master for this type)
    Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),UNO_QUERY);
    if( xFactory.is() )
    {
        Sequence<rtl::OUString> aServices = xFactory->getAvailableServiceNames();
        sal_Bool bFound(sal_False);
        sal_Int32 i(0);
        sal_Int32 nServiceCount(aServices.getLength());
        while (i < nServiceCount && !bFound)
        {
            if (aServices[i].equals(sFieldMaster_Bibliography))
            // here we should use a methode which compares in reverse order if available
            // #85282#
                bFound = sal_True;
            else
                i++;
        }
        if (bFound)
        {
            Reference<XInterface> xIfc =
                xFactory->createInstance(sFieldMaster_Bibliography);
            if( xIfc.is() )
            {
                Reference<XPropertySet> xPropSet( xIfc, UNO_QUERY );
                Any aAny;

                aAny <<= sSuffix;
                xPropSet->setPropertyValue(sBracketAfter, aAny);

                aAny <<= sPrefix;
                xPropSet->setPropertyValue(sBracketBefore, aAny);

                aAny.setValue(&bNumberedEntries, ::getBooleanCppuType());
                xPropSet->setPropertyValue(sIsNumberEntries, aAny);

                aAny.setValue(&bSortByPosition, ::getBooleanCppuType());
                xPropSet->setPropertyValue(sIsSortByPosition, aAny);

                if( (aLocale.Language.getLength() > 0) &&
                    (aLocale.Country.getLength() > 0)     )
                {
                    aAny <<= aLocale;
                    xPropSet->setPropertyValue(sLocale, aAny);
                }

                if( sAlgorithm.getLength() > 0 )
                {
                    aAny <<= sAlgorithm;
                    xPropSet->setPropertyValue(sSortAlgorithm, aAny);
                }

                sal_Int32 nCount = aSortKeys.size();
                Sequence<Sequence<PropertyValue> > aKeysSeq(nCount);
                for(i = 0; i < nCount; i++)
                {
                    aKeysSeq[i] = aSortKeys[i];
                }
                aAny <<= aKeysSeq;
                xPropSet->setPropertyValue(sSortKeys, aAny);
            }
            // else: can't get FieldMaster -> ignore
        }
    }
    // else: can't even get Factory -> ignore
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.10.34); FILE MERGED 2006/09/01 18:00:01 kaib 1.10.34.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLIndexBibliographyConfigurationContext.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 11:05:00 $
 *
 *  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
 *
 ************************************************************************/

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

#ifndef _XMLOFF_XMLINDEXBIBLIOGRAPHYCONFIGURATIONCONTEXT_HXX_
#include "XMLIndexBibliographyConfigurationContext.hxx"
#endif

#ifndef _XMLOFF_XMLINDEXBIBLIOGRAPHYENTRYCONTEXT_HXX_
#include "XMLIndexBibliographyEntryContext.hxx"
#endif

#ifndef _XMLOFF_XMLICTXT_HXX
#include "xmlictxt.hxx"
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif

#ifndef _XMLOFF_TEXTIMP_HXX_
#include "txtimp.hxx"
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

using namespace ::com::sun::star::text;
using namespace ::com::sun::star::uno;
using namespace ::xmloff::token;

using ::rtl::OUString;
using ::com::sun::star::xml::sax::XAttributeList;
using ::com::sun::star::beans::PropertyValue;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::lang::XMultiServiceFactory;

const sal_Char sAPI_FieldMaster_Bibliography[] =
                                "com.sun.star.text.FieldMaster.Bibliography";

TYPEINIT1( XMLIndexBibliographyConfigurationContext, SvXMLStyleContext );

XMLIndexBibliographyConfigurationContext::XMLIndexBibliographyConfigurationContext(
    SvXMLImport& rImport,
    sal_uInt16 nPrfx,
    const OUString& rLocalName,
    const Reference<XAttributeList> & xAttrList) :
        SvXMLStyleContext(rImport, nPrfx, rLocalName, xAttrList, XML_STYLE_FAMILY_TEXT_BIBLIOGRAPHYCONFIG),
        sFieldMaster_Bibliography(
            RTL_CONSTASCII_USTRINGPARAM(sAPI_FieldMaster_Bibliography)),
        sBracketBefore(RTL_CONSTASCII_USTRINGPARAM("BracketBefore")),
        sBracketAfter(RTL_CONSTASCII_USTRINGPARAM("BracketAfter")),
        sIsNumberEntries(RTL_CONSTASCII_USTRINGPARAM("IsNumberEntries")),
        sIsSortByPosition(RTL_CONSTASCII_USTRINGPARAM("IsSortByPosition")),
        sSortKeys(RTL_CONSTASCII_USTRINGPARAM("SortKeys")),
        sSortKey(RTL_CONSTASCII_USTRINGPARAM("SortKey")),
        sIsSortAscending(RTL_CONSTASCII_USTRINGPARAM("IsSortAscending")),
        sSortAlgorithm(RTL_CONSTASCII_USTRINGPARAM("SortAlgorithm")),
        sLocale(RTL_CONSTASCII_USTRINGPARAM("Locale")),
        sSuffix(),
        sPrefix(),
        sAlgorithm(),
        aLocale(),
        bNumberedEntries(sal_False),
        bSortByPosition(sal_True)
{
}

XMLIndexBibliographyConfigurationContext::~XMLIndexBibliographyConfigurationContext()
{
}

void XMLIndexBibliographyConfigurationContext::StartElement(
    const Reference<XAttributeList> & xAttrList)
{
    sal_Int16 nLength = xAttrList->getLength();
    for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
    {
        OUString sLocalName;
        sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
            GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
                              &sLocalName );

        ProcessAttribute(nPrefix, sLocalName,
                         xAttrList->getValueByIndex(nAttr));
        // else: ignore
    }
}

void XMLIndexBibliographyConfigurationContext::ProcessAttribute(
    sal_uInt16 nPrefix,
    OUString sLocalName,
    OUString sValue)
{
    if( XML_NAMESPACE_TEXT == nPrefix )
    {
        if( IsXMLToken(sLocalName, XML_PREFIX) )
        {
            sPrefix = sValue;
        }
        else if( IsXMLToken(sLocalName, XML_SUFFIX) )
        {
            sSuffix = sValue;
        }
        else if( IsXMLToken(sLocalName, XML_NUMBERED_ENTRIES) )
        {
            sal_Bool bTmp;
            if( SvXMLUnitConverter::convertBool(bTmp, sValue) )
            {
                bNumberedEntries = bTmp;
            }
        }
        else if( IsXMLToken(sLocalName, XML_SORT_BY_POSITION) )
        {
            sal_Bool bTmp;
            if (SvXMLUnitConverter::convertBool(bTmp, sValue))
            {
                bSortByPosition = bTmp;
            }
        }
        else if( IsXMLToken(sLocalName, XML_SORT_ALGORITHM) )
        {
            sAlgorithm = sValue;
        }
    }
    else if( XML_NAMESPACE_FO == nPrefix )
    {
        if( IsXMLToken(sLocalName, XML_LANGUAGE) )
        {
            aLocale.Language = sValue;
        }
        else if( IsXMLToken(sLocalName, XML_COUNTRY) )
        {
            aLocale.Country = sValue;
        }
    }
}

SvXMLImportContext *XMLIndexBibliographyConfigurationContext::CreateChildContext(
    sal_uInt16 nPrefix,
    const OUString& rLocalName,
    const Reference<XAttributeList> & xAttrList )
{
    OUString sKey;
    sal_Bool bSort(sal_True);

    // process children here and use default context!
    if ( ( nPrefix == XML_NAMESPACE_TEXT ) &&
         IsXMLToken( rLocalName, XML_SORT_KEY ) )
    {
        sal_Int16 nLength = xAttrList->getLength();
        for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
        {
            OUString sLocalName;
            sal_uInt16 nPrfx = GetImport().GetNamespaceMap().
                GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
                                  &sLocalName );

            if (nPrfx == XML_NAMESPACE_TEXT)
            {
                if ( IsXMLToken( sLocalName, XML_KEY ) )
                {
                    sKey = xAttrList->getValueByIndex(nAttr);
                }
                else if ( IsXMLToken( sLocalName, XML_SORT_ASCENDING ) )
                {
                    sal_Bool bTmp;
                    if (SvXMLUnitConverter::convertBool(
                        bTmp, xAttrList->getValueByIndex(nAttr)))
                    {
                        bSort = bTmp;
                    }
                }
            }
        }

        // valid data?
        sal_uInt16 nKey;
        if (SvXMLUnitConverter::convertEnum(nKey, sKey,
                                            aBibliographyDataFieldMap))
        {

            Any aAny;
            Sequence<PropertyValue> aKey(2);

            PropertyValue aNameValue;
            aNameValue.Name = sSortKey;
            aAny <<= (sal_Int16)nKey;
            aNameValue.Value = aAny;
            aKey[0] = aNameValue;

            PropertyValue aSortValue;
            aSortValue.Name = sIsSortAscending;
            aAny.setValue(&bSort, ::getBooleanCppuType());
            aSortValue.Value = aAny;
            aKey[1] = aSortValue;

            aSortKeys.push_back(aKey);
        }
    }

    return SvXMLImportContext::CreateChildContext(nPrefix, rLocalName,
                                                  xAttrList);
}

void XMLIndexBibliographyConfigurationContext::CreateAndInsert(sal_Bool)
{
    // (code almost the same as export...)

    // insert and block mode is handled in insertStyleFamily

    // first: get field master
    // (we'll create one, and get the only master for this type)
    Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),UNO_QUERY);
    if( xFactory.is() )
    {
        Sequence<rtl::OUString> aServices = xFactory->getAvailableServiceNames();
        sal_Bool bFound(sal_False);
        sal_Int32 i(0);
        sal_Int32 nServiceCount(aServices.getLength());
        while (i < nServiceCount && !bFound)
        {
            if (aServices[i].equals(sFieldMaster_Bibliography))
            // here we should use a methode which compares in reverse order if available
            // #85282#
                bFound = sal_True;
            else
                i++;
        }
        if (bFound)
        {
            Reference<XInterface> xIfc =
                xFactory->createInstance(sFieldMaster_Bibliography);
            if( xIfc.is() )
            {
                Reference<XPropertySet> xPropSet( xIfc, UNO_QUERY );
                Any aAny;

                aAny <<= sSuffix;
                xPropSet->setPropertyValue(sBracketAfter, aAny);

                aAny <<= sPrefix;
                xPropSet->setPropertyValue(sBracketBefore, aAny);

                aAny.setValue(&bNumberedEntries, ::getBooleanCppuType());
                xPropSet->setPropertyValue(sIsNumberEntries, aAny);

                aAny.setValue(&bSortByPosition, ::getBooleanCppuType());
                xPropSet->setPropertyValue(sIsSortByPosition, aAny);

                if( (aLocale.Language.getLength() > 0) &&
                    (aLocale.Country.getLength() > 0)     )
                {
                    aAny <<= aLocale;
                    xPropSet->setPropertyValue(sLocale, aAny);
                }

                if( sAlgorithm.getLength() > 0 )
                {
                    aAny <<= sAlgorithm;
                    xPropSet->setPropertyValue(sSortAlgorithm, aAny);
                }

                sal_Int32 nCount = aSortKeys.size();
                Sequence<Sequence<PropertyValue> > aKeysSeq(nCount);
                for(i = 0; i < nCount; i++)
                {
                    aKeysSeq[i] = aSortKeys[i];
                }
                aAny <<= aKeysSeq;
                xPropSet->setPropertyValue(sSortKeys, aAny);
            }
            // else: can't get FieldMaster -> ignore
        }
    }
    // else: can't even get Factory -> ignore
}
<|endoftext|>


<commit_before>//===-- ubsan_type_hash.cc ------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implementation of a hash table for fast checking of inheritance
// relationships. This file is only linked into C++ compilations, and is
// permitted to use language features which require a C++ ABI library.
//
//===----------------------------------------------------------------------===//

#include "ubsan_type_hash.h"

#include "sanitizer_common/sanitizer_common.h"

// The following are intended to be binary compatible with the definitions
// given in the Itanium ABI. We make no attempt to be ODR-compatible with
// those definitions, since existing ABI implementations aren't.

namespace std {
  class type_info {
  public:
    virtual ~type_info();

    const char *__type_name;
  };
}

namespace __cxxabiv1 {

/// Type info for classes with no bases, and base class for type info for
/// classes with bases.
class __class_type_info : public std::type_info {
  virtual ~__class_type_info();
};

/// Type info for classes with simple single public inheritance.
class __si_class_type_info : public __class_type_info {
public:
  virtual ~__si_class_type_info();

  const __class_type_info *__base_type;
};

class __base_class_type_info {
public:
  const __class_type_info *__base_type;
  long __offset_flags;

  enum __offset_flags_masks {
    __virtual_mask = 0x1,
    __public_mask = 0x2,
    __offset_shift = 8
  };
};

/// Type info for classes with multiple, virtual, or non-public inheritance.
class __vmi_class_type_info : public __class_type_info {
public:
  virtual ~__vmi_class_type_info();

  unsigned int flags;
  unsigned int base_count;
  __base_class_type_info base_info[1];
};

}

namespace abi = __cxxabiv1;

// We implement a simple two-level cache for type-checking results. For each
// (vptr,type) pair, a hash is computed. This hash is assumed to be globally
// unique; if it collides, we will get false negatives, but:
//  * such a collision would have to occur on the *first* bad access,
//  * the probability of such a collision is low (and for a 64-bit target, is
//    negligible), and
//  * the vptr, and thus the hash, can be affected by ASLR, so multiple runs
//    give better coverage.
//
// The first caching layer is a small hash table with no chaining; buckets are
// reused as needed. The second caching layer is a large hash table with open
// chaining. We can freely evict from either layer since this is just a cache.
//
// FIXME: Make these hash table accesses thread-safe. The races here are benign
//        (worst-case, we could miss a bug or see a slowdown) but we should
//        avoid upsetting race detectors.

/// Find a bucket to store the given hash value in.
static __ubsan::HashValue *getTypeCacheHashTableBucket(__ubsan::HashValue V) {
  static const unsigned HashTableSize = 65537;
  static __ubsan::HashValue __ubsan_vptr_hash_set[HashTableSize] = { 1 };

  unsigned Probe = V & 65535;
  for (int Tries = 5; Tries; --Tries) {
    if (!__ubsan_vptr_hash_set[Probe] || __ubsan_vptr_hash_set[Probe] == V)
      return &__ubsan_vptr_hash_set[Probe];
    Probe += ((V >> 16) & 65535) + 1;
    if (Probe >= HashTableSize)
      Probe -= HashTableSize;
  }
  // FIXME: Pick a random entry from the probe sequence to evict rather than
  //        just taking the first.
  return &__ubsan_vptr_hash_set[V];
}

/// A cache of recently-checked hashes. Mini hash table with "random" evictions.
__ubsan::HashValue
__ubsan::__ubsan_vptr_type_cache[__ubsan::VptrTypeCacheSize] = { 1 };

/// \brief Determine whether \p Derived has a \p Base base class subobject at
/// offset \p Offset.
static bool isDerivedFromAtOffset(const abi::__class_type_info *Derived,
                                  const abi::__class_type_info *Base,
                                  sptr Offset) {
  if (Derived->__type_name == Base->__type_name)
    return Offset == 0;

  if (const abi::__si_class_type_info *SI =
        dynamic_cast<const abi::__si_class_type_info*>(Derived))
    return isDerivedFromAtOffset(SI->__base_type, Base, Offset);

  const abi::__vmi_class_type_info *VTI =
    dynamic_cast<const abi::__vmi_class_type_info*>(Derived);
  if (!VTI)
    // No base class subobjects.
    return false;

  // Look for a base class which is derived from \p Base at the right offset.
  for (unsigned int base = 0; base != VTI->base_count; ++base) {
    // FIXME: Curtail the recursion if this base can't possibly contain the
    //        given offset.
    sptr OffsetHere = VTI->base_info[base].__offset_flags >>
                      abi::__base_class_type_info::__offset_shift;
    if (VTI->base_info[base].__offset_flags &
          abi::__base_class_type_info::__virtual_mask)
      // For now, just punt on virtual bases and say 'yes'.
      // FIXME: OffsetHere is the offset in the vtable of the virtual base
      //        offset. Read the vbase offset out of the vtable and use it.
      return true;
    if (isDerivedFromAtOffset(VTI->base_info[base].__base_type,
                              Base, Offset - OffsetHere))
      return true;
  }

  return false;
}

/// \brief Find the derived-most dynamic base class of \p Derived at offset
/// \p Offset.
static const abi::__class_type_info *findBaseAtOffset(
    const abi::__class_type_info *Derived, sptr Offset) {
  if (!Offset)
    return Derived;

  if (const abi::__si_class_type_info *SI =
        dynamic_cast<const abi::__si_class_type_info*>(Derived))
    return findBaseAtOffset(SI->__base_type, Offset);

  const abi::__vmi_class_type_info *VTI =
    dynamic_cast<const abi::__vmi_class_type_info*>(Derived);
  if (!VTI)
    // No base class subobjects.
    return 0;

  for (unsigned int base = 0; base != VTI->base_count; ++base) {
    sptr OffsetHere = VTI->base_info[base].__offset_flags >>
                      abi::__base_class_type_info::__offset_shift;
    if (VTI->base_info[base].__offset_flags &
          abi::__base_class_type_info::__virtual_mask)
      // FIXME: Can't handle virtual bases yet.
      continue;
    if (const abi::__class_type_info *Base =
          findBaseAtOffset(VTI->base_info[base].__base_type,
                           Offset - OffsetHere))
      return Base;
  }

  return 0;
}

namespace {

struct VtablePrefix {
  /// The offset from the vptr to the start of the most-derived object.
  /// This should never be greater than zero, and will usually be exactly
  /// zero.
  sptr Offset;
  /// The type_info object describing the most-derived class type.
  std::type_info *TypeInfo;
};
VtablePrefix *getVtablePrefix(void *Object) {
  VtablePrefix **VptrPtr = reinterpret_cast<VtablePrefix**>(Object);
  if (!*VptrPtr)
    return 0;
  VtablePrefix *Prefix = *VptrPtr - 1;
  if (Prefix->Offset > 0 || !Prefix->TypeInfo)
    // This can't possibly be a valid vtable.
    return 0;
  return Prefix;
}

}

bool __ubsan::checkDynamicType(void *Object, void *Type, HashValue Hash) {
  // A crash anywhere within this function probably means the vptr is corrupted.
  // FIXME: Perform these checks more cautiously.

  // Check whether this is something we've evicted from the cache.
  HashValue *Bucket = getTypeCacheHashTableBucket(Hash);
  if (*Bucket == Hash) {
    __ubsan_vptr_type_cache[Hash % VptrTypeCacheSize] = Hash;
    return true;
  }

  VtablePrefix *Vtable = getVtablePrefix(Object);
  if (!Vtable)
    return false;

  // Check that this is actually a type_info object for a class type.
  abi::__class_type_info *Derived =
    dynamic_cast<abi::__class_type_info*>(Vtable->TypeInfo);
  if (!Derived)
    return false;

  abi::__class_type_info *Base = (abi::__class_type_info*)Type;
  if (!isDerivedFromAtOffset(Derived, Base, -Vtable->Offset))
    return false;

  // Success. Cache this result.
  __ubsan_vptr_type_cache[Hash % VptrTypeCacheSize] = Hash;
  *Bucket = Hash;
  return true;
}

__ubsan::DynamicTypeInfo __ubsan::getDynamicTypeInfo(void *Object) {
  VtablePrefix *Vtable = getVtablePrefix(Object);
  if (!Vtable)
    return DynamicTypeInfo(0, 0, 0);
  const abi::__class_type_info *ObjectType = findBaseAtOffset(
    static_cast<const abi::__class_type_info*>(Vtable->TypeInfo),
    -Vtable->Offset);
  return DynamicTypeInfo(Vtable->TypeInfo->__type_name, -Vtable->Offset,
                         ObjectType ? ObjectType->__type_name : "<unknown>");
}
<commit_msg>Make the big array in the UBSan C++ runtime be zero-initialized to dramatically shrink the binary size of the ubsan runtime.<commit_after>//===-- ubsan_type_hash.cc ------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implementation of a hash table for fast checking of inheritance
// relationships. This file is only linked into C++ compilations, and is
// permitted to use language features which require a C++ ABI library.
//
//===----------------------------------------------------------------------===//

#include "ubsan_type_hash.h"

#include "sanitizer_common/sanitizer_common.h"

// The following are intended to be binary compatible with the definitions
// given in the Itanium ABI. We make no attempt to be ODR-compatible with
// those definitions, since existing ABI implementations aren't.

namespace std {
  class type_info {
  public:
    virtual ~type_info();

    const char *__type_name;
  };
}

namespace __cxxabiv1 {

/// Type info for classes with no bases, and base class for type info for
/// classes with bases.
class __class_type_info : public std::type_info {
  virtual ~__class_type_info();
};

/// Type info for classes with simple single public inheritance.
class __si_class_type_info : public __class_type_info {
public:
  virtual ~__si_class_type_info();

  const __class_type_info *__base_type;
};

class __base_class_type_info {
public:
  const __class_type_info *__base_type;
  long __offset_flags;

  enum __offset_flags_masks {
    __virtual_mask = 0x1,
    __public_mask = 0x2,
    __offset_shift = 8
  };
};

/// Type info for classes with multiple, virtual, or non-public inheritance.
class __vmi_class_type_info : public __class_type_info {
public:
  virtual ~__vmi_class_type_info();

  unsigned int flags;
  unsigned int base_count;
  __base_class_type_info base_info[1];
};

}

namespace abi = __cxxabiv1;

// We implement a simple two-level cache for type-checking results. For each
// (vptr,type) pair, a hash is computed. This hash is assumed to be globally
// unique; if it collides, we will get false negatives, but:
//  * such a collision would have to occur on the *first* bad access,
//  * the probability of such a collision is low (and for a 64-bit target, is
//    negligible), and
//  * the vptr, and thus the hash, can be affected by ASLR, so multiple runs
//    give better coverage.
//
// The first caching layer is a small hash table with no chaining; buckets are
// reused as needed. The second caching layer is a large hash table with open
// chaining. We can freely evict from either layer since this is just a cache.
//
// FIXME: Make these hash table accesses thread-safe. The races here are benign:
//        assuming the unsequenced loads and stores don't misbehave too badly,
//        the worst case is false negatives or poor cache behavior, not false
//        positives or crashes.

/// Find a bucket to store the given hash value in.
static __ubsan::HashValue *getTypeCacheHashTableBucket(__ubsan::HashValue V) {
  static const unsigned HashTableSize = 65537;
  static __ubsan::HashValue __ubsan_vptr_hash_set[HashTableSize];

  unsigned First = (V & 65535) ^ 1;
  unsigned Probe = First;
  for (int Tries = 5; Tries; --Tries) {
    if (!__ubsan_vptr_hash_set[Probe] || __ubsan_vptr_hash_set[Probe] == V)
      return &__ubsan_vptr_hash_set[Probe];
    Probe += ((V >> 16) & 65535) + 1;
    if (Probe >= HashTableSize)
      Probe -= HashTableSize;
  }
  // FIXME: Pick a random entry from the probe sequence to evict rather than
  //        just taking the first.
  return &__ubsan_vptr_hash_set[First];
}

/// A cache of recently-checked hashes. Mini hash table with "random" evictions.
__ubsan::HashValue
__ubsan::__ubsan_vptr_type_cache[__ubsan::VptrTypeCacheSize];

/// \brief Determine whether \p Derived has a \p Base base class subobject at
/// offset \p Offset.
static bool isDerivedFromAtOffset(const abi::__class_type_info *Derived,
                                  const abi::__class_type_info *Base,
                                  sptr Offset) {
  if (Derived->__type_name == Base->__type_name)
    return Offset == 0;

  if (const abi::__si_class_type_info *SI =
        dynamic_cast<const abi::__si_class_type_info*>(Derived))
    return isDerivedFromAtOffset(SI->__base_type, Base, Offset);

  const abi::__vmi_class_type_info *VTI =
    dynamic_cast<const abi::__vmi_class_type_info*>(Derived);
  if (!VTI)
    // No base class subobjects.
    return false;

  // Look for a base class which is derived from \p Base at the right offset.
  for (unsigned int base = 0; base != VTI->base_count; ++base) {
    // FIXME: Curtail the recursion if this base can't possibly contain the
    //        given offset.
    sptr OffsetHere = VTI->base_info[base].__offset_flags >>
                      abi::__base_class_type_info::__offset_shift;
    if (VTI->base_info[base].__offset_flags &
          abi::__base_class_type_info::__virtual_mask)
      // For now, just punt on virtual bases and say 'yes'.
      // FIXME: OffsetHere is the offset in the vtable of the virtual base
      //        offset. Read the vbase offset out of the vtable and use it.
      return true;
    if (isDerivedFromAtOffset(VTI->base_info[base].__base_type,
                              Base, Offset - OffsetHere))
      return true;
  }

  return false;
}

/// \brief Find the derived-most dynamic base class of \p Derived at offset
/// \p Offset.
static const abi::__class_type_info *findBaseAtOffset(
    const abi::__class_type_info *Derived, sptr Offset) {
  if (!Offset)
    return Derived;

  if (const abi::__si_class_type_info *SI =
        dynamic_cast<const abi::__si_class_type_info*>(Derived))
    return findBaseAtOffset(SI->__base_type, Offset);

  const abi::__vmi_class_type_info *VTI =
    dynamic_cast<const abi::__vmi_class_type_info*>(Derived);
  if (!VTI)
    // No base class subobjects.
    return 0;

  for (unsigned int base = 0; base != VTI->base_count; ++base) {
    sptr OffsetHere = VTI->base_info[base].__offset_flags >>
                      abi::__base_class_type_info::__offset_shift;
    if (VTI->base_info[base].__offset_flags &
          abi::__base_class_type_info::__virtual_mask)
      // FIXME: Can't handle virtual bases yet.
      continue;
    if (const abi::__class_type_info *Base =
          findBaseAtOffset(VTI->base_info[base].__base_type,
                           Offset - OffsetHere))
      return Base;
  }

  return 0;
}

namespace {

struct VtablePrefix {
  /// The offset from the vptr to the start of the most-derived object.
  /// This should never be greater than zero, and will usually be exactly
  /// zero.
  sptr Offset;
  /// The type_info object describing the most-derived class type.
  std::type_info *TypeInfo;
};
VtablePrefix *getVtablePrefix(void *Object) {
  VtablePrefix **VptrPtr = reinterpret_cast<VtablePrefix**>(Object);
  if (!*VptrPtr)
    return 0;
  VtablePrefix *Prefix = *VptrPtr - 1;
  if (Prefix->Offset > 0 || !Prefix->TypeInfo)
    // This can't possibly be a valid vtable.
    return 0;
  return Prefix;
}

}

bool __ubsan::checkDynamicType(void *Object, void *Type, HashValue Hash) {
  // A crash anywhere within this function probably means the vptr is corrupted.
  // FIXME: Perform these checks more cautiously.

  // Check whether this is something we've evicted from the cache.
  HashValue *Bucket = getTypeCacheHashTableBucket(Hash);
  if (*Bucket == Hash) {
    __ubsan_vptr_type_cache[Hash % VptrTypeCacheSize] = Hash;
    return true;
  }

  VtablePrefix *Vtable = getVtablePrefix(Object);
  if (!Vtable)
    return false;

  // Check that this is actually a type_info object for a class type.
  abi::__class_type_info *Derived =
    dynamic_cast<abi::__class_type_info*>(Vtable->TypeInfo);
  if (!Derived)
    return false;

  abi::__class_type_info *Base = (abi::__class_type_info*)Type;
  if (!isDerivedFromAtOffset(Derived, Base, -Vtable->Offset))
    return false;

  // Success. Cache this result.
  __ubsan_vptr_type_cache[Hash % VptrTypeCacheSize] = Hash;
  *Bucket = Hash;
  return true;
}

__ubsan::DynamicTypeInfo __ubsan::getDynamicTypeInfo(void *Object) {
  VtablePrefix *Vtable = getVtablePrefix(Object);
  if (!Vtable)
    return DynamicTypeInfo(0, 0, 0);
  const abi::__class_type_info *ObjectType = findBaseAtOffset(
    static_cast<const abi::__class_type_info*>(Vtable->TypeInfo),
    -Vtable->Offset);
  return DynamicTypeInfo(Vtable->TypeInfo->__type_name, -Vtable->Offset,
                         ObjectType ? ObjectType->__type_name : "<unknown>");
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file EthereumPeer.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "EthereumPeer.h"

#include <chrono>
#include <libdevcore/Common.h>
#include <libethcore/Exceptions.h>
#include <libp2p/Session.h>
#include "BlockChain.h"
#include "EthereumHost.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace p2p;

#define clogS(X) dev::LogOutputStream<X, true>(false) << "| " << std::setw(2) << session()->socketId() << "] "

EthereumPeer::EthereumPeer(Session* _s, HostCapabilityFace* _h):
	Capability(_s, _h),
	m_sub(host()->m_man)
{
	sendStatus();
}

EthereumPeer::~EthereumPeer()
{
	giveUpOnFetch();
}

EthereumHost* EthereumPeer::host() const
{
	return static_cast<EthereumHost*>(Capability::hostCapability());
}

void EthereumPeer::sendStatus()
{
	RLPStream s;
	prep(s);
	s.appendList(6) << StatusPacket
					<< host()->protocolVersion()
					<< host()->networkId()
					<< host()->m_chain.details().totalDifficulty
					<< host()->m_chain.currentHash()
					<< host()->m_chain.genesisHash();
	sealAndSend(s);
}

void EthereumPeer::startInitialSync()
{
	// Grab transactions off them.
	{
		RLPStream s;
		prep(s).appendList(1);
		s << GetTransactionsPacket;
		sealAndSend(s);
	}

	host()->noteHavePeerState(this);
}

void EthereumPeer::tryGrabbingHashChain()
{
	// if already done this, then ignore.
	if (m_grabbing != Grabbing::State)
	{
		clogS(NetAllDetail) << "Already synced with this peer.";
		return;
	}

	h256 c = host()->m_chain.currentHash();
	unsigned n = host()->m_chain.number();
	u256 td = host()->m_chain.details().totalDifficulty;

	clogS(NetAllDetail) << "Attempt chain-grab? Latest:" << c.abridged() << ", number:" << n << ", TD:" << td << " versus " << m_totalDifficulty;
	if (td >= m_totalDifficulty)
	{
		clogS(NetAllDetail) << "No. Our chain is better.";
		m_grabbing = Grabbing::Nothing;
		return;	// All good - we have the better chain.
	}

	// Our chain isn't better - grab theirs.
	{
		clogS(NetAllDetail) << "Yes. Their chain is better.";

		host()->updateGrabbing(Grabbing::Hashes);
		m_grabbing = Grabbing::Hashes;
		RLPStream s;
		prep(s).appendList(3);
		s << GetBlockHashesPacket << m_latestHash << c_maxHashesAsk;
		m_neededBlocks = h256s(1, m_latestHash);
		sealAndSend(s);
	}
}

void EthereumPeer::giveUpOnFetch()
{
	clogS(NetNote) << "GIVE UP FETCH";

	// a bit overkill given that the other nodes may yet have the needed blocks, but better to be safe than sorry.
	if (m_grabbing == Grabbing::Chain || m_grabbing == Grabbing::ChainHelper)
	{
		host()->noteDoneBlocks(this);
		m_grabbing = Grabbing::Nothing;
	}

	m_sub.doneFetch();
	// NOTE: need to notify of giving up on chain-hashes, too, altering state as necessary.
}

bool EthereumPeer::interpret(RLP const& _r)
{
	switch (_r[0].toInt<unsigned>())
	{
	case StatusPacket:
	{
		m_protocolVersion = _r[1].toInt<unsigned>();
		m_networkId = _r[2].toInt<u256>();
		m_totalDifficulty = _r[3].toInt<u256>();
		m_latestHash = _r[4].toHash<h256>();
		auto genesisHash = _r[5].toHash<h256>();

		clogS(NetMessageSummary) << "Status:" << m_protocolVersion << "/" << m_networkId << "/" << genesisHash.abridged() << ", TD:" << m_totalDifficulty << "=" << m_latestHash.abridged();

		if (genesisHash != host()->m_chain.genesisHash())
			disable("Invalid genesis hash");
		if (m_protocolVersion != host()->protocolVersion())
			disable("Invalid protocol version.");
		if (m_networkId != host()->networkId())
			disable("Invalid network identifier.");

		startInitialSync();
		break;
	}
	case GetTransactionsPacket:
	{
		m_requireTransactions = true;
		break;
	}
	case TransactionsPacket:
	{
		clogS(NetMessageSummary) << "Transactions (" << dec << (_r.itemCount() - 1) << "entries)";
		addRating(_r.itemCount() - 1);
		lock_guard<recursive_mutex> l(host()->m_incomingLock);
		for (unsigned i = 1; i < _r.itemCount(); ++i)
		{
			host()->addIncomingTransaction(_r[i].data().toBytes());

			lock_guard<mutex> l(x_knownTransactions);
			m_knownTransactions.insert(sha3(_r[i].data()));
		}
		break;
	}
	case GetBlockHashesPacket:
	{
		h256 later = _r[1].toHash<h256>();
		unsigned limit = _r[2].toInt<unsigned>();
		clogS(NetMessageSummary) << "GetBlockHashes (" << limit << "entries," << later.abridged() << ")";

		unsigned c = min<unsigned>(max<unsigned>(1, host()->m_chain.number(later)) - 1, limit);

		RLPStream s;
		prep(s).appendList(1 + c).append(BlockHashesPacket);
		h256 p = host()->m_chain.details(later).parent;
		for (unsigned i = 0; i < c; ++i, p = host()->m_chain.details(p).parent)
			s << p;
		sealAndSend(s);
		break;
	}
	case BlockHashesPacket:
	{
		clogS(NetMessageSummary) << "BlockHashes (" << dec << (_r.itemCount() - 1) << "entries)" << (_r.itemCount() - 1 ? "" : ": NoMoreHashes");

		if (m_grabbing != Grabbing::Hashes)
		{
			cwarn << "Peer giving us hashes when we didn't ask for them.";
			break;
		}
		if (_r.itemCount() == 1)
		{
			host()->noteHaveChain(this);
			return true;
		}
		for (unsigned i = 1; i < _r.itemCount(); ++i)
		{
			auto h = _r[i].toHash<h256>();
			if (host()->m_chain.details(h))
			{
				host()->noteHaveChain(this);
				return true;
			}
			else
				m_neededBlocks.push_back(h);
		}
		// run through - ask for more.
		RLPStream s;
		prep(s).appendList(3);
		s << GetBlockHashesPacket << m_neededBlocks.back() << c_maxHashesAsk;
		sealAndSend(s);
		break;
	}
	case GetBlocksPacket:
	{
		clogS(NetMessageSummary) << "GetBlocks (" << dec << (_r.itemCount() - 1) << "entries)";
		// return the requested blocks.
		bytes rlp;
		unsigned n = 0;
		for (unsigned i = 1; i < _r.itemCount() && i <= c_maxBlocks; ++i)
		{
			auto b = host()->m_chain.block(_r[i].toHash<h256>());
			if (b.size())
			{
				rlp += b;
				++n;
			}
		}
		RLPStream s;
		sealAndSend(prep(s).appendList(n + 1).append(BlocksPacket).appendRaw(rlp, n));
		break;
	}
	case BlocksPacket:
	{
		clogS(NetMessageSummary) << "Blocks (" << dec << (_r.itemCount() - 1) << "entries)" << (_r.itemCount() - 1 ? "" : ": NoMoreBlocks");

		if (_r.itemCount() == 1)
		{
			// Couldn't get any from last batch - probably got to this peer's latest block - just give up.
			m_sub.doneFetch();
			giveUpOnFetch();
		}

		unsigned used = 0;
		for (unsigned i = 1; i < _r.itemCount(); ++i)
		{
			auto h = BlockInfo::headerHash(_r[i].data());
			m_sub.noteBlock(h);
			if (host()->noteBlock(h, _r[i].data()))
				used++;
			Guard l(x_knownBlocks);
			m_knownBlocks.insert(h);
		}
		addRating(used);
		unsigned knownParents = 0;
		unsigned unknownParents = 0;
		if (g_logVerbosity >= NetMessageSummary::verbosity)
		{
			for (unsigned i = 1; i < _r.itemCount(); ++i)
			{
				auto h = BlockInfo::headerHash(_r[i].data());
				BlockInfo bi(_r[i].data());
				Guard l(x_knownBlocks);
				if (!host()->m_chain.details(bi.parentHash) && !m_knownBlocks.count(bi.parentHash))
				{
					unknownParents++;
					clogS(NetAllDetail) << "Unknown parent" << bi.parentHash.abridged() << "of block" << h.abridged();
				}
				else
				{
					knownParents++;
					clogS(NetAllDetail) << "Known parent" << bi.parentHash.abridged() << "of block" << h.abridged();
				}
			}
		}
		clogS(NetMessageSummary) << dec << knownParents << "known parents," << unknownParents << "unknown," << used << "used.";
		continueGettingChain();
		break;
	}
	default:
		return false;
	}
	return true;
}

void EthereumPeer::ensureGettingChain()
{
	if (m_grabbing == Grabbing::ChainHelper)
		return;	// Already asked & waiting for some.

	continueGettingChain();
}

void EthereumPeer::continueGettingChain()
{
	if (m_grabbing != Grabbing::Chain)
		m_grabbing = Grabbing::ChainHelper;

	auto blocks = m_sub.nextFetch(c_maxBlocksAsk);

	if (blocks.size())
	{
		RLPStream s;
		prep(s);
		s.appendList(blocks.size() + 1) << GetBlocksPacket;
		for (auto const& i: blocks)
			s << i;
		sealAndSend(s);
	}
	else
		giveUpOnFetch();
}
<commit_msg>Actually stop getting chain once no more to grab.<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file EthereumPeer.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "EthereumPeer.h"

#include <chrono>
#include <libdevcore/Common.h>
#include <libethcore/Exceptions.h>
#include <libp2p/Session.h>
#include "BlockChain.h"
#include "EthereumHost.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace p2p;

#define clogS(X) dev::LogOutputStream<X, true>(false) << "| " << std::setw(2) << session()->socketId() << "] "

EthereumPeer::EthereumPeer(Session* _s, HostCapabilityFace* _h):
	Capability(_s, _h),
	m_sub(host()->m_man)
{
	sendStatus();
}

EthereumPeer::~EthereumPeer()
{
	giveUpOnFetch();
}

EthereumHost* EthereumPeer::host() const
{
	return static_cast<EthereumHost*>(Capability::hostCapability());
}

void EthereumPeer::sendStatus()
{
	RLPStream s;
	prep(s);
	s.appendList(6) << StatusPacket
					<< host()->protocolVersion()
					<< host()->networkId()
					<< host()->m_chain.details().totalDifficulty
					<< host()->m_chain.currentHash()
					<< host()->m_chain.genesisHash();
	sealAndSend(s);
}

void EthereumPeer::startInitialSync()
{
	// Grab transactions off them.
	{
		RLPStream s;
		prep(s).appendList(1);
		s << GetTransactionsPacket;
		sealAndSend(s);
	}

	host()->noteHavePeerState(this);
}

void EthereumPeer::tryGrabbingHashChain()
{
	// if already done this, then ignore.
	if (m_grabbing != Grabbing::State)
	{
		clogS(NetAllDetail) << "Already synced with this peer.";
		return;
	}

	h256 c = host()->m_chain.currentHash();
	unsigned n = host()->m_chain.number();
	u256 td = host()->m_chain.details().totalDifficulty;

	clogS(NetAllDetail) << "Attempt chain-grab? Latest:" << c.abridged() << ", number:" << n << ", TD:" << td << " versus " << m_totalDifficulty;
	if (td >= m_totalDifficulty)
	{
		clogS(NetAllDetail) << "No. Our chain is better.";
		m_grabbing = Grabbing::Nothing;
		return;	// All good - we have the better chain.
	}

	// Our chain isn't better - grab theirs.
	{
		clogS(NetAllDetail) << "Yes. Their chain is better.";

		host()->updateGrabbing(Grabbing::Hashes);
		m_grabbing = Grabbing::Hashes;
		RLPStream s;
		prep(s).appendList(3);
		s << GetBlockHashesPacket << m_latestHash << c_maxHashesAsk;
		m_neededBlocks = h256s(1, m_latestHash);
		sealAndSend(s);
	}
}

void EthereumPeer::giveUpOnFetch()
{
	clogS(NetNote) << "GIVE UP FETCH";

	// a bit overkill given that the other nodes may yet have the needed blocks, but better to be safe than sorry.
	if (m_grabbing == Grabbing::Chain || m_grabbing == Grabbing::ChainHelper)
	{
		host()->noteDoneBlocks(this);
		m_grabbing = Grabbing::Nothing;
	}

	m_sub.doneFetch();
	// NOTE: need to notify of giving up on chain-hashes, too, altering state as necessary.
}

bool EthereumPeer::interpret(RLP const& _r)
{
	switch (_r[0].toInt<unsigned>())
	{
	case StatusPacket:
	{
		m_protocolVersion = _r[1].toInt<unsigned>();
		m_networkId = _r[2].toInt<u256>();
		m_totalDifficulty = _r[3].toInt<u256>();
		m_latestHash = _r[4].toHash<h256>();
		auto genesisHash = _r[5].toHash<h256>();

		clogS(NetMessageSummary) << "Status:" << m_protocolVersion << "/" << m_networkId << "/" << genesisHash.abridged() << ", TD:" << m_totalDifficulty << "=" << m_latestHash.abridged();

		if (genesisHash != host()->m_chain.genesisHash())
			disable("Invalid genesis hash");
		if (m_protocolVersion != host()->protocolVersion())
			disable("Invalid protocol version.");
		if (m_networkId != host()->networkId())
			disable("Invalid network identifier.");

		startInitialSync();
		break;
	}
	case GetTransactionsPacket:
	{
		m_requireTransactions = true;
		break;
	}
	case TransactionsPacket:
	{
		clogS(NetMessageSummary) << "Transactions (" << dec << (_r.itemCount() - 1) << "entries)";
		addRating(_r.itemCount() - 1);
		lock_guard<recursive_mutex> l(host()->m_incomingLock);
		for (unsigned i = 1; i < _r.itemCount(); ++i)
		{
			host()->addIncomingTransaction(_r[i].data().toBytes());

			lock_guard<mutex> l(x_knownTransactions);
			m_knownTransactions.insert(sha3(_r[i].data()));
		}
		break;
	}
	case GetBlockHashesPacket:
	{
		h256 later = _r[1].toHash<h256>();
		unsigned limit = _r[2].toInt<unsigned>();
		clogS(NetMessageSummary) << "GetBlockHashes (" << limit << "entries," << later.abridged() << ")";

		unsigned c = min<unsigned>(max<unsigned>(1, host()->m_chain.number(later)) - 1, limit);

		RLPStream s;
		prep(s).appendList(1 + c).append(BlockHashesPacket);
		h256 p = host()->m_chain.details(later).parent;
		for (unsigned i = 0; i < c; ++i, p = host()->m_chain.details(p).parent)
			s << p;
		sealAndSend(s);
		break;
	}
	case BlockHashesPacket:
	{
		clogS(NetMessageSummary) << "BlockHashes (" << dec << (_r.itemCount() - 1) << "entries)" << (_r.itemCount() - 1 ? "" : ": NoMoreHashes");

		if (m_grabbing != Grabbing::Hashes)
		{
			cwarn << "Peer giving us hashes when we didn't ask for them.";
			break;
		}
		if (_r.itemCount() == 1)
		{
			host()->noteHaveChain(this);
			return true;
		}
		for (unsigned i = 1; i < _r.itemCount(); ++i)
		{
			auto h = _r[i].toHash<h256>();
			if (host()->m_chain.details(h))
			{
				host()->noteHaveChain(this);
				return true;
			}
			else
				m_neededBlocks.push_back(h);
		}
		// run through - ask for more.
		RLPStream s;
		prep(s).appendList(3);
		s << GetBlockHashesPacket << m_neededBlocks.back() << c_maxHashesAsk;
		sealAndSend(s);
		break;
	}
	case GetBlocksPacket:
	{
		clogS(NetMessageSummary) << "GetBlocks (" << dec << (_r.itemCount() - 1) << "entries)";
		// return the requested blocks.
		bytes rlp;
		unsigned n = 0;
		for (unsigned i = 1; i < _r.itemCount() && i <= c_maxBlocks; ++i)
		{
			auto b = host()->m_chain.block(_r[i].toHash<h256>());
			if (b.size())
			{
				rlp += b;
				++n;
			}
		}
		RLPStream s;
		sealAndSend(prep(s).appendList(n + 1).append(BlocksPacket).appendRaw(rlp, n));
		break;
	}
	case BlocksPacket:
	{
		clogS(NetMessageSummary) << "Blocks (" << dec << (_r.itemCount() - 1) << "entries)" << (_r.itemCount() - 1 ? "" : ": NoMoreBlocks");

		if (_r.itemCount() == 1)
		{
			// Couldn't get any from last batch - probably got to this peer's latest block - just give up.
			m_sub.doneFetch();
			giveUpOnFetch();
			break;
		}

		unsigned used = 0;
		for (unsigned i = 1; i < _r.itemCount(); ++i)
		{
			auto h = BlockInfo::headerHash(_r[i].data());
			m_sub.noteBlock(h);
			if (host()->noteBlock(h, _r[i].data()))
				used++;
			Guard l(x_knownBlocks);
			m_knownBlocks.insert(h);
		}
		addRating(used);
		unsigned knownParents = 0;
		unsigned unknownParents = 0;
		if (g_logVerbosity >= NetMessageSummary::verbosity)
		{
			for (unsigned i = 1; i < _r.itemCount(); ++i)
			{
				auto h = BlockInfo::headerHash(_r[i].data());
				BlockInfo bi(_r[i].data());
				Guard l(x_knownBlocks);
				if (!host()->m_chain.details(bi.parentHash) && !m_knownBlocks.count(bi.parentHash))
				{
					unknownParents++;
					clogS(NetAllDetail) << "Unknown parent" << bi.parentHash.abridged() << "of block" << h.abridged();
				}
				else
				{
					knownParents++;
					clogS(NetAllDetail) << "Known parent" << bi.parentHash.abridged() << "of block" << h.abridged();
				}
			}
		}
		clogS(NetMessageSummary) << dec << knownParents << "known parents," << unknownParents << "unknown," << used << "used.";
		continueGettingChain();
		break;
	}
	default:
		return false;
	}
	return true;
}

void EthereumPeer::ensureGettingChain()
{
	if (m_grabbing == Grabbing::ChainHelper)
		return;	// Already asked & waiting for some.

	continueGettingChain();
}

void EthereumPeer::continueGettingChain()
{
	if (m_grabbing != Grabbing::Chain)
		m_grabbing = Grabbing::ChainHelper;

	auto blocks = m_sub.nextFetch(c_maxBlocksAsk);

	if (blocks.size())
	{
		RLPStream s;
		prep(s);
		s.appendList(blocks.size() + 1) << GetBlocksPacket;
		for (auto const& i: blocks)
			s << i;
		sealAndSend(s);
	}
	else
		giveUpOnFetch();
}
<|endoftext|>


<commit_before>/*
    kopeteprotocol.cpp - Kopete Protocol

    Copyright (c) 2002 by Duncan Mac-Vicar Prett <duncan@kde.org>
    Copyright (c) 2002 by Martijn Klingens       <klingens@kde.org>

    Kopete    (c) 2002 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "kopeteprotocol.h"
#include "kopetemetacontact.h"
#include "kopetecontact.h"
#include "kopete.h"

KopeteProtocol::KopeteProtocol(QObject *parent, const char *name)
    : Plugin( parent, name )
{
	m_canStream = false;
}

KopeteProtocol::~KopeteProtocol()
{
}

QString KopeteProtocol::icon() const
{
	return m_icon;
}

void KopeteProtocol::setIcon( const QString &icon )
{
	m_icon = icon;
}

// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>grmbl... save first, commit later :(<commit_after>/*
    kopeteprotocol.cpp - Kopete Protocol

    Copyright (c) 2002 by Duncan Mac-Vicar Prett <duncan@kde.org>
    Copyright (c) 2002 by Martijn Klingens       <klingens@kde.org>

    Kopete    (c) 2002 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "kopeteprotocol.h"
#include "kopetemetacontact.h"
#include "kopetecontact.h"
#include "kopete.h"

KopeteProtocol::KopeteProtocol(QObject *parent, const char *name)
    : Plugin( parent, name )
{
}

KopeteProtocol::~KopeteProtocol()
{
}

QString KopeteProtocol::icon() const
{
	return m_icon;
}

void KopeteProtocol::setIcon( const QString &icon )
{
	m_icon = icon;
}

// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before>// DepthOp.cpp
/*
 * Copyright (c) 2009, Dan Heeks
 * This program is released under the BSD license. See the file COPYING for
 * details.
 */

#include "stdafx.h"
#include "DepthOp.h"
#include "CNCConfig.h"
#include "ProgramCanvas.h"
#include "Program.h"
#include "interface/PropertyInt.h"
#include "interface/PropertyDouble.h"
#include "interface/PropertyLength.h"
#include "tinyxml/tinyxml.h"
#include "interface/Tool.h"

CDepthOpParams::CDepthOpParams()
{
	m_tool_number = 0;
	m_tool_diameter = 0.0;
	m_clearance_height = 0.0;
	m_start_depth = 0.0;
	m_step_down = 0.0;
	m_final_depth = 0.0;
	m_rapid_down_to_height = 0.0;
	m_horizontal_feed_rate = 0.0;
	m_vertical_feed_rate = 0.0;
	m_spindle_speed = 0.0;
}

void CDepthOpParams::set_initial_values()
{
	CNCConfig config;
	config.Read(_T("DepthOpToolNumber"), &m_tool_number, 1);
	config.Read(_T("DepthOpToolDiameter"), &m_tool_diameter, 3.0);
	config.Read(_T("DepthOpClearanceHeight"), &m_clearance_height, 5.0);
	config.Read(_T("DepthOpStartDepth"), &m_start_depth, 0.0);
	config.Read(_T("DepthOpStepDown"), &m_step_down, 1.0);
	config.Read(_T("DepthOpFinalDepth"), &m_final_depth, -1.0);
	config.Read(_T("DepthOpRapidDown"), &m_rapid_down_to_height, 2.0);
	config.Read(_T("DepthOpHorizFeed"), &m_horizontal_feed_rate, 100.0);
	config.Read(_T("DepthOpVertFeed"), &m_vertical_feed_rate, 100.0);
	config.Read(_T("DepthOpSpindleSpeed"), &m_spindle_speed, 7000);
}

void CDepthOpParams::write_values_to_config()
{
	CNCConfig config;
	config.Write(_T("DepthOpToolNumber"), m_tool_number);
	config.Write(_T("DepthOpToolDiameter"), m_tool_diameter);
	config.Write(_T("DepthOpClearanceHeight"), m_clearance_height);
	config.Write(_T("DepthOpStartDepth"), m_start_depth);
	config.Write(_T("DepthOpStepDown"), m_step_down);
	config.Write(_T("DepthOpFinalDepth"), m_final_depth);
	config.Write(_T("DepthOpRapidDown"), m_rapid_down_to_height);
	config.Write(_T("DepthOpHorizFeed"), m_horizontal_feed_rate);
	config.Write(_T("DepthOpVertFeed"), m_vertical_feed_rate);
	config.Write(_T("DepthOpSpindleSpeed"), m_spindle_speed);
}

static void on_set_tool_number(int value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_tool_number = value;}
static void on_set_tool_diameter(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_tool_diameter = value;}
static void on_set_clearance_height(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_clearance_height = value;}
static void on_set_step_down(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_step_down = value;}
static void on_set_start_depth(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_start_depth = value;}
static void on_set_final_depth(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_final_depth = value;}
static void on_set_rapid_down_to_height(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_rapid_down_to_height = value;}
static void on_set_horizontal_feed_rate(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_horizontal_feed_rate = value;}
static void on_set_vertical_feed_rate(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_vertical_feed_rate = value;}
static void on_set_spindle_speed(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_spindle_speed = value;}

void CDepthOpParams::GetProperties(CDepthOp* parent, std::list<Property *> *list)
{
	list->push_back(new PropertyInt(_("tool number"), m_tool_number, parent, on_set_tool_number));
	list->push_back(new PropertyLength(_("tool diameter"), m_tool_diameter, parent, on_set_tool_diameter));
	list->push_back(new PropertyLength(_("clearance height"), m_clearance_height, parent, on_set_clearance_height));
	list->push_back(new PropertyLength(_("step down"), m_step_down, parent, on_set_step_down));
	list->push_back(new PropertyLength(_("start depth"), m_start_depth, parent, on_set_start_depth));
	list->push_back(new PropertyLength(_("final depth"), m_final_depth, parent, on_set_final_depth));
	list->push_back(new PropertyLength(_("rapid down to height"), m_rapid_down_to_height, parent, on_set_rapid_down_to_height));
	list->push_back(new PropertyDouble(_("horizontal feed rate"), m_horizontal_feed_rate, parent, on_set_horizontal_feed_rate));
	list->push_back(new PropertyDouble(_("vertical feed rate"), m_vertical_feed_rate, parent, on_set_vertical_feed_rate));
	list->push_back(new PropertyDouble(_("spindle speed"), m_spindle_speed, parent, on_set_spindle_speed));
}

void CDepthOpParams::WriteXMLAttributes(TiXmlNode* pElem)
{
	TiXmlElement * element = new TiXmlElement( "depthop" );
	pElem->LinkEndChild( element );
	element->SetAttribute("tooln", m_tool_number);
	element->SetDoubleAttribute("toold", m_tool_diameter);
	element->SetDoubleAttribute("clear", m_clearance_height);
	element->SetDoubleAttribute("down", m_step_down);
	element->SetDoubleAttribute("startdepth", m_start_depth);
	element->SetDoubleAttribute("depth", m_final_depth);
	element->SetDoubleAttribute("r", m_rapid_down_to_height);
	element->SetDoubleAttribute("hfeed", m_horizontal_feed_rate);
	element->SetDoubleAttribute("vfeed", m_vertical_feed_rate);
	element->SetDoubleAttribute("spin", m_spindle_speed);
}

void CDepthOpParams::ReadFromXMLElement(TiXmlElement* pElem)
{
	TiXmlElement* depthop = TiXmlHandle(pElem).FirstChildElement("depthop").Element();
	if(depthop)
	{
		depthop->Attribute("tooln", &m_tool_number);
		depthop->Attribute("toold", &m_tool_diameter);
		depthop->Attribute("clear", &m_clearance_height);
		depthop->Attribute("down", &m_step_down);
		depthop->Attribute("startdepth", &m_start_depth);
		depthop->Attribute("depth", &m_final_depth);
		depthop->Attribute("r", &m_rapid_down_to_height);
		depthop->Attribute("hfeed", &m_horizontal_feed_rate);
		depthop->Attribute("vfeed", &m_vertical_feed_rate);
		depthop->Attribute("spin", &m_spindle_speed);
	}
}

void CDepthOp::WriteBaseXML(TiXmlElement *element)
{
	m_depth_op_params.WriteXMLAttributes(element);
	COp::WriteBaseXML(element);
}

void CDepthOp::ReadBaseXML(TiXmlElement* element)
{
	m_depth_op_params.ReadFromXMLElement(element);
	COp::ReadBaseXML(element);
}

void CDepthOp::GetProperties(std::list<Property *> *list)
{
	m_depth_op_params.GetProperties(this, list);
	COp::GetProperties(list);
}

void CDepthOp::AppendTextToProgram()
{
	COp::AppendTextToProgram();

	theApp.m_program_canvas->AppendText(_T("clearance = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_clearance_height / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("clearance = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_clearance_height / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("rapid_down_to_height = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_rapid_down_to_height / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("start_depth = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_start_depth / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("step_down = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_step_down / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("final_depth = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_final_depth / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("tool_diameter = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_tool_diameter / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("spindle("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_spindle_speed);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("feedrate("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_horizontal_feed_rate);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("tool_change("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_tool_number);
	theApp.m_program_canvas->AppendText(_T(")\n"));
}

<commit_msg>duplicate "clearance" python script written<commit_after>// DepthOp.cpp
/*
 * Copyright (c) 2009, Dan Heeks
 * This program is released under the BSD license. See the file COPYING for
 * details.
 */

#include "stdafx.h"
#include "DepthOp.h"
#include "CNCConfig.h"
#include "ProgramCanvas.h"
#include "Program.h"
#include "interface/PropertyInt.h"
#include "interface/PropertyDouble.h"
#include "interface/PropertyLength.h"
#include "tinyxml/tinyxml.h"
#include "interface/Tool.h"

CDepthOpParams::CDepthOpParams()
{
	m_tool_number = 0;
	m_tool_diameter = 0.0;
	m_clearance_height = 0.0;
	m_start_depth = 0.0;
	m_step_down = 0.0;
	m_final_depth = 0.0;
	m_rapid_down_to_height = 0.0;
	m_horizontal_feed_rate = 0.0;
	m_vertical_feed_rate = 0.0;
	m_spindle_speed = 0.0;
}

void CDepthOpParams::set_initial_values()
{
	CNCConfig config;
	config.Read(_T("DepthOpToolNumber"), &m_tool_number, 1);
	config.Read(_T("DepthOpToolDiameter"), &m_tool_diameter, 3.0);
	config.Read(_T("DepthOpClearanceHeight"), &m_clearance_height, 5.0);
	config.Read(_T("DepthOpStartDepth"), &m_start_depth, 0.0);
	config.Read(_T("DepthOpStepDown"), &m_step_down, 1.0);
	config.Read(_T("DepthOpFinalDepth"), &m_final_depth, -1.0);
	config.Read(_T("DepthOpRapidDown"), &m_rapid_down_to_height, 2.0);
	config.Read(_T("DepthOpHorizFeed"), &m_horizontal_feed_rate, 100.0);
	config.Read(_T("DepthOpVertFeed"), &m_vertical_feed_rate, 100.0);
	config.Read(_T("DepthOpSpindleSpeed"), &m_spindle_speed, 7000);
}

void CDepthOpParams::write_values_to_config()
{
	CNCConfig config;
	config.Write(_T("DepthOpToolNumber"), m_tool_number);
	config.Write(_T("DepthOpToolDiameter"), m_tool_diameter);
	config.Write(_T("DepthOpClearanceHeight"), m_clearance_height);
	config.Write(_T("DepthOpStartDepth"), m_start_depth);
	config.Write(_T("DepthOpStepDown"), m_step_down);
	config.Write(_T("DepthOpFinalDepth"), m_final_depth);
	config.Write(_T("DepthOpRapidDown"), m_rapid_down_to_height);
	config.Write(_T("DepthOpHorizFeed"), m_horizontal_feed_rate);
	config.Write(_T("DepthOpVertFeed"), m_vertical_feed_rate);
	config.Write(_T("DepthOpSpindleSpeed"), m_spindle_speed);
}

static void on_set_tool_number(int value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_tool_number = value;}
static void on_set_tool_diameter(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_tool_diameter = value;}
static void on_set_clearance_height(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_clearance_height = value;}
static void on_set_step_down(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_step_down = value;}
static void on_set_start_depth(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_start_depth = value;}
static void on_set_final_depth(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_final_depth = value;}
static void on_set_rapid_down_to_height(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_rapid_down_to_height = value;}
static void on_set_horizontal_feed_rate(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_horizontal_feed_rate = value;}
static void on_set_vertical_feed_rate(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_vertical_feed_rate = value;}
static void on_set_spindle_speed(double value, HeeksObj* object){((CDepthOp*)object)->m_depth_op_params.m_spindle_speed = value;}

void CDepthOpParams::GetProperties(CDepthOp* parent, std::list<Property *> *list)
{
	list->push_back(new PropertyInt(_("tool number"), m_tool_number, parent, on_set_tool_number));
	list->push_back(new PropertyLength(_("tool diameter"), m_tool_diameter, parent, on_set_tool_diameter));
	list->push_back(new PropertyLength(_("clearance height"), m_clearance_height, parent, on_set_clearance_height));
	list->push_back(new PropertyLength(_("step down"), m_step_down, parent, on_set_step_down));
	list->push_back(new PropertyLength(_("start depth"), m_start_depth, parent, on_set_start_depth));
	list->push_back(new PropertyLength(_("final depth"), m_final_depth, parent, on_set_final_depth));
	list->push_back(new PropertyLength(_("rapid down to height"), m_rapid_down_to_height, parent, on_set_rapid_down_to_height));
	list->push_back(new PropertyDouble(_("horizontal feed rate"), m_horizontal_feed_rate, parent, on_set_horizontal_feed_rate));
	list->push_back(new PropertyDouble(_("vertical feed rate"), m_vertical_feed_rate, parent, on_set_vertical_feed_rate));
	list->push_back(new PropertyDouble(_("spindle speed"), m_spindle_speed, parent, on_set_spindle_speed));
}

void CDepthOpParams::WriteXMLAttributes(TiXmlNode* pElem)
{
	TiXmlElement * element = new TiXmlElement( "depthop" );
	pElem->LinkEndChild( element );
	element->SetAttribute("tooln", m_tool_number);
	element->SetDoubleAttribute("toold", m_tool_diameter);
	element->SetDoubleAttribute("clear", m_clearance_height);
	element->SetDoubleAttribute("down", m_step_down);
	element->SetDoubleAttribute("startdepth", m_start_depth);
	element->SetDoubleAttribute("depth", m_final_depth);
	element->SetDoubleAttribute("r", m_rapid_down_to_height);
	element->SetDoubleAttribute("hfeed", m_horizontal_feed_rate);
	element->SetDoubleAttribute("vfeed", m_vertical_feed_rate);
	element->SetDoubleAttribute("spin", m_spindle_speed);
}

void CDepthOpParams::ReadFromXMLElement(TiXmlElement* pElem)
{
	TiXmlElement* depthop = TiXmlHandle(pElem).FirstChildElement("depthop").Element();
	if(depthop)
	{
		depthop->Attribute("tooln", &m_tool_number);
		depthop->Attribute("toold", &m_tool_diameter);
		depthop->Attribute("clear", &m_clearance_height);
		depthop->Attribute("down", &m_step_down);
		depthop->Attribute("startdepth", &m_start_depth);
		depthop->Attribute("depth", &m_final_depth);
		depthop->Attribute("r", &m_rapid_down_to_height);
		depthop->Attribute("hfeed", &m_horizontal_feed_rate);
		depthop->Attribute("vfeed", &m_vertical_feed_rate);
		depthop->Attribute("spin", &m_spindle_speed);
	}
}

void CDepthOp::WriteBaseXML(TiXmlElement *element)
{
	m_depth_op_params.WriteXMLAttributes(element);
	COp::WriteBaseXML(element);
}

void CDepthOp::ReadBaseXML(TiXmlElement* element)
{
	m_depth_op_params.ReadFromXMLElement(element);
	COp::ReadBaseXML(element);
}

void CDepthOp::GetProperties(std::list<Property *> *list)
{
	m_depth_op_params.GetProperties(this, list);
	COp::GetProperties(list);
}

void CDepthOp::AppendTextToProgram()
{
	COp::AppendTextToProgram();

	theApp.m_program_canvas->AppendText(_T("clearance = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_clearance_height / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("rapid_down_to_height = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_rapid_down_to_height / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("start_depth = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_start_depth / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("step_down = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_step_down / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("final_depth = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_final_depth / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("tool_diameter = float("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_tool_diameter / theApp.m_program->m_units);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("spindle("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_spindle_speed);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("feedrate("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_horizontal_feed_rate);
	theApp.m_program_canvas->AppendText(_T(")\n"));
	theApp.m_program_canvas->AppendText(_T("tool_change("));
	theApp.m_program_canvas->AppendText(m_depth_op_params.m_tool_number);
	theApp.m_program_canvas->AppendText(_T(")\n"));
}

<|endoftext|>


<commit_before>#include "main.h"
#include "File.h"
#include "header.h"

#ifdef NO_PNG
namespace FilePNG {
#include "FileNotImplemented.h"
}
#else

namespace FilePNG {

#define PNG_DEBUG 3
#include <png.h>

void help() {
    printf(".png files. These have a bit depth of 8, and may have 1-4 channels. They may\n"
           "only have 1 frame.\n");
}

Image load(string filename) {
    png_byte header[8];        // 8 is the maximum size that can be checked
    png_structp png_ptr;
    png_infop info_ptr;
    int number_of_passes;
    png_bytep *row_pointers;

    /* open file and test for it being a png */
    FILE *f = fopen(filename.c_str(), "rb");
    assert(f, "File %s could not be opened for reading\n", filename.c_str());
    assert(fread(header, 1, 8, f) == 8, "File ended before end of header\n");
    assert(!png_sig_cmp(header, 0, 8), "File %s is not recognized as a PNG file\n", filename.c_str());

    /* initialize stuff */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

    assert(png_ptr, "[read_png_file] png_create_read_struct failed\n");

    info_ptr = png_create_info_struct(png_ptr);
    assert(info_ptr, "[read_png_file] png_create_info_struct failed\n");

    assert(!setjmp(png_jmpbuf(png_ptr)), "[read_png_file] Error during init_io\n");

    png_init_io(png_ptr, f);
    png_set_sig_bytes(png_ptr, 8);

    png_read_info(png_ptr, info_ptr);

    int width = png_get_image_width(png_ptr, info_ptr);
    int height = png_get_image_height(png_ptr, info_ptr);
    int channels = png_get_channels(png_ptr, info_ptr);
    int bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    // Expand low-bpp images to have only 1 pixel per byte (As opposed to tight packing)
    if (bit_depth < 8) {
        png_set_packing(png_ptr);
    }

    Image im(width, height, 1, channels);

    number_of_passes = png_set_interlace_handling(png_ptr);
    png_read_update_info(png_ptr, info_ptr);

    // read the file
    assert(!setjmp(png_jmpbuf(png_ptr)), "[read_png_file] Error during read_image\n");

    row_pointers = new png_bytep[im.height];
    for (int y = 0; y < im.height; y++) {
        row_pointers[y] = new png_byte[info_ptr->rowbytes];
    }

    png_read_image(png_ptr, row_pointers);

    fclose(f);

    // convert the data to floats
    if (bit_depth <= 8) {
        int bit_scale = 8/bit_depth;
        for (int y = 0; y < im.height; y++) {
            png_bytep srcPtr = row_pointers[y];
            for (int x = 0; x < im.width; x++) {
                for (int c = 0; c < im.channels; c++) {
                    im(x, y)[c] = LDRtoHDR(bit_scale* (*srcPtr++));
                }
            }
        }
    } else if (bit_depth == 16) {
        printf("Reading a 16-bit PNG image (Image may be darker than expected!)\n");
        for (int y = 0; y < im.height; y++) {
            png_bytep srcPtr = row_pointers[y];
            for (int x = 0; x < im.width; x++) {
                for (int c = 0; c < im.channels; c++) {
                    im(x, y)[c] = LDR16toHDR(*srcPtr);  // Note: Endian issues may be possible here, seems to work in WinXP
                    srcPtr+=2;
                }
            }
        }
    }

    // clean up
    for (int y = 0; y < im.height; y++) {
        delete[] row_pointers[y];
    }
    delete[] row_pointers;

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    return im;
}

void save(Window im, string filename) {
    png_structp png_ptr;
    png_infop info_ptr;
    png_bytep *row_pointers;
    png_byte color_type;

    assert(im.frames == 1, "Can't save a multi-frame PNG image\n");
    assert(im.channels > 0 && im.channels < 5,
           "Imagestack can't write PNG files that have other than 1, 2, 3, or 4 channels\n");

    png_byte color_types[4] = {PNG_COLOR_TYPE_GRAY, PNG_COLOR_TYPE_GRAY_ALPHA,
                               PNG_COLOR_TYPE_RGB,  PNG_COLOR_TYPE_RGB_ALPHA
                              };
    color_type = color_types[im.channels - 1];

    // open file
    FILE *f = fopen(filename.c_str(), "wb");
    assert(f, "[write_png_file] File %s could not be opened for writing\n", filename.c_str());

    // initialize stuff
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    assert(png_ptr, "[write_png_file] png_create_write_struct failed\n");

    info_ptr = png_create_info_struct(png_ptr);
    assert(info_ptr, "[write_png_file] png_create_info_struct failed\n");

    assert(!setjmp(png_jmpbuf(png_ptr)), "[write_png_file] Error during init_io\n");

    png_init_io(png_ptr, f);

    // write header
    assert(!setjmp(png_jmpbuf(png_ptr)), "[write_png_file] Error during writing header\n");

    png_set_IHDR(png_ptr, info_ptr, im.width, im.height,
                 8, color_type, PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

    png_write_info(png_ptr, info_ptr);

    // convert the floats to bytes
    row_pointers = new png_bytep[im.height];
    for (int y = 0; y < im.height; y++) {
        row_pointers[y] = new png_byte[info_ptr->rowbytes];
        png_bytep dstPtr = row_pointers[y];
        for (int x = 0; x < im.width; x++) {
            for (int c = 0; c < im.channels; c++) {
                *dstPtr++ = (png_byte)(HDRtoLDR(im(x, y)[c]));
            }
        }
    }

    // write data
    assert(!setjmp(png_jmpbuf(png_ptr)), "[write_png_file] Error during writing bytes");

    png_write_image(png_ptr, row_pointers);

    // finish write
    assert(!setjmp(png_jmpbuf(png_ptr)), "[write_png_file] Error during end of write");

    png_write_end(png_ptr, NULL);

    // clean up
    for (int y = 0; y < im.height; y++) {
        delete[] row_pointers[y];
    }
    delete[] row_pointers;

    fclose(f);

    png_destroy_write_struct(&png_ptr, &info_ptr);
}

}

#endif
#include "footer.h"
<commit_msg>Updated FilePNG to work with libpng 1.5<commit_after>#include "main.h"
#include "File.h"
#include "header.h"

#ifdef NO_PNG
namespace FilePNG {
#include "FileNotImplemented.h"
}
#else

namespace FilePNG {

#define PNG_DEBUG 3
#include <png.h>

void help() {
    printf(".png files. These have a bit depth of 8, and may have 1-4 channels. They may\n"
           "only have 1 frame.\n");
}

Image load(string filename) {
    png_byte header[8];        // 8 is the maximum size that can be checked
    png_structp png_ptr;
    png_infop info_ptr;
    int number_of_passes;
    png_bytep *row_pointers;

    /* open file and test for it being a png */
    FILE *f = fopen(filename.c_str(), "rb");
    assert(f, "File %s could not be opened for reading\n", filename.c_str());
    assert(fread(header, 1, 8, f) == 8, "File ended before end of header\n");
    assert(!png_sig_cmp(header, 0, 8), "File %s is not recognized as a PNG file\n", filename.c_str());

    /* initialize stuff */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

    assert(png_ptr, "[read_png_file] png_create_read_struct failed\n");

    info_ptr = png_create_info_struct(png_ptr);
    assert(info_ptr, "[read_png_file] png_create_info_struct failed\n");

    assert(!setjmp(png_jmpbuf(png_ptr)), "[read_png_file] Error during init_io\n");

    png_init_io(png_ptr, f);
    png_set_sig_bytes(png_ptr, 8);

    png_read_info(png_ptr, info_ptr);

    int width = png_get_image_width(png_ptr, info_ptr);
    int height = png_get_image_height(png_ptr, info_ptr);
    int channels = png_get_channels(png_ptr, info_ptr);
    int bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    // Expand low-bpp images to have only 1 pixel per byte (As opposed to tight packing)
    if (bit_depth < 8) {
        png_set_packing(png_ptr);
    }

    Image im(width, height, 1, channels);

    number_of_passes = png_set_interlace_handling(png_ptr);
    png_read_update_info(png_ptr, info_ptr);

    // read the file
    assert(!setjmp(png_jmpbuf(png_ptr)), "[read_png_file] Error during read_image\n");

    row_pointers = new png_bytep[im.height];
    for (int y = 0; y < im.height; y++) {
        row_pointers[y] = new png_byte[png_get_rowbytes(png_ptr, info_ptr)];
    }

    png_read_image(png_ptr, row_pointers);

    fclose(f);

    // convert the data to floats
    if (bit_depth <= 8) {
        int bit_scale = 8/bit_depth;
        for (int y = 0; y < im.height; y++) {
            png_bytep srcPtr = row_pointers[y];
            for (int x = 0; x < im.width; x++) {
                for (int c = 0; c < im.channels; c++) {
                    im(x, y)[c] = LDRtoHDR(bit_scale* (*srcPtr++));
                }
            }
        }
    } else if (bit_depth == 16) {
        printf("Reading a 16-bit PNG image (Image may be darker than expected!)\n");
        for (int y = 0; y < im.height; y++) {
            png_bytep srcPtr = row_pointers[y];
            for (int x = 0; x < im.width; x++) {
                for (int c = 0; c < im.channels; c++) {
                    im(x, y)[c] = LDR16toHDR(*srcPtr);  // Note: Endian issues may be possible here, seems to work in WinXP
                    srcPtr+=2;
                }
            }
        }
    }

    // clean up
    for (int y = 0; y < im.height; y++) {
        delete[] row_pointers[y];
    }
    delete[] row_pointers;

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    return im;
}

void save(Window im, string filename) {
    png_structp png_ptr;
    png_infop info_ptr;
    png_bytep *row_pointers;
    png_byte color_type;

    assert(im.frames == 1, "Can't save a multi-frame PNG image\n");
    assert(im.channels > 0 && im.channels < 5,
           "Imagestack can't write PNG files that have other than 1, 2, 3, or 4 channels\n");

    png_byte color_types[4] = {PNG_COLOR_TYPE_GRAY, PNG_COLOR_TYPE_GRAY_ALPHA,
                               PNG_COLOR_TYPE_RGB,  PNG_COLOR_TYPE_RGB_ALPHA
                              };
    color_type = color_types[im.channels - 1];

    // open file
    FILE *f = fopen(filename.c_str(), "wb");
    assert(f, "[write_png_file] File %s could not be opened for writing\n", filename.c_str());

    // initialize stuff
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    assert(png_ptr, "[write_png_file] png_create_write_struct failed\n");

    info_ptr = png_create_info_struct(png_ptr);
    assert(info_ptr, "[write_png_file] png_create_info_struct failed\n");

    assert(!setjmp(png_jmpbuf(png_ptr)), "[write_png_file] Error during init_io\n");

    png_init_io(png_ptr, f);

    // write header
    assert(!setjmp(png_jmpbuf(png_ptr)), "[write_png_file] Error during writing header\n");

    png_set_IHDR(png_ptr, info_ptr, im.width, im.height,
                 8, color_type, PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

    png_write_info(png_ptr, info_ptr);

    // convert the floats to bytes
    row_pointers = new png_bytep[im.height];
    for (int y = 0; y < im.height; y++) {
	row_pointers[y] = new png_byte[png_get_rowbytes(png_ptr, info_ptr)];
        png_bytep dstPtr = row_pointers[y];
        for (int x = 0; x < im.width; x++) {
            for (int c = 0; c < im.channels; c++) {
                *dstPtr++ = (png_byte)(HDRtoLDR(im(x, y)[c]));
            }
        }
    }

    // write data
    assert(!setjmp(png_jmpbuf(png_ptr)), "[write_png_file] Error during writing bytes");

    png_write_image(png_ptr, row_pointers);

    // finish write
    assert(!setjmp(png_jmpbuf(png_ptr)), "[write_png_file] Error during end of write");

    png_write_end(png_ptr, NULL);

    // clean up
    for (int y = 0; y < im.height; y++) {
        delete[] row_pointers[y];
    }
    delete[] row_pointers;

    fclose(f);

    png_destroy_write_struct(&png_ptr, &info_ptr);
}

}

#endif
#include "footer.h"
<|endoftext|>


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

   Flexbar - flexible barcode and adapter removal

   Version 3.0.0

   uses SeqAn library release 2.1.1
   and TBB library 4.0 or later

             Developer:  Johannes Roehr

   Former contributors:  Matthias Dodt
                         Benjamin Menkuec
                         Sebastian Roskosch

   https://github.com/seqan/flexbar

===================================================*/

#include "Flexbar.h"

int main(int argc, const char* argv[]){

	using namespace std;
	using namespace flexbar;

	using seqan::ArgumentParser;

	const string version = "3.0 dev";
	const string date    = "May 2016";

	ArgumentParser parser("flexbar");

	defineOptions(parser, version, date);
	parseCmdLine(parser, version, argc, argv);

	Options o;

	initOptions(o, parser);
	loadOptions(o, parser);

	startComputation(o);

	return 0;
}
<commit_msg>Minor changes<commit_after>/*==================================================

   Flexbar - flexible barcode and adapter removal

   Version 3.0.0

   uses SeqAn library release 2.1.1
   and TBB library 4.0 or later

             Developer:  Johannes Roehr

   Former contributors:  Matthias Dodt
                         Benjamin Menkuec
                         Sebastian Roskosch

   https://github.com/seqan/flexbar

===================================================*/

#include "Flexbar.h"

int main(int argc, const char* argv[]){

	using namespace std;
	using namespace seqan;

	const string version = "3.0 dev";
	const string date    = "June 2016";

	ArgumentParser parser("flexbar");

	defineOptions(parser, version, date);
	parseCmdLine(parser, version, argc, argv);

	Options o;

	initOptions(o, parser);
	loadOptions(o, parser);

	startComputation(o);

	return 0;
}
<|endoftext|>