<commit_before>// This file is part of the HörTech Open Master Hearing Aid (openMHA)
// Copyright © 2018 2019 HörTech gGmbH
//
// openMHA is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// openMHA is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License, version 3 for more details.
//
// You should have received a copy of the GNU Affero General Public License,
// version 3 along with openMHA.  If not, see <http://www.gnu.org/licenses/>.

#include "fshift.hh"
#include <cmath>

int fshift::fft_find_bin(mha_real_t frequency, unsigned fftlen, mha_real_t srate){
  if(frequency<-srate/2 or frequency>srate/2){
    throw MHA_Error(__FILE__,__LINE__,"fft_find_bin: Frequency %.0f is out of range [0, %0.f].",frequency,srate/2);
  }
  return round(frequency*fftlen/srate);
}

fshift::fshift_config_t::fshift_config_t(fshift_t const * const plug)
  :  kmin(fft_find_bin(plug->fmin(),plug->input_cfg().fftlen,plug->input_cfg().srate)),
     kmax(fft_find_bin(plug->fmax(),plug->input_cfg().fftlen,plug->input_cfg().srate)),
     df(fft_find_bin(plug->df(),plug->input_cfg().fftlen,plug->input_cfg().srate)),
     delta_phi{std::cos(plug->input_cfg().fragsize*plug->df()*static_cast<mha_real_t>(M_PI)*2.0f/plug->input_cfg().srate),
               std::sin(plug->input_cfg().fragsize*plug->df()*static_cast<mha_real_t>(M_PI)*2.0f/plug->input_cfg().srate)},
     delta_phi_total{1.0f,0.0f}
{}

mha_spec_t *fshift::fshift_config_t::process(mha_spec_t *in)
{
  if(df==0){
    return in;
  }

  for(unsigned ch=0U; ch<in->num_channels; ++ch){
    if(df<0){
      for(unsigned fr=kmin; fr<kmax; ++fr){
        int idx=fr+df;
        if(idx<static_cast<int>(in->num_frames) and idx>=0){
          value(in,idx,ch)+=value(in,fr,ch)*delta_phi_total;
          value(in, fr, ch)={0,0};
        }
      }
    }
    else{
      for(unsigned fr=kmax; fr>=kmin; --fr){
        int idx=fr+df;
        if(idx<static_cast<int>(in->num_frames) and idx>=0){
          value(in,idx,ch)+=value(in,fr,ch)*delta_phi_total;
          value(in, fr, ch)={0,0};
        }
      }
    }
  }
  delta_phi_total*=delta_phi;
  delta_phi_total=delta_phi_total/abs(delta_phi_total);
  return in;
}

/** Constructs our plugin. */
fshift::fshift_t::fshift_t(algo_comm_t & ac,
                   const std::string & chain_name,
                   const std::string & algo_name)
       : MHAPlugin::plugin_t<fshift_config_t>("",ac),
  m_fmin("lower boundary for frequency shifter in Hz","4000","[0,]"),
  m_fmax("upper boundary for frequency shifter in Hz","16000","[0,]"),
  m_df("shift frequency in Hz","40","")
{
  insert_item("fmin",&m_fmin);
  patchbay.connect(&m_fmin.valuechanged, this, &fshift::fshift_t::update_cfg);
  insert_item("fmax",&m_fmax);
  patchbay.connect(&m_fmax.valuechanged, this, &fshift::fshift_t::update_cfg);
  insert_item("df",&m_df);
  patchbay.connect(&m_df.valuechanged, this, &fshift::fshift_t::update_cfg);
}

fshift::fshift_t::~fshift_t() {}

/** Plugin preparation.
 *  An opportunity to validate configuration parameters before instantiating a configuration.
 * @param signal_info
 *   Structure containing a description of the form of the signal (domain,
 *   number of channels, frames per block, sampling rate.
 */
void fshift::fshift_t::prepare(mhaconfig_t & signal_info)
{
  if (signal_info.domain != MHA_SPECTRUM)
    throw MHA_Error(__FILE__, __LINE__,
                    "This plugin can only process spectrum signals.");

  mha_real_t frate = 0.5*signal_info.srate;
  if( m_df.data > frate )
    m_df.data= frate;
  if( m_df.data < -frate )
    m_df.data = -frate;
  /* make sure that a valid runtime configuration exists: */
  update_cfg();
}

void fshift::fshift_t::update_cfg()
{
    if ( is_prepared() ) {

        //when necessary, make a new configuration instance
        //possibly based on changes in parser variables
        fshift_config_t *config;
        config = new fshift_config_t( this );
        push_config( config );
    }
}

/**
 * Checks for the most recent configuration and defers processing to it.
 */
mha_spec_t * fshift::fshift_t::process(mha_spec_t * signal)
{
    //this stub method defers processing to the configuration class
    return poll_config()->process( signal );
}

/*
 * This macro connects the plugin1_t class with the MHA plugin C interface
 * The first argument is the class name, the other arguments define the
 * input and output domain of the algorithm.
 */
MHAPLUGIN_CALLBACKS(fshift,fshift::fshift_t,
                    spec,spec)

/*
 * This macro creates code classification of the plugin and for
 * automatic documentation.
 *
 * The first argument to the macro is a space separated list of
 * categories, starting with the most relevant category. The second
 * argument is a LaTeX-compatible character array with some detailed
 * documentation of the plugin.
 */
MHAPLUGIN_DOCUMENTATION
(fshift::fshift_t,
 "feedback-suppression frequency-modification",
 " Performs a quantized frequency shift on the selected frequency"
 " interval. "
 " The frequency band between (originally)"
 " \\texttt{fmin} and \\texttt{fmax} (frequencies in Hz)"
 " is shifted by \\texttt{df} (desired frequency change"
 " in Hz). "
 " Positive \\texttt{df} shifts the selected band to"
 " higher frequencies, negative \\texttt{df} shifts to"
 " lower frequencies."
 " \n\n"
 " The shifted and the unshifted parts of the"
 " input signal are split at the STFT bin boundaries nearest to the."
 " The frequency shift \\texttt{df} is rounded to the nearest bin as well."
 " The parts of the spectrum that would be shifted below 0 Hz or above the Nyquist"
 " frequency are discarded. "
 )

// Local Variables:
// compile-command: "make"
// c-basic-offset: 2
// indent-tabs-mode: nil
// coding: utf-8-unix
// End:
<commit_msg>fshift: Clamp fmax to nyquist frequency<commit_after>// This file is part of the HörTech Open Master Hearing Aid (openMHA)
// Copyright © 2018 2019 HörTech gGmbH
//
// openMHA is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// openMHA is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License, version 3 for more details.
//
// You should have received a copy of the GNU Affero General Public License,
// version 3 along with openMHA.  If not, see <http://www.gnu.org/licenses/>.

#include "fshift.hh"
#include <cmath>

int fshift::fft_find_bin(mha_real_t frequency, unsigned fftlen, mha_real_t srate){
  if(frequency<-srate/2 or frequency>srate/2){
    throw MHA_Error(__FILE__,__LINE__,"fft_find_bin: Frequency %.0f is out of range [0, %0.f].",frequency,srate/2);
  }
  return round(frequency*fftlen/srate);
}

fshift::fshift_config_t::fshift_config_t(fshift_t const * const plug)
  :  kmin(fft_find_bin(plug->fmin(),plug->input_cfg().fftlen,plug->input_cfg().srate)),
     kmax(fft_find_bin(plug->fmax(),plug->input_cfg().fftlen,plug->input_cfg().srate)),
     df(fft_find_bin(plug->df(),plug->input_cfg().fftlen,plug->input_cfg().srate)),
     delta_phi{std::cos(plug->input_cfg().fragsize*plug->df()*static_cast<mha_real_t>(M_PI)*2.0f/plug->input_cfg().srate),
               std::sin(plug->input_cfg().fragsize*plug->df()*static_cast<mha_real_t>(M_PI)*2.0f/plug->input_cfg().srate)},
     delta_phi_total{1.0f,0.0f}
{}

mha_spec_t *fshift::fshift_config_t::process(mha_spec_t *in)
{
  if(df==0){
    return in;
  }
  for(unsigned ch=0U; ch<in->num_channels; ++ch){
    if(df<0){
      for(unsigned fr=kmin; fr<kmax; ++fr){
        int idx=fr+df;
        if(idx<static_cast<int>(in->num_frames) and idx>=0){
          value(in,idx,ch)+=value(in,fr,ch)*delta_phi_total;
          value(in, fr, ch)={0,0};
        }
      }
    }
    else{
      for(unsigned fr=kmax; fr-->kmin;){
        int idx=fr+df;
        if(idx<static_cast<int>(in->num_frames) and idx>=0){
          value(in,idx,ch)+=value(in,fr,ch)*delta_phi_total;
          value(in, fr, ch)={0,0};
        }
      }
    }
  }
  delta_phi_total*=delta_phi;
  delta_phi_total=delta_phi_total/abs(delta_phi_total);
  return in;
}

/** Constructs our plugin. */
fshift::fshift_t::fshift_t(algo_comm_t & ac,
                   const std::string & chain_name,
                   const std::string & algo_name)
       : MHAPlugin::plugin_t<fshift_config_t>("",ac),
  m_fmin("lower boundary for frequency shifter in Hz","4000","[0,]"),
  m_fmax("upper boundary for frequency shifter in Hz","16000","[0,]"),
  m_df("shift frequency in Hz","40","")
{
  insert_item("fmin",&m_fmin);
  patchbay.connect(&m_fmin.valuechanged, this, &fshift::fshift_t::update_cfg);
  insert_item("fmax",&m_fmax);
  patchbay.connect(&m_fmax.valuechanged, this, &fshift::fshift_t::update_cfg);
  insert_item("df",&m_df);
  patchbay.connect(&m_df.valuechanged, this, &fshift::fshift_t::update_cfg);
}

fshift::fshift_t::~fshift_t() {}

/** Plugin preparation.
 *  An opportunity to validate configuration parameters before instantiating a configuration.
 * @param signal_info
 *   Structure containing a description of the form of the signal (domain,
 *   number of channels, frames per block, sampling rate.
 */
void fshift::fshift_t::prepare(mhaconfig_t & signal_info)
{
  if (signal_info.domain != MHA_SPECTRUM)
    throw MHA_Error(__FILE__, __LINE__,
                    "This plugin can only process spectrum signals.");

  mha_real_t frate = 0.5*signal_info.srate;
  if( m_df.data > frate )
    m_df.data= frate;
  if( m_df.data < -frate )
    m_df.data = -frate;
  if(m_fmax.data > frate)
    m_fmax.data=frate;
  /* make sure that a valid runtime configuration exists: */
  update_cfg();
}

void fshift::fshift_t::update_cfg()
{
    if ( is_prepared() ) {

        //when necessary, make a new configuration instance
        //possibly based on changes in parser variables
        fshift_config_t *config;
        config = new fshift_config_t( this );
        push_config( config );
    }
}

/**
 * Checks for the most recent configuration and defers processing to it.
 */
mha_spec_t * fshift::fshift_t::process(mha_spec_t * signal)
{
    //this stub method defers processing to the configuration class
    return poll_config()->process( signal );
}

/*
 * This macro connects the plugin1_t class with the MHA plugin C interface
 * The first argument is the class name, the other arguments define the
 * input and output domain of the algorithm.
 */
