<commit_before>/*************************************************************************
 *
 *  $RCSfile: iderdll2.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2004-07-23 12:05:11 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _IDERDLL2_HXX
#define _IDERDLL2_HXX

class StarBASIC;
class SvxSearchItem;
class Accelerator;

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif

#ifndef _GEN_HXX //autogen
#include <tools/gen.hxx>
#endif

#ifndef _LINK_HXX //autogen
#include <tools/link.hxx>
#endif

#include <bastypes.hxx>
#include <bastype2.hxx>

#define INVPOSITION 0x7fff

class BasicIDEData
{
private:
    Accelerator*    pAccelerator;
    SvxSearchItem*  pSearchItem;

    LibInfos        aLibInfos;

    BasicEntryDescriptor    m_aLastEntryDesc;

    Point           aObjCatPos;
    Size            aObjCatSize;

    String          aAddLibPath;
    String          aAddLibFilter;

    USHORT          nBasicDialogCount;

    BOOL            OLD_bRelMacroRecording;
    BOOL            bChoosingMacro;
    BOOL            bShellInCriticalSection;

    void            InitAccelerator();

protected:
    DECL_LINK( GlobalBasicBreakHdl, StarBASIC * );

public:
                            BasicIDEData();
                            ~BasicIDEData();

    LibInfos&               GetLibInfos() { return aLibInfos; }

    BasicEntryDescriptor&   GetLastEntryDescriptor()    { return m_aLastEntryDesc; }
    void                    SetLastEntryDescriptor( BasicEntryDescriptor& rDesc ) { m_aLastEntryDesc = rDesc; }

    BOOL&                   ChoosingMacro()             { return bChoosingMacro; }
    BOOL&                   ShellInCriticalSection()    { return bShellInCriticalSection; }

    USHORT                  GetBasicDialogCount() const { return nBasicDialogCount; }
    void                    IncBasicDialogCount()       { nBasicDialogCount++; }
    void                    DecBasicDialogCount()       { nBasicDialogCount--; }

    SvxSearchItem&          GetSearchItem() const;
    void                    SetSearchItem( const SvxSearchItem& rItem );

    void                    SetObjectCatalogPos( const Point& rPnt )
                                { aObjCatPos = rPnt; }
    const Point&            GetObjectCatalogPos() const
                                { return aObjCatPos; }

    void                    SetObjectCatalogSize( const Size& rSize )
                                { aObjCatSize = rSize; }
    const Size&             GetObjectCatalogSize() const
                                { return aObjCatSize; }

    const String&           GetAddLibPath() const   { return aAddLibPath; }
    void                    SetAddLibPath( const String& rPath ) { aAddLibPath = rPath; }

    const String&           GetAddLibFilter() const { return aAddLibFilter; }
    void                    SetAddLibFilter( const String& rFilter )  { aAddLibFilter = rFilter; }

    Accelerator*            GetAccelerator()
                            {
                                if ( !pAccelerator )
                                    InitAccelerator();
                                return pAccelerator;
                            }

    DECL_LINK( ExecuteMacroEvent, void * );
};

#endif //_IDERDLL2_HXX
<commit_msg>INTEGRATION: CWS ooo19126 (1.3.140); FILE MERGED 2005/09/05 13:55:37 rt 1.3.140.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: iderdll2.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 20:04:10 $
 *
 *  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 _IDERDLL2_HXX
#define _IDERDLL2_HXX

class StarBASIC;
class SvxSearchItem;
class Accelerator;

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif

#ifndef _GEN_HXX //autogen
#include <tools/gen.hxx>
#endif

#ifndef _LINK_HXX //autogen
#include <tools/link.hxx>
#endif

#include <bastypes.hxx>
#include <bastype2.hxx>

#define INVPOSITION 0x7fff

class BasicIDEData
{
private:
    Accelerator*    pAccelerator;
    SvxSearchItem*  pSearchItem;

    LibInfos        aLibInfos;

    BasicEntryDescriptor    m_aLastEntryDesc;

    Point           aObjCatPos;
    Size            aObjCatSize;

    String          aAddLibPath;
    String          aAddLibFilter;

    USHORT          nBasicDialogCount;

    BOOL            OLD_bRelMacroRecording;
    BOOL            bChoosingMacro;
    BOOL            bShellInCriticalSection;

    void            InitAccelerator();

protected:
    DECL_LINK( GlobalBasicBreakHdl, StarBASIC * );

public:
                            BasicIDEData();
                            ~BasicIDEData();

    LibInfos&               GetLibInfos() { return aLibInfos; }

    BasicEntryDescriptor&   GetLastEntryDescriptor()    { return m_aLastEntryDesc; }
    void                    SetLastEntryDescriptor( BasicEntryDescriptor& rDesc ) { m_aLastEntryDesc = rDesc; }

    BOOL&                   ChoosingMacro()             { return bChoosingMacro; }
    BOOL&                   ShellInCriticalSection()    { return bShellInCriticalSection; }

    USHORT                  GetBasicDialogCount() const { return nBasicDialogCount; }
    void                    IncBasicDialogCount()       { nBasicDialogCount++; }
    void                    DecBasicDialogCount()       { nBasicDialogCount--; }

    SvxSearchItem&          GetSearchItem() const;
    void                    SetSearchItem( const SvxSearchItem& rItem );

    void                    SetObjectCatalogPos( const Point& rPnt )
                                { aObjCatPos = rPnt; }
    const Point&            GetObjectCatalogPos() const
                                { return aObjCatPos; }

    void                    SetObjectCatalogSize( const Size& rSize )
                                { aObjCatSize = rSize; }
    const Size&             GetObjectCatalogSize() const
                                { return aObjCatSize; }

    const String&           GetAddLibPath() const   { return aAddLibPath; }
    void                    SetAddLibPath( const String& rPath ) { aAddLibPath = rPath; }

    const String&           GetAddLibFilter() const { return aAddLibFilter; }
    void                    SetAddLibFilter( const String& rFilter )  { aAddLibFilter = rFilter; }

    Accelerator*            GetAccelerator()
                            {
                                if ( !pAccelerator )
                                    InitAccelerator();
                                return pAccelerator;
                            }

    DECL_LINK( ExecuteMacroEvent, void * );
};

#endif //_IDERDLL2_HXX
<|endoftext|>


<commit_before>using namespace GeFiCa;
// draw V, E distributions saved in an input ROOT file
void drawFields(const char *input="ppc.root")
{
   // Get data from input file
   TFile *file = new TFile(input, "update"); // "update" allows creation of TH3
   PointContactDZ *detector = (PointContactDZ*) file->Get("pcdz");
   TTree *t = detector->GetTree(true);
   const int n = t->GetEntries();

   // fine tune margins, etc.
   gStyle->SetTitleOffset(0.6,"Y");
   gStyle->SetPadRightMargin(0.12);
   gStyle->SetPadLeftMargin(0.07);

   // generate plots
   TCanvas *cv = new TCanvas;
   //cv->SetLogz();
   t->Draw("c1:c2:v","","goff");
   TGraph2D *gv = new TGraph2D(n, t->GetV1(), t->GetV2(), t->GetV3());
   gv->SetName("gv"); gv->SetNpx(500); gv->SetNpy(500); // fine bin histogram
   TH2D *hv = gv->GetHistogram();
   hv->SetTitle(";Radius [cm];Height [cm];Potential [V]");
   hv->GetZaxis()->CenterTitle();
   hv->Draw("colz");

   TCanvas *ce = new TCanvas;
   ce->SetLogz();
   t->Draw("c1:c2:e","","goff");
   TGraph2D *ge = new TGraph2D(n, t->GetV1(), t->GetV2(), t->GetV3());
   ge->SetName("ge"); ge->SetNpx(500); ge->SetNpy(500); // fine bin histogram
   TH2D *he = ge->GetHistogram();
   he->SetTitle(";Radius [cm];Height [cm];E [V/cm]");
   he->GetZaxis()->CenterTitle();
   he->Draw("colz");
}
<commit_msg>added debug switch<commit_after>using namespace GeFiCa;
// draw V, E distributions saved in an input ROOT file
void drawFields(const char *input="ppc.root")
{
   // Get data from input file
   TFile *file = new TFile(input, "update"); // "update" allows creation of TH3
   PointContactDZ *detector = (PointContactDZ*) file->Get("pcdz");
   TTree *t = detector->GetTree(true);
   const int n = t->GetEntries();

   // fine tune margins, etc.
   gStyle->SetTitleOffset(0.6,"Y");
   gStyle->SetPadRightMargin(0.12);
   gStyle->SetPadLeftMargin(0.07);

   // generate plots
   TCanvas *cv = new TCanvas;
   //cv->SetLogz();
   t->Draw("c1:c2:v","","goff");
   TGraph2D *gv = new TGraph2D(n, t->GetV1(), t->GetV2(), t->GetV3());
   gv->SetName("gv"); gv->SetNpx(500); gv->SetNpy(500); // fine bin histogram
   TH2D *hv = gv->GetHistogram();
   hv->SetTitle(";Radius [cm];Height [cm];Potential [V]");
   hv->GetZaxis()->CenterTitle();
   hv->Draw("colz");

   TCanvas *ce = new TCanvas;
   ce->SetLogz();
   t->Draw("c1:c2:e","","goff");
   TGraph2D *ge = new TGraph2D(n, t->GetV1(), t->GetV2(), t->GetV3());
   ge->SetName("ge"); ge->SetNpx(500); ge->SetNpy(500); // fine bin histogram
   TH2D *he = ge->GetHistogram();
   he->SetTitle(";Radius [cm];Height [cm];E [V/cm]");
   he->GetZaxis()->CenterTitle();
   he->Draw("colz");

   gDebug=1;
   TGraph *g1 = detector->GetFieldLineFrom(3*cm, 1*cm);
   g1->Draw("pl");
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "TestHarness.h"
#include "TestInstaller.h"

// this is file scope because the test is installed
// with all other tests, which also happen to be
// created as static instances at file scope

static NullTest nullTest;

TEST_GROUP(TestInstaller)
  {
  TestInstaller* testInstaller;
	TestRegistry* myRegistry;
  TEST_SETUP()
  {
  	myRegistry = new TestRegistry();
  	myRegistry->setCurrentRegistry(myRegistry);
    testInstaller = new TestInstaller(&nullTest, "TestInstaller", "test", __FILE__, __LINE__);
  }
  TEST_TEARDOWN()
  {
  	myRegistry->setCurrentRegistry(0);
    testInstaller->unDo();
    delete testInstaller;
  	delete myRegistry;
  }
};

TEST(TestInstaller, Create)
{}

<commit_msg>Removed TestInstaller<commit_after>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "TestHarness.h"

// this is file scope because the test is installed
// with all other tests, which also happen to be
// created as static instances at file scope

static NullTest nullTest;

TEST_GROUP(TestInstaller)
  {
  TestInstaller* testInstaller;
	TestRegistry* myRegistry;
  TEST_SETUP()
  {
  	myRegistry = new TestRegistry();
  	myRegistry->setCurrentRegistry(myRegistry);
    testInstaller = new TestInstaller(&nullTest, "TestInstaller", "test", __FILE__, __LINE__);
  }
  TEST_TEARDOWN()
  {
  	myRegistry->setCurrentRegistry(0);
    testInstaller->unDo();
    delete testInstaller;
  	delete myRegistry;
  }
};

TEST(TestInstaller, Create)
{}

<|endoftext|>


<commit_before>// Copyright 2012 Cloudera Inc.
//
// 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 "statestore/query-schedule.h"

#include <sstream>
#include <boost/algorithm/string/join.hpp>
#include <boost/foreach.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>

#include "util/container-util.h"
#include "util/network-util.h"
#include "util/uid-util.h"
#include "util/debug-util.h"

using namespace std;
using namespace boost;
using namespace boost::algorithm;
using namespace boost::uuids;
using namespace impala;

namespace impala {

// Default value for the request_timeout in a reservation request. The timeout is the
// max time in milliseconds to wait for a resource request to be fulfilled by Llama.
const int64_t DEFAULT_REQUEST_TIMEOUT = 60000;

QuerySchedule::QuerySchedule(const TUniqueId& query_id,
    const TQueryExecRequest& request, const TQueryOptions& query_options,
    bool is_mini_llama)
  : query_id_(query_id),
    request_(request),
    query_options_(query_options),
    is_mini_llama_(is_mini_llama),
    num_backends_(0),
    num_scan_ranges_(0) {
  fragment_exec_params_.resize(request.fragments.size());
  // map from plan node id to fragment index in exec_request.fragments
  vector<PlanNodeId> per_node_fragment_idx;
  for (int i = 0; i < request.fragments.size(); ++i) {
    BOOST_FOREACH(const TPlanNode& node, request.fragments[i].plan.nodes) {
      if (plan_node_to_fragment_idx_.size() < node.node_id + 1) {
        plan_node_to_fragment_idx_.resize(node.node_id + 1);
      }
      plan_node_to_fragment_idx_[node.node_id] = i;
    }
  }
}

void QuerySchedule::GetResourceHostport(const TNetworkAddress& src,
    TNetworkAddress* dest) {
  if (is_mini_llama_) {
    *dest = impalad_to_dn_[src];
  } else {
    dest->hostname = src.hostname;
    dest->port = 0;
  }
}

void QuerySchedule::CreateMiniLlamaMapping(const vector<string>& llama_nodes) {
  DCHECK(is_mini_llama_);
  DCHECK(!llama_nodes.empty());
  int llama_node_ix = 0;
  BOOST_FOREACH(const TNetworkAddress& host, unique_hosts_) {
    TNetworkAddress dn_hostport = MakeNetworkAddress(llama_nodes[llama_node_ix]);
    impalad_to_dn_[host] = dn_hostport;
    dn_to_impalad_[dn_hostport] = host;
    // Round robin the registered Llama nodes.
    ++llama_node_ix;
    llama_node_ix = llama_node_ix % llama_nodes.size();
  }
}

void QuerySchedule::CreateReservationRequest(const string& pool,
    const vector<string>& llama_nodes) {
  yarn_pool_ = pool;
  DCHECK(reservation_request_.get() == NULL);
  reservation_request_.reset(new TResourceBrokerReservationRequest());
  reservation_request_->resources.clear();
  reservation_request_->version = TResourceBrokerServiceVersion::V1;
  reservation_request_->queue = pool;
  reservation_request_->gang = true;

  // Set optional request timeout from query options.
  if (query_options_.__isset.reservation_request_timeout) {
    DCHECK_GT(query_options_.reservation_request_timeout, 0);
    reservation_request_->__set_request_timeout(
        query_options_.reservation_request_timeout);
  }

  // Set the per-host requested memory and virtual CPU cores.
  // Prefer the manual overrides from the query options over the
  // estimation given in the request.
  // TODO: Remove default values. Not having an estimate or a query option
  // should be an error.
  int32_t memory_mb = 4096;
  if (query_options_.__isset.mem_limit && query_options_.mem_limit > 0) {
    memory_mb = max(1L, query_options_.mem_limit / (1024 * 1024));
  } else if (request_.__isset.per_host_mem_req) {
    memory_mb = request_.per_host_mem_req / (1024 * 1024);
  }
  int16_t v_cpu_cores = 2;
  if (query_options_.__isset.v_cpu_cores && query_options_.v_cpu_cores > 0) {
    v_cpu_cores = query_options_.v_cpu_cores;
  } else if (request_.__isset.per_host_vcores) {
    v_cpu_cores = request_.per_host_vcores;
  }

  // Set the reservation timeout from the query options or use a default.
  int64_t timeout = DEFAULT_REQUEST_TIMEOUT;
  if (query_options_.__isset.reservation_request_timeout) {
    timeout = query_options_.reservation_request_timeout;
  }
  reservation_request_->__set_request_timeout(timeout);

  // The memory_mb and v_cpu_cores estimates may legitimately be zero,
  // e.g., for constant selects. Do not reserve any resources in those cases.
  if (memory_mb == 0 && v_cpu_cores == 0) return;

  if (is_mini_llama_) CreateMiniLlamaMapping(llama_nodes);

  random_generator uuid_generator;
  BOOST_FOREACH(const TNetworkAddress& host, unique_hosts_) {
    reservation_request_->resources.push_back(llama::TResource());
    llama::TResource& resource = reservation_request_->resources.back();
    uuid id = uuid_generator();
    resource.client_resource_id.hi = *reinterpret_cast<uint64_t*>(&id.data[0]);
    resource.client_resource_id.lo = *reinterpret_cast<uint64_t*>(&id.data[8]);
    resource.enforcement = llama::TLocationEnforcement::MUST;

    stringstream ss;
    TNetworkAddress resource_hostport;
    GetResourceHostport(host, &resource_hostport);
    ss << resource_hostport;
    resource.askedLocation = ss.str();
    resource.memory_mb = memory_mb;
    resource.v_cpu_cores = v_cpu_cores;
  }
}

Status QuerySchedule::ValidateReservation() {
  if (!HasReservation()) return Status("Query schedule does not have a reservation.");
  vector<TNetworkAddress> hosts_missing_resources;
  BOOST_FOREACH(const FragmentExecParams& params, fragment_exec_params_) {
    BOOST_FOREACH(const TNetworkAddress& host, params.hosts) {
      // Ignore the coordinator host which is not contained in unique_hosts_.
      if (unique_hosts_.find(host) == unique_hosts_.end()) continue;
      TNetworkAddress resource_hostport;
      GetResourceHostport(host, &resource_hostport);
      if (reservation_.allocated_resources.find(resource_hostport) ==
          reservation_.allocated_resources.end()) {
        hosts_missing_resources.push_back(host);
      }
    }
  }
  if (!hosts_missing_resources.empty()) {
    stringstream ss;
    ss << "Failed to validate reservation " << reservation_.reservation_id << "." << endl
       << "Missing resources for hosts [";
    for (int i = 0; i < hosts_missing_resources.size(); ++i) {
      ss << hosts_missing_resources[i];
      if (i + 1 !=  hosts_missing_resources.size()) ss << ", ";
    }
    ss << "]";
    return Status(ss.str());
  }
  return Status::OK;
}

}
<commit_msg>[CDH5->CDH4] Change default reservation request timeout to 5 minutes.<commit_after>// Copyright 2012 Cloudera Inc.
//
// 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 "statestore/query-schedule.h"

#include <sstream>
#include <boost/algorithm/string/join.hpp>
#include <boost/foreach.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>

#include "util/container-util.h"
#include "util/network-util.h"
#include "util/uid-util.h"
#include "util/debug-util.h"

using namespace std;
using namespace boost;
using namespace boost::algorithm;
using namespace boost::uuids;
using namespace impala;

namespace impala {

// Default value for the request_timeout in a reservation request. The timeout is the
// max time in milliseconds to wait for a resource request to be fulfilled by Llama.
// The default value of five minutes was determined to be reasonable based on
// experiments on a 20-node cluster with TPCDS 15TB and 8 concurrent clients.
// Over 30% of queries timed out with a reservation timeout of 1 minute but only less
// than 5% timed out when using 5 minutes. Still, the default value is somewhat
// arbitrary and a good value is workload dependent.
const int64_t DEFAULT_REQUEST_TIMEOUT_MS = 5 * 60 * 1000;

QuerySchedule::QuerySchedule(const TUniqueId& query_id,
    const TQueryExecRequest& request, const TQueryOptions& query_options,
    bool is_mini_llama)
  : query_id_(query_id),
    request_(request),
    query_options_(query_options),
    is_mini_llama_(is_mini_llama),
    num_backends_(0),
    num_scan_ranges_(0) {
  fragment_exec_params_.resize(request.fragments.size());
  // map from plan node id to fragment index in exec_request.fragments
  vector<PlanNodeId> per_node_fragment_idx;
  for (int i = 0; i < request.fragments.size(); ++i) {
    BOOST_FOREACH(const TPlanNode& node, request.fragments[i].plan.nodes) {
      if (plan_node_to_fragment_idx_.size() < node.node_id + 1) {
        plan_node_to_fragment_idx_.resize(node.node_id + 1);
      }
      plan_node_to_fragment_idx_[node.node_id] = i;
    }
  }
}

void QuerySchedule::GetResourceHostport(const TNetworkAddress& src,
    TNetworkAddress* dest) {
  if (is_mini_llama_) {
    *dest = impalad_to_dn_[src];
  } else {
    dest->hostname = src.hostname;
    dest->port = 0;
  }
}

void QuerySchedule::CreateMiniLlamaMapping(const vector<string>& llama_nodes) {
  DCHECK(is_mini_llama_);
  DCHECK(!llama_nodes.empty());
  int llama_node_ix = 0;
  BOOST_FOREACH(const TNetworkAddress& host, unique_hosts_) {
    TNetworkAddress dn_hostport = MakeNetworkAddress(llama_nodes[llama_node_ix]);
    impalad_to_dn_[host] = dn_hostport;
    dn_to_impalad_[dn_hostport] = host;
    // Round robin the registered Llama nodes.
    ++llama_node_ix;
    llama_node_ix = llama_node_ix % llama_nodes.size();
  }
}

void QuerySchedule::CreateReservationRequest(const string& pool,
    const vector<string>& llama_nodes) {
  yarn_pool_ = pool;
  DCHECK(reservation_request_.get() == NULL);
  reservation_request_.reset(new TResourceBrokerReservationRequest());
  reservation_request_->resources.clear();
  reservation_request_->version = TResourceBrokerServiceVersion::V1;
  reservation_request_->queue = pool;
  reservation_request_->gang = true;

  // Set optional request timeout from query options.
  if (query_options_.__isset.reservation_request_timeout) {
    DCHECK_GT(query_options_.reservation_request_timeout, 0);
    reservation_request_->__set_request_timeout(
        query_options_.reservation_request_timeout);
  }

  // Set the per-host requested memory and virtual CPU cores.
  // Prefer the manual overrides from the query options over the
  // estimation given in the request.
  // TODO: Remove default values. Not having an estimate or a query option
  // should be an error.
  int32_t memory_mb = 4096;
  if (query_options_.__isset.mem_limit && query_options_.mem_limit > 0) {
    memory_mb = max(1L, query_options_.mem_limit / (1024 * 1024));
  } else if (request_.__isset.per_host_mem_req) {
    memory_mb = request_.per_host_mem_req / (1024 * 1024);
  }
  int16_t v_cpu_cores = 2;
  if (query_options_.__isset.v_cpu_cores && query_options_.v_cpu_cores > 0) {
    v_cpu_cores = query_options_.v_cpu_cores;
  } else if (request_.__isset.per_host_vcores) {
    v_cpu_cores = request_.per_host_vcores;
  }

  // Set the reservation timeout from the query options or use a default.
  int64_t timeout = DEFAULT_REQUEST_TIMEOUT_MS;
  if (query_options_.__isset.reservation_request_timeout) {
    timeout = query_options_.reservation_request_timeout;
  }
  reservation_request_->__set_request_timeout(timeout);

  // The memory_mb and v_cpu_cores estimates may legitimately be zero,
  // e.g., for constant selects. Do not reserve any resources in those cases.
  if (memory_mb == 0 && v_cpu_cores == 0) return;

  if (is_mini_llama_) CreateMiniLlamaMapping(llama_nodes);

  random_generator uuid_generator;
  BOOST_FOREACH(const TNetworkAddress& host, unique_hosts_) {
    reservation_request_->resources.push_back(llama::TResource());
    llama::TResource& resource = reservation_request_->resources.back();
    uuid id = uuid_generator();
    resource.client_resource_id.hi = *reinterpret_cast<uint64_t*>(&id.data[0]);
    resource.client_resource_id.lo = *reinterpret_cast<uint64_t*>(&id.data[8]);
    resource.enforcement = llama::TLocationEnforcement::MUST;

    stringstream ss;
    TNetworkAddress resource_hostport;
    GetResourceHostport(host, &resource_hostport);
    ss << resource_hostport;
    resource.askedLocation = ss.str();
    resource.memory_mb = memory_mb;
    resource.v_cpu_cores = v_cpu_cores;
  }
}

Status QuerySchedule::ValidateReservation() {
  if (!HasReservation()) return Status("Query schedule does not have a reservation.");
  vector<TNetworkAddress> hosts_missing_resources;
  BOOST_FOREACH(const FragmentExecParams& params, fragment_exec_params_) {
    BOOST_FOREACH(const TNetworkAddress& host, params.hosts) {
      // Ignore the coordinator host which is not contained in unique_hosts_.
      if (unique_hosts_.find(host) == unique_hosts_.end()) continue;
      TNetworkAddress resource_hostport;
      GetResourceHostport(host, &resource_hostport);
      if (reservation_.allocated_resources.find(resource_hostport) ==
          reservation_.allocated_resources.end()) {
        hosts_missing_resources.push_back(host);
      }
    }
  }
  if (!hosts_missing_resources.empty()) {
    stringstream ss;
    ss << "Failed to validate reservation " << reservation_.reservation_id << "." << endl
       << "Missing resources for hosts [";
    for (int i = 0; i < hosts_missing_resources.size(); ++i) {
      ss << hosts_missing_resources[i];
      if (i + 1 !=  hosts_missing_resources.size()) ss << ", ";
    }
    ss << "]";
    return Status(ss.str());
  }
  return Status::OK;
}

}
<|endoftext|>


<commit_before>#pragma once
#include <numeric>
#include <type_traits>
#include <utility>
#include <functional>
#include <string>
#include <cstring>
#include <cassert>
#include <tuple>
#include <vector>
#if __cplusplus <= 201402L
#include <experimental/optional>
namespace std { using namespace std::experimental; }
#else
#include <optional>
#endif

namespace bw
{
	template<template<class...> class TT, class X> constexpr bool is_same_template = false;
	template<template<class...> class TT, class... P> constexpr bool is_same_template<TT, TT<P...>> = true;

	struct Reader
	{
		Reader(const char* from, const char* to) : from(from), to(to) {}
		Reader(const std::vector<char>& src) : from(src.data()), to(src.data() + src.size()) {}

		size_t size() const { return to - from; }

		void read(void* dest, size_t len)
		{
			if(len > size()) throw std::range_error("Insufficient bytes in range");
			memcpy(dest, from, len);
			from += len;
		}

		uint32_t readBits(uint8_t count)
		{
			uint32_t result = 0;
			uint8_t pos = 0;
			while(count)
			{
				if(!bitsLeft)
				{
					read(&bits, 1);
					bitsLeft = 8;
				}
				uint8_t bitsToRead = std::min(bitsLeft, count);
				uint8_t mask = (uint32_t(1) << bitsToRead) - 1;
				result |= (mask & bits) << pos;
				pos += bitsToRead;
				count -= bitsToRead;
				bitsLeft -= bitsToRead;
				bits >>= bitsToRead;
			}
			return result;
		}

	private:
		const char* from;
		const char* to;
		uint8_t bits;
		uint8_t bitsLeft = 0;
	};

	struct Writer
	{
		Writer(std::vector<char>& dest) : dest(dest) {}

		void write(const void* src, size_t len)
		{
			dest.insert(dest.end(), (const char*)src, (const char*)src + len);
		}

		void writeBits(uint32_t bits, uint8_t count)
		{
			while(count)
			{
				if(!bitsLeft)
				{
					bitsPos = dest.size();
					dest.push_back(0);
					bitsLeft = 8;
				}
				uint8_t bitsToWrite = std::min(bitsLeft, count);
				uint8_t mask = (uint32_t(1) << bitsToWrite) - 1;
				dest[bitsPos] |= (mask & bits) << (8 - bitsLeft);
				bitsLeft -= bitsToWrite;
				count -= bitsToWrite;
				bits >>= bitsToWrite;
			}
		}

	private:
		std::vector<char>& dest;
		size_t bitsPos;
		uint8_t bitsLeft = 0;
	};

	template<class T> constexpr int EnumCount = 0;
	template<class T, class = void> struct Type;
	template<class T> auto asTuple(T&& x) { return std::forward<T>(x); }

	template<class T> std::string toString(const T& x) { return Type<std::decay_t<T>>::toString(x); }
	template<class T> size_t bitLength(const T& x) { return Type<std::decay_t<T>>::bitLength(x); }
	template<class T> void unpackFrom(Reader& r, T&& x) { Type<std::decay_t<T>>::unpackFrom(r, std::forward<T>(x)); }
	template<class T> void unpackFrom(Reader& r, T& x) { Type<std::decay_t<T>>::unpackFrom(r, x); }
	template<class T> void packInto(Writer& w, const T& x) { Type<std::decay_t<T>>::packInto(w, x); }

	inline float asFloat(uint32_t x) { float f; memcpy(&f, &x, sizeof(x)); return f; }
	inline float scale(float v, float vmin, float vmax, float min, float max) { return (v - vmin)/(vmax - vmin)*(max - min) + min; }

	template<class U, uint32_t Min, uint32_t Max> struct Scaled
	{
		U value;
		Scaled() {}
		Scaled(float v) { *this = v; }
		static float min() { return asFloat(Min); }
		static float max() { return asFloat(Max); }
		operator float() const { return scale(value, std::numeric_limits<U>::min(), std::numeric_limits<U>::max(), min(), max()); }
		auto& operator=(float v) { value = scale(v, min(), max(), std::numeric_limits<U>::min(), std::numeric_limits<U>::max()); return *this; }
		auto operator~() const { return value; }
		auto& operator~() { return value; }
	};

	template<> struct Type<bool>
	{
		static std::string toString(const bool& x) { return x ? "+" : "-"; }
		static size_t bitLength(const bool&) { return 1; }
		static void unpackFrom(Reader& r, bool& x) { x = r.readBits(1); }
		static void packInto(Writer& w, const bool& x) { w.writeBits(x, 1); }
	};

	template<class T> struct Type<T, std::enable_if_t<std::is_enum<T>::value, void>>
	{
		static constexpr uint8_t bits = 32 - __builtin_clz(EnumCount<T> - 1);
		static std::string toString(const T& x) { return std::to_string((uint8_t)x); }
		static size_t bitLength(const T&) { return bits; }
		static void unpackFrom(Reader& r, T& x) { x = (T)r.readBits(bits); }
		static void packInto(Writer& w, const T& x) { w.writeBits((uint32_t)x, bits); }
	};

	template<class T> struct Type<T, std::enable_if_t<std::is_arithmetic<T>::value, void>>
	{
		static std::string toString(const T& x) { return std::to_string(x); }
		static size_t bitLength(const T&) { return 8*sizeof(T); }
		static void unpackFrom(Reader& r, T& x) { r.read(&x, sizeof(T)); }
		static void packInto(Writer& w, const T& x) { w.write(&x, sizeof(T)); }
	};

	struct VarInt
	{
		static uint8_t bytesBitsNeeded(size_t v) { return v <= 0xffff ? (v <= 0xff ? 0 : 1) : (v <= 0xffffffff ? 2 : 3); }
		static std::string toString(size_t x) { return std::to_string(x); }
		static size_t bitLength(size_t x) { return 2 + 8*(size_t(1) << bytesBitsNeeded(x)); }

		static void unpackFrom(Reader& r, size_t& x)
		{
			switch(r.readBits(2))
			{
				case 0: { uint8_t l; bw::unpackFrom(r, l); x = l; break; }
				case 1: { uint16_t l; bw::unpackFrom(r, l); x = l; break; }
				case 2: { uint32_t l; bw::unpackFrom(r, l); x = l; break; }
				case 3: { bw::unpackFrom(r, x); break; }
			}
		}

		static void packInto(Writer& w, size_t x)
		{
			uint8_t bb = bytesBitsNeeded(x);
			w.writeBits(bb, 2);
			switch(bb)
			{
				case 0: Type<uint8_t>::packInto(w, x); break;
				case 1: Type<uint16_t>::packInto(w, x); break;
				case 2: Type<uint32_t>::packInto(w, x); break;
				case 3: Type<uint64_t>::packInto(w, x); break;
			}
		}
	};

	template<> struct Type<std::string>
	{
		static std::string toString(const std::string& x) { return '\'' + x + '\''; }
		static size_t bitLength(const std::string& x) { return VarInt::bitLength(x.size()) + 8*x.size(); }

		static void unpackFrom(Reader& r, std::string& x)
		{
			size_t len;
			VarInt::unpackFrom(r, len);
			x.clear();
			char s[1024];
			while(len)
			{
				size_t n = std::min(len, sizeof(s));
				r.read(s, n);
				x.insert(x.end(), s, s + n);
				len -= n;
			}
		}

		static void packInto(Writer& w, const std::string& x)
		{
			VarInt::packInto(w, x.size());
			w.write(x.data(), x.size());
		}
	};

	template<class T> struct Type<std::optional<T>>
	{
		static std::string toString(const std::optional<T>& x) { return x ? bw::toString(*x) : "?"; }
		static size_t bitLength(const std::optional<T>& x) { return 1 + (x ? bw::bitLength(*x) : 0); }

		static void unpackFrom(Reader& r, std::optional<T>& x)
		{
			if(r.readBits(1))
			{
				x = T();
				bw::unpackFrom(r, *x);
			}
			else x = std::nullopt;
		}

		static void packInto(Writer& w, const std::optional<T>& x)
		{
			w.writeBits(bool(x), 1);
			if(x) bw::packInto(w, *x);
		}
	};

	template<class T> struct Type<std::vector<T>>
	{
		static std::string toString(const std::vector<T>& x)
		{
			std::string result = "[ ";
			for(const auto& m : x) result += bw::toString(m) += ' ';
			return result += ']';
		}

		static size_t bitLength(const std::vector<T>& x)
		{
			size_t s = VarInt::bitLength(x.size());
			for(const T& m : x) s += bw::bitLength(m);
			return s;
		}

		static void unpackFrom(Reader& r, std::vector<T>& x)
		{
			size_t len;
			VarInt::unpackFrom(r, len);
			x.clear();
			while(len--)
			{
				x.emplace_back();
				bw::unpackFrom(r, x.back());
			}
		}

		static void packInto(Writer& w, const std::vector<T>& x)
		{
			VarInt::packInto(w, x.size());
			for(const auto& v : x) bw::packInto(w, v);
		}
	};

	inline std::string toStringArgs() { return ""; }
	template<class Arg, class... Args> inline std::string toStringArgs(const Arg& first, const Args&... rest) { return bw::toString(first) + ' ' + toStringArgs(rest...); }

	inline size_t sumArgs() { return 0; }
	template<class Arg, class... Args> inline size_t sumArgs(Arg first, Args... rest) { return first + sumArgs(rest...); }

	inline void unpackArgs(Reader&) {}
	template<class Arg, class... Args> inline void unpackArgs(Reader& r, Arg& first, Args&... rest) { unpackFrom(r, first); unpackArgs(r, rest...); }

	inline void packArgs(Writer&) {}
	template<class Arg, class... Args> inline void packArgs(Writer& w, const Arg& first, const Args&... rest) { packInto(w, first); packArgs(w, rest...); }

	template<class T, size_t... I> std::string toStringTuple(const T& x, std::index_sequence<I...>) { return toStringArgs(std::get<I>(x)...); }
	template<class T, size_t... I> size_t bitLengthTuple(const T& x, std::index_sequence<I...>) { return sumArgs(bitLength(std::get<I>(x))...); }
	template<class T, size_t... I> void unpackTuple(Reader& r, T&& x, std::index_sequence<I...>) { unpackArgs(r, std::get<I>(std::forward<T>(x))...); }
	template<class T, size_t... I> void packTuple(Writer& w, const T& x, std::index_sequence<I...>) { packArgs(w, std::get<I>(x)...); }

	template<class... Args> struct Type<std::tuple<Args...>>
	{
		using T = std::tuple<Args...>;

		static std::string toString(const T& x) { return "( " + toStringTuple(x, std::make_index_sequence<std::tuple_size<T>::value>()) + ')'; }
		static size_t bitLength(const T& x) { return bitLengthTuple(x, std::make_index_sequence<std::tuple_size<T>::value>()); }
		static void unpackFrom(Reader& r, T&& x) { unpackTuple(r, std::forward<T>(x), std::make_index_sequence<std::tuple_size<T>::value>()); }
		static void packInto(Writer& w, const T& x) { packTuple(w, x, std::make_index_sequence<std::tuple_size<T>::value>()); }
	};

	template<class T> struct Type<T, std::enable_if_t<std::is_class<T>::value
		&& !is_same_template<std::optional, T>
		&& !is_same_template<std::vector, T>
		&& !is_same_template<std::tuple, T>, void>>
	{
		static std::string toString(const T& x) { return bw::toString(~x); }
		static size_t bitLength(const T& x) { return bw::bitLength(~x); }
		static void unpackFrom(Reader& r, T& x) { bw::unpackFrom(r, ~x); }
		static void packInto(Writer& w, const T& x) { bw::packInto(w, ~x); }
	};

	template<class T> size_t byteLength(const T& x) { return (bitLength(x) + 7)/8; }
	template<class T> void unpackFrom(const std::vector<char>& v, T& x) { Reader r(v); unpackFrom(r, x); }
	template<class T, class B> T unpack(B& v) { T x; unpackFrom(v, x); return x; }
	template<class T> void packInto(std::vector<char>& v, const T& x) { Writer w(v); packInto(w, x); }
	template<class T> std::vector<char> pack(const T& x) { std::vector<char> r; r.reserve(byteLength(x)); packInto(r, x); return r; }
}
<commit_msg>Fixed VarInt<commit_after>#pragma once
#include <numeric>
#include <type_traits>
#include <utility>
#include <functional>
#include <string>
#include <cstring>
#include <cassert>
#include <tuple>
#include <vector>
#if __cplusplus <= 201402L
#include <experimental/optional>
namespace std { using namespace std::experimental; }
#else
#include <optional>
#endif

namespace bw
{
	template<template<class...> class TT, class X> constexpr bool is_same_template = false;
	template<template<class...> class TT, class... P> constexpr bool is_same_template<TT, TT<P...>> = true;

	struct Reader
	{
		Reader(const char* from, const char* to) : from(from), to(to) {}
		Reader(const std::vector<char>& src) : from(src.data()), to(src.data() + src.size()) {}

		size_t size() const { return to - from; }

		void read(void* dest, size_t len)
		{
			if(len > size()) throw std::range_error("Insufficient bytes in range");
			memcpy(dest, from, len);
			from += len;
		}

		uint32_t readBits(uint8_t count)
		{
			uint32_t result = 0;
			uint8_t pos = 0;
			while(count)
			{
				if(!bitsLeft)
				{
					read(&bits, 1);
					bitsLeft = 8;
				}
				uint8_t bitsToRead = std::min(bitsLeft, count);
				uint8_t mask = (uint32_t(1) << bitsToRead) - 1;
				result |= (mask & bits) << pos;
				pos += bitsToRead;
				count -= bitsToRead;
				bitsLeft -= bitsToRead;
				bits >>= bitsToRead;
			}
			return result;
		}

	private:
		const char* from;
		const char* to;
		uint8_t bits;
		uint8_t bitsLeft = 0;
	};

	struct Writer
	{
		Writer(std::vector<char>& dest) : dest(dest) {}

		void write(const void* src, size_t len)
		{
			dest.insert(dest.end(), (const char*)src, (const char*)src + len);
		}

		void writeBits(uint32_t bits, uint8_t count)
		{
			while(count)
			{
				if(!bitsLeft)
				{
					bitsPos = dest.size();
					dest.push_back(0);
					bitsLeft = 8;
				}
				uint8_t bitsToWrite = std::min(bitsLeft, count);
				uint8_t mask = (uint32_t(1) << bitsToWrite) - 1;
				dest[bitsPos] |= (mask & bits) << (8 - bitsLeft);
				bitsLeft -= bitsToWrite;
				count -= bitsToWrite;
				bits >>= bitsToWrite;
			}
		}

	private:
		std::vector<char>& dest;
		size_t bitsPos;
		uint8_t bitsLeft = 0;
	};

	template<class T> constexpr int EnumCount = 0;
	template<class T, class = void> struct Type;
	template<class T> auto asTuple(T&& x) { return std::forward<T>(x); }

	template<class T> std::string toString(const T& x) { return Type<std::decay_t<T>>::toString(x); }
	template<class T> size_t bitLength(const T& x) { return Type<std::decay_t<T>>::bitLength(x); }
	template<class T> void unpackFrom(Reader& r, T&& x) { Type<std::decay_t<T>>::unpackFrom(r, std::forward<T>(x)); }
	template<class T> void unpackFrom(Reader& r, T& x) { Type<std::decay_t<T>>::unpackFrom(r, x); }
	template<class T> void packInto(Writer& w, const T& x) { Type<std::decay_t<T>>::packInto(w, x); }

	template<class T> size_t byteLength(const T& x) { return (bitLength(x) + 7)/8; }
	template<class T> void unpackFrom(const std::vector<char>& v, T& x) { Reader r(v); unpackFrom(r, x); }
	template<class T, class B> T unpack(B& v) { T x; unpackFrom(v, x); return x; }
	template<class T> void packInto(std::vector<char>& v, const T& x) { Writer w(v); packInto(w, x); }
	template<class T> std::vector<char> pack(const T& x) { std::vector<char> r; r.reserve(byteLength(x)); packInto(r, x); return r; }

	inline float asFloat(uint32_t x) { float f; memcpy(&f, &x, sizeof(x)); return f; }
	inline float scale(float v, float vmin, float vmax, float min, float max) { return (v - vmin)/(vmax - vmin)*(max - min) + min; }

	template<class U, uint32_t Min, uint32_t Max> struct Scaled
	{
		U value;
		Scaled() {}
		Scaled(float v) { *this = v; }
		static float min() { return asFloat(Min); }
		static float max() { return asFloat(Max); }
		operator float() const { return scale(value, std::numeric_limits<U>::min(), std::numeric_limits<U>::max(), min(), max()); }
		auto& operator=(float v) { value = scale(v, min(), max(), std::numeric_limits<U>::min(), std::numeric_limits<U>::max()); return *this; }
		auto operator~() const { return value; }
		auto& operator~() { return value; }
	};

	template<> struct Type<bool>
	{
		static std::string toString(const bool& x) { return x ? "+" : "-"; }
		static size_t bitLength(const bool&) { return 1; }
		static void unpackFrom(Reader& r, bool& x) { x = r.readBits(1); }
		static void packInto(Writer& w, const bool& x) { w.writeBits(x, 1); }
	};

	template<class T> struct Type<T, std::enable_if_t<std::is_enum<T>::value, void>>
	{
		static constexpr uint8_t bits = 32 - __builtin_clz(EnumCount<T> - 1);
		static std::string toString(const T& x) { return std::to_string((uint8_t)x); }
		static size_t bitLength(const T&) { return bits; }
		static void unpackFrom(Reader& r, T& x) { x = (T)r.readBits(bits); }
		static void packInto(Writer& w, const T& x) { w.writeBits((uint32_t)x, bits); }
	};

	template<class T> struct Type<T, std::enable_if_t<std::is_arithmetic<T>::value, void>>
	{
		static std::string toString(const T& x) { return std::to_string(x); }
		static size_t bitLength(const T&) { return 8*sizeof(T); }
		static void unpackFrom(Reader& r, T& x) { r.read(&x, sizeof(T)); }
		static void packInto(Writer& w, const T& x) { w.write(&x, sizeof(T)); }
	};

	struct VarInt
	{
		static uint8_t bytesBitsNeeded(size_t v) { return v <= 0xffff ? (v <= 0xff ? 0 : 1) : (v <= 0xffffffff ? 2 : 3); }
		static std::string toString(size_t x) { return std::to_string(x); }
		static size_t bitLength(size_t x) { return 2 + 8*(size_t(1) << bytesBitsNeeded(x)); }

		static size_t unpack(Reader& r)
		{
			switch(r.readBits(2))
			{
				case 0: return bw::unpack<uint8_t>(r);
				case 1: return bw::unpack<uint16_t>(r);
				case 2: return bw::unpack<uint32_t>(r);
				case 3: return bw::unpack<uint64_t>(r);
			}
		}

		static void packInto(Writer& w, size_t x)
		{
			uint8_t bb = bytesBitsNeeded(x);
			w.writeBits(bb, 2);
			switch(bb)
			{
				case 0: Type<uint8_t>::packInto(w, x); break;
				case 1: Type<uint16_t>::packInto(w, x); break;
				case 2: Type<uint32_t>::packInto(w, x); break;
				case 3: Type<uint64_t>::packInto(w, x); break;
			}
		}
	};

	template<> struct Type<std::string>
	{
		static std::string toString(const std::string& x) { return '\'' + x + '\''; }
		static size_t bitLength(const std::string& x) { return VarInt::bitLength(x.size()) + 8*x.size(); }

		static void unpackFrom(Reader& r, std::string& x)
		{
			size_t len = VarInt::unpack(r);
			x.clear();
			char s[1024];
			while(len)
			{
				size_t n = std::min(len, sizeof(s));
				r.read(s, n);
				x.insert(x.end(), s, s + n);
				len -= n;
			}
		}

		static void packInto(Writer& w, const std::string& x)
		{
			VarInt::packInto(w, x.size());
			w.write(x.data(), x.size());
		}
	};

	template<class T> struct Type<std::optional<T>>
	{
		static std::string toString(const std::optional<T>& x) { return x ? bw::toString(*x) : "?"; }
		static size_t bitLength(const std::optional<T>& x) { return 1 + (x ? bw::bitLength(*x) : 0); }

		static void unpackFrom(Reader& r, std::optional<T>& x)
		{
			if(r.readBits(1))
			{
				x = T();
				bw::unpackFrom(r, *x);
			}
			else x = std::nullopt;
		}

		static void packInto(Writer& w, const std::optional<T>& x)
		{
			w.writeBits(bool(x), 1);
			if(x) bw::packInto(w, *x);
		}
	};

	template<class T> struct Type<std::vector<T>>
	{
		static std::string toString(const std::vector<T>& x)
		{
			std::string result = "[ ";
			for(const auto& m : x) result += bw::toString(m) += ' ';
			return result += ']';
		}

		static size_t bitLength(const std::vector<T>& x)
		{
			size_t s = VarInt::bitLength(x.size());
			for(const T& m : x) s += bw::bitLength(m);
			return s;
		}

		static void unpackFrom(Reader& r, std::vector<T>& x)
		{
			size_t len = VarInt::unpack(r);
			x.clear();
			while(len--)
			{
				x.emplace_back();
				bw::unpackFrom(r, x.back());
			}
		}

		static void packInto(Writer& w, const std::vector<T>& x)
		{
			VarInt::packInto(w, x.size());
			for(const auto& v : x) bw::packInto(w, v);
		}
	};

	inline std::string toStringArgs() { return ""; }
	template<class Arg, class... Args> inline std::string toStringArgs(const Arg& first, const Args&... rest) { return bw::toString(first) + ' ' + toStringArgs(rest...); }

	inline size_t sumArgs() { return 0; }
	template<class Arg, class... Args> inline size_t sumArgs(Arg first, Args... rest) { return first + sumArgs(rest...); }

	inline void unpackArgs(Reader&) {}
	template<class Arg, class... Args> inline void unpackArgs(Reader& r, Arg& first, Args&... rest) { unpackFrom(r, first); unpackArgs(r, rest...); }

	inline void packArgs(Writer&) {}
	template<class Arg, class... Args> inline void packArgs(Writer& w, const Arg& first, const Args&... rest) { packInto(w, first); packArgs(w, rest...); }

	template<class T, size_t... I> std::string toStringTuple(const T& x, std::index_sequence<I...>) { return toStringArgs(std::get<I>(x)...); }
	template<class T, size_t... I> size_t bitLengthTuple(const T& x, std::index_sequence<I...>) { return sumArgs(bitLength(std::get<I>(x))...); }
	template<class T, size_t... I> void unpackTuple(Reader& r, T&& x, std::index_sequence<I...>) { unpackArgs(r, std::get<I>(std::forward<T>(x))...); }
	template<class T, size_t... I> void packTuple(Writer& w, const T& x, std::index_sequence<I...>) { packArgs(w, std::get<I>(x)...); }

	template<class... Args> struct Type<std::tuple<Args...>>
	{
		using T = std::tuple<Args...>;

		static std::string toString(const T& x) { return "( " + toStringTuple(x, std::make_index_sequence<std::tuple_size<T>::value>()) + ')'; }
		static size_t bitLength(const T& x) { return bitLengthTuple(x, std::make_index_sequence<std::tuple_size<T>::value>()); }
		static void unpackFrom(Reader& r, T&& x) { unpackTuple(r, std::forward<T>(x), std::make_index_sequence<std::tuple_size<T>::value>()); }
		static void packInto(Writer& w, const T& x) { packTuple(w, x, std::make_index_sequence<std::tuple_size<T>::value>()); }
	};

	template<class T> struct Type<T, std::enable_if_t<std::is_class<T>::value
		&& !is_same_template<std::optional, T>
		&& !is_same_template<std::vector, T>
		&& !is_same_template<std::tuple, T>, void>>
	{
		static std::string toString(const T& x) { return bw::toString(~x); }
		static size_t bitLength(const T& x) { return bw::bitLength(~x); }
		static void unpackFrom(Reader& r, T& x) { bw::unpackFrom(r, ~x); }
		static void packInto(Writer& w, const T& x) { bw::packInto(w, ~x); }
	};
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

// boost
#include <boost/python.hpp>
#include <boost/python/def.hpp>
#include <boost/python/exception_translator.hpp>
#include <boost/python/manage_new_object.hpp>
#include <boost/python/iterator.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/make_shared.hpp>

// mapnik
#include <mapnik/geometry.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/wkb.hpp>

#include <boost/version.hpp>
#if BOOST_VERSION >= 104700
#include <mapnik/util/geometry_to_wkb.hpp>
#include <mapnik/util/geometry_to_wkt.hpp>
#endif

namespace {

using mapnik::from_wkt;
using mapnik::geometry_type;

typedef boost::ptr_vector<geometry_type> path_type;

geometry_type const& getitem_impl(path_type & p, int key)
{
    if (key >=0 && key < p.size())
        return p[key];
    PyErr_SetString(PyExc_IndexError, "Index is out of range");
    throw boost::python::error_already_set();
}

void add_wkt_impl(path_type& p, std::string const& wkt)
{
    bool result = mapnik::from_wkt(wkt , p);
    if (!result) throw std::runtime_error("Failed to parse WKT");
}

void add_wkb_impl(path_type& p, std::string const& wkb)
{
    mapnik::geometry_utils::from_wkb(p, wkb.c_str(), wkb.size());
}

boost::shared_ptr<path_type> from_wkt_impl(std::string const& wkt)
{
    boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
    bool result = mapnik::from_wkt(wkt, *paths);
    if (!result) throw std::runtime_error("Failed to parse WKT");
    return paths;
}

boost::shared_ptr<path_type> from_wkb_impl(std::string const& wkb)
{
    boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
    mapnik::geometry_utils::from_wkb(*paths, wkb.c_str(), wkb.size());
    return paths;
}

}

inline std::string boost_version()
{
    std::ostringstream s;
    s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000  << "." << BOOST_VERSION % 100;
    return s.str();
}

#if BOOST_VERSION >= 104700
PyObject* to_wkb( geometry_type const& geom, mapnik::util::wkbByteOrder byte_order)
{
    mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,byte_order);
    return
#if PY_VERSION_HEX >= 0x03000000
        ::PyBytes_FromStringAndSize
#else
        ::PyString_FromStringAndSize
#endif
        ((const char*)wkb->buffer(),wkb->size());
}
#else
PyObject* to_wkb( geometry_type const& geom)
{
    throw std::runtime_error("mapnik::to_wkb() requires at least boost 1.47 while your build was compiled against boost "
                             + boost_version());
}
#endif

#if BOOST_VERSION >= 104700
PyObject* to_wkb2( path_type const& p, mapnik::util::wkbByteOrder byte_order)
{
    mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(p,byte_order);
    return
#if PY_VERSION_HEX >= 0x03000000
        ::PyBytes_FromStringAndSize
#else
        ::PyString_FromStringAndSize
#endif
        ((const char*)wkb->buffer(),wkb->size());
}
#else
PyObject* to_wkb2( path_type const& p)
{
    throw std::runtime_error("mapnik::to_wkb() requires at least boost 1.47 while your build was compiled against boost "
                             + boost_version());
}
#endif

std::string to_wkt( geometry_type const& geom)
{
#if BOOST_VERSION >= 104700
    std::string wkt; // Use Python String directly ?
    bool result = mapnik::util::to_wkt(wkt,geom);
    if (!result)
    {
        throw std::runtime_error("Generate WKT failed");
    }
    return wkt;
#else
    throw std::runtime_error("mapnik::to_wkt() requires at least boost 1.47 while your build was compiled against boost "
                             + boost_version());
#endif
}

std::string to_wkt2( path_type const& geom)
{
#if BOOST_VERSION >= 104700
    std::string wkt; // Use Python String directly ?
    bool result = mapnik::util::to_wkt(wkt,geom);
    if (!result)
    {
        throw std::runtime_error("Generate WKT failed");
    }
    return wkt;
#else
    throw std::runtime_error("mapnik::to_wkt() requires at least boost 1.47 while your build was compiled against boost "
                             + boost_version());
#endif
}

void export_geometry()
{
    using namespace boost::python;

    enum_<mapnik::eGeomType>("GeometryType")
        .value("Point",mapnik::Point)
        .value("LineString",mapnik::LineString)
        .value("Polygon",mapnik::Polygon)
        ;

    enum_<mapnik::util::wkbByteOrder>("wkbByteOrder")
        .value("XDR",mapnik::util::wkbXDR)
        .value("NDR",mapnik::util::wkbNDR)
        ;

    using mapnik::geometry_type;
    class_<geometry_type, std::auto_ptr<geometry_type>, boost::noncopyable>("Geometry2d",no_init)
        .def("envelope",&geometry_type::envelope)
        // .def("__str__",&geometry_type::to_string)
        .def("type",&geometry_type::type)
        .def("to_wkb",&to_wkb)
        .def("to_wkt",&to_wkt)
        // TODO add other geometry_type methods
        ;

    class_<path_type, boost::shared_ptr<path_type>, boost::noncopyable>("Path")
        .def("__getitem__", getitem_impl,return_value_policy<reference_existing_object>())
        .def("__len__", &path_type::size)
        .def("add_wkt",add_wkt_impl)
        .def("add_wkb",add_wkb_impl)
        .def("to_wkt",&to_wkt2)
        .def("to_wkb",&to_wkb2)
        .def("from_wkt",from_wkt_impl)
        .def("from_wkb",from_wkb_impl)
        .staticmethod("from_wkt")
        .staticmethod("from_wkb")
        ;

}
<commit_msg>fix compile with older boost<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

// boost
#include <boost/python.hpp>
#include <boost/python/def.hpp>
#include <boost/python/exception_translator.hpp>
#include <boost/python/manage_new_object.hpp>
#include <boost/python/iterator.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/make_shared.hpp>

// mapnik
#include <mapnik/geometry.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/wkb.hpp>

#include <boost/version.hpp>
#if BOOST_VERSION >= 104700
#include <mapnik/util/geometry_to_wkb.hpp>
#include <mapnik/util/geometry_to_wkt.hpp>
#endif

namespace {

using mapnik::from_wkt;
using mapnik::geometry_type;

typedef boost::ptr_vector<geometry_type> path_type;

geometry_type const& getitem_impl(path_type & p, int key)
{
    if (key >=0 && key < p.size())
        return p[key];
    PyErr_SetString(PyExc_IndexError, "Index is out of range");
    throw boost::python::error_already_set();
}

void add_wkt_impl(path_type& p, std::string const& wkt)
{
    bool result = mapnik::from_wkt(wkt , p);
    if (!result) throw std::runtime_error("Failed to parse WKT");
}

void add_wkb_impl(path_type& p, std::string const& wkb)
{
    mapnik::geometry_utils::from_wkb(p, wkb.c_str(), wkb.size());
}

boost::shared_ptr<path_type> from_wkt_impl(std::string const& wkt)
{
    boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
    bool result = mapnik::from_wkt(wkt, *paths);
    if (!result) throw std::runtime_error("Failed to parse WKT");
    return paths;
}

boost::shared_ptr<path_type> from_wkb_impl(std::string const& wkb)
{
    boost::shared_ptr<path_type> paths = boost::make_shared<path_type>();
    mapnik::geometry_utils::from_wkb(*paths, wkb.c_str(), wkb.size());
    return paths;
}

}

inline std::string boost_version()
{
    std::ostringstream s;
    s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000  << "." << BOOST_VERSION % 100;
    return s.str();
}

#if BOOST_VERSION >= 104700
PyObject* to_wkb( geometry_type const& geom, mapnik::util::wkbByteOrder byte_order)
{
    mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,byte_order);
    return
#if PY_VERSION_HEX >= 0x03000000
        ::PyBytes_FromStringAndSize
#else
        ::PyString_FromStringAndSize
#endif
        ((const char*)wkb->buffer(),wkb->size());
}
#else
PyObject* to_wkb( geometry_type const& geom)
{
    throw std::runtime_error("mapnik::to_wkb() requires at least boost 1.47 while your build was compiled against boost "
                             + boost_version());
}
#endif

#if BOOST_VERSION >= 104700
PyObject* to_wkb2( path_type const& p, mapnik::util::wkbByteOrder byte_order)
{
    mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(p,byte_order);
    return
#if PY_VERSION_HEX >= 0x03000000
        ::PyBytes_FromStringAndSize
#else
        ::PyString_FromStringAndSize
#endif
        ((const char*)wkb->buffer(),wkb->size());
}
#else
PyObject* to_wkb2( path_type const& p)
{
    throw std::runtime_error("mapnik::to_wkb() requires at least boost 1.47 while your build was compiled against boost "
                             + boost_version());
}
#endif

std::string to_wkt( geometry_type const& geom)
{
#if BOOST_VERSION >= 104700
    std::string wkt; // Use Python String directly ?
    bool result = mapnik::util::to_wkt(wkt,geom);
    if (!result)
    {
        throw std::runtime_error("Generate WKT failed");
    }
    return wkt;
#else
    throw std::runtime_error("mapnik::to_wkt() requires at least boost 1.47 while your build was compiled against boost "
                             + boost_version());
#endif
}

std::string to_wkt2( path_type const& geom)
{
#if BOOST_VERSION >= 104700
    std::string wkt; // Use Python String directly ?
    bool result = mapnik::util::to_wkt(wkt,geom);
    if (!result)
    {
        throw std::runtime_error("Generate WKT failed");
    }
    return wkt;
#else
    throw std::runtime_error("mapnik::to_wkt() requires at least boost 1.47 while your build was compiled against boost "
                             + boost_version());
#endif
}

void export_geometry()
{
    using namespace boost::python;

    enum_<mapnik::eGeomType>("GeometryType")
        .value("Point",mapnik::Point)
        .value("LineString",mapnik::LineString)
        .value("Polygon",mapnik::Polygon)
        ;

#if BOOST_VERSION >= 104700
    enum_<mapnik::util::wkbByteOrder>("wkbByteOrder")
        .value("XDR",mapnik::util::wkbXDR)
        .value("NDR",mapnik::util::wkbNDR)
        ;
#endif

    using mapnik::geometry_type;
    class_<geometry_type, std::auto_ptr<geometry_type>, boost::noncopyable>("Geometry2d",no_init)
        .def("envelope",&geometry_type::envelope)
        // .def("__str__",&geometry_type::to_string)
        .def("type",&geometry_type::type)
        .def("to_wkb",&to_wkb)
        .def("to_wkt",&to_wkt)
        // TODO add other geometry_type methods
        ;

    class_<path_type, boost::shared_ptr<path_type>, boost::noncopyable>("Path")
        .def("__getitem__", getitem_impl,return_value_policy<reference_existing_object>())
        .def("__len__", &path_type::size)
        .def("add_wkt",add_wkt_impl)
        .def("add_wkb",add_wkb_impl)
        .def("to_wkt",&to_wkt2)
        .def("to_wkb",&to_wkb2)
        .def("from_wkt",from_wkt_impl)
        .def("from_wkb",from_wkb_impl)
        .staticmethod("from_wkt")
        .staticmethod("from_wkb")
        ;

}
<|endoftext|>


<commit_before>#include "small_int.h"
#include <iostream>

using namespace std;

template<long long max, long long min = 0>
void print_int()
{
	cout << "(max=" << max << ", min=" << min << ") -> " << typeid(integer<max, min>).name() << " " << sizeof(integer<max, min>) << endl;
}

template<unsigned long long max>
void print_uint()
{
	cout << "max=" << max << " -> " << typeid(integer<max>).name() << " " << sizeof(integer<max>) << endl;
}

#define PRINT_TYPE_UINT(type) cout << "(" << #type << ") "; print_uint<numeric_limits<type>::max()>()
#define PRINT_TYPE_INT(type) cout << "(" << #type << ") "; print_int<numeric_limits<type>::max(), numeric_limits<type>::min()>()
#define PRINT_TYPE_INT_MIN(type) cout << "(" << #type << ") "; print_int<0, numeric_limits<type>::min()>()

int main()
{
	// unsigned
	cout << endl << "unsigned:" << endl;
	print_uint<1>();
	PRINT_TYPE_UINT(unsigned char);
	PRINT_TYPE_UINT(unsigned short);
	PRINT_TYPE_UINT(unsigned int);
	PRINT_TYPE_UINT(unsigned long);
	//PRINT_TYPE_UINT(unsigned long long);	// Too big for max_value

	// signed
	cout << endl << "signed:" << endl;
	print_int<-1, -2>();
	print_int<0, -1>();
	print_int<1, -1>();
	print_int<1, -1000>();
	cout << endl;
	PRINT_TYPE_INT(char);
	PRINT_TYPE_INT(short);
	PRINT_TYPE_INT(int);
	PRINT_TYPE_INT(long);
	PRINT_TYPE_INT(long long);

	cout << endl << "signed (max=0):" << endl;
	PRINT_TYPE_INT_MIN(char);
	PRINT_TYPE_INT_MIN(short);
	PRINT_TYPE_INT_MIN(int);
	PRINT_TYPE_INT_MIN(long);
	PRINT_TYPE_INT_MIN(long long);

	// constexpr
	constexpr unsigned ce = 10;
	integer<ce> a = ce;

	cout << endl;

	int_least<100> least;
	cout << "least: " << typeid(least).name() << endl;
	int_fast<1000> fast;
	cout << "fast: " << typeid(fast).name() << endl;

	cout << endl;

	// range values order doesn't matter
	integer<100, -100> range = 1;
	integer<-100, 100> flipped_range = 1;
	cout << "range: " << typeid(range).name() << endl;
	cout << "flipped_range: " << typeid(flipped_range).name() << endl;
}<commit_msg>Small improvement<commit_after>#include "small_int.h"
#include <iostream>

using namespace std;

template<long long max, long long min = 0>
void print_int()
{
	cout << "(max=" << max << ", min=" << min << ") -> " <<
			typeid(integer<max, min>).name() << " " << sizeof(integer<max, min>) << endl;
}

template<unsigned long long max>
void print_uint()
{
	cout << "max=" << max << " -> " <<
			typeid(integer<max>).name() << " " << sizeof(integer<max>) << endl;
}

#define PRINT_TYPE_UINT(type) cout << "(" << #type << ") "; print_uint<numeric_limits<type>::max()>()
#define PRINT_TYPE_INT(type) cout << "(" << #type << ") "; print_int<numeric_limits<type>::max(), numeric_limits<type>::min()>()
#define PRINT_TYPE_INT_MIN(type) cout << "(" << #type << ") "; print_int<0, numeric_limits<type>::min()>()

int main()
{
	// unsigned
	cout << endl << "unsigned:" << endl;
	print_uint<1>();
	PRINT_TYPE_UINT(unsigned char);
	PRINT_TYPE_UINT(unsigned short);
	PRINT_TYPE_UINT(unsigned int);
	PRINT_TYPE_UINT(unsigned long);
	//PRINT_TYPE_UINT(unsigned long long);	// Too big for max_value

	// signed
	cout << endl << "signed:" << endl;
	print_int<-1, -2>();
	print_int<0, -1>();
	print_int<1, -1>();
	print_int<1, -1000>();
	cout << endl;
	PRINT_TYPE_INT(char);
	PRINT_TYPE_INT(short);
	PRINT_TYPE_INT(int);
	PRINT_TYPE_INT(long);
	PRINT_TYPE_INT(long long);

	cout << endl << "signed (max=0):" << endl;
	PRINT_TYPE_INT_MIN(char);
	PRINT_TYPE_INT_MIN(short);
	PRINT_TYPE_INT_MIN(int);
	PRINT_TYPE_INT_MIN(long);
	PRINT_TYPE_INT_MIN(long long);

	// constexpr
	constexpr unsigned ce = 10;
	integer<ce> a = ce;

	cout << endl;

	constexpr auto max_value = 1000;
	int_least<max_value> least;
	cout << "least (" << max_value << ") -> " << typeid(least).name() << endl;
	int_fast<max_value> fast;
	cout << "fast (" << max_value << ") -> " << typeid(fast).name() << endl;

	cout << endl;

	// range values order doesn't matter
	integer<100, -100> range = 1;
	integer<-100, 100> flipped_range = 1;
	cout << "range -> " << typeid(range).name() << endl;
	cout << "flipped_range -> " << typeid(flipped_range).name() << endl;

	cout << endl;
}<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015-2016 Nagisa Sekiguchi
 *
 * 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.
 */

