<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include "worksheetsettings.hxx"

#include <com/sun/star/util/XProtectable.hpp>
#include "oox/core/filterbase.hxx"
#include "oox/helper/attributelist.hxx"
#include "oox/token/properties.hxx"
#include "biffinputstream.hxx"
#include "pagesettings.hxx"
#include "workbooksettings.hxx"
#include "tabprotection.hxx"
#include "document.hxx"

namespace oox {
namespace xls {

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

using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::util;

using ::oox::core::CodecHelper;

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

namespace {

const sal_uInt8 BIFF12_SHEETPR_FILTERMODE       = 0x01;
const sal_uInt8 BIFF12_SHEETPR_EVAL_CF          = 0x02;

const sal_uInt32 BIFF_SHEETEXT_NOTABCOLOR       = 0x7F;

const sal_uInt16 BIFF_SHEETPR_DIALOGSHEET       = 0x0010;
const sal_uInt16 BIFF_SHEETPR_APPLYSTYLES       = 0x0020;
const sal_uInt16 BIFF_SHEETPR_SYMBOLSBELOW      = 0x0040;
const sal_uInt16 BIFF_SHEETPR_SYMBOLSRIGHT      = 0x0080;
const sal_uInt16 BIFF_SHEETPR_FITTOPAGES        = 0x0100;
const sal_uInt16 BIFF_SHEETPR_SKIPEXT           = 0x0200;       // BIFF3-BIFF4

const sal_uInt32 BIFF_SHEETPROT_OBJECTS         = 0x00000001;
const sal_uInt32 BIFF_SHEETPROT_SCENARIOS       = 0x00000002;
const sal_uInt32 BIFF_SHEETPROT_FORMAT_CELLS    = 0x00000004;
const sal_uInt32 BIFF_SHEETPROT_FORMAT_COLUMNS  = 0x00000008;
const sal_uInt32 BIFF_SHEETPROT_FORMAT_ROWS     = 0x00000010;
const sal_uInt32 BIFF_SHEETPROT_INSERT_COLUMNS  = 0x00000020;
const sal_uInt32 BIFF_SHEETPROT_INSERT_ROWS     = 0x00000040;
const sal_uInt32 BIFF_SHEETPROT_INSERT_HLINKS   = 0x00000080;
const sal_uInt32 BIFF_SHEETPROT_DELETE_COLUMNS  = 0x00000100;
const sal_uInt32 BIFF_SHEETPROT_DELETE_ROWS     = 0x00000200;
const sal_uInt32 BIFF_SHEETPROT_SELECT_LOCKED   = 0x00000400;
const sal_uInt32 BIFF_SHEETPROT_SORT            = 0x00000800;
const sal_uInt32 BIFF_SHEETPROT_AUTOFILTER      = 0x00001000;
const sal_uInt32 BIFF_SHEETPROT_PIVOTTABLES     = 0x00002000;
const sal_uInt32 BIFF_SHEETPROT_SELECT_UNLOCKED = 0x00004000;

} // namespace

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

SheetSettingsModel::SheetSettingsModel() :
    mbFilterMode( false ),
    mbApplyStyles( false ),
    mbSummaryBelow( true ),
    mbSummaryRight( true )
{
}

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

SheetProtectionModel::SheetProtectionModel() :
    mnPasswordHash( 0 ),
    mbSheet( false ),
    mbObjects( false ),
    mbScenarios( false ),
    mbFormatCells( true ),
    mbFormatColumns( true ),
    mbFormatRows( true ),
    mbInsertColumns( true ),
    mbInsertRows( true ),
    mbInsertHyperlinks( true ),
    mbDeleteColumns( true ),
    mbDeleteRows( true ),
    mbSelectLocked( false ),
    mbSort( true ),
    mbAutoFilter( true ),
    mbPivotTables( true ),
    mbSelectUnlocked( false )
{
}

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

WorksheetSettings::WorksheetSettings( const WorksheetHelper& rHelper ) :
    WorksheetHelper( rHelper ),
    maPhoneticSett( rHelper )
{
}

void WorksheetSettings::importSheetPr( const AttributeList& rAttribs )
{
    maSheetSettings.maCodeName = rAttribs.getString( XML_codeName, OUString() );
    maSheetSettings.mbFilterMode = rAttribs.getBool( XML_filterMode, false );
}

void WorksheetSettings::importChartSheetPr( const AttributeList& rAttribs )
{
    maSheetSettings.maCodeName = rAttribs.getString( XML_codeName, OUString() );
}

void WorksheetSettings::importTabColor( const AttributeList& rAttribs )
{
    maSheetSettings.maTabColor.importColor( rAttribs );
}

void WorksheetSettings::importOutlinePr( const AttributeList& rAttribs )
{
    maSheetSettings.mbApplyStyles  = rAttribs.getBool( XML_applyStyles, false );
    maSheetSettings.mbSummaryBelow = rAttribs.getBool( XML_summaryBelow, true );
    maSheetSettings.mbSummaryRight = rAttribs.getBool( XML_summaryRight, true );
}

void WorksheetSettings::importSheetProtection( const AttributeList& rAttribs )
{
    maSheetProt.mnPasswordHash     = CodecHelper::getPasswordHash( rAttribs, XML_password );
    maSheetProt.mbSheet            = rAttribs.getBool( XML_sheet, false );
    maSheetProt.mbObjects          = rAttribs.getBool( XML_objects, false );
    maSheetProt.mbScenarios        = rAttribs.getBool( XML_scenarios, false );
    maSheetProt.mbFormatCells      = rAttribs.getBool( XML_formatCells, true );
    maSheetProt.mbFormatColumns    = rAttribs.getBool( XML_formatColumns, true );
    maSheetProt.mbFormatRows       = rAttribs.getBool( XML_formatRows, true );
    maSheetProt.mbInsertColumns    = rAttribs.getBool( XML_insertColumns, true );
    maSheetProt.mbInsertRows       = rAttribs.getBool( XML_insertRows, true );
    maSheetProt.mbInsertHyperlinks = rAttribs.getBool( XML_insertHyperlinks, true );
    maSheetProt.mbDeleteColumns    = rAttribs.getBool( XML_deleteColumns, true );
    maSheetProt.mbDeleteRows       = rAttribs.getBool( XML_deleteRows, true );
    maSheetProt.mbSelectLocked     = rAttribs.getBool( XML_selectLockedCells, false );
    maSheetProt.mbSort             = rAttribs.getBool( XML_sort, true );
    maSheetProt.mbAutoFilter       = rAttribs.getBool( XML_autoFilter, true );
    maSheetProt.mbPivotTables      = rAttribs.getBool( XML_pivotTables, true );
    maSheetProt.mbSelectUnlocked   = rAttribs.getBool( XML_selectUnlockedCells, false );
}

void WorksheetSettings::importChartProtection( const AttributeList& rAttribs )
{
    maSheetProt.mnPasswordHash = CodecHelper::getPasswordHash( rAttribs, XML_password );
    maSheetProt.mbSheet        = rAttribs.getBool( XML_content, false );
    maSheetProt.mbObjects      = rAttribs.getBool( XML_objects, false );
}

void WorksheetSettings::importPhoneticPr( const AttributeList& rAttribs )
{
    maPhoneticSett.importPhoneticPr( rAttribs );
}

void WorksheetSettings::importSheetPr( SequenceInputStream& rStrm )
{
    sal_uInt16 nFlags1;
    sal_uInt8 nFlags2;
    rStrm >> nFlags1 >> nFlags2 >> maSheetSettings.maTabColor;
    rStrm.skip( 8 );    // sync anchor cell
    rStrm >> maSheetSettings.maCodeName;
    // sheet settings
    maSheetSettings.mbFilterMode = getFlag( nFlags2, BIFF12_SHEETPR_FILTERMODE );
    // outline settings, equal flags in all BIFFs
    maSheetSettings.mbApplyStyles  = getFlag( nFlags1, BIFF_SHEETPR_APPLYSTYLES );
    maSheetSettings.mbSummaryRight = getFlag( nFlags1, BIFF_SHEETPR_SYMBOLSRIGHT );
    maSheetSettings.mbSummaryBelow = getFlag( nFlags1, BIFF_SHEETPR_SYMBOLSBELOW );
    /*  Fit printout to width/height - for whatever reason, this flag is still
        stored separated from the page settings */
    getPageSettings().setFitToPagesMode( getFlag( nFlags1, BIFF_SHEETPR_FITTOPAGES ) );
}

void WorksheetSettings::importChartSheetPr( SequenceInputStream& rStrm )
{
    rStrm.skip( 2 );    // flags, contains only the 'published' flag
    rStrm >> maSheetSettings.maTabColor >> maSheetSettings.maCodeName;
}

void WorksheetSettings::importSheetProtection( SequenceInputStream& rStrm )
{
    rStrm >> maSheetProt.mnPasswordHash;
    // no flags field for all these boolean flags?!?
    maSheetProt.mbSheet            = rStrm.readInt32() != 0;
    maSheetProt.mbObjects          = rStrm.readInt32() != 0;
    maSheetProt.mbScenarios        = rStrm.readInt32() != 0;
    maSheetProt.mbFormatCells      = rStrm.readInt32() != 0;
    maSheetProt.mbFormatColumns    = rStrm.readInt32() != 0;
    maSheetProt.mbFormatRows       = rStrm.readInt32() != 0;
    maSheetProt.mbInsertColumns    = rStrm.readInt32() != 0;
    maSheetProt.mbInsertRows       = rStrm.readInt32() != 0;
    maSheetProt.mbInsertHyperlinks = rStrm.readInt32() != 0;
    maSheetProt.mbDeleteColumns    = rStrm.readInt32() != 0;
    maSheetProt.mbDeleteRows       = rStrm.readInt32() != 0;
    maSheetProt.mbSelectLocked     = rStrm.readInt32() != 0;
    maSheetProt.mbSort             = rStrm.readInt32() != 0;
    maSheetProt.mbAutoFilter       = rStrm.readInt32() != 0;
    maSheetProt.mbPivotTables      = rStrm.readInt32() != 0;
    maSheetProt.mbSelectUnlocked   = rStrm.readInt32() != 0;
}

void WorksheetSettings::importChartProtection( SequenceInputStream& rStrm )
{
    rStrm >> maSheetProt.mnPasswordHash;
    // no flags field for all these boolean flags?!?
    maSheetProt.mbSheet            = rStrm.readInt32() != 0;
    maSheetProt.mbObjects          = rStrm.readInt32() != 0;
}

void WorksheetSettings::importPhoneticPr( SequenceInputStream& rStrm )
{
    maPhoneticSett.importPhoneticPr( rStrm );
}

void WorksheetSettings::finalizeImport()
{
    // sheet protection
    if( maSheetProt.mbSheet )
    {
        ScTableProtection aProtect;
        aProtect.setProtected(true);
        if (maSheetProt.mnPasswordHash)
        {
            Sequence<sal_Int8> aPass(2);
            aPass[0] = ( maSheetProt.mnPasswordHash>> 8) & 0xFF;
            aPass[1] = maSheetProt.mnPasswordHash & 0xFF;
            aProtect.setPasswordHash(aPass, PASSHASH_XL);
        }
        aProtect.setOption( ScTableProtection::OBJECTS, maSheetProt.mbObjects);
        aProtect.setOption( ScTableProtection::SCENARIOS, maSheetProt.mbScenarios );
        aProtect.setOption( ScTableProtection::FORMAT_CELLS, maSheetProt.mbFormatCells );
        aProtect.setOption( ScTableProtection::FORMAT_COLUMNS, maSheetProt.mbFormatColumns );
        aProtect.setOption( ScTableProtection::FORMAT_ROWS, maSheetProt.mbFormatRows );
        aProtect.setOption( ScTableProtection::INSERT_COLUMNS, maSheetProt.mbInsertColumns );
        aProtect.setOption( ScTableProtection::INSERT_ROWS,  maSheetProt.mbInsertRows );
        aProtect.setOption( ScTableProtection::INSERT_HYPERLINKS, maSheetProt.mbInsertHyperlinks );
        aProtect.setOption( ScTableProtection::DELETE_COLUMNS, maSheetProt.mbDeleteColumns );
        aProtect.setOption( ScTableProtection::DELETE_ROWS,maSheetProt.mbDeleteRows );
        aProtect.setOption( ScTableProtection::SELECT_LOCKED_CELLS, maSheetProt.mbSelectLocked );
        aProtect.setOption( ScTableProtection::SORT, maSheetProt.mbSort );
        aProtect.setOption( ScTableProtection::AUTOFILTER, maSheetProt.mbAutoFilter );
        aProtect.setOption( ScTableProtection::PIVOT_TABLES, maSheetProt.mbPivotTables );
        aProtect.setOption( ScTableProtection::SELECT_UNLOCKED_CELLS, maSheetProt.mbSelectUnlocked );

        getScDocument().SetTabProtection( getSheetIndex(), &aProtect );
    }

    // VBA code name
    PropertySet aPropSet( getSheet() );
    aPropSet.setProperty( PROP_CodeName, maSheetSettings.maCodeName );

    // sheet tab color
    if( !maSheetSettings.maTabColor.isAuto() )
    {
        sal_Int32 nColor = maSheetSettings.maTabColor.getColor( getBaseFilter().getGraphicHelper() );
        aPropSet.setProperty( PROP_TabColor, nColor );
    }
}

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

} // namespace xls
} // namespace oox

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>-Werror,-Wunused-const-variable<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include "worksheetsettings.hxx"

