<commit_before>#include <catch2/catch.hpp>

#include "types.hpp"
#include <set>

TEST_CASE("momentary_switch_event") {
  {
    krbn::momentary_switch_event e(krbn::key_code::keyboard_a);
    REQUIRE(e.make_modifier_flag() == std::nullopt);
    REQUIRE(e.modifier_flag() == false);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::key_code::keyboard_left_shift);
    REQUIRE(e.make_modifier_flag() == krbn::modifier_flag::left_shift);
    REQUIRE(e.modifier_flag() == true);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::consumer_key_code::mute);
    REQUIRE(e.make_modifier_flag() == std::nullopt);
    REQUIRE(e.modifier_flag() == false);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::apple_vendor_keyboard_key_code::expose_all);
    REQUIRE(e.make_modifier_flag() == std::nullopt);
    REQUIRE(e.modifier_flag() == false);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::apple_vendor_keyboard_key_code::function);
    REQUIRE(e.make_modifier_flag() == krbn::modifier_flag::fn);
    REQUIRE(e.modifier_flag() == true);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::apple_vendor_top_case_key_code::brightness_down);
    REQUIRE(e.make_modifier_flag() == std::nullopt);
    REQUIRE(e.modifier_flag() == false);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::apple_vendor_top_case_key_code::keyboard_fn);
    REQUIRE(e.make_modifier_flag() == krbn::modifier_flag::fn);
    REQUIRE(e.modifier_flag() == true);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::pointing_button::button1);
    REQUIRE(e.make_modifier_flag() == std::nullopt);
    REQUIRE(e.modifier_flag() == false);
    REQUIRE(e.pointing_button() == true);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    std::set<krbn::momentary_switch_event> map;
    map.insert(krbn::momentary_switch_event(krbn::consumer_key_code::mute));
    map.insert(krbn::momentary_switch_event(krbn::key_code::keyboard_b));
    map.insert(krbn::momentary_switch_event(krbn::key_code::keyboard_a));
    map.insert(krbn::momentary_switch_event(krbn::key_code::keyboard_c));
    map.insert(krbn::momentary_switch_event(krbn::pointing_button::button2));
    map.insert(krbn::momentary_switch_event(krbn::pointing_button::button1));

    int i = 0;
    for (const auto& m : map) {
      switch (i++) {
        case 0:
          REQUIRE(m == krbn::momentary_switch_event(krbn::key_code::keyboard_a));
          break;
        case 1:
          REQUIRE(m == krbn::momentary_switch_event(krbn::key_code::keyboard_b));
          break;
        case 2:
          REQUIRE(m == krbn::momentary_switch_event(krbn::key_code::keyboard_c));
          break;
        case 3:
          REQUIRE(m == krbn::momentary_switch_event(krbn::consumer_key_code::mute));
          break;
        case 4:
          REQUIRE(m == krbn::momentary_switch_event(krbn::pointing_button::button1));
          break;
        case 5:
          REQUIRE(m == krbn::momentary_switch_event(krbn::pointing_button::button2));
          break;
      }
    }
  }
}
<commit_msg>Update tests<commit_after>#include <catch2/catch.hpp>

#include "types.hpp"
#include <set>

TEST_CASE("momentary_switch_event") {
  {
    krbn::momentary_switch_event e(krbn::key_code::keyboard_a);
    REQUIRE(e.make_modifier_flag() == std::nullopt);
    REQUIRE(e.modifier_flag() == false);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::key_code::keyboard_left_shift);
    REQUIRE(e.make_modifier_flag() == krbn::modifier_flag::left_shift);
    REQUIRE(e.modifier_flag() == true);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::consumer_key_code::mute);
    REQUIRE(e.make_modifier_flag() == std::nullopt);
    REQUIRE(e.modifier_flag() == false);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::apple_vendor_keyboard_key_code::expose_all);
    REQUIRE(e.make_modifier_flag() == std::nullopt);
    REQUIRE(e.modifier_flag() == false);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::apple_vendor_keyboard_key_code::function);
    REQUIRE(e.make_modifier_flag() == krbn::modifier_flag::fn);
    REQUIRE(e.modifier_flag() == true);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::apple_vendor_top_case_key_code::brightness_down);
    REQUIRE(e.make_modifier_flag() == std::nullopt);
    REQUIRE(e.modifier_flag() == false);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::apple_vendor_top_case_key_code::keyboard_fn);
    REQUIRE(e.make_modifier_flag() == krbn::modifier_flag::fn);
    REQUIRE(e.modifier_flag() == true);
    REQUIRE(e.pointing_button() == false);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    krbn::momentary_switch_event e(krbn::pointing_button::button1);
    REQUIRE(e.make_modifier_flag() == std::nullopt);
    REQUIRE(e.modifier_flag() == false);
    REQUIRE(e.pointing_button() == true);
    REQUIRE(nlohmann::json(e).get<krbn::momentary_switch_event>() == e);
  }
  {
    std::set<krbn::momentary_switch_event> map;
    map.insert(krbn::momentary_switch_event(krbn::consumer_key_code::mute));
    map.insert(krbn::momentary_switch_event(krbn::key_code::keyboard_b));
    map.insert(krbn::momentary_switch_event(krbn::key_code::keyboard_a));
    map.insert(krbn::momentary_switch_event(krbn::key_code::keyboard_c));
    map.insert(krbn::momentary_switch_event(krbn::pointing_button::button2));
    map.insert(krbn::momentary_switch_event(krbn::pointing_button::button1));

    int i = 0;
    for (const auto& m : map) {
      switch (i++) {
        case 0:
          REQUIRE(m == krbn::momentary_switch_event(krbn::key_code::keyboard_a));
          break;
        case 1:
          REQUIRE(m == krbn::momentary_switch_event(krbn::key_code::keyboard_b));
          break;
        case 2:
          REQUIRE(m == krbn::momentary_switch_event(krbn::key_code::keyboard_c));
          break;
        case 3:
          REQUIRE(m == krbn::momentary_switch_event(krbn::consumer_key_code::mute));
          break;
        case 4:
          REQUIRE(m == krbn::momentary_switch_event(krbn::pointing_button::button1));
          break;
        case 5:
          REQUIRE(m == krbn::momentary_switch_event(krbn::pointing_button::button2));
          break;
      }
    }
  }
}

TEST_CASE("momentary_switch_event json") {
  {
    std::string expected("{\"pointing_button\":\"button1\"}");
    nlohmann::json actual = krbn::momentary_switch_event(pqrs::hid::usage_page::button, pqrs::hid::usage::button::button_1);
    REQUIRE(actual.dump() == expected);
  }
  {
    std::string expected("{\"pointing_button\":\"(number:1234)\"}");
    nlohmann::json actual = krbn::momentary_switch_event(pqrs::hid::usage_page::button, pqrs::hid::usage::value_t(1234));
    REQUIRE(actual.dump() == expected);
  }
}
<|endoftext|>


<commit_before>#ifndef _DATA_TYPES
#define _DATA_TYPES

#include <iostream>

struct dimension {
  dimension(void);
  dimension(unsigned int w, unsigned int h);
  unsigned int width, height;
};

struct position {
  position(void);
  position(int x, int y);
  int x, y;
};

struct rectangle {
  rectangle(void);
  rectangle(position pos, dimension dim);
  rectangle(int x, int y, unsigned int width, unsigned int height);

  int & x(void);
  int const & x(void) const;
  int & y(void);
  int const & y(void) const;
  unsigned int & width(void);
  unsigned int const & width(void) const;
  unsigned int & height(void);
  unsigned int const & height(void) const;

  position _position;
  dimension _dimension;
};

std::ostream & operator<<(std::ostream & os, const rectangle & rect);

#endif
<commit_msg>Data types for xft cpp adapter<commit_after>#ifndef _DATA_TYPES
#define _DATA_TYPES

#include <iostream>

struct dimension {
  dimension(void);
  dimension(unsigned int w, unsigned int h);
  unsigned int width, height;
};

struct position {
  position(void);
  position(int x, int y);
  int x, y;
};

struct rectangle {
  rectangle(void);
  rectangle(position pos, dimension dim);
  rectangle(int x, int y, unsigned int width, unsigned int height);

  int & x(void);
  int const & x(void) const;
  int & y(void);
  int const & y(void) const;
  unsigned int & width(void);
  unsigned int const & width(void) const;
  unsigned int & height(void);
  unsigned int const & height(void) const;

  position _position;
  dimension _dimension;
};

std::ostream & operator<<(std::ostream & os, const rectangle & rect);

namespace x {

namespace type {

namespace generic {

class name {
  public:
    name(const std::string & name) : m_name(name) {}
    std::string & operator*(void) { return m_name; }
    const std::string & operator*(void) const { return m_name; }
    std::string * const operator->(void) { return &m_name; }
    const std::string * const operator->(void) const { return &m_name; }
  private:
    std::string m_name;
}; // class name

}; // namespace generic

class colorname : public generic::name {
  using generic::name::name;
};

class fontname : public generic::name {
  using generic::name::name;
};

}; // namespace type

}; // namespace x

#endif
<|endoftext|>


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

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

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QBigInt.cpp
 * @author Yann yann@ethdev.com
 * @date 2015
 */

#include <boost/variant/multivisitors.hpp>
#include <boost/variant.hpp>
#include <libethcore/CommonJS.h>
#include "QBigInt.h"

using namespace dev;
using namespace dev::mix;

QString QBigInt::value() const
{
	std::ostringstream s;
	s << m_internalValue;
	return QString::fromStdString(s.str());
}

QBigInt* QBigInt::subtract(QBigInt* const& _value) const
{
	BigIntVariant toSubtract = _value->internalValue();
	return new QBigInt(boost::apply_visitor(mix::subtract(), m_internalValue, toSubtract));
}

QBigInt* QBigInt::add(QBigInt* const& _value) const
{
	BigIntVariant toAdd = _value->internalValue();
	return new QBigInt(boost::apply_visitor(mix::add(), m_internalValue, toAdd));
}

QBigInt* QBigInt::multiply(QBigInt* const& _value) const
{
	BigIntVariant toMultiply = _value->internalValue();
	return new QBigInt(boost::apply_visitor(mix::multiply(), m_internalValue, toMultiply));
}

QBigInt* QBigInt::divide(QBigInt* const& _value) const
{
	BigIntVariant toDivide = _value->internalValue();
	return new QBigInt(boost::apply_visitor(mix::divide(), m_internalValue, toDivide));
}

QVariantMap QBigInt::checkAgainst(QString const& _type) const
{
	QVariantMap ret;
	QString type = _type;
	QString capacity = type.replace("uint", "").replace("int", "");
	if (capacity.isEmpty())
		capacity = "256";
	bigint range = 256^(capacity.toInt() / 8);
	bigint value = boost::get<bigint>(this->internalValue());
	ret.insert("valid", true);
	if (_type.startsWith("uint") && value > range - 1)
	{
		ret.insert("minValue", "0");
		std::ostringstream s;
		s << range - 1;
		ret.insert("maxValue", QString::fromStdString(s.str()));
		if (value > range)
			ret["valid"] = false;
	}
	else if (_type.startsWith("int"))
	{
		range = range / 2;
		std::ostringstream s;
		s << -range;
		ret.insert("minValue", QString::fromStdString(s.str()));
		s.str("");
		s.clear();
		s << range - 1;
		ret.insert("maxValue", QString::fromStdString(s.str()));
		if (-range > value || value > range - 1)
			ret["valid"] = false;
	}
	return ret;
}
<commit_msg>bug fix: #2020<commit_after>/*
	This file is part of cpp-ethereum.

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

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QBigInt.cpp
 * @author Yann yann@ethdev.com
 * @date 2015
 */

#include <boost/variant/multivisitors.hpp>
#include <boost/variant.hpp>
#include <libethcore/CommonJS.h>
#include "QBigInt.h"

using namespace dev;
using namespace dev::mix;

QString QBigInt::value() const
{
	std::ostringstream s;
	s << m_internalValue;
	return QString::fromStdString(s.str());
}

QBigInt* QBigInt::subtract(QBigInt* const& _value) const
{
	BigIntVariant toSubtract = _value->internalValue();
	return new QBigInt(boost::apply_visitor(mix::subtract(), m_internalValue, toSubtract));
}