#ifndef YDSH_MISC_BUFFER_HPP
#define YDSH_MISC_BUFFER_HPP

#include <cstring>
#include <type_traits>
#include <stdexcept>
#include <string>
#include <cassert>
#include <cmath>
#include <initializer_list>

#include "noncopyable.h"

namespace ydsh {

/**
 * only available POD type.
 * default maximum capacity is 4GB
 */
template <typename T, typename SIZE_T = unsigned int>
class FlexBuffer {
public:
    using size_type = SIZE_T;
    using iterator = T *;
    using const_iterator = const T *;
    using reference = T &;
    using const_reference = const T &;

    static constexpr size_type MINIMUM_CAPACITY = 8;
    static constexpr size_type MAXIMUM_CAPACITY = static_cast<SIZE_T>(-1);

private:
    static_assert(std::is_unsigned<SIZE_T>::value, "need unsigned type");

    static_assert(std::is_pod<T>::value, "forbidden type");

    size_type maxSize;
    size_type usedSize;

    T *data;

    /**
     * expand memory of old.
     * if old is null, only allocate.
     */
    static T *allocArray(T *old, SIZE_T size) {
        T *ptr = static_cast<T *>(realloc(old, sizeof(T) * size));
        if(ptr == nullptr) {
            throw std::bad_alloc();
        }
        return ptr;
    }