#include <com/sun/star/util/XProtectable.hpp>
#include "oox/core/filterbase.hxx"
#include "oox/helper/attributelist.hxx"
#include "oox/token/properties.hxx"
#include "biffinputstream.hxx"
#include "pagesettings.hxx"
#include "workbooksettings.hxx"
#include "tabprotection.hxx"
#include "document.hxx"

namespace oox {
namespace xls {

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

using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::util;

using ::oox::core::CodecHelper;

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

namespace {

const sal_uInt8 BIFF12_SHEETPR_FILTERMODE       = 0x01;

const sal_uInt16 BIFF_SHEETPR_APPLYSTYLES       = 0x0020;
const sal_uInt16 BIFF_SHEETPR_SYMBOLSBELOW      = 0x0040;
const sal_uInt16 BIFF_SHEETPR_SYMBOLSRIGHT      = 0x0080;
const sal_uInt16 BIFF_SHEETPR_FITTOPAGES        = 0x0100;

} // namespace

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

SheetSettingsModel::SheetSettingsModel() :
    mbFilterMode( false ),
    mbApplyStyles( false ),
    mbSummaryBelow( true ),
    mbSummaryRight( true )
{
}

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

SheetProtectionModel::SheetProtectionModel() :
    mnPasswordHash( 0 ),
    mbSheet( false ),
    mbObjects( false ),
    mbScenarios( false ),
    mbFormatCells( true ),
    mbFormatColumns( true ),
    mbFormatRows( true ),
    mbInsertColumns( true ),
    mbInsertRows( true ),
    mbInsertHyperlinks( true ),
    mbDeleteColumns( true ),
    mbDeleteRows( true ),
    mbSelectLocked( false ),
    mbSort( true ),
    mbAutoFilter( true ),
    mbPivotTables( true ),
    mbSelectUnlocked( false )
{
}

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

WorksheetSettings::WorksheetSettings( const WorksheetHelper& rHelper ) :
    WorksheetHelper( rHelper ),
    maPhoneticSett( rHelper )
{
}

void WorksheetSettings::importSheetPr( const AttributeList& rAttribs )
{
    maSheetSettings.maCodeName = rAttribs.getString( XML_codeName, OUString() );
    maSheetSettings.mbFilterMode = rAttribs.getBool( XML_filterMode, false );
}

void WorksheetSettings::importChartSheetPr( const AttributeList& rAttribs )
{
    maSheetSettings.maCodeName = rAttribs.getString( XML_codeName, OUString() );
}

void WorksheetSettings::importTabColor( const AttributeList& rAttribs )
{
    maSheetSettings.maTabColor.importColor( rAttribs );
}

void WorksheetSettings::importOutlinePr( const AttributeList& rAttribs )
{
    maSheetSettings.mbApplyStyles  = rAttribs.getBool( XML_applyStyles, false );
    maSheetSettings.mbSummaryBelow = rAttribs.getBool( XML_summaryBelow, true );
    maSheetSettings.mbSummaryRight = rAttribs.getBool( XML_summaryRight, true );
}

void WorksheetSettings::importSheetProtection( const AttributeList& rAttribs )
{
    maSheetProt.mnPasswordHash     = CodecHelper::getPasswordHash( rAttribs, XML_password );
    maSheetProt.mbSheet            = rAttribs.getBool( XML_sheet, false );
    maSheetProt.mbObjects          = rAttribs.getBool( XML_objects, false );
    maSheetProt.mbScenarios        = rAttribs.getBool( XML_scenarios, false );
    maSheetProt.mbFormatCells      = rAttribs.getBool( XML_formatCells, true );
    maSheetProt.mbFormatColumns    = rAttribs.getBool( XML_formatColumns, true );
    maSheetProt.mbFormatRows       = rAttribs.getBool( XML_formatRows, true );
    maSheetProt.mbInsertColumns    = rAttribs.getBool( XML_insertColumns, true );
    maSheetProt.mbInsertRows       = rAttribs.getBool( XML_insertRows, true );
    maSheetProt.mbInsertHyperlinks = rAttribs.getBool( XML_insertHyperlinks, true );
    maSheetProt.mbDeleteColumns    = rAttribs.getBool( XML_deleteColumns, true );
    maSheetProt.mbDeleteRows       = rAttribs.getBool( XML_deleteRows, true );
    maSheetProt.mbSelectLocked     = rAttribs.getBool( XML_selectLockedCells, false );
    maSheetProt.mbSort             = rAttribs.getBool( XML_sort, true );
    maSheetProt.mbAutoFilter       = rAttribs.getBool( XML_autoFilter, true );
    maSheetProt.mbPivotTables      = rAttribs.getBool( XML_pivotTables, true );
    maSheetProt.mbSelectUnlocked   = rAttribs.getBool( XML_selectUnlockedCells, false );
}

void WorksheetSettings::importChartProtection( const AttributeList& rAttribs )
{
    maSheetProt.mnPasswordHash = CodecHelper::getPasswordHash( rAttribs, XML_password );
    maSheetProt.mbSheet        = rAttribs.getBool( XML_content, false );
    maSheetProt.mbObjects      = rAttribs.getBool( XML_objects, false );
}

void WorksheetSettings::importPhoneticPr( const AttributeList& rAttribs )
{
    maPhoneticSett.importPhoneticPr( rAttribs );
}

void WorksheetSettings::importSheetPr( SequenceInputStream& rStrm )
{
    sal_uInt16 nFlags1;
    sal_uInt8 nFlags2;
    rStrm >> nFlags1 >> nFlags2 >> maSheetSettings.maTabColor;
    rStrm.skip( 8 );    // sync anchor cell
    rStrm >> maSheetSettings.maCodeName;
    // sheet settings
    maSheetSettings.mbFilterMode = getFlag( nFlags2, BIFF12_SHEETPR_FILTERMODE );
    // outline settings, equal flags in all BIFFs
    maSheetSettings.mbApplyStyles  = getFlag( nFlags1, BIFF_SHEETPR_APPLYSTYLES );
    maSheetSettings.mbSummaryRight = getFlag( nFlags1, BIFF_SHEETPR_SYMBOLSRIGHT );
    maSheetSettings.mbSummaryBelow = getFlag( nFlags1, BIFF_SHEETPR_SYMBOLSBELOW );
    /*  Fit printout to width/height - for whatever reason, this flag is still
        stored separated from the page settings */
    getPageSettings().setFitToPagesMode( getFlag( nFlags1, BIFF_SHEETPR_FITTOPAGES ) );
}

void WorksheetSettings::importChartSheetPr( SequenceInputStream& rStrm )
{
    rStrm.skip( 2 );    // flags, contains only the 'published' flag
    rStrm >> maSheetSettings.maTabColor >> maSheetSettings.maCodeName;
}

void WorksheetSettings::importSheetProtection( SequenceInputStream& rStrm )
{
    rStrm >> maSheetProt.mnPasswordHash;
    // no flags field for all these boolean flags?!?
    maSheetProt.mbSheet            = rStrm.readInt32() != 0;
    maSheetProt.mbObjects          = rStrm.readInt32() != 0;
    maSheetProt.mbScenarios        = rStrm.readInt32() != 0;
    maSheetProt.mbFormatCells      = rStrm.readInt32() != 0;
    maSheetProt.mbFormatColumns    = rStrm.readInt32() != 0;
    maSheetProt.mbFormatRows       = rStrm.readInt32() != 0;
    maSheetProt.mbInsertColumns    = rStrm.readInt32() != 0;
    maSheetProt.mbInsertRows       = rStrm.readInt32() != 0;
    maSheetProt.mbInsertHyperlinks = rStrm.readInt32() != 0;
    maSheetProt.mbDeleteColumns    = rStrm.readInt32() != 0;
    maSheetProt.mbDeleteRows       = rStrm.readInt32() != 0;
    maSheetProt.mbSelectLocked     = rStrm.readInt32() != 0;
    maSheetProt.mbSort             = rStrm.readInt32() != 0;
    maSheetProt.mbAutoFilter       = rStrm.readInt32() != 0;
    maSheetProt.mbPivotTables      = rStrm.readInt32() != 0;
    maSheetProt.mbSelectUnlocked   = rStrm.readInt32() != 0;
}

void WorksheetSettings::importChartProtection( SequenceInputStream& rStrm )
{
    rStrm >> maSheetProt.mnPasswordHash;
    // no flags field for all these boolean flags?!?
    maSheetProt.mbSheet            = rStrm.readInt32() != 0;
    maSheetProt.mbObjects          = rStrm.readInt32() != 0;
}

void WorksheetSettings::importPhoneticPr( SequenceInputStream& rStrm )
{
    maPhoneticSett.importPhoneticPr( rStrm );
}

void WorksheetSettings::finalizeImport()
{
    // sheet protection
    if( maSheetProt.mbSheet )
    {
        ScTableProtection aProtect;
        aProtect.setProtected(true);
        if (maSheetProt.mnPasswordHash)
        {
            Sequence<sal_Int8> aPass(2);
            aPass[0] = ( maSheetProt.mnPasswordHash>> 8) & 0xFF;
            aPass[1] = maSheetProt.mnPasswordHash & 0xFF;
            aProtect.setPasswordHash(aPass, PASSHASH_XL);
        }
        aProtect.setOption( ScTableProtection::OBJECTS, maSheetProt.mbObjects);
        aProtect.setOption( ScTableProtection::SCENARIOS, maSheetProt.mbScenarios );
        aProtect.setOption( ScTableProtection::FORMAT_CELLS, maSheetProt.mbFormatCells );
        aProtect.setOption( ScTableProtection::FORMAT_COLUMNS, maSheetProt.mbFormatColumns );
        aProtect.setOption( ScTableProtection::FORMAT_ROWS, maSheetProt.mbFormatRows );
        aProtect.setOption( ScTableProtection::INSERT_COLUMNS, maSheetProt.mbInsertColumns );
        aProtect.setOption( ScTableProtection::INSERT_ROWS,  maSheetProt.mbInsertRows );
        aProtect.setOption( ScTableProtection::INSERT_HYPERLINKS, maSheetProt.mbInsertHyperlinks );
        aProtect.setOption( ScTableProtection::DELETE_COLUMNS, maSheetProt.mbDeleteColumns );
        aProtect.setOption( ScTableProtection::DELETE_ROWS,maSheetProt.mbDeleteRows );
        aProtect.setOption( ScTableProtection::SELECT_LOCKED_CELLS, maSheetProt.mbSelectLocked );
        aProtect.setOption( ScTableProtection::SORT, maSheetProt.mbSort );
        aProtect.setOption( ScTableProtection::AUTOFILTER, maSheetProt.mbAutoFilter );
        aProtect.setOption( ScTableProtection::PIVOT_TABLES, maSheetProt.mbPivotTables );
        aProtect.setOption( ScTableProtection::SELECT_UNLOCKED_CELLS, maSheetProt.mbSelectUnlocked );

        getScDocument().SetTabProtection( getSheetIndex(), &aProtect );
    }

    // VBA code name
    PropertySet aPropSet( getSheet() );
    aPropSet.setProperty( PROP_CodeName, maSheetSettings.maCodeName );

    // sheet tab color
    if( !maSheetSettings.maTabColor.isAuto() )
    {
        sal_Int32 nColor = maSheetSettings.maTabColor.getColor( getBaseFilter().getGraphicHelper() );
        aPropSet.setProperty( PROP_TabColor, nColor );
    }
}

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

} // namespace xls
} // namespace oox

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


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/planning/planning.h"

