<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: treeactions.hxx,v $
 * $Revision: 1.17 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _CONFIGMGR_TREEACTIONS_HXX_
#define _CONFIGMGR_TREEACTIONS_HXX_

#include "change.hxx"

#ifndef INCLUDED_VECTOR
#include <vector>
#define INCLUDED_VECTOR
#endif

//..........................................................................
namespace configmgr
{
//-----------------------------------------------------------------------------

// helper to implement force-writable support
void forceWritable(INode& _rNode);
void forceWritable(data::TreeAccessor const & _aTree);

//==========================================================================
//= OChangeActionCounter
//==========================================================================
/** collects meta data about a changes tree
*/
struct OChangeActionCounter : public ChangeTreeAction
{
    sal_Int32       nValues, nAdds, nRemoves;

    OChangeActionCounter() :nValues(0), nAdds(0), nRemoves(0) {}

    virtual void handle(ValueChange const& aValueNode);
    virtual void handle(AddNode const& aAddNode);
    virtual void handle(RemoveNode const& aRemoveNode);
    virtual void handle(SubtreeChange const& aSubtree);

    sal_Bool hasChanges() const {return nValues || nAdds || nRemoves;}
};

// ===================================================================
// = CollectNames
// ===================================================================
class CollectNames :  public NodeAction
{
public:
    typedef std::vector<OUString> NameList;

public:
    NameList const& list() const { return aList; }

    CollectNames() : aList() {}

    void handle(ValueNode const& aValue)    { add(aValue); }
    void handle(ISubtree const&  m_aSubtree)    { add(m_aSubtree); }

    void add(INode const& aNode)
    {
        aList.push_back(aNode.getName());
    }
private:
    NameList aList;
};

//..........................................................................
}   // namespace configmgr
//..........................................................................

#endif // _CONFIGMGR_TREEACTIONS_HXX_

<commit_msg>INTEGRATION: CWS sb88 (1.17.10); FILE MERGED 2008/06/03 15:29:49 sb 1.17.10.1: #i89553 applied patch by cmc<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: treeactions.hxx,v $
 * $Revision: 1.18 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _CONFIGMGR_TREEACTIONS_HXX_
#define _CONFIGMGR_TREEACTIONS_HXX_

#include "change.hxx"

#ifndef INCLUDED_VECTOR
#include <vector>
#define INCLUDED_VECTOR
#endif

//..........................................................................
namespace configmgr
{
//-----------------------------------------------------------------------------

//==========================================================================
//= OChangeActionCounter
//==========================================================================
/** collects meta data about a changes tree
*/
struct OChangeActionCounter : public ChangeTreeAction
{
    sal_Int32       nValues, nAdds, nRemoves;

    OChangeActionCounter() :nValues(0), nAdds(0), nRemoves(0) {}

    virtual void handle(ValueChange const& aValueNode);
    virtual void handle(AddNode const& aAddNode);
    virtual void handle(RemoveNode const& aRemoveNode);
    virtual void handle(SubtreeChange const& aSubtree);

    sal_Bool hasChanges() const {return nValues || nAdds || nRemoves;}
};

// ===================================================================
// = CollectNames
// ===================================================================
class CollectNames :  public NodeAction
{
public:
    typedef std::vector<OUString> NameList;

public:
    NameList const& list() const { return aList; }

    CollectNames() : aList() {}

    void handle(ValueNode const& aValue)    { add(aValue); }
    void handle(ISubtree const&  m_aSubtree)    { add(m_aSubtree); }

    void add(INode const& aNode)
    {
        aList.push_back(aNode.getName());
    }
private:
    NameList aList;
};

//..........................................................................
}   // namespace configmgr
//..........................................................................

#endif // _CONFIGMGR_TREEACTIONS_HXX_

<|endoftext|>


<commit_before><commit_msg>Reduce number of iterations on TimeTicks.Deltas test so that unittests run faster.<commit_after><|endoftext|>


<commit_before>/*******************************************************************
Qt extended Library
Copyright (C) 2007 J-P Nurmi <jpnurmi@gmail.com>
released under the Terms of LGPL (see the LICENSE file)
*******************************************************************/

#include "QxtStringSpinBox.h"

class QxtStringSpinBoxPrivate : public QxtPrivate<QxtStringSpinBox>
{
public:
	QXT_DECLARE_PUBLIC(QxtStringSpinBox);
	int startsWith(const QString& start, QString& string) const;
	QStringList strings;
};

int QxtStringSpinBoxPrivate::startsWith(const QString& start, QString& string) const
{
	const int size = strings.size();
	for (int i = 0; i < size; ++i)
	{
		if (strings.at(i).startsWith(start, Qt::CaseInsensitive))
		{
			// found
			string = strings.at(i);
			return i;
		}
	}
	// not found
	return -1;
}

/*!
    \class QxtStringSpinBox QxtStringSpinBox
    \ingroup gui
    \brief A spin box with string items.

    QxtStringSpinBox is spin box that takes strings. QxtStringSpinBox allows
    the user to choose a value by clicking the up and down buttons or by
    pressing Up or Down on the keyboard to increase or decrease the value
    currently displayed. The user can also type the value in manually.
 */

/*!
    Constructs a new QxtStringSpinBox with \a parent.
 */
QxtStringSpinBox::QxtStringSpinBox(QWidget* pParent) : QSpinBox(pParent)
{
	setRange(0, 0);
}

/*!
    Destructs the spin box.
 */
QxtStringSpinBox::~QxtStringSpinBox()
{
}

/*!
    \property QxtStringSpinBox::strings
    \brief This property holds the string items of the spin box.
 */
const QStringList& QxtStringSpinBox::strings() const
{
	return qxt_d().strings;
}

void QxtStringSpinBox::setStrings(const QStringList& strings)
{
	qxt_d().strings = strings;
	setRange(0, strings.size() - 1);
}

void QxtStringSpinBox::fixup(QString& input) const
{
	// just attempt to change the input string to be valid according to the string list
	// no need to result in a valid string, callers of this function are responsible to
	// re-test the validity afterwards

	// try finding a string from the list which starts with input
	input = input.simplified();
	if (!input.isEmpty())
	{
		qxt_d().startsWith(input, input);
	}
}

QValidator::State QxtStringSpinBox::validate(QString& input, int& pos) const
{
	// Invalid:		input is invalid according to the string list
	// Intermediate:	it is likely that a little more editing will make the input acceptable
	//			(e.g. the user types "A" and stringlist contains "ABC")
	// Acceptable:		the input is valid.
	Q_UNUSED(pos);
	QString temp;
	QValidator::State state = QValidator::Invalid;
	if (qxt_d().strings.contains(input))
	{
		// exact match
		state = QValidator::Acceptable;
	}
	else if (input.isEmpty() || qxt_d().startsWith(input, temp) != -1)
	{
		// still empty or some string in the list starts with input
		state = QValidator::Intermediate;
	}
	// else invalid
	return state;
}

QString QxtStringSpinBox::textFromValue(int value) const
{
	Q_ASSERT(value >= 0 && value < qxt_d().strings.size());
	return qxt_d().strings.isEmpty() ? QLatin1String("") : qxt_d().strings.at(value);
}

int QxtStringSpinBox::valueFromText(const QString& text) const
{
	return qxt_d().strings.indexOf(text);
}
<commit_msg>Fixed the assertion in QxtStringSpinBox::textFromValue().<commit_after>/*******************************************************************
Qt extended Library
Copyright (C) 2007 J-P Nurmi <jpnurmi@gmail.com>
released under the Terms of LGPL (see the LICENSE file)
*******************************************************************/

#include "QxtStringSpinBox.h"

class QxtStringSpinBoxPrivate : public QxtPrivate<QxtStringSpinBox>
{
public:
	QXT_DECLARE_PUBLIC(QxtStringSpinBox);
	int startsWith(const QString& start, QString& string) const;
	QStringList strings;
};

int QxtStringSpinBoxPrivate::startsWith(const QString& start, QString& string) const
{
	const int size = strings.size();
	for (int i = 0; i < size; ++i)
	{
		if (strings.at(i).startsWith(start, Qt::CaseInsensitive))
		{
			// found
			string = strings.at(i);
			return i;
		}
	}
	// not found
	return -1;
}

/*!
    \class QxtStringSpinBox QxtStringSpinBox
    \ingroup gui
    \brief A spin box with string items.

    QxtStringSpinBox is spin box that takes strings. QxtStringSpinBox allows
    the user to choose a value by clicking the up and down buttons or by
    pressing Up or Down on the keyboard to increase or decrease the value
    currently displayed. The user can also type the value in manually.
 */

/*!
    Constructs a new QxtStringSpinBox with \a parent.
 */
QxtStringSpinBox::QxtStringSpinBox(QWidget* pParent) : QSpinBox(pParent)
{
	setRange(0, 0);
}

/*!
    Destructs the spin box.
 */
QxtStringSpinBox::~QxtStringSpinBox()
{
}

/*!
    \property QxtStringSpinBox::strings
    \brief This property holds the string items of the spin box.
 */
const QStringList& QxtStringSpinBox::strings() const
{
	return qxt_d().strings;
}

void QxtStringSpinBox::setStrings(const QStringList& strings)
{
	qxt_d().strings = strings;
	setRange(0, strings.size() - 1);
}

void QxtStringSpinBox::fixup(QString& input) const
{
	// just attempt to change the input string to be valid according to the string list
	// no need to result in a valid string, callers of this function are responsible to
	// re-test the validity afterwards

	// try finding a string from the list which starts with input
	input = input.simplified();
	if (!input.isEmpty())
	{
		qxt_d().startsWith(input, input);
	}
}

QValidator::State QxtStringSpinBox::validate(QString& input, int& pos) const
{
	// Invalid:		input is invalid according to the string list
	// Intermediate:	it is likely that a little more editing will make the input acceptable
	//			(e.g. the user types "A" and stringlist contains "ABC")
	// Acceptable:		the input is valid.
	Q_UNUSED(pos);
	QString temp;
	QValidator::State state = QValidator::Invalid;
	if (qxt_d().strings.contains(input))
	{
		// exact match
		state = QValidator::Acceptable;
	}
	else if (input.isEmpty() || qxt_d().startsWith(input, temp) != -1)
	{
		// still empty or some string in the list starts with input
		state = QValidator::Intermediate;
	}
	// else invalid
	return state;
}

QString QxtStringSpinBox::textFromValue(int value) const
{
	Q_ASSERT(qxt_d().strings.isEmpty() || (value >= 0 && value < qxt_d().strings.size()));
	return qxt_d().strings.isEmpty() ? QLatin1String("") : qxt_d().strings.at(value);
}

int QxtStringSpinBox::valueFromText(const QString& text) const
{
	return qxt_d().strings.indexOf(text);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "Benchmark.h"
#include "Resources.h"
#include "SkBitmap.h"
#include "SkJpegEncoder.h"
#include "SkPngEncoder.h"
#include "SkWebpEncoder.h"
#include "SkStream.h"

class EncodeBench : public Benchmark {
public:
    using Encoder = bool (*)(SkWStream*, const SkPixmap&);
    EncodeBench(const char* filename, Encoder encoder, const char* encoderName)
        : fSourceFilename(filename)
        , fEncoder(encoder)
        , fName(SkStringPrintf("Encode_%s_%s", filename, encoderName)) {}

    bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }

    const char* onGetName() override { return fName.c_str(); }

    void onPreDraw(SkCanvas*) override {
        SkAssertResult(GetResourceAsBitmap(fSourceFilename, &fBitmap));
    }

    void onDraw(int loops, SkCanvas*) override {
        while (loops-- > 0) {
            SkPixmap pixmap;
            SkAssertResult(fBitmap.peekPixels(&pixmap));
            SkNullWStream dst;
            SkAssertResult(fEncoder(&dst, pixmap));
            SkASSERT(dst.bytesWritten() > 0);
        }
    }

private:
    const char* fSourceFilename;
    Encoder     fEncoder;
    SkString    fName;
    SkBitmap    fBitmap;
};