    void moveElements(iterator src, iterator dest) noexcept {
        if(src == dest) {
            return;
        }

        memmove(dest, src, sizeof(T) * (this->end() - src));
        if(src < dest) {
            this->usedSize += (dest - src);
        } else {
            this->usedSize -= (src - dest);
        }
    }

    /**
     * if out of range, throw exception
     */
    void checkRange(size_type index) const;

public:
    NON_COPYABLE(FlexBuffer);

    /**
     * default initial size is equivalent to MINIMUM_CAPACITY
     */
    explicit FlexBuffer(size_type initSize) :
            maxSize(initSize < MINIMUM_CAPACITY ? MINIMUM_CAPACITY : initSize),
            usedSize(0),
            data(allocArray(nullptr, this->maxSize)) { }

    FlexBuffer(std::initializer_list<T> list) : FlexBuffer(list.size()) {
        for(auto iter = list.begin(); iter != list.end(); ++iter) {
            this->data[this->usedSize++] = *iter;
        }
    }

    /**
     * for lazy allocation
     */
    FlexBuffer() noexcept : maxSize(0), usedSize(0), data(nullptr) { }

    FlexBuffer(FlexBuffer &&buffer) noexcept :
            maxSize(buffer.maxSize), usedSize(buffer.usedSize), data(extract(std::move(buffer))) { }