QBigInt* QBigInt::add(QBigInt* const& _value) const
{
	BigIntVariant toAdd = _value->internalValue();
	return new QBigInt(boost::apply_visitor(mix::add(), m_internalValue, toAdd));
}

QBigInt* QBigInt::multiply(QBigInt* const& _value) const
{
	BigIntVariant toMultiply = _value->internalValue();
	return new QBigInt(boost::apply_visitor(mix::multiply(), m_internalValue, toMultiply));
}

QBigInt* QBigInt::divide(QBigInt* const& _value) const
{
	BigIntVariant toDivide = _value->internalValue();
	return new QBigInt(boost::apply_visitor(mix::divide(), m_internalValue, toDivide));
}

QVariantMap QBigInt::checkAgainst(QString const& _type) const
{
	QVariantMap ret;
	QString type = _type;
	QString capacity = type.replace("uint", "").replace("int", "");
	if (capacity.isEmpty())
		capacity = "256";
	bigint range = 1;
	for (int k = 0; k < capacity.toInt() / 8; ++k)
		range = range * 256;
	bigint value = boost::get<bigint>(this->internalValue());
	ret.insert("valid", true);
	if (_type.startsWith("uint") && value > range - 1)
	{
		ret.insert("minValue", "0");
		std::ostringstream s;
		s << range - 1;
		ret.insert("maxValue", QString::fromStdString(s.str()));
		if (value > range)
			ret["valid"] = false;
	}
	else if (_type.startsWith("int"))
	{
		range = range / 2;
		std::ostringstream s;
		s << -range;
		ret.insert("minValue", QString::fromStdString(s.str()));
		s.str("");
		s.clear();
		s << range - 1;
		ret.insert("maxValue", QString::fromStdString(s.str()));
		if (-range > value || value > range - 1)
			ret["valid"] = false;
	}
	return ret;
}
<|endoftext|>


<commit_before><commit_msg>[NFC] Fix warnings in RHist.hxx<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.

//
// Implements two reader subclasses: MkvReaderQT and MkvBufferedReaderQT
// that can be passed to the mkvparser object for its use in reading WebM data.
// See www.webmproject.org for more info.
//

#include "mkvreaderqt.hpp"

extern "C" {
#include "log.h"
}

static void ReadCompletion(Ptr request, long refcon, OSErr readErr);

//--------------------------------------------------------------------------------
MkvReaderQT::MkvReaderQT() :
  m_length(0), m_dataRef(NULL), m_dataHandler(NULL)
{
}

//--------------------------------------------------------------------------------
MkvReaderQT::~MkvReaderQT()
{
  Close();
}

//--------------------------------------------------------------------------------
int MkvReaderQT::Open(Handle dataRef, OSType dataRefType)
{
  if (dataRef == NULL)
    return -11;

  if ((m_dataRef) || (m_dataHandler))
    return -2;

  m_dataRef = dataRef;

  long fileSize = 0;

  // Retrieve the best data handler component to use with the given data reference, for read purpoases.
	// Then open the returned component using standard Component Manager calls.
  OSType err;
  ComponentInstance dataHandler = 0;
	err = OpenAComponent(GetDataHandler(dataRef, dataRefType, kDataHCanRead), &dataHandler);
	if (err) return -3;

  // Provide a data reference to the data handler.
	// Then you may start reading and/or writing
	// movie data from that data reference.
	err = DataHSetDataRef(dataHandler, dataRef);
	if (err) return -4;

  // Open a read path to the current data reference.
  // You need to do this before your component can read data using a data handler component.
	err = DataHOpenForRead(dataHandler);
	if (err) return -5;

  // Get the size, in bytes, of the current data reference.
  // This is functionally equivalent to the File Manager's GetEOF function.
	err = DataHGetFileSize(dataHandler, &fileSize);
	if (err) return -6;
  m_length = fileSize;

#if 0
  Boolean buffersReads;
  Boolean buffersWrites;
  DataHDoesBuffer(dataHandler,  &buffersReads, &buffersWrites);
  dbg_printf("DataHDoesBuffer() buffersReads = %d\n", buffersReads);
  long blockSize = 0;
  DataHGetPreferredBlockSize(dataHandler, &blockSize);
  dbg_printf("DataHGetPreferredBlockSize() is %ld\n", blockSize);
#endif

  // dbg_printf("[WebM Import] DataHGetFileSize = %d\n", fileSize);
  //  dbg_printf("[WebM Import] sizeof Header %d\n", sizeof(header));

  m_dataHandler = dataHandler;
  return 0;
}

//--------------------------------------------------------------------------------
void MkvReaderQT::Close()
{
  // ****
}

//--------------------------------------------------------------------------------
int MkvReaderQT::Read(long long position, long length, unsigned char* buffer)
{
  // sanity checks
  if ((m_dataRef == NULL) || (position < 0) || (length < 0) || (position >= m_length))
    return -1;

  if (length == 0)
    return 0;

  if (length != 1)
    dbg_printf("MkvReaderQT::Read() len = %ld\n", length);

  // DatHGetPreferredBlockSize()
  // MovieImportSetIdleManager(store, store->idleManager)

  // seek and read
	// This function provides both a synchronous and an asynchronous read interface. Synchronous read operations
	// work like the DataHGetData function--the data handler component returns control to the client program only
	// after it has serviced the read request. Asynchronous read operations allow client programs to schedule read
	// requests in the context of a specified QuickTime time base. The DataHandler queues the request and immediately
	// returns control to the caller. After the component actually reads the data, it calls the completion function -
	// calling of the completion will occurs in DataHTask. Not all data handlers support scheduling, if they don't
	// they'll complete synchronously and then call the completion function. Additionally as a note, some DataHandlers
	// support 64-bit file offsets, for example DataHScheduleData64, we're not using this call here but you could use
	// 64-bit versions first, and if they fail fall back to the older calls.
	OSType err;
  err = DataHScheduleData(m_dataHandler,	// DataHandler Component Instance
                          (Ptr)buffer,	// Specifies the location in memory that is to receive the data
                          position,	        	// Offset in the data reference from which you want to read
                          length,       // The number of bytes to read
                          0,            // refCon
                          NULL,         // pointer to a schedule record - NULL for Synchronous operation
                          NULL);        // pointer to a data-handler completion function - NULL for Syncronous operation
	if (err)
    return -2;

  // if we read less than what caller asked for, then return error.
  //if (size < size_t(length))
  //  return -1;

  return 0;
}

//--------------------------------------------------------------------------------
int MkvReaderQT::Length(long long* total, long long* available)
{
  if (total)
    *total = m_length;

  if (available)
    *available = m_length;

  return 0;
}

//--------------------------------------------------------------------------------
//
MkvBufferedReaderQT::MkvBufferedReaderQT() :
  bufDataSize(0), bufStartFilePos(0), bufCurFilePos(0), bufEndFilePos(0), m_PendingReadSize(0)
{
  bufDataMax = sizeof(buf);
  m_previousReadPos = 0;
}

//--------------------------------------------------------------------------------
MkvBufferedReaderQT::~MkvBufferedReaderQT()
{
  // ****
}

//--------------------------------------------------------------------------------
//
int MkvBufferedReaderQT::Read(long long requestedPos, long requestedLen, unsigned char* outbuf)
{
  // **** NOTE - any dbg_print() in this function has big impact on runtime performance.
  //dbg_printf("MkvBufferedReaderQT::Read() - requestedPos = %lld, requestedLen = %ld\n", requestedPos, requestedLen);
  //dbg_printf("\tbufStartFilePos = %lld, m_buffer.size = %lu\n", bufStartFilePos, m_buffer.size());
  //  dbg_printf("ReadPos\t%c\t%ld\tdelta=%ld\n", (requestedPos > m_previousReadPos)?'+':'-', requestedPos, (requestedPos-m_previousReadPos));

  m_previousReadPos = requestedPos;

  if ((requestedPos < bufStartFilePos) ||
      (requestedPos > bufEndFilePos) ||
      ((requestedPos + requestedLen - 1) > bufEndFilePos)) {  // m_bufHeadPos+m_buffer.size())) {
    // non-contiguous read, miss
    dbg_printf("\tNON-CONTIGUOUS READ, CACHE MISS requestedPos = %lld, requestedLen = %ld [%ld - %ld - %ld]\n", requestedPos, requestedLen, bufStartFilePos, bufCurFilePos, bufEndFilePos);
    int err = this->MkvReaderQT::Read(requestedPos, requestedLen, outbuf);
    return err;
  }

  //dbg_printf("\tm_bufpos=%lld, requestedLen=%ld, m_buffer.size() = %lu\n", m_bufpos, requestedLen, m_buffer.size());
#if 0
  // contiguous read (or empty buffer)
  // is the request larger than what we already have in buffer?
  if ((requestedPos + requestedLen - 1) > bufEndFilePos) {  // (m_bufHeadPos + m_buffer.size() - 1)) {
    dbg_printf("\tNOT ENOUGH IN BUFFER, read from file.\n");
    // not enough in buffer...
    // read from data handler (file)
    size_t growSize = (requestedLen < m_chunksize) ? m_chunksize : requestedLen; // grow buffer by chunksize or requestedLen, whichever is greater.
    unsigned char* tempBuf = (unsigned char*)malloc(growSize);
    int err = this->MkvReaderQT::Read(requestedPos, growSize, tempBuf);
    if (err != 0) {
      free(tempBuf);
      return err;
    }

    // append to existing buffer
    for (long i=0; i < growSize; i++) {
      m_buffer.push_back(tempBuf[i]);
    }

    free(tempBuf);
  }
#endif
  //dbg_printf("\tm_buffer.front = %1x\n", m_buffer.front());

  // read from buffer
  if (requestedLen > 0) {
    for (long i=0; i < requestedLen; i++) {
      outbuf[i] = buf[requestedPos - bufStartFilePos + i];
      //outbuf[i] = m_buffer[requestedPos - bufStartFilePos + i]; //.front();
      //m_buffer.pop();
      //m_bufpos++;
    }
    // ****  dbg_printf("BUF CACHE HIT!\n");
    bufCurFilePos = (requestedPos + requestedLen);
  }

  //dbg_printf("\toutbuf[0]=%1x\n", outbuf[0]);
  //dbg_printf("MkvBufferedReaderQT::Read() return.\n");
  //dbg_printf("\n");
  return 0;
}

//--------------------------------------------------------------------------------
void MkvBufferedReaderQT::ReadAsync(MkvBufferedReaderQT* reader, long requestedLen)
{
  if (reader->m_PendingReadSize != 0) {
    // if an async read is already pending, nop and return now.
    return;
  }

  dbg_printf("ReadAsync...\n");
  dbg_printf("MkvBufferedReaderQT::buf %ld [%ld - %ld - %ld] %ld\n", reader->bufDataSize, reader->bufStartFilePos, reader->bufCurFilePos, reader->bufEndFilePos, reader->bufDataMax);

  if (reader->read_completion_cb == NULL)
    reader->read_completion_cb = NewDataHCompletionUPP(ReadCompletion);

  // if requested size wouldn't fit into available space in buffer, and currently consumed more than 3/4 of data in buffer, then compact the buffer.
  if ((reader->bufDataSize + requestedLen > reader->bufDataMax) &&
      ((reader->bufCurFilePos - reader->bufStartFilePos) > (reader->bufEndFilePos - reader->bufStartFilePos) * 0.75)) {
    reader->CompactBuffer(requestedLen);
  }

  if (reader->bufDataSize + requestedLen <= reader->bufDataMax) {
    wide ofst;
    ofst.hi = 0;
    ofst.lo = reader->bufEndFilePos;
    reader->m_PendingReadSize = requestedLen;
    reader->readErr = DataHReadAsync(reader->m_dataHandler, reader->buf + reader->bufDataSize, requestedLen, &ofst, reader->read_completion_cb, (long)reader);
  }
  else {
    dbg_printf("MkvBufferedReaderQT::ReadAsync() FAIL - BUFFER FULL. bufDataSize=%ld, consumed=%ld\n", reader->bufDataSize, (reader->bufCurFilePos - reader->bufStartFilePos));
    reader->m_PendingReadSize = 0;
    DataHTask(reader->m_dataHandler);
    //ReadCompletion(NULL, (long)reader, noErr);  // **** maybe wait, and then call comletion, just to keep pump going...
  }
}