#include <algorithm>
#include <thread>

#include "google/protobuf/repeated_field.h"
#include "modules/common/adapters/adapter_manager.h"
#include "modules/common/time/time.h"
#include "modules/common/vehicle_state/vehicle_state.h"
#include "modules/map/hdmap/hdmap_util.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/planner/em/em_planner.h"
#include "modules/planning/planner/rtk/rtk_replay_planner.h"
#include "modules/planning/trajectory_stitcher/trajectory_stitcher.h"

namespace apollo {
namespace planning {

using apollo::common::ErrorCode;
using apollo::common::Status;
using apollo::common::TrajectoryPoint;
using apollo::common::VehicleState;
using apollo::common::adapter::AdapterManager;
using apollo::common::time::Clock;

std::string Planning::Name() const { return "planning"; }

void Planning::RegisterPlanners() {
  planner_factory_.Register(
      PlanningConfig::RTK, []() -> Planner* { return new RTKReplayPlanner(); });
  planner_factory_.Register(PlanningConfig::EM,
                            []() -> Planner* { return new EMPlanner(); });
}

Status Planning::InitFrame(const uint32_t sequence_num,
                           const TrajectoryPoint& init_adc_point) {
  frame_.reset(new Frame(sequence_num));
  frame_->SetPlanningStartPoint(init_adc_point);

  if (AdapterManager::GetRoutingResponse()->Empty()) {
    AERROR << "Routing is empty";
    return Status(ErrorCode::PLANNING_ERROR, "routing is empty");
  }
  frame_->SetVehicleInitPose(VehicleState::instance()->pose());
  frame_->SetRoutingResponse(
      AdapterManager::GetRoutingResponse()->GetLatestObserved());
  if (FLAGS_enable_prediction && !AdapterManager::GetPrediction()->Empty()) {
    const auto& prediction =
        AdapterManager::GetPrediction()->GetLatestObserved();
    frame_->SetPrediction(prediction);
    ADEBUG << "Get prediction done.";
  }

  auto status = frame_->Init(config_, start_timestamp_);
  if (!status.ok()) {
    AERROR << "failed to init frame";
    return Status(ErrorCode::PLANNING_ERROR, "init frame failed");
  }
  frame_->RecordInputDebug();
  return Status::OK();
}

Status Planning::Init() {
  pnc_map_.reset(new hdmap::PncMap(apollo::hdmap::BaseMapFile()));
  Frame::SetMap(pnc_map_.get());

  CHECK(apollo::common::util::GetProtoFromFile(FLAGS_planning_config_file,
                                               &config_))
      << "failed to load planning config file " << FLAGS_planning_config_file;
  if (!AdapterManager::Initialized()) {
    AdapterManager::Init(FLAGS_adapter_config_path);
  }
  if (AdapterManager::GetLocalization() == nullptr) {
    std::string error_msg("Localization is not registered");
    AERROR << error_msg;
    return Status(ErrorCode::PLANNING_ERROR, error_msg);
  }
  if (AdapterManager::GetChassis() == nullptr) {
    std::string error_msg("Chassis is not registered");
    AERROR << error_msg;
    return Status(ErrorCode::PLANNING_ERROR, error_msg);
  }
  if (AdapterManager::GetRoutingResponse() == nullptr) {
    std::string error_msg("RoutingResponse is not registered");
    AERROR << error_msg;
    return Status(ErrorCode::PLANNING_ERROR, error_msg);
  }
  if (FLAGS_enable_prediction && AdapterManager::GetPrediction() == nullptr) {
    std::string error_msg("Prediction is not registered");
    AERROR << error_msg;
    return Status(ErrorCode::PLANNING_ERROR, error_msg);
  }

  RegisterPlanners();
  planner_ = planner_factory_.CreateObject(config_.planner_type());
  if (!planner_) {
    return Status(
        ErrorCode::PLANNING_ERROR,
        "planning is not initialized with config : " + config_.DebugString());
  }

  return planner_->Init(config_);
}

Status Planning::Start() {
  static ros::Rate loop_rate(FLAGS_planning_loop_rate);
  while (ros::ok()) {
    RunOnce();
    if (frame_) {
      auto seq_num = frame_->SequenceNum();
      FrameHistory::instance()->Add(seq_num, std::move(frame_));
    }
    ros::spinOnce();
    loop_rate.sleep();
  }
  return Status::OK();
}

void Planning::PublishPlanningPb(ADCTrajectory* trajectory_pb) {
  AdapterManager::FillPlanningHeader("planning", trajectory_pb);
  // TODO(all): integrate reverse gear
  trajectory_pb->set_gear(canbus::Chassis::GEAR_DRIVE);
  AdapterManager::PublishPlanning(*trajectory_pb);
}

void Planning::PublishPlanningPb(ADCTrajectory* trajectory_pb,
                                 double timestamp) {
  AdapterManager::FillPlanningHeader("planning", trajectory_pb);
  trajectory_pb->mutable_header()->set_timestamp_sec(timestamp);
  // TODO(all): integrate reverse gear
  trajectory_pb->set_gear(canbus::Chassis::GEAR_DRIVE);
  AdapterManager::PublishPlanning(*trajectory_pb);
}

void Planning::RunOnce() {
  start_timestamp_ = Clock::NowInSecond();
  AdapterManager::Observe();
  ADCTrajectory not_ready_pb;
  auto* not_ready = not_ready_pb.mutable_decision()
                        ->mutable_main_decision()
                        ->mutable_not_ready();
  if (AdapterManager::GetLocalization()->Empty()) {
    not_ready->set_reason("localization not ready");
  } else if (AdapterManager::GetChassis()->Empty()) {
    not_ready->set_reason("chassis not ready");
  } else if (AdapterManager::GetRoutingResponse()->Empty()) {
    not_ready->set_reason("routing not ready");
  } else if (FLAGS_enable_prediction &&
             AdapterManager::GetPrediction()->Empty()) {
    not_ready->set_reason("prediction not ready");
  }
  if (not_ready->has_reason()) {
    AERROR << not_ready->reason() << "; skip the planning cycle.";
    PublishPlanningPb(&not_ready_pb);
    return;
  }

  // localization
  const auto& localization =
      AdapterManager::GetLocalization()->GetLatestObserved();
  ADEBUG << "Get localization:" << localization.DebugString();

  // chassis
  const auto& chassis = AdapterManager::GetChassis()->GetLatestObserved();
  ADEBUG << "Get chassis:" << chassis.DebugString();

  common::Status status =
      common::VehicleState::instance()->Update(localization, chassis);

  if (!status.ok()) {
    AERROR << "Update VehicleState failed.";
    not_ready->set_reason("Update VehicleState failed.");
    status.Save(not_ready_pb.mutable_header()->mutable_status());
    PublishPlanningPb(&not_ready_pb);
    return;
  }

  const double planning_cycle_time = 1.0 / FLAGS_planning_loop_rate;

  bool is_auto_mode = chassis.driving_mode() == chassis.COMPLETE_AUTO_DRIVE;
  const auto& stitching_trajectory =
      TrajectoryStitcher::ComputeStitchingTrajectory(
          is_auto_mode, start_timestamp_, planning_cycle_time,
          last_publishable_trajectory_);

  const uint32_t frame_num = AdapterManager::GetPlanning()->GetSeqNum() + 1;
  status = InitFrame(frame_num, stitching_trajectory.back());
  if (!status.ok()) {
    ADCTrajectory estop;
    estop.mutable_estop();
    AERROR << "Init frame failed";
    status.Save(estop.mutable_header()->mutable_status());
    PublishPlanningPb(&estop, start_timestamp_);
    return;
  }

  status = Plan(start_timestamp_, stitching_trajectory);

  const double end_timestamp = Clock::NowInSecond();
  const double time_diff_ms = (end_timestamp - start_timestamp_) * 1000;
  auto trajectory_pb = frame_->MutableADCTrajectory();
  trajectory_pb->mutable_latency_stats()->set_total_time_ms(time_diff_ms);
  ADEBUG << "Planning latency: "
         << trajectory_pb->latency_stats().DebugString();

  if (status.ok()) {
    PublishPlanningPb(trajectory_pb, start_timestamp_);
    ADEBUG << "Planning succeeded:" << trajectory_pb->header().DebugString();
  } else {
    status.Save(trajectory_pb->mutable_header()->mutable_status());
    PublishPlanningPb(trajectory_pb, start_timestamp_);
    AERROR << "Planning failed";
  }
}

void Planning::Stop() {
  last_publishable_trajectory_.Clear();
  frame_.reset(nullptr);
  planner_.reset(nullptr);
}

common::Status Planning::Plan(
    const double current_time_stamp,
    const std::vector<common::TrajectoryPoint>& stitching_trajectory) {
  auto trajectory_pb = frame_->MutableADCTrajectory();
  if (FLAGS_enable_record_debug) {
    trajectory_pb->mutable_debug()
        ->mutable_planning_data()
        ->mutable_init_point()
        ->CopyFrom(stitching_trajectory.back());
  }
  auto status = Status::OK();
  for (auto& reference_line_info : frame_->reference_line_info()) {
    status = planner_->Plan(stitching_trajectory.back(), frame_.get(),
                            &reference_line_info);
    AERROR_IF(!status.ok()) << "planner failed to make a driving plan.";
  }

  const auto* best_reference_line = frame_->FindDriveReferenceLineInfo();
  if (!best_reference_line) {
    std::string msg("planner failed to make a driving plan");
    AERROR << msg;
    last_publishable_trajectory_.Clear();
    return Status(ErrorCode::PLANNING_ERROR, msg);
  }

  auto* ptr_debug = frame_->MutableADCTrajectory()->mutable_debug();
  ptr_debug->MergeFrom(best_reference_line->debug());
  frame_->MutableADCTrajectory()->mutable_latency_stats()->MergeFrom(
      best_reference_line->latency_stats());

  // Add debug information.
  if (FLAGS_enable_record_debug) {
    auto* reference_line = ptr_debug->mutable_planning_data()->add_path();
    reference_line->set_name("planning_reference_line");
    const auto& reference_points =
        best_reference_line->reference_line().reference_points();
    for (const auto& reference_point : reference_points) {
      auto* path_point = reference_line->add_path_point();
      path_point->set_x(reference_point.x());
      path_point->set_y(reference_point.y());
      path_point->set_theta(reference_point.heading());
      path_point->set_kappa(reference_point.kappa());
      path_point->set_dkappa(reference_point.dkappa());
    }
  }

  PublishableTrajectory publishable_trajectory(
      current_time_stamp, best_reference_line->trajectory());

  publishable_trajectory.PrependTrajectoryPoints(
      stitching_trajectory.begin(), stitching_trajectory.end() - 1);

  publishable_trajectory.PopulateTrajectoryProtobuf(trajectory_pb);
  trajectory_pb->set_is_replan(stitching_trajectory.size() == 1);

  // update last publishable trajectory;
  last_publishable_trajectory_ = std::move(publishable_trajectory);

  return status;
}

}  // namespace planning
}  // namespace apollo
<commit_msg>planning: remove hard code planning name.<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/planning/planning.h"