MHAPLUGIN_CALLBACKS(fshift,fshift::fshift_t,
                    spec,spec)

/*
 * This macro creates code classification of the plugin and for
 * automatic documentation.
 *
 * The first argument to the macro is a space separated list of
 * categories, starting with the most relevant category. The second
 * argument is a LaTeX-compatible character array with some detailed
 * documentation of the plugin.
 */
MHAPLUGIN_DOCUMENTATION
(fshift::fshift_t,
 "feedback-suppression frequency-modification",
 " Performs a quantized frequency shift on the selected frequency"
 " interval. "
 " The frequency band between (originally)"
 " \\texttt{fmin} and \\texttt{fmax} (frequencies in Hz)"
 " is shifted by \\texttt{df} (desired frequency change"
 " in Hz). "
 " Positive \\texttt{df} shifts the selected band to"
 " higher frequencies, negative \\texttt{df} shifts to"
 " lower frequencies."
 " \n\n"
 " The shifted and the unshifted parts of the"
 " input signal are split at the STFT bin boundaries nearest to the."
 " The frequency shift \\texttt{df} is rounded to the nearest bin as well."
 " The parts of the spectrum that would be shifted below 0 Hz or above the Nyquist"
 " frequency are discarded. "
 )

// Local Variables:
// compile-command: "make"
// c-basic-offset: 2
// indent-tabs-mode: nil
// coding: utf-8-unix
// End:
<|endoftext|>


<commit_before>/***************************************************************************
 *  @file       redblacktree.hpp
 *  @author     Alan.W
 *  @date       05  July 2014
 *  @remark     Algorithims implementation for CLRS, using C++ templates.
 ***************************************************************************/
#ifndef REDBLACKTREE_HPP
#define REDBLACKTREE_HPP
#include <memory>
#include <functional>
#include "node.hpp"

namespace ch13{

/**
 * @brief The RedBlackTree class
 */
template<typename K, typename D>
class RedBlackTree
{
public:
    using KeyType   =   K;
    using DataType  =   D;
    using NodeType  =   Node<K,D>;
    using sPointer  =   std::shared_ptr<NodeType>;
    using wPointer  =   std::weak_ptr<NodeType>;

    RedBlackTree():
        nil(std::make_shared<NodeType>())
    {
        root = nil;
    }

    /**
     * @brief print
     *
     * O(n)
     */
    void print()const
    {
        std::function<void(sPointer node)> inorder_walk =
                [&inorder_walk,this](sPointer node)
        {
            if(node != nil)
            {
                inorder_walk(node->left);
                node->print();
                inorder_walk(node->right);
            }
        };
        inorder_walk(root);
    }

    /**
     * @brief insert
     * @param key
     *
     * O(h)
     */
    void insert(const KeyType& key)
    {
        sPointer added = std::make_shared<NodeType>(key);
        insert(added);
    }

    /**
     * @brief insert
     * @param added
     *
     * O(h)
     */
    void insert(sPointer added)
    {
        sPointer tracker = nil;
        sPointer curr = root;
        while(curr != nil)
        {
            tracker =   curr;
            curr    =   curr->key > added->key?     curr->left  :   curr->right;
        }

        added->parent   =   tracker;
        if(tracker == nil)
            root    =   added;
        else
            (added->key < tracker->key?     tracker->left   :   tracker->right)
                    =   added;

        added->left =   added->right    =   nil;
        added->color=   Color::RED;

        //--to do   :   add fixup
    }
private:
    sPointer root;
    sPointer nil;
};
}//namespace

#endif // REDBLACKTREE_HPP
<commit_msg>add left rotate  On branch ch13 	modified:   ch13/redblacktree.hpp<commit_after>/***************************************************************************
 *  @file       redblacktree.hpp
 *  @author     Alan.W
 *  @date       05  July 2014
 *  @remark     Algorithims implementation for CLRS, using C++ templates.
 ***************************************************************************/
#ifndef REDBLACKTREE_HPP
#define REDBLACKTREE_HPP
#include <memory>
#include <functional>
#include "node.hpp"

namespace ch13{

/**
 * @brief The RedBlackTree class
 */
template<typename K, typename D>
class RedBlackTree
{
public:
    using KeyType   =   K;
    using DataType  =   D;
    using NodeType  =   Node<K,D>;
    using sPointer  =   std::shared_ptr<NodeType>;
    using wPointer  =   std::weak_ptr<NodeType>;

    RedBlackTree():
        nil(std::make_shared<NodeType>())
    {
        root = nil;
    }

    /**
     * @brief print
     *
     * O(n)
     */
    void print()const
    {
        std::function<void(sPointer node)> inorder_walk =
                [&inorder_walk,this](sPointer node)
        {
            if(node != nil)
            {
                inorder_walk(node->left);
                node->print();
                inorder_walk(node->right);
            }
        };
        inorder_walk(root);
    }

    /**
     * @brief insert
     * @param key
     *
     * O(h)
     */
    void insert(const KeyType& key)
    {
        sPointer added = std::make_shared<NodeType>(key);
        insert(added);
    }

    /**
     * @brief insert
     * @param added
     *
     * O(h)
     */
    void insert(sPointer added)
    {
        sPointer tracker = nil;
        sPointer curr = root;
        while(curr != nil)
        {
            tracker =   curr;
            curr    =   curr->key > added->key?     curr->left  :   curr->right;
        }

        added->parent   =   tracker;
        if(tracker == nil)
            root    =   added;
        else
            (added->key < tracker->key?     tracker->left   :   tracker->right)
                    =   added;

        added->left =   added->right    =   nil;
        added->color=   Color::RED;

        //--to do   :   add fixup
    }

    sPointer search(const KeyType& key)const
    {
        sPointer ret  = nullptr;
        sPointer curr = this->root;
        while(curr)
        {
            if(curr->key    ==  key)
            {
                ret = curr;
                break;
            }
            else
                curr = (curr->key > key?    curr->left  :   curr->right);
        }
        return ret;
    }

    /**
     * @brief left_rotate
     * @param x
     *
     *      [x]                    [y]
     *         \        =>        /
     *          [y]            [x]
     *
     * @complx  o(1)
     */
    void left_rotate(sPointer x)
    {
        sPointer y = x->right;      //  set y

        x->right    =   y->left;    //  turn y's left into x's right
        if(y->left  !=  this->nil)
            y->left->parent = x;

        y->parent   =   x->parent;  //  link x's parent to y
        if(x->parent    ==  this->nil)
            this->root  =   y;
        else
            (x->is_left()?  x->parent.lock()->left  :  x->parent.lock()->right)
                        =   y;

        y->left     =   x;
        x->parent   =   y;
    }
private:
    sPointer root;
    sPointer nil;
};
}//namespace

#endif // REDBLACKTREE_HPP
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// 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 <string>

#include "runtime/free-pool.h"
#include "runtime/mem-pool.h"
#include "runtime/mem-tracker.h"
#include "testutil/gtest-util.h"

#include "common/names.h"

namespace impala {

TEST(FreePoolTest, Basic) {
  MemTracker tracker;
  MemPool mem_pool(&tracker);
  FreePool pool(&mem_pool);

  // Start off with some corner cases.
  uint8_t* p1 = pool.Allocate(0);
  ASSERT_TRUE(p1 != NULL);
  pool.Free(p1);
  pool.Free(NULL);

  EXPECT_EQ(mem_pool.total_allocated_bytes(), 0);
  p1 = pool.Allocate(1);
  *p1 = 111; // Scribble something to make sure it doesn't mess up the list.
  ASSERT_TRUE(p1 != NULL);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 16);
  pool.Free(p1);

  // Allocating this should return p again.
  for (int i = 0; i < 10; ++i) {
    uint8_t* p2 = pool.Allocate(1);
    *p2 = 111;
    EXPECT_EQ(p1, p2);
    EXPECT_EQ(mem_pool.total_allocated_bytes(), 16);
    pool.Free(p2);
  }

  uint8_t* p2 = pool.Allocate(1);
  *p2 = 111;
  // p3 will cause a new allocation.
  uint8_t* p3 = pool.Allocate(1);
  *p3 = 111;
  EXPECT_TRUE(p1 == p2);
  EXPECT_TRUE(p1 != p3);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 32);
  pool.Free(p2);
  pool.Free(p3);

  // We know have 2 1 byte allocations, which were rounded up to 8 bytes. Make an 8
  // byte allocation, which can reuse one of the existing ones.
  uint8_t* p4 = pool.Allocate(2);
  memset(p4, 2, 123);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 32);
  EXPECT_TRUE(p4 == p1 || p4 == p2 || p4 == p3);
  pool.Free(p4);

  // Make a 9 byte allocation, which requires a new allocation.
  uint8_t* p5 = pool.Allocate(9);
  memset(p5, 9, 123);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 56);
  pool.Free(p5);
  EXPECT_TRUE(p5 != p1);
  EXPECT_TRUE(p5 != p2);
  EXPECT_TRUE(p5 != p3);

  // Everything's freed. Try grabbing the ones that have been allocated.
  p1 = pool.Allocate(1);
  *p1 = 123;
  p2 = pool.Allocate(1);
  *p2 = 123;
  p5 = pool.Allocate(9);
  memset(p5, 123, 9);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 56);

  // Make another 1 byte allocation.
  p4 = pool.Allocate(1);
  *p4 = 1;
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 72);

  mem_pool.FreeAll();

  // Try making allocations larger than 1GB.
  uint8_t* p6 = pool.Allocate(1LL << 32);
  EXPECT_TRUE(p6 != NULL);
  for (int64_t i = 0; i < (1LL << 32); i += (1 << 29)) {
    *(p6 + i) = i;
  }
  EXPECT_EQ(mem_pool.total_allocated_bytes(), (1LL << 32) + 8);

  // Test zero-byte allocation.
  p6 = pool.Allocate(0);
  EXPECT_TRUE(p6 != NULL);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), (1LL << 32) + 8);
  pool.Free(p6);

  mem_pool.FreeAll();
}

// In this test we make two allocations at increasing sizes and then we
// free both to prime the pool. Then, for a few iterations, we make the same allocations
// as we did to prime the pool in a random order. We validate that the returned
// allocation is one of the two original and the pool did not increase in size.
TEST(FreePoolTest, Loop) {
  MemTracker tracker;
  MemPool mem_pool(&tracker);
  FreePool pool(&mem_pool);

  map<int64_t, pair<uint8_t*, uint8_t*>> primed_allocations;
  vector<int64_t> allocation_sizes;

  int64_t expected_pool_size = 0;

  // Pick a non-power of 2 to exercise more code.
  for (int64_t size = 5; size < 6LL * 1024 * 1024 * 1024; size *= 5) {
    uint8_t* p1 = pool.Allocate(size);
    uint8_t* p2 = pool.Allocate(size);
    EXPECT_TRUE(p1 != NULL);
    EXPECT_TRUE(p2 != NULL);
    EXPECT_TRUE(p1 != p2);
    memset(p1, 1, size); // Scribble the expected value (used below).
    memset(p2, 1, size);
    primed_allocations[size] = make_pair(p1, p2);
    pool.Free(p1);
    pool.Free(p2);
    allocation_sizes.push_back(size);
  }
  expected_pool_size = mem_pool.total_allocated_bytes();

  for (int iters = 1; iters <= 5; ++iters) {
    std::random_shuffle(allocation_sizes.begin(), allocation_sizes.end());
    for (int i = 0; i < allocation_sizes.size(); ++i) {
      uint8_t* p1 = pool.Allocate(allocation_sizes[i]);
      uint8_t* p2 = pool.Allocate(allocation_sizes[i]);
      EXPECT_TRUE(p1 != p2);
      EXPECT_TRUE(p1 == primed_allocations[allocation_sizes[i]].first ||
                  p1 == primed_allocations[allocation_sizes[i]].second);
      EXPECT_TRUE(p2 == primed_allocations[allocation_sizes[i]].first ||
                  p2 == primed_allocations[allocation_sizes[i]].second);
      EXPECT_EQ(*p1, iters);
      EXPECT_EQ(*p2, iters);
      ++(*p1);
      ++(*p2);
      pool.Free(p1);
      pool.Free(p2);
    }
    EXPECT_EQ(mem_pool.total_allocated_bytes(), expected_pool_size);
  }

  mem_pool.FreeAll();
}

