<commit_before>/**
 * BBC Vamp plugin collection
 *
 * Copyright (c) 2011-2014 British Broadcasting Corporation
 *
 * 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 "Energy.h"
/// @cond

Energy::Energy(float inputSampleRate):Plugin(inputSampleRate)
{
  sampleRate = inputSampleRate;
	threshRatio = 1;
	useRoot = true;
  prevRMS=0;
  avgWindowLength=1;
  avgPercentile=3;
  dipThresh=3;
}

Energy::~Energy()
{
}

string
Energy::getIdentifier() const
{
    return "bbc-energy";
}

string
Energy::getName() const
{
    return "Energy";
}

string
Energy::getDescription() const
{
    return "";
}

string
Energy::getMaker() const
{
    return "BBC";
}

int
Energy::getPluginVersion() const
{
    return 3;
}

string
Energy::getCopyright() const
{
    return "(c) 2014 British Broadcasting Corporation";
}

Energy::InputDomain
Energy::getInputDomain() const
{
    return TimeDomain;
}

size_t
Energy::getPreferredBlockSize() const
{
    return 1024;
}

size_t
Energy::getPreferredStepSize() const
{
    return 1024;
}

size_t
Energy::getMinChannelCount() const
{
    return 1;
}

size_t
Energy::getMaxChannelCount() const
{
    return 1;
}

Energy::ParameterList
Energy::getParameterDescriptors() const
{
    ParameterList list;

    ParameterDescriptor root;
    root.identifier = "root";
    root.name = "Use root";
    root.description = "Whether to apply root to energy calc.";
    root.unit = "";
    root.minValue = 0;
    root.maxValue = 1;
    root.defaultValue = 1;
    root.isQuantized = true;
    root.quantizeStep = 1;
    list.push_back(root);

    ParameterDescriptor avgwindow;
    avgwindow.identifier = "avgwindow";
    avgwindow.name = "Moving average window size";
    avgwindow.description = "Size of moving averagw window, in seconds.";
    avgwindow.unit = "seconds";
    avgwindow.minValue = 0.001;
    avgwindow.maxValue = 10;
    avgwindow.defaultValue = 1;
    avgwindow.isQuantized = false;
    list.push_back(avgwindow);

    ParameterDescriptor avgpercentile;
    avgpercentile.identifier = "avgpercentile";
    avgpercentile.name = "Moving average percentile";
    avgpercentile.description = "Percentile to use when calculating moving average.";
    avgpercentile.unit = "";
    avgpercentile.minValue = 0;
    avgpercentile.maxValue = 100;
    avgpercentile.defaultValue = 3;
    avgpercentile.isQuantized = false;
    list.push_back(avgpercentile);

    ParameterDescriptor dipthresh;
    dipthresh.identifier = "dipthresh";
    dipthresh.name = "Dip threshold";
    dipthresh.description = "Threshold for calculating dips, as multiple of the moving average.";
    dipthresh.unit = "";
    dipthresh.minValue = 0;
    dipthresh.maxValue = 10;
    dipthresh.defaultValue = 3;
    dipthresh.isQuantized = false;
    list.push_back(dipthresh);

    ParameterDescriptor threshold;
    threshold.identifier = "threshold";
    threshold.name = "Low energy threshold";
    threshold.description = "Threshold to use for low energy, as a multiple of mean energy.";
    threshold.unit = "";
    threshold.minValue = 0;
    threshold.maxValue = 10;
    threshold.defaultValue = 1;
    threshold.isQuantized = false;
    list.push_back(threshold);

    return list;
}

float
Energy::getParameter(string identifier) const
{
    if (identifier == "threshold") {
        return threshRatio;
    }
    else if (identifier == "root")
    {
    	return useRoot;
    }
    else if (identifier == "avgwindow")
    {
    	return avgWindowLength;
    }
    else if (identifier == "avgpercentile")
    {
    	return avgPercentile;
    }
    else if (identifier == "dipthresh")
    {
      return dipThresh;
    }

    return 0;
}

void
Energy::setParameter(string identifier, float value)
{
    if (identifier == "threshold") {
    	threshRatio = value;
    }
    else if (identifier == "root")
    {
    	if (value == 1)
    		useRoot = true;
    	else
    		useRoot = false;
    }
    else if (identifier == "avgwindow")
    {
      avgWindowLength = value;
    }
    else if (identifier == "avgpercentile")
    {
      avgPercentile = value;
    }
    else if (identifier == "dipthresh")
    {
      dipThresh = value;
    }
}

Energy::ProgramList
Energy::getPrograms() const
{
    ProgramList list;

    return list;
}

string
Energy::getCurrentProgram() const
{
    return "";
}

void
Energy::selectProgram(string name)
{
}

Energy::OutputList
Energy::getOutputDescriptors() const
{
    OutputList list;

    OutputDescriptor rmsenergy;
    rmsenergy.identifier = "rmsenergy";
    rmsenergy.name = "RMS Energy";
    rmsenergy.description = "RMS of the signal.";
    rmsenergy.unit = "";
    rmsenergy.hasFixedBinCount = true;
    rmsenergy.binCount = 1;
    rmsenergy.hasKnownExtents = false;
    rmsenergy.isQuantized = false;
    rmsenergy.sampleType = OutputDescriptor::OneSamplePerStep;
    rmsenergy.hasDuration = false;
    list.push_back(rmsenergy);

    OutputDescriptor rmsdelta;
    rmsdelta.identifier = "rmsdelta";
    rmsdelta.name = "RMS Energy Delta";
    rmsdelta.description = "Difference between RMS of previous and current blocks.";
    rmsdelta.unit = "";
    rmsdelta.hasFixedBinCount = true;
    rmsdelta.binCount = 1;
    rmsdelta.hasKnownExtents = false;
    rmsdelta.isQuantized = false;
    rmsdelta.sampleType = OutputDescriptor::OneSamplePerStep;
    rmsdelta.hasDuration = false;
    list.push_back(rmsdelta);

    OutputDescriptor lowenergy;
    lowenergy.identifier = "lowenergy";
    lowenergy.name = "Low Energy";
    lowenergy.description = "Percentage of track which is below the low energy threshold.";
    lowenergy.unit = "";
    lowenergy.hasFixedBinCount = true;
    lowenergy.binCount = 1;
    lowenergy.hasKnownExtents = false;
    lowenergy.isQuantized = false;
    lowenergy.sampleType = OutputDescriptor::VariableSampleRate;
    lowenergy.sampleRate = 0;
    lowenergy.hasDuration = false;
    list.push_back(lowenergy);

    OutputDescriptor average;
    average.identifier = "average";
    average.name = "Moving Average";
    average.description = "Mean of RMS values over moving average window.";
    average.unit = "";
    average.hasFixedBinCount = true;
    average.binCount = 1;
    average.hasKnownExtents = false;
    average.isQuantized = false;
    average.sampleType = OutputDescriptor::FixedSampleRate;
    average.sampleRate = (float)sampleRate/(float)m_stepSize;
    average.hasDuration = false;
    list.push_back(average);

    OutputDescriptor pdip;
    pdip.identifier = "pdip";
    pdip.name = "Dip probability";
    pdip.description = "Probability of the RMS energy dipping below the threshold.";
    pdip.unit = "";
    pdip.hasFixedBinCount = true;
    pdip.binCount = 1;
    pdip.hasKnownExtents = false;
    pdip.isQuantized = false;
    pdip.sampleType = OutputDescriptor::FixedSampleRate;
    pdip.sampleRate = (float)sampleRate/(float)m_stepSize;
    pdip.hasDuration = false;
    list.push_back(pdip);

    return list;
}

bool
Energy::initialise(size_t channels, size_t stepSize, size_t blockSize)
{
    if (channels < getMinChannelCount() ||
	channels > getMaxChannelCount()) return false;

    m_blockSize = blockSize;
    m_stepSize = stepSize;
    reset();

    return true;
}

void
Energy::reset()
{
	rmsEnergy.clear();
}

Energy::FeatureSet
Energy::process(const float *const *inputBuffers, Vamp::RealTime timestamp)
{
	FeatureSet output;
	Feature fRMS, fDelta;
	float totalEnergy = 0.f;
	float rms;

  // find total energy for frame
	for (int i=0; i<m_blockSize; i++)
	{
		totalEnergy += inputBuffers[0][i]*inputBuffers[0][i];
	}

  // apply square root
	if (useRoot)
		rms = sqrt(totalEnergy / (float)m_blockSize);
	else
		rms = totalEnergy / (float)m_blockSize;
	rmsEnergy.push_back(rms);

  // return RMS and delta
	fRMS.values.push_back(rms);
	output[0].push_back(fRMS);
  fDelta.values.push_back(std::abs(rms-prevRMS));
  output[1].push_back(fDelta);

  // save RMS of current frame
  prevRMS=rms;

  return output;
}

Energy::FeatureSet
Energy::getRemainingFeatures()
{
	FeatureSet output;
  vector<float> rmsAvg;
	float total = 0.f, average = 0.f;
	float lowEnergy = 0.f, highEnergy = 0.f;

  // set window size
  float avgWindowSize = avgWindowLength*sampleRate/(float)m_blockSize;
  int avgWindowOffsetL = (int)floor(avgWindowSize/2.0);
  int avgWindowOffsetR = (int)ceil(avgWindowSize/2.0);

	for (unsigned i=0; i<rmsEnergy.size(); i++)
	{
	  // find total of RMS energy values
		total += rmsEnergy.at(i);

    // get start and end of window
    int start = i-avgWindowOffsetL;
    if (start<0) start=0;
    int end = i+avgWindowOffsetR-1;
    if (end>=rmsEnergy.size()) end = rmsEnergy.size()-1;

    // copy window
    vector<float>::const_iterator first = rmsEnergy.begin() + start;
    vector<float>::const_iterator last = rmsEnergy.begin() + end + 1;
    vector<float> window(first, last);

    // sort window
    std::sort(window.begin(), window.end());

    // find Xth percentile of window
    int pos = (int)((float)(window.size()-1) / 100.0 * avgPercentile);
    rmsAvg.push_back(window[pos]);

    // return moving average
    Feature fAvg;
    fAvg.values.push_back(rmsAvg[i]);
    output[3].push_back(fAvg);
	}

  // find mean of all RMS values
	if (rmsEnergy.size() != 0)
		average = total / (float)rmsEnergy.size();

	// find threshold value
	float threshLowEnergy = average * threshRatio;

	for (unsigned i=0; i<rmsEnergy.size(); i++)
	{
	  // find number of frames above/below low energy threshold
		if (rmsEnergy.at(i) < threshLowEnergy)
			lowEnergy++;
		else
			highEnergy++;

    // get start and end of window
    int start = i-avgWindowOffsetL;
    if (start<0) start=0;
    int end = i+avgWindowOffsetR-1;
    if (end>=rmsEnergy.size()) end = rmsEnergy.size()-1;

    // count dips below moving average * dipThresh
    float dipCount = 0;
    float threshDip = rmsAvg[i]*dipThresh;
    for (unsigned int j=start; j<=end; j++)
    {
      if (rmsEnergy[j] < threshDip)
        dipCount++;
    }

    // return dip probability
    Feature fProb;
    fProb.values.push_back(dipCount/(float)(end-start));
    output[4].push_back(fProb);
	}

	// calculate low energy ratio
	float lowEnergyRatio = 0.f;
	if (lowEnergy + highEnergy != 0)
		lowEnergyRatio = (100.f * lowEnergy) / (lowEnergy + highEnergy);

  // return low energy
	Feature fLowEnergy;
	fLowEnergy.hasTimestamp = true;
	fLowEnergy.timestamp = Vamp::RealTime::fromSeconds(0);
	fLowEnergy.values.push_back(lowEnergyRatio);
	output[2].push_back(fLowEnergy);

  return output;
}

/// @endcond
<commit_msg>Fixed bug with not resetting prevRMS in Energy<commit_after>/**
 * BBC Vamp plugin collection
 *
 * Copyright (c) 2011-2014 British Broadcasting Corporation
 *
 * 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 "Energy.h"
/// @cond

Energy::Energy(float inputSampleRate):Plugin(inputSampleRate)
{
  sampleRate = inputSampleRate;
	threshRatio = 1;
	useRoot = true;
  prevRMS=0;
  avgWindowLength=1;
  avgPercentile=3;
  dipThresh=3;
}

Energy::~Energy()
{
}

string
Energy::getIdentifier() const
{
    return "bbc-energy";
}

string
Energy::getName() const
{
    return "Energy";
}

string
Energy::getDescription() const
{
    return "";
}

string
Energy::getMaker() const
{
    return "BBC";
}

int
Energy::getPluginVersion() const
{
    return 3;
}

string
Energy::getCopyright() const
{
    return "(c) 2014 British Broadcasting Corporation";
}

Energy::InputDomain
Energy::getInputDomain() const
{
    return TimeDomain;
}

size_t
Energy::getPreferredBlockSize() const
{
    return 1024;
}

size_t
Energy::getPreferredStepSize() const
{
    return 1024;
}

size_t
Energy::getMinChannelCount() const
{
    return 1;
}

size_t
Energy::getMaxChannelCount() const
{
    return 1;
}

Energy::ParameterList
Energy::getParameterDescriptors() const
{
    ParameterList list;

    ParameterDescriptor root;
    root.identifier = "root";
    root.name = "Use root";
    root.description = "Whether to apply root to energy calc.";
    root.unit = "";
    root.minValue = 0;
    root.maxValue = 1;
    root.defaultValue = 1;
    root.isQuantized = true;
    root.quantizeStep = 1;
    list.push_back(root);

    ParameterDescriptor avgwindow;
    avgwindow.identifier = "avgwindow";
    avgwindow.name = "Moving average window size";
    avgwindow.description = "Size of moving averagw window, in seconds.";
    avgwindow.unit = "seconds";
    avgwindow.minValue = 0.001;
    avgwindow.maxValue = 10;
    avgwindow.defaultValue = 1;
    avgwindow.isQuantized = false;
    list.push_back(avgwindow);

    ParameterDescriptor avgpercentile;
    avgpercentile.identifier = "avgpercentile";
    avgpercentile.name = "Moving average percentile";
    avgpercentile.description = "Percentile to use when calculating moving average.";
    avgpercentile.unit = "";
    avgpercentile.minValue = 0;
    avgpercentile.maxValue = 100;
    avgpercentile.defaultValue = 3;
    avgpercentile.isQuantized = false;
    list.push_back(avgpercentile);

    ParameterDescriptor dipthresh;
    dipthresh.identifier = "dipthresh";
    dipthresh.name = "Dip threshold";
    dipthresh.description = "Threshold for calculating dips, as multiple of the moving average.";
    dipthresh.unit = "";
    dipthresh.minValue = 0;
    dipthresh.maxValue = 10;
    dipthresh.defaultValue = 3;
    dipthresh.isQuantized = false;
    list.push_back(dipthresh);

    ParameterDescriptor threshold;
    threshold.identifier = "threshold";
    threshold.name = "Low energy threshold";
    threshold.description = "Threshold to use for low energy, as a multiple of mean energy.";
    threshold.unit = "";
    threshold.minValue = 0;
    threshold.maxValue = 10;
    threshold.defaultValue = 1;
    threshold.isQuantized = false;
    list.push_back(threshold);

    return list;
}

float
Energy::getParameter(string identifier) const
{
    if (identifier == "threshold") {
        return threshRatio;
    }
    else if (identifier == "root")
    {
    	return useRoot;
    }
    else if (identifier == "avgwindow")
    {
    	return avgWindowLength;
    }
    else if (identifier == "avgpercentile")
    {
    	return avgPercentile;
    }
    else if (identifier == "dipthresh")
    {
      return dipThresh;
    }

    return 0;
}

void
Energy::setParameter(string identifier, float value)
{
    if (identifier == "threshold") {
    	threshRatio = value;
    }
    else if (identifier == "root")
    {
    	if (value == 1)
    		useRoot = true;
    	else
    		useRoot = false;
    }
    else if (identifier == "avgwindow")
    {
      avgWindowLength = value;
    }
    else if (identifier == "avgpercentile")
    {
      avgPercentile = value;
    }
    else if (identifier == "dipthresh")
    {
      dipThresh = value;
    }
}

Energy::ProgramList
Energy::getPrograms() const
{
    ProgramList list;

    return list;
}

string
Energy::getCurrentProgram() const
{
    return "";
}

void
Energy::selectProgram(string name)
{
}

Energy::OutputList
Energy::getOutputDescriptors() const
{
    OutputList list;

    OutputDescriptor rmsenergy;
    rmsenergy.identifier = "rmsenergy";
    rmsenergy.name = "RMS Energy";
    rmsenergy.description = "RMS of the signal.";
    rmsenergy.unit = "";
    rmsenergy.hasFixedBinCount = true;
    rmsenergy.binCount = 1;
    rmsenergy.hasKnownExtents = false;
    rmsenergy.isQuantized = false;
    rmsenergy.sampleType = OutputDescriptor::OneSamplePerStep;
    rmsenergy.hasDuration = false;
    list.push_back(rmsenergy);

    OutputDescriptor rmsdelta;
    rmsdelta.identifier = "rmsdelta";
    rmsdelta.name = "RMS Energy Delta";
    rmsdelta.description = "Difference between RMS of previous and current blocks.";
    rmsdelta.unit = "";
    rmsdelta.hasFixedBinCount = true;
    rmsdelta.binCount = 1;
    rmsdelta.hasKnownExtents = false;
    rmsdelta.isQuantized = false;
    rmsdelta.sampleType = OutputDescriptor::OneSamplePerStep;
    rmsdelta.hasDuration = false;
    list.push_back(rmsdelta);

    OutputDescriptor lowenergy;
    lowenergy.identifier = "lowenergy";
    lowenergy.name = "Low Energy";
    lowenergy.description = "Percentage of track which is below the low energy threshold.";
    lowenergy.unit = "";
    lowenergy.hasFixedBinCount = true;
    lowenergy.binCount = 1;
    lowenergy.hasKnownExtents = false;
    lowenergy.isQuantized = false;
    lowenergy.sampleType = OutputDescriptor::VariableSampleRate;
    lowenergy.sampleRate = 0;
    lowenergy.hasDuration = false;
    list.push_back(lowenergy);

    OutputDescriptor average;
    average.identifier = "average";
    average.name = "Moving Average";
    average.description = "Mean of RMS values over moving average window.";
    average.unit = "";
    average.hasFixedBinCount = true;
    average.binCount = 1;
    average.hasKnownExtents = false;
    average.isQuantized = false;
    average.sampleType = OutputDescriptor::FixedSampleRate;
    average.sampleRate = (float)sampleRate/(float)m_stepSize;
    average.hasDuration = false;
    list.push_back(average);

    OutputDescriptor pdip;
    pdip.identifier = "pdip";
    pdip.name = "Dip probability";
    pdip.description = "Probability of the RMS energy dipping below the threshold.";
    pdip.unit = "";
    pdip.hasFixedBinCount = true;
    pdip.binCount = 1;
    pdip.hasKnownExtents = false;
    pdip.isQuantized = false;
    pdip.sampleType = OutputDescriptor::FixedSampleRate;
    pdip.sampleRate = (float)sampleRate/(float)m_stepSize;
    pdip.hasDuration = false;
    list.push_back(pdip);

    return list;
}

bool
Energy::initialise(size_t channels, size_t stepSize, size_t blockSize)
{
    if (channels < getMinChannelCount() ||
	channels > getMaxChannelCount()) return false;

    m_blockSize = blockSize;
    m_stepSize = stepSize;
    reset();

    return true;
}

void
Energy::reset()
{
	rmsEnergy.clear();
  prevRMS=0;
}

Energy::FeatureSet
Energy::process(const float *const *inputBuffers, Vamp::RealTime timestamp)
{
	FeatureSet output;
	Feature fRMS, fDelta;
	float totalEnergy = 0.f;
	float rms;

  // find total energy for frame
	for (int i=0; i<m_blockSize; i++)
	{
		totalEnergy += inputBuffers[0][i]*inputBuffers[0][i];
	}

  // apply square root
	if (useRoot)
		rms = sqrt(totalEnergy / (float)m_blockSize);
	else
		rms = totalEnergy / (float)m_blockSize;
	rmsEnergy.push_back(rms);

  // return RMS and delta
	fRMS.values.push_back(rms);
	output[0].push_back(fRMS);
  fDelta.values.push_back(std::abs(rms-prevRMS));
  output[1].push_back(fDelta);

  // save RMS of current frame
  prevRMS=rms;

  return output;
}

Energy::FeatureSet
Energy::getRemainingFeatures()
{
	FeatureSet output;
  vector<float> rmsAvg;
	float total = 0.f, average = 0.f;
	float lowEnergy = 0.f, highEnergy = 0.f;

  // set window size
  float avgWindowSize = avgWindowLength*sampleRate/(float)m_blockSize;
  int avgWindowOffsetL = (int)floor(avgWindowSize/2.0);
  int avgWindowOffsetR = (int)ceil(avgWindowSize/2.0);

	for (unsigned i=0; i<rmsEnergy.size(); i++)
	{
	  // find total of RMS energy values
		total += rmsEnergy.at(i);

    // get start and end of window
    int start = i-avgWindowOffsetL;
    if (start<0) start=0;
    int end = i+avgWindowOffsetR-1;
    if (end>=rmsEnergy.size()) end = rmsEnergy.size()-1;

    // copy window
    vector<float>::const_iterator first = rmsEnergy.begin() + start;
    vector<float>::const_iterator last = rmsEnergy.begin() + end + 1;
    vector<float> window(first, last);

    // sort window
    std::sort(window.begin(), window.end());

    // find Xth percentile of window
    int pos = (int)((float)(window.size()-1) / 100.0 * avgPercentile);
    rmsAvg.push_back(window[pos]);

    // return moving average
    Feature fAvg;
    fAvg.values.push_back(rmsAvg[i]);
    output[3].push_back(fAvg);
	}

  // find mean of all RMS values
	if (rmsEnergy.size() != 0)
		average = total / (float)rmsEnergy.size();

	// find threshold value
	float threshLowEnergy = average * threshRatio;

	for (unsigned i=0; i<rmsEnergy.size(); i++)
	{
	  // find number of frames above/below low energy threshold
		if (rmsEnergy.at(i) < threshLowEnergy)
			lowEnergy++;
		else
			highEnergy++;

    // get start and end of window
    int start = i-avgWindowOffsetL;
    if (start<0) start=0;
    int end = i+avgWindowOffsetR-1;
    if (end>=rmsEnergy.size()) end = rmsEnergy.size()-1;

    // count dips below moving average * dipThresh
    float dipCount = 0;
    float threshDip = rmsAvg[i]*dipThresh;
    for (unsigned int j=start; j<=end; j++)
    {
      if (rmsEnergy[j] < threshDip)
        dipCount++;
    }

    // return dip probability
    Feature fProb;
    fProb.values.push_back(dipCount/(float)(end-start));
    output[4].push_back(fProb);
	}

	// calculate low energy ratio
	float lowEnergyRatio = 0.f;
	if (lowEnergy + highEnergy != 0)
		lowEnergyRatio = (100.f * lowEnergy) / (lowEnergy + highEnergy);

  // return low energy
	Feature fLowEnergy;
	fLowEnergy.hasTimestamp = true;
	fLowEnergy.timestamp = Vamp::RealTime::fromSeconds(0);
	fLowEnergy.values.push_back(lowEnergyRatio);
	output[2].push_back(fLowEnergy);

  return output;
}

/// @endcond
<|endoftext|>


<commit_before>#ifndef CYCLE__H__
#define CYCLE__H__

#include "iterbase.hpp"

#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    //Forward declarations of Cycle and cycle
    template <typename Container>
    class Cycle;

    template <typename Container>
    Cycle<Container> cycle(Container &&);

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(
            std::initializer_list<T> &&);

    template <typename Container>
    class Cycle : public IterBase<Container>{
        private:
            // The cycle function is the only thing allowed to create a Cycle
            friend Cycle cycle<Container>(Container &&);
            template <typename T>
            friend Cycle<std::initializer_list<T>> cycle(
                    std::initializer_list<T> &&);

            using typename IterBase<Container>::contained_iter_type;

            using typename IterBase<Container>::contained_iter_ret;

            Container & container;

            // Value constructor for use only in the cycle function
            Cycle(Container && container) : container(container) { }
            Cycle () = delete;
            Cycle & operator=(const Cycle &) = delete;

        public:
            Cycle(const Cycle &) = default;
            class Iterator {
                private:
                    contained_iter_type sub_iter;
                    const contained_iter_type begin;
                    const contained_iter_type end;
                public:
                    Iterator (contained_iter_type iter,
                            contained_iter_type end) :
                        sub_iter(iter),
                        begin(iter),
                        end(end)
                    { }

                    contained_iter_ret operator*() const {
                        return *this->sub_iter;
                    }

                    Iterator & operator++() {
                        ++this->sub_iter;
                        // reset to beginning upon reaching the end
                        if (!(this->sub_iter != this->end)) {
                            this->sub_iter = this->begin;
                        }
                        return *this;
                    }

                    constexpr bool operator!=(const Iterator &) const {
                        return true;
                    }
            };

            Iterator begin() const {
                return Iterator(std::begin(this->container),
                        std::end(this->container));
            }

            Iterator end() const {
                return Iterator(std::end(this->container),
                    std::end(this->container));
            }

    };

    // Helper function to instantiate an Filter
    template <typename Container>
    Cycle<Container> cycle(Container && container) {
        return Cycle<Container>(std::forward<Container>(container));
    }

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(std::initializer_list<T> && il)
    {
        return Cycle<std::initializer_list<T>>(std::move(il));
    }
}

#endif //ifndef CYCLE__H__
<commit_msg>Removes cycle's requirement on iterator assignment<commit_after>#ifndef CYCLE__H__
#define CYCLE__H__

#include "iterbase.hpp"

#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    //Forward declarations of Cycle and cycle
    template <typename Container>
    class Cycle;

    template <typename Container>
    Cycle<Container> cycle(Container &&);

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(
            std::initializer_list<T> &&);

    template <typename Container>
    class Cycle : public IterBase<Container>{
        private:
            // The cycle function is the only thing allowed to create a Cycle
            friend Cycle cycle<Container>(Container &&);
            template <typename T>
            friend Cycle<std::initializer_list<T>> cycle(
                    std::initializer_list<T> &&);

            using typename IterBase<Container>::contained_iter_type;

            using typename IterBase<Container>::contained_iter_ret;

            Container & container;

            // Value constructor for use only in the cycle function
            Cycle(Container && container) : container(container) { }
            Cycle () = delete;
            Cycle & operator=(const Cycle &) = delete;

        public:
            Cycle(const Cycle &) = default;
            class Iterator {
                private:
                    contained_iter_type sub_iter;
                    const contained_iter_type begin;
                    const contained_iter_type end;
                public:
                    Iterator (contained_iter_type iter,
                            contained_iter_type end) :
                        sub_iter(iter),
                        begin(iter),
                        end(end)
                    { }

                    contained_iter_ret operator*() const {
                        return *this->sub_iter;
                    }

                    Iterator & operator++() {
                        ++this->sub_iter;
                        // reset to beginning upon reaching the end
                        if (!(this->sub_iter != this->end)) {
                            this->sub_iter.~contained_iter_type();
                            new(&this->sub_iter) contained_iter_type(
                                    this->begin);
                        }
                        return *this;
                    }

                    constexpr bool operator!=(const Iterator &) const {
                        return true;
                    }
            };

            Iterator begin() const {
                return Iterator(std::begin(this->container),
                        std::end(this->container));
            }

            Iterator end() const {
                return Iterator(std::end(this->container),
                    std::end(this->container));
            }

    };

    // Helper function to instantiate an Filter
    template <typename Container>
    Cycle<Container> cycle(Container && container) {
        return Cycle<Container>(std::forward<Container>(container));
    }

    template <typename T>
    Cycle<std::initializer_list<T>> cycle(std::initializer_list<T> && il)
    {
        return Cycle<std::initializer_list<T>>(std::move(il));
    }
}

#endif //ifndef CYCLE__H__
<|endoftext|>


<commit_before>//解法1
//#include <iostream>
//#include <stack>
//#include<cmath>
//using namespace std;
//class MinStack {
//	typedef struct X{
//			int x;
//					int minx;
//							X(int x,int minx):x(x),minx(minx){}  //构造函数
//								}minX;
//								public:
//									void push(int x) {
//											int minx=S.empty() ? x : min(x,S.top().minx); // 最小元素
//													S.push(minX(x,minx));
//														}
//															void pop() {
//																	S.pop();
//																		}
//																			int top() {
//																					return S.top().x;
//																						}
//																							int getMin() {
//																									return S.top().minx;
//																										}
//																										private:
//																											stack<minX> S;
//																											};
//																											int main()
//																											{
//																											  MinStack S1;
//																											    int a[]={12,5,6,41,10,1,16};
//																											      for(int i=0;i<7;i++)
//																											        {
//																											        	S1.push(a[i]);
//																											        		cout<<“top=”<<S1.top()<<”  min=”<<S1.getMin()<<endl;
//																											        			if(i==1) S1.pop();
//																											        			  }
//																											        			    system(“pause”);
//																											        			    }
//
//																											        			    //解法2
//																											        			    #include <iostream>
//																											        			    #include <stack>
//																											        			    using namespace std;
//																											        			    class MinStack {
//																											        			    	typedef struct X{
//																											        			    			int min;
//																											        			    					int count;
//																											        			    							X(int min,int count):min(min),count(count){}  //构造函数
//																											        			    								}minX;
//																											        			    								public:
//																											        			    									void push(int x) {
//																											        			    											S.push(x);
//																											        			    													if(minS.empty()|| minS.top().min>x) { // 空栈 或 最小值出现
//																											        			    															   minS.push(minX(x,1));
//																											        			    															   		} else if(minS.top().min==x){  // 等于最小值
//																											        			    															   				   minS.top().count++;
//																											        			    															   				   		}
//																											        			    															   				   			}
//																											        			    															   				   				void pop() {
//																											        			    															   				   						if(S.top()==minS.top().min)
//																											        			    															   				   									if(minS.top().count>1)
//																											        			    															   				   												 minS.top().count–;
//																											        			    															   				   												 else
//																											        			    															   				   												 minS.pop();
//																											        			    															   				   												 S.pop();
//																											        			    															   				   												 }
//																											        			    															   				   												 int top() {
//																											        			    															   				   												 return S.top();
//																											        			    															   				   												 }
//																											        			    															   				   												 int getMin() {
//																											        			    															   				   												 return minS.top().min;
//																											        			    															   				   												 }
//																											        			    															   				   												 private:
//																											        			    															   				   												 stack<int> S;
//																											        			    															   				   												 stack<minX> minS;
//																											        			    															   				   												 };
//																											        			    															   				   												 int main()
//																											        			    															   				   												 {
//																											        			    															   				   												 MinStack S1;
//																											        			    															   				   												 int a[]={12,5,6,8,10,1,16};
//																											        			    															   				   												 for(int i=0;i<7;i++)
//																											        			    															   				   												 {
//																											        			    															   				   												 S1.push(a[i]);
//																											        			    															   				   												 cout<<“top=”<<S1.top()<<”  min=”<<S1.getMin()<<endl;
//																											        			    															   				   												 if(i==1) S1.pop();
//																											        			    															   				   												 }
//																											        			    															   				   												 system(“pause”);
//																											        			    															   				   												 }
//
<commit_msg>Update min-statck.cpp<commit_after>//解法1
#include <iostream>
#include <stack>
#include<cmath>
using namespace std;
class MinStack {
	typedef struct X{
		int x;
		int minx;
		X(int x,int minx):x(x),minx(minx){}  //构造函数
	}minX;
public:
	void push(int x) {
		int minx=S.empty() ? x : min(x,S.top().minx); // 最小元素
		S.push(minX(x,minx));
	}
	void pop() {
		S.pop();
	}
	int top() {
		return S.top().x;
	}
	int getMin() {
		return S.top().minx;
	}
private:
	stack<minX> S;
};
int main()
{
  MinStack S1;
  int a[]={12,5,6,41,10,1,16};
  for(int i=0;i<7;i++)
  {
	S1.push(a[i]);
	cout<<“top=”<<S1.top()<<”  min=”<<S1.getMin()<<endl;
	if(i==1) S1.pop();
  }
  system(“pause”);
}

//解法2
#include <iostream>
#include <stack>
using namespace std;
class MinStack {
	typedef struct X{
		int min;
		int count;
		X(int min,int count):min(min),count(count){}  //构造函数
	}minX;
public:
	void push(int x) {
		S.push(x);
		if(minS.empty()|| minS.top().min>x) { // 空栈 或 最小值出现
		   minS.push(minX(x,1));
		} else if(minS.top().min==x){  // 等于最小值
		   minS.top().count++;
		}
	}
	void pop() {
		if(S.top()==minS.top().min)
			if(minS.top().count>1)
			  minS.top().count–;
			else
			  minS.pop();
		S.pop();
	}
	int top() {
		return S.top();
	}
	int getMin() {
		return minS.top().min;
	}
private:
	stack<int> S;
	stack<minX> minS;
};
int main()
{
  MinStack S1;
  int a[]={12,5,6,8,10,1,16};
  for(int i=0;i<7;i++)
  {
	S1.push(a[i]);
	cout<<“top=”<<S1.top()<<”  min=”<<S1.getMin()<<endl;
	if(i==1) S1.pop();
  }
  system(“pause”);
}

<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2012-2013 Danny Y., Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef GEARS_META_META_HPP
#define GEARS_META_META_HPP

#include <type_traits>
#include <utility>

namespace gears {
template<typename T>
using Type = typename T::type;

template<typename... Args>
using CommonType = Type<std::common_type<Args...>>;

template<typename T>
using UnderlyingType = Type<std::underlying_type<T>>;

template<typename T, T t>
using Const = std::integral_constant<T,t>;

template<int i>
using Integer = Const<int,i>;

template<typename T>
struct identity {
    using type = T;
};

template<typename...>
struct void_ {
    using type = void;
};

template<typename... T>
using Void = Type<void_<T...>>;

template<bool I>
using Bool = Const<bool, I>;

template<typename Condition, typename Then, typename Else>
using If = Type<std::conditional<Condition::value, Then, Else>>;

template<typename Condition, typename Then, typename Else>
using TypeIf = Type<If<Condition, Then, Else>>;

template<typename T>
using Not = Bool<!T::value>;

template<typename... Args>
struct Any : Bool<false> {};

template<typename T, typename... Args>
struct Any<T, Args...> : If<T, Bool<true>, Any<Args...>> {};

template<typename... Args>
struct All : Bool<true> {};

template<typename T, typename... Args>
struct All<T, Args...> : If<T, All<Args...>, Bool<false>> {};

template<typename Signature, typename Anon = void>
struct result_of_impl {};

template<typename Function, typename... Args>
struct result_of_impl<Function(Args...), Void<decltype(std::declval<Function>()(std::declval<Args>()...))>> {
    using type = decltype(std::declval<Function>()(std::declval<Args>()...));
};

template<typename Signature>
using ResultOf = Type<result_of_impl<Signature>>;

template<typename T>
struct class_of {};

template<typename Signature, typename Class>
struct class_of<Signature Class::*> : identity<Class> {};

template<typename T>
using ClassOf = Type<class_of<T>>;

template<typename T>
constexpr const T& as_const(T& t) {
    return t;
}

template<typename T>
constexpr T abs(T t) {
    return t < 0 ? -t : t;
}

template<typename T>
constexpr T min(T&& t) {
    return std::forward<T>(t);
}

template<typename T, typename U>
constexpr auto min(T&& t, U&& u) -> CommonType<T,U> {
    return t < u ? std::forward<T>(t) : std::forward<U>(u);
}

template<typename T, typename U, typename... Args>
constexpr auto min(T&& t, U&& u, Args&&... args) -> CommonType<T,U,Args...> {
    return min(min(std::forward<T>(t), std::forward<U>(u)), std::forward<Args>(args)...);
}

template<typename T>
constexpr T max(T&& t) {
    return std::forward<T>(t);
}

template<typename T, typename U>
constexpr auto max(T&& t, U&& u) -> CommonType<T,U> {
    return t > u ? std::forward<T>(t) : std::forward<U>(u);
}

template<typename T, typename U, typename... Args>
constexpr auto max(T&& t, U&& u, Args&&... args) -> CommonType<T,U,Args...> {
    return max(max(std::forward<T>(t), std::forward<U>(u)), std::forward<Args>(args)...);
}
} // gears

#endif // GEARS_META_META_HPP<commit_msg>Add placeholder type for deduced template parameters<commit_after>// The MIT License (MIT)

// Copyright (c) 2012-2013 Danny Y., Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef GEARS_META_META_HPP
#define GEARS_META_META_HPP

#include <type_traits>
#include <utility>

namespace gears {
template<typename T>
using Type = typename T::type;

template<typename... Args>
using CommonType = Type<std::common_type<Args...>>;

template<typename T>
using UnderlyingType = Type<std::underlying_type<T>>;

template<typename T, T t>
using Const = std::integral_constant<T,t>;

template<int i>
using Integer = Const<int,i>;

struct deduced {};

template<typename T>
using is_deduced = std::is_same<T, deduced>;

template<typename T>
struct identity {
    using type = T;
};

template<typename...>
struct void_ {
    using type = void;
};

template<typename... T>
using Void = Type<void_<T...>>;

template<bool I>
using Bool = Const<bool, I>;

template<typename Condition, typename Then, typename Else>
using If = Type<std::conditional<Condition::value, Then, Else>>;

template<typename Condition, typename Then, typename Else>
using TypeIf = Type<If<Condition, Then, Else>>;

template<typename T>
using Not = Bool<!T::value>;

template<typename... Args>
struct Any : Bool<false> {};

template<typename T, typename... Args>
struct Any<T, Args...> : If<T, Bool<true>, Any<Args...>> {};

template<typename... Args>
struct All : Bool<true> {};

template<typename T, typename... Args>
struct All<T, Args...> : If<T, All<Args...>, Bool<false>> {};

template<typename Signature, typename Anon = void>
struct result_of_impl {};

template<typename Function, typename... Args>
struct result_of_impl<Function(Args...), Void<decltype(std::declval<Function>()(std::declval<Args>()...))>> {
    using type = decltype(std::declval<Function>()(std::declval<Args>()...));
};

template<typename Signature>
using ResultOf = Type<result_of_impl<Signature>>;

template<typename T>
struct class_of {};

template<typename Signature, typename Class>
struct class_of<Signature Class::*> : identity<Class> {};

template<typename T>
using ClassOf = Type<class_of<T>>;

template<typename T>
constexpr const T& as_const(T& t) {
    return t;
}

template<typename T>
constexpr T abs(T t) {
    return t < 0 ? -t : t;
}

template<typename T>
constexpr T min(T&& t) {
    return std::forward<T>(t);
}

template<typename T, typename U>
constexpr auto min(T&& t, U&& u) -> CommonType<T,U> {
    return t < u ? std::forward<T>(t) : std::forward<U>(u);
}

template<typename T, typename U, typename... Args>
constexpr auto min(T&& t, U&& u, Args&&... args) -> CommonType<T,U,Args...> {
    return min(min(std::forward<T>(t), std::forward<U>(u)), std::forward<Args>(args)...);
}

template<typename T>
constexpr T max(T&& t) {
    return std::forward<T>(t);
}

template<typename T, typename U>
constexpr auto max(T&& t, U&& u) -> CommonType<T,U> {
    return t > u ? std::forward<T>(t) : std::forward<U>(u);
}

template<typename T, typename U, typename... Args>
constexpr auto max(T&& t, U&& u, Args&&... args) -> CommonType<T,U,Args...> {
    return max(max(std::forward<T>(t), std::forward<U>(u)), std::forward<Args>(args)...);
}
} // gears

#endif // GEARS_META_META_HPP<|endoftext|>


<commit_before>#include <iostream>
#include <math.h>
#include <stdio.h>
#include <string>
#include <thread>

double doCalc(double x) { return x * x; }

void calculPortion(const double min, const double max, const unsigned long segments)
{
	double resultat, tmp;
	double x = min;

	double pas = (max - min) / (double) segments;

	for (unsigned long i = 0; i < segments; i++)
	{
		resultat += doCalc(x) * pas;
		x += pas;
	}

	printf("De %e à %e : %f\n", min, max, resultat);
}

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

	// read the number of cores of the machine
	unsigned int nbCores = std::thread::hardware_concurrency();

	// verify command line arguments
	unsigned long nbSegments;
	double        min, max;
	if(argc == 4)
	{
		min        = std::stod(argv[1]);
		max        = std::stod(argv[2]);
		nbSegments = std::stol(argv[3]);
	}
	else
	{
		printf("Usage : %s <min> <max> <nbSegments>\n", argv[0]);
		exit(1);
	}

	if(min > max)
	{
		printf("Wrong input, maximum is inferior to minimum...");
		exit(2);
	}

	double increment = (max - min) / (double) nbCores;
	max = min + increment;

	// on crée autant de thread fils que de cœurs sur la machine
	std::thread tabThreads[nbCores];

	for(unsigned int i = 0; i < nbCores; i++)
	{
		// creation of child threads for computing
		// store it in an array for easier access
		tabThreads[i] = std::thread(calculPortion, min, max, nbSegments);

		min += increment;
		max += increment;
	}

	for(unsigned int i = 0 ; i < nbCores; i++)
	{
		tabThreads[i].join();
	}
}<commit_msg>Bugfix dans Calcul.cpp<commit_after>#include <iostream>
#include <math.h>
#include <stdio.h>
#include <string>
#include <thread>

double doCalc(double x) { return x * x; }

void calculPortion(const double min, const double max, const unsigned long segments)
{
	double resultat, tmp;
	double x = min;

	double pas = (max - min) / (double) segments;

	for (unsigned long i = 0; i < segments; i++)
	{
		resultat += doCalc(x) * pas;
		x += pas;
	}

	//printf("De %e à %e : %f\n", min, max, resultat);
}

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

	// verify command line arguments
	unsigned long nbSegments, nbCores;
	double        min, max;

	for (int i = 0 ; i < argc ; i++)
	{
		printf("%s\n", argv[i]);
	}

	if(argc == 5)
	{
		nbCores    = std::stol(argv[1]);
		min        = std::stod(argv[2]);
		max        = std::stod(argv[3]);
		nbSegments = std::stol(argv[4]);
	}
	else
	{
		printf("Usage : %s <nbCores> <min> <max> <nbSegments>\n", argv[0]);
		exit(1);
	}

	if(min > max)
	{
		printf("Wrong input, maximum is inferior to minimum...");
		exit(2);
	}

	if (nbCores < 0) {
		printf("Impossible to use less than 1 core...");
		exit(3);
	}

	double increment = (max - min) / (double) nbCores;
	max = min + increment;

	// on crée autant de thread fils que de cœurs sur la machine
	std::thread tabThreads[nbCores];

	for(unsigned int i = 0; i < nbCores; i++)
	{
		// creation of child threads for computing
		// store it in an array for easier access
		tabThreads[i] = std::thread(calculPortion, min, max, nbSegments);

		min += increment;
		max += increment;
	}

	for(unsigned int i = 0 ; i < nbCores; i++)
	{
		tabThreads[i].join();
	}
}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexLua.cxx
 ** Lexer for Lua language.
 **
 ** Written by Paul Winwood.
 ** Folder by Alexey Yutkin.
 ** Modified by Marcos E. Wurzius & Philippe Lhoste
 **/

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {
	return ch >= 0x80 ||
	       (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(int ch) {
	return ch >= 0x80 ||
	       (isalpha(ch) || ch == '_');
}

static inline bool IsANumberChar(int ch) {
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases.
	return (ch < 0x80) &&
	        (isdigit(ch) || toupper(ch) == 'E' ||
             ch == '.' || ch == '-' || ch == '+');
}

static inline bool IsLuaOperator(int ch) {
	if (ch >= 0x80 || isalnum(ch)) {
		return false;
	}
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' ||
		ch == '{' || ch == '}' || ch == '~' ||
		ch == '[' || ch == ']' || ch == ';' ||
		ch == '<' || ch == '>' || ch == ',' ||
		ch == '.' || ch == '^' || ch == '%' || ch == ':' ||
		ch == '#') {
		return true;
	}
	return false;
}

// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ],
// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on.
// The maximum number of '=' characters allowed is 254.
static int LongDelimCheck(StyleContext &sc) {
	int sep = 1;
	while (sc.GetRelative(sep) == '=' && sep < 0xFF)
		sep++;
	if (sc.GetRelative(sep) == sc.ch)
		return sep;
	return 0;
}

static void ColouriseLuaDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];
	WordList &keywords7 = *keywordlists[6];
	WordList &keywords8 = *keywordlists[7];

	int currentLine = styler.GetLine(startPos);
	// Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level,
	// if we are inside such a string. Block comment was introduced in Lua 5.0,
	// blocks with separators [=[ ... ]=] in Lua 5.1.
	int nestLevel = 0;
	int sepCount = 0;
	if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT) {
		int lineState = styler.GetLineState(currentLine - 1);
		nestLevel = lineState >> 8;
		sepCount = lineState & 0xFF;
	}

	// Do not leak onto next line
	if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) {
		initStyle = SCE_LUA_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);
	if (startPos == 0 && sc.ch == '#') {
		// shbang line: # is a comment only if first char of the script
		sc.SetState(SCE_LUA_COMMENTLINE);
	}
	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			currentLine = styler.GetLine(sc.currentPos);
			switch (sc.state) {
			case SCE_LUA_LITERALSTRING:
			case SCE_LUA_COMMENT:
				// Inside a literal string or block comment, we set the line state
				styler.SetLineState(currentLine, (nestLevel << 8) | sepCount);
				break;
			default:
				// Reset the line state
				styler.SetLineState(currentLine, 0);
				break;
			}
		}
		if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) {
			// Prevent SCE_LUA_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_LUA_STRING);
		}

		// Handle string line continuation
		if ((sc.state == SCE_LUA_STRING || sc.state == SCE_LUA_CHARACTER) &&
		        sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_LUA_OPERATOR) {
			sc.SetState(SCE_LUA_DEFAULT);
		} else if (sc.state == SCE_LUA_NUMBER) {
			// We stop the number definition on non-numerical non-dot non-eE non-sign char
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || sc.Match('.', '.')) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD3);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD4);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD5);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords7.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD7);
				} else if (keywords8.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD8);
				}
				sc.SetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) {
			if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_CHARACTER) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) {
			if (sc.ch == '[') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // [[-only allowed to nest
					nestLevel++;
					sc.Forward();
				}
			} else if (sc.ch == ']') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // un-nest with ]]-only
					nestLevel--;
					sc.Forward();
					if (nestLevel == 0) {
						sc.ForwardSetState(SCE_LUA_DEFAULT);
					}
				} else if (sep > 1 && sep == sepCount) {   // ]=]-style delim
					sc.Forward(sep);
					sc.ForwardSetState(SCE_LUA_DEFAULT);
				}
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_LUA_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_LUA_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_LUA_IDENTIFIER);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_LUA_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_LUA_CHARACTER);
			} else if (sc.ch == '[') {
				sepCount = LongDelimCheck(sc);
				if (sepCount == 0) {
					sc.SetState(SCE_LUA_OPERATOR);
				} else {
					nestLevel = 1;
					sc.SetState(SCE_LUA_LITERALSTRING);
					sc.Forward(sepCount);
				}
			} else if (sc.Match('-', '-')) {
				sc.SetState(SCE_LUA_COMMENTLINE);
				if (sc.Match("--[")) {
					sc.Forward(2);
					sepCount = LongDelimCheck(sc);
					if (sepCount > 0) {
						nestLevel = 1;
						sc.ChangeState(SCE_LUA_COMMENT);
						sc.Forward(sepCount);
					}
				} else {
					sc.Forward();
				}
			} else if (sc.atLineStart && sc.Match('$')) {
				sc.SetState(SCE_LUA_PREPROCESSOR);	// Obsolete since Lua 4.0, but still in old code
			} else if (IsLuaOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_LUA_OPERATOR);
			}
		}
	}
	sc.Complete();
}