//--------------------------------------------------------------------------------
void MkvBufferedReaderQT::InitBuffer()
{
  if ((m_PendingReadSize == 0) && (bufDataSize == 0) && (bufEndFilePos == 0)) {
    dbg_printf("InitBuffer (sync) ...");
    long requestedLen = kReadChunkSize * 16;   // **** try larger initial chunk
    m_PendingReadSize = requestedLen;
    int err = this->MkvReaderQT::Read(0, requestedLen, buf);

    ReadCompletion(NULL, (long)this, err);

  }
  else {
    dbg_printf("InitBuffer FAIL.");
  }
}

//--------------------------------------------------------------------------------
static void ReadCompletion(Ptr request, long refcon, OSErr readErr)
{
  MkvBufferedReaderQT* reader = (MkvBufferedReaderQT*)refcon;
  reader->readErr = readErr;
  reader->bufEndFilePos += reader->m_PendingReadSize; // incr file position by amount that was just read into buf
  reader->bufDataSize += reader->m_PendingReadSize; // incr size of data in buf
  reader->m_PendingReadSize = 0;

  dbg_printf("...ReadCompletion (filePos=%ld)\n", reader->bufEndFilePos);

  long readSize = kReadChunkSize; // MkvBufferedReaderQT::kDefaultChunkSize;
  MkvBufferedReaderQT::ReadAsync(reader);   // , readSize);  use default arg
}

//--------------------------------------------------------------------------------
void MkvBufferedReaderQT::CompactBuffer(long requestedSize)
{
  long remainingDataSize = (bufDataMax - bufDataSize);
  long consumedDataSize = (bufCurFilePos - bufStartFilePos);
  long killDataSize = (consumedDataSize > kReadChunkSize) ? (consumedDataSize - kReadChunkSize) : (consumedDataSize * 0.50);   //* 0.5;   // 0.66;  // / 2;
  if (requestedSize > remainingDataSize) {
    if (killDataSize > (requestedSize - remainingDataSize)) {
      dbg_printf("CompactBuffer() consumedDataSize=%ld, killDataSize=%ld\n", consumedDataSize, killDataSize);
      memmove(&buf[0], &buf[killDataSize], (bufDataSize - killDataSize));
      bufDataSize -= killDataSize;
      bufStartFilePos += killDataSize;
    }
    else {
      dbg_printf("CompactBuffer() FAIL. Wait for more data to be consumed.\n");
    }
  }
  else
    dbg_printf("CompactBuffer() NOP, don't need to compact at this time.\n");
}

<commit_msg>Fix off-by-one bug in the importer's reader.<commit_after>// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.

//
// Implements two reader subclasses: MkvReaderQT and MkvBufferedReaderQT
// that can be passed to the mkvparser object for its use in reading WebM data.
// See www.webmproject.org for more info.
//

#include "mkvreaderqt.hpp"

extern "C" {
#include "log.h"
}

static void ReadCompletion(Ptr request, long refcon, OSErr readErr);

//--------------------------------------------------------------------------------
MkvReaderQT::MkvReaderQT() :
  m_length(0), m_dataRef(NULL), m_dataHandler(NULL)
{
}

//--------------------------------------------------------------------------------
MkvReaderQT::~MkvReaderQT()
{
  Close();
}

//--------------------------------------------------------------------------------
int MkvReaderQT::Open(Handle dataRef, OSType dataRefType)
{
  if (dataRef == NULL)
    return -11;

  if ((m_dataRef) || (m_dataHandler))
    return -2;

  m_dataRef = dataRef;

  long fileSize = 0;

  // Retrieve the best data handler component to use with the given data reference, for read purpoases.
	// Then open the returned component using standard Component Manager calls.
  OSType err;
  ComponentInstance dataHandler = 0;
	err = OpenAComponent(GetDataHandler(dataRef, dataRefType, kDataHCanRead), &dataHandler);
	if (err) return -3;

  // Provide a data reference to the data handler.
	// Then you may start reading and/or writing
	// movie data from that data reference.
	err = DataHSetDataRef(dataHandler, dataRef);
	if (err) return -4;

  // Open a read path to the current data reference.
  // You need to do this before your component can read data using a data handler component.
	err = DataHOpenForRead(dataHandler);
	if (err) return -5;

  // Get the size, in bytes, of the current data reference.
  // This is functionally equivalent to the File Manager's GetEOF function.
	err = DataHGetFileSize(dataHandler, &fileSize);
	if (err) return -6;
  m_length = fileSize;

#if 0
  Boolean buffersReads;
  Boolean buffersWrites;
  DataHDoesBuffer(dataHandler,  &buffersReads, &buffersWrites);
  dbg_printf("DataHDoesBuffer() buffersReads = %d\n", buffersReads);
  long blockSize = 0;
  DataHGetPreferredBlockSize(dataHandler, &blockSize);
  dbg_printf("DataHGetPreferredBlockSize() is %ld\n", blockSize);
#endif

  // dbg_printf("[WebM Import] DataHGetFileSize = %d\n", fileSize);
  //  dbg_printf("[WebM Import] sizeof Header %d\n", sizeof(header));

  m_dataHandler = dataHandler;
  return 0;
}

//--------------------------------------------------------------------------------
void MkvReaderQT::Close()
{
  // ****
}

//--------------------------------------------------------------------------------
int MkvReaderQT::Read(long long position, long length, unsigned char* buffer)
{
  // sanity checks
  if ((m_dataRef == NULL) || (position < 0) || (length < 0) || (position >= m_length))
    return -1;

  if (length == 0)
    return 0;

  if (length != 1)
    dbg_printf("MkvReaderQT::Read() len = %ld\n", length);

  // DatHGetPreferredBlockSize()
  // MovieImportSetIdleManager(store, store->idleManager)

  // seek and read
	// This function provides both a synchronous and an asynchronous read interface. Synchronous read operations
	// work like the DataHGetData function--the data handler component returns control to the client program only
	// after it has serviced the read request. Asynchronous read operations allow client programs to schedule read
	// requests in the context of a specified QuickTime time base. The DataHandler queues the request and immediately
	// returns control to the caller. After the component actually reads the data, it calls the completion function -
	// calling of the completion will occurs in DataHTask. Not all data handlers support scheduling, if they don't
	// they'll complete synchronously and then call the completion function. Additionally as a note, some DataHandlers
	// support 64-bit file offsets, for example DataHScheduleData64, we're not using this call here but you could use
	// 64-bit versions first, and if they fail fall back to the older calls.
	OSType err;
  err = DataHScheduleData(m_dataHandler,	// DataHandler Component Instance
                          (Ptr)buffer,	// Specifies the location in memory that is to receive the data
                          position,	        	// Offset in the data reference from which you want to read
                          length,       // The number of bytes to read
                          0,            // refCon
                          NULL,         // pointer to a schedule record - NULL for Synchronous operation
                          NULL);        // pointer to a data-handler completion function - NULL for Syncronous operation
	if (err)
    return -2;

  // if we read less than what caller asked for, then return error.
  //if (size < size_t(length))
  //  return -1;

  return 0;
}

//--------------------------------------------------------------------------------
int MkvReaderQT::Length(long long* total, long long* available)
{
  if (total)
    *total = m_length;

  if (available)
    *available = m_length;

  return 0;
}

//--------------------------------------------------------------------------------
//
MkvBufferedReaderQT::MkvBufferedReaderQT() :
  bufDataSize(0), bufStartFilePos(0), bufCurFilePos(0), bufEndFilePos(0), m_PendingReadSize(0)
{
  bufDataMax = sizeof(buf);
  m_previousReadPos = 0;
}

//--------------------------------------------------------------------------------
MkvBufferedReaderQT::~MkvBufferedReaderQT()
{
  // ****
}

//--------------------------------------------------------------------------------
//
int MkvBufferedReaderQT::Read(long long requestedPos, long requestedLen, unsigned char* outbuf)
{
  // **** NOTE - any dbg_print() in this function has big impact on runtime performance.
  //dbg_printf("MkvBufferedReaderQT::Read() - requestedPos = %lld, requestedLen = %ld\n", requestedPos, requestedLen);
  //dbg_printf("\tbufStartFilePos = %lld, m_buffer.size = %lu\n", bufStartFilePos, m_buffer.size());
  //  dbg_printf("ReadPos\t%c\t%ld\tdelta=%ld\n", (requestedPos > m_previousReadPos)?'+':'-', requestedPos, (requestedPos-m_previousReadPos));

  m_previousReadPos = requestedPos;

  if ((requestedPos < bufStartFilePos) ||
      (requestedPos >= bufEndFilePos) ||
      ((requestedPos + requestedLen) > bufEndFilePos)) {  // m_bufHeadPos+m_buffer.size())) {
    // non-contiguous read, miss
    dbg_printf("\tNON-CONTIGUOUS READ, CACHE MISS requestedPos = %lld, requestedLen = %ld [%ld - %ld - %ld]\n", requestedPos, requestedLen, bufStartFilePos, bufCurFilePos, bufEndFilePos);
    int err = this->MkvReaderQT::Read(requestedPos, requestedLen, outbuf);
    return err;
  }

  //dbg_printf("\tm_bufpos=%lld, requestedLen=%ld, m_buffer.size() = %lu\n", m_bufpos, requestedLen, m_buffer.size());
#if 0
  // contiguous read (or empty buffer)
  // is the request larger than what we already have in buffer?
  if ((requestedPos + requestedLen - 1) > bufEndFilePos) {  // (m_bufHeadPos + m_buffer.size() - 1)) {
    dbg_printf("\tNOT ENOUGH IN BUFFER, read from file.\n");
    // not enough in buffer...
    // read from data handler (file)
    size_t growSize = (requestedLen < m_chunksize) ? m_chunksize : requestedLen; // grow buffer by chunksize or requestedLen, whichever is greater.
    unsigned char* tempBuf = (unsigned char*)malloc(growSize);
    int err = this->MkvReaderQT::Read(requestedPos, growSize, tempBuf);
    if (err != 0) {
      free(tempBuf);
      return err;
    }

    // append to existing buffer
    for (long i=0; i < growSize; i++) {
      m_buffer.push_back(tempBuf[i]);
    }

    free(tempBuf);
  }
#endif
  //dbg_printf("\tm_buffer.front = %1x\n", m_buffer.front());

  // read from buffer
  if (requestedLen > 0) {
    for (long i=0; i < requestedLen; i++) {
      outbuf[i] = buf[requestedPos - bufStartFilePos + i];
      //outbuf[i] = m_buffer[requestedPos - bufStartFilePos + i]; //.front();
      //m_buffer.pop();
      //m_bufpos++;
    }
    // ****  dbg_printf("BUF CACHE HIT!\n");
    bufCurFilePos = (requestedPos + requestedLen);
  }

  //dbg_printf("\toutbuf[0]=%1x\n", outbuf[0]);
  //dbg_printf("MkvBufferedReaderQT::Read() return.\n");
  //dbg_printf("\n");
  return 0;
}

//--------------------------------------------------------------------------------
void MkvBufferedReaderQT::ReadAsync(MkvBufferedReaderQT* reader, long requestedLen)
{
  if (reader->m_PendingReadSize != 0) {
    // if an async read is already pending, nop and return now.
    return;
  }

  dbg_printf("ReadAsync...\n");
  dbg_printf("MkvBufferedReaderQT::buf %ld [%ld - %ld - %ld] %ld\n", reader->bufDataSize, reader->bufStartFilePos, reader->bufCurFilePos, reader->bufEndFilePos, reader->bufDataMax);

  if (reader->read_completion_cb == NULL)
    reader->read_completion_cb = NewDataHCompletionUPP(ReadCompletion);

  // if requested size wouldn't fit into available space in buffer, and currently consumed more than 3/4 of data in buffer, then compact the buffer.
  if ((reader->bufDataSize + requestedLen > reader->bufDataMax) &&
      ((reader->bufCurFilePos - reader->bufStartFilePos) > (reader->bufEndFilePos - reader->bufStartFilePos) * 0.75)) {
    reader->CompactBuffer(requestedLen);
  }

  if (reader->bufDataSize + requestedLen <= reader->bufDataMax) {
    wide ofst;
    ofst.hi = 0;
    ofst.lo = reader->bufEndFilePos;
    reader->m_PendingReadSize = requestedLen;
    reader->readErr = DataHReadAsync(reader->m_dataHandler, reader->buf + reader->bufDataSize, requestedLen, &ofst, reader->read_completion_cb, (long)reader);
  }
  else {
    dbg_printf("MkvBufferedReaderQT::ReadAsync() FAIL - BUFFER FULL. bufDataSize=%ld, consumed=%ld\n", reader->bufDataSize, (reader->bufCurFilePos - reader->bufStartFilePos));
    reader->m_PendingReadSize = 0;
    DataHTask(reader->m_dataHandler);
    //ReadCompletion(NULL, (long)reader, noErr);  // **** maybe wait, and then call comletion, just to keep pump going...
  }
}