    ~FlexBuffer() {
        free(this->data);
    }

    FlexBuffer &operator=(FlexBuffer &&buffer) noexcept {
        FlexBuffer tmp(std::move(buffer));
        this->swap(tmp);
        return *this;
    }

    FlexBuffer &operator+=(const T &value);

    /**
     * buffer.data is not equivalent to this.data.
     */
    FlexBuffer &operator+=(const FlexBuffer &buffer);

    FlexBuffer &operator+=(FlexBuffer &&buffer);

    template <std::size_t N>
    FlexBuffer &operator+=(const T (&value)[N]) {
        return this->append(value, N);
    }

    /**
     * value is not equivalent to this.data.
     */
    FlexBuffer &append(const T *value, size_type size);

    size_type capacity() const noexcept {
        return this->maxSize;
    }

    size_type size() const noexcept {
        return this->usedSize;
    }

    bool empty() const noexcept {
        return this->size() == 0;
    }

    const T *get() const noexcept {
        return this->data;
    }

    void clear() noexcept {
        this->usedSize = 0;
    }

    void swap(FlexBuffer &buf) noexcept {
        std::swap(this->usedSize, buf.usedSize);
        std::swap(this->maxSize, buf.maxSize);
        std::swap(this->data, buf.data);
    }

    /**
     * capacity will be at least reservingSize.
     */
    void reserve(size_type reservingSize);