static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	int styleNext = styler.StyleAt(startPos);
	char s[10];

	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LUA_WORD) {
			if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') {
				for (unsigned int j = 0; j < 8; j++) {
					if (!iswordchar(styler[i + j])) {
						break;
					}
					s[j] = styler[i + j];
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) {
					levelCurrent++;
				}
				if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0) || (strcmp(s, "until") == 0)) {
					levelCurrent--;
				}
			}
		} else if (style == SCE_LUA_OPERATOR) {
			if (ch == '{' || ch == '(') {
				levelCurrent++;
			} else if (ch == '}' || ch == ')') {
				levelCurrent--;
			}
		} else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) {
			if (ch == '[') {
				levelCurrent++;
			} else if (ch == ']') {
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact) {
				lev |= SC_FOLDLEVELWHITEFLAG;
			}
			if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch)) {
			visibleChars++;
		}
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const luaWordListDesc[] = {
	"Keywords",
	"Basic functions",
	"String, (table) & math functions",
	"(coroutines), I/O & system facilities",
	"user1",
	"user2",
	"user3",
	"user4",
	0
};

LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc);
<commit_msg>Patch from Kein-Hong Man to allow more forms of numeric literal.<commit_after>// Scintilla source code edit control
/** @file LexLua.cxx
 ** Lexer for Lua language.
 **
 ** Written by Paul Winwood.
 ** Folder by Alexey Yutkin.
 ** Modified by Marcos E. Wurzius & Philippe Lhoste
 **/

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {
	return ch >= 0x80 ||
	       (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(int ch) {
	return ch >= 0x80 ||
	       (isalpha(ch) || ch == '_');
}

static inline bool IsANumberChar(int ch) {
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases.
	return (ch < 0x80) &&
	        (isdigit(ch) || toupper(ch) == 'E' ||
	        ch == '.' || ch == '-' || ch == '+' ||
	        (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'));
}

static inline bool IsLuaOperator(int ch) {
	if (ch >= 0x80 || isalnum(ch)) {
		return false;
	}
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' ||
		ch == '{' || ch == '}' || ch == '~' ||
		ch == '[' || ch == ']' || ch == ';' ||
		ch == '<' || ch == '>' || ch == ',' ||
		ch == '.' || ch == '^' || ch == '%' || ch == ':' ||
		ch == '#') {
		return true;
	}
	return false;
}

// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ],
// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on.
// The maximum number of '=' characters allowed is 254.
static int LongDelimCheck(StyleContext &sc) {
	int sep = 1;
	while (sc.GetRelative(sep) == '=' && sep < 0xFF)
		sep++;
	if (sc.GetRelative(sep) == sc.ch)
		return sep;
	return 0;
}

static void ColouriseLuaDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];
	WordList &keywords7 = *keywordlists[6];
	WordList &keywords8 = *keywordlists[7];

	int currentLine = styler.GetLine(startPos);
	// Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level,
	// if we are inside such a string. Block comment was introduced in Lua 5.0,
	// blocks with separators [=[ ... ]=] in Lua 5.1.
	int nestLevel = 0;
	int sepCount = 0;
	if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT) {
		int lineState = styler.GetLineState(currentLine - 1);
		nestLevel = lineState >> 8;
		sepCount = lineState & 0xFF;
	}

	// Do not leak onto next line
	if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) {
		initStyle = SCE_LUA_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);
	if (startPos == 0 && sc.ch == '#') {
		// shbang line: # is a comment only if first char of the script
		sc.SetState(SCE_LUA_COMMENTLINE);
	}
	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			currentLine = styler.GetLine(sc.currentPos);
			switch (sc.state) {
			case SCE_LUA_LITERALSTRING:
			case SCE_LUA_COMMENT:
				// Inside a literal string or block comment, we set the line state
				styler.SetLineState(currentLine, (nestLevel << 8) | sepCount);
				break;
			default:
				// Reset the line state
				styler.SetLineState(currentLine, 0);
				break;
			}
		}
		if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) {
			// Prevent SCE_LUA_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_LUA_STRING);
		}

		// Handle string line continuation
		if ((sc.state == SCE_LUA_STRING || sc.state == SCE_LUA_CHARACTER) &&
		        sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_LUA_OPERATOR) {
			sc.SetState(SCE_LUA_DEFAULT);
		} else if (sc.state == SCE_LUA_NUMBER) {
			// We stop the number definition on non-numerical non-dot non-eE non-sign non-hexdigit char
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || sc.Match('.', '.')) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD3);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD4);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD5);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords7.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD7);
				} else if (keywords8.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD8);
				}
				sc.SetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) {
			if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_CHARACTER) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) {
			if (sc.ch == '[') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // [[-only allowed to nest
					nestLevel++;
					sc.Forward();
				}
			} else if (sc.ch == ']') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // un-nest with ]]-only
					nestLevel--;
					sc.Forward();
					if (nestLevel == 0) {
						sc.ForwardSetState(SCE_LUA_DEFAULT);
					}
				} else if (sep > 1 && sep == sepCount) {   // ]=]-style delim
					sc.Forward(sep);
					sc.ForwardSetState(SCE_LUA_DEFAULT);
				}
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_LUA_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_LUA_NUMBER);
				if (sc.ch == '0' && toupper(sc.chNext) == 'X') {
					sc.Forward(1);
				}
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_LUA_IDENTIFIER);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_LUA_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_LUA_CHARACTER);
			} else if (sc.ch == '[') {
				sepCount = LongDelimCheck(sc);
				if (sepCount == 0) {
					sc.SetState(SCE_LUA_OPERATOR);
				} else {
					nestLevel = 1;
					sc.SetState(SCE_LUA_LITERALSTRING);
					sc.Forward(sepCount);
				}
			} else if (sc.Match('-', '-')) {
				sc.SetState(SCE_LUA_COMMENTLINE);
				if (sc.Match("--[")) {
					sc.Forward(2);
					sepCount = LongDelimCheck(sc);
					if (sepCount > 0) {
						nestLevel = 1;
						sc.ChangeState(SCE_LUA_COMMENT);
						sc.Forward(sepCount);
					}
				} else {
					sc.Forward();
				}
			} else if (sc.atLineStart && sc.Match('$')) {
				sc.SetState(SCE_LUA_PREPROCESSOR);	// Obsolete since Lua 4.0, but still in old code
			} else if (IsLuaOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_LUA_OPERATOR);
			}
		}
	}
	sc.Complete();
}

