<commit_before>/*
 * Copyright 2009 Blanton Black
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file Chunk.cpp
 * @brief Gas::Chunk implementation
 */

#include "Chunk.moc"

#include <QHash>
#include <QtDebug>
#include <QTextStream>
#include <QReadWriteLock>
#include <QStringList>
#include <QFile>

static inline
unsigned int encoded_size (unsigned int value)
{
    unsigned int i;
    for (i = 1; 1; i++) {
        if (value < ((1UL << (7UL*i))-1UL)) {
            break;
        }
    }
    return i + ((i - 1) >> 3);
}

using namespace Gas;

static QDataStream::ByteOrder g_defaultByteOrder = QDataStream::BigEndian;
static QDataStream::FloatingPointPrecision g_defaultFloatingPointPrecision
    = QDataStream::SinglePrecision;
static QReadWriteLock g_byteOrderLock;
static QReadWriteLock g_floatingPointPrecisionLock;

void Gas::setDefaultByteOrder (QDataStream::ByteOrder v)
{
    QWriteLocker ml (&g_byteOrderLock);
    g_defaultByteOrder = v;
}
void Gas::setDefaultFloatingPointPrecision (
    QDataStream::FloatingPointPrecision v)
{
    QWriteLocker ml (&g_floatingPointPrecisionLock);
    g_defaultFloatingPointPrecision = v;
}
QDataStream::ByteOrder Gas::defaultByteOrder ()
{
    QReadLocker ml (&g_byteOrderLock);
    return g_defaultByteOrder;
}
QDataStream::FloatingPointPrecision Gas::defaultFloatingPointPrecision ()
{
    QReadLocker ml (&g_floatingPointPrecisionLock);
    return g_defaultFloatingPointPrecision;
}

#if 0
void Gas::hexdump (const QByteArray& buf)
{
    gas_hexdump(buf.data(), buf.size());
}
#endif

struct Chunk::Private
{
    mutable unsigned int size;
    QHash<QString, QByteArray> attributes;
    QByteArray payload;

    QDataStream::FloatingPointPrecision floatingPointPrecision;
    QDataStream::ByteOrder byteOrder;

    Chunk* parent;
    ChunkList children;

    Private () :
        size(0),
        parent(NULL)
    {
    }
};

Chunk::Chunk (QString id, Chunk* parent) :
    QObject(),
    d(new Private)
{
    setId(id);

    setParentChunk(parent);

    if (parent) {
        d->floatingPointPrecision = parent->floatingPointPrecision();
        d->byteOrder = parent->byteOrder();
    } else {
        d->floatingPointPrecision = defaultFloatingPointPrecision();
        d->byteOrder = defaultByteOrder();
    }
}

Chunk::~Chunk ()
{
    qDeleteAll(d->children);
}

QString Chunk::id () const
{
    return objectName();
}

void Chunk::setId (const QString& id)
{
    setObjectName(id);
}

QByteArray& Chunk::payload () const
{
    return d->payload;
}

void Chunk::setPayload (const QByteArray& payload)
{
    d->payload = payload;
}

void Chunk::setPayload (const QVariant& payload)
{
    setPayload(payload.toString().toUtf8());
}

Chunk* Chunk::parentChunk ()
{
    return d->parent;
}

void Chunk::setParentChunk (Chunk* parent)
{
    d->parent = parent;
    if (parent) {
        parent->d->children.append(this);
    }
}

ChunkList& Chunk::childChunks () const
{
    return d->children;
}

Chunk* Chunk::at (const QString& path) const
{
    const Chunk* top = this;
    QStringList segments = path.split("/");
    int remainingLevels = segments.size();
    QStringListIterator segmentIter (segments);
    while (segmentIter.hasNext()) {
        const QString& segment = segmentIter.next();
        QListIterator<Chunk*> children (top->childChunks());
        while (children.hasNext()) {
            if (children.next()->id() == segment) {
                top = children.peekPrevious();
                remainingLevels--;
                break;
            }
        }
    }
    return remainingLevels ? NULL : const_cast<Chunk*>(top);
}

QHash<QString, QByteArray>& Chunk::attributes ()
{
    return d->attributes;
}

const QHash<QString, QByteArray> Chunk::attributes () const
{
    return d->attributes;
}

QByteArray& Chunk::operator[] (const QString& key)
{
    return d->attributes[key];
}

const QByteArray Chunk::operator[] (const QString& key) const
{
    return d->attributes[key];
}

void Chunk::setAttribute (const QString& key, const QByteArray& value)
{
    d->attributes.insert(key, value);
}

void Chunk::setAttribute (const QString& key, const QVariant& value)
{
    d->attributes.insert(key, value.toString().toUtf8());
}

bool Chunk::hasAttribute (const QString& key) const
{
    return d->attributes.contains(key);
}

int Chunk::size () const
{
    return d->size + encoded_size(d->size);
}

unsigned int Chunk::update () const
{
    const Chunk* child;
    unsigned int& sum = d->size;
    QHashIterator<QString, QByteArray> it (d->attributes);

    int tmp;

    sum = 0;
    // id
    tmp = id().size();
    sum += encoded_size(tmp);
    sum += tmp;
    // attributes
    sum += encoded_size(d->attributes.size());
    while (it.hasNext()) {
        it.next();
        // key
        tmp = it.key().size();
        sum += encoded_size(tmp);
        sum += tmp;
        // value
        tmp = it.value().size();
        sum += encoded_size(tmp);
        sum += tmp;
    }
    // payload
    tmp = d->payload.size();
    sum += encoded_size(tmp);
    sum += tmp;
    // children
    sum += encoded_size(d->children.size());

    for (ChunkList::ConstIterator it=d->children.begin(), end=d->children.end();
         it != end; ++it)
    {
        child = *it;
        tmp = child->update();
        sum += encoded_size(tmp);
        sum += tmp;
    }

    return sum;
}

/**
 * @remarks Qt's write returns false when the byte array is empty.
 *
 * @todo check the encode calls
 */
bool Chunk::write (QIODevice* io, bool needsUpdate) const
{
    if (needsUpdate) {
        update();
    }

    QHashIterator<QString, QByteArray> it (d->attributes);

    encode(io, d->size);
    encode(io, id().toUtf8().size());
    if (!io->write(id().toUtf8())) {
        goto abort;
    }
    encode(io, d->attributes.size());
    while (it.hasNext()) {
        it.next();
        encode(io, it.key().toUtf8().size());
        if (!io->write(it.key().toUtf8())) {
            goto abort;
        }
        encode(io, it.value().size());
        if ((it.value().size() > 0) && !io->write(it.value())) {
            goto abort;
        }
    }
    encode(io, payload().size());
    if ((payload().size() > 0) && !io->write(payload())) {
        goto abort;
    }
    encode(io, d->children.size());
    foreach (Chunk* child, d->children) {
        if (!child->write(io, false)) {
            goto abort;
        }
    }

    return true;

abort:
    qWarning() << io->errorString();
    return false;
}

QByteArray Chunk::serialize () const
{
    QByteArray byteArray;
    QBuffer buffer (&byteArray);
    buffer.open(QIODevice::WriteOnly);
    write(&buffer);
    return byteArray;
}

bool Chunk::read (QIODevice* io)
{
    unsigned int tmp, attr_count, child_count;
    QString key;
    QByteArray val;
    QByteArray buf;
    Chunk* child;

    decode(io, d->size, true);

    while (io->bytesAvailable() < d->size) {
        if (!io->waitForReadyRead(30000)) {
            qWarning() << Q_FUNC_INFO << io->errorString();
            return false;
        }
    }

    decode(io, tmp);
    buf = io->read(tmp);
    if (tmp != (unsigned int)buf.size()) {
        return false;
    }
    setId(buf);
    decode(io, attr_count);
    for (unsigned int i = 0; i < attr_count; i++) {
        decode(io, tmp);
        key = io->read(tmp);
        if (tmp != (unsigned int)key.size()) {
            return false;
        }
        decode(io, tmp);
        val = io->read(tmp);
        if (tmp != (unsigned int)val.size()) {
            return false;
        }
        d->attributes.insert(key, val);
    }
    decode(io, tmp);
    buf = io->read(tmp);
    if (tmp != (unsigned int)buf.size()) {
        return false;
    }
    setPayload(buf);
    decode(io, child_count);
    for (unsigned int i = 0; i < child_count; i++) {
        child = new Chunk(QString(), this);
        if (!child->read(io)) {
            delete child;
            return false;
        }
    }
    return true;
}

Chunk* Chunk::parse (QIODevice* io)
{
    Chunk* c = NULL;
    c = new Chunk;
    if (!c->read(io)) {
        qWarning() << "Chunk::read() failed";
        delete c;
        return NULL;
    }
    return c;
}

Chunk* Chunk::parse (const QByteArray& data)
{
    QBuffer buf;
    buf.setData(data);
    buf.open(QIODevice::ReadOnly);
    return parse(&buf);
}

Chunk* Chunk::parse (const QString& filename)
{
    QFile file (filename);

    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << file.errorString();
        return NULL;
    }

    uchar* buf = file.map(0, file.size());
    if (buf) {
        return parse(QByteArray::fromRawData((char*)buf, file.size()));
    } else {
        return parse(&file);
    }
}

Chunk* Chunk::parse (FILE* fs)
{
    QFile dev;
    if (!dev.open(fs, QIODevice::ReadOnly)) {
        return NULL;
    }
    return parse(&dev);
}

QDataStream& operator<< (QDataStream& stream, const Gas::Chunk& c)
{
    c.write(stream.device(), true);
    return stream;
}