#include <algorithm>
#include <thread>

#include "google/protobuf/repeated_field.h"
#include "modules/common/adapters/adapter_manager.h"
#include "modules/common/time/time.h"
#include "modules/common/vehicle_state/vehicle_state.h"
#include "modules/map/hdmap/hdmap_util.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/planner/em/em_planner.h"
#include "modules/planning/planner/rtk/rtk_replay_planner.h"
#include "modules/planning/trajectory_stitcher/trajectory_stitcher.h"

namespace apollo {
namespace planning {

using apollo::common::ErrorCode;
using apollo::common::Status;
using apollo::common::TrajectoryPoint;
using apollo::common::VehicleState;
using apollo::common::adapter::AdapterManager;
using apollo::common::time::Clock;

std::string Planning::Name() const { return "planning"; }

void Planning::RegisterPlanners() {
  planner_factory_.Register(
      PlanningConfig::RTK, []() -> Planner* { return new RTKReplayPlanner(); });
  planner_factory_.Register(PlanningConfig::EM,
                            []() -> Planner* { return new EMPlanner(); });
}

Status Planning::InitFrame(const uint32_t sequence_num,
                           const TrajectoryPoint& init_adc_point) {
  frame_.reset(new Frame(sequence_num));
  frame_->SetPlanningStartPoint(init_adc_point);

  if (AdapterManager::GetRoutingResponse()->Empty()) {
    AERROR << "Routing is empty";
    return Status(ErrorCode::PLANNING_ERROR, "routing is empty");
  }
  frame_->SetVehicleInitPose(VehicleState::instance()->pose());
  frame_->SetRoutingResponse(
      AdapterManager::GetRoutingResponse()->GetLatestObserved());
  if (FLAGS_enable_prediction && !AdapterManager::GetPrediction()->Empty()) {
    const auto& prediction =
        AdapterManager::GetPrediction()->GetLatestObserved();
    frame_->SetPrediction(prediction);
    ADEBUG << "Get prediction done.";
  }

  auto status = frame_->Init(config_, start_timestamp_);
  if (!status.ok()) {
    AERROR << "failed to init frame";
    return Status(ErrorCode::PLANNING_ERROR, "init frame failed");
  }
  frame_->RecordInputDebug();
  return Status::OK();
}

Status Planning::Init() {
  pnc_map_.reset(new hdmap::PncMap(apollo::hdmap::BaseMapFile()));
  Frame::SetMap(pnc_map_.get());

  CHECK(apollo::common::util::GetProtoFromFile(FLAGS_planning_config_file,
                                               &config_))
      << "failed to load planning config file " << FLAGS_planning_config_file;
  if (!AdapterManager::Initialized()) {
    AdapterManager::Init(FLAGS_adapter_config_path);
  }
  if (AdapterManager::GetLocalization() == nullptr) {
    std::string error_msg("Localization is not registered");
    AERROR << error_msg;
    return Status(ErrorCode::PLANNING_ERROR, error_msg);
  }
  if (AdapterManager::GetChassis() == nullptr) {
    std::string error_msg("Chassis is not registered");
    AERROR << error_msg;
    return Status(ErrorCode::PLANNING_ERROR, error_msg);
  }
  if (AdapterManager::GetRoutingResponse() == nullptr) {
    std::string error_msg("RoutingResponse is not registered");
    AERROR << error_msg;
    return Status(ErrorCode::PLANNING_ERROR, error_msg);
  }
  if (FLAGS_enable_prediction && AdapterManager::GetPrediction() == nullptr) {
    std::string error_msg("Prediction is not registered");
    AERROR << error_msg;
    return Status(ErrorCode::PLANNING_ERROR, error_msg);
  }

  RegisterPlanners();
  planner_ = planner_factory_.CreateObject(config_.planner_type());
  if (!planner_) {
    return Status(
        ErrorCode::PLANNING_ERROR,
        "planning is not initialized with config : " + config_.DebugString());
  }

  return planner_->Init(config_);
}

Status Planning::Start() {
  static ros::Rate loop_rate(FLAGS_planning_loop_rate);
  while (ros::ok()) {
    RunOnce();
    if (frame_) {
      auto seq_num = frame_->SequenceNum();
      FrameHistory::instance()->Add(seq_num, std::move(frame_));
    }
    ros::spinOnce();
    loop_rate.sleep();
  }
  return Status::OK();
}

void Planning::PublishPlanningPb(ADCTrajectory* trajectory_pb) {
  AdapterManager::FillPlanningHeader(Name(), trajectory_pb);
  // TODO(all): integrate reverse gear
  trajectory_pb->set_gear(canbus::Chassis::GEAR_DRIVE);
  AdapterManager::PublishPlanning(*trajectory_pb);
}

void Planning::PublishPlanningPb(ADCTrajectory* trajectory_pb,
                                 double timestamp) {
  AdapterManager::FillPlanningHeader(Name(), trajectory_pb);
  trajectory_pb->mutable_header()->set_timestamp_sec(timestamp);
  // TODO(all): integrate reverse gear
  trajectory_pb->set_gear(canbus::Chassis::GEAR_DRIVE);
  AdapterManager::PublishPlanning(*trajectory_pb);
}

void Planning::RunOnce() {
  start_timestamp_ = Clock::NowInSecond();
  AdapterManager::Observe();
  ADCTrajectory not_ready_pb;
  auto* not_ready = not_ready_pb.mutable_decision()
                        ->mutable_main_decision()
                        ->mutable_not_ready();
  if (AdapterManager::GetLocalization()->Empty()) {
    not_ready->set_reason("localization not ready");
  } else if (AdapterManager::GetChassis()->Empty()) {
    not_ready->set_reason("chassis not ready");
  } else if (AdapterManager::GetRoutingResponse()->Empty()) {
    not_ready->set_reason("routing not ready");
  } else if (FLAGS_enable_prediction &&
             AdapterManager::GetPrediction()->Empty()) {
    not_ready->set_reason("prediction not ready");
  }
  if (not_ready->has_reason()) {
    AERROR << not_ready->reason() << "; skip the planning cycle.";
    PublishPlanningPb(&not_ready_pb);
    return;
  }

  // localization
  const auto& localization =
      AdapterManager::GetLocalization()->GetLatestObserved();
  ADEBUG << "Get localization:" << localization.DebugString();

  // chassis
  const auto& chassis = AdapterManager::GetChassis()->GetLatestObserved();
  ADEBUG << "Get chassis:" << chassis.DebugString();

  common::Status status =
      common::VehicleState::instance()->Update(localization, chassis);

  if (!status.ok()) {
    AERROR << "Update VehicleState failed.";
    not_ready->set_reason("Update VehicleState failed.");
    status.Save(not_ready_pb.mutable_header()->mutable_status());
    PublishPlanningPb(&not_ready_pb);
    return;
  }

  const double planning_cycle_time = 1.0 / FLAGS_planning_loop_rate;

  bool is_auto_mode = chassis.driving_mode() == chassis.COMPLETE_AUTO_DRIVE;
  const auto& stitching_trajectory =
      TrajectoryStitcher::ComputeStitchingTrajectory(
          is_auto_mode, start_timestamp_, planning_cycle_time,
          last_publishable_trajectory_);

  const uint32_t frame_num = AdapterManager::GetPlanning()->GetSeqNum() + 1;
  status = InitFrame(frame_num, stitching_trajectory.back());
  if (!status.ok()) {
    ADCTrajectory estop;
    estop.mutable_estop();
    AERROR << "Init frame failed";
    status.Save(estop.mutable_header()->mutable_status());
    PublishPlanningPb(&estop, start_timestamp_);
    return;
  }

  status = Plan(start_timestamp_, stitching_trajectory);

  const double end_timestamp = Clock::NowInSecond();
  const double time_diff_ms = (end_timestamp - start_timestamp_) * 1000;
  auto trajectory_pb = frame_->MutableADCTrajectory();
  trajectory_pb->mutable_latency_stats()->set_total_time_ms(time_diff_ms);
  ADEBUG << "Planning latency: "
         << trajectory_pb->latency_stats().DebugString();

  if (status.ok()) {
    PublishPlanningPb(trajectory_pb, start_timestamp_);
    ADEBUG << "Planning succeeded:" << trajectory_pb->header().DebugString();
  } else {
    status.Save(trajectory_pb->mutable_header()->mutable_status());
    PublishPlanningPb(trajectory_pb, start_timestamp_);
    AERROR << "Planning failed";
  }
}

void Planning::Stop() {
  last_publishable_trajectory_.Clear();
  frame_.reset(nullptr);
  planner_.reset(nullptr);
}

common::Status Planning::Plan(
    const double current_time_stamp,
    const std::vector<common::TrajectoryPoint>& stitching_trajectory) {
  auto trajectory_pb = frame_->MutableADCTrajectory();
  if (FLAGS_enable_record_debug) {
    trajectory_pb->mutable_debug()
        ->mutable_planning_data()
        ->mutable_init_point()
        ->CopyFrom(stitching_trajectory.back());
  }
  auto status = Status::OK();
  for (auto& reference_line_info : frame_->reference_line_info()) {
    status = planner_->Plan(stitching_trajectory.back(), frame_.get(),
                            &reference_line_info);
    AERROR_IF(!status.ok()) << "planner failed to make a driving plan.";
  }

  const auto* best_reference_line = frame_->FindDriveReferenceLineInfo();
  if (!best_reference_line) {
    std::string msg("planner failed to make a driving plan");
    AERROR << msg;
    last_publishable_trajectory_.Clear();
    return Status(ErrorCode::PLANNING_ERROR, msg);
  }

  auto* ptr_debug = frame_->MutableADCTrajectory()->mutable_debug();
  ptr_debug->MergeFrom(best_reference_line->debug());
  frame_->MutableADCTrajectory()->mutable_latency_stats()->MergeFrom(
      best_reference_line->latency_stats());

  // Add debug information.
  if (FLAGS_enable_record_debug) {
    auto* reference_line = ptr_debug->mutable_planning_data()->add_path();
    reference_line->set_name("planning_reference_line");
    const auto& reference_points =
        best_reference_line->reference_line().reference_points();
    for (const auto& reference_point : reference_points) {
      auto* path_point = reference_line->add_path_point();
      path_point->set_x(reference_point.x());
      path_point->set_y(reference_point.y());
      path_point->set_theta(reference_point.heading());
      path_point->set_kappa(reference_point.kappa());
      path_point->set_dkappa(reference_point.dkappa());
    }
  }

  PublishableTrajectory publishable_trajectory(
      current_time_stamp, best_reference_line->trajectory());

  publishable_trajectory.PrependTrajectoryPoints(
      stitching_trajectory.begin(), stitching_trajectory.end() - 1);

  publishable_trajectory.PopulateTrajectoryProtobuf(trajectory_pb);
  trajectory_pb->set_is_replan(stitching_trajectory.size() == 1);

  // update last publishable trajectory;
  last_publishable_trajectory_ = std::move(publishable_trajectory);

  return status;
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <sstream>
#include <cstring>
#include <string>

#include "BoyerMoore.h"

using namespace v8;
using namespace node;

namespace {

// this is an application of the Curiously Recurring Template Pattern
template <class Derived> struct UnaryAction {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope);

	Handle<Value> operator()(const Arguments& args) {
		HandleScope scope;

		Local<Object> self = args.This();
		if (!Buffer::HasInstance(self)) {
			return ThrowException(Exception::TypeError(String::New(
					"Argument should be a buffer object.")));
		}

		return static_cast<Derived*>(this)->apply(self, args, scope);
	}
};

template <class Derived> struct BinaryAction {
	Handle<Value> apply(Handle<Object>& buffer, const char* data, size_t size, const Arguments& args, HandleScope& scope);

	Handle<Value> operator()(const Arguments& args) {
		HandleScope scope;

		Local<Object> self = args.This();
		if (!Buffer::HasInstance(self)) {
			return ThrowException(Exception::TypeError(String::New(
					"Argument should be a buffer object.")));
		}

		if (args[0]->IsString()) {
			String::Utf8Value s(args[0]->ToString());
			return static_cast<Derived*>(this)->apply(self, *s, s.length(), args, scope);
		}
		if (Buffer::HasInstance(args[0])) {
			Local<Object> other = args[0]->ToObject();
			return static_cast<Derived*>(this)->apply(
					self, Buffer::Data(other), Buffer::Length(other), args, scope);
		}

		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
				"Second argument must be a string or a buffer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

//
// helper functions
//
Handle<Value> clear(Handle<Object>& buffer, int c) {
	size_t length = Buffer::Length(buffer);
	char* data = Buffer::Data(buffer);
	memset(data, c, length);
	return buffer;
}

Handle<Value> fill(Handle<Object>& buffer, void* pattern, size_t size) {
	size_t length = Buffer::Length(buffer);
	char* data = Buffer::Data(buffer);

	if (size >= length) {
		memcpy(data, pattern, length);
	} else {
		const int n_copies = length / size;
		const int remainder = length % size;
		for (int i = 0; i < n_copies; i++) {
			memcpy(data + size * i, pattern, size);
		}
		memcpy(data + size * n_copies, pattern, remainder);
	}

	return buffer;
}

int compare(Handle<Object>& buffer, const char* data2, size_t length2) {
	size_t length = Buffer::Length(buffer);
	if (length != length2) {
		return length > length2 ? 1 : -1;
	}

	char* data = Buffer::Data(buffer);
	return memcmp(data, data2, length);
}

//
// actions
//
struct ClearAction: UnaryAction<ClearAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		return clear(buffer, 0);
	}
};

struct FillAction: UnaryAction<FillAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		if (args[0]->IsInt32()) {
			int c = args[0]->ToInt32()->Int32Value();
			return clear(buffer, c);
		}

		if (args[0]->IsString()) {
			String::Utf8Value s(args[0]->ToString());
			return fill(buffer, *s, s.length());
		}

		if (Buffer::HasInstance(args[0])) {
			Handle<Object> other = args[0]->ToObject();
			size_t length = Buffer::Length(other);
			char* data = Buffer::Data(other);
			return fill(buffer, data, length);
		}

		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
				"Second argument should be either a string, a buffer or an integer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

struct ReverseAction: UnaryAction<ReverseAction> {
	// O(n/2) for all cases which is okay, might be optimized some more with whole-word swaps
	// XXX won't this trash the L1 cache something awful?
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		char* head = Buffer::Data(buffer);
		char* tail = head + Buffer::Length(buffer) - 1;

		// xor swap, just because I can
		while (head < tail) *head ^= *tail, *tail ^= *head, *head ^= *tail, ++head, --tail;

		return buffer;
	}
};

struct EqualsAction: BinaryAction<EqualsAction> {
	Handle<Value> apply(Handle<Object>& buffer, const char* data, size_t size, const Arguments& args, HandleScope& scope) {
		return compare(buffer, data, size) == 0 ? True() : False();
	}
};

struct CompareAction: BinaryAction<CompareAction> {
	Handle<Value> apply(Handle<Object>& buffer, const char* data, size_t size, const Arguments& args, HandleScope& scope) {
		return scope.Close(Integer::New(compare(buffer, data, size)));
	}
};

struct IndexOfAction: BinaryAction<IndexOfAction> {
	Handle<Value> apply(Handle<Object>& buffer, const char* data2, size_t size2, const Arguments& args, HandleScope& scope) {
		const char* data = Buffer::Data(buffer);
		size_t size = Buffer::Length(buffer);

		const char* p = boyermoore_search(data, size, data2, size2);
		const ptrdiff_t offset = p ? (p - data) : -1;

		return scope.Close(Integer::New(offset));
	}
};

static char toHexTable[] = "0123456789abcdef";

// CHECKME is this cache efficient?
static char fromHexTable[] = {
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,
		10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};

inline Handle<Value> decodeHex(const char* data, size_t size, const Arguments& args, HandleScope& scope) {
	if (size & 1) {
		return ThrowException(Exception::Error(String::New(
				"Odd string length, this is not hexadecimal data.")));
	}

	if (size == 0) {
		return String::Empty();
	}

	Handle<Object>& buffer = Buffer::New(size / 2)->handle_;
	for (char* s = Buffer::Data(buffer); size > 0; size -= 2) {
		int a = fromHexTable[*data++];
		int b = fromHexTable[*data++];

		if (a == -1 || b == -1) {
			return ThrowException(Exception::Error(String::New(
					"This is not hexadecimal data.")));
		}

		*s++ = b | (a << 4);
	}

	return buffer;
}

struct FromHexAction: UnaryAction<FromHexAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		const char* data = Buffer::Data(buffer);
		size_t length = Buffer::Length(buffer);
		return decodeHex(data, length, args, scope);
	}
};