static bool encode_jpeg(SkWStream* dst, const SkPixmap& src) {
    SkJpegEncoder::Options opts;
    opts.fQuality = 90;
    return SkJpegEncoder::Encode(dst, src, opts);
}

static bool encode_webp_lossy(SkWStream* dst, const SkPixmap& src) {
    SkWebpEncoder::Options opts;
    opts.fCompression = SkWebpEncoder::Compression::kLossy;
    opts.fQuality = 90;
    return SkWebpEncoder::Encode(dst, src, opts);
}

static bool encode_webp_lossless(SkWStream* dst, const SkPixmap& src) {
    SkWebpEncoder::Options opts;
    opts.fCompression = SkWebpEncoder::Compression::kLossless;
    opts.fQuality = 90;
    return SkWebpEncoder::Encode(dst, src, opts);
}

static bool encode_png(SkWStream* dst,
                       const SkPixmap& src,
                       SkPngEncoder::FilterFlag filters,
                       int zlibLevel) {
    SkPngEncoder::Options opts;
    opts.fFilterFlags = filters;
    opts.fZLibLevel = zlibLevel;
    return SkPngEncoder::Encode(dst, src, opts);
}

#define PNG(FLAG, ZLIBLEVEL) [](SkWStream* d, const SkPixmap& s) { \
           return encode_png(d, s, SkPngEncoder::FilterFlag::FLAG, ZLIBLEVEL); }

static const char* srcs[2] = {"images/mandrill_512.png", "images/color_wheel.jpg"};

// The Android Photos app uses a quality of 90 on JPEG encodes
DEF_BENCH(return new EncodeBench(srcs[0], &encode_jpeg, "JPEG"));
DEF_BENCH(return new EncodeBench(srcs[1], &encode_jpeg, "JPEG"));

// TODO: What is the appropriate quality to use to benchmark WEBP encodes?
DEF_BENCH(return new EncodeBench(srcs[0], encode_webp_lossy, "WEBP"));
DEF_BENCH(return new EncodeBench(srcs[1], encode_webp_lossy, "WEBP"));

DEF_BENCH(return new EncodeBench(srcs[0], encode_webp_lossless, "WEBP_LL"));
DEF_BENCH(return new EncodeBench(srcs[1], encode_webp_lossless, "WEBP_LL"));

DEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 6), "PNG"));
DEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 3), "PNG_3"));
DEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 1), "PNG_1"));

DEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 6), "PNG_6s"));
DEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 3), "PNG_3s"));
DEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 1), "PNG_1s"));

DEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 6), "PNG_6n"));
DEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 3), "PNG_3n"));
DEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 1), "PNG_1n"));

DEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 6), "PNG"));
DEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 3), "PNG_3"));
DEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 1), "PNG_1"));

DEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 6), "PNG_6s"));
DEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 3), "PNG_3s"));
DEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 1), "PNG_1s"));

DEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 6), "PNG_6n"));
DEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 3), "PNG_3n"));
DEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 1), "PNG_1n"));

#undef PNG
<commit_msg>Have EncodeBench avoid superfluous setup<commit_after>/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "Benchmark.h"
#include "Resources.h"
#include "SkBitmap.h"
#include "SkJpegEncoder.h"
#include "SkPngEncoder.h"
#include "SkWebpEncoder.h"
#include "SkStream.h"

class EncodeBench : public Benchmark {
public:
    using Encoder = bool (*)(SkWStream*, const SkPixmap&);
    EncodeBench(const char* filename, Encoder encoder, const char* encoderName)
        : fSourceFilename(filename)
        , fEncoder(encoder)
        , fName(SkStringPrintf("Encode_%s_%s", filename, encoderName)) {}

    bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }

    const char* onGetName() override { return fName.c_str(); }

    void onDelayedSetup() override {
        SkAssertResult(GetResourceAsBitmap(fSourceFilename, &fBitmap));
    }

    void onDraw(int loops, SkCanvas*) override {
        while (loops-- > 0) {
            SkPixmap pixmap;
            SkAssertResult(fBitmap.peekPixels(&pixmap));
            SkNullWStream dst;
            SkAssertResult(fEncoder(&dst, pixmap));
            SkASSERT(dst.bytesWritten() > 0);
        }
    }

private:
    const char* fSourceFilename;
    Encoder     fEncoder;
    SkString    fName;
    SkBitmap    fBitmap;
};

static bool encode_jpeg(SkWStream* dst, const SkPixmap& src) {
    SkJpegEncoder::Options opts;
    opts.fQuality = 90;
    return SkJpegEncoder::Encode(dst, src, opts);
}

static bool encode_webp_lossy(SkWStream* dst, const SkPixmap& src) {
    SkWebpEncoder::Options opts;
    opts.fCompression = SkWebpEncoder::Compression::kLossy;
    opts.fQuality = 90;
    return SkWebpEncoder::Encode(dst, src, opts);
}

static bool encode_webp_lossless(SkWStream* dst, const SkPixmap& src) {
    SkWebpEncoder::Options opts;
    opts.fCompression = SkWebpEncoder::Compression::kLossless;
    opts.fQuality = 90;
    return SkWebpEncoder::Encode(dst, src, opts);
}

static bool encode_png(SkWStream* dst,
                       const SkPixmap& src,
                       SkPngEncoder::FilterFlag filters,
                       int zlibLevel) {
    SkPngEncoder::Options opts;
    opts.fFilterFlags = filters;
    opts.fZLibLevel = zlibLevel;
    return SkPngEncoder::Encode(dst, src, opts);
}

#define PNG(FLAG, ZLIBLEVEL) [](SkWStream* d, const SkPixmap& s) { \
           return encode_png(d, s, SkPngEncoder::FilterFlag::FLAG, ZLIBLEVEL); }

static const char* srcs[2] = {"images/mandrill_512.png", "images/color_wheel.jpg"};

// The Android Photos app uses a quality of 90 on JPEG encodes
DEF_BENCH(return new EncodeBench(srcs[0], &encode_jpeg, "JPEG"));
DEF_BENCH(return new EncodeBench(srcs[1], &encode_jpeg, "JPEG"));

// TODO: What is the appropriate quality to use to benchmark WEBP encodes?
DEF_BENCH(return new EncodeBench(srcs[0], encode_webp_lossy, "WEBP"));
DEF_BENCH(return new EncodeBench(srcs[1], encode_webp_lossy, "WEBP"));

DEF_BENCH(return new EncodeBench(srcs[0], encode_webp_lossless, "WEBP_LL"));
DEF_BENCH(return new EncodeBench(srcs[1], encode_webp_lossless, "WEBP_LL"));

DEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 6), "PNG"));
DEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 3), "PNG_3"));
DEF_BENCH(return new EncodeBench(srcs[0], PNG(kAll, 1), "PNG_1"));

DEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 6), "PNG_6s"));
DEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 3), "PNG_3s"));
DEF_BENCH(return new EncodeBench(srcs[0], PNG(kSub, 1), "PNG_1s"));

DEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 6), "PNG_6n"));
DEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 3), "PNG_3n"));
DEF_BENCH(return new EncodeBench(srcs[0], PNG(kNone, 1), "PNG_1n"));

DEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 6), "PNG"));
DEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 3), "PNG_3"));
DEF_BENCH(return new EncodeBench(srcs[1], PNG(kAll, 1), "PNG_1"));

DEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 6), "PNG_6s"));
DEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 3), "PNG_3s"));
DEF_BENCH(return new EncodeBench(srcs[1], PNG(kSub, 1), "PNG_1s"));

DEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 6), "PNG_6n"));
DEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 3), "PNG_3n"));
DEF_BENCH(return new EncodeBench(srcs[1], PNG(kNone, 1), "PNG_1n"));

#undef PNG
<|endoftext|>


<commit_before>#include "from_json.h"

#include <asdf_multiplat/utilities/utilities.h>
#include <asdf_multiplat/utilities/cjson_utils.hpp>

using namespace asdf;
using namespace asdf::util;