TEST(FreePoolTest, ReAlloc) {
  MemTracker tracker;
  MemPool mem_pool(&tracker);
  FreePool pool(&mem_pool);

  uint8_t* ptr = pool.Reallocate(NULL, 0);
  ptr = pool.Reallocate(ptr, 0);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 0);

  ptr = pool.Reallocate(ptr, 600);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8);
  uint8_t* ptr2 = pool.Reallocate(ptr, 200);
  EXPECT_TRUE(ptr == ptr2);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8);

  uint8_t* ptr3 = pool.Reallocate(ptr, 2000);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8 + 2048 + 8);
  EXPECT_TRUE(ptr2 != ptr3);

  // The original 600 allocation should be there.
  ptr = pool.Allocate(600);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8 + 2048 + 8);

  // Try allocation larger than 1GB.
  uint8_t* ptr4 = pool.Reallocate(ptr3, 1LL << 32);
  EXPECT_TRUE(ptr3 != ptr4);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8 + 2048 + 8 + (1LL << 32) + 8);

  // Shrink the allocation.
  uint8_t* ptr5 = pool.Reallocate(ptr4, 1024);
  EXPECT_TRUE(ptr4 == ptr5);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8 + 2048 + 8 + (1LL << 32) + 8);
  pool.Free(ptr5);

  mem_pool.FreeAll();
}

}

IMPALA_TEST_MAIN();
<commit_msg>IMPALA-5297: Reduce free-pool-test mem requirement to avoid OOM<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// 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 <string>

#include "runtime/free-pool.h"
#include "runtime/mem-pool.h"
#include "runtime/mem-tracker.h"
#include "testutil/gtest-util.h"

#include "common/names.h"

namespace impala {

TEST(FreePoolTest, Basic) {
  MemTracker tracker;
  MemPool mem_pool(&tracker);
  FreePool pool(&mem_pool);

  // Start off with some corner cases.
  uint8_t* p1 = pool.Allocate(0);
  ASSERT_TRUE(p1 != NULL);
  pool.Free(p1);
  pool.Free(NULL);

  EXPECT_EQ(mem_pool.total_allocated_bytes(), 0);
  p1 = pool.Allocate(1);
  *p1 = 111; // Scribble something to make sure it doesn't mess up the list.
  ASSERT_TRUE(p1 != NULL);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 16);
  pool.Free(p1);

  // Allocating this should return p again.
  for (int i = 0; i < 10; ++i) {
    uint8_t* p2 = pool.Allocate(1);
    *p2 = 111;
    EXPECT_EQ(p1, p2);
    EXPECT_EQ(mem_pool.total_allocated_bytes(), 16);
    pool.Free(p2);
  }

  uint8_t* p2 = pool.Allocate(1);
  *p2 = 111;
  // p3 will cause a new allocation.
  uint8_t* p3 = pool.Allocate(1);
  *p3 = 111;
  EXPECT_TRUE(p1 == p2);
  EXPECT_TRUE(p1 != p3);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 32);
  pool.Free(p2);
  pool.Free(p3);

  // We know have 2 1 byte allocations, which were rounded up to 8 bytes. Make an 8
  // byte allocation, which can reuse one of the existing ones.
  uint8_t* p4 = pool.Allocate(2);
  memset(p4, 2, 123);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 32);
  EXPECT_TRUE(p4 == p1 || p4 == p2 || p4 == p3);
  pool.Free(p4);

  // Make a 9 byte allocation, which requires a new allocation.
  uint8_t* p5 = pool.Allocate(9);
  memset(p5, 9, 123);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 56);
  pool.Free(p5);
  EXPECT_TRUE(p5 != p1);
  EXPECT_TRUE(p5 != p2);
  EXPECT_TRUE(p5 != p3);

  // Everything's freed. Try grabbing the ones that have been allocated.
  p1 = pool.Allocate(1);
  *p1 = 123;
  p2 = pool.Allocate(1);
  *p2 = 123;
  p5 = pool.Allocate(9);
  memset(p5, 123, 9);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 56);

  // Make another 1 byte allocation.
  p4 = pool.Allocate(1);
  *p4 = 1;
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 72);

  mem_pool.FreeAll();

  // Try making allocations larger than 1GB.
  uint8_t* p6 = pool.Allocate(1LL << 32);
  EXPECT_TRUE(p6 != NULL);
  for (int64_t i = 0; i < (1LL << 32); i += (1 << 29)) {
    *(p6 + i) = i;
  }
  EXPECT_EQ(mem_pool.total_allocated_bytes(), (1LL << 32) + 8);

  // Test zero-byte allocation.
  p6 = pool.Allocate(0);
  EXPECT_TRUE(p6 != NULL);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), (1LL << 32) + 8);
  pool.Free(p6);

  mem_pool.FreeAll();
}

// In this test we make two allocations at increasing sizes and then we
// free both to prime the pool. Then, for a few iterations, we make the same allocations
// as we did to prime the pool in a random order. We validate that the returned
// allocation is one of the two original and the pool did not increase in size.
TEST(FreePoolTest, Loop) {
  MemTracker tracker;
  MemPool mem_pool(&tracker);
  FreePool pool(&mem_pool);

  map<int64_t, pair<uint8_t*, uint8_t*>> primed_allocations;
  vector<int64_t> allocation_sizes;

  int64_t expected_pool_size = 0;

  // Pick a non-power of 2 to exercise more code.
  for (int64_t size = 5; size < 6LL * 1024 * 1024 * 1024; size *= 5) {
    uint8_t* p1 = pool.Allocate(size);
    uint8_t* p2 = pool.Allocate(size);
    EXPECT_TRUE(p1 != NULL);
    EXPECT_TRUE(p2 != NULL);
    EXPECT_TRUE(p1 != p2);
    // Scribble the expected value (used below).
    *p1 = 1;
    *p2 = 1;
    primed_allocations[size] = make_pair(p1, p2);
    pool.Free(p1);
    pool.Free(p2);
    allocation_sizes.push_back(size);
  }
  expected_pool_size = mem_pool.total_allocated_bytes();

  for (int iters = 1; iters <= 5; ++iters) {
    std::random_shuffle(allocation_sizes.begin(), allocation_sizes.end());
    for (int i = 0; i < allocation_sizes.size(); ++i) {
      uint8_t* p1 = pool.Allocate(allocation_sizes[i]);
      uint8_t* p2 = pool.Allocate(allocation_sizes[i]);
      EXPECT_TRUE(p1 != p2);
      EXPECT_TRUE(p1 == primed_allocations[allocation_sizes[i]].first ||
                  p1 == primed_allocations[allocation_sizes[i]].second);
      EXPECT_TRUE(p2 == primed_allocations[allocation_sizes[i]].first ||
                  p2 == primed_allocations[allocation_sizes[i]].second);
      EXPECT_EQ(*p1, iters);
      EXPECT_EQ(*p2, iters);
      ++(*p1);
      ++(*p2);
      pool.Free(p1);
      pool.Free(p2);
    }
    EXPECT_EQ(mem_pool.total_allocated_bytes(), expected_pool_size);
  }

  mem_pool.FreeAll();
}

TEST(FreePoolTest, ReAlloc) {
  MemTracker tracker;
  MemPool mem_pool(&tracker);
  FreePool pool(&mem_pool);

  uint8_t* ptr = pool.Reallocate(NULL, 0);
  ptr = pool.Reallocate(ptr, 0);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 0);

  ptr = pool.Reallocate(ptr, 600);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8);
  uint8_t* ptr2 = pool.Reallocate(ptr, 200);
  EXPECT_TRUE(ptr == ptr2);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8);

  uint8_t* ptr3 = pool.Reallocate(ptr, 2000);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8 + 2048 + 8);
  EXPECT_TRUE(ptr2 != ptr3);

  // The original 600 allocation should be there.
  ptr = pool.Allocate(600);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8 + 2048 + 8);

  // Try allocation larger than 1GB.
  uint8_t* ptr4 = pool.Reallocate(ptr3, 1LL << 32);
  EXPECT_TRUE(ptr3 != ptr4);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8 + 2048 + 8 + (1LL << 32) + 8);

  // Shrink the allocation.
  uint8_t* ptr5 = pool.Reallocate(ptr4, 1024);
  EXPECT_TRUE(ptr4 == ptr5);
  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8 + 2048 + 8 + (1LL << 32) + 8);
  pool.Free(ptr5);

  mem_pool.FreeAll();
}

}

IMPALA_TEST_MAIN();
<|endoftext|>


<commit_before>// @(#)root/test:$Name:  $:$Id: tcollex.cxx,v 1.8 2002/06/29 13:21:08 brun Exp $
// Author: Fons Rademakers   19/08/96

#include <stdlib.h>

#include "Riostream.h"
#include "TString.h"
#include "TObjString.h"
#include "TSortedList.h"
#include "TObjArray.h"
#include "TOrdCollection.h"
#include "THashTable.h"
#include "TBtree.h"
#include "TStopwatch.h"

// To focus on basic collection protocol, this sample program uses
// simple classes inheriting from TObject. One class, TObjString, is a
// collectable string class (a TString wrapped in a TObject) provided
// by the ROOT system. The other class we define below, is an integer
// wrapped in a TObject, just like TObjString.

// TObjNum is a simple container for an integer.
class TObjNum : public TObject {
private:
   int  num;

public:
   TObjNum(int i = 0) : num(i) { }
   ~TObjNum() { Printf("~TObjNum = %d", num); }
   void    SetNum(int i) { num = i; }
   int     GetNum() { return num; }
   void    Print(Option_t *) const { Printf("TObjNum = %d", num); }
   ULong_t Hash() const { return num; }
   Bool_t  IsEqual(const TObject *obj) const { return num == ((TObjNum*)obj)->num; }
   Bool_t  IsSortable() const { return kTRUE; }
   Int_t   Compare(const TObject *obj) const { if (num > ((TObjNum*)obj)->num)
                                      return 1;
                                   else if (num < ((TObjNum*)obj)->num)
                                      return -1;
                                   else
                                      return 0; }
};