struct ToHexAction: UnaryAction<ToHexAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		const size_t size = Buffer::Length(buffer);
		const char* data = Buffer::Data(buffer);

		if (size == 0) {
			return String::Empty();
		}

		std::string s(size * 2, 0);
		for (size_t i = 0; i < size; ++i) {
			const uint8_t c = (uint8_t) data[i];
			s[i * 2] = toHexTable[c >> 4];
			s[i * 2 + 1] = toHexTable[c & 15];
		}

		return scope.Close(String::New(s.c_str(), s.size()));
	}
};

//
// V8 function callbacks
//
Handle<Value> Clear(const Arguments& args) {
	return ClearAction()(args);
}

Handle<Value> Fill(const Arguments& args) {
	return FillAction()(args);
}

Handle<Value> Reverse(const Arguments& args) {
	return ReverseAction()(args);
}

Handle<Value> Equals(const Arguments& args) {
	return EqualsAction()(args);
}

Handle<Value> Compare(const Arguments& args) {
	return CompareAction()(args);
}

Handle<Value> IndexOf(const Arguments& args) {
	return IndexOfAction()(args);
}

Handle<Value> FromHex(const Arguments& args) {
	return FromHexAction()(args);
}

Handle<Value> ToHex(const Arguments& args) {
	return ToHexAction()(args);
}

Handle<Value> Concat(const Arguments& args) {
	HandleScope scope;

	size_t size = 0;
	for (int index = 0, length = args.Length(); index < length; ++index) {
		Local<Value> arg = args[index];
		if (arg->IsString()) {
			// Utf8Length() because we need the length in bytes, not characters
			size += arg->ToString()->Utf8Length();
		}
		else if (Buffer::HasInstance(arg)) {
			size += Buffer::Length(arg->ToObject());
		}
		else {
			std::stringstream s;
			s << "Argument #" << index << " is neither a string nor a buffer object.";
			const char* message = s.str().c_str();
			return ThrowException(Exception::TypeError(String::New(message)));
		}
	}

	Buffer& dst = *Buffer::New(size);
	char* s = Buffer::Data(dst.handle_);

	for (int index = 0, length = args.Length(); index < length; ++index) {
		Local<Value> arg = args[index];
		if (arg->IsString()) {
			String::Utf8Value v(arg->ToString());
			memcpy(s, *v, v.length());
			s += v.length();
		}
		else if (Buffer::HasInstance(arg)) {
			Local<Object> b = arg->ToObject();
			const char* data = Buffer::Data(b);
			size_t length = Buffer::Length(b);
			memcpy(s, data, length);
			s += length;
		}
		else {
			return ThrowException(Exception::Error(String::New(
					"Congratulations! You have run into a bug: argument is neither a string nor a buffer object. "
					"Please make the world a better place and report it.")));
		}
	}

	return scope.Close(dst.handle_);
}

void RegisterModule(Handle<Object> target) {
	target->Set(String::NewSymbol("concat"),  FunctionTemplate::New(Concat)->GetFunction());
	target->Set(String::NewSymbol("fill"),    FunctionTemplate::New(Fill)->GetFunction());
	target->Set(String::NewSymbol("clear"),   FunctionTemplate::New(Clear)->GetFunction());
	target->Set(String::NewSymbol("reverse"), FunctionTemplate::New(Reverse)->GetFunction());
	target->Set(String::NewSymbol("equals"),  FunctionTemplate::New(Equals)->GetFunction());
	target->Set(String::NewSymbol("compare"), FunctionTemplate::New(Compare)->GetFunction());
	target->Set(String::NewSymbol("indexOf"), FunctionTemplate::New(IndexOf)->GetFunction());
	target->Set(String::NewSymbol("fromHex"), FunctionTemplate::New(FromHex)->GetFunction());
	target->Set(String::NewSymbol("toHex"),   FunctionTemplate::New(ToHex)->GetFunction());
}

} // anonymous namespace

NODE_MODULE(buffertools, RegisterModule);
<commit_msg>Use unsigned data types when decoding hexadecimal data, avoid negative or out-of-bounds array indexing.<commit_after>#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <sstream>
#include <cstring>
#include <string>

#include "BoyerMoore.h"

using namespace v8;
using namespace node;

namespace {

// this is an application of the Curiously Recurring Template Pattern
template <class Derived> struct UnaryAction {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope);

	Handle<Value> operator()(const Arguments& args) {
		HandleScope scope;

		Local<Object> self = args.This();
		if (!Buffer::HasInstance(self)) {
			return ThrowException(Exception::TypeError(String::New(
					"Argument should be a buffer object.")));
		}

		return static_cast<Derived*>(this)->apply(self, args, scope);
	}
};