namespace tired_of_build_issues
{
    std::string read_text_file(std::string const& filepath) {
        //if(!is_file(filepath))
        //{
        //    //throw file_open_exception(filepath);
        //    EXPLODE("C'est une probleme");
        //}

        std::string outputstring;
        std::ifstream ifs(filepath, std::ifstream::in);
        ifs.exceptions( std::ios::failbit );

        // ASSERT(ifs.good(), "Error loading text file %s", filepath.c_str());
        if(!ifs.good())
        {
            //throw file_open_exception(filepath);
            EXPLODE("C'est une probleme");
        }

        ifs.seekg(0, std::ios::end);		//seek to the end to get the size the output string should be
        outputstring.reserve(size_t(ifs.tellg()));	//reserve necessary memory up front
        ifs.seekg(0, std::ios::beg);		//seek back to the start

        outputstring.assign((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

        ifs.close();

        return outputstring;
    }
}

// global root_json_dir is used for resolving relative filepaths
// when including other json files as node properties / values
// I should probably devise a better method of doing this, since
// I don't think this will handle more than one level of inclusion
// if the JSON files are not all in the same directory
stdfs::path root_json_dir;

namespace plantgen
{
    bool str_eq(char const* a, char const* b)
    {
        return strcmp(a, b) == 0;
    }

    std::vector<std::string> value_string_list_from_json_array(cJSON* json_array)
    {
        ASSERT(json_array, "");
        ASSERT(json_array->type == cJSON_Array, "json_array is not actually a JSON array");
        std::vector<std::string> values;

        cJSON* j = json_array->child;
        while(j)
        {
            ASSERT(j->type == cJSON_String, "Expected a JSON string");
            values.emplace_back(j->valuestring);
            j = j->next;
        }

        return values;
    }

    multi_value_t multi_value_from_json(cJSON* json)
    {
        ASSERT(str_eq(json->child->string, "Multi"), "Expected a \"Multi\" json_obj");
        ASSERT(json->child->type == cJSON_Number, "JSON Value of \"Multi\" should be an integer");

        multi_value_t v;
        v.num_to_pick = json->child->valueint;
        v.values = std::move(value_string_list_from_json_array(json->child->next));

        return v;
    }

    range_value_t range_value_from_json(cJSON* json)
    {
        ASSERT(str_eq(json->string, "Range"), "Expected a \"Range\" json_obj");
        return value_string_list_from_json_array(json);
    }

    variant_value_t value_type_from_json(cJSON* json)
    {
        if(json->type == cJSON_String)
        {
            return std::string(json->valuestring);
        }
        else if(!json->child)
        {
            EXPLODE("invalid value object %s", json->string);
            return null_value_t();
        }
        else if(str_eq(json->child->string, "Multi"))
        {
            return multi_value_from_json(json);
        }
        else if(str_eq(json->child->string, "Range"))
        {
            return range_value_from_json(json->child);
        }
        else
        {
            EXPLODE("unrecognized value object %s", json->child->string);
            return variant_value_t(null_value_t());
        }
    }

    pregen_node_t node_from_json(cJSON* json_node)
    {
        pregen_node_t node;
        node.name = std::string(CJSON_STR(json_node, Name));

        cJSON* cur_child = json_node->child;
        while(cur_child)
        {
            if(str_eq(cur_child->string, "Properties"))
            {
                cJSON* property_json = cur_child->child;
                while(property_json)
                {
                    node.add_child(node_from_json(property_json));
                    property_json = property_json->next;
                }
            }
            else if(str_eq(cur_child->string, "Values"))
            {
                cJSON* value_json = cur_child->child;
                while(value_json)
                {
                    // if the value is a node, load it differently
                    // since we can't return a node as part of the variant

                    //if the value is an object starting with a child named "Name", it's a node
                    if(value_json->type == cJSON_Object
                    && value_json->child
                    && str_eq(value_json->child->string, "Name"))
                    {
                        node.value_nodes.push_back(std::move(node_from_json(value_json)));
                    }
                    else
                    {
                        node.values.push_back(std::move(value_type_from_json(value_json)));
                    }

                    value_json = value_json->next;
                }
            }
            else if(str_eq(cur_child->string, "Include"))
            {
                ASSERT(cur_child->type == cJSON_String, "Include filepath must be a string");
                stdfs::path relpath(cur_child->valuestring);

                //get path relative to this executable by using parent path
                //of the original json doc
                stdfs::path fullpath = root_json_dir.parent_path() / relpath;

                node.add_child(node_from_json(fullpath));
            }

            cur_child = cur_child->next;
        }

        return node;
    }

    pregen_node_t node_from_json(stdfs::path const& filepath)
    {
        //std::string json_str = asdf::util::read_text_file(filepath);
        std::string json_str = tired_of_build_issues::read_text_file(filepath.string());
        cJSON* json_root = cJSON_Parse(json_str.c_str());

        if(!json_root)
        {
            EXPLODE( "Error parsing JSON");
            return pregen_node_t{};
        }

        auto root = node_from_json(json_root);

        cJSON_Delete(json_root);

        return root;
    }

    generated_node_t generate_node_from_json(stdfs::path const& filepath)
    {
        // global root_json_dir is used for resolving relative filepaths
        // when including other json files as node properties / values
        root_json_dir = filepath;
        auto node = node_from_json(filepath);
        return generate_node(node);
    }

}<commit_msg>switched from a single path to a stack of paths for keeping track of relative paths when including files (I still want to get rid of it being a global variable)<commit_after>#include "from_json.h"

#include <stack>

#include <asdf_multiplat/utilities/utilities.h>
#include <asdf_multiplat/utilities/cjson_utils.hpp>

using namespace asdf;
using namespace asdf::util;

namespace tired_of_build_issues
{
    std::string read_text_file(std::string const& filepath) {
        //if(!is_file(filepath))
        //{
        //    //throw file_open_exception(filepath);
        //    EXPLODE("C'est une probleme");
        //}

        std::string outputstring;
        std::ifstream ifs(filepath, std::ifstream::in);
        ifs.exceptions( std::ios::failbit );

        // ASSERT(ifs.good(), "Error loading text file %s", filepath.c_str());
        if(!ifs.good())
        {
            //throw file_open_exception(filepath);
            EXPLODE("C'est une probleme");
        }

        ifs.seekg(0, std::ios::end);		//seek to the end to get the size the output string should be
        outputstring.reserve(size_t(ifs.tellg()));	//reserve necessary memory up front
        ifs.seekg(0, std::ios::beg);		//seek back to the start

        outputstring.assign((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

        ifs.close();

        return outputstring;
    }
}

// global stack used for resolving relative filepaths
// when including other json files as node properties / values
// I should probably devise a better method of doing this, since
// I don't think this will handle more than one level of inclusion
// if the JSON files are not all in the same directory

//FIXME make this not global
std::stack<stdfs::path> include_dir_stack;

namespace plantgen
{
    bool str_eq(char const* a, char const* b)
    {
        return strcmp(a, b) == 0;
    }

    std::vector<std::string> value_string_list_from_json_array(cJSON* json_array)
    {
        ASSERT(json_array, "");
        ASSERT(json_array->type == cJSON_Array, "json_array is not actually a JSON array");
        std::vector<std::string> values;

        cJSON* j = json_array->child;
        while(j)
        {
            ASSERT(j->type == cJSON_String, "Expected a JSON string");
            values.emplace_back(j->valuestring);
            j = j->next;
        }

        return values;
    }

    multi_value_t multi_value_from_json(cJSON* json)
    {
        ASSERT(str_eq(json->child->string, "Multi"), "Expected a \"Multi\" json_obj");
        ASSERT(json->child->type == cJSON_Number, "JSON Value of \"Multi\" should be an integer");

        multi_value_t v;
        v.num_to_pick = json->child->valueint;
        v.values = std::move(value_string_list_from_json_array(json->child->next));

        return v;
    }

    range_value_t range_value_from_json(cJSON* json)
    {
        ASSERT(str_eq(json->string, "Range"), "Expected a \"Range\" json_obj");
        return value_string_list_from_json_array(json);
    }

    variant_value_t value_type_from_json(cJSON* json)
    {
        if(json->type == cJSON_String)
        {
            return std::string(json->valuestring);
        }
        else if(!json->child)
        {
            EXPLODE("invalid value object %s", json->string);
            return null_value_t();
        }
        else if(str_eq(json->child->string, "Multi"))
        {
            return multi_value_from_json(json);
        }
        else if(str_eq(json->child->string, "Range"))
        {
            return range_value_from_json(json->child);
        }
        else
        {
            EXPLODE("unrecognized value object %s", json->child->string);
            return variant_value_t(null_value_t());
        }
    }

    pregen_node_t node_from_json(cJSON* json_node)
    {
        pregen_node_t node;
        node.name = std::string(CJSON_STR(json_node, Name));

        cJSON* cur_child = json_node->child;
        while(cur_child)
        {
            if(str_eq(cur_child->string, "Properties"))
            {
                cJSON* property_json = cur_child->child;
                while(property_json)
                {
                    node.add_child(node_from_json(property_json));
                    property_json = property_json->next;
                }
            }
            else if(str_eq(cur_child->string, "Values"))
            {
                cJSON* value_json = cur_child->child;
                while(value_json)
                {
                    // if the value is a node, load it differently
                    // since we can't return a node as part of the variant

                    //if the value is an object starting with a child named "Name", it's a node
                    if(value_json->type == cJSON_Object
                    && value_json->child
                    && str_eq(value_json->child->string, "Name"))
                    {
                        node.value_nodes.push_back(std::move(node_from_json(value_json)));
                    }
                    else
                    {
                        node.values.push_back(std::move(value_type_from_json(value_json)));
                    }

                    value_json = value_json->next;
                }
            }
            else if(str_eq(cur_child->string, "Include"))
            {
                ASSERT(cur_child->type == cJSON_String, "Include filepath must be a string");
                stdfs::path relpath(cur_child->valuestring);

                // get path relative to this executable by using parent path
                // of the current json doc
                auto TEST = include_dir_stack.top();
                auto parent_path = include_dir_stack.top().parent_path();
                stdfs::path fullpath = parent_path / relpath;

                node.add_child(node_from_json(fullpath));
            }

            cur_child = cur_child->next;
        }

        return node;
    }

    pregen_node_t node_from_json(stdfs::path const& filepath)
    {
        //std::string json_str = asdf::util::read_text_file(filepath);
        std::string json_str = tired_of_build_issues::read_text_file(filepath.string());
        cJSON* json_root = cJSON_Parse(json_str.c_str());

        if(!json_root)
        {
            EXPLODE( "Error parsing JSON");
            return pregen_node_t{};
        }

        include_dir_stack.push(filepath);
        auto root = node_from_json(json_root);
        include_dir_stack.pop();

        cJSON_Delete(json_root);

        return root;
    }

    generated_node_t generate_node_from_json(stdfs::path const& filepath)
    {
        auto node = node_from_json(filepath);
        return generate_node(node);
    }

}<|endoftext|>


<commit_before>/*************************************************************************
* Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
*                                                                        *
* Author: The ALICE Off-line Project.                                    *
* Contributors are mentioned in the code where appropriate.              *
*                                                                        *
* Permission to use, copy, modify and distribute this software and its   *
* documentation strictly for non-commercial purposes is hereby granted   *
* without fee, provided that the above copyright notice appears in all   *
* copies and that both the copyright notice and this permission notice   *
* appear in the supporting documentation. The authors make no claims     *
* about the suitability of this software for any purpose. It is          *
* provided "as is" without express or implied warranty.                  *
**************************************************************************/
//////////////////////////////////////////////////////////////////////////
//                                                                      //
//             Class AnalysisTaskAliPtMothFromPtDaugh                   //
//   AnalysisTaskSE used for the reconstruction of mothers particles    //
//   spectra (pT and pTMin) starting from the pT-spectra of             //
//   daughters particles.                                               //
//                                                                      //
//             Authors: Giuseppe Bruno & Fiorella Fionda                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <TChain.h>

#include "AliAnalysisManager.h"
#include "AliMCEventHandler.h"
#include "AliMCEvent.h"
#include "AliStack.h"
#include "TNtuple.h"
#include "TH1F.h"
#include "TFile.h"
#include "AliLog.h"
#include "AliAnalysisTaskPtMothFromPtDaugh.h"
#include "AliPtMothFromPtDaugh.h"
#include "AliAnalysisTaskSE.h"

ClassImp(AliAnalysisTaskPtMothFromPtDaugh)

//_________________________________________________________________________________
AliAnalysisTaskPtMothFromPtDaugh::AliAnalysisTaskPtMothFromPtDaugh() :
  AliAnalysisTaskSE(),
  fPtMothDaugh(0),
  fDecayKine(0),
  fReadKineFromNtupla(0),
  fFileNtuplaName(0),
  fList(0)
{
  //
  // Default Constructor
  //
  AliInfo("Default Constructor!\n");
}

//_________________________________________________________________________________
AliAnalysisTaskPtMothFromPtDaugh::AliAnalysisTaskPtMothFromPtDaugh(Bool_t IsNtuplaCreated) :
  AliAnalysisTaskSE("TaskAliPtMothFromDaugh"),
  fPtMothDaugh(0),
  fDecayKine(0),
  fReadKineFromNtupla(IsNtuplaCreated),
  fFileNtuplaName(0),
  fList(0)
{
    //
    // Basic AnalysisTaskSE Constructor
    // Basic input of the analysis: TChain of galice.root files (optional)
    // Basic ouput: TList of mothers histograms (pT and pTMin) (standard)
    //              TNtupla with kinematics informations of mothers
    //              and daughters (optional)
    // If Ntupla already exists loop on kinematics is not needed
    // therefore input is not defined
    //
    if(!IsNtuplaCreated){
           DefineInput(0,TChain::Class()); DefineOutput(2,TNtuple::Class());}
    else {AliInfo("Ntupla is already created! Loop on events is skipped!\n");}
    DefineOutput(1,TList::Class());
}

//___________________________________________________________________________________
AliAnalysisTaskPtMothFromPtDaugh::~AliAnalysisTaskPtMothFromPtDaugh()
   {
    //
    // Destructor
    //
    if(fPtMothDaugh)
     { delete fPtMothDaugh; fPtMothDaugh=0;}
    if(fDecayKine)
     { delete fDecayKine; fDecayKine=0;}
    if(fFileNtuplaName)
     { delete fFileNtuplaName; fFileNtuplaName=0;}
    if (fList)
     { delete fList; fList = 0; }
   }

//_________________________________________________________________________________
void AliAnalysisTaskPtMothFromPtDaugh::UserCreateOutputObjects()
{
  //
  // Initialise the framework objects
  //
   //
    // Initialise the framework objects. OutPut objects created are:
    // 1) TList with mothers histograms
    // 2) TNtuple with kinematics informations of mothers and daughters (optional)
    //
    fList = new TList();
    fList->SetOwner();
    if(fReadKineFromNtupla) return;

    if(!AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler()) {
     Fatal("UserCreateOutputObjects", "This task needs a MC handler");
     return;
     }
    fDecayKine=new TNtuple("DecayKine","Decay kinematics","pdgM:pxM:pyM:pzM:yM:etaM:pdgD:pxD:pyD:pzD:yD:etaD");
    return;
}

//_________________________________________________________________________________
void AliAnalysisTaskPtMothFromPtDaugh::UserExec(Option_t */*option*/)
{
    //
    // Main loop. Called for every event
    // This loop fill a TNtuple with kinematics informations for
    // mother and daughter particles. TNtupla contains:
    //                   pdg of Mothers
    //                    px      "
    //                    py      "
    //                    pz      "
    //                  rapidity  "
    //                   eta      "
    //                   pdg of Daughter
    //                    px      "
    //                    py      "
    //                    pz      "
    //                  rapidity  "
    //                   eta      "
    //
    AliMCEventHandler* mcHandler = dynamic_cast<AliMCEventHandler*>(AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
    if(!mcHandler) {AliError("Could not get MC event handler!"); return; }
    mcHandler->SetReadTR(kFALSE);
    AliMCEvent* mcEvent = mcHandler->MCEvent();
    if(!mcEvent){ AliError("Could not get MC event!"); return; }
    AliStack* stack = mcEvent->Stack();
    if(!stack){ AliError("Could not get stack!"); return; }
    Int_t nPrims = stack->GetNprimary();
    float *inf = new float[12];
    for (Int_t iTrack = 0; iTrack < nPrims; ++iTrack) {
    TParticle *part = stack->Particle(iTrack);
    Int_t pdg=TMath::Abs(part->GetPdgCode());
    Double_t y,y2;
    //check if particle is in mothers list
    Int_t labelDaugh;
    if(fPtMothDaugh->IsMothers(pdg))
           {
           //check if mother particle has a selected daugh
           if(!fPtMothDaugh->IsSelectedDaugh(part,labelDaugh,stack)) continue;
           TParticle *pDaugh=stack->Particle(labelDaugh);
           fPtMothDaugh->Rapidity(part,y);
           fPtMothDaugh->Rapidity(pDaugh,y2);

           inf[0]=part->GetPdgCode();
           inf[1]=part->Px();
           inf[2]=part->Py();
           inf[3]=part->Pz();
           inf[4]=y;
           inf[5]=part->Eta();
           inf[6]=pDaugh->GetPdgCode();
           inf[7]=pDaugh->Px();
           inf[8]=pDaugh->Py();
           inf[9]=pDaugh->Pz();
           inf[10]=y2;
           inf[11]=pDaugh->Eta();
           fDecayKine->Fill(inf);
         } //close if statement for mothers particles
        } //end of tracks loop
    PostData(2,fDecayKine);
    PostData(1,fList);
    return;
}

//___________________________________________________________________________________
void AliAnalysisTaskPtMothFromPtDaugh::Terminate(Option_t */*option*/)
   {
    //
    // Terminate method called at the end of the events loop.
    // Get the Ntupla with kineamtics informations after the
    // events loop or read it from the file fFileNtuplaName
    // if the Ntupla is already created. Then use it to
    // evaluate pT and pTMin spectra for mothers by means
    // of the method implemented in AliPtMothFromPtDaugh
    //
    if(fReadKineFromNtupla) fDecayKine = ReadNtuplaFromFile(fFileNtuplaName);
    else{
         fDecayKine = dynamic_cast<TNtuple*>(GetOutputData(2));
         fList = dynamic_cast<TList*>(GetOutputData(1));
        }
    if(!fDecayKine) { AliInfo("TNtupla not available!\n"); return; }
    if(!fList) { AliInfo("TList not availble!\n"); return; }
    fPtMothDaugh->SetDecayNtupla(fDecayKine);
    fPtMothDaugh->EvaluatePtMoth();
    TH1F *fHistoPt = (TH1F*)fPtMothDaugh->GetHistoPtMother()->Clone();
    TH1F *fHistoPtMin = (TH1F*)fPtMothDaugh->GetHistoPtMinMother()->Clone();
    fList->Add(fHistoPt);
    fList->Add(fHistoPtMin);
    PostData(1,fList);
    return;
   }

//___________________________________________________________________________________
TNtuple *AliAnalysisTaskPtMothFromPtDaugh::ReadNtuplaFromFile(char *inFileName)
   {
    //
    // Get Ntupla from the file inFileName
    // after the it is created.
    // Input: name of the file - Output: TNtupla
    //
    TFile *f = new TFile(inFileName,"READ");
    if(!f) {AliError(Form("File %s with TNtupla doesn't exist!",inFileName)); return 0x0;}
    TNtuple *DecayKine=(TNtuple*)f->Get("DecayKine");
    if(!DecayKine) { AliError("The TNtupla doesn't exist!\n"); return 0x0;}
    return DecayKine;
   }
<commit_msg>Coverity fixes (Ivana)<commit_after>/*************************************************************************
* Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
*                                                                        *
* Author: The ALICE Off-line Project.                                    *
* Contributors are mentioned in the code where appropriate.              *
*                                                                        *
* Permission to use, copy, modify and distribute this software and its   *
* documentation strictly for non-commercial purposes is hereby granted   *
* without fee, provided that the above copyright notice appears in all   *
* copies and that both the copyright notice and this permission notice   *
* appear in the supporting documentation. The authors make no claims     *
* about the suitability of this software for any purpose. It is          *
* provided "as is" without express or implied warranty.                  *
**************************************************************************/
//////////////////////////////////////////////////////////////////////////
//                                                                      //
//             Class AnalysisTaskAliPtMothFromPtDaugh                   //
//   AnalysisTaskSE used for the reconstruction of mothers particles    //
//   spectra (pT and pTMin) starting from the pT-spectra of             //
//   daughters particles.                                               //
//                                                                      //
//             Authors: Giuseppe Bruno & Fiorella Fionda                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <TChain.h>

#include "AliAnalysisManager.h"
#include "AliMCEventHandler.h"
#include "AliMCEvent.h"
#include "AliStack.h"
#include "TNtuple.h"
#include "TH1F.h"
#include "TFile.h"
#include "AliLog.h"
#include "AliAnalysisTaskPtMothFromPtDaugh.h"
#include "AliPtMothFromPtDaugh.h"
#include "AliAnalysisTaskSE.h"

ClassImp(AliAnalysisTaskPtMothFromPtDaugh)

//_________________________________________________________________________________
AliAnalysisTaskPtMothFromPtDaugh::AliAnalysisTaskPtMothFromPtDaugh() :
  AliAnalysisTaskSE(),
  fPtMothDaugh(0),
  fDecayKine(0),
  fReadKineFromNtupla(0),
  fFileNtuplaName(0),
  fList(0)
{
  //
  // Default Constructor
  //
  AliInfo("Default Constructor!\n");
}

//_________________________________________________________________________________
AliAnalysisTaskPtMothFromPtDaugh::AliAnalysisTaskPtMothFromPtDaugh(Bool_t IsNtuplaCreated) :
  AliAnalysisTaskSE("TaskAliPtMothFromDaugh"),
  fPtMothDaugh(0),
  fDecayKine(0),
  fReadKineFromNtupla(IsNtuplaCreated),
  fFileNtuplaName(0),
  fList(0)
{
    //
    // Basic AnalysisTaskSE Constructor
    // Basic input of the analysis: TChain of galice.root files (optional)
    // Basic ouput: TList of mothers histograms (pT and pTMin) (standard)
    //              TNtupla with kinematics informations of mothers
    //              and daughters (optional)
    // If Ntupla already exists loop on kinematics is not needed
    // therefore input is not defined
    //
    if(!IsNtuplaCreated){
           DefineInput(0,TChain::Class()); DefineOutput(2,TNtuple::Class());}
    else {AliInfo("Ntupla is already created! Loop on events is skipped!\n");}
    DefineOutput(1,TList::Class());
}

//___________________________________________________________________________________
AliAnalysisTaskPtMothFromPtDaugh::~AliAnalysisTaskPtMothFromPtDaugh()
   {
    //
    // Destructor
    //
    if(fPtMothDaugh)
     { delete fPtMothDaugh; fPtMothDaugh=0;}
    if(fDecayKine)
     { delete fDecayKine; fDecayKine=0;}
    if(fFileNtuplaName)
     { delete fFileNtuplaName; fFileNtuplaName=0;}
    if (fList)
     { delete fList; fList = 0; }
   }

//_________________________________________________________________________________
void AliAnalysisTaskPtMothFromPtDaugh::UserCreateOutputObjects()
{
  //
  // Initialise the framework objects
  //
   //
    // Initialise the framework objects. OutPut objects created are:
    // 1) TList with mothers histograms
    // 2) TNtuple with kinematics informations of mothers and daughters (optional)
    //
    fList = new TList();
    fList->SetOwner();
    if(fReadKineFromNtupla) return;

    if(!AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler()) {
     Fatal("UserCreateOutputObjects", "This task needs a MC handler");
     return;
     }
    fDecayKine=new TNtuple("DecayKine","Decay kinematics","pdgM:pxM:pyM:pzM:yM:etaM:pdgD:pxD:pyD:pzD:yD:etaD");
    return;
}

//_________________________________________________________________________________
void AliAnalysisTaskPtMothFromPtDaugh::UserExec(Option_t */*option*/)
{
    //
    // Main loop. Called for every event
    // This loop fill a TNtuple with kinematics informations for
    // mother and daughter particles. TNtupla contains:
    //                   pdg of Mothers
    //                    px      "
    //                    py      "
    //                    pz      "
    //                  rapidity  "
    //                   eta      "
    //                   pdg of Daughter
    //                    px      "
    //                    py      "
    //                    pz      "
    //                  rapidity  "
    //                   eta      "
    //
    AliMCEventHandler* mcHandler = dynamic_cast<AliMCEventHandler*>(AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
    if(!mcHandler) {AliError("Could not get MC event handler!"); return; }
    mcHandler->SetReadTR(kFALSE);
    AliMCEvent* mcEvent = mcHandler->MCEvent();
    if(!mcEvent){ AliError("Could not get MC event!"); return; }
    AliStack* stack = mcEvent->Stack();
    if(!stack){ AliError("Could not get stack!"); return; }
    Int_t nPrims = stack->GetNprimary();
    float *inf = new float[12];
    for (Int_t iTrack = 0; iTrack < nPrims; ++iTrack) {
    TParticle *part = stack->Particle(iTrack);
    Int_t pdg=TMath::Abs(part->GetPdgCode());
    Double_t y,y2;
    //check if particle is in mothers list
    Int_t labelDaugh;
    if(fPtMothDaugh->IsMothers(pdg))
           {
           //check if mother particle has a selected daugh
           if(!fPtMothDaugh->IsSelectedDaugh(part,labelDaugh,stack)) continue;
           TParticle *pDaugh=stack->Particle(labelDaugh);
           fPtMothDaugh->Rapidity(part,y);
           fPtMothDaugh->Rapidity(pDaugh,y2);

           inf[0]=part->GetPdgCode();
           inf[1]=part->Px();
           inf[2]=part->Py();
           inf[3]=part->Pz();
           inf[4]=y;
           inf[5]=part->Eta();
           inf[6]=pDaugh->GetPdgCode();
           inf[7]=pDaugh->Px();
           inf[8]=pDaugh->Py();
           inf[9]=pDaugh->Pz();
           inf[10]=y2;
           inf[11]=pDaugh->Eta();
           fDecayKine->Fill(inf);
         } //close if statement for mothers particles
        } //end of tracks loop
    PostData(2,fDecayKine);
    PostData(1,fList);
    delete [] inf;
    return;
}

//___________________________________________________________________________________
void AliAnalysisTaskPtMothFromPtDaugh::Terminate(Option_t */*option*/)
   {
    //
    // Terminate method called at the end of the events loop.
    // Get the Ntupla with kineamtics informations after the
    // events loop or read it from the file fFileNtuplaName
    // if the Ntupla is already created. Then use it to
    // evaluate pT and pTMin spectra for mothers by means
    // of the method implemented in AliPtMothFromPtDaugh
    //
    if(fReadKineFromNtupla) fDecayKine = ReadNtuplaFromFile(fFileNtuplaName);
    else{
         fDecayKine = dynamic_cast<TNtuple*>(GetOutputData(2));
         fList = dynamic_cast<TList*>(GetOutputData(1));
        }
    if(!fDecayKine) { AliInfo("TNtupla not available!\n"); return; }
    if(!fList) { AliInfo("TList not availble!\n"); return; }
    fPtMothDaugh->SetDecayNtupla(fDecayKine);
    fPtMothDaugh->EvaluatePtMoth();
    TH1F *fHistoPt = (TH1F*)fPtMothDaugh->GetHistoPtMother()->Clone();
    TH1F *fHistoPtMin = (TH1F*)fPtMothDaugh->GetHistoPtMinMother()->Clone();
    fList->Add(fHistoPt);
    fList->Add(fHistoPtMin);
    PostData(1,fList);
    return;
   }

//___________________________________________________________________________________
TNtuple *AliAnalysisTaskPtMothFromPtDaugh::ReadNtuplaFromFile(char *inFileName)
   {
    //
    // Get Ntupla from the file inFileName
    // after the it is created.
    // Input: name of the file - Output: TNtupla
    //
    TFile *f = new TFile(inFileName,"READ");
    if(!f) {AliError(Form("File %s with TNtupla doesn't exist!",inFileName)); return 0x0;}
    TNtuple *DecayKine=(TNtuple*)f->Get("DecayKine");
    if(!DecayKine) { AliError("The TNtupla doesn't exist!\n"); return 0x0;}
    return DecayKine;
   }
<|endoftext|>


<commit_before>#include "Snapshoot.h"

#include "dataset/ISymbol.h"
#include "dataset/ImageSaver.h"
#include "render/SpriteDraw.h"

#include <stdlib.h>
#include <string.h>

#include <opengl/opengl.h>
#include <gl/gl.h>
#include <gl/glu.h>

#include <easyanim.h>

namespace d2d
{

static const int DEFAULT_WIDTH = 800;
static const int DEFAULT_HEIGHT = 600;

Snapshoot::Snapshoot()
	: m_tex(0)
	, m_fbo(0)
{
	m_width = DEFAULT_WIDTH;
	m_height = DEFAULT_HEIGHT;

	createFBO();
}

Snapshoot::Snapshoot(int width, int height)
	: m_tex(0)
	, m_fbo(0)
{
	m_width = width;
	m_height = height;

	createFBO();
}

Snapshoot::~Snapshoot()
{
	releaseFBO();
}

unsigned char* Snapshoot::outputToMemory(const ISymbol* symbol, bool whitebg,
										 float scale) const
{
	drawFBO(symbol, whitebg, scale);

	int w = symbol->getSize().xLength() * scale,
		h = symbol->getSize().yLength() * scale;
	size_t size = w*h*4;
	unsigned char* pixels = new unsigned char[size];
	if(!pixels) return NULL;
	memset(&pixels[0], 0, size);

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
	glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ShaderMgr::Instance()->GetFboID());

	return pixels;
}

void Snapshoot::outputToImageFile(const ISymbol* symbol, const std::string& filename,
								  float scale) const
{
	int w = symbol->getSize().xLength() * scale,
		h = symbol->getSize().yLength() * scale;
	unsigned char* pixels = outputToMemory(symbol, false, scale);
	ImageSaver::storeToFile(pixels, w, h, filename, ImageSaver::e_png);
	delete[] pixels;
}

void Snapshoot::DrawSprite(const ISprite* sprite, bool clear) const
{
	drawFBO(sprite, clear, m_width, m_height);
}

void Snapshoot::DrawSprite(const ISprite* sprite, bool clear, int width, int height) const
{
	drawFBO(sprite, clear, width, height);
}

void Snapshoot::SaveToFile(const std::string& filename) const
{
	SaveToFile(filename, m_width, m_height);
}

void Snapshoot::SaveToFile(const std::string& filename, int width, int height) const
{
	size_t size = width * height * 4;
	unsigned char* pixels = new unsigned char[size];
	if(!pixels) return;
	memset(&pixels[0], 0, size);

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
	glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ShaderMgr::Instance()->GetFboID());

	ImageSaver::storeToFile(pixels, width, height, filename, ImageSaver::e_png);

	delete[] pixels;
}

void Snapshoot::createFBO()
{
	initOpenGLExtensions();

	// init texture
	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

	GLuint tex;
	glGenTextures(1, &tex);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, tex);
	m_tex = tex;

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	unsigned char* empty_data = new unsigned char[m_width*m_height*4];
	if(!empty_data) return;
	memset(empty_data, 0, m_width*m_height*4);
	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)m_width, (GLsizei)m_height, GL_RGBA, GL_UNSIGNED_BYTE, &empty_data[0]);
	delete[] empty_data;

	// init fbo
	glGenFramebuffersEXT(1, (GLuint*)&m_fbo);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);

	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0);