QDataStream& operator>> (QDataStream& stream, Gas::Chunk& c)
{
    c.read(stream.device());
    return stream;
}

void Chunk::dump (const QString& prefix, QTextStream* s) const
{
    Q_ASSERT(s);
    QHashIterator<QString, QByteArray> it (d->attributes);
    *s << prefix << "---" << endl;
    *s << prefix << "id: " << id() << endl;
    while (it.hasNext()) {
        it.next();
        *s << prefix << it.key() << ": " << it.value() << endl;
    }
    if (!d->payload.isEmpty()) {
        *s << prefix << "payload: " << d->payload << endl;
    }
    foreach (Chunk* child, d->children) {
        child->dump(prefix + "  ", s);
    }
}

void Chunk::dump (const QString& prefix) const
{
    QTextStream s (stderr);
    dump(prefix, &s);
}

void Chunk::dump () const
{
    QTextStream s (stderr);
    dump(QString(), &s);
}

void Chunk::dump (QTextStream* stream) const
{
    dump(QString(), stream);
}

void Chunk::dump (const QString& prefix, QIODevice* dev) const
{
    QTextStream s (dev);
    dump(prefix, &s);
}

void Chunk::dump (QIODevice* dev) const
{
    dump(QString(), dev);
}

QDebug operator<< (QDebug debug, const Gas::Chunk& c)
{
    QByteArray data;
    QBuffer buf (&data);
    buf.open(QIODevice::WriteOnly);
    c.dump(&buf);
    debug << data.data();
    return debug;
}

void Chunk::setByteOrder (QDataStream::ByteOrder v)
{
    d->byteOrder = v;
}

QDataStream::ByteOrder Chunk::byteOrder () const
{
    return d->byteOrder;
}

void Chunk::setFloatingPointPrecision (QDataStream::FloatingPointPrecision v)
{
    d->floatingPointPrecision = v;
}

QDataStream::FloatingPointPrecision Chunk::floatingPointPrecision () const
{
    return d->floatingPointPrecision;
}

// vim: sw=4
<commit_msg>dump format change<commit_after>/*
 * Copyright 2009 Blanton Black
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file Chunk.cpp
 * @brief Gas::Chunk implementation
 */

#include "Chunk.moc"

#include <QHash>
#include <QtDebug>
#include <QTextStream>
#include <QReadWriteLock>
#include <QStringList>
#include <QFile>

static inline
unsigned int encoded_size (unsigned int value)
{
    unsigned int i;
    for (i = 1; 1; i++) {
        if (value < ((1UL << (7UL*i))-1UL)) {
            break;
        }
    }
    return i + ((i - 1) >> 3);
}

using namespace Gas;

static QDataStream::ByteOrder g_defaultByteOrder = QDataStream::BigEndian;
static QDataStream::FloatingPointPrecision g_defaultFloatingPointPrecision
    = QDataStream::SinglePrecision;
static QReadWriteLock g_byteOrderLock;
static QReadWriteLock g_floatingPointPrecisionLock;

void Gas::setDefaultByteOrder (QDataStream::ByteOrder v)
{
    QWriteLocker ml (&g_byteOrderLock);
    g_defaultByteOrder = v;
}
void Gas::setDefaultFloatingPointPrecision (
    QDataStream::FloatingPointPrecision v)
{
    QWriteLocker ml (&g_floatingPointPrecisionLock);
    g_defaultFloatingPointPrecision = v;
}
QDataStream::ByteOrder Gas::defaultByteOrder ()
{
    QReadLocker ml (&g_byteOrderLock);
    return g_defaultByteOrder;
}
QDataStream::FloatingPointPrecision Gas::defaultFloatingPointPrecision ()
{
    QReadLocker ml (&g_floatingPointPrecisionLock);
    return g_defaultFloatingPointPrecision;
}

#if 0
void Gas::hexdump (const QByteArray& buf)
{
    gas_hexdump(buf.data(), buf.size());
}
#endif

struct Chunk::Private
{
    mutable unsigned int size;
    QHash<QString, QByteArray> attributes;
    QByteArray payload;

    QDataStream::FloatingPointPrecision floatingPointPrecision;
    QDataStream::ByteOrder byteOrder;

    Chunk* parent;
    ChunkList children;

    Private () :
        size(0),
        parent(NULL)
    {
    }
};

Chunk::Chunk (QString id, Chunk* parent) :
    QObject(),
    d(new Private)
{
    setId(id);

    setParentChunk(parent);

    if (parent) {
        d->floatingPointPrecision = parent->floatingPointPrecision();
        d->byteOrder = parent->byteOrder();
    } else {
        d->floatingPointPrecision = defaultFloatingPointPrecision();
        d->byteOrder = defaultByteOrder();
    }
}

Chunk::~Chunk ()
{
    qDeleteAll(d->children);
}

QString Chunk::id () const
{
    return objectName();
}

void Chunk::setId (const QString& id)
{
    setObjectName(id);
}

QByteArray& Chunk::payload () const
{
    return d->payload;
}

void Chunk::setPayload (const QByteArray& payload)
{
    d->payload = payload;
}

void Chunk::setPayload (const QVariant& payload)
{
    setPayload(payload.toString().toUtf8());
}

Chunk* Chunk::parentChunk ()
{
    return d->parent;
}

void Chunk::setParentChunk (Chunk* parent)
{
    d->parent = parent;
    if (parent) {
        parent->d->children.append(this);
    }
}

ChunkList& Chunk::childChunks () const
{
    return d->children;
}

Chunk* Chunk::at (const QString& path) const
{
    const Chunk* top = this;
    QStringList segments = path.split("/");
    int remainingLevels = segments.size();
    QStringListIterator segmentIter (segments);
    while (segmentIter.hasNext()) {
        const QString& segment = segmentIter.next();
        QListIterator<Chunk*> children (top->childChunks());
        while (children.hasNext()) {
            if (children.next()->id() == segment) {
                top = children.peekPrevious();
                remainingLevels--;
                break;
            }
        }
    }
    return remainingLevels ? NULL : const_cast<Chunk*>(top);
}

QHash<QString, QByteArray>& Chunk::attributes ()
{
    return d->attributes;
}

const QHash<QString, QByteArray> Chunk::attributes () const
{
    return d->attributes;
}

QByteArray& Chunk::operator[] (const QString& key)
{
    return d->attributes[key];
}

const QByteArray Chunk::operator[] (const QString& key) const
{
    return d->attributes[key];
}

void Chunk::setAttribute (const QString& key, const QByteArray& value)
{
    d->attributes.insert(key, value);
}

void Chunk::setAttribute (const QString& key, const QVariant& value)
{
    d->attributes.insert(key, value.toString().toUtf8());
}

bool Chunk::hasAttribute (const QString& key) const
{
    return d->attributes.contains(key);
}

int Chunk::size () const
{
    return d->size + encoded_size(d->size);
}

unsigned int Chunk::update () const
{
    const Chunk* child;
    unsigned int& sum = d->size;
    QHashIterator<QString, QByteArray> it (d->attributes);

    int tmp;

    sum = 0;
    // id
    tmp = id().size();
    sum += encoded_size(tmp);
    sum += tmp;
    // attributes
    sum += encoded_size(d->attributes.size());
    while (it.hasNext()) {
        it.next();
        // key
        tmp = it.key().size();
        sum += encoded_size(tmp);
        sum += tmp;
        // value
        tmp = it.value().size();
        sum += encoded_size(tmp);
        sum += tmp;
    }
    // payload
    tmp = d->payload.size();
    sum += encoded_size(tmp);
    sum += tmp;
    // children
    sum += encoded_size(d->children.size());

    for (ChunkList::ConstIterator it=d->children.begin(), end=d->children.end();
         it != end; ++it)
    {
        child = *it;
        tmp = child->update();
        sum += encoded_size(tmp);
        sum += tmp;
    }

    return sum;
}

/**
 * @remarks Qt's write returns false when the byte array is empty.
 *
 * @todo check the encode calls
 */
bool Chunk::write (QIODevice* io, bool needsUpdate) const
{
    if (needsUpdate) {
        update();
    }

    QHashIterator<QString, QByteArray> it (d->attributes);

    encode(io, d->size);
    encode(io, id().toUtf8().size());
    if (!io->write(id().toUtf8())) {
        goto abort;
    }
    encode(io, d->attributes.size());
    while (it.hasNext()) {
        it.next();
        encode(io, it.key().toUtf8().size());
        if (!io->write(it.key().toUtf8())) {
            goto abort;
        }
        encode(io, it.value().size());
        if ((it.value().size() > 0) && !io->write(it.value())) {
            goto abort;
        }
    }
    encode(io, payload().size());
    if ((payload().size() > 0) && !io->write(payload())) {
        goto abort;
    }
    encode(io, d->children.size());
    foreach (Chunk* child, d->children) {
        if (!child->write(io, false)) {
            goto abort;
        }
    }

    return true;

abort:
    qWarning() << io->errorString();
    return false;
}

QByteArray Chunk::serialize () const
{
    QByteArray byteArray;
    QBuffer buffer (&byteArray);
    buffer.open(QIODevice::WriteOnly);
    write(&buffer);
    return byteArray;
}