template <class Derived> struct BinaryAction {
	Handle<Value> apply(Handle<Object>& buffer, const char* data, size_t size, const Arguments& args, HandleScope& scope);

	Handle<Value> operator()(const Arguments& args) {
		HandleScope scope;

		Local<Object> self = args.This();
		if (!Buffer::HasInstance(self)) {
			return ThrowException(Exception::TypeError(String::New(
					"Argument should be a buffer object.")));
		}

		if (args[0]->IsString()) {
			String::Utf8Value s(args[0]->ToString());
			return static_cast<Derived*>(this)->apply(self, *s, s.length(), args, scope);
		}
		if (Buffer::HasInstance(args[0])) {
			Local<Object> other = args[0]->ToObject();
			return static_cast<Derived*>(this)->apply(
					self, Buffer::Data(other), Buffer::Length(other), args, scope);
		}

		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
				"Second argument must be a string or a buffer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

//
// helper functions
//
Handle<Value> clear(Handle<Object>& buffer, int c) {
	size_t length = Buffer::Length(buffer);
	char* data = Buffer::Data(buffer);
	memset(data, c, length);
	return buffer;
}

Handle<Value> fill(Handle<Object>& buffer, void* pattern, size_t size) {
	size_t length = Buffer::Length(buffer);
	char* data = Buffer::Data(buffer);

	if (size >= length) {
		memcpy(data, pattern, length);
	} else {
		const int n_copies = length / size;
		const int remainder = length % size;
		for (int i = 0; i < n_copies; i++) {
			memcpy(data + size * i, pattern, size);
		}
		memcpy(data + size * n_copies, pattern, remainder);
	}

	return buffer;
}

int compare(Handle<Object>& buffer, const char* data2, size_t length2) {
	size_t length = Buffer::Length(buffer);
	if (length != length2) {
		return length > length2 ? 1 : -1;
	}

	char* data = Buffer::Data(buffer);
	return memcmp(data, data2, length);
}

//
// actions
//
struct ClearAction: UnaryAction<ClearAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		return clear(buffer, 0);
	}
};

struct FillAction: UnaryAction<FillAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		if (args[0]->IsInt32()) {
			int c = args[0]->ToInt32()->Int32Value();
			return clear(buffer, c);
		}

		if (args[0]->IsString()) {
			String::Utf8Value s(args[0]->ToString());
			return fill(buffer, *s, s.length());
		}

		if (Buffer::HasInstance(args[0])) {
			Handle<Object> other = args[0]->ToObject();
			size_t length = Buffer::Length(other);
			char* data = Buffer::Data(other);
			return fill(buffer, data, length);
		}

		static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
				"Second argument should be either a string, a buffer or an integer."));
		return ThrowException(Exception::TypeError(illegalArgumentException));
	}
};

struct ReverseAction: UnaryAction<ReverseAction> {
	// O(n/2) for all cases which is okay, might be optimized some more with whole-word swaps
	// XXX won't this trash the L1 cache something awful?
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		char* head = Buffer::Data(buffer);
		char* tail = head + Buffer::Length(buffer) - 1;

		// xor swap, just because I can
		while (head < tail) *head ^= *tail, *tail ^= *head, *head ^= *tail, ++head, --tail;

		return buffer;
	}
};

struct EqualsAction: BinaryAction<EqualsAction> {
	Handle<Value> apply(Handle<Object>& buffer, const char* data, size_t size, const Arguments& args, HandleScope& scope) {
		return compare(buffer, data, size) == 0 ? True() : False();
	}
};

struct CompareAction: BinaryAction<CompareAction> {
	Handle<Value> apply(Handle<Object>& buffer, const char* data, size_t size, const Arguments& args, HandleScope& scope) {
		return scope.Close(Integer::New(compare(buffer, data, size)));
	}
};

struct IndexOfAction: BinaryAction<IndexOfAction> {
	Handle<Value> apply(Handle<Object>& buffer, const char* data2, size_t size2, const Arguments& args, HandleScope& scope) {
		const char* data = Buffer::Data(buffer);
		size_t size = Buffer::Length(buffer);

		const char* p = boyermoore_search(data, size, data2, size2);
		const ptrdiff_t offset = p ? (p - data) : -1;

		return scope.Close(Integer::New(offset));
	}
};

static char toHexTable[] = "0123456789abcdef";

// CHECKME is this cache efficient?
static char fromHexTable[] = {
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,
		10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
		-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};

inline Handle<Value> decodeHex(const char* const data, const size_t size, const Arguments& args, HandleScope& scope) {
	if (size & 1) {
		return ThrowException(Exception::Error(String::New(
				"Odd string length, this is not hexadecimal data.")));
	}

	if (size == 0) {
		return String::Empty();
	}

	Handle<Object>& buffer = Buffer::New(size / 2)->handle_;

	uint8_t *src = (uint8_t *) data;
	uint8_t *dst = (uint8_t *) Buffer::Data(buffer);

	for (size_t i = 0; i < size; i += 2) {
		int a = fromHexTable[*src++];
		int b = fromHexTable[*src++];

		if (a == -1 || b == -1) {
			return ThrowException(Exception::Error(String::New(
					"This is not hexadecimal data.")));
		}

		*dst++ = b | (a << 4);
	}

	return buffer;
}

struct FromHexAction: UnaryAction<FromHexAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		const char* data = Buffer::Data(buffer);
		size_t length = Buffer::Length(buffer);
		return decodeHex(data, length, args, scope);
	}
};

struct ToHexAction: UnaryAction<ToHexAction> {
	Handle<Value> apply(Handle<Object>& buffer, const Arguments& args, HandleScope& scope) {
		const size_t size = Buffer::Length(buffer);
		const char* data = Buffer::Data(buffer);

		if (size == 0) {
			return String::Empty();
		}

		std::string s(size * 2, 0);
		for (size_t i = 0; i < size; ++i) {
			const uint8_t c = (uint8_t) data[i];
			s[i * 2] = toHexTable[c >> 4];
			s[i * 2 + 1] = toHexTable[c & 15];
		}

		return scope.Close(String::New(s.c_str(), s.size()));
	}
};

//
// V8 function callbacks
//
Handle<Value> Clear(const Arguments& args) {
	return ClearAction()(args);
}

Handle<Value> Fill(const Arguments& args) {
	return FillAction()(args);
}

Handle<Value> Reverse(const Arguments& args) {
	return ReverseAction()(args);
}

Handle<Value> Equals(const Arguments& args) {
	return EqualsAction()(args);
}

Handle<Value> Compare(const Arguments& args) {
	return CompareAction()(args);
}

Handle<Value> IndexOf(const Arguments& args) {
	return IndexOfAction()(args);
}

Handle<Value> FromHex(const Arguments& args) {
	return FromHexAction()(args);
}

Handle<Value> ToHex(const Arguments& args) {
	return ToHexAction()(args);
}

Handle<Value> Concat(const Arguments& args) {
	HandleScope scope;

	size_t size = 0;
	for (int index = 0, length = args.Length(); index < length; ++index) {
		Local<Value> arg = args[index];
		if (arg->IsString()) {
			// Utf8Length() because we need the length in bytes, not characters
			size += arg->ToString()->Utf8Length();
		}
		else if (Buffer::HasInstance(arg)) {
			size += Buffer::Length(arg->ToObject());
		}
		else {
			std::stringstream s;
			s << "Argument #" << index << " is neither a string nor a buffer object.";
			const char* message = s.str().c_str();
			return ThrowException(Exception::TypeError(String::New(message)));
		}
	}

	Buffer& dst = *Buffer::New(size);
	char* s = Buffer::Data(dst.handle_);

	for (int index = 0, length = args.Length(); index < length; ++index) {
		Local<Value> arg = args[index];
		if (arg->IsString()) {
			String::Utf8Value v(arg->ToString());
			memcpy(s, *v, v.length());
			s += v.length();
		}
		else if (Buffer::HasInstance(arg)) {
			Local<Object> b = arg->ToObject();
			const char* data = Buffer::Data(b);
			size_t length = Buffer::Length(b);
			memcpy(s, data, length);
			s += length;
		}
		else {
			return ThrowException(Exception::Error(String::New(
					"Congratulations! You have run into a bug: argument is neither a string nor a buffer object. "
					"Please make the world a better place and report it.")));
		}
	}

	return scope.Close(dst.handle_);
}

void RegisterModule(Handle<Object> target) {
	target->Set(String::NewSymbol("concat"),  FunctionTemplate::New(Concat)->GetFunction());
	target->Set(String::NewSymbol("fill"),    FunctionTemplate::New(Fill)->GetFunction());
	target->Set(String::NewSymbol("clear"),   FunctionTemplate::New(Clear)->GetFunction());
	target->Set(String::NewSymbol("reverse"), FunctionTemplate::New(Reverse)->GetFunction());
	target->Set(String::NewSymbol("equals"),  FunctionTemplate::New(Equals)->GetFunction());
	target->Set(String::NewSymbol("compare"), FunctionTemplate::New(Compare)->GetFunction());
	target->Set(String::NewSymbol("indexOf"), FunctionTemplate::New(IndexOf)->GetFunction());
	target->Set(String::NewSymbol("fromHex"), FunctionTemplate::New(FromHex)->GetFunction());
	target->Set(String::NewSymbol("toHex"),   FunctionTemplate::New(ToHex)->GetFunction());
}

} // anonymous namespace

NODE_MODULE(buffertools, RegisterModule);
<|endoftext|>