	int status = checkFramebufferStatus();
	assert(status);

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ShaderMgr::Instance()->GetFboID());
	glBindTexture(GL_TEXTURE_2D, 0);
}

void Snapshoot::releaseFBO()
{
	if (m_tex != 0)
	{
		glDeleteTextures(1, (GLuint*)(&m_tex));
		m_tex = 0;
	}
	if (m_fbo != 0)
	{
		glDeleteFramebuffersEXT(1, (GLuint*)(&m_fbo));
		m_fbo = 0;
	}
}

void Snapshoot::drawFBO(const ISymbol* symbol, bool whitebg, float scale) const
{
	ShaderMgr* shader = ShaderMgr::Instance();
	shader->SetFBO(m_fbo);
	shader->sprite();

 	if (whitebg) {
 		glClearColor(1, 1, 1, 1);
 	} else {
		glClearColor(0, 0, 0, 0);
	}
	glClear(GL_COLOR_BUFFER_BIT);

	d2d::Rect rect = symbol->getSize();
 	int w = rect.xLength() * scale,
 		h = rect.yLength() * scale;
	shader->SetModelView(Vector(0, 0), 1);
	shader->SetProjection(w, h);
	glViewport(0, 0, w, h);

	Matrix mt;
	float dx = symbol->getSize().xCenter();
	float dy = symbol->getSize().yCenter();
	mt.translate(dx, dy);
	SpriteDraw::drawSprite(symbol, mt, d2d::Vector(0, 0), 0.0f, scale, -scale);

	// set fbo to force flush
	// todo symbolĻҪӸơ
 	shader->SetFBO(0);
 	shader->SetTexture(0);
}