static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	int styleNext = styler.StyleAt(startPos);
	char s[10];

	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LUA_WORD) {
			if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') {
				for (unsigned int j = 0; j < 8; j++) {
					if (!iswordchar(styler[i + j])) {
						break;
					}
					s[j] = styler[i + j];
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) {
					levelCurrent++;
				}
				if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0) || (strcmp(s, "until") == 0)) {
					levelCurrent--;
				}
			}
		} else if (style == SCE_LUA_OPERATOR) {
			if (ch == '{' || ch == '(') {
				levelCurrent++;
			} else if (ch == '}' || ch == ')') {
				levelCurrent--;
			}
		} else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) {
			if (ch == '[') {
				levelCurrent++;
			} else if (ch == ']') {
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact) {
				lev |= SC_FOLDLEVELWHITEFLAG;
			}
			if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch)) {
			visibleChars++;
		}
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const luaWordListDesc[] = {
	"Keywords",
	"Basic functions",
	"String, (table) & math functions",
	"(coroutines), I/O & system facilities",
	"user1",
	"user2",
	"user3",
	"user4",
	0
};

LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc);
<|endoftext|>


<commit_before>#include <assert.h>

#include "messageStream.h"
#include "libwatcher/startWatcherMessage.h"
#include "libwatcher/stopWatcherMessage.h"