bool Chunk::read (QIODevice* io)
{
    unsigned int tmp, attr_count, child_count;
    QString key;
    QByteArray val;
    QByteArray buf;
    Chunk* child;

    decode(io, d->size, true);

    while (io->bytesAvailable() < d->size) {
        if (!io->waitForReadyRead(30000)) {
            qWarning() << Q_FUNC_INFO << io->errorString();
            return false;
        }
    }

    decode(io, tmp);
    buf = io->read(tmp);
    if (tmp != (unsigned int)buf.size()) {
        return false;
    }
    setId(buf);
    decode(io, attr_count);
    for (unsigned int i = 0; i < attr_count; i++) {
        decode(io, tmp);
        key = io->read(tmp);
        if (tmp != (unsigned int)key.size()) {
            return false;
        }
        decode(io, tmp);
        val = io->read(tmp);
        if (tmp != (unsigned int)val.size()) {
            return false;
        }
        d->attributes.insert(key, val);
    }
    decode(io, tmp);
    buf = io->read(tmp);
    if (tmp != (unsigned int)buf.size()) {
        return false;
    }
    setPayload(buf);
    decode(io, child_count);
    for (unsigned int i = 0; i < child_count; i++) {
        child = new Chunk(QString(), this);
        if (!child->read(io)) {
            delete child;
            return false;
        }
    }
    return true;
}

Chunk* Chunk::parse (QIODevice* io)
{
    Chunk* c = NULL;
    c = new Chunk;
    if (!c->read(io)) {
        qWarning() << "Chunk::read() failed";
        delete c;
        return NULL;
    }
    return c;
}

Chunk* Chunk::parse (const QByteArray& data)
{
    QBuffer buf;
    buf.setData(data);
    buf.open(QIODevice::ReadOnly);
    return parse(&buf);
}

Chunk* Chunk::parse (const QString& filename)
{
    QFile file (filename);

    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << file.errorString();
        return NULL;
    }

    uchar* buf = file.map(0, file.size());
    if (buf) {
        return parse(QByteArray::fromRawData((char*)buf, file.size()));
    } else {
        return parse(&file);
    }
}

Chunk* Chunk::parse (FILE* fs)
{
    QFile dev;
    if (!dev.open(fs, QIODevice::ReadOnly)) {
        return NULL;
    }
    return parse(&dev);
}

QDataStream& operator<< (QDataStream& stream, const Gas::Chunk& c)
{
    c.write(stream.device(), true);
    return stream;
}

QDataStream& operator>> (QDataStream& stream, Gas::Chunk& c)
{
    c.read(stream.device());
    return stream;
}

void Chunk::dump (const QString& prefix, QTextStream* s) const
{
    Q_ASSERT(s);
    QHashIterator<QString, QByteArray> it (d->attributes);
    *s << prefix << "---" << endl;
    //*s << prefix << "id: " << id() << endl;
    QString idString = id();
    if (idString.isEmpty()) {
        *s << prefix << "\"\"[" << size() << "]" << endl;
    } else {
        *s << prefix << idString << "[" << size() << "]" << endl;
    }
    while (it.hasNext()) {
        it.next();
        *s << prefix << it.key() << ": \"" << it.value() << "\"" << endl;
    }
    if (!d->payload.isEmpty()) {
        *s << prefix << "payload[" << d->payload.size()
           << "]: \"" << d->payload << "\"" << endl;
    }
    foreach (Chunk* child, d->children) {
        child->dump(prefix + "  ", s);
    }
}

void Chunk::dump (const QString& prefix) const
{
    QTextStream s (stderr);
    dump(prefix, &s);
}

void Chunk::dump () const
{
    QTextStream s (stderr);
    dump(QString(), &s);
}

void Chunk::dump (QTextStream* stream) const
{
    dump(QString(), stream);
}

void Chunk::dump (const QString& prefix, QIODevice* dev) const
{
    QTextStream s (dev);
    dump(prefix, &s);
}

void Chunk::dump (QIODevice* dev) const
{
    dump(QString(), dev);
}

QDebug operator<< (QDebug debug, const Gas::Chunk& c)
{
    QByteArray data;
    QBuffer buf (&data);
    buf.open(QIODevice::WriteOnly);
    c.dump(&buf);
    debug << data.data();
    return debug;
}

void Chunk::setByteOrder (QDataStream::ByteOrder v)
{
    d->byteOrder = v;
}

QDataStream::ByteOrder Chunk::byteOrder () const
{
    return d->byteOrder;
}

void Chunk::setFloatingPointPrecision (QDataStream::FloatingPointPrecision v)
{
    d->floatingPointPrecision = v;
}

QDataStream::FloatingPointPrecision Chunk::floatingPointPrecision () const
{
    return d->floatingPointPrecision;
}

// vim: sw=4
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012, Dennis Hedback
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 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.
 */

#include <iostream>
#include <iterator>
#include <set>
#include <string>
#include <vector>

typedef std::set<std::string> Set;
typedef std::vector<std::string> Tuple;
typedef std::set<Tuple> Product;
typedef std::vector<Set> Generator;
typedef std::set<Generator> Quotient;

struct Options
{
    bool verbose;
};

static Options opts;

#define VPRINT(x) if (opts.verbose) { std::cerr << x << std::endl; }

Product read_tuples(void)
{
    Product prod;
    Tuple current_tuple;
    std::string current_elem;

    for (std::istreambuf_iterator<char> it(std::cin), end; it != end; it++)
    {
        char c = *it;

        if (c == ',' || c == '\n')
        {
            current_tuple.push_back(current_elem);
            current_elem.clear();

            if (c == '\n')
            {
                prod.insert(current_tuple);
                current_tuple.clear();
            }
        }
        else
        {
            current_elem += c;
        }
    }

    return prod;
}

unsigned int product_cardinality(Generator gen)
{
    unsigned int cardinality = 1;

    for (Generator::iterator it = gen.begin(); it != gen.end(); it++)
        cardinality *= (*it).size();

    return cardinality;
}

Product cartesian_product(Generator gen)
{
    Product prod;
    unsigned int counters[gen.size()];
    size_t gen_size;

    gen_size = gen.size();

    for (unsigned int i = 0; i < gen_size; i++)
        counters[i] = 0;

    for (unsigned int i = 0; i < product_cardinality(gen); i++)
    {
        Tuple current_tuple;

        for (unsigned int j = 0; j < gen_size; j++)
        {
            Set current_set = gen[j];
            unsigned int k = 0;

            for (Set::iterator it = current_set.begin(); it != current_set.end(); k++, it++)
                if (k == counters[j])
                    current_tuple.push_back(*it);
        }

        prod.insert(current_tuple);

        for (unsigned int j = 0; j < gen_size; j++)
        {
            counters[j]++;
            if (counters[j] > gen[j].size() - 1)
                counters[j] = 0;
            else
                break;
        }
    }

    return prod;
}

Generator init_generator(size_t size)
{
    Generator gen;
    for (unsigned int i = 0; i < size; i++)
        gen.push_back(Set());
    return gen;
}

Generator reference_generator(Product prod)
{
    Generator ref_generator;

    if (prod.size() > 0)
        ref_generator = init_generator((*prod.begin()).size());

    for (Product::iterator pi = prod.begin(); pi != prod.end(); pi++)
    {
        unsigned int i = 0;

        for (Tuple::const_iterator ti = (*pi).begin(); ti != (*pi).end(); i++, ti++)
        {
            ref_generator[i].insert(*ti);
        }
    }

    return ref_generator;
}

bool product_contains(Product prod, Tuple tuple)
{
    bool found = false;
    for (Product::iterator it = prod.begin(); it != prod.end(); it++)
        if ((*it) == tuple)
            found = true;
    return found;
}

Product difference(Product prod_1, Product prod_2)
{
    Product diff;

    for (Product::iterator pi_1 = prod_1.begin(); pi_1 != prod_1.end(); pi_1++)
        if (!product_contains(prod_2, (*pi_1)))
            diff.insert(*pi_1);

    return diff;
}

void print_product(Product prod)
{
    for (Product::iterator pi = prod.begin(); pi != prod.end(); pi++)
    {
        for (Tuple::const_iterator ti = (*pi).begin(); ti != (*pi).end(); ti++)
        {
            std::cout << *ti;

            if (++ti != (*pi).end())
                std::cout << ',';

            ti--;
        }

        std::cout << std::endl;
    }
}

Quotient generating_sets(Product prod)
{
    Quotient quot;
    Product ref_prod = prod;

    /*
    Generator ref_generator = reference_generator(prod);
    Product ref_product = cartesian_product(ref_generator);
    Product diff = difference(ref_product, prod);
    */

    for (unsigned int num_generators = 1, inserted = 0; prod.size() > 0; num_generators++)
    {
        Generator current_generator = init_generator((*prod.begin()).size());
        Product to_erase;
        for (Product::iterator pi = prod.begin(); pi != prod.end();)
        {
            Tuple current_tuple = (*pi);
            Generator tmp = current_generator;
            size_t tup_size = current_tuple.size();

            for (unsigned int i = 0; i < tup_size; i++)
            {
                tmp[i].insert(current_tuple[i]);
            }

            Product tmp_product = cartesian_product(tmp);

            for (Product::iterator tmpi = tmp_product.begin(); tmpi != tmp_product.end(); tmpi++)
            {
                if (!product_contains(ref_prod, *tmpi))
                {
                    ++pi;
                    // FIXME: Go away ugly goto, go away!
                    goto foo;
                }
            }

            current_generator = tmp;
            prod.erase(pi++);
                VPRINT(++inserted << " tuples inserted into " << num_generators << " generators ");
        foo:
            if (1 == 2) break;
        }
        quot.insert(current_generator);
    }

    return quot;
}