void Snapshoot::drawFBO(const ISprite* sprite, bool clear, int width, int height) const
{
	ShaderMgr* shader = ShaderMgr::Instance();
	shader->SetFBO(m_fbo);
	shader->sprite();

	if (clear) {
	 	glClearColor(0, 0, 0, 0);
	 	glClear(GL_COLOR_BUFFER_BIT);
	}

	shader->SetModelView(Vector(0, 0), 1);
	shader->SetProjection(width, height);
	glViewport(0, 0, width, height);

	Matrix mt;
// 	Rect r = sprite->getSymbol().getSize();
// 	mt.translate(-r.xCenter(), r.yCenter());
	SpriteDraw::drawSprite(sprite, mt);

	shader->SetFBO(0);
	shader->SetTexture(0);
}

int Snapshoot::checkFramebufferStatus() const
{
	GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
	switch(status)
	{
	case GL_FRAMEBUFFER_COMPLETE_EXT:
		std::cout << "++ fbo: Framebuffer complete." << std::endl;
		return 1;

	case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
		std::cout << "++ fbo: [ERROR] Framebuffer incomplete: Attachment is NOT complete." << std::endl;
		return 0;

	case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
		std::cout << "++ fbo: [ERROR] Framebuffer incomplete: No image is attached to FBO." << std::endl;
		return 0;

	case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
		std::cout << "++ fbo: [ERROR] Framebuffer incomplete: Draw Buffer." << std::endl;
		return 0;

	case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
		std::cout << "++ fbo: [ERROR] Framebuffer incomplete: Read Buffer." << std::endl;
		return 0;

	case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
		std::cout << "++ fbo: [ERROR] Unsupported by FBO implementation." << std::endl;
		return 0;

	default:
		std::cout << "++ fbo: [ERROR] Unknow error." << std::endl;
		return 0;
	}
}

}<commit_msg>[FIXED] snapshoot上下颠倒<commit_after>#include "Snapshoot.h"

#include "dataset/ISymbol.h"
#include "dataset/ImageSaver.h"
#include "render/SpriteDraw.h"

#include <stdlib.h>
#include <string.h>

#include <opengl/opengl.h>
#include <gl/gl.h>
#include <gl/glu.h>

#include <easyanim.h>

namespace d2d
{

static const int DEFAULT_WIDTH = 800;
static const int DEFAULT_HEIGHT = 600;

Snapshoot::Snapshoot()
	: m_tex(0)
	, m_fbo(0)
{
	m_width = DEFAULT_WIDTH;
	m_height = DEFAULT_HEIGHT;

	createFBO();
}

Snapshoot::Snapshoot(int width, int height)
	: m_tex(0)
	, m_fbo(0)
{
	m_width = width;
	m_height = height;

	createFBO();
}

Snapshoot::~Snapshoot()
{
	releaseFBO();
}

unsigned char* Snapshoot::outputToMemory(const ISymbol* symbol, bool whitebg,
										 float scale) const
{
	drawFBO(symbol, whitebg, scale);

	int w = symbol->getSize().xLength() * scale,
		h = symbol->getSize().yLength() * scale;
	size_t size = w*h*4;
	unsigned char* pixels = new unsigned char[size];
	if(!pixels) return NULL;
	memset(&pixels[0], 0, size);

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
	glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ShaderMgr::Instance()->GetFboID());

	return pixels;
}

void Snapshoot::outputToImageFile(const ISymbol* symbol, const std::string& filename,
								  float scale) const
{
	int w = symbol->getSize().xLength() * scale,
		h = symbol->getSize().yLength() * scale;
	unsigned char* pixels = outputToMemory(symbol, false, scale);
	ImageSaver::storeToFile(pixels, w, h, filename, ImageSaver::e_png);
	delete[] pixels;
}

void Snapshoot::DrawSprite(const ISprite* sprite, bool clear) const
{
	drawFBO(sprite, clear, m_width, m_height);
}

void Snapshoot::DrawSprite(const ISprite* sprite, bool clear, int width, int height) const
{
	drawFBO(sprite, clear, width, height);
}

void Snapshoot::SaveToFile(const std::string& filename) const
{
	SaveToFile(filename, m_width, m_height);
}

void Snapshoot::SaveToFile(const std::string& filename, int width, int height) const
{
	size_t size = width * height * 4;
	unsigned char* pixels = new unsigned char[size];
	if(!pixels) return;
	memset(&pixels[0], 0, size);

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
	glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ShaderMgr::Instance()->GetFboID());

	ImageSaver::storeToFile(pixels, width, height, filename, ImageSaver::e_png);

	delete[] pixels;
}

void Snapshoot::createFBO()
{
	initOpenGLExtensions();

	// init texture
	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

	GLuint tex;
	glGenTextures(1, &tex);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, tex);
	m_tex = tex;

	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	unsigned char* empty_data = new unsigned char[m_width*m_height*4];
	if(!empty_data) return;
	memset(empty_data, 0, m_width*m_height*4);
	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)m_width, (GLsizei)m_height, GL_RGBA, GL_UNSIGNED_BYTE, &empty_data[0]);
	delete[] empty_data;

	// init fbo
	glGenFramebuffersEXT(1, (GLuint*)&m_fbo);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);

	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0);

	int status = checkFramebufferStatus();
	assert(status);

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ShaderMgr::Instance()->GetFboID());
	glBindTexture(GL_TEXTURE_2D, 0);
}