using namespace watcher;
using namespace watcher::event;
using namespace std;
using namespace boost;

INIT_LOGGER(MessageStream, "MessageStream");

MessageStream::MessageStream(
        const string &serverName_,
        const string &serviceName_,
        const Timestamp &startTime_,
        const float streamRate_) :
    messagesSent(0),
    messagesArrived(0),
    messageStreamFilters(),
    streamRate(streamRate_),
    streamStartTime(startTime_),
    serverName(serverName_),
    serviceName(serviceName_),
    connection(),
    messageCache(),
    messageCacheMutex(),
    readReady(false)
{
    TRACE_ENTER();
    TRACE_EXIT();
}

// static
MessageStreamPtr MessageStream::createNewMessageStream(const string &serverName_, const Timestamp &startTime_, const float streamRate_)
{
    TRACE_ENTER();
    MessageStreamPtr retVal(new MessageStream(serverName_,"watcherd",startTime_,streamRate_));
    retVal->initConnection();
    TRACE_EXIT();
    return retVal;
}

// static
MessageStreamPtr MessageStream::createNewMessageStream(
                    const std::string &serverName,
                    const std::string &portNum,  // Connect on a non-standard port (different port than watcherd service)
                    const Timestamp &startTime,
                    const float streamRate)
{
    TRACE_ENTER();
    MessageStreamPtr retVal(new MessageStream(serverName, portNum, startTime, streamRate));
    retVal->initConnection();
    TRACE_EXIT();
    return retVal;
}