void Test_TObjArray()
{

   Printf(
   "////////////////////////////////////////////////////////////////\n"
   "// Test of TObjArray                                          //\n"
   "////////////////////////////////////////////////////////////////"
   );

   // Array of capacity 10, Add() will automatically expand the array if necessary.
   TObjArray  a(10);

   Printf("Filling TObjArray");
   a.Add(new TObjNum(1));            // add at next free slot, pos 0
   a[1] = new TObjNum(2);            // use operator[], put at pos 1
   TObjNum *n3 = new TObjNum(3);
   a.AddAt(n3,2);                    // add at position 2
   a.Add(new TObjNum(4));            // add at next free slot, pos 3
   a.AddLast(new TObjNum(10));       // add at pos 4
   TObjNum n6(6);                    // stack based TObjNum
   a.AddAt(&n6,5);                   // add at pos 5
   a[6] = new TObjNum(5);            // add at respective positions
   a[7] = new TObjNum(8);
   a[8] = new TObjNum(7);
//   a[10] = &n6;                    // gives out-of-bound error

   Printf("Print array");
   a.Print();                        // invoke Print() of all objects

   Printf("Sort array");
   a.Sort();
   for (int i = 0; i < a.Capacity(); i++)  // typical way of iterating over array
      if (a[i])
         a[i]->Print();      // can also use operator[] to access elements
      else
         Printf("%d empty slot", i);

   Printf("Use binary search to get position of number 6");
   Printf("6 is at position %d", a.BinarySearch(&n6));

   Printf("Find number before 6");
   a.Before(&n6)->Print();

   Printf("Find number after 3");
   a.After(n3)->Print();

   Printf("Remove 3 and print list again");
   a.Remove(n3);
   delete n3;
   a.Print();

   Printf("Iterate forward over list and remove 4 and 7");

   // TIter encapsulates the actual class iterator. The type of iterator
   // used depends on the type of the collection.
   TIter next(&a);

   TObjNum *obj;
   while ((obj = (TObjNum*)next()))     // iterator skips empty slots
      if (obj->GetNum() == 4) {
         a.Remove(obj);
         delete obj;
      }

   // Reset the iterator and loop again
   next.Reset();
   while ((obj = (TObjNum*)next()))
      if (obj->GetNum() == 7) {
         a.Remove(obj);
         delete obj;
      }

   Printf("Iterate backward over list and remove 2");
   TIter next1(&a, kIterBackward);
   while ((obj = (TObjNum*)next1()))
      if (obj->GetNum() == 2) {
         a.Remove(obj);
         delete obj;
      }

   Printf("Delete remainder of list: 1,5,8,10 (6 not deleted since not on heap)");

   // Delete heap objects and clear list. Attention: do this only when you
   // own all objects stored in the collection. When you stored aliases to
   // the actual objects (i.e. you did not create the objects) use Clear()
   // instead.
   a.Delete();

   Printf("Delete stack based objects (6)");
}

void Test_TOrdCollection()
{
   Printf(
   "////////////////////////////////////////////////////////////////\n"
   "// Test of TOrdCollection                                     //\n"
   "////////////////////////////////////////////////////////////////"
   );

   // Create collection with default size, Add() will automatically expand
   // the collection if necessary.
   TOrdCollection  c;

   Printf("Filling TOrdCollection");
   c.Add(new TObjString("anton"));      // add at next free slot, pos 0
   c.AddFirst(new TObjString("bobo"));  // put at pos 0, bump anton to pos 1
   TObjString *s3 = new TObjString("damon");
   c.AddAt(s3,1);                       // add at position 1, bump anton to pos 2
   c.Add(new TObjString("cassius"));    // add at next free slot, pos 3
   c.AddLast(new TObjString("enigma")); // add at pos 4
   TObjString s6("fons");               // stack based TObjString
   c.AddBefore(s3,&s6);                 // add at pos 1
   c.AddAfter(s3, new TObjString("gaia"));

   Printf("Print collection");
   c.Print();                           // invoke Print() of all objects

   Printf("Sort collection");
   c.Sort();
   c.Print();

   Printf("Use binary search to get position of string damon");
   Printf("damon is at position %d", c.BinarySearch(s3));

   Printf("Find str before fons");
   c.Before(&s6)->Print();

   Printf("Find string after damon");
   c.After(s3)->Print();

   Printf("Remove damon and print list again");
   c.Remove(s3);
   delete s3;
   c.Print();

   Printf("Iterate forward over list and remove cassius");
   TObjString *objs;
   TIter next(&c);
   while ((objs = (TObjString*)next()))     // iterator skips empty slots
      if (objs->String() == "cassius") {
         c.Remove(objs);
         delete objs;
      }

   Printf("Iterate backward over list and remove gaia");
   TIter next1(&c, kIterBackward);
   while ((objs = (TObjString*)next1()))
      if (objs->String() == "gaia") {
         c.Remove(objs);
         delete objs;
      }

   Printf("Delete remainder of list: anton,bobo,enigma (fons not deleted since not on heap)");
   c.Delete();                        // delete heap objects and clear list

   Printf("Delete stack based objects (fons)");
}

void Test_TList()
{
   Printf(
   "////////////////////////////////////////////////////////////////\n"
   "// Test of TList                                              //\n"
   "////////////////////////////////////////////////////////////////"
   );

   // Create a doubly linked list.
   TList l;

   Printf("Filling TList");
   TObjNum *n3 = new TObjNum(3);
   l.Add(n3);
   l.AddBefore(n3, new TObjNum(5));
   l.AddAfter(n3, new TObjNum(2));
   l.Add(new TObjNum(1));
   l.AddBefore(n3, new TObjNum(4));
   TObjNum n6(6);                     // stack based TObjNum
   l.AddFirst(&n6);

   Printf("Print list");
   l.Print();

   Printf("Remove 3 and print list again");
   l.Remove(n3);
   delete n3;
   l.Print();

   Printf("Iterate forward over list and remove 4");
   TObjNum *obj;
   TIter next(&l);
   while ((obj = (TObjNum*)next()))
      if (obj->GetNum() == 4) l.Remove(obj);

   Printf("Iterate backward over list and remove 2");
   TIter next1(&l, kIterBackward);
   while ((obj = (TObjNum*)next1()))
      if (obj->GetNum() == 2) {
         l.Remove(obj);
         delete obj;
      }

   Printf("Delete remainder of list: 1, 5 (6 not deleted since not on heap)");
   l.Delete();

   Printf("Delete stack based objects (6)");
}

void Test_TSortedList()
{
   Printf(
   "////////////////////////////////////////////////////////////////\n"
   "// Test of TSortedList                                        //\n"
   "////////////////////////////////////////////////////////////////"
   );

   // Create a sorted doubly linked list.
   TSortedList sl;

   Printf("Filling TSortedList");
   TObjNum *n3 = new TObjNum(3);
   sl.Add(n3);
   sl.AddBefore(n3,new TObjNum(5));
   sl.AddAfter(n3, new TObjNum(2));
   sl.Add(new TObjNum(1));
   sl.AddBefore(n3, new TObjNum(4));
   TObjNum n6(6);                     // stack based TObjNum
   sl.AddFirst(&n6);

   Printf("Print list");
   sl.Print();

   Printf("Delete all heap based objects (6 not deleted since not on heap)");
   sl.Delete();

   Printf("Delete stack based objects (6)");
}

void Test_THashTable()
{
   Printf(
   "////////////////////////////////////////////////////////////////\n"
   "// Test of THashTable                                         //\n"
   "////////////////////////////////////////////////////////////////"
   );

   int i;

   // Create a hash table with an initial size of 20 (actually the next prime
   // above 20). No automatic rehashing.
   THashTable ht(20);

   Printf("Filling THashTable");
   Printf("Number of slots before filling: %d", ht.Capacity());
   for (i = 0; i < 1000; i++)
      ht.Add(new TObject);

   Printf("Average collisions: %f", ht.AverageCollisions());

   // rehash the hash table to reduce the collission rate
   ht.Rehash(ht.GetSize());

   Printf("Number of slots after rehash: %d", ht.Capacity());
   Printf("Average collisions after rehash: %f", ht.AverageCollisions());

   ht.Delete();

   // Create a hash table and trigger automatic rehashing when average
   // collision rate becomes larger than 5.
   THashTable ht2(20,5);

   Printf("Filling THashTable with automatic rehash when AverageCollisions>5");
   Printf("Number of slots before filling: %d", ht2.Capacity());
   for (i = 0; i < 1000; i++)
      ht2.Add(new TObject);

   Printf("Number of slots after filling: %d", ht2.Capacity());
   Printf("Average collisions: %f", ht2.AverageCollisions());

   Printf("\nDelete all heap based objects");
   ht2.Delete();
}

void Test_TBtree()
{
   Printf(
   "////////////////////////////////////////////////////////////////\n"
   "// Test of TBtree                                             //\n"
   "////////////////////////////////////////////////////////////////"
   );
   TStopwatch timer;      // create a timer
   TBtree     l;          // btree of order 3

   Printf("Filling TBtree");

   TObjNum *n3 = new TObjNum(3);
   l.Add(n3);
   l.AddBefore(n3,new TObjNum(5));
   l.AddAfter(n3, new TObjNum(2));
   l.Add(new TObjNum(1));
   l.AddBefore(n3, new TObjNum(4));
   TObjNum n6(6);                     // stack based TObjNum
   l.AddFirst(&n6);

   timer.Start();
   for (int i = 0; i < 50; i++)
      l.Add(new TObjNum(i));
   timer.Print();

   Printf("Print TBtree");
   l.Print();

   Printf("Remove 3 and print TBtree again");
   l.Remove(n3);
   l.Print();

   Printf("Iterate forward over TBtree and remove 4 from tree");
   TIter next(&l);
   TObjNum *obj;
   while ((obj = (TObjNum*)next()))
      if (obj->GetNum() == 4) l.Remove(obj);

   Printf("Iterate backward over TBtree and remove 2 from tree");
   TIter next1(&l, kIterBackward);
   while ((obj = (TObjNum*)next1()))
      if (obj->GetNum() == 2) l.Remove(obj);

   Printf("\nDelete all heap based objects");
   l.Delete();

   Printf("Delete stack based objects (6)");
}

int tcollex() {
   Test_TObjArray();
   Test_TOrdCollection();
   Test_TList();
   Test_TSortedList();
   Test_THashTable();
   Test_TBtree();

   return 0;
}

#ifndef __CINT__
int main() {
   return tcollex();
}
#endif
<commit_msg>use new TObjNumI class instead of local example class.<commit_after>// @(#)root/test:$Name:  $:$Id: tcollex.cxx,v 1.9 2002/06/30 13:17:33 brun Exp $
// Author: Fons Rademakers   19/08/96

#include <stdlib.h>

#include "Riostream.h"
#include "TString.h"
#include "TObjString.h"
#include "TSortedList.h"
#include "TObjArray.h"
#include "TOrdCollection.h"
#include "THashTable.h"
#include "TBtree.h"
#include "TStopwatch.h"
#include "TObjNum.h"

// To focus on basic collection protocol, this sample program uses
// simple classes inheriting from TObject. One class, TObjString, is a
// collectable string class (a TString wrapped in a TObject) provided
// by the ROOT system. The other class TObjNumI, is an integer wrapped
// in a TObject, just like TObjString.