void Snapshoot::releaseFBO()
{
	if (m_tex != 0)
	{
		glDeleteTextures(1, (GLuint*)(&m_tex));
		m_tex = 0;
	}
	if (m_fbo != 0)
	{
		glDeleteFramebuffersEXT(1, (GLuint*)(&m_fbo));
		m_fbo = 0;
	}
}

void Snapshoot::drawFBO(const ISymbol* symbol, bool whitebg, float scale) const
{
	ShaderMgr* shader = ShaderMgr::Instance();
	shader->SetFBO(m_fbo);
	shader->sprite();

 	if (whitebg) {
 		glClearColor(1, 1, 1, 1);
 	} else {
		glClearColor(0, 0, 0, 0);
	}
	glClear(GL_COLOR_BUFFER_BIT);

	d2d::Rect rect = symbol->getSize();
 	int w = rect.xLength() * scale,
 		h = rect.yLength() * scale;
	shader->SetModelView(Vector(0, 0), 1);
	shader->SetProjection(w, h);
	glViewport(0, 0, w, h);

	Matrix mt;
	float dx = symbol->getSize().xCenter();
	float dy = symbol->getSize().yCenter();
	mt.translate(dx, dy);
	SpriteDraw::drawSprite(symbol, mt, d2d::Vector(0, 0), 0.0f, scale, -scale);

	// set fbo to force flush
	// todo symbolĻҪӸơ
 	shader->SetFBO(0);
 	shader->SetTexture(0);
}

void Snapshoot::drawFBO(const ISprite* sprite, bool clear, int width, int height) const
{
	ShaderMgr* shader = ShaderMgr::Instance();
	shader->SetFBO(m_fbo);
	shader->sprite();

	if (clear) {
	 	glClearColor(0, 0, 0, 0);
	 	glClear(GL_COLOR_BUFFER_BIT);
	}

	shader->SetModelView(Vector(0, 0), 1);
	shader->SetProjection(width, height);
	glViewport(0, 0, width, height);

// 	Rect r = sprite->getSymbol().getSize();
// 	mt.translate(-r.xCenter(), r.yCenter());

	Matrix mt;
	mt.setScale(1, -1);
	SpriteDraw::drawSprite(sprite, mt);

	shader->SetFBO(0);
	shader->SetTexture(0);
}

int Snapshoot::checkFramebufferStatus() const
{
	GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
	switch(status)
	{
	case GL_FRAMEBUFFER_COMPLETE_EXT:
		std::cout << "++ fbo: Framebuffer complete." << std::endl;
		return 1;

	case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
		std::cout << "++ fbo: [ERROR] Framebuffer incomplete: Attachment is NOT complete." << std::endl;
		return 0;

	case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
		std::cout << "++ fbo: [ERROR] Framebuffer incomplete: No image is attached to FBO." << std::endl;
		return 0;

	case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
		std::cout << "++ fbo: [ERROR] Framebuffer incomplete: Draw Buffer." << std::endl;
		return 0;

	case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
		std::cout << "++ fbo: [ERROR] Framebuffer incomplete: Read Buffer." << std::endl;
		return 0;

	case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
		std::cout << "++ fbo: [ERROR] Unsupported by FBO implementation." << std::endl;
		return 0;

	default:
		std::cout << "++ fbo: [ERROR] Unknow error." << std::endl;
		return 0;
	}
}

}<|endoftext|>


<commit_before>#include <StdAfx.h>
#include <UI/Controls/PaneHeader/PaneHeader.h>
#include <UI/UIFunctions.h>
#include <core/utility/strings.h>
#include <core/utility/output.h>

namespace controls
{
	void PaneHeader::Initialize(_In_ CWnd* pParent, _In_opt_ HDC hdc, _In_ UINT nid)
	{
		if (pParent) m_hWndParent = pParent->m_hWnd;
		// Assign a nID to the collapse button that is IDD_COLLAPSE more than the control's nID
		m_nIDCollapse = nid + IDD_COLLAPSE;
		// TODO: We don't save our header's nID here, but we could if we wanted

		EC_B_S(m_rightLabel.Create(
			WS_CHILD | WS_CLIPSIBLINGS | ES_READONLY | WS_VISIBLE, CRect(0, 0, 0, 0), pParent, IDD_COUNTLABEL));
		ui::SubclassLabel(m_rightLabel.m_hWnd);
		StyleLabel(m_rightLabel.m_hWnd, ui::uiLabelStyle::PaneHeaderText);

		EC_B_S(Create(WS_CHILD | WS_CLIPSIBLINGS | ES_READONLY | WS_VISIBLE, CRect(0, 0, 0, 0), pParent, nid));
		::SetWindowTextW(m_hWnd, m_szLabel.c_str());
		ui::SubclassLabel(m_hWnd);

		if (m_bCollapsible)
		{
			StyleLabel(m_hWnd, ui::uiLabelStyle::PaneHeaderLabel);

			EC_B_S(m_CollapseButton.Create(
				nullptr,
				WS_TABSTOP | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
				CRect(0, 0, 0, 0),
				pParent,
				m_nIDCollapse));
			StyleButton(
				m_CollapseButton.m_hWnd, m_bCollapsed ? ui::uiButtonStyle::UpArrow : ui::uiButtonStyle::DownArrow);
		}

		const auto sizeText = ui::GetTextExtentPoint32(hdc, m_szLabel);
		m_iLabelWidth = sizeText.cx;
		output::DebugPrint(
			output::dbgLevel::Draw,
			L"PaneHeader::Initialize m_iLabelWidth:%d \"%ws\"\n",
			m_iLabelWidth,
			m_szLabel.c_str());

		// If we need an action button, go ahead and create it
		if (m_nIDAction)
		{
			EC_B_S(m_actionButton.Create(
				strings::wstringTotstring(m_szActionButton).c_str(),
				WS_TABSTOP | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
				CRect(0, 0, 0, 0),
				pParent,
				m_nIDAction));
			StyleButton(m_actionButton.m_hWnd, ui::uiButtonStyle::Unstyled);
		}

		m_bInitialized = true;
	}

	// Draw our collapse button and label, if needed.
	// Draws everything to GetFixedHeight()
	void PaneHeader::DeferWindowPos(_In_ HDWP hWinPosInfo, const _In_ int x, const _In_ int y, const _In_ int width)
	{
		const auto height = GetFixedHeight();
		auto curX = x;
		const auto actionButtonWidth = m_actionButtonWidth ? m_actionButtonWidth + 2 * m_iMargin : 0;
		const auto actionButtonAndGutterWidth = actionButtonWidth ? actionButtonWidth + m_iSideMargin : 0;
		if (m_bCollapsible)
		{
			::DeferWindowPos(
				hWinPosInfo,
				m_CollapseButton.GetSafeHwnd(),
				nullptr,
				curX,
				y,
				width - actionButtonAndGutterWidth,
				height,
				SWP_NOZORDER);
			curX += m_iButtonHeight;
		}

		output::DebugPrint(
			output::dbgLevel::Draw,
			L"PaneHeader::DeferWindowPos x:%d width:%d labelpos:%d labelwidth:%d \n",
			x,
			width,
			curX,
			m_iLabelWidth);

		::DeferWindowPos(hWinPosInfo, GetSafeHwnd(), nullptr, curX, y, m_iLabelWidth, height, SWP_NOZORDER);

		if (!m_bCollapsed)
		{
			// Drop the count on top of the label we drew above
			EC_B_S(::DeferWindowPos(
				hWinPosInfo,
				m_rightLabel.GetSafeHwnd(),
				nullptr,
				x + width - m_rightLabelWidth - actionButtonAndGutterWidth,
				y,
				m_rightLabelWidth,
				height,
				SWP_NOZORDER));
		}

		if (m_nIDAction)
		{
			// Drop the action button next to the label we drew above
			EC_B_S(::DeferWindowPos(
				hWinPosInfo,
				m_actionButton.GetSafeHwnd(),
				nullptr,
				x + width - actionButtonWidth,
				y,
				actionButtonWidth,
				height,
				SWP_NOZORDER));
		}
	}

	int PaneHeader::GetMinWidth()
	{
		auto cx = m_iLabelWidth;
		if (m_bCollapsible) cx += m_iButtonHeight;
		if (m_rightLabelWidth)
		{
			cx += m_iSideMargin;
			cx += m_rightLabelWidth;
		}

		if (m_actionButtonWidth)
		{
			cx += m_iSideMargin;
			cx += m_actionButtonWidth + 2 * m_iMargin;
		}

		return cx;
	}

	void PaneHeader::SetRightLabel(const std::wstring szLabel)
	{
		if (!m_bInitialized) return;
		EC_B_S(::SetWindowTextW(m_rightLabel.m_hWnd, szLabel.c_str()));

		const auto hdc = ::GetDC(m_rightLabel.GetSafeHwnd());
		const auto hfontOld = SelectObject(hdc, ui::GetSegoeFont());
		const auto sizeText = ui::GetTextExtentPoint32(hdc, szLabel);
		static_cast<void>(SelectObject(hdc, hfontOld));
		::ReleaseDC(m_rightLabel.GetSafeHwnd(), hdc);
		m_rightLabelWidth = sizeText.cx;
	}

	void PaneHeader::SetActionButton(const std::wstring szActionButton)
	{
		// Don't bother if we never enabled the button
		if (m_nIDAction == 0) return;

		EC_B_S(::SetWindowTextW(m_actionButton.GetSafeHwnd(), szActionButton.c_str()));

		m_szActionButton = szActionButton;
		const auto hdc = ::GetDC(m_actionButton.GetSafeHwnd());
		const auto hfontOld = SelectObject(hdc, ui::GetSegoeFont());
		const auto sizeText = ui::GetTextExtentPoint32(hdc, szActionButton);
		static_cast<void>(SelectObject(hdc, hfontOld));
		::ReleaseDC(m_actionButton.GetSafeHwnd(), hdc);
		m_actionButtonWidth = sizeText.cx;
	}

	bool PaneHeader::HandleChange(UINT nID)
	{
		// Collapse buttons have a nID IDD_COLLAPSE higher than nID of the pane they toggle.
		// So if we get asked about one that matches, we can assume it's time to toggle our collapse.
		if (m_nIDCollapse == nID)
		{
			OnToggleCollapse();
			return true;
		}

		return false;
	}

	void PaneHeader::OnToggleCollapse()
	{
		m_bCollapsed = !m_bCollapsed;

		StyleButton(m_CollapseButton.m_hWnd, m_bCollapsed ? ui::uiButtonStyle::UpArrow : ui::uiButtonStyle::DownArrow);
		WC_B_S(m_rightLabel.ShowWindow(m_bCollapsed ? SW_HIDE : SW_SHOW));

		// Trigger a redraw
		::PostMessage(m_hWndParent, WM_COMMAND, IDD_RECALCLAYOUT, NULL);
	}

	void PaneHeader::SetMargins(
		int iMargin,
		int iSideMargin,
		int iLabelHeight, // Height of the label
		int iButtonHeight) // Height of button
	{
		m_iMargin = iMargin;
		m_iSideMargin = iSideMargin;
		m_iLabelHeight = iLabelHeight;
		m_iButtonHeight = iButtonHeight;
	}
} // namespace controls<commit_msg>Fix tab order of labels<commit_after>#include <StdAfx.h>
#include <UI/Controls/PaneHeader/PaneHeader.h>
#include <UI/UIFunctions.h>
#include <core/utility/strings.h>
#include <core/utility/output.h>