void MessageStream::initConnection()
{
    TRACE_ENTER();
    connection=ClientPtr(new Client(serverName, serviceName));
    connection->addMessageHandler(shared_from_this());
    TRACE_EXIT();
}

// virtual
MessageStream::~MessageStream()
{
    TRACE_ENTER();
    TRACE_EXIT();
}

bool MessageStream::setStreamTimeStart(const Timestamp &startTime)
{
    TRACE_ENTER()
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::setStreamRate(const float &messageStreamRate)
{
    TRACE_ENTER();
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::getNextMessage(MessagePtr newMessage)
{
    TRACE_ENTER();
    if(!connection)
    {
        TRACE_EXIT_RET(false);
        return false;
    }

    unique_lock<mutex> lock(messageCacheMutex);
    while(false==readReady)
    {
        messageCacheCond.wait(lock);
    }

    assert(messageCache.size() > 0);
    newMessage=messageCache.front();
    messageCache.erase(messageCache.begin());
    readReady=messageCache.size()>0;
    LOG_DEBUG("Setting readReady to " << (readReady?"true":"false"));

    TRACE_EXIT_RET(true);
    return true;
}
bool MessageStream::isStreamReadable() const
{
    TRACE_ENTER();
    bool retVal=messageCache.size() > 1;
    TRACE_EXIT_RET(retVal);
    return retVal;
}
bool MessageStream::addMessageFilter(const MessageStreamFilter &filter)
{
    TRACE_ENTER();

    assert(0);  // filters are not supported yet.

    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::getMessageTimeRange(Timestamp &startTime, Timestamp endTime)
{
    TRACE_ENTER();
    TRACE_EXIT_RET("true");
    return true;
}

//virtual
std::ostream &MessageStream::toStream(std::ostream &out) const
{
    TRACE_ENTER();
    out << "MessageStream output operator not yet implemented - this space intensionally left blank";
    TRACE_EXIT();
    return out;
}
bool MessageStream::startStream()
{
    TRACE_ENTER();
    StartMessagePtr mess(new StartMessage);
    bool retVal=connection->sendMessage(mess);
    TRACE_EXIT_RET((retVal==true?"true":"false"));
    return retVal;
}
bool MessageStream::stopStream()
{
    TRACE_ENTER();
    StopMessagePtr mess(new StopMessage);
    bool retVal=connection->sendMessage(mess);
    TRACE_EXIT_RET((retVal==true?"true":"false"));
    return retVal;
}

//virtual
bool MessageStream::handleMessageArrive(ConnectionPtr conn, const MessagePtr &message)
{
    TRACE_ENTER();

    messagesArrived++;

    // We don't really add anything yet to a generic watcherdAPI client.
    bool retVal=WatcherdAPIMessageHandler::handleMessageArrive(conn, message);

    TRACE_EXIT_RET((retVal==true?"true":"false"));
    return retVal;
}

//virtual
bool MessageStream::handleMessagesArrive(ConnectionPtr conn, const vector<MessagePtr> &messages)
{
    TRACE_ENTER();

    bool retVal=true;
    for(vector<MessagePtr>::const_iterator m=messages.begin(); m!=messages.end(); ++m)
        if(!handleMessageArrive(conn, *m))
            retVal=false;

    TRACE_EXIT_RET(retVal);
    return retVal;
}

//virtual
bool MessageStream::handleMessageSent(const MessagePtr &message)
{
    TRACE_ENTER();

    messagesSent++;

    // We don't really add anything yet to a generic watcherdAPI client.
    bool retVal=WatcherdAPIMessageHandler::handleMessageSent(message);

    TRACE_EXIT_RET((retVal==true?"true":"false"));
    return retVal;
}

//virtual
bool MessageStream::handleMessagesSent(const vector<MessagePtr> &messages)
{
    TRACE_ENTER();

    bool retVal=true;
    for(vector<MessagePtr>::const_iterator m=messages.begin(); m!=messages.end(); ++m)
        if(!handleMessageSent(*m))
            retVal=false;

    TRACE_EXIT_RET(retVal);
    return retVal;
}

std::ostream &operator<<(std::ostream &out, const MessageStream &messStream)
{
    TRACE_ENTER();
    TRACE_EXIT();
    return out;
}
<commit_msg>Add incoming message to message cache and signal to waiting threads (probably waiting in getNextMessage()) that there is at least one message in the cache. Also - fix warnings about unused arguments.<commit_after>#include <assert.h>

#include "messageStream.h"
#include "libwatcher/startWatcherMessage.h"
#include "libwatcher/stopWatcherMessage.h"

using namespace watcher;
using namespace watcher::event;
using namespace std;
using namespace boost;

INIT_LOGGER(MessageStream, "MessageStream");

MessageStream::MessageStream(
        const string &serverName_,
        const string &serviceName_,
        const Timestamp &startTime_,
        const float streamRate_) :
    messagesSent(0),
    messagesArrived(0),
    messageStreamFilters(),
    streamRate(streamRate_),
    streamStartTime(startTime_),
    serverName(serverName_),
    serviceName(serviceName_),
    connection(),
    messageCache(),
    messageCacheMutex(),
    readReady(false)
{
    TRACE_ENTER();
    TRACE_EXIT();
}

// static
MessageStreamPtr MessageStream::createNewMessageStream(const string &serverName_, const Timestamp &startTime_, const float streamRate_)
{
    TRACE_ENTER();
    MessageStreamPtr retVal(new MessageStream(serverName_,"watcherd",startTime_,streamRate_));
    retVal->initConnection();
    TRACE_EXIT();
    return retVal;
}

// static
MessageStreamPtr MessageStream::createNewMessageStream(
                    const std::string &serverName,
                    const std::string &portNum,  // Connect on a non-standard port (different port than watcherd service)
                    const Timestamp &startTime,
                    const float streamRate)
{
    TRACE_ENTER();
    MessageStreamPtr retVal(new MessageStream(serverName, portNum, startTime, streamRate));
    retVal->initConnection();
    TRACE_EXIT();
    return retVal;
}

void MessageStream::initConnection()
{
    TRACE_ENTER();
    connection=ClientPtr(new Client(serverName, serviceName));
    connection->addMessageHandler(shared_from_this());
    TRACE_EXIT();
}

// virtual
MessageStream::~MessageStream()
{
    TRACE_ENTER();
    TRACE_EXIT();
}

bool MessageStream::setStreamTimeStart(const Timestamp &startTime)
{
    TRACE_ENTER();
    LOG_DEBUG("Setting stream start time to " << startTime);
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::setStreamRate(const float &messageStreamRate)
{
    TRACE_ENTER();
    LOG_DEBUG("Setting message stream rate to " << messageStreamRate);
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::getNextMessage(MessagePtr newMessage)
{
    TRACE_ENTER();
    if(!connection)
    {
        TRACE_EXIT_RET(false);
        return false;
    }

    unique_lock<mutex> lock(messageCacheMutex);
    while(false==readReady)
    {
        messageCacheCond.wait(lock);
    }

    assert(messageCache.size() > 0);
    newMessage=messageCache.front();
    messageCache.erase(messageCache.begin());
    readReady=messageCache.size()>0;
    LOG_DEBUG("Setting readReady to " << (readReady?"true":"false"));

    TRACE_EXIT_RET(true);
    return true;
}
bool MessageStream::isStreamReadable() const
{
    TRACE_ENTER();
    bool retVal=messageCache.size() > 1;
    TRACE_EXIT_RET(retVal);
    return retVal;
}
bool MessageStream::addMessageFilter(const MessageStreamFilter & /*filter*/)
{
    TRACE_ENTER();

    assert(0);  // filters are not supported yet.

    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::getMessageTimeRange(Timestamp &startTime, Timestamp endTime)
{
    TRACE_ENTER();

    startTime=0;
    endTime=0;

    // query watcherd for the least and greatest time here.
    assert(0); // not yet supported - goodbye.

    LOG_DEBUG("Got message time range from server. Start:" << startTime << " End:" << endTime);

    TRACE_EXIT_RET("true");
    return true;
}

//virtual
std::ostream &MessageStream::toStream(std::ostream &out) const
{
    TRACE_ENTER();
    out << "MessageStream output operator not yet implemented - this space intensionally left blank";
    TRACE_EXIT();
    return out;
}
bool MessageStream::startStream()
{
    TRACE_ENTER();
    StartMessagePtr mess(new StartMessage);
    bool retVal=connection->sendMessage(mess);
    TRACE_EXIT_RET((retVal==true?"true":"false"));
    return retVal;
}
bool MessageStream::stopStream()
{
    TRACE_ENTER();
    StopMessagePtr mess(new StopMessage);
    bool retVal=connection->sendMessage(mess);
    TRACE_EXIT_RET((retVal==true?"true":"false"));
    return retVal;
}

//virtual
bool MessageStream::handleMessageArrive(ConnectionPtr conn, const MessagePtr &message)
{
    TRACE_ENTER();

    messagesArrived++;

    // We don't really add anything yet to a generic watcherdAPI client.
    bool retVal=WatcherdAPIMessageHandler::handleMessageArrive(conn, message);

    {
        lock_guard<mutex> lock(messageCacheMutex);
        messageCache.push_back(message);
        readReady=true;
        // let lock go out of scope
    }
    messageCacheCond.notify_all();

    TRACE_EXIT_RET((retVal==true?"true":"false"));
    return retVal;
}

//virtual
bool MessageStream::handleMessagesArrive(ConnectionPtr conn, const vector<MessagePtr> &messages)
{
    TRACE_ENTER();

    bool retVal=true;
    for(vector<MessagePtr>::const_iterator m=messages.begin(); m!=messages.end(); ++m)
        if(!handleMessageArrive(conn, *m))
            retVal=false;

    TRACE_EXIT_RET(retVal);
    return retVal;
}

//virtual
bool MessageStream::handleMessageSent(const MessagePtr &message)
{
    TRACE_ENTER();

    messagesSent++;

    // We don't really add anything yet to a generic watcherdAPI client.
    bool retVal=WatcherdAPIMessageHandler::handleMessageSent(message);

    TRACE_EXIT_RET((retVal==true?"true":"false"));
    return retVal;
}

//virtual
bool MessageStream::handleMessagesSent(const vector<MessagePtr> &messages)
{
    TRACE_ENTER();

    bool retVal=true;
    for(vector<MessagePtr>::const_iterator m=messages.begin(); m!=messages.end(); ++m)
        if(!handleMessageSent(*m))
            retVal=false;

    TRACE_EXIT_RET(retVal);
    return retVal;
}

std::ostream &operator<<(std::ostream &out, const MessageStream & /*messStream*/)
{
    TRACE_ENTER();
    TRACE_EXIT();
    return out;
}
<|endoftext|>


<commit_before>// This file is part of the "x0" project
//   (c) 2009-2015 Christian Parpart <https://github.com/christianparpart>
//
// x0 is free software: you can redistribute it and/or modify it under
// the terms of the GNU Affero General Public License v3.0.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#include <xzero/http/hpack/Parser.h>
#include <xzero/http/hpack/StaticTable.h>
#include <xzero/http/hpack/DynamicTable.h>
#include <xzero/http/hpack/Huffman.h>
#include <xzero/http/HeaderField.h>
#include <xzero/RuntimeError.h>
#include <xzero/logging.h>

namespace xzero {
namespace http {
namespace hpack {

#if !defined(NDEBUG)
#define TRACE(msg...) logTrace("http.hpack.Parser", msg)
#else
#define TRACE(msg...) do {} while (0)
#endif

// 2^n
#define BIT(n) (1 << (n))

// LSB from 0 to n set, rest cleared
#define BITMASK(n) (BIT(n) - 1)

Parser::Parser(size_t maxSize, Emitter emitter)
    : maxSize_(maxSize),
      dynamicTable_(maxSize),
      emitter_(emitter) {
}

void Parser::setMaxSize(size_t newMaxSize) {
  maxSize_ = newMaxSize;
  dynamicTable_.setMaxSize(newMaxSize);
}

size_t Parser::parse(const_iterator beg, const_iterator end) {
  const_iterator pos = beg;

  while (pos != end) {
    value_type octet = *pos;

    if (octet & (1 << 7)) {
      // indexed header field
      pos = indexedHeaderField(pos, end);
    }
    else if (octet & (1 << 6)) {
      // literal header field with incremental indexing
      pos = incrementalIndexedField(pos, end);
    }
    else if (octet & (1 << 5)) {
      // dynamic table size update
      pos = updateTableSize(pos, end);
    }
    else if (octet & (1 << 4)) {
      // literal header field (never indexed)
      pos = literalHeaderNeverIndex(pos, end);
    }
    else {
      pos = literalHeaderNoIndex(pos, end);
      RAISE(RuntimeError, "Oh what instraction are you?");
    }
  }

  return pos - beg;
}

Parser::const_iterator Parser::indexedHeaderField(const_iterator pos,
                                                  const_iterator end) {
  // (6.1) Indexed Header Field Representation
  uint64_t index;
  size_t n = decodeInt(7, &index, pos, end);
  pos += n;

  const HeaderField& field = at(index);
  emit(field.name(), field.value());

  return pos;
}

Parser::const_iterator Parser::incrementalIndexedField(const_iterator pos,
                                                       const_iterator end) {
  // (6.2.1) Literal Header Field with Incremental Indexing

  size_t index;
  size_t n = decodeInt(6, &index, pos, end);
  pos += n;

  if (index != 0) {
    // (index, literal)
    const std::string& name = at(index).name();

    std::string value;
    n = decodeString(&value, pos, end);
    pos += n;

    dynamicTable_.add(name, value);
    emit(name, value);
  } else {
    // (literal, literal)
    std::string name;
    n = decodeString(&name, pos, end);
    pos += n;

    std::string value;
    n = decodeString(&value, pos, end);
    pos += n;

    dynamicTable_.add(name, value);
    emit(name, value);
  }

  return pos;
}

Parser::const_iterator Parser::updateTableSize(const_iterator pos,
                                               const_iterator end) {
  // (6.3) Dynamic Table Size Update

  uint64_t newMaxSize;
  size_t n = decodeInt(5, &newMaxSize, pos, end);
  pos += n;

  if (newMaxSize > maxSize_)
    RAISE(CompressionError, "Received a MAX_SIZE value larger than allowed.");

  setMaxSize(newMaxSize);

  return pos;
}

Parser::const_iterator Parser::literalHeaderNoIndex(const_iterator pos,
                                                    const_iterator end) {
  // (6.2.2) Literal Header Field without Indexing

  uint64_t index;
  size_t n = decodeInt(4, &index, pos, end);
  pos += n;

  if (index != 0) {
    // (index, literal)
    const std::string& name = at(index).name();

    std::string value;
    n = decodeString(&value, pos, end);
    pos += n;

    emitSenstive(name, value, false);
  } else {
    // literal, literal)
    std::string name;
    size_t n = decodeString(&name, pos, end);
    pos += n;

    std::string value;
    n = decodeString(&value, pos, end);
    pos += n;

    emitSenstive(name, value, false);
  }

  return pos;
}

Parser::const_iterator Parser::literalHeaderNeverIndex(
    const_iterator pos,
    const_iterator end) {
  // (6.2.3) Literal Header Field Never Indexed

  uint64_t index;
  size_t n = decodeInt(4, &index, pos, end);
  pos += n;

  if (index != 0) {
    // (index, literal)
    const std::string& name = at(index).name();

    std::string value;
    n = decodeString(&value, pos, end);
    pos += n;

    emitSenstive(name, value, true);
  } else {
    // (literal, literal)
    std::string name;
    size_t n = decodeString(&name, pos, end);
    pos += n;

    std::string value;
    n = decodeString(&value, pos, end);
    pos += n;

    emitSenstive(name, value, true);
  }

  return pos;
}

const HeaderField& Parser::at(size_t index) {
  if (index == 0)
    RAISE(CompressionError, "Invalid index (must not be 0)");

  index--;

  if (index < StaticTable::length())
    return StaticTable::at(index);

  index -= StaticTable::length();

  if (index < dynamicTable_.length())
    return dynamicTable_.at(index);

  RAISE(CompressionError, "Index out of bounds");
}

size_t Parser::decodeInt(uint8_t prefixBits, uint64_t* output,
                         const_iterator pos, const_iterator end) {
  if (!(prefixBits >= 1 && prefixBits <= 8))
    RAISE(InternalError, "prefixBits must be between 0 and 8 (not %u)", prefixBits);

  if (pos == end)
    RAISE(CompressionError, "Need more data");

  *output = *pos & BITMASK(prefixBits);

  if (*output < BITMASK(prefixBits))
    return 1;

  pos++;

  size_t nbytes = 1;
  unsigned shift = 0;

  while (pos != end) {
    uint8_t octet = *pos;
    pos++;
    nbytes++;

    *output += (octet & 0b01111111) << shift;

    if ((octet & BIT(7)) == 0)
      return nbytes;

    shift += 7;
  }

  RAISE(CompressionError, "Need more data");
}

size_t Parser::decodeString(std::string* output,
                            const_iterator pos,
                            const_iterator end) {
  assert(output != nullptr);

  uint64_t slen;
  size_t n = decodeInt(7, &slen, pos, end);
  bool compressed = *pos & (1 << 7);
  pos += n;

  if (slen > end - pos)
    RAISE(CompressionError, "Need more data");

  if (compressed)
    *output = Huffman::decode(pos, pos + slen);
  else
    output->assign((char*) pos, slen);

  n += slen;

  return n;
}

void Parser::emit(const std::string& name, const std::string& value) {
  emitSenstive(name, value, false);
}

void Parser::emitSenstive(const std::string& name, const std::string& value, bool sensitive) {
  if (emitter_) {
    emitter_(name, value, sensitive);
  }
}

} // namespace hpack
} // namespace http
} // namespace xzero
<commit_msg>exchange me<commit_after>// This file is part of the "x0" project
//   (c) 2009-2015 Christian Parpart <https://github.com/christianparpart>
//
// x0 is free software: you can redistribute it and/or modify it under
// the terms of the GNU Affero General Public License v3.0.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#include <xzero/http/hpack/Parser.h>
#include <xzero/http/hpack/StaticTable.h>
#include <xzero/http/hpack/DynamicTable.h>
#include <xzero/http/hpack/Huffman.h>
#include <xzero/http/HeaderField.h>
#include <xzero/RuntimeError.h>
#include <xzero/logging.h>

namespace xzero {
namespace http {
namespace hpack {

#if !defined(NDEBUG)
#define TRACE(msg...) logTrace("http.hpack.Parser", msg)
#else
#define TRACE(msg...) do {} while (0)
#endif

// 2^n
#define BIT(n) (1 << (n))

// LSB from 0 to n set, rest cleared
#define BITMASK(n) (BIT(n) - 1)

Parser::Parser(size_t maxSize, Emitter emitter)
    : maxSize_(maxSize),
      dynamicTable_(maxSize),
      emitter_(emitter) {
}

void Parser::setMaxSize(size_t newMaxSize) {
  maxSize_ = newMaxSize;
  dynamicTable_.setMaxSize(newMaxSize);
}

size_t Parser::parse(const_iterator beg, const_iterator end) {
  const_iterator pos = beg;

  while (pos != end) {
    value_type octet = *pos;

    if (octet & (1 << 7)) {
      // indexed header field
      pos = indexedHeaderField(pos, end);
    }
    else if (octet & (1 << 6)) {
      // literal header field with incremental indexing
      pos = incrementalIndexedField(pos, end);
    }
    else if (octet & (1 << 5)) {
      // dynamic table size update
      pos = updateTableSize(pos, end);
    }
    else if (octet & (1 << 4)) {
      // literal header field (never indexed)
      pos = literalHeaderNeverIndex(pos, end);
    }
    else {
      pos = literalHeaderNoIndex(pos, end);
      RAISE(RuntimeError, "Oh what instraction are you?");
    }
  }

  return pos - beg;
}

Parser::const_iterator Parser::indexedHeaderField(const_iterator pos,
                                                  const_iterator end) {
  // (6.1) Indexed Header Field Representation
  uint64_t index;
  size_t n = decodeInt(7, &index, pos, end);
  pos += n;

  const HeaderField& field = at(index);
  emit(field.name(), field.value());

  return pos;
}

Parser::const_iterator Parser::incrementalIndexedField(const_iterator pos,
                                                       const_iterator end) {
  // (6.2.1) Literal Header Field with Incremental Indexing

  size_t index;
  size_t n = decodeInt(6, &index, pos, end);
  pos += n;

  if (index != 0) {
    // (index, literal)
    const std::string& name = at(index).name();

    std::string value;
    n = decodeString(&value, pos, end);
    pos += n;

    dynamicTable_.add(name, value);
    emit(name, value);
  } else {
    // (literal, literal)
    std::string name;
    n = decodeString(&name, pos, end);
    pos += n;

    std::string value;
    n = decodeString(&value, pos, end);
    pos += n;

    dynamicTable_.add(name, value);
    emit(name, value);
  }

  return pos;
}

Parser::const_iterator Parser::updateTableSize(const_iterator pos,
                                               const_iterator end) {
  // (6.3) Dynamic Table Size Update

  uint64_t newMaxSize;
  size_t n = decodeInt(5, &newMaxSize, pos, end);
  pos += n;

  if (newMaxSize > maxSize_)
    RAISE(CompressionError, "Received a MAX_SIZE value larger than allowed.");

  setMaxSize(newMaxSize);

  return pos;
}

Parser::const_iterator Parser::literalHeaderNoIndex(const_iterator pos,
                                                    const_iterator end) {
  // (6.2.2) Literal Header Field without Indexing

  uint64_t index;
  size_t n = decodeInt(4, &index, pos, end);
  pos += n;

  if (index != 0) {
    // (index, literal)
    const std::string& name = at(index).name();

    std::string value;
    n = decodeString(&value, pos, end);
    pos += n;

    emitSenstive(name, value, false);
  } else {
    // literal, literal)
    std::string name;
    size_t n = decodeString(&name, pos, end);
    pos += n;

    std::string value;
    n = decodeString(&value, pos, end);
    pos += n;

    emitSenstive(name, value, false);
  }

  return pos;
}

Parser::const_iterator Parser::literalHeaderNeverIndex(
    const_iterator pos,
    const_iterator end) {
  // (6.2.3) Literal Header Field Never Indexed

  uint64_t index;
  size_t n = decodeInt(4, &index, pos, end);
  pos += n;

  if (index != 0) {
    // (index, literal)
    const std::string& name = at(index).name();

    std::string value;
    n = decodeString(&value, pos, end);
    pos += n;

    emitSenstive(name, value, true);
  } else {
    // (literal, literal)
    std::string name;
    size_t n = decodeString(&name, pos, end);
    pos += n;

    std::string value;
    n = decodeString(&value, pos, end);
    pos += n;

    emitSenstive(name, value, true);
  }

  return pos;
}

const HeaderField& Parser::at(size_t index) {
  if (index == 0)
    RAISE(CompressionError, "Invalid index (must not be 0)");

  index--;

  if (index < StaticTable::length())
    return StaticTable::at(index);

  index -= StaticTable::length();

  if (index < dynamicTable_.length())
    return dynamicTable_.at(index);

  RAISE(CompressionError, "Index out of bounds");
}

size_t Parser::decodeInt(uint8_t prefixBits, uint64_t* output,
                         const_iterator pos, const_iterator end) {
  if (!(prefixBits >= 1 && prefixBits <= 8))
    RAISE(InternalError, "prefixBits must be between 0 and 8 (not %u)", prefixBits);

  if (pos == end)
    RAISE(CompressionError, "Need more data");

  *output = *pos & BITMASK(prefixBits);

  if (*output < BITMASK(prefixBits))
    return 1;

  pos++;

  size_t nbytes = 1;
  unsigned shift = 0;

  while (pos != end) {
    uint8_t octet = *pos;
    pos++;
    nbytes++;

    *output += (octet & 0b01111111) << shift;

    if ((octet & BIT(7)) == 0)
      return nbytes;

    shift += 7;
  }

  RAISE(CompressionError, "Need more data");
}

size_t Parser::decodeString(std::string* output,
                            const_iterator pos,
                            const_iterator end) {
  assert(output != nullptr);

  uint64_t slen;
  bool compressed = *pos & (1 << 7);
  size_t n = decodeInt(7, &slen, pos, end);
  pos += n;

  if (slen > end - pos)
    RAISE(CompressionError, "Need more data");

  if (compressed)
    *output = Huffman::decode(pos, pos + slen);
  else
    output->assign((char*) pos, slen);

  n += slen;

  return n;
}

void Parser::emit(const std::string& name, const std::string& value) {
  emitSenstive(name, value, false);
}

void Parser::emitSenstive(const std::string& name, const std::string& value, bool sensitive) {
  if (emitter_) {
    emitter_(name, value, sensitive);
  }
}

} // namespace hpack
} // namespace http
} // namespace xzero
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS hr50 (1.133.46); FILE MERGED 2008/04/09 11:05:53 hr 1.133.46.1: #i86574#: fix warning (gcc-4.2.3)<commit_after><|endoftext|>


<commit_before><commit_msg>editor: translator Z axis fix<commit_after><|endoftext|>