void print_quotient(Quotient quot)
{
    for (Quotient::iterator qi = quot.begin(); qi != quot.end(); qi++)
    {
        for (Generator::const_iterator gi = (*qi).begin(); gi != (*qi).end(); gi++)
        {
            for (Set::iterator si = (*gi).begin(); si != (*gi).end(); si++)
            {
                std::cout << *si;

                if (++si != (*gi).end())
                    std::cout << ',';

                si--;
            }

            std::cout << std::endl;
        }

        std::cout << "%%" << std::endl;
    }
}

int main(int argc, char *argv[])
{
    opts.verbose = true;
    Product prod = read_tuples();
    Quotient quot = generating_sets(prod);
    print_quotient(quot);

    return 0;
}
<commit_msg>Decreased execution time from 46 sec to 5 sec using a typical dataset as input<commit_after>/*
 * Copyright (c) 2012, Dennis Hedback
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 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.
 */

#include <iostream>
#include <iterator>
#include <set>
#include <string>
#include <vector>

typedef std::set<std::string> Set;
typedef std::vector<std::string> Tuple;
typedef std::set<Tuple> Product;
typedef std::vector<Set> Generator;
typedef std::set<Generator> Quotient;

struct Options
{
    bool verbose;
};

static Options opts;

#define VPRINT(x) if (opts.verbose) { std::cerr << x << std::endl; }

Product read_tuples(void)
{
    Product prod;
    Tuple current_tuple;
    std::string current_elem;

    for (std::istreambuf_iterator<char> it(std::cin), end; it != end; it++)
    {
        char c = *it;

        if (c == ',' || c == '\n')
        {
            current_tuple.push_back(current_elem);
            current_elem.clear();

            if (c == '\n')
            {
                prod.insert(current_tuple);
                current_tuple.clear();
            }
        }
        else
        {
            current_elem += c;
        }
    }

    return prod;
}

unsigned int product_cardinality(Generator gen)
{
    unsigned int cardinality = 1;

    for (Generator::iterator it = gen.begin(); it != gen.end(); it++)
        cardinality *= (*it).size();

    return cardinality;
}

Product cartesian_product(Generator gen)
{
    Product prod;
    unsigned int counters[gen.size()];
    size_t gen_size;

    gen_size = gen.size();

    for (unsigned int i = 0; i < gen_size; i++)
        counters[i] = 0;

    for (unsigned int i = 0; i < product_cardinality(gen); i++)
    {
        Tuple current_tuple;

        for (unsigned int j = 0; j < gen_size; j++)
        {
            Set current_set = gen[j];
            unsigned int k = 0;

            for (Set::iterator it = current_set.begin(); it != current_set.end(); k++, it++)
                if (k == counters[j])
                    current_tuple.push_back(*it);
        }

        prod.insert(current_tuple);

        for (unsigned int j = 0; j < gen_size; j++)
        {
            counters[j]++;
            if (counters[j] > gen[j].size() - 1)
                counters[j] = 0;
            else
                break;
        }
    }

    return prod;
}

Generator init_generator(size_t size)
{
    Generator gen;
    for (unsigned int i = 0; i < size; i++)
        gen.push_back(Set());
    return gen;
}

Generator reference_generator(Product prod)
{
    Generator ref_generator;

    if (prod.size() > 0)
        ref_generator = init_generator((*prod.begin()).size());

    for (Product::iterator pi = prod.begin(); pi != prod.end(); pi++)
    {
        unsigned int i = 0;

        for (Tuple::const_iterator ti = (*pi).begin(); ti != (*pi).end(); i++, ti++)
        {
            ref_generator[i].insert(*ti);
        }
    }

    return ref_generator;
}

bool product_contains(Product &prod, Tuple tuple)
{
    return prod.find(tuple) != prod.end();
}

Quotient generating_sets(Product prod)
{
    Quotient quot;
    Product ref_prod = prod;

    for (unsigned int num_generators = 1, inserted = 0; prod.size() > 0; num_generators++)
    {
        Generator current_generator = init_generator((*prod.begin()).size());
        Product to_erase;
        for (Product::iterator pi = prod.begin(); pi != prod.end();)
        {
            Tuple current_tuple = (*pi);
            Generator tmp = current_generator;
            size_t tup_size = current_tuple.size();

            for (unsigned int i = 0; i < tup_size; i++)
            {
                tmp[i].insert(current_tuple[i]);
            }

            Product tmp_product = cartesian_product(tmp);

            for (Product::iterator tmpi = tmp_product.begin(); tmpi != tmp_product.end(); tmpi++)
            {
                if (!product_contains(ref_prod, *tmpi))
                {
                    ++pi;
                    // FIXME: Go away ugly goto, go away!
                    goto foo;
                }
            }

            current_generator = tmp;
            prod.erase(pi++);
            VPRINT(++inserted << " tuples inserted into " << num_generators << " generators ");
        // FIXME: Ugly "expected primary-expression before '}' token" fix
        foo:
            if (1 == 2) break;
        }
        quot.insert(current_generator);
    }

    return quot;
}

void print_quotient(Quotient quot)
{
    for (Quotient::iterator qi = quot.begin(); qi != quot.end(); qi++)
    {
        for (Generator::const_iterator gi = (*qi).begin(); gi != (*qi).end(); gi++)
        {
            for (Set::iterator si = (*gi).begin(); si != (*gi).end(); si++)
            {
                std::cout << *si;

                if (++si != (*gi).end())
                    std::cout << ',';

                si--;
            }

            std::cout << std::endl;
        }

        std::cout << "%%" << std::endl;
    }
}

int main(int argc, char *argv[])
{
    opts.verbose = true;
    Product prod = read_tuples();
    Quotient quot = generating_sets(prod);
    print_quotient(quot);

    return 0;
}
<|endoftext|>


<commit_before>#include "registry.hpp"
#include "services/logger.hpp"
#include "utils/string.hpp"

std::shared_ptr<Registry> registry;
std::shared_ptr<Registry> &get_registry()
{
  if (registry == nullptr)
    registry = std::make_shared<Registry>();
  return registry;
}

Registry::Registry()
{
  get_logger()->debug("Entering STAGE 1");
  this->stage = STAGE_1;
}

bool Registry::ready()
{
  auto stage = this->stage();

  if (stage == STAGE_2)
    for (auto &&entry : this->modules)
      if (!entry->warmedup) get_logger()->debug("Waiting for: "+ entry->module->name());

  return stage == STAGE_3;
}

void Registry::insert(std::unique_ptr<modules::ModuleInterface> &&module)
{
  log_trace("Inserting module: "+ module->name());
  this->modules.emplace_back(std::make_unique<RegistryModuleEntry>(std::move(module)));
}

void Registry::load()
{
  if (this->stage() != STAGE_1)
    return;

  get_logger()->debug("Entering STAGE 2");

  this->stage = STAGE_2;

  get_logger()->debug("Loading modules");

  for (auto &&entry : this->modules) {
    std::lock_guard<std::mutex> wait_lck(this->wait_mtx);
    entry->module->start();
  }
}

void Registry::unload()
{
  if (this->stage() != STAGE_3)
    return;

  get_logger()->debug("Entering STAGE 4");

  this->stage = STAGE_4;

  get_logger()->debug("Unloading modules");

  // Release wait lock
  {
    std::lock_guard<std::mutex> wait_lck(this->wait_mtx);
    this->wait_cv.notify_one();
  }

  for (auto &&entry : this->modules)
    entry->module->stop();
}

bool Registry::wait()
{
  log_trace("STAGE "+ std::to_string(this->stage()));

  std::unique_lock<std::mutex> wait_lck(this->wait_mtx);

  auto stage = this->stage();

  if (stage < STAGE_2)
    return false;

  else if (stage == STAGE_2)
    while (stage == STAGE_2) {
      bool ready = true;

      for (auto &&entry : this->modules)
        if (!entry->warmedup) ready = false;

      if (!ready) {
        this->wait_cv.wait(wait_lck);
        continue;
      }

      get_logger()->info("Received initial broadcast from all modules");
      get_logger()->debug("Entering STAGE 3");

      this->stage = STAGE_3;
      break;
    }

  else if (stage == STAGE_3)
    this->wait_cv.wait(wait_lck);

  else if (stage == STAGE_4)
    this->modules.clear();

  return true;
}

void Registry::notify(const std::string& module_name)
{
  log_trace(module_name +" - STAGE "+ std::to_string(this->stage()));

  auto stage = this->stage();

  if (stage == STAGE_4)
    return;

  auto &mod_entry = this->find(module_name);

  if (stage == STAGE_2) {
    if (mod_entry->warmedup())
      while (this->stage() == STAGE_2)
        std::this_thread::sleep_for(100ms);
    else
      mod_entry->warmedup = true;
  }

  std::unique_lock<std::mutex> wait_lck(this->wait_mtx);

  try {
    mod_entry->module->refresh();
  } catch (Exception &e) {
    log_trace("Exception occurred in runner thread for: "+ module_name);
    get_logger()->error(e.what());
  }

  wait_lck.unlock();

  this->wait_cv.notify_one();
}

std::string Registry::get(const std::string& module_name)
{
  return (*this->find(module_name)->module)();
}

std::unique_ptr<RegistryModuleEntry>& Registry::find(const std::string& module_name)
{
  for (auto &&entry : this->modules)
    if (entry->module->name() == module_name)
      return entry;
  throw ModuleNotFound(module_name);
}
<commit_msg>fix(registry): Offset module loading<commit_after>#include "registry.hpp"
#include "services/logger.hpp"
#include "utils/string.hpp"

std::shared_ptr<Registry> registry;
std::shared_ptr<Registry> &get_registry()
{
  if (registry == nullptr)
    registry = std::make_shared<Registry>();
  return registry;
}