namespace controls
{
	void PaneHeader::Initialize(_In_ CWnd* pParent, _In_opt_ HDC hdc, _In_ UINT nid)
	{
		if (pParent) m_hWndParent = pParent->m_hWnd;
		// Assign a nID to the collapse button that is IDD_COLLAPSE more than the control's nID
		m_nIDCollapse = nid + IDD_COLLAPSE;
		// TODO: We don't save our header's nID here, but we could if we wanted

		EC_B_S(Create(WS_CHILD | WS_CLIPSIBLINGS | ES_READONLY | WS_VISIBLE, CRect(0, 0, 0, 0), pParent, nid));
		::SetWindowTextW(m_hWnd, m_szLabel.c_str());
		ui::SubclassLabel(m_hWnd);

		EC_B_S(m_rightLabel.Create(
			WS_CHILD | WS_CLIPSIBLINGS | ES_READONLY | WS_VISIBLE, CRect(0, 0, 0, 0), pParent, IDD_COUNTLABEL));
		ui::SubclassLabel(m_rightLabel.m_hWnd);
		StyleLabel(m_rightLabel.m_hWnd, ui::uiLabelStyle::PaneHeaderText);

		if (m_bCollapsible)
		{
			StyleLabel(m_hWnd, ui::uiLabelStyle::PaneHeaderLabel);

			EC_B_S(m_CollapseButton.Create(
				nullptr,
				WS_TABSTOP | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
				CRect(0, 0, 0, 0),
				pParent,
				m_nIDCollapse));
			StyleButton(
				m_CollapseButton.m_hWnd, m_bCollapsed ? ui::uiButtonStyle::UpArrow : ui::uiButtonStyle::DownArrow);
		}

		const auto sizeText = ui::GetTextExtentPoint32(hdc, m_szLabel);
		m_iLabelWidth = sizeText.cx;
		output::DebugPrint(
			output::dbgLevel::Draw,
			L"PaneHeader::Initialize m_iLabelWidth:%d \"%ws\"\n",
			m_iLabelWidth,
			m_szLabel.c_str());

		// If we need an action button, go ahead and create it
		if (m_nIDAction)
		{
			EC_B_S(m_actionButton.Create(
				strings::wstringTotstring(m_szActionButton).c_str(),
				WS_TABSTOP | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
				CRect(0, 0, 0, 0),
				pParent,
				m_nIDAction));
			StyleButton(m_actionButton.m_hWnd, ui::uiButtonStyle::Unstyled);
		}

		m_bInitialized = true;
	}

	// Draw our collapse button and label, if needed.
	// Draws everything to GetFixedHeight()
	void PaneHeader::DeferWindowPos(_In_ HDWP hWinPosInfo, const _In_ int x, const _In_ int y, const _In_ int width)
	{
		const auto height = GetFixedHeight();
		auto curX = x;
		const auto actionButtonWidth = m_actionButtonWidth ? m_actionButtonWidth + 2 * m_iMargin : 0;
		const auto actionButtonAndGutterWidth = actionButtonWidth ? actionButtonWidth + m_iSideMargin : 0;
		if (m_bCollapsible)
		{
			::DeferWindowPos(
				hWinPosInfo,
				m_CollapseButton.GetSafeHwnd(),
				nullptr,
				curX,
				y,
				width - actionButtonAndGutterWidth,
				height,
				SWP_NOZORDER);
			curX += m_iButtonHeight;
		}

		output::DebugPrint(
			output::dbgLevel::Draw,
			L"PaneHeader::DeferWindowPos x:%d width:%d labelpos:%d labelwidth:%d \n",
			x,
			width,
			curX,
			m_iLabelWidth);

		::DeferWindowPos(hWinPosInfo, GetSafeHwnd(), nullptr, curX, y, m_iLabelWidth, height, SWP_NOZORDER);

		if (!m_bCollapsed)
		{
			// Drop the count on top of the label we drew above
			EC_B_S(::DeferWindowPos(
				hWinPosInfo,
				m_rightLabel.GetSafeHwnd(),
				nullptr,
				x + width - m_rightLabelWidth - actionButtonAndGutterWidth,
				y,
				m_rightLabelWidth,
				height,
				SWP_NOZORDER));
		}

		if (m_nIDAction)
		{
			// Drop the action button next to the label we drew above
			EC_B_S(::DeferWindowPos(
				hWinPosInfo,
				m_actionButton.GetSafeHwnd(),
				nullptr,
				x + width - actionButtonWidth,
				y,
				actionButtonWidth,
				height,
				SWP_NOZORDER));
		}
	}

	int PaneHeader::GetMinWidth()
	{
		auto cx = m_iLabelWidth;
		if (m_bCollapsible) cx += m_iButtonHeight;
		if (m_rightLabelWidth)
		{
			cx += m_iSideMargin;
			cx += m_rightLabelWidth;
		}

		if (m_actionButtonWidth)
		{
			cx += m_iSideMargin;
			cx += m_actionButtonWidth + 2 * m_iMargin;
		}

		return cx;
	}

	void PaneHeader::SetRightLabel(const std::wstring szLabel)
	{
		if (!m_bInitialized) return;
		EC_B_S(::SetWindowTextW(m_rightLabel.m_hWnd, szLabel.c_str()));

		const auto hdc = ::GetDC(m_rightLabel.GetSafeHwnd());
		const auto hfontOld = SelectObject(hdc, ui::GetSegoeFont());
		const auto sizeText = ui::GetTextExtentPoint32(hdc, szLabel);
		static_cast<void>(SelectObject(hdc, hfontOld));
		::ReleaseDC(m_rightLabel.GetSafeHwnd(), hdc);
		m_rightLabelWidth = sizeText.cx;
	}

	void PaneHeader::SetActionButton(const std::wstring szActionButton)
	{
		// Don't bother if we never enabled the button
		if (m_nIDAction == 0) return;

		EC_B_S(::SetWindowTextW(m_actionButton.GetSafeHwnd(), szActionButton.c_str()));

		m_szActionButton = szActionButton;
		const auto hdc = ::GetDC(m_actionButton.GetSafeHwnd());
		const auto hfontOld = SelectObject(hdc, ui::GetSegoeFont());
		const auto sizeText = ui::GetTextExtentPoint32(hdc, szActionButton);
		static_cast<void>(SelectObject(hdc, hfontOld));
		::ReleaseDC(m_actionButton.GetSafeHwnd(), hdc);
		m_actionButtonWidth = sizeText.cx;
	}

	bool PaneHeader::HandleChange(UINT nID)
	{
		// Collapse buttons have a nID IDD_COLLAPSE higher than nID of the pane they toggle.
		// So if we get asked about one that matches, we can assume it's time to toggle our collapse.
		if (m_nIDCollapse == nID)
		{
			OnToggleCollapse();
			return true;
		}

		return false;
	}

	void PaneHeader::OnToggleCollapse()
	{
		m_bCollapsed = !m_bCollapsed;

		StyleButton(m_CollapseButton.m_hWnd, m_bCollapsed ? ui::uiButtonStyle::UpArrow : ui::uiButtonStyle::DownArrow);
		WC_B_S(m_rightLabel.ShowWindow(m_bCollapsed ? SW_HIDE : SW_SHOW));

		// Trigger a redraw
		::PostMessage(m_hWndParent, WM_COMMAND, IDD_RECALCLAYOUT, NULL);
	}

	void PaneHeader::SetMargins(
		int iMargin,
		int iSideMargin,
		int iLabelHeight, // Height of the label
		int iButtonHeight) // Height of button
	{
		m_iMargin = iMargin;
		m_iSideMargin = iSideMargin;
		m_iLabelHeight = iLabelHeight;
		m_iButtonHeight = iButtonHeight;
	}
} // namespace controls<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include <ICUBridge/ICUBridge.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/XalanAutoPtr.hpp>
#include <PlatformSupport/XalanDecimalFormatSymbols.hpp>

#include <unicode/coll.h>
#include <unicode/dcfmtsym.h>
#include <unicode/decimfmt.h>

#if defined(XALAN_NO_NAMESPACES)
	typedef vector<UChar>					UCharVectorType;
#else
	typedef std::vector<UChar>				UCharVectorType;
#endif

const UnicodeString
ICUBridge::XalanDOMCharStringToUnicodeString(const XalanDOMChar*	theString)
{
	if (theString == 0)
	{
		return UnicodeString();
	}
	else
	{
#if defined(XALAN_ICU_BRIDGE_UCHAR_MISMATCH)

		// Create a buffer to copy out the UnicodeString data...
		UCharVectorType		theBuffer;

		const unsigned int	theLength = length(theString);

		// Resize the buffer appropriately...
		theBuffer.reserve(theLength);

		// Copy the data, truncating each character...
		for (unsigned int i = 0; i < theLength; ++i)
		{
			// There should be no truncation, since XalanDOMChars
			// hold UTF-16 code points, but assert, just in case...
			assert(theString[i] == UChar(theString[i]));
			theBuffer.push_back(theString[i]);
		}

		return UnicodeString(&theBuffer[0], theBuffer.size());

#else

		return UnicodeString(theString, length(theString));

#endif
	}
}

const UnicodeString
ICUBridge::XalanDOMStringToUnicodeString(const XalanDOMString&	theString)
{
	// Just call up to the XalanDOMChar* version...
	return XalanDOMCharStringToUnicodeString(c_wstr(theString));
}

const XalanDOMString
ICUBridge::UnicodeStringToXalanDOMString(const UnicodeString&		theString)
{
#if defined(XALAN_ICU_BRIDGE_UCHAR_MISMATCH)

	// If XalanDOMChar is larger than the ICU's UChar, we have to more work...
	const int32_t	theLength = theString.length();

	// Create a buffer...
	XalanDOMCharVectorType	theBuffer;

	// Reserve the appropriate amount of space...
	theBuffer.reserve(theLength);

	// Copy the data...
	for (int32_t i = 0; i < theLength; ++i)
	{
		theBuffer.push_back(theString[i]);
	}

	return XalanDOMString(&theBuffer[0], theBuffer.size());

#else

	// Create a buffer to copy out the UnicodeString data...
	UCharVectorType		theResult;

	const int32_t	theLength = theString.length();

	// Resize the buffer appropriately...
	theResult.resize(theLength);

	// Extract the data...
	theString.extract(0, theLength, &theResult[0]);

	return XalanDOMString(&theResult[0], theResult.size());

#endif
}

void
ICUBridge::UnicodeStringToXalanDOMString(
			const UnicodeString&	theString,
			XalanDOMString&			theResult)
{
#if defined(XALAN_ICU_BRIDGE_UCHAR_MISMATCH)

	// If XalanDOMChar is larger than the ICU's UChar, we have to more work.
	// Don't bother to provide the optimized version, just call to the
	// previous function.

	theResult = UnicodeStringToXalanDOMString(theString);

#else

#if defined(XALAN_NO_NAMESPACES)
	typedef vector<UChar>					UCharVectorType;
#else
	typedef std::vector<UChar>				UCharVectorType;
#endif

	// Create a buffer to copy out the UnicodeString data...
	UCharVectorType		theBuffer;

	const int32_t	theLength = theString.length();

	// Resize the buffer appropriately...
	theBuffer.resize(theLength);

	// Extract the data...
	theString.extract(0, theLength, &theBuffer[0]);

	theResult = XalanDOMString(&theBuffer[0], theBuffer.size());

#endif
}