//--------------------------------------------------------------------------------
void MkvBufferedReaderQT::InitBuffer()
{
  if ((m_PendingReadSize == 0) && (bufDataSize == 0) && (bufEndFilePos == 0)) {
    dbg_printf("InitBuffer (sync) ...");
    long requestedLen = kReadChunkSize * 16;   // **** try larger initial chunk
    m_PendingReadSize = requestedLen;
    int err = this->MkvReaderQT::Read(0, requestedLen, buf);

    ReadCompletion(NULL, (long)this, err);

  }
  else {
    dbg_printf("InitBuffer FAIL.");
  }
}

//--------------------------------------------------------------------------------
static void ReadCompletion(Ptr request, long refcon, OSErr readErr)
{
  MkvBufferedReaderQT* reader = (MkvBufferedReaderQT*)refcon;
  reader->readErr = readErr;
  reader->bufEndFilePos += reader->m_PendingReadSize; // incr file position by amount that was just read into buf
  reader->bufDataSize += reader->m_PendingReadSize; // incr size of data in buf
  reader->m_PendingReadSize = 0;

  dbg_printf("...ReadCompletion (filePos=%ld)\n", reader->bufEndFilePos);

  long readSize = kReadChunkSize; // MkvBufferedReaderQT::kDefaultChunkSize;
  MkvBufferedReaderQT::ReadAsync(reader);   // , readSize);  use default arg
}

//--------------------------------------------------------------------------------
void MkvBufferedReaderQT::CompactBuffer(long requestedSize)
{
  long remainingDataSize = (bufDataMax - bufDataSize);
  long consumedDataSize = (bufCurFilePos - bufStartFilePos);
  long killDataSize = (consumedDataSize > kReadChunkSize) ? (consumedDataSize - kReadChunkSize) : (consumedDataSize * 0.50);   //* 0.5;   // 0.66;  // / 2;
  if (requestedSize > remainingDataSize) {
    if (killDataSize > (requestedSize - remainingDataSize)) {
      dbg_printf("CompactBuffer() consumedDataSize=%ld, killDataSize=%ld\n", consumedDataSize, killDataSize);
      memmove(&buf[0], &buf[killDataSize], (bufDataSize - killDataSize));
      bufDataSize -= killDataSize;
      bufStartFilePos += killDataSize;
    }
    else {
      dbg_printf("CompactBuffer() FAIL. Wait for more data to be consumed.\n");
    }
  }
  else
    dbg_printf("CompactBuffer() NOP, don't need to compact at this time.\n");
}

<|endoftext|>


<commit_before>/*********************************************************************
 *
 * Condor ClassAd library
 * Copyright (C) 1990-2001, CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI, and Rajesh Raman.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of version 2.1 of the GNU Lesser General
 * Public License 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
 *
 *********************************************************************/

#include "common.h"
#include "lexer.h"
#include "exprTree.h"
#include "collection.h"
#include "collectionBase.h"
#include "classad.h"

BEGIN_NAMESPACE( classad )
//-------------classad templates --------------

template map<string, bool>;

// function table
template map<string, void*, CaseIgnLTStr>;
template map<string, void*, CaseIgnLTStr>::iterator;

// XML attributes
template map<string, string>;
template map<string, string>::iterator;

// attribute list
template hash_map<string, ExprTree*, StringCaseIgnHash, CaseIgnEqStr>;
template hash_map<string, ExprTree*, StringCaseIgnHash, CaseIgnEqStr>::iterator;
template hash_map<string, ExprTree*, StringCaseIgnHash, CaseIgnEqStr>::const_iterator;

// expr evaluation cache
template hash_map<const ExprTree*, Value, ExprHash >;
template hash_map<const ExprTree*, Value, ExprHash >::iterator;

// component stuff
template vector< pair<string, ExprTree*> >;
template vector<ExprTree*>;

template map<string, ClassAd *>;
template map<string, ClassAdCollection *>;

#ifdef CLASSAD_DISTRIBUTION
template vector<string>;
#include "transaction.h"
#include "view.h"

// view content
template multiset<ViewMember, ViewMemberLT>;
template multiset<ViewMember, ViewMemberLT>::iterator;

// list of sub-views
template slist<View*>;

// view registry
template hash_map<string,View*,StringHash>;
template hash_map<string,View*,StringHash>::iterator;

// index
template hash_map<string,multiset<ViewMember,ViewMemberLT>::iterator,
    StringHash>::iterator;
template hash_map<string,multiset<ViewMember,ViewMemberLT>::iterator,
    StringHash>;

// main classad table
template hash_map<string, ClassAdProxy, StringHash>;
template hash_map<string, ClassAdProxy, StringHash>::iterator;

// index file
template map<string, int>;
template hash_map<string,int,StringHash>;
template hash_map<string,int,StringHash>::iterator;

// transaction registry
template hash_map<string, ServerTransaction*, StringHash>;
template hash_map<string, ServerTransaction*, StringHash>::iterator;

// operations in transaction
template list<XactionRecord>;
#endif

class _ClassAdInit
{
	public:
		_ClassAdInit( ) { tzset( ); }
} __ClassAdInit;

END_NAMESPACE
<commit_msg>Change for standalone to compile with GCC 3.0. It was a goofy thing: we need to define an operator+. Francesco Giacomini figured it out for us a while ago, and I only just added it. Also added "using namespace std" for the standalong to compile well with GCC 3.0<commit_after>/*********************************************************************
 *
 * Condor ClassAd library
 * Copyright (C) 1990-2001, CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI, and Rajesh Raman.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of version 2.1 of the GNU Lesser General
 * Public License 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
 *
 *********************************************************************/

#include "common.h"
#include "lexer.h"
#include "exprTree.h"
#include "collection.h"
#include "collectionBase.h"
#include "classad.h"

using namespace std;

BEGIN_NAMESPACE( classad )
//-------------classad templates --------------

template map<string, bool>;

// function table
template map<string, void*, CaseIgnLTStr>;
template map<string, void*, CaseIgnLTStr>::iterator;

// XML attributes
template map<string, string>;
template map<string, string>::iterator;

// attribute list
template hash_map<string, ExprTree*, StringCaseIgnHash, CaseIgnEqStr>;
template hash_map<string, ExprTree*, StringCaseIgnHash, CaseIgnEqStr>::iterator;
template hash_map<string, ExprTree*, StringCaseIgnHash, CaseIgnEqStr>::const_iterator;

// expr evaluation cache
template hash_map<const ExprTree*, Value, ExprHash >;
template hash_map<const ExprTree*, Value, ExprHash >::iterator;

// component stuff
template vector< pair<string, ExprTree*> >;
template vector<ExprTree*>;

template map<string, ClassAd *>;
template map<string, ClassAdCollection *>;

#ifdef CLASSAD_DISTRIBUTION
template vector<string>;
#include "transaction.h"
#include "view.h"

// view content
template multiset<ViewMember, ViewMemberLT>;
template multiset<ViewMember, ViewMemberLT>::iterator;

// list of sub-views
template slist<View*>;

// view registry
template hash_map<string,View*,StringHash>;
template hash_map<string,View*,StringHash>::iterator;

// index
template hash_map<string,multiset<ViewMember,ViewMemberLT>::iterator,
    StringHash>::iterator;
template hash_map<string,multiset<ViewMember,ViewMemberLT>::iterator,
    StringHash>;

// main classad table
template hash_map<string, ClassAdProxy, StringHash>;
template hash_map<string, ClassAdProxy, StringHash>::iterator;

// index file
template map<string, int>;
template hash_map<string,int,StringHash>;
template hash_map<string,int,StringHash>::iterator;

// transaction registry
template hash_map<string, ServerTransaction*, StringHash>;
template hash_map<string, ServerTransaction*, StringHash>::iterator;

// operations in transaction
template list<XactionRecord>;

#if (__GNUC__>=3)
template string std::operator+<char, std::char_traits<char>, std::allocator<char> >(const string&, const string&);
#endif

#endif

class _ClassAdInit
{
	public:
		_ClassAdInit( ) { tzset( ); }
} __ClassAdInit;

END_NAMESPACE
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2017 gRPC authors.
 *
 * 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 "src/core/lib/channel/channel_tracer.h"

#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include <stdlib.h>
#include <string.h>

#include "src/core/lib/channel/object_registry.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/connectivity_state.h"

namespace grpc_core {

class TraceEvent {
 public:
  TraceEvent(grpc_slice data, grpc_error* error,
             grpc_connectivity_state connectivity_state,
             ChannelTracer* referenced_tracer)
      : data_(data),
        error_(error),
        connectivity_state_(connectivity_state),
        next_(nullptr) {
    referenced_tracer_ = referenced_tracer ? referenced_tracer->Ref() : nullptr;
    time_created_ = gpr_now(GPR_CLOCK_REALTIME);
  }

 private:
  friend class ChannelTracer;
  friend class ChannelTracerRenderer;
  grpc_slice data_;
  grpc_error* error_;
  gpr_timespec time_created_;
  grpc_connectivity_state connectivity_state_;
  TraceEvent* next_;
  // the tracer object for the (sub)channel that this trace node refers to.
  ChannelTracer* referenced_tracer_;
};

ChannelTracer::ChannelTracer(size_t max_nodes)
    : channel_uuid_(-1),
      num_nodes_logged_(0),
      num_children_seen_(0),
      list_size_(0),
      max_list_size_(max_nodes),
      head_trace_(0),
      tail_trace_(0) {
  if (!max_list_size_) return;  // tracing is disabled if max_nodes == 0
  gpr_mu_init(&tracer_mu_);
  gpr_ref_init(&refs_, 1);
  channel_uuid_ = grpc_object_registry_register_object(
      this, GRPC_OBJECT_REGISTRY_CHANNEL_TRACER);
  max_list_size_ = max_nodes;
  time_created_ = gpr_now(GPR_CLOCK_REALTIME);
}

ChannelTracer* ChannelTracer::Ref() {
  if (!max_list_size_) return nullptr;  // tracing is disabled if max_nodes == 0
  gpr_ref(&refs_);
  return this;
}

void ChannelTracer::FreeNode(TraceEvent* node) {
  GRPC_ERROR_UNREF(node->error_);
  if (node->referenced_tracer_) {
    node->referenced_tracer_->Unref();
  }
  grpc_slice_unref_internal(node->data_);
  gpr_free(node);
}

void ChannelTracer::Unref() {
  if (!max_list_size_) return;  // tracing is disabled if max_nodes == 0
  if (gpr_unref(&refs_)) {
    TraceEvent* it = head_trace_;
    while (it != nullptr) {
      TraceEvent* to_free = it;
      it = it->next_;
      FreeNode(to_free);
    }
    gpr_mu_destroy(&tracer_mu_);
  }
}

intptr_t ChannelTracer::GetUuid() { return channel_uuid_; }

void ChannelTracer::AddTrace(grpc_slice data, grpc_error* error,
                             grpc_connectivity_state connectivity_state,
                             ChannelTracer* referenced_tracer) {
  if (!max_list_size_) return;  // tracing is disabled if max_nodes == 0
  ++num_nodes_logged_;
  if (referenced_tracer != nullptr) ++num_children_seen_;
  // create and fill up the new node
  TraceEvent* new_trace_node =
      New<TraceEvent>(data, error, connectivity_state, referenced_tracer);
  // first node case
  if (head_trace_ == nullptr) {
    head_trace_ = tail_trace_ = new_trace_node;
  }
  // regular node add case
  else {
    tail_trace_->next_ = new_trace_node;
    tail_trace_ = tail_trace_->next_;
  }
  ++list_size_;
  // maybe garbage collect the end
  if (list_size_ > max_list_size_) {
    TraceEvent* to_free = head_trace_;
    head_trace_ = head_trace_->next_;
    FreeNode(to_free);
    --list_size_;
  }
}

// returns an allocated string that represents tm according to RFC-3339.
static char* fmt_time(gpr_timespec tm) {
  char buffer[35];
  struct tm* tm_info = localtime((const time_t*)&tm.tv_sec);
  strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%S", tm_info);
  char* full_time_str;
  gpr_asprintf(&full_time_str, "%s.%09dZ", buffer, tm.tv_nsec);
  return full_time_str;
}

// Helper class that is responsible for walking the tree of ChannelTracer
// objects and rendering the trace as JSON according to:
// https://github.com/grpc/proposal/pull/7

// The rendered JSON should be of this format:
// {
//   "channelData": {
//     "uuid": string,
//     "numNodesLogged": number,
//     "startTime": timestamp string,
//     "nodes": [
//       {
//         "data": string,
//         "error": string,
//         "time": timestamp string,
//         // can only be one of the states in connectivity_state.h
//         "state": enum string,
//         // uuid of referenced subchannel.
//         // Optional, only present if this event refers to a child object.
//         // and example of a referenced child would be a trace event for a
//         // subchannel being created.
//         "child_uuid": string
//       },
//     ]
//   },
//   // Optional, only present if this channel has children
//   "childData": [
//     // List of child data, which is of the exact same format as the
//   ]
// }

class ChannelTracerRenderer {
 public:
  // If recursive==true, then the entire tree of trace will be rendered.
  // If not, then only the top level data will be.
  ChannelTracerRenderer(ChannelTracer* tracer, bool recursive)
      : current_tracer_(tracer),
        recursive_(recursive),
        seen_tracers_(nullptr),
        size_(0),
        cap_(0) {}