void Test_TObjArray()
{

   Printf(
   "////////////////////////////////////////////////////////////////\n"
   "// Test of TObjArray                                          //\n"
   "////////////////////////////////////////////////////////////////"
   );

   // Array of capacity 10, Add() will automatically expand the array if necessary.
   TObjArray  a(10);

   Printf("Filling TObjArray");
   a.Add(new TObjNumI(1));           // add at next free slot, pos 0
   a[1] = new TObjNumI(2);           // use operator[], put at pos 1
   TObjNumI *n3 = new TObjNumI(3);
   a.AddAt(n3,2);                    // add at position 2
   a.Add(new TObjNumI(4));           // add at next free slot, pos 3
   a.AddLast(new TObjNumI(10));      // add at pos 4
   TObjNumI n6(6);                   // stack based TObjNumI
   a.AddAt(&n6,5);                   // add at pos 5
   a[6] = new TObjNumI(5);           // add at respective positions
   a[7] = new TObjNumI(8);
   a[8] = new TObjNumI(7);
//   a[10] = &n6;                    // gives out-of-bound error

   Printf("Print array");
   a.Print();                        // invoke Print() of all objects

   Printf("Sort array");
   a.Sort();
   for (int i = 0; i < a.Capacity(); i++)  // typical way of iterating over array
      if (a[i])
         a[i]->Print();      // can also use operator[] to access elements
      else
         Printf("%d empty slot", i);

   Printf("Use binary search to get position of number 6");
   Printf("6 is at position %d", a.BinarySearch(&n6));

   Printf("Find number before 6");
   a.Before(&n6)->Print();

   Printf("Find number after 3");
   a.After(n3)->Print();

   Printf("Remove 3 and print list again");
   a.Remove(n3);
   delete n3;
   a.Print();

   Printf("Iterate forward over list and remove 4 and 7");

   // TIter encapsulates the actual class iterator. The type of iterator
   // used depends on the type of the collection.
   TIter next(&a);

   TObjNumI *obj;
   while ((obj = (TObjNumI*)next()))     // iterator skips empty slots
      if (obj->GetNum() == 4) {
         a.Remove(obj);
         delete obj;
      }

   // Reset the iterator and loop again
   next.Reset();
   while ((obj = (TObjNumI*)next()))
      if (obj->GetNum() == 7) {
         a.Remove(obj);
         delete obj;
      }

   Printf("Iterate backward over list and remove 2");
   TIter next1(&a, kIterBackward);
   while ((obj = (TObjNumI*)next1()))
      if (obj->GetNum() == 2) {
         a.Remove(obj);
         delete obj;
      }

   Printf("Delete remainder of list: 1,5,8,10 (6 not deleted since not on heap)");

   // Delete heap objects and clear list. Attention: do this only when you
   // own all objects stored in the collection. When you stored aliases to
   // the actual objects (i.e. you did not create the objects) use Clear()
   // instead.
   a.Delete();

   Printf("Delete stack based objects (6)");
}

void Test_TOrdCollection()
{
   Printf(
   "////////////////////////////////////////////////////////////////\n"
   "// Test of TOrdCollection                                     //\n"
   "////////////////////////////////////////////////////////////////"
   );

   // Create collection with default size, Add() will automatically expand
   // the collection if necessary.
   TOrdCollection  c;

   Printf("Filling TOrdCollection");
   c.Add(new TObjString("anton"));      // add at next free slot, pos 0
   c.AddFirst(new TObjString("bobo"));  // put at pos 0, bump anton to pos 1
   TObjString *s3 = new TObjString("damon");
   c.AddAt(s3,1);                       // add at position 1, bump anton to pos 2
   c.Add(new TObjString("cassius"));    // add at next free slot, pos 3
   c.AddLast(new TObjString("enigma")); // add at pos 4
   TObjString s6("fons");               // stack based TObjString
   c.AddBefore(s3,&s6);                 // add at pos 1
   c.AddAfter(s3, new TObjString("gaia"));

   Printf("Print collection");
   c.Print();                           // invoke Print() of all objects

   Printf("Sort collection");
   c.Sort();
   c.Print();

   Printf("Use binary search to get position of string damon");
   Printf("damon is at position %d", c.BinarySearch(s3));

   Printf("Find str before fons");
   c.Before(&s6)->Print();

   Printf("Find string after damon");
   c.After(s3)->Print();

   Printf("Remove damon and print list again");
   c.Remove(s3);
   delete s3;
   c.Print();

   Printf("Iterate forward over list and remove cassius");
   TObjString *objs;
   TIter next(&c);
   while ((objs = (TObjString*)next()))     // iterator skips empty slots
      if (objs->String() == "cassius") {
         c.Remove(objs);
         delete objs;
      }

   Printf("Iterate backward over list and remove gaia");
   TIter next1(&c, kIterBackward);
   while ((objs = (TObjString*)next1()))
      if (objs->String() == "gaia") {
         c.Remove(objs);
         delete objs;
      }

   Printf("Delete remainder of list: anton,bobo,enigma (fons not deleted since not on heap)");
   c.Delete();                        // delete heap objects and clear list

   Printf("Delete stack based objects (fons)");
}

void Test_TList()
{
   Printf(
   "////////////////////////////////////////////////////////////////\n"
   "// Test of TList                                              //\n"
   "////////////////////////////////////////////////////////////////"
   );

   // Create a doubly linked list.
   TList l;

   Printf("Filling TList");
   TObjNumI *n3 = new TObjNumI(3);
   l.Add(n3);
   l.AddBefore(n3, new TObjNumI(5));
   l.AddAfter(n3, new TObjNumI(2));
   l.Add(new TObjNumI(1));
   l.AddBefore(n3, new TObjNumI(4));
   TObjNumI n6(6);                     // stack based TObjNumI
   l.AddFirst(&n6);

   Printf("Print list");
   l.Print();

   Printf("Remove 3 and print list again");
   l.Remove(n3);
   delete n3;
   l.Print();

   Printf("Iterate forward over list and remove 4");
   TObjNumI *obj;
   TIter next(&l);
   while ((obj = (TObjNumI*)next()))
      if (obj->GetNum() == 4) l.Remove(obj);

   Printf("Iterate backward over list and remove 2");
   TIter next1(&l, kIterBackward);
   while ((obj = (TObjNumI*)next1()))
      if (obj->GetNum() == 2) {
         l.Remove(obj);
         delete obj;
      }

   Printf("Delete remainder of list: 1, 5 (6 not deleted since not on heap)");
   l.Delete();

   Printf("Delete stack based objects (6)");
}

void Test_TSortedList()
{
   Printf(
   "////////////////////////////////////////////////////////////////\n"
   "// Test of TSortedList                                        //\n"
   "////////////////////////////////////////////////////////////////"
   );

   // Create a sorted doubly linked list.
   TSortedList sl;

   Printf("Filling TSortedList");
   TObjNumI *n3 = new TObjNumI(3);
   sl.Add(n3);
   sl.AddBefore(n3,new TObjNumI(5));
   sl.AddAfter(n3, new TObjNumI(2));
   sl.Add(new TObjNumI(1));
   sl.AddBefore(n3, new TObjNumI(4));
   TObjNumI n6(6);                     // stack based TObjNumI
   sl.AddFirst(&n6);

   Printf("Print list");
   sl.Print();

   Printf("Delete all heap based objects (6 not deleted since not on heap)");
   sl.Delete();

   Printf("Delete stack based objects (6)");
}

void Test_THashTable()
{
   Printf(
   "////////////////////////////////////////////////////////////////\n"
   "// Test of THashTable                                         //\n"
   "////////////////////////////////////////////////////////////////"
   );

   int i;

   // Create a hash table with an initial size of 20 (actually the next prime
   // above 20). No automatic rehashing.
   THashTable ht(20);

   Printf("Filling THashTable");
   Printf("Number of slots before filling: %d", ht.Capacity());
   for (i = 0; i < 1000; i++)
      ht.Add(new TObject);

   Printf("Average collisions: %f", ht.AverageCollisions());

   // rehash the hash table to reduce the collission rate
   ht.Rehash(ht.GetSize());

   Printf("Number of slots after rehash: %d", ht.Capacity());
   Printf("Average collisions after rehash: %f", ht.AverageCollisions());

   ht.Delete();

   // Create a hash table and trigger automatic rehashing when average
   // collision rate becomes larger than 5.
   THashTable ht2(20,5);

   Printf("Filling THashTable with automatic rehash when AverageCollisions>5");
   Printf("Number of slots before filling: %d", ht2.Capacity());
   for (i = 0; i < 1000; i++)
      ht2.Add(new TObject);

   Printf("Number of slots after filling: %d", ht2.Capacity());
   Printf("Average collisions: %f", ht2.AverageCollisions());

   Printf("\nDelete all heap based objects");
   ht2.Delete();
}

void Test_TBtree()
{
   Printf(
   "////////////////////////////////////////////////////////////////\n"
   "// Test of TBtree                                             //\n"
   "////////////////////////////////////////////////////////////////"
   );
   TStopwatch timer;      // create a timer
   TBtree     l;          // btree of order 3

   Printf("Filling TBtree");

   TObjNumI *n3 = new TObjNumI(3);
   l.Add(n3);
   l.AddBefore(n3,new TObjNumI(5));
   l.AddAfter(n3, new TObjNumI(2));
   l.Add(new TObjNumI(1));
   l.AddBefore(n3, new TObjNumI(4));
   TObjNumI n6(6);                     // stack based TObjNumI
   l.AddFirst(&n6);

   timer.Start();
   for (int i = 0; i < 50; i++)
      l.Add(new TObjNumI(i));
   timer.Print();

   Printf("Print TBtree");
   l.Print();

   Printf("Remove 3 and print TBtree again");
   l.Remove(n3);
   l.Print();

   Printf("Iterate forward over TBtree and remove 4 from tree");
   TIter next(&l);
   TObjNumI *obj;
   while ((obj = (TObjNumI*)next()))
      if (obj->GetNum() == 4) l.Remove(obj);

   Printf("Iterate backward over TBtree and remove 2 from tree");
   TIter next1(&l, kIterBackward);
   while ((obj = (TObjNumI*)next1()))
      if (obj->GetNum() == 2) l.Remove(obj);

   Printf("\nDelete all heap based objects");
   l.Delete();

   Printf("Delete stack based objects (6)");
}

int tcollex() {
   Test_TObjArray();
   Test_TOrdCollection();
   Test_TList();
   Test_TSortedList();
   Test_THashTable();
   Test_TBtree();

   return 0;
}

#ifndef __CINT__
int main() {
   return tcollex();
}
#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: porexp.cxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-27 09:15:51 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _VIEWOPT_HXX
#include <viewopt.hxx>  // SwViewOptions
#endif
#ifndef _SW_PORTIONHANDLER_HXX
#include <SwPortionHandler.hxx>
#endif
#ifndef _INFTXT_HXX
#include <inftxt.hxx>
#endif
#ifndef _POREXP_HXX
#include <porexp.hxx>
#endif

/*************************************************************************
 *                      class SwExpandPortion
 *************************************************************************/

xub_StrLen SwExpandPortion::GetCrsrOfst( const MSHORT nOfst ) const
{ return SwLinePortion::GetCrsrOfst( nOfst ); }

/*************************************************************************
 *              virtual SwExpandPortion::GetExpTxt()
 *************************************************************************/

sal_Bool SwExpandPortion::GetExpTxt( const SwTxtSizeInfo&,
                                 XubString &rTxt ) const
{
    rTxt.Erase();
    // Nicht etwa: return 0 != rTxt.Len();
    // Weil: leere Felder ersetzen CH_TXTATR gegen einen Leerstring
    return sal_True;
}