Registry::Registry()
{
  get_logger()->debug("Entering STAGE 1");
  this->stage = STAGE_1;
}

bool Registry::ready()
{
  auto stage = this->stage();

  if (stage == STAGE_2)
    for (auto &&entry : this->modules)
      if (!entry->warmedup) get_logger()->debug("Waiting for: "+ entry->module->name());

  return stage == STAGE_3;
}

void Registry::insert(std::unique_ptr<modules::ModuleInterface> &&module)
{
  log_trace("Inserting module: "+ module->name());
  this->modules.emplace_back(std::make_unique<RegistryModuleEntry>(std::move(module)));
}

void Registry::load()
{
  if (this->stage() != STAGE_1)
    return;

  get_logger()->debug("Entering STAGE 2");

  this->stage = STAGE_2;

  get_logger()->debug("Loading modules");

  for (auto &&entry : this->modules) {
    std::lock_guard<std::mutex> wait_lck(this->wait_mtx);
    entry->module->start();
    std::this_thread::sleep_for(10ms);
  }
}

void Registry::unload()
{
  if (this->stage() != STAGE_3)
    return;

  get_logger()->debug("Entering STAGE 4");

  this->stage = STAGE_4;

  get_logger()->debug("Unloading modules");

  // Release wait lock
  {
    std::lock_guard<std::mutex> wait_lck(this->wait_mtx);
    this->wait_cv.notify_one();
  }

  for (auto &&entry : this->modules)
    entry->module->stop();
}

bool Registry::wait()
{
  log_trace("STAGE "+ std::to_string(this->stage()));

  std::unique_lock<std::mutex> wait_lck(this->wait_mtx);

  auto stage = this->stage();

  if (stage < STAGE_2)
    return false;

  else if (stage == STAGE_2)
    while (stage == STAGE_2) {
      bool ready = true;

      for (auto &&entry : this->modules)
        if (!entry->warmedup) ready = false;

      if (!ready) {
        this->wait_cv.wait(wait_lck);
        continue;
      }

      get_logger()->info("Received initial broadcast from all modules");
      get_logger()->debug("Entering STAGE 3");

      this->stage = STAGE_3;
      break;
    }

  else if (stage == STAGE_3)
    this->wait_cv.wait(wait_lck);

  else if (stage == STAGE_4)
    this->modules.clear();

  return true;
}

void Registry::notify(const std::string& module_name)
{
  log_trace(module_name +" - STAGE "+ std::to_string(this->stage()));

  auto stage = this->stage();

  if (stage == STAGE_4)
    return;

  auto &mod_entry = this->find(module_name);

  if (stage == STAGE_2) {
    if (mod_entry->warmedup())
      while (this->stage() == STAGE_2)
        std::this_thread::sleep_for(100ms);
    else
      mod_entry->warmedup = true;
  }

  std::unique_lock<std::mutex> wait_lck(this->wait_mtx);

  try {
    mod_entry->module->refresh();
  } catch (Exception &e) {
    log_trace("Exception occurred in runner thread for: "+ module_name);
    get_logger()->error(e.what());
  }

  wait_lck.unlock();

  this->wait_cv.notify_one();
}

std::string Registry::get(const std::string& module_name)
{
  return (*this->find(module_name)->module)();
}

std::unique_ptr<RegistryModuleEntry>& Registry::find(const std::string& module_name)
{
  for (auto &&entry : this->modules)
    if (entry->module->name() == module_name)
      return entry;
  throw ModuleNotFound(module_name);
}
<|endoftext|>


<commit_before>#include "xchainer/array.h"

#include <algorithm>
#include <cassert>
#include <cstring>
#include <string>
#include <unordered_map>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA
#include <gsl/gsl>

#include "xchainer/array_fill.h"
#include "xchainer/array_math.h"
#include "xchainer/array_repr.h"
#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/array_fill.h"
#include "xchainer/cuda/array_math.h"
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device.h"
#include "xchainer/error.h"
#include "xchainer/memory.h"
#include "xchainer/op_node.h"
#include "xchainer/scalar.h"