  // Renders the trace and returns an allocated char* with the formatted JSON
  char* Run() {
    grpc_json* json = grpc_json_create(GRPC_JSON_OBJECT);
    AddSeenTracer(current_tracer_);
    RecursivelyPopulateJson(json);
    gpr_free(seen_tracers_);
    char* json_str = grpc_json_dump_to_string(json, 0);
    grpc_json_destroy(json);
    return json_str;
  }

 private:
  // tracks that a tracer has already been rendered to avoid infinite
  // recursion.
  void AddSeenTracer(ChannelTracer* newly_seen) {
    if (size_ >= cap_) {
      cap_ = GPR_MAX(5 * sizeof(newly_seen), 3 * cap_ / 2);
      seen_tracers_ = (ChannelTracer**)gpr_realloc(seen_tracers_, cap_);
    }
    seen_tracers_[size_++] = newly_seen;
  }

  // Checks if a tracer has already been seen.
  bool TracerAlreadySeen(ChannelTracer* tracer) {
    for (size_t i = 0; i < size_; ++i) {
      if (seen_tracers_[i] == tracer) return true;
    }
    return false;
  }

  // Recursively fills up json by walking over all of the trace of
  // current_tracer_. Starts at the top level, by creating the fields
  // channelData, and childData.
  void RecursivelyPopulateJson(grpc_json* json) {
    grpc_json* channel_data = grpc_json_create_child(
        nullptr, json, "channelData", nullptr, GRPC_JSON_OBJECT, false);
    grpc_json* children = nullptr;
    if (recursive_) {
      children = grpc_json_create_child(channel_data, json, "childData",
                                        nullptr, GRPC_JSON_ARRAY, false);
    }
    PopulateChannelData(channel_data, children);
  }

  // Fills up the channelData object. If children is not null, it will
  // recursively populate each referenced child as it passes that node.
  void PopulateChannelData(grpc_json* channel_data, grpc_json* children) {
    grpc_json* child = nullptr;

    char* uuid_str;
    gpr_asprintf(&uuid_str, "%" PRIdPTR, current_tracer_->channel_uuid_);
    child = grpc_json_create_child(child, channel_data, "uuid", uuid_str,
                                   GRPC_JSON_NUMBER, true);
    char* num_nodes_logged_str;
    gpr_asprintf(&num_nodes_logged_str, "%" PRId64,
                 current_tracer_->num_nodes_logged_);
    child =
        grpc_json_create_child(child, channel_data, "numNodesLogged",
                               num_nodes_logged_str, GRPC_JSON_NUMBER, true);
    child = grpc_json_create_child(child, channel_data, "startTime",
                                   fmt_time(current_tracer_->time_created_),
                                   GRPC_JSON_STRING, true);
    child = grpc_json_create_child(child, channel_data, "nodes", nullptr,
                                   GRPC_JSON_ARRAY, false);
    PopulateNodeList(child, children);
  }

  // Iterated over the list of TraceEvents and populates their data.
  void PopulateNodeList(grpc_json* nodes, grpc_json* children) {
    grpc_json* child = nullptr;
    TraceEvent* it = current_tracer_->head_trace_;
    while (it != nullptr) {
      child = grpc_json_create_child(child, nodes, nullptr, nullptr,
                                     GRPC_JSON_OBJECT, false);
      PopulateNode(it, child, children);
      it = it->next_;
    }
  }

  // Fills in all the data for a single TraceEvent. If children is not null
  // and the TraceEvent refers to a child Tracer object and recursive_ is true,
  // then that child object will be rendered into the trace.
  void PopulateNode(TraceEvent* node, grpc_json* json, grpc_json* children) {
    grpc_json* child = nullptr;
    child = grpc_json_create_child(child, json, "data",
                                   grpc_slice_to_c_string(node->data_),
                                   GRPC_JSON_STRING, true);
    if (node->error_ != GRPC_ERROR_NONE) {
      child = grpc_json_create_child(
          child, json, "error", gpr_strdup(grpc_error_string(node->error_)),
          GRPC_JSON_STRING, true);
    }
    child = grpc_json_create_child(child, json, "time",
                                   fmt_time(node->time_created_),
                                   GRPC_JSON_STRING, true);
    child = grpc_json_create_child(
        child, json, "state",
        grpc_connectivity_state_name(node->connectivity_state_),
        GRPC_JSON_STRING, false);
    if (node->referenced_tracer_ != nullptr) {
      char* uuid_str;
      gpr_asprintf(&uuid_str, "%" PRIdPTR,
                   node->referenced_tracer_->channel_uuid_);
      child = grpc_json_create_child(child, json, "uuid", uuid_str,
                                     GRPC_JSON_NUMBER, true);

      // If we are recursively populating everything, and this node
      // references a tracer we haven't seen yet, we render that tracer
      // in full, adding it to the parent JSON's "children" field.
      if (children && !TracerAlreadySeen(node->referenced_tracer_)) {
        grpc_json* referenced_tracer = grpc_json_create_child(
            nullptr, children, nullptr, nullptr, GRPC_JSON_OBJECT, false);
        AddSeenTracer(node->referenced_tracer_);
        ChannelTracer* saved = current_tracer_;
        current_tracer_ = node->referenced_tracer_;
        RecursivelyPopulateJson(referenced_tracer);
        current_tracer_ = saved;
      }
    }
  }

  // Tracks the current tracer we are rendering as we walk the tree of tracers.
  ChannelTracer* current_tracer_;

  // If true, we will render the data of all of this tracer's children.
  bool recursive_;