/*************************************************************************
 *              virtual SwExpandPortion::HandlePortion()
 *************************************************************************/

void SwExpandPortion::HandlePortion( SwPortionHandler& rPH ) const
{
    String aString;
    rPH.Special( GetLen(), aString, GetWhichPor() );
}

/*************************************************************************
 *              virtual SwExpandPortion::GetTxtSize()
 *************************************************************************/

SwPosSize SwExpandPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
{
    SwTxtSlot aDiffTxt( &rInf, this, false, false );
    return rInf.GetTxtSize();
}

/*************************************************************************
 *                 virtual SwExpandPortion::Format()
 *************************************************************************/

// 5010: Exp und Tabs

sal_Bool SwExpandPortion::Format( SwTxtFormatInfo &rInf )
{
    SwTxtSlot aDiffTxt( &rInf, this, true, false );
    const xub_StrLen nFullLen = rInf.GetLen();

    // So komisch es aussieht, die Abfrage auf GetLen() muss wegen der
    // ExpandPortions _hinter_ aDiffTxt (vgl. SoftHyphs)
    // sal_False returnen wegen SetFull ...
    if( !nFullLen )
    {
        // nicht Init(), weil wir Hoehe und Ascent brauchen
        Width(0);
        return sal_False;
    }
    return SwTxtPortion::Format( rInf );
}

/*************************************************************************
 *              virtual SwExpandPortion::Paint()
 *************************************************************************/

void SwExpandPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
    SwTxtSlot aDiffTxt( &rInf, this, true, true );

    rInf.DrawBackBrush( *this );

    // do we have to repaint a post it portion?
    if( rInf.OnWin() && pPortion && !pPortion->Width() )
        pPortion->PrePaint( rInf, this );

    // The contents of field portions is not considered during the
    // calculation of the directions. Therefore we let vcl handle
    // the calculation by removing the BIDI_STRONG_FLAG temporarily.
    SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
    aLayoutModeModifier.SetAuto();

    // ST2
    if ( rInf.GetSmartTags() )
        rInf.DrawMarkedText( *this, rInf.GetLen(), sal_False, sal_False, sal_True );
    else
        rInf.DrawText( *this, rInf.GetLen(), sal_False );
}

/*************************************************************************
 *                      class SwBlankPortion
 *************************************************************************/

SwLinePortion *SwBlankPortion::Compress() { return this; }

/*************************************************************************
 *                 SwBlankPortion::MayUnderFlow()
 *************************************************************************/

// 5497: Es gibt schon Gemeinheiten auf der Welt...
// Wenn eine Zeile voll mit HardBlanks ist und diese ueberlaeuft,
// dann duerfen keine Underflows generiert werden!
// Komplikationen bei Flys...

MSHORT SwBlankPortion::MayUnderFlow( const SwTxtFormatInfo &rInf,
    xub_StrLen nIdx, sal_Bool bUnderFlow ) const
{
    if( rInf.StopUnderFlow() )
        return 0;
    const SwLinePortion *pPos = rInf.GetRoot();
    if( pPos->GetPortion() )
        pPos = pPos->GetPortion();
    while( pPos && pPos->IsBlankPortion() )
        pPos = pPos->GetPortion();
    if( !pPos || !rInf.GetIdx() || ( !pPos->GetLen() && pPos == rInf.GetRoot() ) )
        return 0; // Nur noch BlankPortions unterwegs
    // Wenn vor uns ein Blank ist, brauchen wir kein Underflow ausloesen,
    // wenn hinter uns ein Blank ist, brauchen wir kein Underflow weiterreichen
    if( bUnderFlow && CH_BLANK == rInf.GetTxt().GetChar( nIdx + 1) )
        return 0;
    if( nIdx && !((SwTxtFormatInfo&)rInf).GetFly() )
    {
        while( pPos && !pPos->IsFlyPortion() )
            pPos = pPos->GetPortion();
        if( !pPos )
        {
        //Hier wird ueberprueft, ob es in dieser Zeile noch sinnvolle Umbrueche
        //gibt, Blanks oder Felder etc., wenn nicht, kein Underflow.
        //Wenn Flys im Spiel sind, lassen wir das Underflow trotzdem zu.
            xub_StrLen nBlank = nIdx;
            while( --nBlank > rInf.GetLineStart() )
            {
                const xub_Unicode cCh = rInf.GetChar( nBlank );
                if( CH_BLANK == cCh ||
                    (( CH_TXTATR_BREAKWORD == cCh || CH_TXTATR_INWORD == cCh )
                        && rInf.HasHint( nBlank ) ) )
                    break;
            }
            if( nBlank <= rInf.GetLineStart() )
                return 0;
        }
    }
    xub_Unicode cCh;
    if( nIdx < 2 || CH_BLANK == (cCh = rInf.GetChar( nIdx - 1 )) )
        return 1;
    if( CH_BREAK == cCh )
        return 0;
    return 2;
}

/*************************************************************************
 *                 virtual SwBlankPortion::FormatEOL()
 *************************************************************************/
// Format end of Line

void SwBlankPortion::FormatEOL( SwTxtFormatInfo &rInf )
{
    MSHORT nMay = MayUnderFlow( rInf, rInf.GetIdx() - nLineLength, sal_True );
    if( nMay )
    {
        if( nMay > 1 )
        {
            if( rInf.GetLast() == this )
               rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
            rInf.X( rInf.X() - PrtWidth() );
            rInf.SetIdx( rInf.GetIdx() - GetLen() );
        }
        Truncate();
        rInf.SetUnderFlow( this );
        if( rInf.GetLast()->IsKernPortion() )
            rInf.SetUnderFlow( rInf.GetLast() );
    }
}

/*************************************************************************
 *                 virtual SwBlankPortion::Format()
 *************************************************************************/

// 7771: UnderFlows weiterreichen und selbst ausloesen!
sal_Bool SwBlankPortion::Format( SwTxtFormatInfo &rInf )
{
    const sal_Bool bFull = rInf.IsUnderFlow() || SwExpandPortion::Format( rInf );
    if( bFull && MayUnderFlow( rInf, rInf.GetIdx(), rInf.IsUnderFlow() ) )
    {
        Truncate();
        rInf.SetUnderFlow( this );
        if( rInf.GetLast()->IsKernPortion() )
            rInf.SetUnderFlow( rInf.GetLast() );
    }
    return bFull;
}

/*************************************************************************
 *                 virtual SwBlankPortion::Paint()
 *************************************************************************/

void SwBlankPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
    if( !bMulti ) // No gray background for multiportion brackets
        rInf.DrawViewOpt( *this, POR_BLANK );
    SwExpandPortion::Paint( rInf );
}

/*************************************************************************
 *              virtual SwBlankPortion::GetExpTxt()
 *************************************************************************/

sal_Bool SwBlankPortion::GetExpTxt( const SwTxtSizeInfo&, XubString &rTxt ) const
{
    rTxt = cChar;
    return sal_True;
}

/*************************************************************************
 *              virtual SwBlankPortion::HandlePortion()
 *************************************************************************/

void SwBlankPortion::HandlePortion( SwPortionHandler& rPH ) const
{
    String aString( cChar );
    rPH.Special( GetLen(), aString, GetWhichPor() );
}

/*************************************************************************
 *                      class SwPostItsPortion
 *************************************************************************/

SwPostItsPortion::SwPostItsPortion( sal_Bool bScrpt )
    : nViewWidth(0), bScript( bScrpt )
{
    nLineLength = 1;
    SetWhichPor( POR_POSTITS );
}

void SwPostItsPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
    if( rInf.OnWin() && Width() )
        rInf.DrawPostIts( *this, IsScript() );
}

KSHORT SwPostItsPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
{
    // Nicht zu fassen: PostIts sind immer zu sehen.
    return rInf.OnWin() ?
                (KSHORT)rInf.GetOpt().GetPostItsWidth( rInf.GetOut() ) : 0;
}

/*************************************************************************
 *                 virtual SwPostItsPortion::Format()
 *************************************************************************/

sal_Bool SwPostItsPortion::Format( SwTxtFormatInfo &rInf )
{
    sal_Bool bRet = SwLinePortion::Format( rInf );
    // 32749: PostIts sollen keine Auswirkung auf Zeilenhoehe etc. haben
    SetAscent( 1 );
    Height( 1 );
    return bRet;
}

/*************************************************************************
 *              virtual SwPostItsPortion::GetExpTxt()
 *************************************************************************/

sal_Bool SwPostItsPortion::GetExpTxt( const SwTxtSizeInfo &rInf,
                                  XubString &rTxt ) const
{
    if( rInf.OnWin() && rInf.GetOpt().IsPostIts() )
        rTxt = ' ';
    else
        rTxt.Erase();
    return sal_True;
}

<commit_msg>INTEGRATION: CWS gcframework_DEV300 (1.15.268); FILE MERGED 2008/01/08 10:05:02 tl 1.15.268.2: RESYNC: (1.15-1.16); FILE MERGED 2007/11/26 09:14:32 tl 1.15.268.1: #i83776# get SwXTextMarkup::commitTextMarkup working<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: porexp.cxx,v $
 *
 *  $Revision: 1.17 $
 *
 *  last change: $Author: obo $ $Date: 2008-02-26 09:46:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _VIEWOPT_HXX
#include <viewopt.hxx>  // SwViewOptions
#endif
#ifndef _SW_PORTIONHANDLER_HXX
#include <SwPortionHandler.hxx>
#endif
#ifndef _INFTXT_HXX
#include <inftxt.hxx>
#endif
#ifndef _POREXP_HXX
#include <porexp.hxx>
#endif

/*************************************************************************
 *                      class SwExpandPortion
 *************************************************************************/

xub_StrLen SwExpandPortion::GetCrsrOfst( const MSHORT nOfst ) const
{ return SwLinePortion::GetCrsrOfst( nOfst ); }

/*************************************************************************
 *              virtual SwExpandPortion::GetExpTxt()
 *************************************************************************/

sal_Bool SwExpandPortion::GetExpTxt( const SwTxtSizeInfo&,
                                 XubString &rTxt ) const
{
    rTxt.Erase();
    // Nicht etwa: return 0 != rTxt.Len();
    // Weil: leere Felder ersetzen CH_TXTATR gegen einen Leerstring
    return sal_True;
}

/*************************************************************************
 *              virtual SwExpandPortion::HandlePortion()
 *************************************************************************/

void SwExpandPortion::HandlePortion( SwPortionHandler& rPH ) const
{
    String aString;
    rPH.Special( GetLen(), aString, GetWhichPor() );
}

/*************************************************************************
 *              virtual SwExpandPortion::GetTxtSize()
 *************************************************************************/

SwPosSize SwExpandPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
{
    SwTxtSlot aDiffTxt( &rInf, this, false, false );
    return rInf.GetTxtSize();
}

/*************************************************************************
 *                 virtual SwExpandPortion::Format()
 *************************************************************************/

// 5010: Exp und Tabs