    iterator begin() noexcept {
        return this->data;
    }

    iterator end() noexcept {
        return this->data + this->usedSize;
    }

    const_iterator begin() const noexcept {
        return this->data;
    }

    const_iterator end() const noexcept {
        return this->data + this->usedSize;
    }

    reference front() noexcept {
        return this->operator[](0);
    }

    const_reference front() const noexcept {
        return this->operator[](0);
    }

    reference back() noexcept {
        return this->operator[](this->usedSize - 1);
    }

    const_reference back() const noexcept {
        return this->operator[](this->usedSize - 1);
    }

    void pop_back() noexcept {
        this->usedSize--;
    }

    reference operator[](size_type index) noexcept {
        return this->data[index];
    }

    const_reference operator[](size_type index) const noexcept {
        return this->data[index];
    }

    reference at(size_type index);

    const_reference at(size_type index) const;

    /**
     * pos (begin() <= pos <= end()).
     * return position inserted element.
     */
    iterator insert(const_iterator pos, const T &value);

    /**
     * pos must not equivalent to this->end().
     */
    iterator erase(const_iterator pos) noexcept;

    /**
     * first must be last or less. (first <= last).
     * last must be this->end() or less. (last <= this->end())
     * first is inclusive, last is exclusive.
     */
    iterator erase(const_iterator first, const_iterator last) noexcept;