unsigned long
ICUBridge::FormatNumber(
			const XalanDOMString&				thePattern,
			double								theNumber,
			const XalanDecimalFormatSymbols*	theXalanDFS,
			XalanDOMString&						theResult)
{
	UErrorCode				theStatus = U_ZERO_ERROR;

	// Use a XalanAutoPtr, to keep this safe until we construct the DecimalFormat instance.
	XalanAutoPtr<DecimalFormatSymbols>	theDFS(new DecimalFormatSymbols(theStatus));

	if (theStatus == U_ZERO_ERROR ||
		theStatus == U_USING_DEFAULT_ERROR)
	{
		if (theXalanDFS != 0)
		{
			// We got a XalanDecimalFormatSymbols, so set the
			// corresponding data in the ICU DecimalFormatSymbols.
			theDFS->setZeroDigit(theXalanDFS->getZeroDigit());
			theDFS->setGroupingSeparator(theXalanDFS->getGroupingSeparator());
			theDFS->setDecimalSeparator(theXalanDFS->getDecimalSeparator());
			theDFS->setPerMill(theXalanDFS->getPerMill());
			theDFS->setPercent(theXalanDFS->getPercent());
			theDFS->setDigit(theXalanDFS->getDigit());
			theDFS->setPatternSeparator(theXalanDFS->getPatternSeparator());

			theDFS->setInfinity(XalanDOMStringToUnicodeString(theXalanDFS->getInfinity()));
			theDFS->setNaN(XalanDOMStringToUnicodeString(theXalanDFS->getNaN()));
		//	theDFS->setPlusSign(theZeroDigitChar);
			theDFS->setMinusSign(theXalanDFS->getMinusSign());
		//	theDFS->setExponentialSymbol(theZeroDigitChar);
			theDFS->setCurrencySymbol(XalanDOMStringToUnicodeString(theXalanDFS->getCurrencySymbol()));
			theDFS->setInternationalCurrencySymbol(XalanDOMStringToUnicodeString(theXalanDFS->getInternationalCurrencySymbol()));
			theDFS->setMonetaryDecimalSeparator(theXalanDFS->getMonetaryDecimalSeparator());
		}

		UnicodeString	theUnicodeResult;

		// Construct a DecimalFormat.  Note that we release the XalanAutoPtr, since the
		// DecimalFormat will adopt the DecimalFormatSymbols instance.
		DecimalFormat	theFormatter(XalanDOMStringToUnicodeString(thePattern), theDFS.release(), theStatus);

		if (theStatus == U_ZERO_ERROR ||
			theStatus == U_USING_DEFAULT_ERROR)
		{
			// Do the format...
			theFormatter.format(theNumber, theUnicodeResult);

			UnicodeStringToXalanDOMString(theUnicodeResult, theResult);

			theStatus = U_ZERO_ERROR;
		}
	}

	return theStatus;
}

int
ICUBridge::collationCompare(
			const XalanDOMString&	theLHS,
			const XalanDOMString&	theRHS)
{
	// Just call to the XalanDOMChar* version...
	return collationCompare(c_wstr(theLHS), c_wstr(theRHS));
}

int
ICUBridge::collationCompare(
			const XalanDOMChar*		theLHS,
			const XalanDOMChar*		theRHS)
{
	UErrorCode				theStatus = U_ZERO_ERROR;

	// Create a collator, and keep it in an XalanAutoPtr...
	const XalanAutoPtr<Collator>	theCollator(Collator::createInstance(theStatus));

	if (theStatus == U_ZERO_ERROR || theStatus == U_USING_DEFAULT_ERROR)
	{
		// OK, do the compare...
		return theCollator->compare(
#if defined(XALAN_ICU_BRIDGE_UCHAR_MISMATCH)
					XalanDOMCharStringToUnicodeString(theLHS),
					XalanDOMCharStringToUnicodeString(theRHS));
#else
					theLHS,
					length(theLHS),
					theRHS,
					length(theRHS));
#endif
	}
	else
	{
		// If creating the ICU Collator failed, fall back to the default...
		return collationCompare(theLHS, theRHS);
	}
}
<commit_msg>Use our own default XalanDecimalFormatSymbols to get proper XSLT-default number formatting.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include <ICUBridge/ICUBridge.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/XalanAutoPtr.hpp>
#include <PlatformSupport/XalanDecimalFormatSymbols.hpp>

#include <PlatformSupport/DoubleSupport.hpp>

#include <unicode/coll.h>
#include <unicode/dcfmtsym.h>
#include <unicode/decimfmt.h>

#if defined(XALAN_NO_NAMESPACES)
	typedef vector<UChar>					UCharVectorType;
#else
	typedef std::vector<UChar>				UCharVectorType;
#endif

const UnicodeString
ICUBridge::XalanDOMCharStringToUnicodeString(const XalanDOMChar*	theString)
{
	if (theString == 0)
	{
		return UnicodeString();
	}
	else
	{
#if defined(XALAN_ICU_BRIDGE_UCHAR_MISMATCH)

		// Create a buffer to copy out the UnicodeString data...
		UCharVectorType		theBuffer;

		const unsigned int	theLength = length(theString);

		// Resize the buffer appropriately...
		theBuffer.reserve(theLength);

		// Copy the data, truncating each character...
		for (unsigned int i = 0; i < theLength; ++i)
		{
			// There should be no truncation, since XalanDOMChars
			// hold UTF-16 code points, but assert, just in case...
			assert(theString[i] == UChar(theString[i]));
			theBuffer.push_back(theString[i]);
		}

		return UnicodeString(&theBuffer[0], theBuffer.size());

#else

		return UnicodeString(theString, length(theString));

#endif
	}
}

const UnicodeString
ICUBridge::XalanDOMStringToUnicodeString(const XalanDOMString&	theString)
{
	// Just call up to the XalanDOMChar* version...
	return XalanDOMCharStringToUnicodeString(c_wstr(theString));
}

const XalanDOMString
ICUBridge::UnicodeStringToXalanDOMString(const UnicodeString&		theString)
{
#if defined(XALAN_ICU_BRIDGE_UCHAR_MISMATCH)

	// If XalanDOMChar is larger than the ICU's UChar, we have to more work...
	const int32_t	theLength = theString.length();

	// Create a buffer...
	XalanDOMCharVectorType	theBuffer;

	// Reserve the appropriate amount of space...
	theBuffer.reserve(theLength);

	// Copy the data...
	for (int32_t i = 0; i < theLength; ++i)
	{
		theBuffer.push_back(theString[i]);
	}

	return XalanDOMString(&theBuffer[0], theBuffer.size());

#else

	// Create a buffer to copy out the UnicodeString data...
	UCharVectorType		theResult;

	const int32_t	theLength = theString.length();

	// Resize the buffer appropriately...
	theResult.resize(theLength);

	// Extract the data...
	theString.extract(0, theLength, &theResult[0]);

	return XalanDOMString(&theResult[0], theResult.size());

#endif
}

void
ICUBridge::UnicodeStringToXalanDOMString(
			const UnicodeString&	theString,
			XalanDOMString&			theResult)
{
#if defined(XALAN_ICU_BRIDGE_UCHAR_MISMATCH)

	// If XalanDOMChar is larger than the ICU's UChar, we have to more work.
	// Don't bother to provide the optimized version, just call to the
	// previous function.

	theResult = UnicodeStringToXalanDOMString(theString);

#else

#if defined(XALAN_NO_NAMESPACES)
	typedef vector<UChar>					UCharVectorType;
#else
	typedef std::vector<UChar>				UCharVectorType;
#endif

	// Create a buffer to copy out the UnicodeString data...
	UCharVectorType		theBuffer;

	const int32_t	theLength = theString.length();

	// Resize the buffer appropriately...
	theBuffer.resize(theLength);

	// Extract the data...
	theString.extract(0, theLength, &theBuffer[0]);

	theResult = XalanDOMString(&theBuffer[0], theBuffer.size());

#endif
}

static void
doFormatNumber(
			const XalanDOMString&				thePattern,
			double								theNumber,
			const XalanDecimalFormatSymbols&	theXalanDFS,
			UErrorCode&							theStatus,
			XalanDOMString&						theResult)
{
	if (theStatus == U_ZERO_ERROR ||
		theStatus == U_USING_DEFAULT_ERROR)
	{
		// Use a XalanAutoPtr, to keep this safe until we construct the DecimalFormat instance.
		XalanAutoPtr<DecimalFormatSymbols>	theDFS(new DecimalFormatSymbols(theStatus));

		// We got a XalanDecimalFormatSymbols, so set the
		// corresponding data in the ICU DecimalFormatSymbols.
		theDFS->setZeroDigit(theXalanDFS.getZeroDigit());
		theDFS->setGroupingSeparator(theXalanDFS.getGroupingSeparator());
		theDFS->setDecimalSeparator(theXalanDFS.getDecimalSeparator());
		theDFS->setPerMill(theXalanDFS.getPerMill());
		theDFS->setPercent(theXalanDFS.getPercent());
		theDFS->setDigit(theXalanDFS.getDigit());
		theDFS->setPatternSeparator(theXalanDFS.getPatternSeparator());

		theDFS->setInfinity(ICUBridge::XalanDOMStringToUnicodeString(theXalanDFS.getInfinity()));
		theDFS->setNaN(ICUBridge::XalanDOMStringToUnicodeString(theXalanDFS.getNaN()));
	//	theDFS->setPlusSign(theZeroDigitChar);
		theDFS->setMinusSign(theXalanDFS.getMinusSign());
	//	theDFS->setExponentialSymbol(theZeroDigitChar);
		theDFS->setCurrencySymbol(ICUBridge::XalanDOMStringToUnicodeString(theXalanDFS.getCurrencySymbol()));
		theDFS->setInternationalCurrencySymbol(ICUBridge::XalanDOMStringToUnicodeString(theXalanDFS.getInternationalCurrencySymbol()));
		theDFS->setMonetaryDecimalSeparator(theXalanDFS.getMonetaryDecimalSeparator());

		UnicodeString	theUnicodeResult;

		// Construct a DecimalFormat.  Note that we release the XalanAutoPtr, since the
		// DecimalFormat will adopt the DecimalFormatSymbols instance.
		DecimalFormat	theFormatter(ICUBridge::XalanDOMStringToUnicodeString(thePattern), theDFS.release(), theStatus);

		if (theStatus == U_ZERO_ERROR ||
			theStatus == U_USING_DEFAULT_ERROR)
		{
			// Do the format...
			theFormatter.format(theNumber, theUnicodeResult);

			ICUBridge::UnicodeStringToXalanDOMString(theUnicodeResult, theResult);

			theStatus = U_ZERO_ERROR;
		}
	}
}

unsigned long
ICUBridge::FormatNumber(
			const XalanDOMString&				thePattern,
			double								theNumber,
			const XalanDecimalFormatSymbols*	theXalanDFS,
			XalanDOMString&						theResult)
{
	UErrorCode	theStatus = U_ZERO_ERROR;

	if (theXalanDFS == 0)
	{
		XalanDecimalFormatSymbols	theDefaultSymbols;

		doFormatNumber(
				thePattern,
				theNumber,
				theDefaultSymbols,
				theStatus,
				theResult);
	}
	else
	{
		doFormatNumber(
				thePattern,
				theNumber,
				*theXalanDFS,
				theStatus,
				theResult);
	}

	return theStatus;
}

int
ICUBridge::collationCompare(
			const XalanDOMString&	theLHS,
			const XalanDOMString&	theRHS)
{
	// Just call to the XalanDOMChar* version...
	return collationCompare(c_wstr(theLHS), c_wstr(theRHS));
}

int
ICUBridge::collationCompare(
			const XalanDOMChar*		theLHS,
			const XalanDOMChar*		theRHS)
{
	UErrorCode				theStatus = U_ZERO_ERROR;

	// Create a collator, and keep it in an XalanAutoPtr...
	const XalanAutoPtr<Collator>	theCollator(Collator::createInstance(theStatus));

	if (theStatus == U_ZERO_ERROR || theStatus == U_USING_DEFAULT_ERROR)
	{
		// OK, do the compare...
		return theCollator->compare(
#if defined(XALAN_ICU_BRIDGE_UCHAR_MISMATCH)
					XalanDOMCharStringToUnicodeString(theLHS),
					XalanDOMCharStringToUnicodeString(theRHS));
#else
					theLHS,
					length(theLHS),
					theRHS,
					length(theRHS));
#endif
	}
	else
	{
		// If creating the ICU Collator failed, fall back to the default...
		return collationCompare(theLHS, theRHS);
	}
}
<|endoftext|>