sal_Bool SwExpandPortion::Format( SwTxtFormatInfo &rInf )
{
    SwTxtSlot aDiffTxt( &rInf, this, true, false );
    const xub_StrLen nFullLen = rInf.GetLen();

    // So komisch es aussieht, die Abfrage auf GetLen() muss wegen der
    // ExpandPortions _hinter_ aDiffTxt (vgl. SoftHyphs)
    // sal_False returnen wegen SetFull ...
    if( !nFullLen )
    {
        // nicht Init(), weil wir Hoehe und Ascent brauchen
        Width(0);
        return sal_False;
    }
    return SwTxtPortion::Format( rInf );
}

/*************************************************************************
 *              virtual SwExpandPortion::Paint()
 *************************************************************************/

void SwExpandPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
    SwTxtSlot aDiffTxt( &rInf, this, true, true );

    rInf.DrawBackBrush( *this );

    // do we have to repaint a post it portion?
    if( rInf.OnWin() && pPortion && !pPortion->Width() )
        pPortion->PrePaint( rInf, this );

    // The contents of field portions is not considered during the
    // calculation of the directions. Therefore we let vcl handle
    // the calculation by removing the BIDI_STRONG_FLAG temporarily.
    SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
    aLayoutModeModifier.SetAuto();

    // ST2
    if ( rInf.GetSmartTags() )
        rInf.DrawMarkedText( *this, rInf.GetLen(), sal_False, sal_False, sal_True, sal_False );
    else
        rInf.DrawText( *this, rInf.GetLen(), sal_False );
}

/*************************************************************************
 *                      class SwBlankPortion
 *************************************************************************/

SwLinePortion *SwBlankPortion::Compress() { return this; }

/*************************************************************************
 *                 SwBlankPortion::MayUnderFlow()
 *************************************************************************/

// 5497: Es gibt schon Gemeinheiten auf der Welt...
// Wenn eine Zeile voll mit HardBlanks ist und diese ueberlaeuft,
// dann duerfen keine Underflows generiert werden!
// Komplikationen bei Flys...

MSHORT SwBlankPortion::MayUnderFlow( const SwTxtFormatInfo &rInf,
    xub_StrLen nIdx, sal_Bool bUnderFlow ) const
{
    if( rInf.StopUnderFlow() )
        return 0;
    const SwLinePortion *pPos = rInf.GetRoot();
    if( pPos->GetPortion() )
        pPos = pPos->GetPortion();
    while( pPos && pPos->IsBlankPortion() )
        pPos = pPos->GetPortion();
    if( !pPos || !rInf.GetIdx() || ( !pPos->GetLen() && pPos == rInf.GetRoot() ) )
        return 0; // Nur noch BlankPortions unterwegs
    // Wenn vor uns ein Blank ist, brauchen wir kein Underflow ausloesen,
    // wenn hinter uns ein Blank ist, brauchen wir kein Underflow weiterreichen
    if( bUnderFlow && CH_BLANK == rInf.GetTxt().GetChar( nIdx + 1) )
        return 0;
    if( nIdx && !((SwTxtFormatInfo&)rInf).GetFly() )
    {
        while( pPos && !pPos->IsFlyPortion() )
            pPos = pPos->GetPortion();
        if( !pPos )
        {
        //Hier wird ueberprueft, ob es in dieser Zeile noch sinnvolle Umbrueche
        //gibt, Blanks oder Felder etc., wenn nicht, kein Underflow.
        //Wenn Flys im Spiel sind, lassen wir das Underflow trotzdem zu.
            xub_StrLen nBlank = nIdx;
            while( --nBlank > rInf.GetLineStart() )
            {
                const xub_Unicode cCh = rInf.GetChar( nBlank );
                if( CH_BLANK == cCh ||
                    (( CH_TXTATR_BREAKWORD == cCh || CH_TXTATR_INWORD == cCh )
                        && rInf.HasHint( nBlank ) ) )
                    break;
            }
            if( nBlank <= rInf.GetLineStart() )
                return 0;
        }
    }
    xub_Unicode cCh;
    if( nIdx < 2 || CH_BLANK == (cCh = rInf.GetChar( nIdx - 1 )) )
        return 1;
    if( CH_BREAK == cCh )
        return 0;
    return 2;
}

/*************************************************************************
 *                 virtual SwBlankPortion::FormatEOL()
 *************************************************************************/
// Format end of Line

void SwBlankPortion::FormatEOL( SwTxtFormatInfo &rInf )
{
    MSHORT nMay = MayUnderFlow( rInf, rInf.GetIdx() - nLineLength, sal_True );
    if( nMay )
    {
        if( nMay > 1 )
        {
            if( rInf.GetLast() == this )
               rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
            rInf.X( rInf.X() - PrtWidth() );
            rInf.SetIdx( rInf.GetIdx() - GetLen() );
        }
        Truncate();
        rInf.SetUnderFlow( this );
        if( rInf.GetLast()->IsKernPortion() )
            rInf.SetUnderFlow( rInf.GetLast() );
    }
}

/*************************************************************************
 *                 virtual SwBlankPortion::Format()
 *************************************************************************/

// 7771: UnderFlows weiterreichen und selbst ausloesen!
sal_Bool SwBlankPortion::Format( SwTxtFormatInfo &rInf )
{
    const sal_Bool bFull = rInf.IsUnderFlow() || SwExpandPortion::Format( rInf );
    if( bFull && MayUnderFlow( rInf, rInf.GetIdx(), rInf.IsUnderFlow() ) )
    {
        Truncate();
        rInf.SetUnderFlow( this );
        if( rInf.GetLast()->IsKernPortion() )
            rInf.SetUnderFlow( rInf.GetLast() );
    }
    return bFull;
}

/*************************************************************************
 *                 virtual SwBlankPortion::Paint()
 *************************************************************************/

void SwBlankPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
    if( !bMulti ) // No gray background for multiportion brackets
        rInf.DrawViewOpt( *this, POR_BLANK );
    SwExpandPortion::Paint( rInf );
}

/*************************************************************************
 *              virtual SwBlankPortion::GetExpTxt()
 *************************************************************************/

sal_Bool SwBlankPortion::GetExpTxt( const SwTxtSizeInfo&, XubString &rTxt ) const
{
    rTxt = cChar;
    return sal_True;
}

/*************************************************************************
 *              virtual SwBlankPortion::HandlePortion()
 *************************************************************************/

void SwBlankPortion::HandlePortion( SwPortionHandler& rPH ) const
{
    String aString( cChar );
    rPH.Special( GetLen(), aString, GetWhichPor() );
}

/*************************************************************************
 *                      class SwPostItsPortion
 *************************************************************************/

SwPostItsPortion::SwPostItsPortion( sal_Bool bScrpt )
    : nViewWidth(0), bScript( bScrpt )
{
    nLineLength = 1;
    SetWhichPor( POR_POSTITS );
}

void SwPostItsPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
    if( rInf.OnWin() && Width() )
        rInf.DrawPostIts( *this, IsScript() );
}

KSHORT SwPostItsPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
{
    // Nicht zu fassen: PostIts sind immer zu sehen.
    return rInf.OnWin() ?
                (KSHORT)rInf.GetOpt().GetPostItsWidth( rInf.GetOut() ) : 0;
}

/*************************************************************************
 *                 virtual SwPostItsPortion::Format()
 *************************************************************************/

sal_Bool SwPostItsPortion::Format( SwTxtFormatInfo &rInf )
{
    sal_Bool bRet = SwLinePortion::Format( rInf );
    // 32749: PostIts sollen keine Auswirkung auf Zeilenhoehe etc. haben
    SetAscent( 1 );
    Height( 1 );
    return bRet;
}

/*************************************************************************
 *              virtual SwPostItsPortion::GetExpTxt()
 *************************************************************************/

sal_Bool SwPostItsPortion::GetExpTxt( const SwTxtSizeInfo &rInf,
                                  XubString &rTxt ) const
{
    if( rInf.OnWin() && rInf.GetOpt().IsPostIts() )
        rTxt = ' ';
    else
        rTxt.Erase();
    return sal_True;
}

<|endoftext|>


<commit_before>#include "Shader.h"

using namespace ENGINE;

Shader::Shader(const std::string path)
{
	std::string vertContent = FileSystem::LoadFile(path + ".vert");
	std::string fragContent = FileSystem::LoadFile(path + ".frag");

	//create shaders
	GLuint vertexID = makeShaderFromSource(vertContent, GL_VERTEX_SHADER);
	GLuint fragID = makeShaderFromSource(fragContent, GL_FRAGMENT_SHADER);

	//make combined shader program
	//link program
	programID = glCreateProgram();
	glAttachShader(programID, vertexID);
	glAttachShader(programID, fragID);
	glLinkProgram(programID);

	GLint Result = GL_FALSE;
	int infoLogLength;
	//check if program is valid
	glGetProgramiv(programID, GL_LINK_STATUS, &Result);
	glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
	if (infoLogLength > 1) {
		//we could not bundle the two shaders
		std::vector<char> programErrorMessage(infoLogLength + 1);
		glGetProgramInfoLog(programID, infoLogLength, NULL, &programErrorMessage[0]);
		printf("Shader link failed. \n %s \n", &programErrorMessage[0]);
		std::cerr << "Shader link failed. TODO: Handle Event." << std::endl;
	}

	//Detach Shaders
	glDetachShader(programID, vertexID);
	glDetachShader(programID, fragID);

	//Delete shaders since program is enough information
	glDeleteShader(vertexID);
	glDeleteShader(fragID);

	//register uniforms
	RegisterAllUniforms(vertContent);
	RegisterAllUniforms(fragContent);

}

Shader::~Shader()
{
	//delete shader program
	glDeleteProgram(programID);
}

void Shader::_bind()
{
	//Start using the shader program
	glUseProgram(programID);
}

void Shader::_unbind()
{
	//stop using shader program
	glUseProgram(0);
}

void Shader::RegisterAllUniforms(std::string shaderSource)
{
	//search for "unifrom" in source code
	std::string buf;
	std::stringstream ss(shaderSource);

	while (ss >> buf) { //read word by word (and remove new line character)
		if (buf == "uniform") {
			if (ss >> buf) {	//read type of unifom
				if (ss >> buf) {	//read name of uniform
					RegUniform(buf);	//register uniform with that name
				}
			}
		}
	}
}

void Shader::RegUniform(const std::string name)
{
	std::map<const std::string, GLint>::iterator it = uniforms.find(name.c_str());

	if (it == uniforms.end()) {
		GLint id = glGetUniformLocation(programID, name.c_str());
		uniforms.insert(std::make_pair(name.c_str(), id));
	}
}

void Shader::RegUniformArray(const std::string name)
{
	//TODO
}

GLint Shader::getUniform(std::string name)
{
	std::map<const std::string, GLint>::iterator it = uniforms.find(name.c_str());
	return it->second;
}

GLuint Shader::makeShaderFromSource(std::string source, GLuint shaderType)
{
	GLuint shaderID = glCreateShader(shaderType);;
	const char * sourcePointer = source.c_str();

	glShaderSource(shaderID, 1, &sourcePointer, NULL);
	glCompileShader(shaderID);

	//Check for errors
	GLint result = GL_FALSE;
	int infoLogLength;
	glGetShaderiv(shaderID, GL_COMPILE_STATUS, &result);
	glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &infoLogLength);

	if (infoLogLength > 1) {
		//the shader did not compile...
		std::vector<char> vertexShaderErrorMessage(infoLogLength + 1);
		glGetShaderInfoLog(shaderID, infoLogLength, NULL, &vertexShaderErrorMessage[0]);
		printf("Shader Compile Error: \n %s\n", &vertexShaderErrorMessage[0]);

		//Error handling..
		std::cerr << "Error was detected..." << std::endl;
	}
	return shaderID;
}
<commit_msg>Found a problem where a uniform name contained a semicolon at the end. Fixed this problem.<commit_after>#include "Shader.h"