<commit_before>/*------------gauss_vis.cpp----------------------------------------------------/
*
* Purpose: Simple visualization script for difference scenes for computus video
*          2020
*
*   Notes: Compilation instructions:
*              g++ -L/path/to/GathVL -I/path/to/GathVL -lgathvl -o gauss_vis gauss_vis.cpp `pkg-config --cflags --libs cairo libavformat libavcodec libswresample libswscale libavutil` -Wl,-rpath,/path/to/GathVL
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <cmath>
#include <memory>
#include <vector>

#include "include/camera.h"
#include "include/scene.h"

void orbit_scene(camera& cam, scene& world, double end_frame, double timestep){

    color sun_clr = {1, 1, 0.5, 1};
    color earth_clr = {0, 1, 1, 1};
    color moon_clr = {0.5, 0.5, 0.5, 1};

    double earth_radius = 200;
    double moon_radius = 100;

    vec earth_offset = vec{sqrt(earth_radius*earth_radius/2),
                           sqrt(earth_radius*earth_radius/2)};

    vec moon_offset = vec{sqrt(moon_radius*moon_radius/2),
                          sqrt(moon_radius*moon_radius/2)};

    vec sun_loc = {world.size.x/2, world.size.y/2};
    vec earth_loc = sun_loc + earth_offset;
    vec moon_loc = earth_loc + moon_offset;

    auto sun = std::make_shared<ellipse>(sun_clr,
                                         sun_loc,
                                         vec{0,0}, 0, true);

    sun->add_animator<vec_animator>(0,20, &sun->size, vec{0,0}, vec{60,60});
    sun->add_animator<vec_animator>(20,25, &sun->size, vec{60,60}, vec{55,55});

    std::shared_ptr<ellipse> earths[3];
    std::shared_ptr<ellipse> moons[3];
    for (int i = 0; i < 3; ++i){
        earths[i] = std::make_shared<ellipse>(earth_clr, earth_loc,
                                             vec{0,0}, 0, true);

        earths[i]->add_animator<vec_animator>(10,30, &earths[i]->size,
                                              vec{0,0}, vec{30,30});
        earths[i]->add_animator<vec_animator>(30,35, &earths[i]->size,
                                              vec{30,30}, vec{25,25});

        moons[i] = std::make_shared<ellipse>(moon_clr, moon_loc,
                                             vec{0,0}, 0, true);

        moons[i]->add_animator<vec_animator>(20,40, &moons[i]->size,
                                             vec{0,0}, vec{15,15});
        moons[i]->add_animator<vec_animator>(40,45, &moons[i]->size,
                                             vec{15,15}, vec{10,10});
    }

    // Creating a theta for the earth that changes with time
    double earth_theta[2] = {M_PI/4, 0};
    double moon_theta[2] = {M_PI/4, 0};

    double earth_freq = 0.1;
    double moon_freq = earth_freq*365*12/354;

    // TODO: figure out exact number for lunar cycle
    double gregorian_year_frames = 2*M_PI/earth_freq/timestep;
    double lunar_year_frames = gregorian_year_frames*29.53*12/365.2524;
    int indices = 2;
    for (int i = 50; i < gregorian_year_frames + 51; ++i){
        //if (i > lunar_year_frames + 32){
        if (i == floor(lunar_year_frames) + 51){
            indices = 1;
            earth_theta[1] = fmod(earth_theta[0], 2*M_PI);
        }
        earth_theta[0] -= earth_freq*timestep;
        moon_theta[0] -= moon_freq*timestep + earth_freq*timestep;
        for (int j = 0; j < indices; ++j){
            vec new_loc = sun_loc + vec(earth_radius*cos(earth_theta[0]),
                                        earth_radius*sin(earth_theta[0]));
            earths[j]->add_animator<vec_animator>(i-1,i, &earths[j]->location,
                                                  earth_loc, new_loc);
            earth_loc = new_loc;

            new_loc = earth_loc + vec(moon_radius*cos(moon_theta[0]),
                                      moon_radius*sin(moon_theta[0]));
            moons[j]->add_animator<vec_animator>(i-1,i, &moons[j]->location,
                                                 moon_loc, new_loc);
            moon_loc = new_loc;
        }
    }
    moon_theta[1] = fmod(moon_theta[0], 2*M_PI);
    moon_theta[0] = M_PI/4;

    // Drawing the line for the Earths
    auto earth_arc = std::make_shared<arc>(sun_loc,
                                           vec(earth_radius,earth_radius),
                                           vec{0,0});
    earth_arc->add_animator<vec_animator>(50+gregorian_year_frames,
                                          80+gregorian_year_frames,
                                          &earth_arc->angles,
                                          vec{earth_theta[0], earth_theta[0]},
                                          vec{earth_theta[0], earth_theta[1]});

    // Drawing the line for the Earths
    auto moon_arc = std::make_shared<arc>(earth_loc,
                                          vec(moon_radius,moon_radius),
                                          vec{0,0});
    moon_arc->add_animator<vec_animator>(90+gregorian_year_frames,
                                         120+gregorian_year_frames,
                                         &moon_arc->angles,
                                         vec{moon_theta[1], moon_theta[1]},
                                         vec{moon_theta[1], moon_theta[0]});

    world.add_layer();
    world.add_layer();
    world.add_object(sun, 1);
    for (int i = 0; i < 3; ++i){
        world.add_object(earths[i], 1);
        world.add_object(moons[i], 1);
    }

    for (int i = 0; i < end_frame; ++i){
        world.update(i);
        if (i > 50+gregorian_year_frames){
            world.add_object(earth_arc, 1);
        }
        if (i > 90+gregorian_year_frames){
            world.add_object(moon_arc, 1);
        }
        cam.encode_frame(world);
    }
}

int main() {
    camera cam(vec{1280, 720});
    scene world = scene({1280, 720}, {0, 0, 0, 1});

    cam.add_encoder<video_encoder>("/tmp/video.mp4", cam.size, 60);

    orbit_scene(cam, world, 1000, 0.1);

    cam.clear_encoders();

    return 0;
}
<commit_msg>Adding 'complete' animation for synodic year<commit_after>/*------------gauss_vis.cpp----------------------------------------------------/
*
* Purpose: Simple visualization script for difference scenes for computus video
*          2020
*
*   Notes: Compilation instructions:
*              g++ -L/path/to/GathVL -I/path/to/GathVL -lgathvl -o gauss_vis gauss_vis.cpp `pkg-config --cflags --libs cairo libavformat libavcodec libswresample libswscale libavutil` -Wl,-rpath,/path/to/GathVL
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <cmath>
#include <memory>
#include <vector>

#include "include/camera.h"
#include "include/scene.h"

void orbit_scene(camera& cam, scene& world, double end_frame, double timestep){

    vec sun_size = {world.size.y*0.09, world.size.y*0.09};
    vec earth_size = {world.size.y*0.045, world.size.y*0.045};
    vec moon_size = {world.size.y*0.018, world.size.y*0.018};

    color sun_clr = {1, 1, 0.5, 1};
    color earth_clr = {0, 1, 1, 1};
    color moon_clr = {0.5, 0.5, 0.5, 1};

    double earth_radius = 200;
    double moon_radius = 100;

    vec earth_offset = vec{sqrt(earth_radius*earth_radius/2),
                           sqrt(earth_radius*earth_radius/2)};

    vec moon_offset = vec{sqrt(moon_radius*moon_radius/2),
                          sqrt(moon_radius*moon_radius/2)};

    vec sun_loc = {world.size.x/2, world.size.y/2};
    vec earth_loc[3] = {sun_loc + earth_offset, vec(0,0), vec(0,0)};
    vec moon_loc[3] = {earth_loc[0] + moon_offset, vec(0,0), vec(0,0)};

    // Don't Judge Me!
    for (int i = 1; i < 3; ++i){
        earth_loc[i] = earth_loc[0];
        moon_loc[i] = moon_loc[0];
    }

    auto sun = std::make_shared<ellipse>(sun_clr,
                                         sun_loc,
                                         vec{0,0}, 0, true);

    sun->add_animator<vec_animator>(0,20, &sun->size, vec{0,0},
                                    sun_size*1.1);
    sun->add_animator<vec_animator>(20,25, &sun->size, sun_size*1.1,
                                    sun_size);

    std::shared_ptr<ellipse> earth;
    std::shared_ptr<ellipse> moon;
    earth = std::make_shared<ellipse>(earth_clr, earth_loc[0],
                                     vec{0,0}, 0, true);

    earth->add_animator<vec_animator>(10,30, &earth->size,
                                      vec{0,0}, earth_size*1.1);
    earth->add_animator<vec_animator>(30,35, &earth->size,
                                      earth_size*1.1, earth_size);

    moon = std::make_shared<ellipse>(moon_clr, moon_loc[0],
                                     vec{0,0}, 0, true);

    moon->add_animator<vec_animator>(20,40, &moon->size,
                                     vec{0,0}, moon_size*1.1);
    moon->add_animator<vec_animator>(40,45, &moon->size,
                                     moon_size*1.1, moon_size);

    // Creating a theta for the earth that changes with time
    double earth_theta[2] = {M_PI/4, 0};
    double moon_theta[2] = {M_PI/4, 0};

    double earth_freq = 0.1;
    double moon_freq = earth_freq*365*12/354;

    double gregorian_year_frames = 2*M_PI/earth_freq/timestep;
    double lunar_year_frames = gregorian_year_frames*29.53*12/365.2524;
    int indices = 2;
    for (int i = 50; i < gregorian_year_frames + 51; ++i){
        //if (i > lunar_year_frames + 32){
        if (i == floor(lunar_year_frames) + 51){
            indices = 1;
            earth_theta[1] = fmod(earth_theta[0] + earth_freq*timestep, 2*M_PI);
        }
        earth_theta[0] -= earth_freq*timestep;
        moon_theta[0] -= (moon_freq + earth_freq)*timestep;
        for (int j = 0; j < indices; ++j){
            vec new_loc = sun_loc + vec(earth_radius*cos(earth_theta[0]),
                                        earth_radius*sin(earth_theta[0]));
            earth->add_animator<vec_animator>(i-1,i, &earth->location,
                                              earth_loc[0], new_loc);
            earth_loc[j] = new_loc;

            new_loc = earth_loc[0] + vec(moon_radius*cos(moon_theta[0]),
                                         moon_radius*sin(moon_theta[0]));
            moon->add_animator<vec_animator>(i-1,i, &moon->location,
                                             moon_loc[0], new_loc);
            moon_loc[j] = new_loc;
        }
    }
    moon_theta[1] = fmod(moon_theta[0] + (moon_freq+earth_freq)*timestep,
                         2*M_PI);
    moon_theta[0] = M_PI/4 + (moon_freq+earth_freq)*timestep;

    // Drawing the line for the Earths
    auto earth_arc = std::make_shared<arc>(sun_loc,
                                           vec(earth_radius,earth_radius),
                                           vec{0,0});
    earth_arc->add_animator<vec_animator>(50+gregorian_year_frames,
                                          80+gregorian_year_frames,
                                          &earth_arc->angles,
                                          vec{earth_theta[0], earth_theta[0]},
                                          vec{earth_theta[0], earth_theta[1]});

    // Drawing the line for the Earths
    auto moon_arc = std::make_shared<arc>(earth_loc[0],
                                          vec(moon_radius,moon_radius),
                                          vec{0,0});
    moon_arc->add_animator<vec_animator>(90+gregorian_year_frames,
                                         120+gregorian_year_frames,
                                         &moon_arc->angles,
                                         vec{moon_theta[1], moon_theta[1]},
                                         vec{moon_theta[1], moon_theta[0]});

    std::shared_ptr<arc> earth_shadows[2];
    std::shared_ptr<arc> moon_shadows[2];

    for (int i = 0; i < 2; ++i){
        earth_shadows[i] = std::make_shared<arc>(earth_loc[i+1],
                                                 earth_size*0.95,
                                                 vec{0,2*M_PI});
        moon_shadows[i] = std::make_shared<arc>(moon_loc[i+1],
                                                moon_size*0.95,
                                                vec{0,2*M_PI});
    }

    world.add_layer();
    world.add_layer();
    world.add_object(sun, 1);
    world.add_object(earth, 2);
    world.add_object(moon, 2);

    for (int i = 0; i < end_frame; ++i){
        world.update(i);
        if (i == 51){
            world.add_object(earth_shadows[1], 1);
            world.add_object(moon_shadows[1], 1);
        }
        if (i == floor(lunar_year_frames) + 51){
            world.add_object(earth_shadows[0], 1);
            world.add_object(moon_shadows[0], 1);
        }
        if (i == 50+floor(gregorian_year_frames)){
            world.add_object(earth_arc, 2);
        }
        if (i == 90+floor(gregorian_year_frames)){
            world.add_object(moon_arc, 2);
        }
        cam.encode_frame(world);
    }
}

int main() {
    camera cam(vec{1280, 720});
    scene world = scene({1280, 720}, {0, 0, 0, 1});

    cam.add_encoder<video_encoder>("/tmp/video.mp4", cam.size, 60);

    orbit_scene(cam, world, 1000, 0.1);

    cam.clear_encoders();

    return 0;
}
<|endoftext|>


<commit_before>/*
 *  dht11.c:
 *      Simple test program to test the wiringPi functions
 *      DHT11 test
 */

#include <wiringPi.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <string>
#include <iostream>
#include <fstream>

#define MAXTIMINGS      85
#define PARAM_ASSIGN_ERROR 22
int dht_buff_data[5] = { 0, 0, 0, 0, 0 };

void dht11_print(int DHTPIN, bool MACHINE_READABLE, bool SKIP, bool DEBUG, int DHVER, int dht_buff_data[5], uint8_t j, float f){
  /*
  * check we read 40 bits (8bit x 5 ) + verify checksum in the last byte
  */
  if ( (j >= 40) &&
          (dht_buff_data[4] == ( (dht_buff_data[0] + dht_buff_data[1] + dht_buff_data[2] + dht_buff_data[3]) & 0xFF) ) )
  {
      f = dht_buff_data[2] * 9. / 5. + 32;
      if(MACHINE_READABLE){
          printf( "%d.%d %d.%d\n",
                  dht_buff_data[0], dht_buff_data[1], dht_buff_data[2], dht_buff_data[3], f );
      }else{
          printf( "Humidity = %d.%d %% Temperature = %d.%d *C (%.1f *F)\n",
                  dht_buff_data[0], dht_buff_data[1], dht_buff_data[2], dht_buff_data[3], f );
      }
  }else if(!SKIP) {
      if(MACHINE_READABLE){
          printf("Error \n");
      }else{
          printf("Error reading data from sensor, skipping...\n");
      }
  }
}