    void assign(size_type n, const T &value);

    /**
     * extract data. after call it, maxSize and usedSize is 0, and data is null.
     * call free() to release returned pointer.
     */
    friend T *extract(FlexBuffer &&buf) noexcept {
        buf.maxSize = 0;
        buf.usedSize = 0;
        T *ptr = buf.data;
        buf.data = nullptr;
        return ptr;
    }
};

// ########################
// ##     FlexBuffer     ##
// ########################

template <typename T, typename SIZE_T>
constexpr typename FlexBuffer<T, SIZE_T>::size_type FlexBuffer<T, SIZE_T>::MINIMUM_CAPACITY;

template <typename T, typename SIZE_T>
constexpr typename FlexBuffer<T, SIZE_T>::size_type FlexBuffer<T, SIZE_T>::MAXIMUM_CAPACITY;

template <typename T, typename SIZE_T>
void FlexBuffer<T, SIZE_T>::checkRange(size_type index) const {
    if(index >= this->usedSize) {
        std::string str("size is: ");
        str += std::to_string(this->usedSize);
        str += ", but index is: ";
        str += std::to_string(index);
        throw std::out_of_range(str);
    }
}

template <typename T, typename SIZE_T>
FlexBuffer<T, SIZE_T> &FlexBuffer<T, SIZE_T>::operator+=(const T &value) {
    this->reserve(this->usedSize + 1);
    this->data[this->usedSize++] = value;
    return *this;
}

template <typename T, typename SIZE_T>
FlexBuffer<T, SIZE_T> &FlexBuffer<T, SIZE_T>::operator+=(const FlexBuffer<T, SIZE_T> &buffer) {
    return this->append(buffer.get(), buffer.size());
}

template <typename T, typename SIZE_T>
FlexBuffer<T, SIZE_T> &FlexBuffer<T, SIZE_T>::operator+=(FlexBuffer<T, SIZE_T> &&buffer) {
    FlexBuffer<T, SIZE_T> tmp(std::move(buffer));
    *this += tmp;
    return *this;
}

template <typename T, typename SIZE_T>
FlexBuffer<T, SIZE_T> &FlexBuffer<T, SIZE_T>::append(const T *value, size_type size) {
    if(this->data == value) {
        throw std::invalid_argument("appending own buffer");
    }
    this->reserve(this->usedSize + size);
    memcpy(this->data + this->usedSize, value, sizeof(T) * size);
    this->usedSize += size;
    return *this;
}

template <typename T, typename SIZE_T>
void FlexBuffer<T, SIZE_T>::reserve(size_type reservingSize) {
    if(reservingSize > this->maxSize) {
        std::size_t newSize = (this->maxSize == 0 ? MINIMUM_CAPACITY : this->maxSize);
        while(newSize < reservingSize) {
            newSize += (newSize >> 1);
        }

        if(newSize > MAXIMUM_CAPACITY) {
            throw std::length_error("reach maximum capacity");
        }

        this->maxSize = newSize;
        this->data = allocArray(this->data, newSize);
    }
}

template <typename T, typename SIZE_T>
typename FlexBuffer<T, SIZE_T>::reference FlexBuffer<T, SIZE_T>::at(size_type index) {
    this->checkRange(index);
    return this->data[index];
}

template <typename T, typename SIZE_T>
typename FlexBuffer<T, SIZE_T>::const_reference FlexBuffer<T, SIZE_T>::at(size_type index) const {
    this->checkRange(index);
    return this->data[index];
}

template <typename T, typename SIZE_T>
typename FlexBuffer<T, SIZE_T>::iterator FlexBuffer<T, SIZE_T>::insert(const_iterator pos, const T &value) {
    assert(pos >= this->begin() && pos <= this->end());

    const size_type index = pos - this->begin();
    this->reserve(this->size() + 1);
    iterator iter = this->begin() + index;

    this->moveElements(iter, iter + 1);
    this->data[index] = value;

    return iter;
}

template <typename T, typename SIZE_T>
typename FlexBuffer<T, SIZE_T>::iterator FlexBuffer<T, SIZE_T>::erase(const_iterator pos) noexcept {
    assert(pos < this->end());

    const size_type index = pos - this->begin();
    iterator iter = this->begin() + index;

    this->moveElements(iter + 1, iter);

    return iter;
}

template <typename T, typename SIZE_T>
typename FlexBuffer<T, SIZE_T>::iterator FlexBuffer<T, SIZE_T>::erase(const_iterator first, const_iterator last) noexcept {
    assert(last <= this->end());
    assert(first <= last);

    const size_type index = first - this->begin();
    iterator iter = this->begin() + index;

    this->moveElements(iter + (last - first), iter);

    return iter;
}

template <typename T, typename SIZE_T>
void FlexBuffer<T, SIZE_T>::assign(size_type n, const T &value) {
    this->reserve(this->usedSize + n);
    for(unsigned int i = 0; i < n; i++) {
        this->data[this->usedSize++] = value;
    }
}

using ByteBuffer = FlexBuffer<char>;

// for byte reading
inline unsigned char read8(const unsigned char *const code, unsigned int index) noexcept {
    return code[index];
}

inline unsigned short read16(const unsigned char *const code, unsigned int index) noexcept {
    return read8(code, index) << 8 | read8(code, index + 1);
}

inline unsigned int read32(const unsigned char *const code, unsigned int index) noexcept {
    return read8(code, index) << 24 | read8(code, index + 1) << 16
           | read8(code, index + 2) << 8 | read8(code, index + 3);
}

inline unsigned long read64(const unsigned char *const code, unsigned int index) noexcept {
    unsigned long v = 0;
    for(unsigned int i = 0; i < 8; i++) {
        v |= static_cast<unsigned long>(read8(code, index + i)) << ((7 - i) * 8);
    }
    return v;
}

// for byte writing
inline void write8(unsigned char *ptr, unsigned char b) noexcept {
    *ptr = b;
}

inline void write16(unsigned char *ptr, unsigned short b) noexcept {
    write8(ptr, (b & 0xFF00) >> 8);
    write8(ptr + 1, b & 0xFF);
}

inline void write32(unsigned char *ptr, unsigned int b) noexcept {
    write8(ptr,     (b & 0xFF000000) >> 24);
    write8(ptr + 1, (b & 0xFF0000) >> 16);
    write8(ptr + 2, (b & 0xFF00) >> 8);
    write8(ptr + 3,  b & 0xFF);
}

inline void write64(unsigned char *ptr, unsigned long b) noexcept {
    for(unsigned int i = 0; i < 8; i++) {
        const unsigned long mask = 0xFF * static_cast<unsigned long>(pow(0x100, 7 - i));
        write8(ptr + i, (b & mask) >> ((7 - i) * 8));
    }
}

} // namespace ydsh