using namespace ENGINE;

Shader::Shader(const std::string path)
{
	std::string vertContent = FileSystem::LoadFile(path + ".vert");
	std::string fragContent = FileSystem::LoadFile(path + ".frag");

	//create shaders
	GLuint vertexID = makeShaderFromSource(vertContent, GL_VERTEX_SHADER);
	GLuint fragID = makeShaderFromSource(fragContent, GL_FRAGMENT_SHADER);

	//make combined shader program
	//link program
	programID = glCreateProgram();
	glAttachShader(programID, vertexID);
	glAttachShader(programID, fragID);
	glLinkProgram(programID);

	GLint Result = GL_FALSE;
	int infoLogLength;
	//check if program is valid
	glGetProgramiv(programID, GL_LINK_STATUS, &Result);
	glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
	if (infoLogLength > 1) {
		//we could not bundle the two shaders
		std::vector<char> programErrorMessage(infoLogLength + 1);
		glGetProgramInfoLog(programID, infoLogLength, NULL, &programErrorMessage[0]);
		printf("Shader link failed. \n %s \n", &programErrorMessage[0]);
		std::cerr << "Shader link failed. TODO: Handle Event." << std::endl;
	}

	//Detach Shaders
	glDetachShader(programID, vertexID);
	glDetachShader(programID, fragID);

	//Delete shaders since program is enough information
	glDeleteShader(vertexID);
	glDeleteShader(fragID);

	//register uniforms
	RegisterAllUniforms(vertContent);
	RegisterAllUniforms(fragContent);

}

Shader::~Shader()
{
	//delete shader program
	glDeleteProgram(programID);
}

void Shader::_bind()
{
	//Start using the shader program
	glUseProgram(programID);
}

void Shader::_unbind()
{
	//stop using shader program
	glUseProgram(0);
}

void Shader::RegisterAllUniforms(std::string shaderSource)
{
	//search for "unifrom" in source code
	std::string buf;
	std::stringstream ss(shaderSource);

	while (ss >> buf) { //read word by word (and remove new line character)
		if (buf == "uniform") {
			if (ss >> buf) {	//read type of unifom
				if (ss >> buf) {	//read name of uniform
					//TODO check if string contains ";"
					if (buf.find(';') >= 0)
						RegUniform(buf.substr(0,buf.size()-1));	//register uniform with that name (remove ";")
					else
						RegUniform(buf);	//register uniform with that name

				}
			}
		}
	}
}

void Shader::RegUniform(const std::string name)
{
	std::map<const std::string, GLint>::iterator it = uniforms.find(name.c_str());

	if (it == uniforms.end()) {
		GLint id = glGetUniformLocation(programID, name.c_str());
		uniforms.insert(std::make_pair(name.c_str(), id));
	}
}

void Shader::RegUniformArray(const std::string name)
{
	//TODO
}

GLint Shader::getUniform(std::string name)
{
	std::map<const std::string, GLint>::iterator it = uniforms.find(name.c_str());
	return it->second;
}

GLuint Shader::makeShaderFromSource(std::string source, GLuint shaderType)
{
	GLuint shaderID = glCreateShader(shaderType);;
	const char * sourcePointer = source.c_str();

	glShaderSource(shaderID, 1, &sourcePointer, NULL);
	glCompileShader(shaderID);

	//Check for errors
	GLint result = GL_FALSE;
	int infoLogLength;
	glGetShaderiv(shaderID, GL_COMPILE_STATUS, &result);
	glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &infoLogLength);

	if (infoLogLength > 1) {
		//the shader did not compile...
		std::vector<char> vertexShaderErrorMessage(infoLogLength + 1);
		glGetShaderInfoLog(shaderID, infoLogLength, NULL, &vertexShaderErrorMessage[0]);
		printf("Shader Compile Error: \n %s\n", &vertexShaderErrorMessage[0]);

		//Error handling..
		std::cerr << "Error was detected..." << std::endl;
	}
	return shaderID;
}
<|endoftext|>


<commit_before>#include <lemon/lgf_writer.h>
#include <cassert>
#include <vector>
#include <unordered_set>
#include <map>
#include <algorithm>
#include <iomanip>
#include "lib/parse_trace.h"
#include <limits>

using namespace lemon;

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

    if (argc != 2) {
        std::cerr << argv[0] << " traceFile" << std::endl;
        return 1;
    }

    std::cerr << "starting..\n";

    std::string path(argv[1]);

    // parse trace file
    std::vector<trEntry> trace;
    uint64_t uniqCount;
    uint64_t totalReqc = parseTraceFile(trace, path, uniqCount);
    std::cerr << "scanned trace n=" << totalReqc << std::endl;

    // ordered list of utilities
    std::vector<utilEntry> utils;
    std::cerr << "reserving " <<  trace.size() - uniqCount << " " << trace.size() << " " << uniqCount << "\n";
    utils.reserve(trace.size() - uniqCount);
    for(size_t i=0; i<trace.size(); i++) {
        const trEntry & cur = trace[i];
        if(cur.nextSeen > 0) {
            // calculate utility
            const double intervalLength = cur.nextSeen - i;
            const double utilityDenominator = cur.size*intervalLength;
            if(utilityDenominator<=0) {
                std::cerr << "fail " << cur.size << " ns " << cur.nextSeen << " " << i << " " << utilityDenominator << " " << intervalLength << "\n";
            }
            assert(utilityDenominator>0);
            utils.emplace_back(1.0L/utilityDenominator, i);
        }
    }
    std::sort(utils.begin(), utils.end());
    std::cerr << "ordered " << utils.size() << " utilities\n";

    // create used-up capacity mask
    int64_t * usedcap = new int64_t[trace.size()];
#pragma omp simd
    for(size_t i=0; i<trace.size(); i++) {
        usedcap[i] = 0;
    }

    std::unordered_set<size_t> cached;
    uint64_t counter = 0;

    for(int64_t cs=1; cached.size() != trace.size(); cs = cs * 2) {

        // safe guard
        if(cs > std::numeric_limits<int64_t>::max()/2) {
            break;
        }

        std::cerr << cs;
        for (auto it = utils.rbegin(); it != utils.rend(); it++) {

            if(cached.count(it->index)>0) {
                continue; // already cached
            }

            const trEntry & cur = trace[it->index];
            const auto s = cur.size;
            if(s > cs) {
                continue; // skip if too large to store at the moment
            }

            bool checkedAnything = false;
            for(size_t i = it->index; i<cur.nextSeen; i++) {
                checkedAnything = true;
                if(usedcap[i] + s > cs) {
                    continue; // skip
                }
            }

            if(!checkedAnything) {
                std::cerr << "\n nothing checked " << it->index << " " << cur.nextSeen << std::endl;
            }

            // reaching here means we space to store the object
#pragma omp simd
            for(size_t i = it->index; i<cur.nextSeen; i++) {
                usedcap[i] += s;
            }
            cached.insert(it->index);

            if(counter++ > 10000) {
                std::cerr << ".";
                counter = 0;
            }

        }
        std::cerr << std::endl;
        counter = 0;
        std::cout << "lboundfastc " + std::to_string(cs) + " " + std::to_string(cached.size()) + " " + std::to_string(totalReqc) +  " " + std::to_string((double)(cached.size())/totalReqc) + "\n";
    }

    return 0;
}
<commit_msg>bug fix in lboundfastcomplete<commit_after>#include <lemon/lgf_writer.h>
#include <cassert>
#include <vector>
#include <unordered_set>
#include <map>
#include <algorithm>
#include <iomanip>
#include "lib/parse_trace.h"
#include <limits>

using namespace lemon;

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

    if (argc != 2) {
        std::cerr << argv[0] << " traceFile" << std::endl;
        return 1;
    }

    std::cerr << "starting..\n";

    std::string path(argv[1]);

    // parse trace file
    std::vector<trEntry> trace;
    uint64_t uniqCount = 0;
    uint64_t totalReqc = parseTraceFile(trace, path, uniqCount);
    std::cerr << "scanned trace n=" << totalReqc << std::endl;

    // ordered list of utilities
    std::vector<utilEntry> utils;
    std::cerr << "reserving " <<  trace.size() - uniqCount << " " << trace.size() << " " << uniqCount << "\n";
    utils.reserve(trace.size() - uniqCount);
    for(size_t i=0; i<trace.size(); i++) {
        const trEntry & cur = trace[i];
        if(cur.nextSeen > 0) {
            // calculate utility
            const double intervalLength = cur.nextSeen - i;
            const double utilityDenominator = cur.size*intervalLength;
            if(utilityDenominator<=0) {
                std::cerr << "fail " << cur.size << " ns " << cur.nextSeen << " " << i << " " << utilityDenominator << " " << intervalLength << "\n";
            }
            assert(utilityDenominator>0);
            utils.emplace_back(1.0L/utilityDenominator, i);
        }
    }
    std::sort(utils.begin(), utils.end());
    std::cerr << "ordered " << utils.size() << " utilities\n";

    // create used-up capacity mask
    int64_t * usedcap = new int64_t[trace.size()];
#pragma omp simd
    for(size_t i=0; i<trace.size(); i++) {
        usedcap[i] = 0;
    }

    std::unordered_set<size_t> cached;
    uint64_t counter = 0;

    for(int64_t cs=1; cached.size() != trace.size()-uniqCount; cs = cs * 2) {

        // safe guard
        if(cs > std::numeric_limits<int64_t>::max()/2) {
            break;
        }

        std::cerr << cs;
        for (auto it = utils.rbegin(); it != utils.rend(); it++) {

            if(cached.count(it->index)>0) {
                continue; // already cached
            }

            const trEntry & cur = trace[it->index];
            const auto s = cur.size;
            if(s > cs) {
                continue; // skip if too large to store at the moment
            }

            bool cacheThis = true;
            for(size_t i = it->index; i<cur.nextSeen; i++) {
                if(usedcap[i] + s > cs) {
                    cacheThis = false;
                    break;
                }
            }

            if(cacheThis) {
#pragma omp simd
                for(size_t i = it->index; i<cur.nextSeen; i++) {
                    usedcap[i] += s;
                }
                cached.insert(it->index);
            }

            if(counter++ > 10000) {
                std::cerr << ".";
                counter = 0;
            }

        }

        std::cerr << std::endl;
        counter = 0;
        std::cout << "lboundfastc " + std::to_string(cs) + " " + std::to_string(cached.size()) + " " + std::to_string(totalReqc) +  " " + std::to_string((double)(cached.size())/totalReqc) + "\n";
    }

    return 0;
}
<|endoftext|>


<commit_before><commit_msg>:new: validate binary search tree<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS dxliberate01 (1.1.2); FILE ADDED 2007/07/23 12:05:05 thb 1.1.2.1: #i48454# dxcanvas is now part of OOo<commit_after><|endoftext|>


<commit_before><commit_msg>gtk_message_dialog_new expects a format string already.<commit_after><|endoftext|>