namespace xchainer {
namespace internal {

// Private definition of ArrayBody
ArrayBody::ArrayBody(const Shape& shape, Dtype dtype, bool is_contiguous, std::shared_ptr<void> data, int64_t offset,
                     std::vector<std::shared_ptr<ArrayNode>> nodes)
    : shape_(shape), dtype_(dtype), is_contiguous_(is_contiguous), data_(std::move(data)), offset_(offset), nodes_(std::move(nodes)) {}

void SetUpOpNodes(const std::string& name, const std::vector<std::reference_wrapper<const Array>>& inputs, Array& out,
                  const std::vector<std::function<Array(const Array&, const std::vector<GraphId>&)>>& backward_functions) {
    if (inputs.size() != backward_functions.size()) {
        throw XchainerError("Cannot construct a graph where numbers of input Arrays and backward functions do not match.");
    }

    std::unordered_map<GraphId, std::shared_ptr<OpNode>> graph_edges;

    // Helper function to create an edge in the graph
    auto create_edge = [&name, &graph_edges](const std::shared_ptr<ArrayNode>& next_node, auto& backward_function) {
        std::shared_ptr<OpNode>& op_node = graph_edges[next_node->graph_id()];  // Create if not exists
        if (!op_node) {
            op_node = std::make_shared<OpNode>(name);
        }
        op_node->set_rank(std::max(op_node->rank(), next_node->rank()));
        op_node->RegisterNextNode(next_node, backward_function);
    };

    for (size_t i = 0; i < inputs.size(); ++i) {                                  // For each input
        for (const std::shared_ptr<ArrayNode>& node : inputs[i].get().nodes()) {  // For each graph, create an edge
            create_edge(node, backward_functions[i]);
        }
    }

    if (!graph_edges.empty() && std::any_of(inputs.begin(), inputs.end(), [&out](const Array& input) { return &out == &input; })) {
        throw XchainerError("In-place operation (" + name + ") is not supported for an array that require gradients.");
    }

    // Bind edges to output
    for (const auto& edge : graph_edges) {
        const GraphId& graph_id = edge.first;
        const std::shared_ptr<OpNode>& op_node = edge.second;

        const std::shared_ptr<ArrayNode>& out_node = CreateArrayNode(out, graph_id);
        out_node->set_next_node(op_node);
        out_node->set_rank(op_node->rank() + 1);
    }
}

bool HasArrayNode(const Array& array, const GraphId& graph_id) {
    return std::find_if(array.nodes().begin(), array.nodes().end(),
                        [&graph_id](const auto& node) { return graph_id == node->graph_id(); }) != array.nodes().end();
}

const std::shared_ptr<ArrayNode>& CreateArrayNode(Array& array, const GraphId& graph_id) {
    if (HasArrayNode(array, graph_id)) {
        throw XchainerError("Duplicate graph registration: " + graph_id);
    }
    array.nodes().emplace_back(std::make_shared<ArrayNode>(graph_id));
    return array.nodes().back();
}

std::shared_ptr<const ArrayNode> GetArrayNode(const Array& array, const GraphId& graph_id) { return GetMutableArrayNode(array, graph_id); }

const std::shared_ptr<ArrayNode>& GetMutableArrayNode(const Array& array, const GraphId& graph_id) {
    auto it =
        std::find_if(array.nodes().begin(), array.nodes().end(), [&graph_id](const auto& node) { return graph_id == node->graph_id(); });
    if (it == array.nodes().end()) {
        throw XchainerError("Cannot find ArrayNode for graph: " + graph_id);
    }
    return *it;
}

}  // namespace internal

Array::Array(const Shape& shape, Dtype dtype, std::shared_ptr<void> data, bool is_contiguous, int64_t offset)
    : body_(std::make_shared<internal::ArrayBody>(shape, dtype, is_contiguous, std::move(data), offset)) {}

Array::Array(const Array& other)
    : body_(std::make_shared<internal::ArrayBody>(other.shape(), other.dtype(), other.is_contiguous(), other.body_->data_, other.offset(),
                                                  other.body_->nodes_)) {}

const nonstd::optional<Array>& Array::GetGrad(const GraphId& graph_id) const { return internal::GetArrayNode(*this, graph_id)->grad(); }

void Array::SetGrad(Array grad, const GraphId& graph_id) { internal::GetMutableArrayNode(*this, graph_id)->set_grad(std::move(grad)); }

void Array::ClearGrad(const GraphId& graph_id) { internal::GetMutableArrayNode(*this, graph_id)->ClearGrad(); }

Array Array::FromBuffer(const Shape& shape, Dtype dtype, std::shared_ptr<void> data) {
    auto bytesize = static_cast<size_t>(shape.total_size() * GetElementSize(dtype));
    std::shared_ptr<void> device_data = internal::MemoryFromBuffer(GetCurrentDevice(), data, bytesize);
    return {shape, dtype, device_data};
}

Array Array::Empty(const Shape& shape, Dtype dtype) {
    auto bytesize = static_cast<size_t>(shape.total_size() * GetElementSize(dtype));
    std::shared_ptr<void> data = internal::Allocate(GetCurrentDevice(), bytesize);
    return {shape, dtype, data};
}

Array Array::Full(const Shape& shape, Scalar scalar, Dtype dtype) {
    Array array = Empty(shape, dtype);
    array.Fill(scalar);
    return array;
}

Array Array::Full(const Shape& shape, Scalar scalar) { return Full(shape, scalar, scalar.dtype()); }

Array Array::Zeros(const Shape& shape, Dtype dtype) { return Full(shape, 0, dtype); }

Array Array::Ones(const Shape& shape, Dtype dtype) { return Full(shape, 1, dtype); }

Array Array::EmptyLike(const Array& array) { return Empty(array.shape(), array.dtype()); }

Array Array::FullLike(const Array& array, Scalar scalar) { return Full(array.shape(), scalar, array.dtype()); }

Array Array::ZerosLike(const Array& array) { return Zeros(array.shape(), array.dtype()); }

Array Array::OnesLike(const Array& array) { return Ones(array.shape(), array.dtype()); }

Array& Array::operator+=(const Array& rhs) {
    Add(rhs, *this);
    return *this;
}

Array& Array::operator*=(const Array& rhs) {
    Mul(rhs, *this);
    return *this;
}

Array Array::operator+(const Array& rhs) const {
    Array out = Array::EmptyLike(*this);
    Add(rhs, out);
    return out;
}

Array Array::operator*(const Array& rhs) const {
    Array out = Array::EmptyLike(*this);
    Mul(rhs, out);
    return out;
}

Array Array::Copy() const {
    Array out = Array::EmptyLike(*this);
    CopyTo(out);
    return out;
}

void Array::CopyTo(Array& out) const {
    internal::SetUpOpNodes("copy", {*this}, out, {[](const Array& gout, const std::vector<GraphId>&) { return gout; }});

    // TODO(hvy): When non-C-contiguous orders are supported, we cannot blindly copy all elements but need to take
    // is_contiguous_ and offset_ into account
    internal::MemoryCopy(out.data().get(), body_->data_.get(), total_bytes());
}

Array Array::AsConstant(CopyKind kind) const {
    switch (kind) {
        case CopyKind::kCopy:
            // TODO(takgi): implement deep copy version
            throw NotImplementedError("not implemented");
        case CopyKind::kView:
            return Array{shape(), dtype(), body_->data_, is_contiguous(), offset()};
        default:
            assert(false);  // should never be reached
    }
}

Array Array::AsConstant(const std::vector<GraphId>& graph_ids, CopyKind kind) const {
    switch (kind) {
        case CopyKind::kCopy:
            // TODO(takgi): implement deep copy version
            throw NotImplementedError("not implemented");
        case CopyKind::kView: {
            Array out{shape(), dtype(), body_->data_, is_contiguous(), offset()};
            for (const std::shared_ptr<ArrayNode>& node : nodes()) {
                if (std::find(graph_ids.begin(), graph_ids.end(), node->graph_id()) == graph_ids.end()) {
                    out.body_->nodes_.emplace_back(node);
                }
            }
            return std::move(out);
        }
        default:
            assert(false);  // should never be reached
    }
}

void Array::Add(const Array& rhs, Array& out) const {
    // TODO(sonots): dtype conversion
    CheckEqual(dtype(), rhs.dtype());
    // TODO(sonots): broadcasting
    CheckEqual(shape(), rhs.shape());

    auto lhs_backward_function = [](const Array& gout, const std::vector<GraphId>&) -> Array { return gout; };
    auto rhs_backward_function = lhs_backward_function;
    internal::SetUpOpNodes("add", {*this, rhs}, out, {lhs_backward_function, rhs_backward_function});

    Device device = GetCurrentDevice();
    if (device == MakeDevice("cpu")) {
        xchainer::Add(*this, rhs, out);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        xchainer::cuda::Add(*this, rhs, out);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void Array::Mul(const Array& rhs, Array& out) const {
    // TODO(sonots): dtype conversion
    CheckEqual(dtype(), rhs.dtype());
    // TODO(sonots): broadcasting
    CheckEqual(shape(), rhs.shape());

    auto lhs_backward_function = [other = rhs](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient) {
        return gout * other.AsConstant(graph_ids_to_stop_gradient);
    };
    auto rhs_backward_function = [other = *this](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient) {
        return gout * other.AsConstant(graph_ids_to_stop_gradient);
    };
    internal::SetUpOpNodes("mul", {*this, rhs}, out, {lhs_backward_function, rhs_backward_function});

    Device device = GetCurrentDevice();
    if (device == MakeDevice("cpu")) {
        xchainer::Mul(*this, rhs, out);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        xchainer::cuda::Mul(*this, rhs, out);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void Array::Fill(Scalar value) {
    Device device = GetCurrentDevice();
    if (device == MakeDevice("cpu")) {
        xchainer::Fill(*this, value);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        xchainer::cuda::Fill(*this, value);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

std::string Array::ToString() const { return ArrayRepr(*this); }

namespace {

void DebugDumpComputationalGraph(std::ostream& os, const ArrayNode& array_node, int indent) {
    static const char kIndentChar = ' ';

    os << std::string(static_cast<size_t>(indent * 2), kIndentChar) << "ArrayNode<" << &array_node << ">" << std::endl;

    std::shared_ptr<const OpNode> op = array_node.next_node();
    if (op) {
        os << std::string(static_cast<size_t>((indent + 1) * 2), kIndentChar) << "Op<" << op->name() << "," << op.get() << ">" << std::endl;
        for (const std::shared_ptr<const ArrayNode>& next_node : op->next_nodes()) {
            DebugDumpComputationalGraph(os, *next_node, static_cast<size_t>(indent + 2));
        }
    }
}

}  // namespace

void DebugDumpComputationalGraph(std::ostream& os, const Array& array, const GraphId& graph_id, int indent) {
    DebugDumpComputationalGraph(os, *internal::GetArrayNode(array, graph_id), indent);
}

}  // namespace xchainer
<commit_msg>temporary fix for array.cc<commit_after>#include "xchainer/array.h"

#include <algorithm>
#include <cassert>
#include <cstring>
#include <string>
#include <unordered_map>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA
#include <gsl/gsl>

#include "xchainer/array_fill.h"
#include "xchainer/array_math.h"
#include "xchainer/array_repr.h"
#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/array_fill.h"
#include "xchainer/cuda/array_math.h"
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device.h"
#include "xchainer/error.h"
#include "xchainer/memory.h"
#include "xchainer/op_node.h"
#include "xchainer/scalar.h"

namespace xchainer {
namespace internal {

// Private definition of ArrayBody
ArrayBody::ArrayBody(const Shape& shape, Dtype dtype, bool is_contiguous, std::shared_ptr<void> data, int64_t offset,
                     std::vector<std::shared_ptr<ArrayNode>> nodes)
    : shape_(shape), dtype_(dtype), is_contiguous_(is_contiguous), data_(std::move(data)), offset_(offset), nodes_(std::move(nodes)) {}

void SetUpOpNodes(const std::string& name, const std::vector<std::reference_wrapper<const Array>>& inputs, Array& out,
                  const std::vector<std::function<Array(const Array&, const std::vector<GraphId>&)>>& backward_functions) {
    if (inputs.size() != backward_functions.size()) {
        throw XchainerError("Cannot construct a graph where numbers of input Arrays and backward functions do not match.");
    }

    std::unordered_map<GraphId, std::shared_ptr<OpNode>> graph_edges;

    // Helper function to create an edge in the graph
    auto create_edge = [&name, &graph_edges](const std::shared_ptr<ArrayNode>& next_node, auto& backward_function) {
        std::shared_ptr<OpNode>& op_node = graph_edges[next_node->graph_id()];  // Create if not exists
        if (!op_node) {
            op_node = std::make_shared<OpNode>(name);
        }
        op_node->set_rank(std::max(op_node->rank(), next_node->rank()));
        op_node->RegisterNextNode(next_node, backward_function);
    };

    for (size_t i = 0; i < inputs.size(); ++i) {                                  // For each input
        for (const std::shared_ptr<ArrayNode>& node : inputs[i].get().nodes()) {  // For each graph, create an edge
            create_edge(node, backward_functions[i]);
        }
    }

    if (!graph_edges.empty() && std::any_of(inputs.begin(), inputs.end(), [&out](const Array& input) { return &out == &input; })) {
        throw XchainerError("In-place operation (" + name + ") is not supported for an array that require gradients.");
    }

    // Bind edges to output
    for (const auto& edge : graph_edges) {
        const GraphId& graph_id = edge.first;
        const std::shared_ptr<OpNode>& op_node = edge.second;

        const std::shared_ptr<ArrayNode>& out_node = CreateArrayNode(out, graph_id);
        out_node->set_next_node(op_node);
        out_node->set_rank(op_node->rank() + 1);
    }
}

bool HasArrayNode(const Array& array, const GraphId& graph_id) {
    return std::find_if(array.nodes().begin(), array.nodes().end(),
                        [&graph_id](const auto& node) { return graph_id == node->graph_id(); }) != array.nodes().end();
}

const std::shared_ptr<ArrayNode>& CreateArrayNode(Array& array, const GraphId& graph_id) {
    if (HasArrayNode(array, graph_id)) {
        throw XchainerError("Duplicate graph registration: " + graph_id);
    }
    array.nodes().emplace_back(std::make_shared<ArrayNode>(graph_id));
    return array.nodes().back();
}

std::shared_ptr<const ArrayNode> GetArrayNode(const Array& array, const GraphId& graph_id) { return GetMutableArrayNode(array, graph_id); }

const std::shared_ptr<ArrayNode>& GetMutableArrayNode(const Array& array, const GraphId& graph_id) {
    auto it =
        std::find_if(array.nodes().begin(), array.nodes().end(), [&graph_id](const auto& node) { return graph_id == node->graph_id(); });
    if (it == array.nodes().end()) {
        throw XchainerError("Cannot find ArrayNode for graph: " + graph_id);
    }
    return *it;
}

}  // namespace internal

Array::Array(const Shape& shape, Dtype dtype, std::shared_ptr<void> data, bool is_contiguous, int64_t offset)
    : body_(std::make_shared<internal::ArrayBody>(shape, dtype, is_contiguous, std::move(data), offset)) {}

Array::Array(const Array& other)
    : body_(std::make_shared<internal::ArrayBody>(other.shape(), other.dtype(), other.is_contiguous(), other.body_->data_, other.offset(),
                                                  other.body_->nodes_)) {}

const nonstd::optional<Array>& Array::GetGrad(const GraphId& graph_id) const { return internal::GetArrayNode(*this, graph_id)->grad(); }

void Array::SetGrad(Array grad, const GraphId& graph_id) { internal::GetMutableArrayNode(*this, graph_id)->set_grad(std::move(grad)); }

void Array::ClearGrad(const GraphId& graph_id) { internal::GetMutableArrayNode(*this, graph_id)->ClearGrad(); }

Array Array::FromBuffer(const Shape& shape, Dtype dtype, std::shared_ptr<void> data) {
    auto bytesize = static_cast<size_t>(shape.total_size() * GetElementSize(dtype));
    std::shared_ptr<void> device_data = internal::MemoryFromBuffer(GetCurrentDevice(), data, bytesize);
    return {shape, dtype, device_data};
}

Array Array::Empty(const Shape& shape, Dtype dtype) {
    auto bytesize = static_cast<size_t>(shape.total_size() * GetElementSize(dtype));
    std::shared_ptr<void> data = internal::Allocate(GetCurrentDevice(), bytesize);
    return {shape, dtype, data};
}

Array Array::Full(const Shape& shape, Scalar scalar, Dtype dtype) {
    Array array = Empty(shape, dtype);
    array.Fill(scalar);
    return array;
}

Array Array::Full(const Shape& shape, Scalar scalar) { return Full(shape, scalar, scalar.dtype()); }

Array Array::Zeros(const Shape& shape, Dtype dtype) { return Full(shape, 0, dtype); }

Array Array::Ones(const Shape& shape, Dtype dtype) { return Full(shape, 1, dtype); }

Array Array::EmptyLike(const Array& array) { return Empty(array.shape(), array.dtype()); }

Array Array::FullLike(const Array& array, Scalar scalar) { return Full(array.shape(), scalar, array.dtype()); }

Array Array::ZerosLike(const Array& array) { return Zeros(array.shape(), array.dtype()); }

Array Array::OnesLike(const Array& array) { return Ones(array.shape(), array.dtype()); }

Array& Array::operator+=(const Array& rhs) {
    Add(rhs, *this);
    return *this;
}

Array& Array::operator*=(const Array& rhs) {
    Mul(rhs, *this);
    return *this;
}

Array Array::operator+(const Array& rhs) const {
    Array out = Array::EmptyLike(*this);
    Add(rhs, out);
    return out;
}

Array Array::operator*(const Array& rhs) const {
    Array out = Array::EmptyLike(*this);
    Mul(rhs, out);
    return out;
}

Array Array::Copy() const {
    Array out = Array::EmptyLike(*this);
    CopyTo(out);
    return out;
}

void Array::CopyTo(Array& out) const {
    internal::SetUpOpNodes("copy", {*this}, out, {[](const Array& gout, const std::vector<GraphId>&) { return gout; }});

    // TODO(hvy): When non-C-contiguous orders are supported, we cannot blindly copy all elements but need to take
    // is_contiguous_ and offset_ into account
    internal::MemoryCopy(out.data().get(), body_->data_.get(), total_bytes());
}

Array Array::AsConstant(CopyKind kind) const {
    switch (kind) {
        case CopyKind::kCopy:
            // TODO(takgi): implement deep copy version
            throw NotImplementedError("not implemented");
        case CopyKind::kView:
            return Array{shape(), dtype(), body_->data_, is_contiguous(), offset()};
        default:
            assert(false);  // should never be reached
    }
}

Array Array::AsConstant(const std::vector<GraphId>& graph_ids, CopyKind kind) const {
    switch (kind) {
        case CopyKind::kCopy:
            // TODO(takgi): implement deep copy version
            throw NotImplementedError("not implemented");
        case CopyKind::kView: {
            Array out{shape(), dtype(), body_->data_, is_contiguous(), offset()};
            for (const std::shared_ptr<ArrayNode>& node : nodes()) {
                if (std::find(graph_ids.begin(), graph_ids.end(), node->graph_id()) == graph_ids.end()) {
                    out.body_->nodes_.emplace_back(node);
                }
            }
            return std::move(out);
        }
        default:
            assert(false);  // should never be reached
    }
}

void Array::Add(const Array& rhs, Array& out) const {
    // TODO(sonots): dtype conversion
    CheckEqual(dtype(), rhs.dtype());
    // TODO(sonots): broadcasting
    CheckEqual(shape(), rhs.shape());

    auto lhs_backward_function = [](const Array& gout, const std::vector<GraphId>&) -> Array { return gout; };
    auto rhs_backward_function = lhs_backward_function;
    internal::SetUpOpNodes("add", {*this, rhs}, out, {lhs_backward_function, rhs_backward_function});

    Device device = GetCurrentDevice();
    // TODO(sonots): Use device.backend->Add()
    if (strncmp(device.name, "cpu", kMaxDeviceNameLength) == 0) {
        xchainer::Add(*this, rhs, out);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (strncmp(device.name, "cuda", kMaxDeviceNameLength) == 0) {
        xchainer::cuda::Add(*this, rhs, out);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void Array::Mul(const Array& rhs, Array& out) const {
    // TODO(sonots): dtype conversion
    CheckEqual(dtype(), rhs.dtype());
    // TODO(sonots): broadcasting
    CheckEqual(shape(), rhs.shape());

    auto lhs_backward_function = [other = rhs](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient) {
        return gout * other.AsConstant(graph_ids_to_stop_gradient);
    };
    auto rhs_backward_function = [other = *this](const Array& gout, const std::vector<GraphId>& graph_ids_to_stop_gradient) {
        return gout * other.AsConstant(graph_ids_to_stop_gradient);
    };
    internal::SetUpOpNodes("mul", {*this, rhs}, out, {lhs_backward_function, rhs_backward_function});

    Device device = GetCurrentDevice();
    // TODO(sonots): Use device.backend->Mul()
    if (strncmp(device.name, "cpu", kMaxDeviceNameLength) == 0) {
        xchainer::Mul(*this, rhs, out);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (strncmp(device.name, "cuda", kMaxDeviceNameLength) == 0) {
        xchainer::cuda::Mul(*this, rhs, out);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void Array::Fill(Scalar value) {
    Device device = GetCurrentDevice();
    // TODO(sonots): Use device.backend->Fill()
    if (strncmp(device.name, "cpu", kMaxDeviceNameLength) == 0) {
        xchainer::Fill(*this, value);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (strncmp(device.name, "cuda", kMaxDeviceNameLength) == 0) {
        xchainer::cuda::Fill(*this, value);
#endif  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

std::string Array::ToString() const { return ArrayRepr(*this); }

namespace {

void DebugDumpComputationalGraph(std::ostream& os, const ArrayNode& array_node, int indent) {
    static const char kIndentChar = ' ';

    os << std::string(static_cast<size_t>(indent * 2), kIndentChar) << "ArrayNode<" << &array_node << ">" << std::endl;

    std::shared_ptr<const OpNode> op = array_node.next_node();
    if (op) {
        os << std::string(static_cast<size_t>((indent + 1) * 2), kIndentChar) << "Op<" << op->name() << "," << op.get() << ">" << std::endl;
        for (const std::shared_ptr<const ArrayNode>& next_node : op->next_nodes()) {
            DebugDumpComputationalGraph(os, *next_node, static_cast<size_t>(indent + 2));
        }
    }
}

}  // namespace

void DebugDumpComputationalGraph(std::ostream& os, const Array& array, const GraphId& graph_id, int indent) {
    DebugDumpComputationalGraph(os, *internal::GetArrayNode(array, graph_id), indent);
}

}  // namespace xchainer
<|endoftext|>


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

// include ---------------------------------------------------------------

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

// define ----------------------------------------------------------------

// Styles
#define BS_ABC_BIG          0
#define BS_ABC_SMALL        1
#define BS_ROMAN_BIG        2
#define BS_ROMAN_SMALL      3
#define BS_123              4
#define BS_NONE             5
#define BS_BULLET           6
#define BS_BMP              128

// Justification
#define BJ_HLEFT            0x01
#define BJ_HRIGHT           0x02
#define BJ_HCENTER          0x04
#define BJ_VTOP             0x08
#define BJ_VBOTTOM          0x10
#define BJ_VCENTER          0x20

// Valid-Bits
// Erstmal nur die Werte, die vom Dialog geaendert werden...
#define VALID_FONTCOLOR     0x0001
#define VALID_FONTNAME      0x0002
#define VALID_SYMBOL        0x0004
#define VALID_BITMAP        0x0008
#define VALID_SCALE         0x0010
#define VALID_START         0x0020
#define VALID_STYLE         0x0040
#define VALID_PREVTEXT      0x0080
#define VALID_FOLLOWTEXT    0x0100

#ifndef _SFXPOOLITEM_HXX //autogen
#include <svtools/poolitem.hxx>
#endif
#ifndef _VCL_FONT_HXX //autogen
#include <vcl/font.hxx>
#endif
#ifndef _GRFMGR_HXX //autogen
#include <goodies/grfmgr.hxx>
#endif

// class SvxBulletItem ---------------------------------------------------

class SVX_DLLPUBLIC SvxBulletItem : public SfxPoolItem
{
    Font            aFont;
    GraphicObject*  pGraphicObject;
    String          aPrevText;
    String          aFollowText;
    USHORT          nStart;
    USHORT          nStyle;
    long            nWidth;
    USHORT          nScale;
    sal_Unicode     cSymbol;
    BYTE            nJustify;
    USHORT          nValidMask; // Nur temporaer fuer GetAttribs/SetAttribs, wegen des grossen Bullets

#ifdef _SVX_BULITEM_CXX
    void    SetDefaultFont_Impl();
    void    SetDefaults_Impl();
#endif

public:
    TYPEINFO();

    SvxBulletItem( USHORT nWhich = 0 );
    SvxBulletItem( BYTE nStyle, const Font& rFont, USHORT nStart = 0, USHORT nWhich = 0 );
    SvxBulletItem( const Font& rFont, sal_Unicode cSymbol, USHORT nWhich=0 );
    SvxBulletItem( const Bitmap&, USHORT nWhich = 0 );
    SvxBulletItem( const GraphicObject&, USHORT nWhich = 0 );
    SvxBulletItem( SvStream& rStrm, USHORT nWhich = 0 );
    SvxBulletItem( const SvxBulletItem& );
    ~SvxBulletItem();

    virtual SfxPoolItem*    Clone( SfxItemPool *pPool = 0 ) const;
    virtual SfxPoolItem*    Create( SvStream&, USHORT nVersion ) const;
    virtual SvStream&       Store( SvStream & , USHORT nItemVersion ) const;

    String              GetFullText() const;
    sal_Unicode         GetSymbol() const { return cSymbol; }
    String              GetPrevText() const { return aPrevText; }
    String              GetFollowText() const { return aFollowText; }

    USHORT              GetStart() const { return nStart; }
    long                GetWidth() const { return nWidth; }
    USHORT              GetStyle() const { return nStyle; }
    BYTE                GetJustification() const { return nJustify; }
    Font                GetFont() const { return aFont; }
    USHORT              GetScale() const { return nScale; }

    Bitmap              GetBitmap() const;
    void                SetBitmap( const Bitmap& rBmp );

    const GraphicObject& GetGraphicObject() const;
    void                 SetGraphicObject( const GraphicObject& rGraphicObject );

    void                SetSymbol( sal_Unicode c) { cSymbol = c; }
    void                SetPrevText( const String& rStr) { aPrevText = rStr;}
    void                SetFollowText(const String& rStr) { aFollowText=rStr;}

    void                SetStart( USHORT nNew ) { nStart = nNew; }
    void                SetWidth( long nNew ) { nWidth = nNew; }
    void                SetStyle( USHORT nNew ) { nStyle = nNew; }
    void                SetJustification( BYTE nNew ) { nJustify = nNew; }
    void                SetFont( const Font& rNew) { aFont = rNew; }
    void                SetScale( USHORT nNew ) { nScale = nNew; }

    virtual USHORT      GetVersion(USHORT nFileVersion) const;
    virtual int         operator==( const SfxPoolItem& ) const;
    virtual SfxItemPresentation GetPresentation( SfxItemPresentation ePres,
                                    SfxMapUnit eCoreMetric,
                                    SfxMapUnit ePresMetric,
                                    String &rText, const IntlWrapper * = 0 ) const;

    static void         StoreFont( SvStream&, const Font& );
    static Font         CreateFont( SvStream&, USHORT nVer );

    USHORT&             GetValidMask()                  { return nValidMask;    }
    USHORT              GetValidMask() const            { return nValidMask;    }
    USHORT              IsValid( USHORT nFlag ) const   { return nValidMask & nFlag; }
    void                SetValid( USHORT nFlag, BOOL bValid )
                        {
                            if ( bValid )
                                nValidMask |= nFlag;
                            else
                                nValidMask &= ~nFlag;
                        }
    void                CopyValidProperties( const SvxBulletItem& rCopyFrom );
};

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.4.430); FILE MERGED 2005/09/05 14:15:10 rt 1.4.430.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: bulitem.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 17:18:52 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _SVX_BULITEM_HXX
#define _SVX_BULITEM_HXX

// include ---------------------------------------------------------------

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

// define ----------------------------------------------------------------

// Styles
#define BS_ABC_BIG          0
#define BS_ABC_SMALL        1
#define BS_ROMAN_BIG        2
#define BS_ROMAN_SMALL      3
#define BS_123              4
#define BS_NONE             5
#define BS_BULLET           6
#define BS_BMP              128

// Justification
#define BJ_HLEFT            0x01
#define BJ_HRIGHT           0x02
#define BJ_HCENTER          0x04
#define BJ_VTOP             0x08
#define BJ_VBOTTOM          0x10
#define BJ_VCENTER          0x20

// Valid-Bits
// Erstmal nur die Werte, die vom Dialog geaendert werden...
#define VALID_FONTCOLOR     0x0001
#define VALID_FONTNAME      0x0002
#define VALID_SYMBOL        0x0004
#define VALID_BITMAP        0x0008
#define VALID_SCALE         0x0010
#define VALID_START         0x0020
#define VALID_STYLE         0x0040
#define VALID_PREVTEXT      0x0080
#define VALID_FOLLOWTEXT    0x0100

#ifndef _SFXPOOLITEM_HXX //autogen
#include <svtools/poolitem.hxx>
#endif
#ifndef _VCL_FONT_HXX //autogen
#include <vcl/font.hxx>
#endif
#ifndef _GRFMGR_HXX //autogen
#include <goodies/grfmgr.hxx>
#endif

// class SvxBulletItem ---------------------------------------------------

class SVX_DLLPUBLIC SvxBulletItem : public SfxPoolItem
{
    Font            aFont;
    GraphicObject*  pGraphicObject;
    String          aPrevText;
    String          aFollowText;
    USHORT          nStart;
    USHORT          nStyle;
    long            nWidth;
    USHORT          nScale;
    sal_Unicode     cSymbol;
    BYTE            nJustify;
    USHORT          nValidMask; // Nur temporaer fuer GetAttribs/SetAttribs, wegen des grossen Bullets

#ifdef _SVX_BULITEM_CXX
    void    SetDefaultFont_Impl();
    void    SetDefaults_Impl();
#endif

public:
    TYPEINFO();

    SvxBulletItem( USHORT nWhich = 0 );
    SvxBulletItem( BYTE nStyle, const Font& rFont, USHORT nStart = 0, USHORT nWhich = 0 );
    SvxBulletItem( const Font& rFont, sal_Unicode cSymbol, USHORT nWhich=0 );
    SvxBulletItem( const Bitmap&, USHORT nWhich = 0 );
    SvxBulletItem( const GraphicObject&, USHORT nWhich = 0 );
    SvxBulletItem( SvStream& rStrm, USHORT nWhich = 0 );
    SvxBulletItem( const SvxBulletItem& );
    ~SvxBulletItem();

    virtual SfxPoolItem*    Clone( SfxItemPool *pPool = 0 ) const;
    virtual SfxPoolItem*    Create( SvStream&, USHORT nVersion ) const;
    virtual SvStream&       Store( SvStream & , USHORT nItemVersion ) const;

    String              GetFullText() const;
    sal_Unicode         GetSymbol() const { return cSymbol; }
    String              GetPrevText() const { return aPrevText; }
    String              GetFollowText() const { return aFollowText; }

    USHORT              GetStart() const { return nStart; }
    long                GetWidth() const { return nWidth; }
    USHORT              GetStyle() const { return nStyle; }
    BYTE                GetJustification() const { return nJustify; }
    Font                GetFont() const { return aFont; }
    USHORT              GetScale() const { return nScale; }

    Bitmap              GetBitmap() const;
    void                SetBitmap( const Bitmap& rBmp );

    const GraphicObject& GetGraphicObject() const;
    void                 SetGraphicObject( const GraphicObject& rGraphicObject );

    void                SetSymbol( sal_Unicode c) { cSymbol = c; }
    void                SetPrevText( const String& rStr) { aPrevText = rStr;}
    void                SetFollowText(const String& rStr) { aFollowText=rStr;}

    void                SetStart( USHORT nNew ) { nStart = nNew; }
    void                SetWidth( long nNew ) { nWidth = nNew; }
    void                SetStyle( USHORT nNew ) { nStyle = nNew; }
    void                SetJustification( BYTE nNew ) { nJustify = nNew; }
    void                SetFont( const Font& rNew) { aFont = rNew; }
    void                SetScale( USHORT nNew ) { nScale = nNew; }

    virtual USHORT      GetVersion(USHORT nFileVersion) const;
    virtual int         operator==( const SfxPoolItem& ) const;
    virtual SfxItemPresentation GetPresentation( SfxItemPresentation ePres,
                                    SfxMapUnit eCoreMetric,
                                    SfxMapUnit ePresMetric,
                                    String &rText, const IntlWrapper * = 0 ) const;

    static void         StoreFont( SvStream&, const Font& );
    static Font         CreateFont( SvStream&, USHORT nVer );

    USHORT&             GetValidMask()                  { return nValidMask;    }
    USHORT              GetValidMask() const            { return nValidMask;    }
    USHORT              IsValid( USHORT nFlag ) const   { return nValidMask & nFlag; }
    void                SetValid( USHORT nFlag, BOOL bValid )
                        {
                            if ( bValid )
                                nValidMask |= nFlag;
                            else
                                nValidMask &= ~nFlag;
                        }
    void                CopyValidProperties( const SvxBulletItem& rCopyFrom );
};

#endif

<|endoftext|>