#endif //YDSH_MISC_BUFFER_HPP
<commit_msg>update misc header<commit_after>/*
 * Copyright (C) 2015-2017 Nagisa Sekiguchi
 *
 * 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.
 */

#ifndef YDSH_MISC_BUFFER_HPP
#define YDSH_MISC_BUFFER_HPP

#include <cstring>
#include <type_traits>
#include <cassert>
#include <initializer_list>

#include "noncopyable.h"
#include "fatal.h"

namespace ydsh {

/**
 * only available POD type.
 * default maximum capacity is 4GB
 */
template <typename T, typename SIZE_T = unsigned int>
class FlexBuffer {
public:
    using size_type = SIZE_T;
    using iterator = T *;
    using const_iterator = const T *;
    using reference = T &;
    using const_reference = const T &;

    static constexpr size_type MINIMUM_CAPACITY = 8;
    static constexpr size_type MAXIMUM_CAPACITY = static_cast<SIZE_T>(-1);

private:
    static_assert(std::is_unsigned<SIZE_T>::value, "need unsigned type");

    static_assert(std::is_pod<T>::value, "forbidden type");

    size_type maxSize;
    size_type usedSize;

    T *data;

    /**
     * expand memory of old.
     * if old is null, only allocate.
     */
    static T *allocArray(T *old, SIZE_T size) noexcept {
        T *ptr = static_cast<T *>(realloc(old, sizeof(T) * size));
        if(ptr == nullptr) {
            fatal("memory allocation failed\n");
        }
        return ptr;
    }