void dht22_print(int DHTPIN, bool MACHINE_READABLE, bool SKIP, bool DEBUG, int DHVER, int dht_buff_data[5], uint8_t j, float f){
  // check we read 40 bits (8bit x 5 ) + verify checksum in the last byte
  if ((j >= 40) &&
      (dht_buff_data[4] == ((dht_buff_data[0] + dht_buff_data[1] + dht_buff_data[2] + dht_buff_data[3]) & 0xFF)) ) {
        float t, h;
        h = (float)dht_buff_data[0] * 256 + (float)dht_buff_data[1];
        h /= 10;
        t = (float)(dht_buff_data[2] & 0x7F)* 256 + (float)dht_buff_data[3];
        t /= 10.0;
        if ((dht_buff_data[2] & 0x80) != 0)  t *= -1;
    if(MACHINE_READABLE){
        printf("%.2f %% %.2f\n", h, t );
    }else{
        printf("Humidity = %.2f %% Temperature = %.2f *C \n", h, t );
    }
  }
  else if(!SKIP) {
      if(MACHINE_READABLE){
          printf("Error \n");
      }else{
          printf("Error reading data from sensor, skipping...\n");
      }
  }
}

void read_dht_buff_data(int DHTPIN, bool MACHINE_READABLE, bool SKIP, bool DEBUG, int DHVER)
{
    uint8_t laststate       = HIGH;
    uint8_t counter         = 0;
    uint8_t j               = 0, i;
    float   f; /* fahrenheit */

    dht_buff_data[0] = dht_buff_data[1] = dht_buff_data[2] = dht_buff_data[3] = dht_buff_data[4] = 0;

    /* pull pin down for 18 milliseconds */
    pinMode( DHTPIN, OUTPUT );
    digitalWrite( DHTPIN, LOW );
    delay( 18 );
    /* then pull it up for 40 microseconds */
    digitalWrite( DHTPIN, HIGH );
    delayMicroseconds( 40 );
    /* prepare to read the pin */
    pinMode( DHTPIN, INPUT );

    /* detect change and read data */
    for ( i = 0; i < MAXTIMINGS; i++ )
    {
        counter = 0;
        while ( digitalRead( DHTPIN ) == laststate )
        {
            counter++;
            delayMicroseconds( 1 );
            if ( counter == 255 )
            {
                    break;
            }
        }
        laststate = digitalRead( DHTPIN );

        // Print stream of data to terminal.
        if (DEBUG){
            printf("%d ", laststate);
        }

        if ( counter == 255 )
            break;

        /* ignore first 3 transitions */
        if ( (i >= 4) && (i % 2 == 0) )
        {
            /* shove each bit into the storage bytes */
            dht_buff_data[j / 8] <<= 1;
            if ( counter > 16 )
                    dht_buff_data[j / 8] |= 1;
            j++;
        }
    }

    // Depending the version how we print out the data.
    if (DHVER == 11){
      dht11_print(DHTPIN, MACHINE_READABLE, SKIP, DEBUG, DHVER, dht_buff_data, j, f);
    }else{
      dht22_print(DHTPIN, MACHINE_READABLE, SKIP, DEBUG, DHVER, dht_buff_data, j, f);
    }
}

int main( int argc, char *argv[] )
{
    int interval = 1000;
    int opt;
    bool skip = false;
    bool machineReadable = false;
    bool justOne = false;
    bool debug = false;
    int dataPin = 7;
    int version = 11;
    while ((opt = getopt(argc, argv, "MDJI:V:P:s")) != -1) {
        switch (opt) {
            case 'I':
                interval = atoi(optarg) * 1000;
                break;
            case 'M':
                machineReadable = true;
                break;
            case 'P':
                dataPin = atoi(optarg);
                break;
            case 'J':
                justOne = true;
                break;
            case 'D':
                debug = true;
                break;
            case 'V':
              version = atoi(optarg);
              break;
	    case 's':
		skip = true;
		break;
            case ':':
                /* missing option argument */
                fprintf(stderr, "%s: option '-%c' requires an argument\n",
                        argv[0], optopt);
                exit(PARAM_ASSIGN_ERROR);
                break;
            case '?':
            default:
                printf( "Raspberry Pi wiringPi DHT11 Temperature test program\n" );
                printf( "I number is the interval to run [Seconds].\n" );
                printf( "M flag to set machine readable which is [Humidity Temperature]\n" );
                printf( "P number is the data pin to use, default is 7\n" );
                printf( "J is just one value pair, for scripting mainly...\n" );
                printf( "D Will print everything in the pin out...\n" );
                printf( "V Sensor version, default 11...\n" );
        }
    }

    if ( wiringPiSetup() == -1 )
        exit( 1 );

    if ( justOne ){
        read_dht_buff_data(dataPin, machineReadable, skip, debug, version);
    }else{
        while ( 1 )
        {
            read_dht_buff_data(dataPin, machineReadable, skip, debug, version);
            delay(interval); /* wait 1sec to refresh */
        }
    }
    return(0);
}
<commit_msg>Removed % from print out, and removed extra spaces.<commit_after>/*
 *  dht11.c:
 *      Simple test program to test the wiringPi functions
 *      DHT11 test
 */

#include <wiringPi.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <string>
#include <iostream>
#include <fstream>

#define MAXTIMINGS      85
#define PARAM_ASSIGN_ERROR 22
int dht_buff_data[5] = { 0, 0, 0, 0, 0 };

void dht11_print(int DHTPIN, bool MACHINE_READABLE, bool SKIP, bool DEBUG, int DHVER, int dht_buff_data[5], uint8_t j, float f){
  /*
  * check we read 40 bits (8bit x 5 ) + verify checksum in the last byte
  */
  if ( (j >= 40) &&
          (dht_buff_data[4] == ( (dht_buff_data[0] + dht_buff_data[1] + dht_buff_data[2] + dht_buff_data[3]) & 0xFF) ) )
  {
      f = dht_buff_data[2] * 9. / 5. + 32;
      if(MACHINE_READABLE){
          printf( "%d.%d %d.%d\n",
                  dht_buff_data[0], dht_buff_data[1], dht_buff_data[2], dht_buff_data[3], f );
      }else{
          printf( "Humidity = %d.%d Temperature = %d.%d *C (%.1f *F)\n",
                  dht_buff_data[0], dht_buff_data[1], dht_buff_data[2], dht_buff_data[3], f );
      }
  }else if(!SKIP) {
      if(MACHINE_READABLE){
          printf("Error \n");
      }else{
          printf("Error reading data from sensor, skipping...\n");
      }
  }
}

void dht22_print(int DHTPIN, bool MACHINE_READABLE, bool SKIP, bool DEBUG, int DHVER, int dht_buff_data[5], uint8_t j, float f){
  // check we read 40 bits (8bit x 5 ) + verify checksum in the last byte
  if ((j >= 40) &&
      (dht_buff_data[4] == ((dht_buff_data[0] + dht_buff_data[1] + dht_buff_data[2] + dht_buff_data[3]) & 0xFF)) ) {
        float t, h;
        h = (float)dht_buff_data[0] * 256 + (float)dht_buff_data[1];
        h /= 10;
        t = (float)(dht_buff_data[2] & 0x7F)* 256 + (float)dht_buff_data[3];
        t /= 10.0;
        if ((dht_buff_data[2] & 0x80) != 0)  t *= -1;
    if(MACHINE_READABLE){
        printf("%.2f %.2f\n", h, t );
    }else{
        printf("Humidity = %.2f Temperature = %.2f *C \n", h, t );
    }
  }
  else if(!SKIP) {
      if(MACHINE_READABLE){
          printf("Error \n");
      }else{
          printf("Error reading data from sensor, skipping...\n");
      }
  }
}

void read_dht_buff_data(int DHTPIN, bool MACHINE_READABLE, bool SKIP, bool DEBUG, int DHVER)
{
    uint8_t laststate       = HIGH;
    uint8_t counter         = 0;
    uint8_t j               = 0, i;
    float   f; /* fahrenheit */

    dht_buff_data[0] = dht_buff_data[1] = dht_buff_data[2] = dht_buff_data[3] = dht_buff_data[4] = 0;

    /* pull pin down for 18 milliseconds */
    pinMode( DHTPIN, OUTPUT );
    digitalWrite( DHTPIN, LOW );
    delay( 18 );
    /* then pull it up for 40 microseconds */
    digitalWrite( DHTPIN, HIGH );
    delayMicroseconds( 40 );
    /* prepare to read the pin */
    pinMode( DHTPIN, INPUT );

    /* detect change and read data */
    for ( i = 0; i < MAXTIMINGS; i++ )
    {
        counter = 0;
        while ( digitalRead( DHTPIN ) == laststate )
        {
            counter++;
            delayMicroseconds( 1 );
            if ( counter == 255 )
            {
                    break;
            }
        }
        laststate = digitalRead( DHTPIN );

        // Print stream of data to terminal.
        if (DEBUG){
            printf("%d ", laststate);
        }

        if ( counter == 255 )
            break;

        /* ignore first 3 transitions */
        if ( (i >= 4) && (i % 2 == 0) )
        {
            /* shove each bit into the storage bytes */
            dht_buff_data[j / 8] <<= 1;
            if ( counter > 16 )
                    dht_buff_data[j / 8] |= 1;
            j++;
        }
    }

    // Depending the version how we print out the data.
    if (DHVER == 11){
      dht11_print(DHTPIN, MACHINE_READABLE, SKIP, DEBUG, DHVER, dht_buff_data, j, f);
    }else{
      dht22_print(DHTPIN, MACHINE_READABLE, SKIP, DEBUG, DHVER, dht_buff_data, j, f);
    }
}

int main( int argc, char *argv[] )
{
    int interval = 1000;
    int opt;
    bool skip = false;
    bool machineReadable = false;
    bool justOne = false;
    bool debug = false;
    int dataPin = 7;
    int version = 11;
    while ((opt = getopt(argc, argv, "MDJI:V:P:s")) != -1) {
        switch (opt) {
            case 'I':
                interval = atoi(optarg) * 1000;
                break;
            case 'M':
                machineReadable = true;
                break;
            case 'P':
                dataPin = atoi(optarg);
                break;
            case 'J':
                justOne = true;
                break;
            case 'D':
                debug = true;
                break;
            case 'V':
              version = atoi(optarg);
              break;
	    case 's':
		skip = true;
		break;
            case ':':
                /* missing option argument */
                fprintf(stderr, "%s: option '-%c' requires an argument\n",
                        argv[0], optopt);
                exit(PARAM_ASSIGN_ERROR);
                break;
            case '?':
            default:
                printf( "Raspberry Pi wiringPi DHT11 Temperature test program\n" );
                printf( "I number is the interval to run [Seconds].\n" );
                printf( "M flag to set machine readable which is [Humidity Temperature]\n" );
                printf( "P number is the data pin to use, default is 7\n" );
                printf( "J is just one value pair, for scripting mainly...\n" );
                printf( "D Will print everything in the pin out...\n" );
                printf( "V Sensor version, default 11...\n" );
        }
    }

    if ( wiringPiSetup() == -1 )
        exit( 1 );

    if ( justOne ){
        read_dht_buff_data(dataPin, machineReadable, skip, debug, version);
    }else{
        while ( 1 )
        {
            read_dht_buff_data(dataPin, machineReadable, skip, debug, version);
            delay(interval); /* wait 1sec to refresh */
        }
    }
    return(0);
}
<|endoftext|>