  // These members are used to track tracers we have already rendered. This is
  // a dynamically growing array that is deallocated when the rendering is done.
  ChannelTracer** seen_tracers_;
  size_t size_;
  size_t cap_;
};

char* ChannelTracer::RenderTrace(bool recursive) {
  if (!max_list_size_) return nullptr;  // tracing is disabled if max_nodes == 0
  ChannelTracerRenderer renderer(this, recursive);
  return renderer.Run();
}

char* ChannelTracer::GetChannelTraceFromUuid(intptr_t uuid, bool recursive) {
  void* object;
  grpc_object_registry_type type =
      grpc_object_registry_get_object(uuid, &object);
  GPR_ASSERT(type == GRPC_OBJECT_REGISTRY_CHANNEL_TRACER);
  return static_cast<ChannelTracer*>(object)->RenderTrace(recursive);
}

}  // namespace grpc_core
<commit_msg>Fix clang tidy<commit_after>/*
 *
 * Copyright 2017 gRPC authors.
 *
 * 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 "src/core/lib/channel/channel_tracer.h"

#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include <stdlib.h>
#include <string.h>

#include "src/core/lib/channel/object_registry.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/connectivity_state.h"

namespace grpc_core {

class TraceEvent {
 public:
  TraceEvent(grpc_slice data, grpc_error* error,
             grpc_connectivity_state connectivity_state,
             ChannelTracer* referenced_tracer)
      : data_(data),
        error_(error),
        connectivity_state_(connectivity_state),
        next_(nullptr) {
    referenced_tracer_ = referenced_tracer ? referenced_tracer->Ref() : nullptr;
    time_created_ = gpr_now(GPR_CLOCK_REALTIME);
  }

 private:
  friend class ChannelTracer;
  friend class ChannelTracerRenderer;
  grpc_slice data_;
  grpc_error* error_;
  gpr_timespec time_created_;
  grpc_connectivity_state connectivity_state_;
  TraceEvent* next_;
  // the tracer object for the (sub)channel that this trace node refers to.
  ChannelTracer* referenced_tracer_;
};

ChannelTracer::ChannelTracer(size_t max_nodes)
    : channel_uuid_(-1),
      num_nodes_logged_(0),
      num_children_seen_(0),
      list_size_(0),
      max_list_size_(max_nodes),
      head_trace_(nullptr),
      tail_trace_(nullptr) {
  if (!max_list_size_) return;  // tracing is disabled if max_nodes == 0
  gpr_mu_init(&tracer_mu_);
  gpr_ref_init(&refs_, 1);
  channel_uuid_ = grpc_object_registry_register_object(
      this, GRPC_OBJECT_REGISTRY_CHANNEL_TRACER);
  max_list_size_ = max_nodes;
  time_created_ = gpr_now(GPR_CLOCK_REALTIME);
}

ChannelTracer* ChannelTracer::Ref() {
  if (!max_list_size_) return nullptr;  // tracing is disabled if max_nodes == 0
  gpr_ref(&refs_);
  return this;
}

void ChannelTracer::FreeNode(TraceEvent* node) {
  GRPC_ERROR_UNREF(node->error_);
  if (node->referenced_tracer_) {
    node->referenced_tracer_->Unref();
  }
  grpc_slice_unref_internal(node->data_);
  gpr_free(node);
}

void ChannelTracer::Unref() {
  if (!max_list_size_) return;  // tracing is disabled if max_nodes == 0
  if (gpr_unref(&refs_)) {
    TraceEvent* it = head_trace_;
    while (it != nullptr) {
      TraceEvent* to_free = it;
      it = it->next_;
      FreeNode(to_free);
    }
    gpr_mu_destroy(&tracer_mu_);
  }
}

intptr_t ChannelTracer::GetUuid() { return channel_uuid_; }

void ChannelTracer::AddTrace(grpc_slice data, grpc_error* error,
                             grpc_connectivity_state connectivity_state,
                             ChannelTracer* referenced_tracer) {
  if (!max_list_size_) return;  // tracing is disabled if max_nodes == 0
  ++num_nodes_logged_;
  if (referenced_tracer != nullptr) ++num_children_seen_;
  // create and fill up the new node
  TraceEvent* new_trace_node =
      New<TraceEvent>(data, error, connectivity_state, referenced_tracer);
  // first node case
  if (head_trace_ == nullptr) {
    head_trace_ = tail_trace_ = new_trace_node;
  }
  // regular node add case
  else {
    tail_trace_->next_ = new_trace_node;
    tail_trace_ = tail_trace_->next_;
  }
  ++list_size_;
  // maybe garbage collect the end
  if (list_size_ > max_list_size_) {
    TraceEvent* to_free = head_trace_;
    head_trace_ = head_trace_->next_;
    FreeNode(to_free);
    --list_size_;
  }
}

// returns an allocated string that represents tm according to RFC-3339.
static char* fmt_time(gpr_timespec tm) {
  char buffer[35];
  struct tm* tm_info = localtime((const time_t*)&tm.tv_sec);
  strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%S", tm_info);
  char* full_time_str;
  gpr_asprintf(&full_time_str, "%s.%09dZ", buffer, tm.tv_nsec);
  return full_time_str;
}

// Helper class that is responsible for walking the tree of ChannelTracer
// objects and rendering the trace as JSON according to:
// https://github.com/grpc/proposal/pull/7

// The rendered JSON should be of this format:
// {
//   "channelData": {
//     "uuid": string,
//     "numNodesLogged": number,
//     "startTime": timestamp string,
//     "nodes": [
//       {
//         "data": string,
//         "error": string,
//         "time": timestamp string,
//         // can only be one of the states in connectivity_state.h
//         "state": enum string,
//         // uuid of referenced subchannel.
//         // Optional, only present if this event refers to a child object.
//         // and example of a referenced child would be a trace event for a
//         // subchannel being created.
//         "child_uuid": string
//       },
//     ]
//   },
//   // Optional, only present if this channel has children
//   "childData": [
//     // List of child data, which is of the exact same format as the
//   ]
// }

class ChannelTracerRenderer {
 public:
  // If recursive==true, then the entire tree of trace will be rendered.
  // If not, then only the top level data will be.
  ChannelTracerRenderer(ChannelTracer* tracer, bool recursive)
      : current_tracer_(tracer),
        recursive_(recursive),
        seen_tracers_(nullptr),
        size_(0),
        cap_(0) {}

  // Renders the trace and returns an allocated char* with the formatted JSON
  char* Run() {
    grpc_json* json = grpc_json_create(GRPC_JSON_OBJECT);
    AddSeenTracer(current_tracer_);
    RecursivelyPopulateJson(json);
    gpr_free(seen_tracers_);
    char* json_str = grpc_json_dump_to_string(json, 0);
    grpc_json_destroy(json);
    return json_str;
  }

 private:
  // tracks that a tracer has already been rendered to avoid infinite
  // recursion.
  void AddSeenTracer(ChannelTracer* newly_seen) {
    if (size_ >= cap_) {
      cap_ = GPR_MAX(5 * sizeof(newly_seen), 3 * cap_ / 2);
      seen_tracers_ = (ChannelTracer**)gpr_realloc(seen_tracers_, cap_);
    }
    seen_tracers_[size_++] = newly_seen;
  }

  // Checks if a tracer has already been seen.
  bool TracerAlreadySeen(ChannelTracer* tracer) {
    for (size_t i = 0; i < size_; ++i) {
      if (seen_tracers_[i] == tracer) return true;
    }
    return false;
  }

  // Recursively fills up json by walking over all of the trace of
  // current_tracer_. Starts at the top level, by creating the fields
  // channelData, and childData.
  void RecursivelyPopulateJson(grpc_json* json) {
    grpc_json* channel_data = grpc_json_create_child(
        nullptr, json, "channelData", nullptr, GRPC_JSON_OBJECT, false);
    grpc_json* children = nullptr;
    if (recursive_) {
      children = grpc_json_create_child(channel_data, json, "childData",
                                        nullptr, GRPC_JSON_ARRAY, false);
    }
    PopulateChannelData(channel_data, children);
  }

  // Fills up the channelData object. If children is not null, it will
  // recursively populate each referenced child as it passes that node.
  void PopulateChannelData(grpc_json* channel_data, grpc_json* children) {
    grpc_json* child = nullptr;

    char* uuid_str;
    gpr_asprintf(&uuid_str, "%" PRIdPTR, current_tracer_->channel_uuid_);
    child = grpc_json_create_child(child, channel_data, "uuid", uuid_str,
                                   GRPC_JSON_NUMBER, true);
    char* num_nodes_logged_str;
    gpr_asprintf(&num_nodes_logged_str, "%" PRId64,
                 current_tracer_->num_nodes_logged_);
    child =
        grpc_json_create_child(child, channel_data, "numNodesLogged",
                               num_nodes_logged_str, GRPC_JSON_NUMBER, true);
    child = grpc_json_create_child(child, channel_data, "startTime",
                                   fmt_time(current_tracer_->time_created_),
                                   GRPC_JSON_STRING, true);
    child = grpc_json_create_child(child, channel_data, "nodes", nullptr,
                                   GRPC_JSON_ARRAY, false);
    PopulateNodeList(child, children);
  }

  // Iterated over the list of TraceEvents and populates their data.
  void PopulateNodeList(grpc_json* nodes, grpc_json* children) {
    grpc_json* child = nullptr;
    TraceEvent* it = current_tracer_->head_trace_;
    while (it != nullptr) {
      child = grpc_json_create_child(child, nodes, nullptr, nullptr,
                                     GRPC_JSON_OBJECT, false);
      PopulateNode(it, child, children);
      it = it->next_;
    }
  }

  // Fills in all the data for a single TraceEvent. If children is not null
  // and the TraceEvent refers to a child Tracer object and recursive_ is true,
  // then that child object will be rendered into the trace.
  void PopulateNode(TraceEvent* node, grpc_json* json, grpc_json* children) {
    grpc_json* child = nullptr;
    child = grpc_json_create_child(child, json, "data",
                                   grpc_slice_to_c_string(node->data_),
                                   GRPC_JSON_STRING, true);
    if (node->error_ != GRPC_ERROR_NONE) {
      child = grpc_json_create_child(
          child, json, "error", gpr_strdup(grpc_error_string(node->error_)),
          GRPC_JSON_STRING, true);
    }
    child = grpc_json_create_child(child, json, "time",
                                   fmt_time(node->time_created_),
                                   GRPC_JSON_STRING, true);
    child = grpc_json_create_child(
        child, json, "state",
        grpc_connectivity_state_name(node->connectivity_state_),
        GRPC_JSON_STRING, false);
    if (node->referenced_tracer_ != nullptr) {
      char* uuid_str;
      gpr_asprintf(&uuid_str, "%" PRIdPTR,
                   node->referenced_tracer_->channel_uuid_);
      child = grpc_json_create_child(child, json, "uuid", uuid_str,
                                     GRPC_JSON_NUMBER, true);

      // If we are recursively populating everything, and this node
      // references a tracer we haven't seen yet, we render that tracer
      // in full, adding it to the parent JSON's "children" field.
      if (children && !TracerAlreadySeen(node->referenced_tracer_)) {
        grpc_json* referenced_tracer = grpc_json_create_child(
            nullptr, children, nullptr, nullptr, GRPC_JSON_OBJECT, false);
        AddSeenTracer(node->referenced_tracer_);
        ChannelTracer* saved = current_tracer_;
        current_tracer_ = node->referenced_tracer_;
        RecursivelyPopulateJson(referenced_tracer);
        current_tracer_ = saved;
      }
    }
  }

  // Tracks the current tracer we are rendering as we walk the tree of tracers.
  ChannelTracer* current_tracer_;

  // If true, we will render the data of all of this tracer's children.
  bool recursive_;

  // These members are used to track tracers we have already rendered. This is
  // a dynamically growing array that is deallocated when the rendering is done.
  ChannelTracer** seen_tracers_;
  size_t size_;
  size_t cap_;
};

char* ChannelTracer::RenderTrace(bool recursive) {
  if (!max_list_size_) return nullptr;  // tracing is disabled if max_nodes == 0
  ChannelTracerRenderer renderer(this, recursive);
  return renderer.Run();
}

char* ChannelTracer::GetChannelTraceFromUuid(intptr_t uuid, bool recursive) {
  void* object;
  grpc_object_registry_type type =
      grpc_object_registry_get_object(uuid, &object);
  GPR_ASSERT(type == GRPC_OBJECT_REGISTRY_CHANNEL_TRACER);
  return static_cast<ChannelTracer*>(object)->RenderTrace(recursive);
}

}  // namespace grpc_core
<|endoftext|>


<commit_before>// definition of necessary units
static const double cm=1;
static const double cm3=cm*cm*cm;
static const double volt=1;
static const double C=1; // Coulomb
static const double Qe=-1.6e-19*C; // eletron charge
static const double epsilon0=8.854187817e-14*C/volt/cm; // vacuum permittivity
// https://link.springer.com/chapter/10.1007/10832182_519
static const double epsilonGe=15.8; // Ge dielectric constant
//______________________________________________________________________________
// V"(x)=a, https://www.wolframalpha.com/input/?i=V%27%27(x)%3Da
double V(double *coordinates, double *parameters)
{
	double x = coordinates[0];  // there is no y and z dependence
	double x0= 0*cm;            // lower electrode
	double x1= parameters[0];   // upper electrode
	double v0= 0*volt;          // lower voltage
	double v1= parameters[1];   // upper voltage
	double rho=parameters[2]*Qe;// space charge density [C/cm3]

	double a =-rho/epsilon0/epsilonGe;
	double c2= (v1-v0)/(x1-x0) - a/2*(x1+x0);
	double c1= (v0*x1-v1*x0)/(x1-x0) + a/2*x0*x1;
	return a*x*x/2 + c2*x + c1;
}
//______________________________________________________________________________
// search for depletion voltage of a planar detector given impurity & thickness
double GetVdep(double impurity, double thickness, double vupper)
{
	if (impurity==0) return 0; // nothing to deplete

	TF1 *det=new TF1("det", V, 0, thickness, 3); // potential distr.
	double bias, vlower=0*volt; // range of search
	while (abs(vupper-vlower)>1e-3*volt) { // binary search
		bias=(vupper+vlower)/2; // bias voltage
		det->SetParameters(thickness, bias, impurity);
		if (det->Derivative(0)*det->Derivative(thickness)<0) vlower=bias;
		else vupper=bias;
	}
	return bias;
}
//______________________________________________________________________________
// draw results
void getVd(int type=1, double thickness=1*cm)
{
	const int n=10; // number of points
	double impurity[n]={1e9/cm3, 2e9/cm3, 4e9/cm3, 8e9/cm3, 1e10/cm3,
		2e10/cm3, 4e10/cm3, 8e10/cm3, 1e11/cm3, 1.2e11/cm3}; // p-type
	if (type==-1) for (int i=0; i<n; i++) impurity[i]*=type; // n-type
	double absi[n], vdep[n];
	for (int i=0; i<n; i++) {
		vdep[i] = GetVdep(impurity[i], thickness, type*-2e4*volt);
		absi[i] = abs(impurity[i]);
	}

	gROOT->SetStyle("Plain"); // pick up a good default drawing style
	// modify the default style
	gStyle->SetLegendBorderSize(0);
	gStyle->SetLegendFont(132);
	gStyle->SetLabelFont(132,"XY");
	gStyle->SetTitleFont(132,"XY");
	gStyle->SetLabelSize(0.05,"XY");
	gStyle->SetTitleSize(0.05,"XY");
	gStyle->SetTitleOffset(1.1,"XY");
	gStyle->SetPadRightMargin(0.01);
	gStyle->SetPadLeftMargin(0.11);
	gStyle->SetPadTopMargin(0.01);
	gStyle->SetPadBottomMargin(0.12);

	// Vdep VS impurity
	TGraph *g = new TGraph(n,absi,vdep);
	g->SetTitle(";Net Impurity [cm^{-3}];Depletion Voltage [V]");
	g->Draw("apc");
	TText *t1 = new TText(2e9, 6000, Form(
				"%.0f cm thick planar detector", thickness/cm));
	t1->Draw();
	gPad->SetLogx(); gPad->SetGridx(); gPad->SetGridy();
	gPad->Print("depleted.png");

	// voltage VS thickness
	TCanvas *c = new TCanvas;
	double bias = -1000*volt; // p-type
	if(type==-1) bias = 1000*volt; // n-type

	// over depleted
	TF1 *fvo=new TF1("fvo", V, 0, thickness, 3);
	fvo->SetParameters(thickness, vdep[6]+bias, impurity[6]);
	fvo->SetTitle(";Thickness [cm]; Voltage [V]");
	fvo->SetLineColor(kMagenta);
	fvo->SetLineStyle(2);
	fvo->GetXaxis()->SetTitleOffset(1.1);
	fvo->Draw();

	// depleted
	TF1 *fvd=new TF1("fvd", V, 0, thickness, 3);
	fvd->SetParameters(thickness, vdep[6], impurity[6]);
	fvd->Draw("same");

	// undepleted
	TF1 *fvu=new TF1("fvu", V, 0, thickness, 3);
	fvu->SetParameters(thickness, bias, impurity[6]);
	fvu->SetLineColor(kRed);
	fvu->SetLineStyle(3);
	fvu->Draw("same");

	// potential due to bias alone
	TF1 *fvb=new TF1("fvb", V, 0, thickness, 3);
	fvb->SetParameters(thickness, bias, 0/cm3);
	fvb->SetLineColor(kBlue);
	fvb->SetLineStyle(4);
	fvb->Draw("same");

	// potential due to space charges alone
	TF1 *fvc=new TF1("fvc", V, 0, thickness, 3);
	fvc->SetParameters(thickness, 0*volt, impurity[6]);
	fvc->SetLineColor(kGreen);
	fvc->SetLineStyle(5);
	fvc->Draw("same");

	if (type==-1) {
		// draw lines and texts for n-type
		TLine *l1 = new TLine(0,bias/volt,thickness/cm,bias/volt);
		l1->SetLineStyle(kDashed); l1->Draw();
		TLine *l2 = new TLine(0,vdep[6]/volt,thickness/cm,vdep[6]/volt);
		l2->SetLineStyle(kDashed); l2->Draw();
		TLine *l3=new TLine(0,(vdep[6]+bias)/volt,thickness/cm,(vdep[6]+bias)/volt);
		l3->SetLineStyle(kDashed); l3->Draw();
		TText *t2 = new TText(0.04,bias/volt+20,Form("%.0f V", bias/volt));
		t2->SetTextFont(132);
		t2->Draw();
		TText *t3 = new TText(0.04,vdep[6]/volt+20, Form("%.0f V", vdep[6]/volt));
		t3->SetTextFont(132);
		t3->Draw();
		TText *t4 = new TText(0.04,(vdep[6]+bias)/volt+20,
				Form("%.0f V", (vdep[6]+bias)/volt));
		t4->Draw();
		TText *t5 = new TText(0.5, 2800, "over depleted");
		t5->SetTextFont(132);
		t5->SetTextColor(kMagenta); t5->Draw();
		TText *t6 = new TText(0.8, 2310, "just depleted");
		t6->SetTextFont(132);
		t6->Draw();
		TText *t7 = new TText(0.65, 1250, "undepleted");
		t7->SetTextFont(132);
		t7->SetTextColor(kRed); t7->Draw();
		TText *t8 = new TText(0.65, 800, "bias alone");
		t8->SetTextFont(132);
		t8->SetTextColor(kBlue); t8->Draw();
		TText *t9 = new TText(0.55, 200, "space charges alone");
		t9->SetTextFont(132);
		t9->SetTextColor(kGreen); t9->Draw();
		TLatex *t10 = new TLatex(0.1, 2700,
				Form("Impurity: %.0e/cm^{3}",impurity[6]/cm3));
		t10->SetTextFont(132);
		t10->Draw();
	} else {
		// draw lines and texts for p-type
		TLine *l0 = new TLine(0,0,thickness/cm,0);
		l0->SetLineStyle(kDashed); l0->Draw();
		TLine *l1 = new TLine(0,bias/volt,thickness/cm,bias/volt);
		l1->SetLineStyle(kDashed); l1->Draw();
		TLine *l2 = new TLine(0,vdep[6]/volt,thickness/cm,vdep[6]/volt);
		l2->SetLineStyle(kDashed); l2->Draw();
		TLine *l3=new TLine(0,(vdep[6]+bias)/volt,thickness/cm,(vdep[6]+bias)/volt);
		l3->SetLineStyle(kDashed); l3->Draw();
		TText *t2 = new TText(0.04,bias/volt+20,Form("%.0f V", bias/volt));
		t2->SetTextFont(132);
		t2->Draw();
		TText *t3 = new TText(0.04,vdep[6]/volt+20, Form("%.0f V", vdep[6]/volt));
		t3->SetTextFont(132);
		t3->Draw();
		TText *t4 = new TText(0.04,(vdep[6]+bias)/volt+20,
				Form("%.0f V", (vdep[6]+bias)/volt));
		t4->SetTextFont(132);
		t4->Draw();
		TText *t5 = new TText(0.5, -3100, "over depleted");
		t5->SetTextFont(132);
		t5->SetTextColor(kMagenta); t5->Draw();
		TText *t6 = new TText(0.76, -2500, "just depleted");
		t6->SetTextFont(132);
		t6->Draw();
		TText *t7 = new TText(0.65, -1400, "undepleted");
		t7->SetTextFont(132);
		t7->SetTextColor(kRed); t7->Draw();
		TText *t8 = new TText(0.6, -900, "bias alone");
		t8->SetTextFont(132);
		t8->SetTextColor(kBlue); t8->Draw();
		TText *t9 = new TText(0.5, -200, "space charges alone");
		t9->SetTextFont(132);
		t9->SetTextColor(kGreen); t9->Draw();
		TLatex *t10 = new TLatex(0.1, -2700,
				Form("Impurity: %.0e/cm^{3}",impurity[6]/cm3));
		t10->SetTextFont(132);
		t10->Draw();
	}
   c->Print("undepleted.png");
}
<commit_msg>fine tuned text position<commit_after>// definition of necessary units
static const double cm=1;
static const double cm3=cm*cm*cm;
static const double volt=1;
static const double C=1; // Coulomb
static const double Qe=-1.6e-19*C; // eletron charge
static const double epsilon0=8.854187817e-14*C/volt/cm; // vacuum permittivity
// https://link.springer.com/chapter/10.1007/10832182_519
static const double epsilonGe=15.8; // Ge dielectric constant
//______________________________________________________________________________
// V"(x)=a, https://www.wolframalpha.com/input/?i=V%27%27(x)%3Da
double V(double *coordinates, double *parameters)
{
	double x = coordinates[0];  // there is no y and z dependence
	double x0= 0*cm;            // lower electrode
	double x1= parameters[0];   // upper electrode
	double v0= 0*volt;          // lower voltage
	double v1= parameters[1];   // upper voltage
	double rho=parameters[2]*Qe;// space charge density [C/cm3]

	double a =-rho/epsilon0/epsilonGe;
	double c2= (v1-v0)/(x1-x0) - a/2*(x1+x0);
	double c1= (v0*x1-v1*x0)/(x1-x0) + a/2*x0*x1;
	return a*x*x/2 + c2*x + c1;
}
//______________________________________________________________________________
// search for depletion voltage of a planar detector given impurity & thickness
double GetVdep(double impurity, double thickness, double vupper)
{
	if (impurity==0) return 0; // nothing to deplete

	TF1 *det=new TF1("det", V, 0, thickness, 3); // potential distr.
	double bias, vlower=0*volt; // range of search
	while (abs(vupper-vlower)>1e-3*volt) { // binary search
		bias=(vupper+vlower)/2; // bias voltage
		det->SetParameters(thickness, bias, impurity);
		if (det->Derivative(0)*det->Derivative(thickness)<0) vlower=bias;
		else vupper=bias;
	}
	return bias;
}
//______________________________________________________________________________
// draw results
void getVd(int type=1, double thickness=1*cm)
{
	const int n=10; // number of points
	double impurity[n]={1e9/cm3, 2e9/cm3, 4e9/cm3, 8e9/cm3, 1e10/cm3,
		2e10/cm3, 4e10/cm3, 8e10/cm3, 1e11/cm3, 1.2e11/cm3}; // p-type
	if (type==-1) for (int i=0; i<n; i++) impurity[i]*=type; // n-type
	double absi[n], vdep[n];
	for (int i=0; i<n; i++) {
		vdep[i] = GetVdep(impurity[i], thickness, type*-2e4*volt);
		absi[i] = abs(impurity[i]);
	}

	gROOT->SetStyle("Plain"); // pick up a good default drawing style to modify
	// modify the default style
	gStyle->SetLegendBorderSize(0);
	gStyle->SetLegendFont(132);
	gStyle->SetLabelFont(132,"XY");
	gStyle->SetTitleFont(132,"XY");
	gStyle->SetLabelSize(0.05,"XY");
	gStyle->SetTitleSize(0.05,"XY");
	gStyle->SetTitleOffset(1.1,"XY");
	gStyle->SetPadRightMargin(0.01);
	gStyle->SetPadLeftMargin(0.11);
	gStyle->SetPadTopMargin(0.01);
	gStyle->SetPadBottomMargin(0.12);

	// Vdep VS impurity
	TGraph *g = new TGraph(n,absi,vdep);
	g->SetTitle(";Net Impurity [cm^{-3}];Depletion Voltage [V]");
	g->Draw("apc");
	TText *t1 = new TText(2e9, 6000,
         Form("%.0f cm thick planar detector", thickness/cm));
	t1->Draw();
	gPad->SetLogx(); gPad->SetGridx(); gPad->SetGridy();
	gPad->Print("depleted.png");

	// voltage VS thickness
	double bias = -1000*volt*type;
   TCanvas *c = new TCanvas;

	// over depleted
	TF1 *fvo=new TF1("fvo", V, 0, thickness, 3);
	fvo->SetParameters(thickness, vdep[6]+bias, impurity[6]);
	fvo->SetTitle(";Thickness [cm]; Voltage [V]");
	fvo->SetLineColor(kMagenta);
	fvo->SetLineStyle(2);
	fvo->GetXaxis()->SetTitleOffset(1.1);
	fvo->Draw();

	// depleted
	TF1 *fvd=new TF1("fvd", V, 0, thickness, 3);
	fvd->SetParameters(thickness, vdep[6], impurity[6]);
	fvd->Draw("same");

	// undepleted
	TF1 *fvu=new TF1("fvu", V, 0, thickness, 3);
	fvu->SetParameters(thickness, bias, impurity[6]);
	fvu->SetLineColor(kRed);
	fvu->SetLineStyle(3);
	fvu->Draw("same");

	// potential due to bias alone
	TF1 *fvb=new TF1("fvb", V, 0, thickness, 3);
	fvb->SetParameters(thickness, bias, 0/cm3);
	fvb->SetLineColor(kBlue);
	fvb->SetLineStyle(4);
	fvb->Draw("same");

	// potential due to space charges alone
	TF1 *fvc=new TF1("fvc", V, 0, thickness, 3);
	fvc->SetParameters(thickness, 0*volt, impurity[6]);
	fvc->SetLineColor(kGreen);
	fvc->SetLineStyle(5);
	fvc->Draw("same");

	if (type==-1) { // draw lines and texts for n-type
		TLine *l1 = new TLine(0,bias/volt,thickness/cm,bias/volt);
		l1->SetLineStyle(kDashed); l1->Draw();
		TLine *l2 = new TLine(0,vdep[6]/volt,thickness/cm,vdep[6]/volt);
		l2->SetLineStyle(kDashed); l2->Draw();
		TLine *l3=new TLine(0,(vdep[6]+bias)/volt,thickness/cm,(vdep[6]+bias)/volt);
		l3->SetLineStyle(kDashed); l3->Draw();
		TText *t2 = new TText(0.04,bias/volt+20,Form("%.0f V", bias/volt));
		t2->SetTextFont(132); t2->Draw();
		TText *t3 = new TText(0.04,vdep[6]/volt+20, Form("%.0f V", vdep[6]/volt));
		t3->SetTextFont(132); t3->Draw();
		TText *t4 = new TText(0.04,(vdep[6]+bias)/volt+20,
				Form("%.0f V", (vdep[6]+bias)/volt));
		t4->Draw();
		TText *t5 = new TText(0.5, 2800, "over depleted");
		t5->SetTextFont(132); t5->SetTextColor(kMagenta); t5->Draw();
		TText *t6 = new TText(0.8, 2310, "just depleted");
		t6->SetTextFont(132); t6->Draw();
		TText *t7 = new TText(0.65, 1250, "undepleted");
		t7->SetTextFont(132); t7->SetTextColor(kRed); t7->Draw();
		TText *t8 = new TText(0.65, 800, "bias alone");
		t8->SetTextFont(132); t8->SetTextColor(kBlue); t8->Draw();
		TText *t9 = new TText(0.55, 200, "space charges alone");
		t9->SetTextFont(132); t9->SetTextColor(kGreen); t9->Draw();
		TLatex *t10 = new TLatex(0.1, 2700,
				Form("Impurity: %.0e/cm^{3}",impurity[6]/cm3));
		t10->SetTextFont(132); t10->Draw();
	} else { // draw lines and texts for p-type
		TLine *l0 = new TLine(0,0,thickness/cm,0);
		l0->SetLineStyle(kDashed); l0->Draw();
		TLine *l1 = new TLine(0,bias/volt,thickness/cm,bias/volt);
		l1->SetLineStyle(kDashed); l1->Draw();
		TLine *l2 = new TLine(0,vdep[6]/volt,thickness/cm,vdep[6]/volt);
		l2->SetLineStyle(kDashed); l2->Draw();
		TLine *l3=new TLine(0,(vdep[6]+bias)/volt,thickness/cm,(vdep[6]+bias)/volt);
		l3->SetLineStyle(kDashed); l3->Draw();
		TText *t2 = new TText(0.04,bias/volt+20,Form("%.0f V", bias/volt));
		t2->SetTextFont(132); t2->Draw();
		TText *t3 = new TText(0.04,vdep[6]/volt+20, Form("%.0f V", vdep[6]/volt));
		t3->SetTextFont(132); t3->Draw();
		TText *t4 = new TText(0.04,(vdep[6]+bias)/volt+20,
				Form("%.0f V", (vdep[6]+bias)/volt));
		t4->SetTextFont(132); t4->Draw();
		TText *t5 = new TText(0.76, -2850, "over depleted");
		t5->SetTextFont(132); t5->SetTextAngle(-19); t5->SetTextColor(kMagenta);
      t5->Draw();
		TText *t6 = new TText(0.8, -2120, "just depleted");
		t6->SetTextFont(132); t6->SetTextAngle(-9);  t6->Draw();
		TText *t7 = new TText(0.65, -1350, "undepleted");
		t7->SetTextFont(132); t7->SetTextColor(kRed); t7->Draw();
		TText *t8 = new TText(0.75, -700, "bias alone");
		t8->SetTextFont(132); t8->SetTextAngle(-11.5); t8->SetTextColor(kBlue);
      t8->Draw();
		TText *t9 = new TText(0.65, -450, "space charges alone");
		t9->SetTextFont(132); t9->SetTextAngle(12.5); t9->SetTextColor(kGreen);
      t9->Draw();
		TLatex *t10 = new TLatex(0.15, -2800,
				Form("Impurity: %.0e/cm^{3}",impurity[6]/cm3));
		t10->SetTextFont(132); t10->Draw();
	}
   c->Print("undepleted.png");
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ndole.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: kz $ $Date: 2004-10-04 18:59:21 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _NDOLE_HXX
#define _NDOLE_HXX

#ifndef _NDNOTXT_HXX
#include <ndnotxt.hxx>
#endif

#include <svtools/embedhlp.hxx>

class SwGrfFmtColl;
class SwDoc;
class SwOLENode;
class SwOLELink;
class SwOLELRUCache;

class SwOLEListener_Impl;
class SwOLEObj
{
    friend class SwOLENode;

    static SwOLELRUCache* pOLELRU_Cache;

    const SwOLENode* pOLENd;
    SwOLEListener_Impl* pListener;

    //Entweder Ref oder Name sind bekannt, wenn nur der Name bekannt ist, wird
    //dir Ref bei Anforderung durch GetOleRef() vom Sfx besorgt.
    svt::EmbeddedObjectRef xOLERef;
    //com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject > xOLERef;
    String aName;

    SwOLEObj( const SwOLEObj& rObj );   //nicht erlaubt.
    SwOLEObj();

    void SetNode( SwOLENode* pNode );

public:
    SwOLEObj( const svt::EmbeddedObjectRef& pObj );
    SwOLEObj( const String &rName );
    ~SwOLEObj();

    BOOL RemovedFromLRU();

    String GetDescription();

#ifndef _FESHVIEW_ONLY_INLINE_NEEDED
    com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject > GetOleRef();
    svt::EmbeddedObjectRef& GetObject();
//    const String &GetName() const { return aName; }
    const String& GetCurrentPersistName() const { return aName; }

    BOOL IsOleRef() const;  //Damit das Objekt nicht unnoetig geladen werden muss.
#endif
};

// --------------------
// SwOLENode
// --------------------

class SwOLENode: public SwNoTxtNode
{
    friend class SwNodes;
    mutable SwOLEObj aOLEObj;
    Graphic*    pGraphic;
    sal_Int64   nViewAspect;
    String sChartTblName;       // bei Chart Objecten: Name der ref. Tabelle
    BOOL   bOLESizeInvalid;     //Soll beim SwDoc::PrtOLENotify beruecksichtig
                                //werden (zum Beispiel kopiert). Ist nicht
                                //Persistent.

    SwOLENode(  const SwNodeIndex &rWhere,
                const svt::EmbeddedObjectRef&,
                SwGrfFmtColl *pGrfColl,
                SwAttrSet* pAutoAttr = 0 );

    SwOLENode(  const SwNodeIndex &rWhere,
                const String &rName,
                SwGrfFmtColl *pGrfColl,
                SwAttrSet* pAutoAttr = 0 );

    // aOLEObj besitzt einen privaten Copy-CTOR, wir brauchen auch einen:
    SwOLENode( const SwOLENode & );

public:
    const SwOLEObj& GetOLEObj() const { return aOLEObj; }
          SwOLEObj& GetOLEObj()       { return aOLEObj; }
    ~SwOLENode();

    virtual SwCntntNode *SplitNode( const SwPosition & );
        // steht in ndcopy.cxx
    virtual SwCntntNode* MakeCopy( SwDoc*, const SwNodeIndex& ) const;

    virtual Size GetTwipSize() const;
    Graphic* GetGraphic();
    void GetNewReplacement();

    virtual BOOL SavePersistentData();
    virtual BOOL RestorePersistentData();

    BOOL IsInGlobalDocSection() const;
    BOOL IsOLEObjectDeleted() const;

    BOOL IsOLESizeInvalid() const   { return bOLESizeInvalid; }
    void SetOLESizeInvalid( BOOL b ){ bOLESizeInvalid = b; }

    sal_Int64 GetAspect() const { return nViewAspect; }
    void SetAspect( sal_Int64 nAspect) { nViewAspect = nAspect; }

    // OLE-Object aus dem "Speicher" entfernen
    // inline void Unload() { aOLEObj.Unload(); }
    String GetDescription() const { return aOLEObj.GetDescription(); }

#ifndef _FESHVIEW_ONLY_INLINE_NEEDED
    const String& GetChartTblName() const       { return sChartTblName; }
    void SetChartTblName( const String& rNm )   { sChartTblName = rNm; }
#endif
};

// Inline Metoden aus Node.hxx - erst hier ist der TxtNode bekannt !!
inline SwOLENode *SwNode::GetOLENode()
{
     return ND_OLENODE == nNodeType ? (SwOLENode*)this : 0;
}
inline const SwOLENode *SwNode::GetOLENode() const
{
     return ND_OLENODE == nNodeType ? (const SwOLENode*)this : 0;
}

#endif  // _NDOLE_HXX

<commit_msg>INTEGRATION: CWS leanobjects (1.8.122); FILE MERGED 2004/11/18 11:08:20 mba 1.8.122.1: #i37278#: make objects loadable on demand<commit_after>/*************************************************************************
 *
 *  $RCSfile: ndole.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: rt $ $Date: 2004-11-26 16:25:39 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _NDOLE_HXX
#define _NDOLE_HXX

#ifndef _NDNOTXT_HXX
#include <ndnotxt.hxx>
#endif

#include <svtools/embedhlp.hxx>

class SwGrfFmtColl;
class SwDoc;
class SwOLENode;
class SwOLELink;

class SwOLEListener_Impl;
class SwOLEObj
{
    friend class SwOLENode;

    const SwOLENode* pOLENd;
    SwOLEListener_Impl* pListener;

    //Entweder Ref oder Name sind bekannt, wenn nur der Name bekannt ist, wird
    //dir Ref bei Anforderung durch GetOleRef() vom Sfx besorgt.
    svt::EmbeddedObjectRef xOLERef;
    String aName;

    SwOLEObj( const SwOLEObj& rObj );   //nicht erlaubt.
    SwOLEObj();

    void SetNode( SwOLENode* pNode );

public:
    SwOLEObj( const svt::EmbeddedObjectRef& pObj );
    SwOLEObj( const String &rName );
    ~SwOLEObj();

    BOOL UnloadObject();
    String GetDescription();

#ifndef _FESHVIEW_ONLY_INLINE_NEEDED
    com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject > GetOleRef();
    svt::EmbeddedObjectRef& GetObject();
    const String& GetCurrentPersistName() const { return aName; }
    BOOL IsOleRef() const;  //Damit das Objekt nicht unnoetig geladen werden muss.
#endif
};

// --------------------
// SwOLENode
// --------------------

class SwOLENode: public SwNoTxtNode
{
    friend class SwNodes;
    mutable SwOLEObj aOLEObj;
    Graphic*    pGraphic;
    sal_Int64   nViewAspect;
    String sChartTblName;       // bei Chart Objecten: Name der ref. Tabelle
    BOOL   bOLESizeInvalid;     //Soll beim SwDoc::PrtOLENotify beruecksichtig
                                //werden (zum Beispiel kopiert). Ist nicht
                                //Persistent.

    SwOLENode(  const SwNodeIndex &rWhere,
                const svt::EmbeddedObjectRef&,
                SwGrfFmtColl *pGrfColl,
                SwAttrSet* pAutoAttr = 0 );

    SwOLENode(  const SwNodeIndex &rWhere,
                const String &rName,
                SwGrfFmtColl *pGrfColl,
                SwAttrSet* pAutoAttr = 0 );

    // aOLEObj besitzt einen privaten Copy-CTOR, wir brauchen auch einen:
    SwOLENode( const SwOLENode & );

public:
    const SwOLEObj& GetOLEObj() const { return aOLEObj; }
          SwOLEObj& GetOLEObj()       { return aOLEObj; }
    ~SwOLENode();

    virtual SwCntntNode *SplitNode( const SwPosition & );
        // steht in ndcopy.cxx
    virtual SwCntntNode* MakeCopy( SwDoc*, const SwNodeIndex& ) const;

    virtual Size GetTwipSize() const;
    Graphic* GetGraphic();
    void GetNewReplacement();

    virtual BOOL SavePersistentData();
    virtual BOOL RestorePersistentData();

    BOOL IsInGlobalDocSection() const;
    BOOL IsOLEObjectDeleted() const;

    BOOL IsOLESizeInvalid() const   { return bOLESizeInvalid; }
    void SetOLESizeInvalid( BOOL b ){ bOLESizeInvalid = b; }

    sal_Int64 GetAspect() const { return nViewAspect; }
    void SetAspect( sal_Int64 nAspect) { nViewAspect = nAspect; }

    // OLE-Object aus dem "Speicher" entfernen
    // inline void Unload() { aOLEObj.Unload(); }
    String GetDescription() const { return aOLEObj.GetDescription(); }

#ifndef _FESHVIEW_ONLY_INLINE_NEEDED
    const String& GetChartTblName() const       { return sChartTblName; }
    void SetChartTblName( const String& rNm )   { sChartTblName = rNm; }
#endif
};

// Inline Metoden aus Node.hxx - erst hier ist der TxtNode bekannt !!
inline SwOLENode *SwNode::GetOLENode()
{
     return ND_OLENODE == nNodeType ? (SwOLENode*)this : 0;
}
inline const SwOLENode *SwNode::GetOLENode() const
{
     return ND_OLENODE == nNodeType ? (const SwOLENode*)this : 0;
}

#endif  // _NDOLE_HXX

<|endoftext|>