    void moveElements(iterator src, iterator dest) noexcept {
        if(src == dest) {
            return;
        }

        memmove(dest, src, sizeof(T) * (this->end() - src));
        if(src < dest) {
            this->usedSize += (dest - src);
        } else {
            this->usedSize -= (src - dest);
        }
    }

    /**
     * if out of range, abort
     */
    void checkRange(size_type index) const;

    FlexBuffer &push_back_impl(const T &value);

public:
    NON_COPYABLE(FlexBuffer);

    /**
     * default initial size is equivalent to MINIMUM_CAPACITY
     */
    explicit FlexBuffer(size_type initSize) :
            maxSize(initSize < MINIMUM_CAPACITY ? MINIMUM_CAPACITY : initSize),
            usedSize(0),
            data(allocArray(nullptr, this->maxSize)) { }

    FlexBuffer(std::initializer_list<T> list) : FlexBuffer(list.size()) {
        for(auto iter = list.begin(); iter != list.end(); ++iter) {
            this->data[this->usedSize++] = *iter;
        }
    }

    /**
     * for lazy allocation
     */
    FlexBuffer() noexcept : maxSize(0), usedSize(0), data(nullptr) { }

    FlexBuffer(FlexBuffer &&buffer) noexcept :
            maxSize(buffer.maxSize), usedSize(buffer.usedSize), data(extract(std::move(buffer))) { }

    ~FlexBuffer() {
        free(this->data);
    }

    FlexBuffer &operator=(FlexBuffer &&buffer) noexcept {
        FlexBuffer tmp(std::move(buffer));
        this->swap(tmp);
        return *this;
    }

    FlexBuffer &operator+=(const T &value) {
        return this->push_back_impl(value);
    }

    FlexBuffer &operator+=(T &&value) {
        return this->push_back_impl(value);
    }

    /**
     * buffer.data is not equivalent to this.data.
     */
    FlexBuffer &operator+=(const FlexBuffer &buffer);

    FlexBuffer &operator+=(FlexBuffer &&buffer);

    template <std::size_t N>
    FlexBuffer &operator+=(const T (&value)[N]) {
        return this->append(value, N);
    }

    /**
     * value is not equivalent to this.data.
     */
    FlexBuffer &append(const T *value, size_type size);

    size_type capacity() const noexcept {
        return this->maxSize;
    }

    size_type size() const noexcept {
        return this->usedSize;
    }

    bool empty() const noexcept {
        return this->size() == 0;
    }

    const T *get() const noexcept {
        return this->data;
    }

    void clear() noexcept {
        this->usedSize = 0;
    }

    void swap(FlexBuffer &buf) noexcept {
        std::swap(this->usedSize, buf.usedSize);
        std::swap(this->maxSize, buf.maxSize);
        std::swap(this->data, buf.data);
    }

    /**
     * capacity will be at least reservingSize.
     */
    void reserve(size_type reservingSize);

    iterator begin() noexcept {
        return this->data;
    }

    iterator end() noexcept {
        return this->data + this->usedSize;
    }

    const_iterator begin() const noexcept {
        return this->data;
    }

    const_iterator end() const noexcept {
        return this->data + this->usedSize;
    }

    reference front() noexcept {
        return this->operator[](0);
    }

    const_reference front() const noexcept {
        return this->operator[](0);
    }

    reference back() noexcept {
        return this->operator[](this->usedSize - 1);
    }

    const_reference back() const noexcept {
        return this->operator[](this->usedSize - 1);
    }

    void push_back(const T &value) {
        this->push_back_impl(value);
    }

    void push_back(T &&value) {
        this->push_back_impl(value);
    }

    void pop_back() noexcept {
        this->usedSize--;
    }

    reference operator[](size_type index) noexcept {
        return this->data[index];
    }

    const_reference operator[](size_type index) const noexcept {
        return this->data[index];
    }

    reference at(size_type index);

    const_reference at(size_type index) const;

    /**
     * pos (begin() <= pos <= end()).
     * return position inserted element.
     */
    iterator insert(const_iterator pos, const T &value);

    /**
     * pos must not equivalent to this->end().
     */
    iterator erase(const_iterator pos) noexcept;

    /**
     * first must be last or less. (first <= last).
     * last must be this->end() or less. (last <= this->end())
     * first is inclusive, last is exclusive.
     */
    iterator erase(const_iterator first, const_iterator last) noexcept;

    void assign(size_type n, const T &value);

    /**
     * extract data. after call it, maxSize and usedSize is 0, and data is null.
     * call free() to release returned pointer.
     */
    friend T *extract(FlexBuffer &&buf) noexcept {
        buf.maxSize = 0;
        buf.usedSize = 0;
        T *ptr = buf.data;
        buf.data = nullptr;
        return ptr;
    }
};

// ########################
// ##     FlexBuffer     ##
// ########################

template <typename T, typename SIZE_T>
constexpr typename FlexBuffer<T, SIZE_T>::size_type FlexBuffer<T, SIZE_T>::MINIMUM_CAPACITY;

template <typename T, typename SIZE_T>
constexpr typename FlexBuffer<T, SIZE_T>::size_type FlexBuffer<T, SIZE_T>::MAXIMUM_CAPACITY;

template <typename T, typename SIZE_T>
void FlexBuffer<T, SIZE_T>::checkRange(size_type index) const {
    if(index >= this->usedSize) {
        fatal("size is: %d, but index is: %d\n", this->usedSize, index);
    }
}

template <typename T, typename SIZE_T>
FlexBuffer<T, SIZE_T> &FlexBuffer<T, SIZE_T>::push_back_impl(const T &value) {
    this->reserve(this->usedSize + 1);
    this->data[this->usedSize++] = value;
    return *this;
}

template <typename T, typename SIZE_T>
FlexBuffer<T, SIZE_T> &FlexBuffer<T, SIZE_T>::operator+=(const FlexBuffer<T, SIZE_T> &buffer) {
    return this->append(buffer.get(), buffer.size());
}

template <typename T, typename SIZE_T>
FlexBuffer<T, SIZE_T> &FlexBuffer<T, SIZE_T>::operator+=(FlexBuffer<T, SIZE_T> &&buffer) {
    FlexBuffer<T, SIZE_T> tmp(std::move(buffer));
    *this += tmp;
    return *this;
}

template <typename T, typename SIZE_T>
FlexBuffer<T, SIZE_T> &FlexBuffer<T, SIZE_T>::append(const T *value, size_type size) {
    if(this->data == value) {
        fatal("appending own buffer\n");
    }
    this->reserve(this->usedSize + size);
    memcpy(this->data + this->usedSize, value, sizeof(T) * size);
    this->usedSize += size;
    return *this;
}

template <typename T, typename SIZE_T>
void FlexBuffer<T, SIZE_T>::reserve(size_type reservingSize) {
    if(reservingSize > this->maxSize) {
        std::size_t newSize = (this->maxSize == 0 ? MINIMUM_CAPACITY : this->maxSize);
        while(newSize < reservingSize) {
            newSize += (newSize >> 1);
        }

        if(newSize > MAXIMUM_CAPACITY) {
            fatal("reach maximum capacity\n");
        }

        this->maxSize = newSize;
        this->data = allocArray(this->data, newSize);
    }
}

template <typename T, typename SIZE_T>
typename FlexBuffer<T, SIZE_T>::reference FlexBuffer<T, SIZE_T>::at(size_type index) {
    this->checkRange(index);
    return this->data[index];
}

template <typename T, typename SIZE_T>
typename FlexBuffer<T, SIZE_T>::const_reference FlexBuffer<T, SIZE_T>::at(size_type index) const {
    this->checkRange(index);
    return this->data[index];
}

template <typename T, typename SIZE_T>
typename FlexBuffer<T, SIZE_T>::iterator FlexBuffer<T, SIZE_T>::insert(const_iterator pos, const T &value) {
    assert(pos >= this->begin() && pos <= this->end());

    const size_type index = pos - this->begin();
    this->reserve(this->size() + 1);
    iterator iter = this->begin() + index;

    this->moveElements(iter, iter + 1);
    this->data[index] = value;

    return iter;
}

template <typename T, typename SIZE_T>
typename FlexBuffer<T, SIZE_T>::iterator FlexBuffer<T, SIZE_T>::erase(const_iterator pos) noexcept {
    assert(pos < this->end());

    const size_type index = pos - this->begin();
    iterator iter = this->begin() + index;

    this->moveElements(iter + 1, iter);

    return iter;
}

template <typename T, typename SIZE_T>
typename FlexBuffer<T, SIZE_T>::iterator FlexBuffer<T, SIZE_T>::erase(const_iterator first, const_iterator last) noexcept {
    assert(last <= this->end());
    assert(first <= last);

    const size_type index = first - this->begin();
    iterator iter = this->begin() + index;

    this->moveElements(iter + (last - first), iter);

    return iter;
}

template <typename T, typename SIZE_T>
void FlexBuffer<T, SIZE_T>::assign(size_type n, const T &value) {
    this->reserve(this->usedSize + n);
    for(unsigned int i = 0; i < n; i++) {
        this->data[this->usedSize++] = value;
    }
}

using ByteBuffer = FlexBuffer<char>;

// for byte reading
template <unsigned int N>
inline unsigned long readN(const unsigned char *ptr, unsigned int index) noexcept {
    static_assert(N > 0 && N < 9, "out of range");

    ptr += index;
    unsigned long v = 0;
    for(int i = N; i > 0; i--) {
        v |= static_cast<unsigned long>(*(ptr++)) << ((i - 1) * 8);
    }
    return v;
}

inline unsigned char read8(const unsigned char *const code, unsigned int index) noexcept {
    return readN<1>(code, index);
}

inline unsigned short read16(const unsigned char *const code, unsigned int index) noexcept {
    return readN<2>(code, index);
}

inline unsigned int read24(const unsigned char *const code, unsigned int index) noexcept {
    return readN<3>(code, index);
}

inline unsigned int read32(const unsigned char *const code, unsigned int index) noexcept {
    return readN<4>(code, index);
}

inline unsigned long read64(const unsigned char *const code, unsigned int index) noexcept {
    return readN<8>(code, index);
}

// for byte writing
template <unsigned int N>
inline void writeN(unsigned char *ptr, unsigned long b) noexcept {
    static_assert(N > 0 && N < 9, "out of range");

    for(unsigned int i = N; i > 0; --i) {
        const unsigned long mask = static_cast<unsigned long>(0xFF) << ((i - 1) * 8);
        *(ptr++) = (b & mask) >> ((i - 1) * 8);
    }
}

inline void write8(unsigned char *ptr, unsigned char b) noexcept {
    writeN<1>(ptr, b);
}

inline void write16(unsigned char *ptr, unsigned short b) noexcept {
    writeN<2>(ptr, b);
}

inline void write24(unsigned char *ptr, unsigned int b) noexcept {
    writeN<3>(ptr, b);
}

inline void write32(unsigned char *ptr, unsigned int b) noexcept {
    writeN<4>(ptr, b);
}

inline void write64(unsigned char *ptr, unsigned long b) noexcept {
    writeN<8>(ptr, b);
}

} // namespace ydsh

#endif //YDSH_MISC_BUFFER_HPP
<|endoftext|>